fix(chatcompletions): only repair args that look like truncated JSON

The previous repair pass rewrote any non-parseable arguments string to
"{}", which clobbered legitimate accumulator contents in
test_stream_response_yields_events_for_tool_call (concatenated raw
deltas like "arg1arg2"). Narrow the guard: only when the stripped
buffer starts with "{" or "[" *and* fails to parse do we replace it
with "{}". Everything else is left untouched.
This commit is contained in:
Yahya 2026-06-08 10:27:46 +02:00 committed by Rufino Cabrera
parent 967762950c
commit cc82345bc0
2 changed files with 16 additions and 8 deletions

View File

@ -427,11 +427,15 @@ class Converter:
else:
# Truncated/streamed-then-cut function call args (e.g. "{")
# are not valid JSON and the upstream proxy rejects the whole
# request with HTTP 400, wedging the conversation.
try:
json.loads(arguments)
except (TypeError, ValueError):
arguments = "{}"
# request with HTTP 400, wedging the conversation. Only repair
# half-finished JSON object/array buffers; leave anything else
# (raw concatenated deltas, provider-specific blobs) alone.
stripped = arguments.lstrip() if isinstance(arguments, str) else ""
if stripped and stripped[0] in "{[":
try:
json.loads(arguments)
except (TypeError, ValueError):
arguments = "{}"
tool_calls_param.append(
ChatCompletionMessageToolCallParam(
id=tc.get("id", "")[:40],

View File

@ -2678,12 +2678,16 @@ class OpenAIChatCompletionsModel(Model):
# Repair partially-streamed function calls before emission so a
# truncated args string like "{" cannot poison conversation history
# and trigger HTTP 400 on the next request.
# and trigger HTTP 400 on the next request. Only rewrite when the
# buffer is clearly a half-finished JSON object/array; leave other
# accumulator contents (raw concatenated deltas, provider quirks)
# untouched so the rest of the pipeline can decide.
for _fc in state.function_calls.values():
_args = _fc.arguments or ""
if not _args.strip():
_stripped = _args.lstrip()
if not _stripped:
_fc.arguments = "{}"
else:
elif _stripped[0] in "{[":
try:
json.loads(_args)
except (TypeError, ValueError):