diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4157629463..017176ba39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
-- 🔒 **Public sharing permission bypass fix.** Users with write access to knowledge bases, tools, skills, prompts, and models could previously see and use the "Public" sharing option regardless of their actual sharing permissions, and direct API calls could bypass frontend restrictions entirely; both frontend and backend now properly enforce sharing.public_* permissions, silently stripping public grants when users lack the corresponding permission. [#21356](https://github.com/open-webui/open-webui/issues/21356), [#21358](https://github.com/open-webui/open-webui/pull/21358)
+- 🔒 **Public sharing permission bypass fix.** Users with write access to knowledge bases, tools, skills, prompts, and models could previously see and use the "Public" sharing option regardless of their actual sharing permissions, and direct API calls could bypass frontend restrictions entirely; both frontend and backend now properly enforce sharing.public\_\* permissions, silently stripping public grants when users lack the corresponding permission. [#21356](https://github.com/open-webui/open-webui/issues/21356), [#21358](https://github.com/open-webui/open-webui/pull/21358)
- 🐘 **PostgreSQL analytics query fix.** The get_chat_ids_by_model_id function now works correctly with PostgreSQL by using GROUP BY with aggregate ordering instead of DISTINCT with non-aggregate ORDER BY, which PostgreSQL does not support. [Commit](https://github.com/open-webui/open-webui/commit/7bda6bf767d5d5c4dc1111465096a88e10b5030e)
- 🐘 **Skills PostgreSQL compatibility fix.** Skills now work correctly with PostgreSQL by using SQLAlchemy's native JSON column type instead of the custom JSONField, which caused compatibility issues. [Commit](https://github.com/open-webui/open-webui/commit/b4c3f54f9648c4232a0fd6557703ffa66fcf4caa)
- 🗑️ **Chat message deletion cascade fix.** Deleting chats now properly removes associated chat messages from the database, preventing orphaned message records from accumulating when chats or shared chats are deleted. [#21362](https://github.com/open-webui/open-webui/pull/21362)
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 1fa562e0d1..3354889e7e 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -431,7 +431,9 @@ def serialize_output(output: list) -> str:
if isinstance(ci_output, dict):
output_json = json.dumps(ci_output, ensure_ascii=False)
else:
- output_json = json.dumps({"result": str(ci_output)}, ensure_ascii=False)
+ output_json = json.dumps(
+ {"result": str(ci_output)}, ensure_ascii=False
+ )
output_attr = f' output="{html.escape(output_json)}"'
if status == "completed" or duration is not None or not is_last_item:
@@ -3134,8 +3136,6 @@ async def streaming_chat_response_handler(response, ctx):
if re.search(end_tag_pattern, block_content):
end_flag = True
-
-
# Strip start and end tags from content
start_tag_pattern = rf"{re.escape(start_tag)}"
if start_tag.startswith("<") and start_tag.endswith(">"):
@@ -3683,12 +3683,16 @@ async def streaming_chat_response_handler(response, ctx):
# output.
last_item = output[-1] if output else None
last_item_type = (
- last_item.get("type", "") if last_item else ""
+ last_item.get("type", "")
+ if last_item
+ else ""
)
inside_tag_block = (
last_item is not None
and last_item.get("status") == "in_progress"
- and last_item.get("attributes", {}).get("type")
+ and last_item.get("attributes", {}).get(
+ "type"
+ )
!= "reasoning_content"
and (
last_item_type == "reasoning"
@@ -3704,7 +3708,10 @@ async def streaming_chat_response_handler(response, ctx):
if inside_tag_block:
# Append to the existing tag-based item
- if last_item_type == "open_webui:code_interpreter":
+ if (
+ last_item_type
+ == "open_webui:code_interpreter"
+ ):
last_item["code"] = (
last_item.get("code", "") + value
)
@@ -3769,7 +3776,10 @@ async def streaming_chat_response_handler(response, ctx):
msg_parts[-1]["text"] += value
else:
output[-1]["content"] = [
- {"type": "output_text", "text": value}
+ {
+ "type": "output_text",
+ "text": value,
+ }
]
if DETECT_REASONING_TAGS:
diff --git a/backend/open_webui/utils/misc.py b/backend/open_webui/utils/misc.py
index 9d9cfa1d04..13539ca9d0 100644
--- a/backend/open_webui/utils/misc.py
+++ b/backend/open_webui/utils/misc.py
@@ -236,7 +236,9 @@ def convert_output_to_messages(output: list, raw: bool = False) -> list[dict]:
code_output = item.get("output", "")
if code:
- pending_content.append(f"\n{code}\n")
+ pending_content.append(
+ f"\n{code}\n"
+ )
if code_output:
if isinstance(code_output, dict):
@@ -246,7 +248,9 @@ def convert_output_to_messages(output: list, raw: bool = False) -> list[dict]:
else:
output_text = str(code_output)
if output_text:
- pending_content.append(f"\n{output_text}\n")
+ pending_content.append(
+ f"\n{output_text}\n"
+ )
elif item_type.startswith("open_webui:"):
# Skip other extension types