Skip to content

Commit 00b9cac

Browse files
committed
Merge remote-tracking branch 'origin/chore-unskip-e2e-use-mcp-tool' into chore-unskip-e2e-subtasks
2 parents 4f3c395 + 2a54c07 commit 00b9cac

5 files changed

Lines changed: 49 additions & 25 deletions

File tree

apps/vscode-e2e/src/suite/providers/zai.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,12 @@ suite("Z.ai GLM provider", function () {
206206

207207
assert.ok(completionMessage, "Task should complete with the expected Z.ai GLM response")
208208

209-
// Verify max_tokens is the model's documented limit (131_072), not the 20%-of-context
210-
// heuristic cap (40_000) that guards against inaccurate OpenRouter dynamic metadata.
209+
// Verify max_tokens uses the restored default clamp (20% of context window)
210+
// unless the user explicitly overrides it via modelMaxTokens.
211211
assert.strictEqual(
212212
requestCapture.maxTokens,
213-
131_072,
214-
`max_tokens should be the documented glm-5.1 limit (131_072) but was ${requestCapture.maxTokens}`,
213+
40_000,
214+
`max_tokens should default to the glm-5.1 clamp (40_000) but was ${requestCapture.maxTokens}`,
215215
)
216216
})
217217

@@ -245,12 +245,12 @@ suite("Z.ai GLM provider", function () {
245245

246246
assert.ok(completionMessage, "Task should complete with the expected Z.ai GLM-5-Turbo response")
247247

248-
// Verify max_tokens is the model's documented limit (131_072), not the 20%-of-context
249-
// heuristic cap (40_000) that guards against inaccurate OpenRouter dynamic metadata.
248+
// Verify max_tokens uses the restored default clamp (20% of context window)
249+
// unless the user explicitly overrides it via modelMaxTokens.
250250
assert.strictEqual(
251251
requestCapture.maxTokens,
252-
131_072,
253-
`max_tokens should be the documented glm-5-turbo limit (131_072) but was ${requestCapture.maxTokens}`,
252+
40_551,
253+
`max_tokens should default to the glm-5-turbo clamp (40_551) but was ${requestCapture.maxTokens}`,
254254
)
255255
})
256256
})

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)