fix: preserve thinking block signatures and fix compaction headroom asymmetry#14393
fix: preserve thinking block signatures and fix compaction headroom asymmetry#14393gnadaban wants to merge 1 commit intoanomalyco:devfrom
Conversation
|
The following comment was made by an LLM, it may be inaccurate: Potential Related PRs Found:
These PRs address similar domains (thinking block signatures and compaction behavior), though they may be addressing different specific bugs or prior versions of the same issues. |
|
Re: related PRs flagged by bot Checked all three:
|
9f7c64f to
fd795c0
Compare
…symmetry Two compounding bugs caused sessions to crash with 'thinking blocks cannot be modified' when compaction fired for models with extended thinking: 1. toModelMessages() stripped providerMetadata (including cryptographic signatures) from message parts when the current model differed from the original. Anthropic's API requires signatures to be byte-identical. Fix: always pass providerMetadata through — the API handles filtering. 2. isOverflow() used an asymmetric buffer when limit.input was set (capped at 20K via COMPACTION_BUFFER) vs the full maxOutputTokens on the non-input path. This caused compaction to trigger too late. Fix: use maxOutputTokens (capped at 32K) for both paths. Also fixed the non-input path to respect config.compaction.reserved.
fd795c0 to
c045a8f
Compare
…rategy UI Root cause fix (from PR anomalyco#14393): - Always pass providerMetadata for reasoning parts (removed differentModel guard) - Always pass callProviderMetadata for tool parts - Fix asymmetric compaction buffer (use maxOutputTokens consistently) Configurable thinking strategy (none/strip/compact): - Settings > General: Thinking Strategy dropdown - Context tab: Always-visible strategy selector - Error card: Retry buttons for thinking block errors - Processor: Auto-compact on thinking error with compact strategy Default 'none' preserves original behavior.
Issue for this PR
Closes #13286
Related: #10634, #8089, #12621, #8185
Type of change
What does this PR do?
Two compounding bugs cause sessions to crash with
'thinking' or 'redacted_thinking' blocks in the latest assistant message cannot be modifiedwhen compaction fires for models with extended thinking enabled (e.g. Claude Opus on Bedrock).Bug 1 — Thinking block signature stripping (
message-v2.ts)toModelMessages()compares the current model against each historical message's original model via adifferentModelguard. When they differ — which always happens during compaction since it uses its own model — allproviderMetadatais stripped from message parts. This removes the cryptographicsignaturethat Anthropic requires on thinking blocks, causing the API to reject the messages.The fix removes the
differentModelguard entirely and always passesproviderMetadata/callProviderMetadatathrough. This is safe because:{ anthropic: { signature: "..." } }), so other providers ignore unknown keyspart.metadataisundefined, and the Vercel AI SDK'sconvertToModelMessagesalready null-checks before settingproviderOptions(except reasoning parts, where it's a no-op)Bug 2 — Compaction headroom asymmetry (
compaction.ts)isOverflow()had an asymmetric buffer calculation:limit.input:reserved = Math.min(20_000, maxOutputTokens)→ only 20K headroomlimit.input:reserved = maxOutputTokens→ full 32K headroomThis meant models with
limit.inputcould grow ~12K tokens larger before compaction triggered, making context overflow more likely.The fix removes the 20K cap and uses
maxOutputTokens()(itself capped at 32K viaOUTPUT_TOKEN_MAX) for both paths. Also fixed the non-input path to respectconfig.compaction.reserved— previously it hardcodedmaxOutputTokens(), ignoring the user's configured override from #12924.How did you verify your code works?
BUG:in the test file) now pass with correct expectationsScreenshots / recordings
N/A — not a UI change.
Checklist