Files
wp-agentic-writer/FINAL_FRONTEND_CODE.md
2026-01-28 00:26:00 +07:00

356 lines
10 KiB
Markdown

# Final Frontend Implementation Code
This document contains all the JavaScript and CSS code to be added to complete the implementation.
---
## JavaScript Functions to Add to sidebar.js
### 1. Writing Mode Empty State Check
```javascript
// Add after state declarations (around line 100)
const shouldShowWritingEmptyState = () => {
return agentMode === 'writing' && !currentPlanRef.current;
};
```
### 2. Summarize Chat History Function
```javascript
// Add with other utility functions
const summarizeChatHistory = async () => {
const chatMessages = messages.filter(m => m.role !== 'system');
if (chatMessages.length < 4) {
return { summary: '', useFullHistory: true, cost: 0 };
}
try {
const response = await fetch(wpAgenticWriter.apiUrl + '/summarize-context', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpAgenticWriter.nonce,
},
body: JSON.stringify({
chatHistory: chatMessages,
postId: postId,
}),
});
if (!response.ok) {
throw new Error('Summarization failed');
}
const data = await response.json();
if (data.tokens_saved > 0) {
console.log(`💡 Context optimized: ~${data.tokens_saved} tokens saved (~$${(data.tokens_saved * 0.0000002).toFixed(4)})`);
}
return {
summary: data.summary || '',
useFullHistory: data.use_full_history || false,
cost: data.cost || 0,
tokensSaved: data.tokens_saved || 0,
};
} catch (error) {
console.error('Summarization error:', error);
return { summary: '', useFullHistory: true, cost: 0 };
}
};
```
### 3. Detect User Intent Function
```javascript
// Add with other utility functions
const detectUserIntent = async (lastMessage) => {
if (!lastMessage || lastMessage.trim().length === 0) {
return { intent: 'continue_chat', cost: 0 };
}
try {
const response = await fetch(wpAgenticWriter.apiUrl + '/detect-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpAgenticWriter.nonce,
},
body: JSON.stringify({
lastMessage: lastMessage,
hasPlan: Boolean(currentPlanRef.current),
currentMode: agentMode,
postId: postId,
}),
});
if (!response.ok) {
throw new Error('Intent detection failed');
}
const data = await response.json();
return {
intent: data.intent || 'continue_chat',
cost: data.cost || 0,
};
} catch (error) {
console.error('Intent detection error:', error);
return { intent: 'continue_chat', cost: 0 };
}
};
```
### 4. Build Optimized Context Function
```javascript
// Add with other utility functions
const buildOptimizedContext = async () => {
const result = await summarizeChatHistory();
if (result.useFullHistory) {
return {
type: 'full',
messages: messages.filter(m => m.role !== 'system'),
cost: 0,
};
}
return {
type: 'summary',
summary: result.summary,
cost: result.cost,
tokensSaved: result.tokensSaved,
};
};
```
### 5. Handle Reset Command
```javascript
// Add with other command handlers
const handleResetCommand = async () => {
if (!confirm('Clear all conversation history? This cannot be undone.')) {
return;
}
try {
// Clear frontend state
setMessages([]);
currentPlanRef.current = null;
// Clear backend chat history
await fetch(wpAgenticWriter.apiUrl + '/clear-context', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpAgenticWriter.nonce,
},
body: JSON.stringify({ postId: postId }),
});
setMessages([{
role: 'system',
type: 'info',
content: '✅ Context cleared. Starting fresh conversation.'
}]);
} catch (error) {
console.error('Reset error:', error);
setMessages(prev => [...prev, {
role: 'system',
type: 'error',
content: 'Failed to clear context. Please try again.'
}]);
}
};
```
---
## Modifications to Existing Functions
### Modify handleSendMessage (detect /reset command)
Find the message sending logic and add at the beginning:
```javascript
// Check for reset command
if (/^\s*(\/reset|\/clear)\s*$/i.test(userMessage)) {
setInput('');
await handleResetCommand();
return;
}
// Check for Writing mode notes warning
if (agentMode === 'writing' && currentPlanRef.current) {
setMessages(prev => [...prev,
{ role: 'user', content: userMessage },
{
role: 'system',
type: 'info',
content: '💡 Note: Messages in Writing mode are for discussion only. To modify the outline, switch to Planning mode.'
}
]);
}
```
### Modify handleExecuteArticle (add plan check)
Add at the very beginning of the function:
```javascript
// Check if plan exists
if (!currentPlanRef.current) {
setMessages(prev => [...prev, {
role: 'system',
type: 'error',
content: '⚠️ No outline found. Please create an outline first by switching to Planning mode.'
}]);
setIsLoading(false);
return;
}
```
---
## UI Components to Add
### Render Writing Empty State
Add this component function:
```javascript
const renderWritingEmptyState = () => {
return wp.element.createElement('div', { className: 'wpaw-writing-empty-state' },
wp.element.createElement('div', { className: 'wpaw-empty-state-content' },
wp.element.createElement('span', { className: 'wpaw-empty-state-icon' }, '📝'),
wp.element.createElement('h3', null, 'No Outline Yet'),
wp.element.createElement('p', null, 'Writing mode requires an outline to structure your article.'),
wp.element.createElement(Button, {
isPrimary: true,
onClick: () => setAgentMode('planning'),
className: 'wpaw-empty-state-button'
}, '📝 Create Outline First'),
wp.element.createElement('p', { className: 'wpaw-empty-state-hint' },
'Or switch to ',
wp.element.createElement('button', {
onClick: () => setAgentMode('chat'),
className: 'wpaw-link-button'
}, 'Chat mode'),
' to discuss your ideas.'
)
)
);
};
```
### Render Context Indicator
Add this component function:
```javascript
const renderContextIndicator = () => {
const chatMessages = messages.filter(m => m.role !== 'system');
const messageCount = chatMessages.length;
const estimatedTokens = messageCount * 500; // Rough estimate
if (messageCount === 0) return null;
return wp.element.createElement('div', { className: 'wpaw-context-indicator' },
wp.element.createElement('div', { className: 'wpaw-context-info' },
wp.element.createElement('span', { className: 'wpaw-context-count' },
`💬 ${messageCount} messages`
),
wp.element.createElement('span', { className: 'wpaw-context-tokens' },
`~${estimatedTokens} tokens`
)
),
wp.element.createElement('button', {
className: 'wpaw-context-clear',
onClick: handleResetCommand,
title: 'Clear conversation history'
}, '🗑️ Clear')
);
};
```
### Render Contextual Action
Add this component function:
```javascript
const renderContextualAction = (intent) => {
if (!intent || intent === 'continue_chat') return null;
const actions = {
create_outline: {
icon: '📝',
title: 'Ready to create an outline?',
description: 'I can help you structure your article.',
button: 'Create Outline',
onClick: () => setAgentMode('planning')
},
start_writing: {
icon: '✍️',
title: 'Ready to start writing?',
description: 'Let\'s turn your outline into a full article.',
button: 'Start Writing',
onClick: async () => {
setAgentMode('writing');
if (currentPlanRef.current) {
await handleExecuteArticle();
}
}
},
refine_content: {
icon: '✨',
title: 'Want to refine your content?',
description: 'I can help improve specific sections.',
button: 'Show Options',
onClick: () => {} // Could open refinement options
}
};
const action = actions[intent];
if (!action) return null;
return wp.element.createElement('div', { className: 'wpaw-contextual-action' },
wp.element.createElement('div', { className: 'wpaw-action-icon' }, action.icon),
wp.element.createElement('div', { className: 'wpaw-action-content' },
wp.element.createElement('h4', null, action.title),
wp.element.createElement('p', null, action.description),
wp.element.createElement(Button, {
isPrimary: true,
onClick: action.onClick
}, action.button)
)
);
};
```
---
## Integration Points
### In Main Render (where messages are displayed)
Add before the message list:
```javascript
{shouldShowWritingEmptyState() && renderWritingEmptyState()}
{renderContextIndicator()}
```
### In Message Loop (after assistant messages)
Add intent detection display:
```javascript
{message.detectedIntent && renderContextualAction(message.detectedIntent)}
```
---
This completes all the JavaScript logic needed for the frontend implementation.