@@ -299,6 +299,44 @@ def _sanitize_chat_row(self, chat_item):
299299
300300 return changed
301301
302+ def _normalize_assistant_content_from_output (self , chat : dict , prior_chat : dict ) -> dict :
303+ """Rewrite assistant 'content' from 'output' when 'output' has changed.
304+
305+ Skips messages where the caller also changed 'content', or where the prior
306+ 'content' differs from 'serialize_output(prior_output)'. Preserves filter
307+ outlet rewrites and direct user content edits across saves.
308+ """
309+ from open_webui .utils .middleware import serialize_output
310+
311+ history = (chat or {}).get ('history' ) or {}
312+ messages = history .get ('messages' )
313+ if not isinstance (messages , dict ):
314+ return chat
315+
316+ prior_messages = ((prior_chat or {}).get ('history' ) or {}).get ('messages' ) or {}
317+
318+ for message_id , message in messages .items ():
319+ if not (isinstance (message , dict ) and message .get ('role' ) == 'assistant' ):
320+ continue
321+ new_output = message .get ('output' )
322+ if not isinstance (new_output , list ):
323+ continue
324+ prior = prior_messages .get (message_id ) or {}
325+ old_output = prior .get ('output' )
326+ if new_output == old_output :
327+ continue
328+ prior_content = prior .get ('content' )
329+ if message .get ('content' ) != prior_content :
330+ continue
331+ try :
332+ canonical = serialize_output (old_output ) if isinstance (old_output , list ) else None
333+ except Exception :
334+ canonical = None
335+ if prior_content != canonical :
336+ continue
337+ message ['content' ] = serialize_output (new_output )
338+ return chat
339+
302340 async def insert_new_chat (
303341 self , id : str , user_id : str , form_data : ChatForm , db : AsyncSession | None = None
304342 ) -> ChatModel | None :
@@ -394,6 +432,7 @@ async def update_chat_by_id(self, id: str, chat: dict, db: AsyncSession | None =
394432 try :
395433 async with get_async_db_context (db ) as db :
396434 chat_item = await db .get (Chat , id )
435+ chat = self ._normalize_assistant_content_from_output (chat , chat_item .chat )
397436 chat_item .chat = self ._clean_null_bytes (chat )
398437 chat_item .title = self ._clean_null_bytes (chat ['title' ]) if 'title' in chat else 'New Chat'
399438
0 commit comments