fix(volcengine-ark): clamp GLM-5 max_tokens to model output ceiling (#2428)

Ark rejects max_tokens above 128000 for GLM-5.2. Add a config-driven STRIP_RULES entry that clamps max_tokens, max_completion_tokens and max_output_tokens down to the model maxOutput before the upstream call.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whale
2026-07-07 11:54:42 +07:00
committed by decolua
parent 8c068a1f5c
commit bbae990b92
2 changed files with 41 additions and 0 deletions

View File

@@ -1,3 +1,5 @@
import { getCapabilitiesForModel } from "../../providers/capabilities.js";
// Strip request params a given provider/model rejects upstream (e.g. HTTP 400).
// Config-driven: add a rule instead of scattering `delete body.x` across executors.
@@ -12,6 +14,7 @@ const STRIP_RULES = [
{ provider: "github", match: (m) => /claude/i.test(m) && !/claude.*(opus|sonnet).*4\.6/i.test(m), drop: ["thinking", "reasoning_effort"] },
// Cloudflare Workers AI: content must be plain string, rejects OpenAI content-part array (#1926)
{ provider: "cloudflare-ai", flattenContent: true },
{ provider: "volcengine-ark", match: /glm-5/i, clampToModelMaxOutput: true },
];
// Test a rule's match (regex or predicate) against the model id.
@@ -20,6 +23,12 @@ function matches(rule, model) {
return typeof rule.match === "function" ? rule.match(model) : rule.match.test(model);
}
function clampNumber(body, key, ceiling) {
if (typeof body[key] === "number" && Number.isFinite(body[key]) && body[key] > ceiling) {
body[key] = ceiling;
}
}
// Remove unsupported params from body in place; returns body.
export function stripUnsupportedParams(provider, model, body) {
if (!model || !body || typeof body !== "object") return body;
@@ -39,6 +48,14 @@ export function stripUnsupportedParams(provider, model, body) {
}
}
}
if (rule.clampToModelMaxOutput) {
const ceiling = getCapabilitiesForModel(provider, model).maxOutput;
if (Number.isFinite(ceiling) && ceiling > 0) {
clampNumber(body, "max_tokens", ceiling);
clampNumber(body, "max_completion_tokens", ceiling);
clampNumber(body, "max_output_tokens", ceiling);
}
}
}
return body;
}

View File

@@ -28,4 +28,28 @@ describe("stripUnsupportedParams", () => {
expect(body).toEqual({ top_p: 1 });
});
it("clamps VolcEngine Ark GLM max token fields to the model output ceiling", () => {
const body = {
max_tokens: 131072,
max_completion_tokens: 131072,
max_output_tokens: 131072,
};
stripUnsupportedParams("volcengine-ark", "GLM-5.2", body);
expect(body).toEqual({
max_tokens: 128000,
max_completion_tokens: 128000,
max_output_tokens: 128000,
});
});
it("keeps VolcEngine Ark GLM max tokens when already under the ceiling", () => {
const body = { max_tokens: 64000 };
stripUnsupportedParams("volcengine-ark", "GLM-5.2", body);
expect(body.max_tokens).toBe(64000);
});
});