diff --git a/CHANGELOG.md b/CHANGELOG.md index 1be3ab30d..78ba13cbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,8 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename cycles through a closed live-activity set (`working`, `warping`, `buzzing`, `grinding`, `thinking`, `doing`, `cooking`, `creating`, `imagining`, `inventing`) instead of going blank. +- OpenCode Go routes Muse Spark 1.2 Contributor and Muse Spark 1.3 + Contributor through the Responses API instead of chat completions. ## [0.3.19] - 2026-09-10 diff --git a/packages/opencode-go/src/endpoint.test.ts b/packages/opencode-go/src/endpoint.test.ts index 0db852f06..645a0d3fb 100644 --- a/packages/opencode-go/src/endpoint.test.ts +++ b/packages/opencode-go/src/endpoint.test.ts @@ -14,6 +14,8 @@ describe("protocolForGoModel", () => { test("returns protocol for known models", () => { expect(protocolForGoModel("kimi-k2.7-code")).toBe("chat-completions"); expect(protocolForGoModel("gpt-5.6-luna")).toBe("responses"); + expect(protocolForGoModel("muse-spark-1.3-contributor")).toBe("responses"); + expect(protocolForGoModel("muse-spark-1.2-contributor")).toBe("responses"); expect(protocolForGoModel("minimax-m3")).toBe("messages"); }); @@ -48,6 +50,18 @@ describe("resolveGoEndpoint", () => { expect(ep.baseURL).toContain("/zen/go/v1"); }); + test("routes Muse Spark Contributor models to openai-responses adapter", () => { + for (const id of [ + "muse-spark-1.3-contributor", + "muse-spark-1.2-contributor", + ]) { + const ep = resolveGoEndpoint(id); + expect(ep.adapter).toBe("openai-responses"); + expect(ep.protocol).toBe("responses"); + expect(ep.baseURL).toContain("/zen/go/v1"); + } + }); + test("routes messages models to anthropic base", () => { const ep = resolveGoEndpoint("minimax-m3"); expect(ep.adapter).toBe("anthropic"); diff --git a/packages/opencode-go/src/models.ts b/packages/opencode-go/src/models.ts index bf6618df6..723dda5b5 100644 --- a/packages/opencode-go/src/models.ts +++ b/packages/opencode-go/src/models.ts @@ -14,6 +14,16 @@ export interface GoModel { export const OPENCODE_GO_MODELS = [ { id: "grok-4.5", name: "Grok 4.5", protocol: "chat-completions" }, { id: "gpt-5.6-luna", name: "GPT 5.6 Luna", protocol: "responses" }, + { + id: "muse-spark-1.3-contributor", + name: "Muse Spark 1.3 Contributor", + protocol: "responses", + }, + { + id: "muse-spark-1.2-contributor", + name: "Muse Spark 1.2 Contributor", + protocol: "responses", + }, { id: "glm-5.2", name: "GLM-5.2", protocol: "chat-completions" }, { id: "glm-5.1", name: "GLM-5.1", protocol: "chat-completions" }, { id: "kimi-k3", name: "Kimi K3", protocol: "chat-completions" }, diff --git a/src/config.test.ts b/src/config.test.ts index 143da7876..be1a0b7eb 100644 --- a/src/config.test.ts +++ b/src/config.test.ts @@ -1986,13 +1986,13 @@ describe("refreshLiveProviderCatalog", () => { globalThis.fetch = (async () => Response.json({ - data: [{ id: "grok-4.5" }, { id: "muse-spark-1.2-contributor" }], + data: [{ id: "grok-4.5" }, { id: "live-only-fixture-model" }], })) as unknown as typeof fetch; await prefetchGoModels(); const warm = await refreshLiveProviderCatalog(settings, resolved); const warmGo = warm.find((c) => c.name === "go"); - expect(warmGo?.models).toContain("muse-spark-1.2-contributor"); + expect(warmGo?.models).toContain("live-only-fixture-model"); expect(warm.find((c) => c.name === "fp")?.models).toEqual(["fp-large"]); expect( buildProviderCatalog(settings, resolved).find((c) => c.name === "go") diff --git a/src/provider/billing-product.test.ts b/src/provider/billing-product.test.ts index d824ca24c..a8de3b5f7 100644 --- a/src/provider/billing-product.test.ts +++ b/src/provider/billing-product.test.ts @@ -102,12 +102,21 @@ describe("isGoModelOnZenPath", () => { ).toBe(false); }); - test("false for a live-only Go id on Zen (protocol map, not picker membership)", () => { + test("true when a packaged Muse Spark model sits on a Zen-billed provider", () => { expect( isGoModelOnZenPath("muse-spark-1.2-contributor", { name: "zen", baseURL: "https://opencode.ai/zen/v1", }), + ).toBe(true); + }); + + test("false for a live-only Go id on Zen (protocol map, not picker membership)", () => { + expect( + isGoModelOnZenPath("live-only-fixture-model", { + name: "zen", + baseURL: "https://opencode.ai/zen/v1", + }), ).toBe(false); }); diff --git a/src/provider/opencode-go-models.test.ts b/src/provider/opencode-go-models.test.ts index c0f2c7377..5785601b5 100644 --- a/src/provider/opencode-go-models.test.ts +++ b/src/provider/opencode-go-models.test.ts @@ -12,7 +12,7 @@ import { } from "./opencode-go-models.js"; const originalFetch = globalThis.fetch; -const LIVE_ONLY_ID = "muse-spark-1.2-contributor"; +const LIVE_ONLY_ID = "live-only-fixture-model"; const GO_MODELS_URL = "https://opencode.ai/zen/go/v1/models"; beforeEach(() => { diff --git a/src/tui/provider-setup.test.ts b/src/tui/provider-setup.test.ts index c0563e486..defc79860 100644 --- a/src/tui/provider-setup.test.ts +++ b/src/tui/provider-setup.test.ts @@ -751,7 +751,7 @@ describe("runProviderSetup Ollama discovery", () => { }); describe("runProviderSetup Go models", () => { - const LIVE_ONLY_ID = "muse-spark-1.2-contributor"; + const LIVE_ONLY_ID = "live-only-fixture-model"; test("choiceFromDef lists selectable Go ids", () => { const go = providerChoiceById("opencode-go");