diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index c940b31c8c9..b999854c934 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -389,6 +389,14 @@ export function topK(model: Provider.Model) { const WIDELY_SUPPORTED_EFFORTS = ["low", "medium", "high"] const OPENAI_EFFORTS = ["none", "minimal", ...WIDELY_SUPPORTED_EFFORTS, "xhigh"] +// Returns safe budgetTokens for Anthropic's 'high' thinking variant, or undefined +// when the output limit is unknown (0) or the result would be below Anthropic's +// minimum of 1024. Both callers (variants() and kimi-k2.5) share this formula. +function highBudget(output: number): number | undefined { + const tokens = Math.floor(output / 2 - 1) + return tokens >= 1024 ? Math.min(16_000, tokens) : undefined +} + export function variants(model: Provider.Model): Record> { if (!model.capabilities.reasoning) return {} @@ -592,11 +600,14 @@ export function variants(model: Provider.Model): Record { const result = ProviderTransform.variants(model) expect(result).toEqual({}) }) + + test("returns empty object when limit.output is 0 (unknown)", () => { + const model = createMockModel({ + id: "anthropic/claude-4", + providerID: "anthropic", + api: { + id: "claude-4", + url: "https://api.anthropic.com", + npm: "@ai-sdk/anthropic", + }, + limit: { context: 200_000, output: 0 }, + }) + const result = ProviderTransform.variants(model) + expect(result).toEqual({}) + }) + + test("returns empty object when limit.output is too small for valid budgetTokens", () => { + const model = createMockModel({ + id: "anthropic/claude-4", + providerID: "anthropic", + api: { + id: "claude-4", + url: "https://api.anthropic.com", + npm: "@ai-sdk/anthropic", + }, + limit: { context: 200_000, output: 2049 }, + }) + const result = ProviderTransform.variants(model) + expect(result).toEqual({}) + }) }) })