fix(provider): clamp reasoning budgets to output cap

This commit is contained in:
Aiden Cline 2026-07-01 11:11:33 -05:00
commit 60493ab948
2 changed files with 14 additions and 14 deletions

View file

@ -611,9 +611,9 @@ function reasoningOption<T extends ReasoningOption["type"]>(
function reasoningBudgetVariants(
budget: ReasoningBudgetOption,
make: (budgetTokens: number) => Record<string, any>,
output: number,
model: Provider.Model,
) {
const max = Math.max(1, Math.min(budget.max ?? 31_999, (output || OUTPUT_TOKEN_MAX) - 1))
const max = Math.max(1, Math.min(budget.max ?? 31_999, maxOutputTokens(model) - 1))
const min = Math.min(budget.min ?? 1, max)
return {
high: make(Math.max(min, Math.min(16_000, max))),
@ -758,35 +758,35 @@ function reasoningOptionVariants(model: Provider.Model): Record<string, Record<s
switch (model.api.npm) {
case "@openrouter/ai-sdk-provider":
return reasoningBudgetVariants(budget, (max_tokens) => ({ reasoning: { max_tokens } }), model.limit.output)
return reasoningBudgetVariants(budget, (max_tokens) => ({ reasoning: { max_tokens } }), model)
case "@ai-sdk/gateway":
if (idIncludes(model, "anthropic")) {
return reasoningBudgetVariants(
budget,
(budgetTokens) => ({ thinking: { type: "enabled", budgetTokens } }),
model.limit.output,
model,
)
}
if (idIncludes(model, "google")) {
return reasoningBudgetVariants(
budget,
(thinkingBudget) => ({ thinkingConfig: { includeThoughts: true, thinkingBudget } }),
model.limit.output,
model,
)
}
break
case "@ai-sdk/anthropic":
case "@ai-sdk/google-vertex/anthropic":
return reasoningBudgetVariants(budget, (budgetTokens) => ({ thinking: { type: "enabled", budgetTokens } }), model.limit.output)
return reasoningBudgetVariants(budget, (budgetTokens) => ({ thinking: { type: "enabled", budgetTokens } }), model)
case "@ai-sdk/amazon-bedrock":
if (model.api.id.includes("anthropic")) {
return reasoningBudgetVariants(
budget,
(budgetTokens) => ({ reasoningConfig: { type: "enabled", budgetTokens } }),
model.limit.output,
model,
)
}
break
@ -796,13 +796,13 @@ function reasoningOptionVariants(model: Provider.Model): Record<string, Record<s
return reasoningBudgetVariants(
budget,
(thinkingBudget) => ({ thinkingConfig: { includeThoughts: true, thinkingBudget } }),
model.limit.output,
model,
)
case "@jerome-benoit/sap-ai-provider-v2":
if (model.api.id.includes("anthropic")) {
return wrapInSapModelParams(
reasoningBudgetVariants(budget, (budget_tokens) => ({ thinking: { type: "enabled", budget_tokens } }), model.limit.output),
reasoningBudgetVariants(budget, (budget_tokens) => ({ thinking: { type: "enabled", budget_tokens } }), model),
)
}
break

View file

@ -3069,7 +3069,7 @@ describe("ProviderTransform.variants", () => {
)
expect(Object.keys(result)).toEqual(["high", "max"])
expect(result.high).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } })
expect(result.max).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 32768 } })
expect(result.max).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 31999 } })
})
test("reasoning_options ignore toggle-only models", () => {
@ -3304,7 +3304,7 @@ describe("ProviderTransform.variants", () => {
)
expect(result).toEqual({
high: { reasoning: { max_tokens: 16_000 } },
max: { reasoning: { max_tokens: 63_999 } },
max: { reasoning: { max_tokens: 31_999 } },
})
})
})
@ -3361,7 +3361,7 @@ describe("ProviderTransform.variants", () => {
)
expect(Object.keys(result)).toEqual(["high", "max"])
expect(result.high).toEqual({ thinking: { type: "enabled", budgetTokens: 16_000 } })
expect(result.max).toEqual({ thinking: { type: "enabled", budgetTokens: 32_768 } })
expect(result.max).toEqual({ thinking: { type: "enabled", budgetTokens: 31_999 } })
})
test("uses reasoning_options budget tokens for Google variants", () => {
@ -3379,7 +3379,7 @@ describe("ProviderTransform.variants", () => {
)
expect(Object.keys(result)).toEqual(["high", "max"])
expect(result.high).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 16_000 } })
expect(result.max).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 32_768 } })
expect(result.max).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 31_999 } })
})
test("uses reasoning_options effort for Google thinkingConfig variants", () => {
@ -3873,7 +3873,7 @@ describe("ProviderTransform.variants", () => {
apiId: "gemini-2.5-pro",
efforts: ["high", "max"],
expectedHigh: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16_000 } },
expectedMax: { thinkingConfig: { includeThoughts: true, thinkingBudget: 32_768 } },
expectedMax: { thinkingConfig: { includeThoughts: true, thinkingBudget: 31_999 } },
},
{
apiId: "gemini-2.5-flash",