Repository navigation
fix: preserve reasoning.server_tool_call reasoning details - #606
Open
LukasParke wants to merge 2 commits into
Open
LukasParke wants to merge 2 commits into
LukasParke wants to merge 2 commits into
Conversation
OpenRouter emits reasoning.server_tool_call entries in reasoning_details to record server-tool invocations (e.g. openrouter:fusion) so they can be rehydrated on later turns. The SDK schema did not know the type, so these entries were dropped at parse time and never replayed. Add the type to the reasoning detail schemas, dedupe it by tool_call_id (or tool_name:arguments) like the backend, and pass it through streaming accumulation without merging. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#600 adds an empty reasoning part that carries encrypted-only or text-less reasoning details, so the non-streaming content is no longer exactly [text]. Assert the text part is present, any reasoning part is empty, and the server_tool_call detail is reachable from part or response providerMetadata, so the test passes before and after #600. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4 of 5 tasks
LukasParke
added a commit
that referenced
this pull request
Oct 23, 2026
Resolve the tracker conflict so server_tool_call keys get the same type prefix as the backend, and add a test that a server_tool_call and an encrypted detail sharing an id are both kept. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
OpenRouter returns a fourth reasoning detail type,
reasoning.server_tool_call. It records a completed OpenRouter server-tool call (e.g.openrouter:fusion,openrouter:tool_search) so the call can be rehydrated on a later turn. The SDK's reasoning detail union only knewsummary,encryptedandtext, so the unknown-type fallback silently dropped these entries at parse time. They never reachedproviderMetadataand were never sent back, which breaks server-tool continuity across turns.Backend shape (OpenRouterTeam/openrouter-web)
packages/llm-interfaces/schemas/response/reasoning-schemas/index.ts:ReasoningDetailType.ServerToolCall = 'reasoning.server_tool_call'withtool_name: string,tool_call_id?: string | null,arguments: string,result: string, plus the commonid/format/indexfields. It is part ofReasoningDetailUnionSchema.packages/llm-interfaces/reasonings/duplicate-tracker.ts: dedupes it bytool_call_id, falling back to${tool_name}:${arguments}.packages/router/skins/openai-chat-completions/from-internal-stream/handlers.ts(buildRoundTripReasoningDetail/handleGenerationServerToolCall) emits it indelta.reasoning_detailsas a discrete, non-mergeable entry. It is built bypackages/router/plugins/server-tools/server-tool-reasoning-detail.ts.packages/router/plugins/normalize-request/reconstruct-server-tool-messages-openai.tsrehydrates echoedreasoning.server_tool_calldetails into assistanttool_callsandtoolmessages./openapi.json) includesReasoningDetailServerToolCall. The reasoning-tokens guide doesn't mention it yet.Changes
src/schemas/reasoning-details.ts: addedReasoningDetailType.ServerToolCallandReasoningDetailServerToolCallSchemato the union. The response, stream delta and providerOptions schemas all build on it, so all three now accept the type.src/utils/reasoning-details-duplicate-tracker.ts: uses the same canonical key as the backend.src/chat/index.ts: handles the new type in the exhaustive switches. It produces no visible reasoning part or delta, and streaming pushes it as a discrete entry, never merged with text or summary.Tests (all fail on
origin/main, pass here)src/chat/server-tool-call-reasoning.test.ts: parse (doGenerate), stream accumulation (doStreamfinish metadata keeps text merged and the server tool call separate), and astreamTexttwo-turn round trip that checks the second request'sreasoning_details.src/utils/reasoning-details-duplicate-tracker.test.ts: dedup bytool_call_idand bytool_name:arguments.Overlap with #593
#593 changes
src/schemas/format.ts. This PR doesn't touch that file.formatstays optional on the new schema, which matches the backend (server-tool details are emitted without aformat).Checklist
pnpm stylecheckandpnpm typecheckpnpm testand all tests passChangeset
pnpm changesetto create a changeset file🤖 Generated with Claude Code