Skip to content

fix(responses): preserve function calls completed in done events - #2057

Open
MrLiuGangQiang wants to merge 6 commits into
looplj:unstablefrom
MrLiuGangQiang:fix/responses-done-arguments
Open

fix(responses): preserve function calls completed in done events#2057
MrLiuGangQiang wants to merge 6 commits into
looplj:unstablefrom
MrLiuGangQiang:fix/responses-done-arguments

Conversation

@MrLiuGangQiang

@MrLiuGangQiang MrLiuGangQiang commented Jul 22, 2026

Copy link
Copy Markdown

Summary

Fixes an OpenAI Responses streaming conversion issue where a function call completed by response.function_call_arguments.done can lose its arguments or tool identity before it reaches the client.

This affects upstreams that provide arguments, name, namespace, or call_id only in a later event. In Codex, that can leave collaboration.spawn_agent without a dispatchable identity even when the downstream response is valid.

Root cause

The outbound transformer previously treated response.function_call_arguments.done as state-only. The inbound transformer also emitted response.output_item.added immediately, even when the function name was absent. A later terminal event could repair the final item, but it could not repair the already-emitted initial item that clients use to route the call.

Changes

Outbound Responses transformer

  • Resolves calls from call_id, with an item_id to call_id fallback.
  • Treats non-empty terminal arguments as authoritative.
  • Emits the missing argument suffix after partial deltas, without duplicating complete payloads.
  • Emits an identity-only unified delta when name or namespace arrives after all arguments have already streamed.
  • Preserves id, type, name, and namespace in emitted tool-call deltas.
  • Returns an explicit mismatch error for divergent terminal arguments.

Inbound Responses transformer

  • Defers output_item.added for unnamed function calls until a tool name is available.
  • Buffers arguments received before tool identity and replays them only after emitting the correctly identified output_item.added.
  • Merges late tool identity into tracked state.
  • Includes the final call_id, name, namespace, and arguments in terminal response.function_call_arguments.done and response.output_item.done events.

JSON comparison safety

Semantically equivalent JSON that differs only in whitespace or object-key order is accepted without a duplicate delta. Comparisons use json.Decoder.UseNumber(), preserving numeric lexemes so distinct large integers cannot collapse through float64 conversion.

Regression coverage

  • Complete arguments provided only in function_call_arguments.done.
  • Reformatted but equivalent terminal JSON.
  • Distinct large integers (9007199254740992 and 9007199254740993) rejected as a mismatch.
  • Complete outbound to unified to inbound round trip when terminal events provide spawn_agent, collaboration, call ID, and JSON arguments.
  • Arguments that arrive before late tool identity are buffered until a correctly identified output_item.added is emitted.

Verification

cd llm
go test ./transformer/openai/responses -run 'TestOutboundTransformer_TransformStream_(EmitsArgumentsProvidedOnlyInDone|AcceptsEquivalentFinalArguments|RejectsDistinctLargeJSONNumbers)|TestResponsesStream_RoundTrip_(PreservesToolIdentityProvidedOnlyInDone|DefersFunctionCallUntilLateIdentityArrives)' -count=1
git diff --check

@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR preserves completed function calls during OpenAI Responses stream conversion. The main changes are:

  • Reconciles arguments and tool identity from terminal function-call events.
  • Defers unnamed inbound function calls until their identity arrives.
  • Buffers and replays arguments received before tool identity.
  • Compares reformatted JSON without losing large-number precision.
  • Adds tests for terminal arguments, late identity, and JSON comparison.

Confidence Score: 5/5

This looks safe to merge.

  • The updated JSON comparison preserves large-number precision.
  • Terminal arguments and late tool identity are retained across the stream conversion.
  • No remaining blocking issue qualifies for this follow-up review.

Important Files Changed

Filename Overview
llm/transformer/openai/responses/outbound_stream.go Reconciles terminal function-call arguments and identity while preserving JSON number precision.
llm/transformer/openai/responses/inbound_stream.go Defers unnamed calls, buffers early arguments, and includes final identity in completion events.
llm/transformer/openai/responses/outbound_stream_test.go Adds coverage for terminal arguments, late identity, equivalent JSON, and distinct large numbers.

Reviews (6): Last reviewed commit: "test(responses): preserve tool identity ..." | Re-trigger Greptile

Comment thread llm/transformer/openai/responses/outbound_stream.go Outdated
@MrLiuGangQiang MrLiuGangQiang changed the title fix(responses): forward arguments provided only in done event fix(responses): preserve function calls completed in done events Jul 22, 2026
Comment thread llm/transformer/openai/responses/outbound_stream.go
@MrLiuGangQiang

Copy link
Copy Markdown
Author

主要是为了解决codex使用子agent报错的问题

MrLiuGangQiang added a commit to MrLiuGangQiang/axonhub that referenced this pull request Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant