fix: extend empty-text gate to Bedrock and Vertex signature namespaces#1
Open
omer-koren wants to merge 13 commits intoedevil:fix/preserve-thinking-block-signaturesfrom
Conversation
…ng blocks
Anthropic adaptive thinking (Opus 4.6+) emits empty text parts between
thinking blocks. Dropping them invalidates thinking block signatures
('thinking blocks cannot be modified'), but sending them as '' fails
validation ('text content blocks must be non-empty'). Substitute a
single space so the part survives all filters and Anthropic accepts it.
Gated on reasoning having an Anthropic signature (metadata.anthropic.
signature != null) so other providers' reasoning — which don't
position-validate — continue to have empty text filtered normally.
Closes anomalyco#16748
The hasSignedReasoning gate introduced in this PR only matches Anthropic's direct-API signature path (metadata.anthropic.signature). When Claude is hosted on AWS Bedrock or GCP Vertex AI, the reasoning part metadata stores the signature under metadata.bedrock.signature / metadata.vertex.signature respectively. The gate never fires for those providers, so empty text parts between signed reasoning blocks are not substituted with a space, and Anthropic/Bedrock/Vertex still reject the compacted message with: messages.N.content.M: 'thinking' or 'redacted_thinking' blocks in the latest assistant message cannot be modified Extend the check to match signatures under any of the three provider namespaces. Adds two tests covering the Bedrock and Vertex paths.
6 tasks
517afe4 to
876c79f
Compare
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.
Small follow-up to your PR that extends the
hasSignedReasoninggate to cover AWS Bedrock and GCP Vertex AI. Feel free to squash into your PR, take the ideas, or close — whichever is easiest for you.The bug
The gate currently only matches direct-Anthropic signatures:
When Claude is hosted on AWS Bedrock (
amazon-bedrock/anthropic.*) or GCP Vertex AI, the reasoning part's metadata stores the signature under a provider-scoped namespace:metadata.bedrock.signature— AWS Bedrockmetadata.vertex.signature— GCP Vertex AIThe AI SDK's Anthropic adapter keeps the namespace on the host that answered the call, so the gate never fires for Bedrock/Vertex users. The empty-text substitution is skipped, and on compaction/replay the message still trips Anthropic's:
Repro
On Bedrock Claude Opus 4.7 (
amazon-bedrock/anthropic.claude-opus-4-7), inspecting a reasoning part from the SQLite session DB:{ "type": "reasoning", "text": "...", "metadata": { "bedrock": { "signature": "Es4EClkIDRABGAIq..." } } }With only the
anthropicnamespace checked,hasSignedReasoningreturnsfalse→ empty text parts between signed reasoning blocks remain""→ Anthropic rejects on the next turn or manual compact.The fix
Extend the check to any of the three provider namespaces:
The "non-Anthropic providers' reasoning doesn't position-validate" rationale from your existing comment still holds — OpenAI Responses, Gemini thinking, Copilot
reasoningOpaquedon't write under these three keys, so they continue to have empty text filtered normally.Tests
Two new tests alongside your existing one, covering the Bedrock and Vertex paths. Same structure as
leaves empty text alone when reasoning has no Anthropic signature— just flipping the metadata namespace.bun test test/session/message-v2.test.ts)cannot be modifiederror on manual compact — the error no longer triggers after this changeVerification
The aws-sdk/client-bedrock-runtime adapter and google-cloud/vertexai both preserve the provider namespace on streamed response metadata rather than normalizing to
anthropic— so the extension is necessary, not redundant.Thanks for the original fix — saved us from a persistent production issue. Happy to adjust/squash/close as you prefer.