fix(core): keep reasoning provider metadata on errored turns for valid Anthropic replay - #44054
fix(core): keep reasoning provider metadata on errored turns for valid Anthropic replay#44054BigBrown10 wants to merge 1 commit into
Conversation
…d Anthropic replay (anomalyco#38620)
— automated review (ox-alpha, round2) |
|
Thanks for the automated review. Items 1 and 3 are based on a misreading of the diff, item 2 is already covered, and I'm declining the nit to keep the diff minimal. Items 1 & 3 (sameModel gate "disappeared"): The if (item.type === "reasoning")
return sameModel
? [{ type: "reasoning", text: item.text, providerMetadata: item.providerMetadata }]
: item.text.length > 0
? [{ type: "text", text: item.text }]
: []On a model-switch/fallback retry ( Item 2 (model-switch coverage): Already pinned by the existing test Item 4 (helper nit): Declining for now; it touches three call sites to save one expression each in a PR that's intentionally minimal while competing with several open approaches. |
Issue for this PR
Closes #38620
Type of change
What does this PR do?
Replaying an errored assistant turn dropped reasoning
providerMetadatawhile still replaying that turn's tool_use parts. With extended thinking enabled, Anthropic requires every tool_use block to be preceded by its signed/redacted thinking block, so any interrupt mid-step poisoned the rest of the session: the next request replayed orphaned tool_use without its thinking block and got a 400.The fix splits the guard in
to-llm-message.ts. Reasoning continuation metadata is now reused whenever the message stays on the same model (sameModel), regardless ofmessage.error, because both the signature and redactedData Anthropic needs live in that one field. Tool execution metadata still requiresmessage.error === undefined, since metadata from failed executions should not be trusted. That restores the thinking-before-tool_use invariant without changing what gets replayed.The existing test "drops provider-native continuation metadata from failed assistant turns" pinned the broken shape, so I renamed it and updated its expectation deliberately (the issue notes the old guard was itself deliberate).
How did you verify your code works?
packages/core/test/session-runner-message.test.ts: same-model failed turns keep openai metadata; anthropic signature preserved on a failed turn; redactedData preserved on a failed turn; cross-model stripping still drops metadata.bun testin packages/core: 8/8 pass in session-runner-message.test.ts; full package suite is 1083 pass / 7 fail, and those 7 (npm-config, modelsdev, cross-spawn) also fail on a clean dev checkout, so they are unrelated environment failures.tsgo --noEmitpasses.Screenshots / recordings
Not a UI change.
Checklist