feat(opencode): tolerate Anthropic thinking block binding - #46653
Merged
Conversation
rekram1-node
force-pushed
the
thinking-block-binding
branch
2 times, most recently
from
September 1, 2026 19:17
9eb9dce to
3c4eb62
Compare
Bump the direct dependency to 3.0.111 and add a root override so the copy nested under @ai-sdk/google-vertex resolves to the same package. A single resolved version is required so one patch covers both the direct Anthropic provider and the Vertex Anthropic provider.
Anthropic now binds thinking block signatures to the conversation prefix (system, tools, earlier messages) on Fable 5.1. A prefix mismatch rejects the request unless thinking.block_binding.prefix_mismatch_behavior is set to drop_block under the thinking-binding-controls-2026-08-01 beta. No published AI SDK version carries the field yet, so patch it in: - accept thinking.blockBinding.prefixMismatchBehavior on adaptive and enabled thinking provider options - emit thinking.block_binding.prefix_mismatch_behavior in the request body - add the thinking-binding-controls-2026-08-01 beta when it is set - parse input_transformations from the response / message_start event and expose it as providerMetadata.anthropic.inputTransformations The Vertex Anthropic provider reuses AnthropicMessagesLanguageModel from @ai-sdk/anthropic/internal, so the internal build is patched as well.
Bedrock Converse builds the Anthropic thinking object from reasoningConfig and overwrites anything placed in additionalModelRequestFields.thinking, so block_binding has to be threaded through the provider option: - accept reasoningConfig.blockBinding.prefixMismatchBehavior - emit thinking.block_binding.prefix_mismatch_behavior for both enabled and adaptive thinking on Anthropic models - add thinking-binding-controls-2026-08-01 to anthropic_beta when set
Ask Anthropic to drop invalidated thinking blocks instead of rejecting the request when the conversation prefix changed. Applied by SDK, not provider: @ai-sdk/anthropic, @ai-sdk/google-vertex/anthropic, and @ai-sdk/amazon-bedrock all get thinking.blockBinding / reasoningConfig.blockBinding for Claude models. Models that think without a thinking parameter (Opus 5, Sonnet 5, Fable 5.x, Mythos 5.x) get an explicit adaptive thinking object when no variant is selected, since the field has to live on the thinking config. Models where thinking is off by default are left untouched so behaviour does not change.
The patched Anthropic SDK exposes input_transformations on the step providerMetadata. Warn with the session, message, model, and the dropped paths so prefix churn that invalidates thinking can be traced.
Goes through the real createVertexAnthropic provider with an injected auth token and asserts the same transformation Anthropic's own Vertex SDK applies: rawPredict URL, model removed from the body, anthropic_version added, and betas carried in the anthropic-beta header.
rekram1-node
force-pushed
the
thinking-block-binding
branch
from
September 1, 2026 19:25
3c4eb62 to
9390da0
Compare
6 tasks
filipeforattini
added a commit
to reddb-io/redcode
that referenced
this pull request
Sep 5, 2026
…46653) Ported from anomalyco/opencode 3f39a32. Fable 5.1 binds each thinking signature to the system prompt, tool list and messages above it, and rejects the request when any of that changes; we re-render parts of that prefix between turns. The request now asks the API to drop the affected blocks instead of failing, via a patched @ai-sdk/anthropic 3.0.111 and @ai-sdk/amazon-bedrock 4.0.166 that carry the thinking-binding-controls beta, and the processor logs the blocks Anthropic reports dropping. Port notes: the two @ai-sdk versions were bumped here (upstream bumped Bedrock in an earlier commit we had not taken), the lockfile was regenerated rather than patched, and the nested copy under @ai-sdk/google-vertex needed a relink for the override to reach it — the vertex wire test is what showed that. Upstream: 3f39a32
filipeforattini
added a commit
to reddb-io/redcode
that referenced
this pull request
Sep 5, 2026
…46653) Ported from anomalyco/opencode 3f39a32. Fable 5.1 binds each thinking signature to the system prompt, tool list and messages above it, and rejects the request when any of that changes; we re-render parts of that prefix between turns. The request now asks the API to drop the affected blocks instead of failing, via a patched @ai-sdk/anthropic 3.0.111 and @ai-sdk/amazon-bedrock 4.0.166 that carry the thinking-binding-controls beta, and the processor logs the blocks Anthropic reports dropping. Port notes: the two @ai-sdk versions were bumped here (upstream bumped Bedrock in an earlier commit we had not taken), the lockfile was regenerated rather than patched, and the nested copy under @ai-sdk/google-vertex needed a relink for the override to reach it — the vertex wire test is what showed that. Upstream: 3f39a32
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.
Why
Anthropic now binds each thinking block signature to the conversation prefix (top-level
system,tools, and every earlier message). On Claude Fable 5.1, replaying a block behind a changed prefix returns a 400 unless the request setsthinking.block_binding.prefix_mismatch_behavior: "drop_block"under thethinking-binding-controls-2026-08-01beta. Enforcement is on for API accounts created after 2026-08-31 and will expand to everyone on later models.opencode re-renders parts of the prefix between turns (system prompt, tool list, compaction), so without this our users on new accounts get hard failures. This PR is the cheap fix: opt into
drop_blockeverywhere we talk to Claude. Making the prefix stable is separate follow-up work.Docs: https://platform.claude.com/docs/en/build-with-claude/preserved-thinking
What
Each commit stands alone:
@ai-sdk/anthropicto one version — bump to 3.0.111 and add a root override so the copy nested under@ai-sdk/google-vertexresolves to the same package. Needed so one patch covers direct Anthropic and Vertex Anthropic.@ai-sdk/anthropic— no published version (3.0.115 / 4.0.46 checked) carries the field. Addsthinking.blockBinding.prefixMismatchBehaviorto the provider options, emitsblock_bindingin the body, adds the beta to thebetasset, and surfacesinput_transformationsasproviderMetadata.anthropic.inputTransformations.dist/internalis patched too since Vertex importsAnthropicMessagesLanguageModelfrom there.@ai-sdk/amazon-bedrock— Converse rebuildsthinkingfromreasoningConfigand overwritesadditionalModelRequestFields.thinking, soblockBindingis threaded throughreasoningConfigand the beta throughanthropic_beta.ProviderTransform.providerOptions— gated by SDK, not provider:@ai-sdk/anthropic,@ai-sdk/google-vertex/anthropic,@ai-sdk/amazon-bedrock, forclaudemodel IDs. AddsblockBindingto existingadaptive/enabledthinking. Models that think without athinkingparameter (Opus 5, Sonnet 5, Fable 5.x, Mythos 5.x) get an explicit{ type: "adaptive" }when no variant is selected so there is somewhere to put the field; models that are off by default are untouched.step-finishwarns with theinput_transformationspayload so we can see prefix churn in the wild.Notes
drop_blockcosts nothing when the prefix is intact. When it isn't, the API strips the affected blocks (and every later one), unbilled, and the model reasons afresh. Same outcome as stripping thinking client-side, but the API decides exactly which blocks.@ai-sdk/anthropicis also used for Claude via GitHub Copilot, OpenRouter-style proxies, and opencode Zen. Those transports need to forwardthinking.block_bindingand the beta header; a proxy that rejects unknown fields would 400. Not verified here."error"then"drop_block"is still to do.Tests
test/provider/transform.test.ts: unit coverage for the transform gating, plus wire-level tests through the patched SDKs asserting the body, header, andinputTransformationsfor both Anthropic and Bedrock.