From 9faaa789017b8f8fba0014de7dc3e9acc5c0ed25 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Jul 2026 13:52:46 -0700 Subject: [PATCH] fix(opencode): sync Zen runtime catalog (#113858) --- extensions/opencode/index.test.ts | 25 +++++++++++-------------- extensions/opencode/provider-catalog.ts | 23 ++++++++++++++++------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/extensions/opencode/index.test.ts b/extensions/opencode/index.test.ts index 3a549479c0a0..d19694c2b97b 100644 --- a/extensions/opencode/index.test.ts +++ b/extensions/opencode/index.test.ts @@ -84,6 +84,7 @@ describe("opencode provider plugin", () => { const expectedModelIds = [ "claude-fable-5", + "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", @@ -137,7 +138,8 @@ describe("opencode provider plugin", () => { "big-pickle", "deepseek-v4-flash-free", "mimo-v2.5-free", - "hy3-free", + "laguna-s-2.1-free", + "ling-3.0-flash-free", "nemotron-3-ultra-free", "north-mini-code-free", ]; @@ -266,15 +268,6 @@ describe("opencode provider plugin", () => { ], }, }); - expect(requireMapEntry(models, "hy3-free")).toMatchObject({ - name: "Hy3 Free", - api: "openai-completions", - baseUrl: "https://opencode.ai/zen/v1", - input: ["text"], - contextWindow: 256_000, - maxTokens: 64_000, - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - }); expect(requireMapEntry(models, "kimi-k2.7-code")).toMatchObject({ name: "Kimi K2.7 Code", api: "openai-completions", @@ -413,6 +406,7 @@ describe("opencode provider plugin", () => { const verifiedCostExamples = new Map([ ["claude-fable-5", { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }], + ["claude-opus-5", { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }], ["claude-opus-4-8", { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }], ["claude-opus-4-5", { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }], ["claude-opus-4-1", { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }], @@ -470,8 +464,10 @@ describe("opencode provider plugin", () => { ], ["gpt-5.4-mini", { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }], ["glm-5.2", { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }], - ["hy3-free", { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }], ["kimi-k2.7-code", { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }], + ["laguna-s-2.1-free", { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }], + ["ling-3.0-flash-free", { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }], + ["minimax-m2.5", { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }], ["minimax-m2.7", { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }], ["minimax-m3", { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }], ] as const); @@ -510,12 +506,12 @@ describe("opencode provider plugin", () => { throw new Error("expected OpenCode Zen static provider"); } - expect(result.provider.models).toHaveLength(57); + expect(result.provider.models).toHaveLength(59); + expect(result.provider.models.map((model) => model.id)).toContain("claude-opus-5"); expect(result.provider.models.map((model) => model.id)).toContain("claude-opus-4-8"); expect(result.provider.models.map((model) => model.id)).toContain("claude-sonnet-5"); expect(result.provider.models.map((model) => model.id)).toContain("glm-5.2"); expect(result.provider.models.map((model) => model.id)).toContain("grok-4.5"); - expect(result.provider.models.map((model) => model.id)).toContain("hy3-free"); expect(result.provider.models.map((model) => model.id)).toContain("kimi-k2.7-code"); expect(result.provider.models.map((model) => model.id)).toContain("minimax-m2.7"); expect(result.provider.models.map((model) => model.id)).toContain("minimax-m3"); @@ -534,7 +530,8 @@ describe("opencode provider plugin", () => { throw new Error("expected registered OpenCode Zen static provider"); } - expect(result.provider.models).toHaveLength(57); + expect(result.provider.models).toHaveLength(59); + expect(result.provider.models.map((model) => model.id)).toContain("claude-opus-5"); expect(result.provider.models.map((model) => model.id)).toContain("claude-sonnet-5"); expect(result.provider.models.map((model) => model.id)).toContain("gpt-5.6-sol"); expect(result.provider.models.map((model) => model.id)).toContain("minimax-m3"); diff --git a/extensions/opencode/provider-catalog.ts b/extensions/opencode/provider-catalog.ts index 0ea7b3744ac3..eda59364f801 100644 --- a/extensions/opencode/provider-catalog.ts +++ b/extensions/opencode/provider-catalog.ts @@ -29,20 +29,23 @@ const FREE_COST: ModelDefinitionConfig["cost"] = { // Zen publishes route-specific limits that differ from the family defaults below. const MODEL_LIMITS: Record = { + "claude-opus-5": { contextWindow: 1_000_000, maxTokens: 128_000 }, "claude-sonnet-5": { contextWindow: 1_000_000, maxTokens: 128_000 }, "gpt-5.6-luna": { contextWindow: 1_050_000, maxTokens: 128_000 }, "gpt-5.6-sol": { contextWindow: 1_050_000, maxTokens: 128_000 }, "gpt-5.6-terra": { contextWindow: 1_050_000, maxTokens: 128_000 }, "glm-5.2": { contextWindow: 1_000_000, maxTokens: 131_072 }, "grok-4.5": { contextWindow: 500_000, maxTokens: 500_000 }, - "hy3-free": { contextWindow: 256_000, maxTokens: 64_000 }, "kimi-k2.7-code": { contextWindow: 262_144, maxTokens: 262_144 }, + "laguna-s-2.1-free": { contextWindow: 256_000, maxTokens: 32_000 }, + "ling-3.0-flash-free": { contextWindow: 262_144, maxTokens: 32_768 }, "minimax-m3": { contextWindow: 512_000, maxTokens: 128_000 }, }; // These rows are the inverse of their family's usual image-input capability. const MODEL_IMAGE_INPUT_OVERRIDES = new Map([ - ["hy3-free", false], + ["laguna-s-2.1-free", false], + ["ling-3.0-flash-free", false], ["minimax-m3", true], ]); @@ -55,6 +58,7 @@ const MODEL_COSTS: Record = { "claude-opus-4-6": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, "claude-opus-4-7": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, "claude-opus-4-8": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, + "claude-opus-5": { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, "claude-sonnet-4": { input: 3, output: 15, @@ -173,13 +177,14 @@ const MODEL_COSTS: Record = { { input: 4, output: 12, cacheRead: 1, cacheWrite: 0, range: [200_000] }, ], }, - "hy3-free": FREE_COST, "kimi-k2.5": { input: 0.6, output: 3, cacheRead: 0.1, cacheWrite: 0 }, "kimi-k2.6": { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, "kimi-k2.7-code": { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, + "laguna-s-2.1-free": FREE_COST, + "ling-3.0-flash-free": FREE_COST, "mimo-v2.5-free": FREE_COST, - "minimax-m2.5": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 }, - "minimax-m2.7": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 }, + "minimax-m2.5": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, + "minimax-m2.7": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, "minimax-m3": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, "nemotron-3-ultra-free": FREE_COST, "north-mini-code-free": FREE_COST, @@ -196,6 +201,7 @@ const MODEL_NAMES: Record = { "claude-opus-4-6": "Claude Opus 4.6", "claude-opus-4-7": "Claude Opus 4.7", "claude-opus-4-8": "Claude Opus 4.8", + "claude-opus-5": "Claude Opus 5", "claude-sonnet-4": "Claude Sonnet 4", "claude-sonnet-4-5": "Claude Sonnet 4.5", "claude-sonnet-4-6": "Claude Sonnet 4.6", @@ -233,10 +239,11 @@ const MODEL_NAMES: Record = { "gpt-5.5-pro": "GPT-5.5 Pro", "grok-build-0.1": "Grok Build 0.1", "grok-4.5": "Grok 4.5", - "hy3-free": "Hy3 Free", "kimi-k2.5": "Kimi K2.5", "kimi-k2.6": "Kimi K2.6", "kimi-k2.7-code": "Kimi K2.7 Code", + "laguna-s-2.1-free": "Laguna S 2.1 Free", + "ling-3.0-flash-free": "Ling-3.0-flash Free", "mimo-v2.5-free": "MiMo V2.5 Free", "minimax-m2.5": "MiniMax M2.5", "minimax-m2.7": "MiniMax M2.7", @@ -396,6 +403,7 @@ function buildOpencodeZenModel(modelId: string): OpencodeZenModelDefinition { const OPENCODE_ZEN_MODELS = [ "claude-fable-5", + "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", @@ -449,7 +457,8 @@ const OPENCODE_ZEN_MODELS = [ "big-pickle", "deepseek-v4-flash-free", "mimo-v2.5-free", - "hy3-free", + "laguna-s-2.1-free", + "ling-3.0-flash-free", "nemotron-3-ultra-free", "north-mini-code-free", ].map(buildOpencodeZenModel);