From 52a43d65d33deb89a0653cf60c1420d2a57a8b4c Mon Sep 17 00:00:00 2001 From: JeferssonLemes Date: Wed, 27 May 2026 17:06:32 -0300 Subject: [PATCH] feat(modelSpecs): align opencode-go family with upstream provider limits (#2802) Integrated into release/v3.8.6 --- src/shared/constants/modelSpecs.ts | 84 ++++++++++++++++++- .../unit/t31-t33-t34-t38-model-specs.test.ts | 50 +++++++++++ 2 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/shared/constants/modelSpecs.ts b/src/shared/constants/modelSpecs.ts index 23785f561a..7af781da61 100644 --- a/src/shared/constants/modelSpecs.ts +++ b/src/shared/constants/modelSpecs.ts @@ -217,10 +217,35 @@ export const MODEL_SPECS: Record = { aliases: ["kimi-k2.6-thinking", "kimi-for-coding"], }, - // ── Qwen3.7 Max (Bailian multimodal — text/image/video) ───────── - "qwen3.7-max": { - maxOutputTokens: 8192, - contextWindow: 200000, + // ── Kimi K2.5 (Moonshot — 262K native, parity with K2.6) ──────── + "kimi-k2.5": { + maxOutputTokens: 262144, + contextWindow: 262144, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + aliases: ["kimi-k2.5-thinking"], + }, + + // ── Qwen3.x Plus / Max (Bailian — multimodal text/image/video, 1M context) ─ + "qwen3-max": { + maxOutputTokens: 65536, + contextWindow: 1000000, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + aliases: ["qwen3.7-max", "qwen3-max-2026-01-23"], + }, + "qwen3.6-plus": { + maxOutputTokens: 65536, + contextWindow: 1000000, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + }, + "qwen3.5-plus": { + maxOutputTokens: 65536, + contextWindow: 1000000, supportsThinking: true, supportsTools: true, supportsVision: true, @@ -257,6 +282,57 @@ export const MODEL_SPECS: Record = { supportsTools: true, }, + // ── Z.AI GLM-5.x (200K context, 128K max output) ───────────────── + "glm-5.1": { + maxOutputTokens: 128000, + contextWindow: 200000, + supportsThinking: true, + supportsTools: true, + }, + "glm-5": { + maxOutputTokens: 128000, + contextWindow: 200000, + supportsThinking: true, + supportsTools: true, + }, + + // ── MiniMax M2.x (200K context family) ─────────────────────────── + "minimax-m2.7": { + maxOutputTokens: 131072, + contextWindow: 204800, + supportsThinking: true, + supportsTools: true, + }, + "minimax-m2.5": { + maxOutputTokens: 131072, + contextWindow: 200000, + supportsThinking: true, + supportsTools: true, + aliases: ["MiniMax-M2.5"], + }, + + // ── DeepSeek V4 (1M context, 384K max output) ──────────────────── + "deepseek-v4-pro": { + maxOutputTokens: 384000, + contextWindow: 1000000, + supportsThinking: true, + supportsTools: true, + }, + "deepseek-v4-flash": { + maxOutputTokens: 384000, + contextWindow: 1000000, + supportsThinking: true, + supportsTools: true, + }, + + // ── Tencent Hunyuan 3 Preview ──────────────────────────────────── + "hy3-preview": { + maxOutputTokens: 262144, + contextWindow: 262144, + supportsThinking: true, + supportsTools: true, + }, + // Defaults __default__: { maxOutputTokens: 8192, diff --git a/tests/unit/t31-t33-t34-t38-model-specs.test.ts b/tests/unit/t31-t33-t34-t38-model-specs.test.ts index 3fc38afbb0..ef0175557b 100644 --- a/tests/unit/t31-t33-t34-t38-model-specs.test.ts +++ b/tests/unit/t31-t33-t34-t38-model-specs.test.ts @@ -82,3 +82,53 @@ test("T38: MiMo V2.5 and V2 Omni models support vision", () => { assert.equal(MODEL_SPECS["mimo-v2-omni"].supportsVision, true); assert.equal(MODEL_SPECS["mimo-v2-flash"].supportsVision, undefined); }); + +test("opencode-go family: context/output caps match upstream provider docs", () => { + // Qwen3.x Plus / Max: 1M context, 65K output (Bailian) + assert.equal(getModelSpec("qwen3-max").contextWindow, 1000000); + assert.equal(getModelSpec("qwen3-max").maxOutputTokens, 65536); + assert.equal(getModelSpec("qwen3.7-max").contextWindow, 1000000); + assert.equal(getModelSpec("qwen3-max-2026-01-23").contextWindow, 1000000); + assert.equal(getModelSpec("qwen3.6-plus").contextWindow, 1000000); + assert.equal(getModelSpec("qwen3.6-plus").maxOutputTokens, 65536); + assert.equal(getModelSpec("qwen3.5-plus").contextWindow, 1000000); + assert.equal(getModelSpec("qwen3.5-plus").maxOutputTokens, 65536); + + // Kimi K2.5: 262K context/output (Moonshot, parity with K2.6) + assert.equal(getModelSpec("kimi-k2.5").contextWindow, 262144); + assert.equal(getModelSpec("kimi-k2.5").maxOutputTokens, 262144); + + // GLM-5.x: 200K context, 128K output (Z.AI) + assert.equal(getModelSpec("glm-5.1").contextWindow, 200000); + assert.equal(getModelSpec("glm-5.1").maxOutputTokens, 128000); + assert.equal(getModelSpec("glm-5").contextWindow, 200000); + + // MiniMax M2.x: ~200K context, 131K output + assert.equal(getModelSpec("minimax-m2.7").contextWindow, 204800); + assert.equal(getModelSpec("minimax-m2.7").maxOutputTokens, 131072); + assert.equal(getModelSpec("minimax-m2.5").contextWindow, 200000); + assert.equal(getModelSpec("MiniMax-M2.5").contextWindow, 200000); + + // DeepSeek V4: 1M context, 384K output + assert.equal(getModelSpec("deepseek-v4-pro").contextWindow, 1000000); + assert.equal(getModelSpec("deepseek-v4-pro").maxOutputTokens, 384000); + assert.equal(getModelSpec("deepseek-v4-flash").contextWindow, 1000000); + + // Tencent Hunyuan 3 Preview: 262K context/output + assert.equal(getModelSpec("hy3-preview").contextWindow, 262144); + assert.equal(getModelSpec("hy3-preview").maxOutputTokens, 262144); +}); + +test("opencode-go family: capMaxOutputTokens grants full upstream budget", () => { + // Without explicit specs these models would fall back to __default__ (8192). + // Assert they now receive the real upstream cap. + assert.equal(capMaxOutputTokens("qwen3-max", 100000), 65536); + assert.equal(capMaxOutputTokens("qwen3.7-max", 100000), 65536); + assert.equal(capMaxOutputTokens("qwen3-max-2026-01-23", 100000), 65536); + assert.equal(capMaxOutputTokens("kimi-k2.5", 300000), 262144); + assert.equal(capMaxOutputTokens("glm-5.1", 200000), 128000); + assert.equal(capMaxOutputTokens("minimax-m2.7", 200000), 131072); + assert.equal(capMaxOutputTokens("MiniMax-M2.5", 200000), 131072); + assert.equal(capMaxOutputTokens("deepseek-v4-pro", 500000), 384000); + assert.equal(capMaxOutputTokens("hy3-preview", 300000), 262144); +});