Skip to content

Commit 68ba13e

Browse files
committed
Add conversational brief review feature
- Replace editable InlineBriefConfirmation with read-only BriefReview component - BriefReview displays parsed brief fields in styled cards - Users can modify brief via natural language chat messages - handleSendMessage detects brief refinement requests and updates pending brief - handleBriefConfirm now uses pending brief from state - Contextual prompts guide users on how to modify/add/remove content
1 parent d008637 commit 68ba13e

8 files changed

Lines changed: 323 additions & 187 deletions

File tree

-7.27 KB
Binary file not shown.

content-gen/src/frontend-server/static/assets/index-B05PkGx7.js

Lines changed: 0 additions & 125 deletions
This file was deleted.

content-gen/src/frontend-server/static/assets/index-C6xB6aWi.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

content-gen/src/frontend-server/static/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>Content Generation Accelerator</title>
8-
<script type="module" crossorigin src="/assets/index-B05PkGx7.js"></script>
9-
<link rel="stylesheet" crossorigin href="/assets/index-C6xB6aWi.css">
8+
<script type="module" crossorigin src="/assets/index-CrHmFc3s.js"></script>
9+
<link rel="stylesheet" crossorigin href="/assets/index-D9ems1Py.css">
1010
</head>
1111
<body>
1212
<div id="root"></div>

content-gen/src/frontend/src/App.tsx

