@@ -387,13 +387,51 @@ async def update_chat_by_id(self, id: str, chat: dict, db: Optional[AsyncSession
387387 try :
388388 async with get_async_db_context (db ) as db :
389389 chat_item = await db .get (Chat , id )
390+ if chat_item is None :
391+ return None
392+
393+ # Snapshot for the post-commit row diff.
394+ prior_messages = (
395+ (chat_item .chat or {}).get ('history' , {}).get ('messages' , {}) or {}
396+ )
397+
390398 chat_item .chat = self ._clean_null_bytes (chat )
391399 chat_item .title = self ._clean_null_bytes (chat ['title' ]) if 'title' in chat else 'New Chat'
392400
393401 chat_item .updated_at = int (time .time ())
394402
395403 await db .commit ()
396404
405+ # Reconcile chat_message rows with the just-written blob.
406+ try :
407+ new_messages = (chat .get ('history' , {}) or {}).get ('messages' , {}) or {}
408+
409+ for message_id , message in new_messages .items ():
410+ if (
411+ isinstance (message , dict )
412+ and message .get ('role' )
413+ and prior_messages .get (message_id ) != message
414+ ):
415+ await ChatMessages .upsert_message (
416+ message_id = message_id ,
417+ chat_id = id ,
418+ user_id = chat_item .user_id ,
419+ data = message ,
420+ db = db ,
421+ )
422+
423+ removed_message_ids = set (prior_messages .keys ()) - set (new_messages .keys ())
424+ if removed_message_ids :
425+ composite_ids = {f'{ id } -{ mid } ' for mid in removed_message_ids }
426+ await db .execute (
427+ delete (ChatMessage )
428+ .where (ChatMessage .chat_id == id )
429+ .where (ChatMessage .id .in_ (composite_ids ))
430+ )
431+ await db .commit ()
432+ except Exception as e :
433+ log .warning (f'Failed to sync chat_message rows: { e } ' )
434+
397435 return ChatModel .model_validate (chat_item )
398436 except Exception :
399437 return None
0 commit comments