@@ -95,22 +95,23 @@ async def generate():
9595 ):
9696 yield f"data: { json .dumps (response )} \n \n "
9797
98- # Try to save assistant responses
99- if response .get ("is_final" ):
100- try :
101- cosmos_service = await get_cosmos_service ()
102- await cosmos_service .add_message_to_conversation (
103- conversation_id = conversation_id ,
104- user_id = user_id ,
105- message = {
106- "role" : "assistant" ,
107- "content" : response .get ("content" , "" ),
108- "agent" : response .get ("agent" , "" ),
109- "timestamp" : datetime .now (timezone .utc ).isoformat ()
110- }
111- )
112- except Exception as e :
113- logger .warning (f"Failed to save response to CosmosDB: { e } " )
98+ # Save assistant responses when final OR when requiring user input
99+ if response .get ("is_final" ) or response .get ("requires_user_input" ):
100+ if response .get ("content" ):
101+ try :
102+ cosmos_service = await get_cosmos_service ()
103+ await cosmos_service .add_message_to_conversation (
104+ conversation_id = conversation_id ,
105+ user_id = user_id ,
106+ message = {
107+ "role" : "assistant" ,
108+ "content" : response .get ("content" , "" ),
109+ "agent" : response .get ("agent" , "" ),
110+ "timestamp" : datetime .now (timezone .utc ).isoformat ()
111+ }
112+ )
113+ except Exception as e :
114+ logger .warning (f"Failed to save response to CosmosDB: { e } " )
114115 except Exception as e :
115116 logger .exception (f"Error in orchestrator: { e } " )
116117 yield f"data: { json .dumps ({'type' : 'error' , 'content' : str (e ), 'is_final' : True })} \n \n "
@@ -136,24 +137,60 @@ async def parse_brief():
136137
137138 Request body:
138139 {
139- "brief_text": "Free-form creative brief text"
140+ "brief_text": "Free-form creative brief text",
141+ "conversation_id": "optional-uuid",
142+ "user_id": "user identifier"
140143 }
141144
142145 Returns:
143146 Structured CreativeBrief JSON for user confirmation.
144147 """
145148 data = await request .get_json ()
146149 brief_text = data .get ("brief_text" , "" )
150+ conversation_id = data .get ("conversation_id" ) or str (uuid .uuid4 ())
151+ user_id = data .get ("user_id" , "anonymous" )
147152
148153 if not brief_text :
149154 return jsonify ({"error" : "Brief text is required" }), 400
150155
156+ # Save the user's brief text as a message to CosmosDB
157+ try :
158+ cosmos_service = await get_cosmos_service ()
159+ await cosmos_service .add_message_to_conversation (
160+ conversation_id = conversation_id ,
161+ user_id = user_id ,
162+ message = {
163+ "role" : "user" ,
164+ "content" : brief_text ,
165+ "timestamp" : datetime .now (timezone .utc ).isoformat ()
166+ }
167+ )
168+ except Exception as e :
169+ logger .warning (f"Failed to save brief message to CosmosDB: { e } " )
170+
151171 orchestrator = get_orchestrator ()
152172 parsed_brief = await orchestrator .parse_brief (brief_text )
153173
174+ # Save the assistant's parsing response
175+ try :
176+ cosmos_service = await get_cosmos_service ()
177+ await cosmos_service .add_message_to_conversation (
178+ conversation_id = conversation_id ,
179+ user_id = user_id ,
180+ message = {
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" : datetime .now (timezone .utc ).isoformat ()
185+ }
186+ )
187+ except Exception as e :
188+ logger .warning (f"Failed to save parsing response to CosmosDB: { e } " )
189+
154190 return jsonify ({
155191 "brief" : parsed_brief .model_dump (),
156192 "requires_confirmation" : True ,
193+ "conversation_id" : conversation_id ,
157194 "message" : "Please review and confirm the parsed creative brief"
158195 })
159196
@@ -183,13 +220,26 @@ async def confirm_brief():
183220 except Exception as e :
184221 return jsonify ({"error" : f"Invalid brief format: { str (e )} " }), 400
185222
186- # Try to save the confirmed brief to CosmosDB, but don't fail if unavailable
223+ # Try to save the confirmed brief to CosmosDB, preserving existing messages
187224 try :
188225 cosmos_service = await get_cosmos_service ()
226+
227+ # Get existing conversation to preserve messages
228+ existing = await cosmos_service .get_conversation (conversation_id , user_id )
229+ existing_messages = existing .get ("messages" , []) if existing else []
230+
231+ # Add confirmation message
232+ existing_messages .append ({
233+ "role" : "assistant" ,
234+ "content" : "Great! Your creative brief has been confirmed. Now you can select products to feature and generate content." ,
235+ "agent" : "TriageAgent" ,
236+ "timestamp" : datetime .now (timezone .utc ).isoformat ()
237+ })
238+
189239 await cosmos_service .save_conversation (
190240 conversation_id = conversation_id ,
191241 user_id = user_id ,
192- messages = [] ,
242+ messages = existing_messages ,
193243 brief = brief ,
194244 metadata = {"status" : "brief_confirmed" }
195245 )
@@ -227,12 +277,29 @@ async def generate_content():
227277 products_data = data .get ("products" , [])
228278 generate_images = data .get ("generate_images" , True )
229279 conversation_id = data .get ("conversation_id" ) or str (uuid .uuid4 ())
280+ user_id = data .get ("user_id" , "anonymous" )
230281
231282 try :
232283 brief = CreativeBrief (** brief_data )
233284 except Exception as e :
234285 return jsonify ({"error" : f"Invalid brief format: { str (e )} " }), 400
235286
287+ # Save user request for content generation
288+ try :
289+ cosmos_service = await get_cosmos_service ()
290+ product_names = [p .get ("product_name" , "product" ) for p in products_data [:3 ]]
291+ await cosmos_service .add_message_to_conversation (
292+ conversation_id = conversation_id ,
293+ user_id = user_id ,
294+ message = {
295+ "role" : "user" ,
296+ "content" : f"Generate content for: { ', ' .join (product_names ) if product_names else 'the campaign' } " ,
297+ "timestamp" : datetime .now (timezone .utc ).isoformat ()
298+ }
299+ )
300+ except Exception as e :
301+ logger .warning (f"Failed to save generation request to CosmosDB: { e } " )
302+
236303 orchestrator = get_orchestrator ()
237304
238305 async def generate ():
@@ -256,6 +323,24 @@ async def generate():
256323 except Exception as e :
257324 logger .warning (f"Failed to save image to blob storage: { e } " )
258325
326+ # Save generated content to conversation
327+ try :
328+ cosmos_service = await get_cosmos_service ()
329+ text_content = response .get ("text_content" , {})
330+ headline = text_content .get ("headline" , "" ) if isinstance (text_content , dict ) else ""
331+ await cosmos_service .add_message_to_conversation (
332+ conversation_id = conversation_id ,
333+ user_id = user_id ,
334+ message = {
335+ "role" : "assistant" ,
336+ "content" : f"Content generated successfully! { f'Headline: "{ headline } "' if headline else '' } " ,
337+ "agent" : "ContentAgent" ,
338+ "timestamp" : datetime .now (timezone .utc ).isoformat ()
339+ }
340+ )
341+ except Exception as e :
342+ logger .warning (f"Failed to save generated content to CosmosDB: { e } " )
343+
259344 # Format response to match what frontend expects
260345 yield f"data: { json .dumps ({'type' : 'agent_response' , 'content' : json .dumps (response ), 'is_final' : True })} \n \n "
261346 except Exception as e :
@@ -441,6 +526,28 @@ async def get_conversation(conversation_id: str):
441526 return jsonify (conversation )
442527
443528
529+ @app .route ("/api/conversations/<conversation_id>" , methods = ["DELETE" ])
530+ async def delete_conversation (conversation_id : str ):
531+ """
532+ Delete a specific conversation.
533+
534+ Query params:
535+ user_id: User identifier (required)
536+ """
537+ user_id = request .args .get ("user_id" )
538+
539+ if not user_id :
540+ return jsonify ({"error" : "user_id is required" }), 400
541+
542+ try :
543+ cosmos_service = await get_cosmos_service ()
544+ await cosmos_service .delete_conversation (conversation_id , user_id )
545+ return jsonify ({"success" : True , "message" : "Conversation deleted" })
546+ except Exception as e :
547+ logger .warning (f"Failed to delete conversation: { e } " )
548+ return jsonify ({"error" : "Failed to delete conversation" }), 500
549+
550+
444551# ==================== Brand Guidelines Endpoints ====================
445552
446553@app .route ("/api/brand-guidelines" , methods = ["GET" ])
0 commit comments