Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions packages/opencode-go/src/endpoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});

Expand Down Expand Up @@ -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");
Expand Down
10 changes: 10 additions & 0 deletions packages/opencode-go/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down
4 changes: 2 additions & 2 deletions src/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
11 changes: 10 additions & 1 deletion src/provider/billing-product.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand Down
2 changes: 1 addition & 1 deletion src/provider/opencode-go-models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/tui/provider-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Loading