diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 775a703384..97233737dd 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -1403,13 +1403,18 @@ async def process_chat_response(
for block in content_blocks:
if block["type"] == "text":
- content = f"{content}{block['content'].strip()}\n"
+ block_content = block["content"].strip()
+ if block_content:
+ content = f"{content}{block_content}\n"
elif block["type"] == "tool_calls":
attributes = block.get("attributes", {})
tool_calls = block.get("content", [])
results = block.get("results", [])
+ if content and not content.endswith("\n"):
+ content += "\n"
+
if results:
tool_calls_display_content = ""
@@ -1432,12 +1437,12 @@ async def process_chat_response(
break
if tool_result:
- tool_calls_display_content = f'{tool_calls_display_content}\n\nTool Executed
\n \n'
+ tool_calls_display_content = f'{tool_calls_display_content}\nTool Executed
\n \n'
else:
- tool_calls_display_content = f'{tool_calls_display_content}\n\nExecuting...
\n '
+ tool_calls_display_content = f'{tool_calls_display_content}\nExecuting...
\n \n'
if not raw:
- content = f"{content}\n{tool_calls_display_content}\n\n"
+ content = f"{content}{tool_calls_display_content}"
else:
tool_calls_display_content = ""
@@ -1450,10 +1455,10 @@ async def process_chat_response(
"arguments", ""
)
- tool_calls_display_content = f'{tool_calls_display_content}\n\nExecuting...
\n '
+ tool_calls_display_content = f'{tool_calls_display_content}\n\nExecuting...
\n \n'
if not raw:
- content = f"{content}\n{tool_calls_display_content}\n\n"
+ content = f"{content}{tool_calls_display_content}"
elif block["type"] == "reasoning":
reasoning_display_content = "\n".join(
@@ -1466,16 +1471,23 @@ async def process_chat_response(
start_tag = block.get("start_tag", "")
end_tag = block.get("end_tag", "")
+ if content and not content.endswith("\n"):
+ content += "\n"
+
if reasoning_duration is not None:
if raw:
- content = f'{content}\n{start_tag}{block["content"]}{end_tag}\n'
+ content = (
+ f'{content}{start_tag}{block["content"]}{end_tag}\n'
+ )
else:
- content = f'{content}\n\nThought for {reasoning_duration} seconds
\n{reasoning_display_content}\n \n'
+ content = f'{content}\nThought for {reasoning_duration} seconds
\n{reasoning_display_content}\n \n'
else:
if raw:
- content = f'{content}\n{start_tag}{block["content"]}{end_tag}\n'
+ content = (
+ f'{content}{start_tag}{block["content"]}{end_tag}\n'
+ )
else:
- content = f'{content}\n\nThinking…
\n{reasoning_display_content}\n \n'
+ content = f'{content}\nThinking…
\n{reasoning_display_content}\n \n'
elif block["type"] == "code_interpreter":
attributes = block.get("attributes", {})
@@ -1495,22 +1507,26 @@ async def process_chat_response(
# Keep content as is - either closing backticks or no backticks
content = content_stripped + original_whitespace
+ if content and not content.endswith("\n"):
+ content += "\n"
+
if output:
output = html.escape(json.dumps(output))
if raw:
- content = f'{content}\n\n{block["content"]}\n\n```output\n{output}\n```\n'
+ content = f'{content}\n{block["content"]}\n\n```output\n{output}\n```\n'
else:
- content = f'{content}\n\nAnalyzed
\n```{lang}\n{block["content"]}\n```\n \n'
+ content = f'{content}\nAnalyzed
\n```{lang}\n{block["content"]}\n```\n \n'
else:
if raw:
- content = f'{content}\n\n{block["content"]}\n\n'
+ content = f'{content}\n{block["content"]}\n\n'
else:
- content = f'{content}\n\nAnalyzing...
\n```{lang}\n{block["content"]}\n```\n \n'
+ content = f'{content}\nAnalyzing...
\n```{lang}\n{block["content"]}\n```\n \n'
else:
block_content = str(block["content"]).strip()
- content = f"{content}{block['type']}: {block_content}\n"
+ if block_content:
+ content = f"{content}{block['type']}: {block_content}\n"
return content.strip()