Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 0c51feb

Browse files
authored
fix: max tokens when using models like opus with providers other than anthropic (anomalyco#4307)
1 parent d0b4169 commit 0c51feb

3 files changed

Lines changed: 101 additions & 3 deletions

File tree

packages/opencode/src/provider/transform.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,15 @@ export namespace ProviderTransform {
176176
}
177177

178178
export function maxOutputTokens(
179-
providerID: string,
179+
npm: string,
180180
options: Record<string, any>,
181181
modelLimit: number,
182182
globalLimit: number,
183183
): number {
184184
const modelCap = modelLimit || globalLimit
185185
const standardLimit = Math.min(modelCap, globalLimit)
186186

187-
if (providerID === "anthropic") {
187+
if (npm === "@ai-sdk/anthropic") {
188188
const thinking = options?.["thinking"]
189189
const budgetTokens = typeof thinking?.["budgetTokens"] === "number" ? thinking["budgetTokens"] : 0
190190
const enabled = thinking?.["type"] === "enabled"

packages/opencode/src/session/prompt.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ export namespace SessionPrompt {
345345
maxRetries: 0,
346346
activeTools: Object.keys(tools).filter((x) => x !== "invalid"),
347347
maxOutputTokens: ProviderTransform.maxOutputTokens(
348-
model.providerID,
348+
model.npm ?? "",
349349
params.options,
350350
model.info.limit.output,
351351
OUTPUT_TOKEN_MAX,
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { describe, expect, test } from "bun:test"
2+
import { ProviderTransform } from "../../src/provider/transform"
3+
4+
const OUTPUT_TOKEN_MAX = 32000
5+
6+
describe("ProviderTransform.maxOutputTokens", () => {
7+
test("returns 32k when modelLimit > 32k", () => {
8+
const modelLimit = 100000
9+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/openai", {}, modelLimit, OUTPUT_TOKEN_MAX)
10+
expect(result).toBe(OUTPUT_TOKEN_MAX)
11+
})
12+
13+
test("returns modelLimit when modelLimit < 32k", () => {
14+
const modelLimit = 16000
15+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/openai", {}, modelLimit, OUTPUT_TOKEN_MAX)
16+
expect(result).toBe(16000)
17+
})
18+
19+
describe("azure", () => {
20+
test("returns 32k when modelLimit > 32k", () => {
21+
const modelLimit = 100000
22+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/azure", {}, modelLimit, OUTPUT_TOKEN_MAX)
23+
expect(result).toBe(OUTPUT_TOKEN_MAX)
24+
})
25+
26+
test("returns modelLimit when modelLimit < 32k", () => {
27+
const modelLimit = 16000
28+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/azure", {}, modelLimit, OUTPUT_TOKEN_MAX)
29+
expect(result).toBe(16000)
30+
})
31+
})
32+
33+
describe("bedrock", () => {
34+
test("returns 32k when modelLimit > 32k", () => {
35+
const modelLimit = 100000
36+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/amazon-bedrock", {}, modelLimit, OUTPUT_TOKEN_MAX)
37+
expect(result).toBe(OUTPUT_TOKEN_MAX)
38+
})
39+
40+
test("returns modelLimit when modelLimit < 32k", () => {
41+
const modelLimit = 16000
42+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/amazon-bedrock", {}, modelLimit, OUTPUT_TOKEN_MAX)
43+
expect(result).toBe(16000)
44+
})
45+
})
46+
47+
describe("anthropic without thinking options", () => {
48+
test("returns 32k when modelLimit > 32k", () => {
49+
const modelLimit = 100000
50+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/anthropic", {}, modelLimit, OUTPUT_TOKEN_MAX)
51+
expect(result).toBe(OUTPUT_TOKEN_MAX)
52+
})
53+
54+
test("returns modelLimit when modelLimit < 32k", () => {
55+
const modelLimit = 16000
56+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/anthropic", {}, modelLimit, OUTPUT_TOKEN_MAX)
57+
expect(result).toBe(16000)
58+
})
59+
})
60+
61+
describe("anthropic with thinking options", () => {
62+
test("returns 32k when budgetTokens + 32k <= modelLimit", () => {
63+
const modelLimit = 100000
64+
const options = {
65+
thinking: {
66+
type: "enabled",
67+
budgetTokens: 10000,
68+
},
69+
}
70+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/anthropic", options, modelLimit, OUTPUT_TOKEN_MAX)
71+
expect(result).toBe(OUTPUT_TOKEN_MAX)
72+
})
73+
74+
test("returns modelLimit - budgetTokens when budgetTokens + 32k > modelLimit", () => {
75+
const modelLimit = 50000
76+
const options = {
77+
thinking: {
78+
type: "enabled",
79+
budgetTokens: 30000,
80+
},
81+
}
82+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/anthropic", options, modelLimit, OUTPUT_TOKEN_MAX)
83+
expect(result).toBe(20000)
84+
})
85+
86+
test("returns 32k when thinking type is not enabled", () => {
87+
const modelLimit = 100000
88+
const options = {
89+
thinking: {
90+
type: "disabled",
91+
budgetTokens: 10000,
92+
},
93+
}
94+
const result = ProviderTransform.maxOutputTokens("@ai-sdk/anthropic", options, modelLimit, OUTPUT_TOKEN_MAX)
95+
expect(result).toBe(OUTPUT_TOKEN_MAX)
96+
})
97+
})
98+
})

0 commit comments

Comments
 (0)