fix(core): migrate the v1 thinking block-binding opt-out (#52327)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
This commit is contained in:
Dmitrii
2026-10-06 00:06:58 -05:00
committed by GitHub
Unverified
parent 2bddf58716
commit cabb5d035b
4 changed files with 72 additions and 2 deletions
@@ -1477,6 +1477,7 @@ export type ModelCompatibility = {
requireFinishReason?: boolean
requireAssistantAfterTool?: boolean
supportsPromptCacheKey?: boolean
supportsThinkingBlockBinding?: boolean
}
export type ModelCost = {
+23 -2
View File
@@ -168,7 +168,26 @@ export function providerID(input: string) {
}
function migrateModel(info: typeof ConfigProviderV1.Model.Type) {
const settings = info.options && ConfigProviderOptionsV1.model(info.options)
const disableThinkingBlockBinding =
info.options?.thinking?.blockBinding === false || info.options?.reasoningConfig?.blockBinding === false
const options = info.options && { ...info.options }
// Move the legacy opt-out to compatibility without mutating the input.
if (options && disableThinkingBlockBinding) {
for (const key of ["thinking", "reasoningConfig"]) {
if (options[key]?.blockBinding !== false) continue
const { blockBinding, ...rest } = options[key]
if (Object.keys(rest).length) {
options[key] = rest
continue
}
delete options[key]
}
}
const settings = options && ConfigProviderOptionsV1.model(options)
const compatibility = Model.compatibility(info.interleaved)
const costs = info.cost && [
{
input: info.cost.input,
@@ -199,7 +218,9 @@ function migrateModel(info: typeof ConfigProviderV1.Model.Type) {
modelID: info.id,
family: info.family,
name: info.name,
compatibility: Model.compatibility(info.interleaved),
compatibility: disableThinkingBlockBinding
? { ...compatibility, supportsThinkingBlockBinding: false }
: compatibility,
package: info.provider?.npm ? Provider.aisdk(info.provider.npm) : undefined,
settings: info.provider?.api ? { ...settings, baseURL: info.provider.api } : settings,
capabilities,
@@ -508,6 +508,53 @@ describe("ConfigNormalize", () => {
])
})
test("migrates the legacy thinking block-binding opt-out into model compatibility", () => {
const result = normalized({
provider: {
gateway: {
models: {
anthropic: { options: { thinking: { type: "adaptive", blockBinding: false }, effort: "high" } },
bedrock: { options: { reasoningConfig: { blockBinding: false } } },
both: {
options: {
thinking: { type: "adaptive", blockBinding: false },
reasoningConfig: { type: "adaptive", blockBinding: false },
},
},
untouched: { options: { thinking: { type: "adaptive" } } },
},
},
},
})
expect(result.encoded.providers).toMatchObject({
gateway: {
models: {
anthropic: {
compatibility: { supportsThinkingBlockBinding: false },
settings: { thinking: { type: "adaptive" }, effort: "high" },
},
bedrock: { compatibility: { supportsThinkingBlockBinding: false }, settings: {} },
both: {
compatibility: { supportsThinkingBlockBinding: false },
settings: { thinking: { type: "adaptive" }, reasoningConfig: { type: "adaptive" } },
},
untouched: { settings: { thinking: { type: "adaptive" } } },
},
},
})
expect(result.encoded.providers).not.toHaveProperty(["gateway", "models", "bedrock", "settings", "reasoningConfig"])
expect(result.encoded.providers).not.toHaveProperty(["gateway", "models", "both", "settings", "thinking", "blockBinding"])
expect(result.encoded.providers).not.toHaveProperty([
"gateway",
"models",
"both",
"settings",
"reasoningConfig",
"blockBinding",
])
expect(result.encoded.providers).not.toHaveProperty(["gateway", "models", "untouched", "compatibility"])
})
test("invalid legacy provider overlays skip only that provider", () => {
const result = normalized({
provider: {
+1
View File
@@ -80,6 +80,7 @@ export const Compatibility = Schema.Struct({
requireFinishReason: Schema.Boolean.pipe(optional),
requireAssistantAfterTool: Schema.Boolean.pipe(optional),
supportsPromptCacheKey: Schema.Boolean.pipe(optional),
supportsThinkingBlockBinding: Schema.Boolean.pipe(optional),
}).annotate({ identifier: "Model.Compatibility" })
export interface Capabilities extends Schema.Schema.Type<typeof Capabilities> {}