Skip to content

fix(ai): reconcile final response calls by call id - #46084

Merged
kitlangton merged 7 commits into
v2from
responses-call-identity
Sep 1, 2026
Merged

kitlangton merged 7 commits into
v2from
responses-call-identity

Conversation

@kitlangton

@kitlangton kitlangton commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Why

Some OpenAI-compatible providers omit response.output_item.done and rely on response.completed.output for authoritative function-call arguments. If that terminal item differed only in whether its optional item id was present, the parser looked up the pending call by the terminal item ID, skipped reconciliation, and emitted the partial streamed arguments instead.

What Changes

Completed-response reconciliation now admits a pending function call by its stable call_id, then delegates to the existing onOutputItemDone finalizer.

Stream Result
Stable item ID Final arguments reconcile as before
Terminal item ID omitted Final arguments replace the partial buffer
Unseen terminal call Still ignored
Reused or colliding protocol identities Not supported

The existing provider test now omits the terminal item ID while asserting authoritative arguments and first-admission metadata. No parser state or identity maps were added.

Scope

This preserves the existing optional-ID compatibility behavior without attempting to interpret protocol-invalid identity reuse or collisions.

Verification

cd packages/ai
bun run test
bun typecheck

git diff --check origin/v2
  • 927 tests passed, 25 skipped, 0 failed.
  • Both AI typecheck configurations passed.
  • The pre-push hook passed all 33 workspace typecheck tasks.

@kitlangton

kitlangton commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Closing this after rechecking it against current v2, the Responses contract, and recorded OpenAI/Azure streams. Conforming argument events require both item_id and output_index to identify the same output item throughout its lifecycle; output indexes and call_ids cannot be reused within a response. A function-call item id may be absent, but when present it must remain stable and unique. ID-less calls complete through item-level events using their stable call_id, which current v2 already handles.

The remaining diff primarily retains history for reused or colliding item IDs and output indexes. Those streams violate the identity/lifecycle contract and become inherently ambiguous, so four additional identity maps and 300+ lines of adversarial tests are not justified.

@kitlangton kitlangton closed this Sep 1, 2026
@kitlangton kitlangton changed the title fix(ai): isolate response tool call identities fix(ai): reconcile final response calls by call id Sep 1, 2026
@kitlangton kitlangton reopened this Sep 1, 2026
@kitlangton
kitlangton merged commit 831f8f6 into v2 Sep 1, 2026
8 checks passed
@kitlangton
kitlangton deleted the responses-call-identity branch September 1, 2026 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant