fix: preserve Responses tool call correlation IDs - #936
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
🚧 Files skipped from review as they are similar to previous changes (8)
📝 WalkthroughWalkthroughThe Responses adapters now preserve output item IDs separately from function call IDs, use canonical call IDs for tool events, and replay both identifiers in later server-tool requests. Tests, exports, release metadata, and E2E provider support are updated. ChangesResponses tool-call identity
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ResponsesStream
participant ResponsesTextAdapter
participant ServerTool
participant NextResponsesRequest
ResponsesStream->>ResponsesTextAdapter: Emit function call with item ID and call ID
ResponsesTextAdapter->>ServerTool: Emit tool events correlated by call ID
ServerTool->>ResponsesTextAdapter: Return tool result
ResponsesTextAdapter->>NextResponsesRequest: Replay function call item ID and output call ID
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ai-openrouter/src/adapters/responses-text.ts`:
- Around line 1161-1168: Update the output_item.added backfill around
toolCallMetadata and the output_item.done backfill in
packages/ai-openrouter/src/adapters/responses-text.ts#L1161-L1168 and
`#L1281-L1288`: initialize metadata.name with an empty-string fallback when
item.name is missing, and only update an existing name when both metadata.name
is absent and item.name is truthy. Preserve valid names and satisfy the
StreamedFunctionCallMetadata string contract at both sites.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b38e706c-aabd-4520-9ef4-c475e9ce27a9
📒 Files selected for processing (9)
.changeset/fuzzy-pandas-call.mdpackages/ai-openrouter/src/adapters/responses-text.tspackages/ai-openrouter/src/index.tspackages/ai-openrouter/src/message-types.tspackages/ai-openrouter/tests/openrouter-responses-adapter.test.tspackages/openai-base/src/adapters/responses-text.tspackages/openai-base/src/index.tspackages/openai-base/tests/responses-text.test.tstesting/e2e/src/lib/feature-support.ts
The mock-based E2E suite cannot catch this class of bug. aimock maps an incoming `function_call.call_id` straight onto `tool_calls[].id`, so a request that uses the WRONG id consistently in both the `function_call` and its `function_call_output` still correlates and still passes. I confirmed this by running the new `openrouter-responses -- tool-calling` matrix entry against the pre-fix adapter source: it passes. Only a provider that knows the real item -> call_id mapping rejects the old shape. So the regression net has to be a unit test. `openai-base` had none for the full round trip: its request-mapping test hand-builds the assistant message including `metadata.itemId`, which assumes the very propagation that can break. Add a two-turn test that drives the real `chat()` agent loop with a server tool and asserts the second request carries both identifiers. This covers every adapter inheriting the base -- ai-openai, ai-grok, ai-bedrock, and the OpenAI-compatible adapter -- none of which override convertMessagesToInput. Verified it fails against the pre-fix source (`call_id: fc_item_1`, no `id`). Also stop labelling the output item id as `toolCallId` in the diagnostic log payloads of both Responses adapters. Now that the two identifiers differ, those fields reported the item id under the tool-call name. Each site logs `itemId`, plus `toolCallId: metadata.callId` where the metadata is in scope.
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
View your CI Pipeline Execution ↗ for commit 129aef0
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
Summary
call_idas the canonical tool-call correlation IDidas provider metadataRoot cause
Responses function calls carry two opaque identifiers with different roles: output-item
idis referenced by streamed argument events, whilecall_idpairs the call with itsfunction_call_output. The adapters keyed stream state by the output-item ID and also exposed that value as the tool-call ID, which discarded the actual correlation ID.When the provider returned different values, the agent loop sent the output-item ID as
function_call_output.call_id. The follow-up request could no longer correlate the tool result with the original call.Tests
add a two-turn OpenRouter server-tool regression test with deliberately distinct item and call IDs
verify the follow-up request preserves both IDs before and after SDK serialization
update OpenAI Responses coverage to assert
call_idcorrelation and output-item metadatainclude OpenRouter Responses in the tool-calling E2E matrix
pnpm test:prtargeted Playwright
openrouter-responses — tool-callingscenario (1 passed)Summary by CodeRabbit
Bug Fixes
Tests