Skip to content

Commit 4e7e94f

Browse files
committed
fix: cap default glm output reservation
1 parent fd6da8a commit 4e7e94f

4 files changed

Lines changed: 41 additions & 17 deletions

File tree

src/api/providers/__tests__/zai.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,34 @@ describe("ZAiHandler", () => {
475475
})
476476

477477
describe("GLM-4.7 Thinking Mode", () => {
478+
it("should cap GLM-5.1 max_tokens to 20% of context window by default", async () => {
479+
const handlerWithModel = new ZAiHandler({
480+
apiModelId: "glm-5.1",
481+
zaiApiKey: "test-zai-api-key",
482+
zaiApiLine: "international_coding",
483+
})
484+
485+
mockCreate.mockImplementationOnce(() => {
486+
return {
487+
[Symbol.asyncIterator]: () => ({
488+
async next() {
489+
return { done: true }
490+
},
491+
}),
492+
}
493+
})
494+
495+
const messageGenerator = handlerWithModel.createMessage("system prompt", [])
496+
await messageGenerator.next()
497+
498+
expect(mockCreate).toHaveBeenCalledWith(
499+
expect.objectContaining({
500+
model: "glm-5.1",
501+
max_tokens: 40_000,
502+
}),
503+
)
504+
})
505+
478506
it("should enable thinking by default for GLM-4.7 (default reasoningEffort is medium)", async () => {
479507
const handlerWithModel = new ZAiHandler({
480508
apiModelId: "glm-4.7",

src/api/providers/zai.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
zaiApiLineConfigs,
1212
} from "@roo-code/types"
1313

14-
import { type ApiHandlerOptions, shouldUseReasoningEffort } from "../../shared/api"
14+
import { type ApiHandlerOptions, getModelMaxOutputTokens, shouldUseReasoningEffort } from "../../shared/api"
1515
import { convertToZAiFormat } from "../transform/zai-format"
1616

1717
import type { ApiHandlerCreateMessageMetadata } from "../index"
@@ -79,11 +79,15 @@ export class ZAiHandler extends BaseOpenAiCompatibleProvider<string> {
7979
) {
8080
const { id: model, info } = this.getModel()
8181

82-
// Use info.maxTokens directly — Z.ai model definitions are hand-curated and accurate.
83-
// getModelMaxOutputTokens clamps to 20% of contextWindow (a guard for OpenRouter dynamic
84-
// metadata where maxTokens ≈ contextWindow), but ApiHandlerOptions omits apiProvider so
85-
// the zai bypass in api.ts never fires. glm-5.1 legitimately supports 128k output.
86-
const max_tokens = this.options.modelMaxTokens || (info.maxTokens ?? undefined)
82+
const max_tokens =
83+
this.options.modelMaxTokens ||
84+
(getModelMaxOutputTokens({
85+
modelId: model,
86+
model: info,
87+
settings: this.options,
88+
format: "openai",
89+
}) ??
90+
undefined)
8791

8892
const temperature = this.options.modelTemperature ?? this.defaultTemperature
8993

src/shared/__tests__/api.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,7 @@ describe("getModelMaxOutputTokens", () => {
274274
})
275275
})
276276

277-
test("should bypass 20% cap for Z.ai provider and use exact configured max tokens", () => {
278-
// glm-5.1: maxTokens=131_072 on a 200k context window (65.5%) — would be capped to 40k without bypass
277+
test("should still clamp Z.ai models to 20% of context window by default", () => {
279278
const model: ModelInfo = {
280279
contextWindow: 200_000,
281280
supportsPromptCache: true,
@@ -290,7 +289,7 @@ describe("getModelMaxOutputTokens", () => {
290289
format: "openai",
291290
})
292291

293-
expect(result).toBe(131_072)
292+
expect(result).toBe(40_000)
294293
})
295294

296295
test("should still clamp non-Z.ai models with high maxTokens to 20% of context window", () => {

src/shared/api.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,8 @@ export const getModelMaxOutputTokens = ({
138138
// Check if this is a GPT-5 model (case-insensitive)
139139
const isGpt5Model = modelId.toLowerCase().includes("gpt-5")
140140

141-
// Z.ai models have hand-curated maxTokens values from Z.ai's own documentation
142-
// (e.g. glm-5.1 supports 128k output on a 200k context window) — bypass the cap.
143-
// Note: ZAiHandler.createStreamWithThinking bypasses this function entirely because
144-
// ApiHandlerOptions omits apiProvider; this bypass serves callers that pass full
145-
// ProviderSettings (Task.ts context management, model-params.ts).
146-
const isZaiProvider = settings?.apiProvider === "zai"
147-
148141
// GPT-5 models bypass the 20% cap and use their full configured max tokens
149-
if (isGpt5Model || isZaiProvider) {
142+
if (isGpt5Model) {
150143
return model.maxTokens
151144
}
152145

0 commit comments

Comments
 (0)