Skip to content

feat(opencode): tolerate Anthropic thinking block binding - #46653

Merged
rekram1-node merged 6 commits into
devfrom
thinking-block-binding
Sep 1, 2026
Merged

feat(opencode): tolerate Anthropic thinking block binding#46653
rekram1-node merged 6 commits into
devfrom
thinking-block-binding

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

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 sets thinking.block_binding.prefix_mismatch_behavior: "drop_block" under the thinking-binding-controls-2026-08-01 beta. 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_block everywhere 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:

  1. Pin @ai-sdk/anthropic to one version — bump to 3.0.111 and add a root override so the copy nested under @ai-sdk/google-vertex resolves to the same package. Needed so one patch covers direct Anthropic and Vertex Anthropic.
  2. Patch @ai-sdk/anthropic — no published version (3.0.115 / 4.0.46 checked) carries the field. Adds thinking.blockBinding.prefixMismatchBehavior to the provider options, emits block_binding in the body, adds the beta to the betas set, and surfaces input_transformations as providerMetadata.anthropic.inputTransformations. dist/internal is patched too since Vertex imports AnthropicMessagesLanguageModel from there.
  3. Patch @ai-sdk/amazon-bedrock — Converse rebuilds thinking from reasoningConfig and overwrites additionalModelRequestFields.thinking, so blockBinding is threaded through reasoningConfig and the beta through anthropic_beta.
  4. ProviderTransform.providerOptions — gated by SDK, not provider: @ai-sdk/anthropic, @ai-sdk/google-vertex/anthropic, @ai-sdk/amazon-bedrock, for claude model IDs. Adds blockBinding to existing adaptive/enabled thinking. Models that think without a thinking parameter (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.
  5. Log dropped blocksstep-finish warns with the input_transformations payload so we can see prefix churn in the wild.

Notes

  • drop_block costs 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.
  • Anthropic confirms models that don't run the check accept the field, so one body works across all Claude models.
  • @ai-sdk/anthropic is also used for Claude via GitHub Copilot, OpenRouter-style proxies, and opencode Zen. Those transports need to forward thinking.block_binding and the beta header; a proxy that rejects unknown fields would 400. Not verified here.
  • Live verification against Anthropic / Vertex / Bedrock with "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, and inputTransformations for both Anthropic and Bedrock.

@rekram1-node
rekram1-node force-pushed the thinking-block-binding branch 2 times, most recently from 9eb9dce to 3c4eb62 Compare September 1, 2026 19:17
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
rekram1-node force-pushed the thinking-block-binding branch from 3c4eb62 to 9390da0 Compare September 1, 2026 19:25
@rekram1-node
rekram1-node merged commit 3f39a32 into dev Sep 1, 2026
7 of 9 checks passed
@rekram1-node
rekram1-node deleted the thinking-block-binding branch September 1, 2026 19:32
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant