@@ -299,6 +299,32 @@ 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+ Skipping unchanged messages preserves user-typed text on messages
306+ with empty or absent 'output'.
307+ """
308+ from open_webui .utils .middleware import serialize_output
309+
310+ history = (chat or {}).get ('history' ) or {}
311+ messages = history .get ('messages' )
312+ if not isinstance (messages , dict ):
313+ return chat
314+
315+ prior_messages = ((prior_chat or {}).get ('history' ) or {}).get ('messages' ) or {}
316+
317+ for message_id , message in messages .items ():
318+ if not (isinstance (message , dict ) and message .get ('role' ) == 'assistant' ):
319+ continue
320+ new_output = message .get ('output' )
321+ if not isinstance (new_output , list ):
322+ continue
323+ old_output = (prior_messages .get (message_id ) or {}).get ('output' )
324+ if new_output != old_output :
325+ message ['content' ] = serialize_output (new_output )
326+ return chat
327+
302328 async def insert_new_chat (
303329 self , id : str , user_id : str , form_data : ChatForm , db : AsyncSession | None = None
304330 ) -> ChatModel | None :
@@ -402,6 +428,7 @@ async def update_chat_by_id(self, id: str, chat: dict, db: AsyncSession | None =
402428 (chat_item .chat or {}).get ('history' , {}).get ('messages' , {}) or {}
403429 )
404430
431+ chat = self ._normalize_assistant_content_from_output (chat , chat_item .chat )
405432 chat_item .chat = self ._clean_null_bytes (chat )
406433 chat_item .title = self ._clean_null_bytes (chat ['title' ]) if 'title' in chat else 'New Chat'
407434
0 commit comments