From 1b65e471fb3105e6b652accf7a41841f82698216 Mon Sep 17 00:00:00 2001 From: roboomp Date: Wed, 19 Aug 2026 09:24:54 +0000 Subject: [PATCH] fix(catalog): route opencode-go muse-spark to responses api The OpenCode Go gateway serves muse-spark-1.2 and muse-spark-1.2-contributor only at /zen/go/v1/responses, but the /zen/go/v1/models discovery omits the provider.npm hint, so the resolver fell through to openai-completions. The completions parser then closed the stream without a finish_reason on every tool-call turn. Pin both ids to openai-responses in OPENCODE_GO_API_RESOLUTION, mirroring the existing deepseek-v4-flash override, and add a resolver regression. Fixes #8957 --- packages/catalog/CHANGELOG.md | 1 + .../catalog/src/provider-models/openai-compat.ts | 9 +++++++++ packages/catalog/test/opencode-provider.test.ts | 15 +++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/packages/catalog/CHANGELOG.md b/packages/catalog/CHANGELOG.md index 390d0adee..a04761f80 100644 --- a/packages/catalog/CHANGELOG.md +++ b/packages/catalog/CHANGELOG.md @@ -14,6 +14,7 @@ - Fixed SuperGrok (`xai-oauth`) Grok 4.6 hiding the thinking-level picker: the Responses effort-capable allowlist now includes `grok-4.6`, so `/model` can select the documented `low`/`medium`/`high`/`xhigh` ladder (`max` is rejected by api.x.ai). - Marked CoreWeave runtime discovery as authoritative so stale bundled model ids that the endpoint no longer serves stop appearing as selectable models. - ChatGPT Codex discovery that advertises only worker `-wm` SKUs now also registers the plain model route, so a configured `openai-codex/` keeps resolving instead of fuzzy-falling-back to the `-wm` SKU some accounts reject. +- Fixed `opencode-go/muse-spark-1.2` (and `muse-spark-1.2-contributor`) failing every tool-call turn with `OpenAI completions stream closed before a finish_reason was received`. The Go gateway serves these ids only at `/zen/go/v1/responses`, but the `/zen/go/v1/models` discovery omits the `provider.npm` hint, so the resolver fell through to `openai-completions`; both ids are now pinned to `openai-responses` like `deepseek-v4-flash` ([#8957](https://github.com/can1357/oh-my-pi/issues/8957)). ## [17.3.6] - 2026-08-17 diff --git a/packages/catalog/src/provider-models/openai-compat.ts b/packages/catalog/src/provider-models/openai-compat.ts index 7fc21a0ab..b5db5a5fd 100644 --- a/packages/catalog/src/provider-models/openai-compat.ts +++ b/packages/catalog/src/provider-models/openai-compat.ts @@ -5715,8 +5715,17 @@ const OPENCODE_ZEN_API_RESOLUTION = createOpenCodeApiResolution("https://opencod // /zen/go/v1/chat/completions route does not work for this model while // /zen/go/v1/responses does (user-verified against the live gateway, // 2026-08-08; Flash only — deepseek-v4-pro serves fine on chat completions). +// +// muse-spark-1.2 / muse-spark-1.2-contributor are the same inverse case: the +// Go gateway's /zen/go/v1/models discovery drops the `provider.npm` hint, so +// without an override they fall through to openai-completions even though the +// gateway only serves them at /zen/go/v1/responses (@ai-sdk/openai per +// https://opencode.ai/docs/go/#endpoints). The completions parser then closes +// the stream with no finish_reason on every tool-call turn (#8957). const OPENCODE_GO_API_RESOLUTION = createOpenCodeApiResolution("https://opencode.ai/zen/go", { "deepseek-v4-flash": "openai-responses", + "muse-spark-1.2": "openai-responses", + "muse-spark-1.2-contributor": "openai-responses", "minimax-m2.7": "openai-completions", "minimax-m3": "openai-completions", "minimax-m3-free": "openai-completions", diff --git a/packages/catalog/test/opencode-provider.test.ts b/packages/catalog/test/opencode-provider.test.ts index d1717adfa..b8d157c17 100644 --- a/packages/catalog/test/opencode-provider.test.ts +++ b/packages/catalog/test/opencode-provider.test.ts @@ -54,6 +54,21 @@ describe("OpenCode provider discovery", () => { }); }); + test("routes opencode-go muse-spark-1.2 to the responses API (#8957)", () => { + const descriptor = MODELS_DEV_PROVIDER_DESCRIPTORS.find(item => item.providerId === "opencode-go"); + // The Go /zen/go/v1/models discovery drops the provider.npm hint for the + // muse-spark ids, so without an override they fall through to + // openai-completions even though the gateway only serves them at + // /zen/go/v1/responses. Sending completions requests closes the stream + // with no finish_reason on every tool-call turn. + for (const id of ["muse-spark-1.2", "muse-spark-1.2-contributor"]) { + expect(descriptor?.resolveApi?.(id, { tool_call: true })).toEqual({ + api: "openai-responses", + baseUrl: "https://opencode.ai/zen/go/v1", + }); + } + }); + test("replaces stale bundled Zen models with each credential's live endpoint list", async () => { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-opencode-zen-")); try {