Repository navigation
fix(schema): expose effort-update and thinking-binding overrides on model compatibility - #52172
Merged
Merged
Conversation
…odel compatibility Config-level `model.compatibility` decoded through `Model.Compatibility`, which declared neither `supportsEffortUpdates` nor `supportsThinkingBlockBinding`. The config decoder ignores excess properties, so both keys were silently dropped before `config/plugin/provider.ts` merged the object onto the model, leaving the runtime gates in `packages/ai` unreachable from configuration. Declare both optional booleans on the schema (the runtime already reads them) and regenerate the client surface.
Contributor
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Contributor
|
The following comment was made by an LLM, it may be inaccurate: |
This was referenced Sep 30, 2026
3 of 6 tasks
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.
Issue for this PR
Closes #51146
Type of change
What does this PR do?
Issue #51146 reports that a Bedrock-routed Anthropic model rejects every request after an
effort update, because message-level
output_configis accepted by first-partyapi.anthropic.combut not by Bedrock.The protocol layer already knows how to avoid this.
packages/ai/src/protocols/anthropic-messages.tsgates message-level effort updates behind
supportsEffortUpdates(model), and that function's firstbranch is a compatibility override:
packages/ai/src/protocols/utils/claude-model.tshas the same escape hatch for Anthropic'sthinking-binding controls. So the runtime switch exists — it is just unreachable from configuration.
That is the bug this PR fixes. A user configures the model like this:
{ "providers": { "my-bedrock-gateway": { "models": { "global.anthropic.claude-opus-5-5": { "compatibility": { "supportsEffortUpdates": false } } } } } }The config is decoded as
Config.Provider.Info, whose modelcompatibilityfield isModel.Compatibility(packages/schema/src/model.ts). That struct declared neithersupportsEffortUpdatesnorsupportsThinkingBlockBinding, and the config decoder runs withonExcessProperty: "ignore"(packages/core/src/config.ts). The key was therefore dropped duringdecoding, before
packages/core/src/config/plugin/provider.tsmergedcompatibilityonto the model.By the time
supportsEffortUpdatesreadmodel.compatibility, the user's value was gone, so themodel-ID heuristic in
claudeVersion()decided instead — and for a gateway that reuses the Anthropicprotocol against a non-Anthropic backend, that heuristic is wrong.
A provider-level gate would not have fixed the report either: a Bedrock gateway is a
provider: "anthropic"entry with a custombaseURL, so the decision has to stay per-model.The change is two optional booleans on
Model.Compatibility, matching the docs already written onthe AI-side
LanguageModelCompatibility, plus the regenerated client surface (ModelCompatibilityis emitted into
components.schemas). Once the fields are declared, the existing runtime override isreachable from configuration and no change is needed in
packages/ai.How did you verify your code works?
packages/schema/test/model.test.ts— added a decode test asserting both new keys surviveSchema.decodeUnknownSync(Model.Compatibility).packages/core/test/config/provider.test.ts— extended the existing"loads configured providers and applies later model overrides" case so the two flags are present
in the config document, and asserted they reach the resolved model's
compatibility. This runs thereal config decode plus the real plugin merge, so it fails before this change and passes after it.
compatibilityobject containing an undeclared key (bogusFlag)together with
supportsEffortUpdatesyields only{ supportsEffortUpdates: true }. That confirmsthe decoder strips undeclared keys, which is why the fields had to be declared rather than passed
through.
bun test --timeout 30000onpackages/schema/test/model.test.ts,packages/core/test/config/provider.test.ts,packages/core/test/models.test.ts,packages/core/test/model-resolver.test.tsandpackages/ai/test/effort-updates.test.ts— allpass (
effort-updates.test.tsalready covers the gate honoring the override in both directions).tsgo --noEmitclean forpackages/schema,packages/clientandpackages/ai;oxlintreports0 warnings / 0 errors on the changed files.
bun run generatefrompackages/client— the generatedModelCompatibilitynow carries bothfields.
Screenshots / recordings
If this is a UI change, please include a screenshot or recording.
Checklist
If you do not follow this template your PR will be automatically rejected.