From 7088b8817bb5c6bbebe4ed7085250241ff67b240 Mon Sep 17 00:00:00 2001 From: DrMelone <27028174+Classic298@users.noreply.github.com> Date: Sun, 12 Apr 2026 22:14:04 +0200 Subject: [PATCH] chore: convert serialize_output helpers to async Converts content_endswith_newline, ensure_trailing_newline, append_part, and serialize_output to async def. Updates all 12 internal callsites to use await. --- backend/open_webui/utils/middleware.py | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 9ab5c18b74..cce91da1e4 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -389,18 +389,18 @@ def get_citation_source_from_tool_result( ] -def content_endswith_newline(parts): +async def content_endswith_newline(parts): if not parts: return False return parts[-1].endswith('\n') -def ensure_trailing_newline(parts): - if parts and not content_endswith_newline(parts): +async def ensure_trailing_newline(parts): + if parts and not await content_endswith_newline(parts): parts.append('\n') -def serialize_output(output: list) -> str: +async def serialize_output(output: list) -> str: """ Convert OR-aligned output items to HTML for display. For LLM consumption, use convert_output_to_messages() instead. @@ -408,7 +408,7 @@ def serialize_output(output: list) -> str: content_parts = [] fence_count = 0 - def append_part(part): + async def append_part(part): nonlocal fence_count content_parts.append(part) fence_count += part.count('```') @@ -428,12 +428,12 @@ def serialize_output(output: list) -> str: if 'text' in content_part: text = content_part.get('text', '').strip() if text: - append_part(text) - append_part('\n') + await append_part(text) + await append_part('\n') elif item_type == 'function_call': # Render tool call inline with its result (if available) - ensure_trailing_newline(content_parts) + await ensure_trailing_newline(content_parts) call_id = item.get('call_id', '') name = item.get('name', '') @@ -450,9 +450,9 @@ def serialize_output(output: list) -> str: files = result_item.get('files') embeds = result_item.get('embeds', '') - append_part(f'
\nTool Executed\n
\n') + await append_part(f'
\nTool Executed\n
\n') else: - append_part(f'
\nExecuting...\n
\n') + await append_part(f'
\nExecuting...\n
\n') elif item_type == 'function_call_output': # Already handled inline with function_call above @@ -477,7 +477,7 @@ def serialize_output(output: list) -> str: # render as done (a subsequent item means reasoning is complete) is_last_item = idx == len(output) - 1 - ensure_trailing_newline(content_parts) + await ensure_trailing_newline(content_parts) display = html.escape( '\n'.join( @@ -486,9 +486,9 @@ def serialize_output(output: list) -> str: ) if status == 'completed' or duration is not None or not is_last_item: - append_part(f'
\nThought for {duration or 0} seconds\n{display}\n
\n') + await append_part(f'
\nThought for {duration or 0} seconds\n{display}\n
\n') else: - append_part(f'
\nThinking…\n{display}\n
\n') + await append_part(f'
\nThinking…\n{display}\n
\n') elif item_type == 'open_webui:code_interpreter': # Check if previous content ends with an opening code fence (e.g. ```python) @@ -511,7 +511,7 @@ def serialize_output(output: list) -> str: while content_parts and not content_parts[-1].strip(): fence_count -= content_parts.pop().count('```') - ensure_trailing_newline(content_parts) + await ensure_trailing_newline(content_parts) # Render the code_interpreter item as a
block # so the frontend Collapsible renders "Analyzing..."/"Analyzed". @@ -537,9 +537,9 @@ def serialize_output(output: list) -> str: output_attr = f' output="{html.escape(output_json)}"' if status == 'completed' or duration is not None or not is_last_item: - append_part(f'
\nAnalyzed\n{display}\n
\n') + await append_part(f'
\nAnalyzed\n{display}\n
\n') else: - append_part(f'
\nAnalyzing…\n{display}\n
\n') + await append_part(f'
\nAnalyzing…\n{display}\n
\n') return ''.join(content_parts).strip() @@ -3617,7 +3617,7 @@ async def streaming_chat_response_handler(response, ctx): processed_data = { 'output': full_output(), - 'content': serialize_output(full_output()), + 'content': await serialize_output(full_output()), } # print(data) @@ -3776,7 +3776,7 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(full_output() + pending_fc_items), + 'content': await serialize_output(full_output() + pending_fc_items), }, } ) @@ -3835,7 +3835,7 @@ async def streaming_chat_response_handler(response, ctx): } ] - data = {'content': serialize_output(full_output())} + data = {'content': await serialize_output(full_output())} if value: if ( @@ -3986,13 +3986,13 @@ async def streaming_chat_response_handler(response, ctx): metadata['chat_id'], metadata['message_id'], { - 'content': serialize_output(full_output()), + 'content': await serialize_output(full_output()), 'output': full_output(), }, ) else: data = { - 'content': serialize_output(full_output()), + 'content': await serialize_output(full_output()), } if delta: @@ -4130,7 +4130,7 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(full_output()), + 'content': await serialize_output(full_output()), 'output': full_output(), }, } @@ -4382,7 +4382,7 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': frontend_output, }, } @@ -4481,7 +4481,7 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': output, }, } @@ -4605,7 +4605,7 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': output, }, } @@ -4645,7 +4645,7 @@ async def streaming_chat_response_handler(response, ctx): title = await Chats.get_chat_title_by_id(metadata['chat_id']) data = { 'done': True, - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': output, 'title': title, **({'usage': usage} if usage else {}), @@ -4658,7 +4658,7 @@ async def streaming_chat_response_handler(response, ctx): metadata['message_id'], { 'done': True, - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': output, **({'usage': usage} if usage else {}), }, @@ -4711,7 +4711,7 @@ async def streaming_chat_response_handler(response, ctx): metadata['message_id'], { 'done': True, - 'content': serialize_output(output), + 'content': await serialize_output(output), 'output': output, }, )