Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/client/src/promise/generated/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,7 @@ export type ModelCompatibility = {
requireFinishReason?: boolean
requireAssistantAfterTool?: boolean
supportsPromptCacheKey?: boolean
supportsThinkingBlockBinding?: boolean
}

export type ModelCost = {
Expand Down
19 changes: 17 additions & 2 deletions packages/core/src/v1/config/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,20 @@ export function providerID(input: string) {
}

function migrateModel(info: typeof ConfigProviderV1.Model.Type) {
const settings = info.options && ConfigProviderOptionsV1.model(info.options)
// V1 opted out of Anthropic thinking block binding with `blockBinding: false` in the model's provider options.
// V2 reads that decision from compatibility, so move it there instead of forwarding an option nothing consumes.
const optOut = (["thinking", "reasoningConfig"] as const).find((key) => info.options?.[key]?.blockBinding === false)
const options =
optOut && info.options
? Object.fromEntries(
Object.entries(info.options).flatMap(([key, value]) => {
if (key !== optOut) return [[key, value]]
Comment thread
Copilot marked this conversation as resolved.
Outdated
const { blockBinding, ...rest } = value
return Object.keys(rest).length ? [[key, rest]] : []
}),
)
: info.options
const settings = options && ConfigProviderOptionsV1.model(options)
const costs = info.cost && [
{
input: info.cost.input,
Expand Down Expand Up @@ -333,7 +346,9 @@ function migrateModel(info: typeof ConfigProviderV1.Model.Type) {
modelID: info.id,
family: info.family,
name: info.name,
compatibility: Model.compatibility(info.interleaved),
compatibility: optOut
? { ...Model.compatibility(info.interleaved), supportsThinkingBlockBinding: false }
: Model.compatibility(info.interleaved),
package: info.provider?.npm ? Provider.aisdk(info.provider.npm) : undefined,
settings: info.provider?.api ? { ...settings, baseURL: info.provider.api } : settings,
capabilities,
Expand Down
28 changes: 28 additions & 0 deletions packages/core/test/config/normalization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,34 @@ 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 } } },
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: {} },
untouched: { settings: { thinking: { type: "adaptive" } } },
},
},
})
expect(result.encoded.providers).not.toHaveProperty(["gateway", "models", "bedrock", "settings", "reasoningConfig"])
expect(result.encoded.providers).not.toHaveProperty(["gateway", "models", "untouched", "compatibility"])
})

test("invalid legacy provider overlays skip only that provider", () => {
const result = normalized({
provider: {
Expand Down
1 change: 1 addition & 0 deletions packages/schema/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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> {}
Expand Down
Loading