Merge pull request #17882 from ShirasawaSama/patch-3

fix: handle non‑UTF8 chars in third‑party responses without error
This commit is contained in:
Tim Jaeryang Baek 2025-09-29 21:25:55 -05:00 committed by GitHub
commit 170ae9f3be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -148,7 +148,7 @@ def process_tool_result(
if isinstance(tool_result, HTMLResponse): if isinstance(tool_result, HTMLResponse):
content_disposition = tool_result.headers.get("Content-Disposition", "") content_disposition = tool_result.headers.get("Content-Disposition", "")
if "inline" in content_disposition: if "inline" in content_disposition:
content = tool_result.body.decode("utf-8") content = tool_result.body.decode("utf-8", "replace")
tool_result_embeds.append(content) tool_result_embeds.append(content)
if 200 <= tool_result.status_code < 300: if 200 <= tool_result.status_code < 300:
@ -176,7 +176,7 @@ def process_tool_result(
"message": f"{tool_function_name}: Unexpected status code {tool_result.status_code} from embedded UI result.", "message": f"{tool_function_name}: Unexpected status code {tool_result.status_code} from embedded UI result.",
} }
else: else:
tool_result = tool_result.body.decode("utf-8") tool_result = tool_result.body.decode("utf-8", "replace")
elif (tool_type == "external" and isinstance(tool_result, tuple)) or ( elif (tool_type == "external" and isinstance(tool_result, tuple)) or (
direct_tool and isinstance(tool_result, list) and len(tool_result) == 2 direct_tool and isinstance(tool_result, list) and len(tool_result) == 2
@ -284,7 +284,7 @@ async def chat_completion_tools_handler(
content = None content = None
if hasattr(response, "body_iterator"): if hasattr(response, "body_iterator"):
async for chunk in response.body_iterator: async for chunk in response.body_iterator:
data = json.loads(chunk.decode("utf-8")) data = json.loads(chunk.decode("utf-8", "replace"))
content = data["choices"][0]["message"]["content"] content = data["choices"][0]["message"]["content"]
# Cleanup any remaining background tasks if necessary # Cleanup any remaining background tasks if necessary
@ -1643,7 +1643,9 @@ async def process_chat_response(
response.body, bytes response.body, bytes
): ):
try: try:
response_data = json.loads(response.body.decode("utf-8")) response_data = json.loads(
response.body.decode("utf-8", "replace")
)
except json.JSONDecodeError: except json.JSONDecodeError:
response_data = { response_data = {
"error": {"detail": "Invalid JSON response"} "error": {"detail": "Invalid JSON response"}
@ -2277,7 +2279,11 @@ async def process_chat_response(
last_delta_data = None last_delta_data = None
async for line in response.body_iterator: async for line in response.body_iterator:
line = line.decode("utf-8") if isinstance(line, bytes) else line line = (
line.decode("utf-8", "replace")
if isinstance(line, bytes)
else line
)
data = line data = line
# Skip empty lines # Skip empty lines