@@ -394,13 +394,51 @@ async def update_chat_by_id(self, id: str, chat: dict, db: AsyncSession | None =
394394 try :
395395 async with get_async_db_context (db ) as db :
396396 chat_item = await db .get (Chat , id )
397+ if chat_item is None :
398+ return None
399+
400+ # Snapshot for the post-commit row diff.
401+ prior_messages = (
402+ (chat_item .chat or {}).get ('history' , {}).get ('messages' , {}) or {}
403+ )
404+
397405 chat_item .chat = self ._clean_null_bytes (chat )
398406 chat_item .title = self ._clean_null_bytes (chat ['title' ]) if 'title' in chat else 'New Chat'
399407
400408 chat_item .updated_at = int (time .time ())
401409
402410 await db .commit ()
403411
412+ # Reconcile chat_message rows with the just-written blob.
413+ try :
414+ new_messages = (chat .get ('history' , {}) or {}).get ('messages' , {}) or {}
415+
416+ for message_id , message in new_messages .items ():
417+ if (
418+ isinstance (message , dict )
419+ and message .get ('role' )
420+ and prior_messages .get (message_id ) != message
421+ ):
422+ await ChatMessages .upsert_message (
423+ message_id = message_id ,
424+ chat_id = id ,
425+ user_id = chat_item .user_id ,
426+ data = message ,
427+ db = db ,
428+ )
429+
430+ removed_message_ids = set (prior_messages .keys ()) - set (new_messages .keys ())
431+ if removed_message_ids :
432+ composite_ids = {f'{ id } -{ mid } ' for mid in removed_message_ids }
433+ await db .execute (
434+ delete (ChatMessage )
435+ .where (ChatMessage .chat_id == id )
436+ .where (ChatMessage .id .in_ (composite_ids ))
437+ )
438+ await db .commit ()
439+ except Exception as e :
440+ log .warning (f'Failed to sync chat_message rows: { e } ' )
441+
404442 return ChatModel .model_validate (chat_item )
405443 except Exception :
406444 return None
0 commit comments