Skip to content

Conversation

@sumitaryal
Copy link

@sumitaryal sumitaryal commented Nov 29, 2025

Purpose

Fix for #29725,

Summary

This pull request fixes an issue where non harmony models using the Responses API with streaming and tools emit only ResponseTextDeltaEvent events, instead of ResponseFunctionCallArgumentsDeltaEvent when a tool call is selected. This prevents clients from reliably detecting and parsing tool call arguments from the stream.

Fix

This change updates the streaming path for non harmony models so that:

When the model selects a tool call, the arguments are surfaced as ResponseFunctionCallArgumentsDeltaEvent instead of plain text deltas. The event structure is now consistent with harmony models and with the non streaming Responses API behavior. With this, clients can treat harmony and non harmony models uniformly when handling tool calls during streaming.

Test Plan

Added a e2e test

Test Result:

For the example mentioned in the issue, the events emitted are as:

ResponseOutputItemAddedEvent(item=ResponseFunctionToolCall(arguments='', call_id='call_89716b1d95f08274', name='get_weather', type='function_call', id='chatcmpl-tool-a36680e5d0778655', status='in_progress'), output_index=0, sequence_number=2, type='response.output_item.added')
ResponseFunctionCallArgumentsDeltaEvent(delta='{"location": "', item_id='chatcmpl-tool-a36680e5d0778655', output_index=0, sequence_number=3, type='response.function_call_arguments.delta')
ResponseFunctionCallArgumentsDeltaEvent(delta='Paris', item_id='chatcmpl-tool-a36680e5d0778655', output_index=0, sequence_number=4, type='response.function_call_arguments.delta')
ResponseFunctionCallArgumentsDeltaEvent(delta='"}', item_id='chatcmpl-tool-a36680e5d0778655', output_index=0, sequence_number=5, type='response.function_call_arguments.delta')
ResponseFunctionCallArgumentsDoneEvent(arguments='{"location": "Paris"}', item_id='chatcmpl-tool-a36680e5d0778655', name='get_weather', output_index=0, sequence_number=6, type='response.function_call_arguments.done')
ResponseOutputItemDoneEvent(item=ResponseFunctionToolCall(arguments='{"location": "Paris"}', call_id='call_89716b1d95f08274', name='get_weather', type='function_call', id='chatcmpl-tool-a36680e5d0778655', status='completed'), output_index=0, sequence_number=7, type='response.output_item.done')

Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.
  • (Optional) Release notes update. If your change is user facing, please update the release notes draft in the Google Doc.

@chatgpt-codex-connector
Copy link

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for streaming tool calls in the Responses API for non-Harmony models, which is a great enhancement. The changes introduce new logic to parse tool calls from the streaming response and emit the correct events, aligning the behavior with Harmony models.

My review focuses on the new parsing logic. I've identified a critical issue in the manual JSON parsing implementation that could lead to incorrect behavior with certain tool call arguments. I've also pointed out an area where error handling could be improved to make debugging easier.

The addition of an end-to-end test for streaming tool calls is a good step towards ensuring correctness.

Comment on lines +1137 to +1145
def _bracket_level(s: str, opening: str = "{", closing: str = "}") -> int:
"""Calculate the current level of nested brackets in a given string."""
level = 0
for char in s:
if char == opening:
level += 1
elif char == closing:
level -= 1
return level
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current implementation of _bracket_level does not account for JSON string contents. If a string within the JSON contains the opening ({) or closing (}) characters, the bracket level count will be incorrect. This will cause _filter_delta_text to fail, and ultimately _extract_tool_call_required_streaming will produce incorrect output or fail when streaming tool calls.

For example, a tool call with an argument like {"code": "function foo() { return 1; }"} would be misparsed.

This is a critical issue as it can lead to incorrect parsing of tool calls. For robustness, the parsing logic should be made aware of JSON string boundaries. Consider using partial_json_parser more extensively to handle JSON parsing instead of manual bracket counting, as it is already a dependency and is designed to handle such cases robustly.

Comment on lines +1287 to +1292
try:
tool_parser = self.tool_parser(tokenizer)
except Exception:
logger.exception("Error in tool parser creation.")
tool_choice_auto = False
tool_parser = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Catching a broad Exception and silently disabling tool_choice_auto can hide important errors from the user. If the tool parser fails to initialize due to a misconfiguration or a bug, the request will unexpectedly fall back to not using tools, which can be difficult to debug. It would be better to log this as an error and potentially fail the request with an informative message, rather than silently changing its behavior.

@ApostaC
Copy link
Collaborator

ApostaC commented Dec 1, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend gpt-oss Related to GPT-OSS models

Projects

Status: To Triage

Development

Successfully merging this pull request may close these issues.

2 participants