Lines changed: 106 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -167,56 +167,114 @@ function App() {
167167
// Import dynamically to avoid SSR issues
168168
const { streamChat, parseBrief } = await import('./api');
169169

170-
// Check if this looks like a creative brief
171-
const briefKeywords = ['campaign', 'marketing', 'target audience', 'objective', 'deliverable'];
172-
const isBriefLike = briefKeywords.some(kw => content.toLowerCase().includes(kw));
173-
174-
if (isBriefLike && !confirmedBrief) {
175-
// Parse as a creative brief
176-
const parsed = await parseBrief(content, conversationId, userId);
177-
setPendingBrief(parsed.brief);
170+
// If we have a pending brief and user is providing feedback, update the brief
171+
if (pendingBrief && !confirmedBrief) {
172+
// User is refining the brief conversationally
173+
const refinementKeywords = ['change', 'update', 'modify', 'add', 'remove', 'delete', 'set', 'make', 'should be'];
174+
const isRefinement = refinementKeywords.some(kw => content.toLowerCase().includes(kw));
178175

179-
const assistantMessage: ChatMessage = {
180-
id: uuidv4(),
181-
role: 'assistant',
182-
content: 'I\'ve parsed your creative brief. Please review and confirm the details before we proceed.',
183-
agent: 'PlanningAgent',
184-
timestamp: new Date().toISOString(),
185-
};
186-
setMessages(prev => [...prev, assistantMessage]);
176+
if (isRefinement) {
177+
// Send the refinement request to update the brief
178+
// Combine original brief context with the refinement request
179+
const refinementPrompt = `Current creative brief:\n${JSON.stringify(pendingBrief, null, 2)}\n\nUser requested change: ${content}\n\nPlease update the brief accordingly and return the complete updated brief.`;
180+
181+
const parsed = await parseBrief(refinementPrompt, conversationId, userId);
182+
setPendingBrief(parsed.brief);
183+
184+
const assistantMessage: ChatMessage = {
185+
id: uuidv4(),
186+
role: 'assistant',
187+
content: "I've updated the brief based on your feedback. Please review the changes above. Let me know if you'd like any other modifications, or click **Confirm Brief** when you're satisfied.",
188+
agent: 'PlanningAgent',
189+
timestamp: new Date().toISOString(),
190+
};
191+
setMessages(prev => [...prev, assistantMessage]);
192+
} else {
193+
// General question or comment while brief is pending
194+
let fullContent = '';
195+
let currentAgent = '';
196+
let messageAdded = false;
197+
198+
for await (const response of streamChat(content, conversationId, userId)) {
199+
if (response.type === 'agent_response') {
200+
fullContent = response.content;
201+
currentAgent = response.agent || '';
202+
203+
if ((response.is_final || response.requires_user_input) && !messageAdded) {
204+
const assistantMessage: ChatMessage = {
205+
id: uuidv4(),
206+
role: 'assistant',
207+
content: fullContent,
208+
agent: currentAgent,
209+
timestamp: new Date().toISOString(),
210+
};
211+
setMessages(prev => [...prev, assistantMessage]);
212+
messageAdded = true;
213+
}
214+
} else if (response.type === 'error') {
215+
const errorMessage: ChatMessage = {
216+
id: uuidv4(),
217+
role: 'assistant',
218+
content: response.content || 'An error occurred while processing your request.',
219+
timestamp: new Date().toISOString(),
220+
};
221+
setMessages(prev => [...prev, errorMessage]);
222+
messageAdded = true;
223+
}
224+
}
225+
}
187226
} else {
188-
// Stream chat response
189-
let fullContent = '';
190-
let currentAgent = '';
191-
let messageAdded = false;
227+
// Check if this looks like a creative brief
228+
const briefKeywords = ['campaign', 'marketing', 'target audience', 'objective', 'deliverable'];
229+
const isBriefLike = briefKeywords.some(kw => content.toLowerCase().includes(kw));
192230

193-
for await (const response of streamChat(content, conversationId, userId)) {
194-
if (response.type === 'agent_response') {
195-
fullContent = response.content;
196-
currentAgent = response.agent || '';
197-
198-
// Add message when final OR when requiring user input (interactive response)
199-
if ((response.is_final || response.requires_user_input) && !messageAdded) {
200-
const assistantMessage: ChatMessage = {
231+
if (isBriefLike && !confirmedBrief) {
232+
// Parse as a creative brief
233+
const parsed = await parseBrief(content, conversationId, userId);
234+
setPendingBrief(parsed.brief);
235+
236+
const assistantMessage: ChatMessage = {
237+
id: uuidv4(),
238+
role: 'assistant',
239+
content: "I've parsed your creative brief. Please review the details below and let me know if you'd like to make any changes. You can say things like \"change the target audience to...\" or \"add a call to action...\". When everything looks good, click **Confirm Brief** to proceed.",
240+
agent: 'PlanningAgent',
241+
timestamp: new Date().toISOString(),
242+
};
243+
setMessages(prev => [...prev, assistantMessage]);
244+
} else {
245+
// Stream chat response
246+
let fullContent = '';
247+
let currentAgent = '';
248+
let messageAdded = false;
249+
250+
for await (const response of streamChat(content, conversationId, userId)) {
251+
if (response.type === 'agent_response') {
252+
fullContent = response.content;
253+
currentAgent = response.agent || '';
254+
255+
// Add message when final OR when requiring user input (interactive response)
256+
if ((response.is_final || response.requires_user_input) && !messageAdded) {
257+
const assistantMessage: ChatMessage = {
258+
id: uuidv4(),
259+
role: 'assistant',
260+
content: fullContent,
261+
agent: currentAgent,
262+
timestamp: new Date().toISOString(),
263+
};
264+
setMessages(prev => [...prev, assistantMessage]);
265+
messageAdded = true;
266+
}
267+
} else if (response.type === 'error') {
268+
// Handle error responses
269+
const errorMessage: ChatMessage = {
201270
id: uuidv4(),
202271
role: 'assistant',
203-
content: fullContent,
204-
agent: currentAgent,
272+
content: response.content || 'An error occurred while processing your request.',
205273
timestamp: new Date().toISOString(),
206274
};
207-
setMessages(prev => [...prev, assistantMessage]);
275+
setMessages(prev => [...prev, errorMessage]);
208276
messageAdded = true;
209277
}
210-
} else if (response.type === 'error') {
211-
// Handle error responses
212-
const errorMessage: ChatMessage = {
213-
id: uuidv4(),
214-
role: 'assistant',
215-
content: response.content || 'An error occurred while processing your request.',
216-
timestamp: new Date().toISOString(),
217-
};
218-
setMessages(prev => [...prev, errorMessage]);
219-
messageAdded = true;
220278
}
221279
}
222280
}
@@ -234,13 +292,15 @@ function App() {
234292
// Trigger refresh of chat history after message is sent
235293
setHistoryRefreshTrigger(prev => prev + 1);
236294
}
237-
}, [conversationId, userId, confirmedBrief]);
295+
}, [conversationId, userId, confirmedBrief, pendingBrief]);
238296

239-
const handleBriefConfirm = useCallback(async (brief: CreativeBrief) => {
297+
const handleBriefConfirm = useCallback(async () => {
298+
if (!pendingBrief) return;
299+
240300
try {
241301
const { confirmBrief } = await import('./api');
242-
await confirmBrief(brief, conversationId, userId);
243-
setConfirmedBrief(brief);
302+
await confirmBrief(pendingBrief, conversationId, userId);
303+
setConfirmedBrief(pendingBrief);
244304
setPendingBrief(null);
245305

246306
const assistantMessage: ChatMessage = {
@@ -254,7 +314,7 @@ function App() {
254314
} catch (error) {
255315
console.error('Error confirming brief:', error);
256316
}
257-
}, [conversationId, userId]);
317+
}, [conversationId, userId, pendingBrief]);
258318

259319
const handleBriefCancel = useCallback(() => {
260320
setPendingBrief(null);
@@ -407,7 +467,6 @@ function App() {
407467
selectedProducts={selectedProducts}
408468
onBriefConfirm={handleBriefConfirm}
409469
onBriefCancel={handleBriefCancel}
410-
onBriefEdit={setPendingBrief}
411470
onProductsChange={setSelectedProducts}
412471
onGenerateContent={handleGenerateContent}
413472
onRegenerateContent={handleGenerateContent}

0 commit comments

Comments
 (0)