diff --git a/changelog.d/fixes/12196-opencode-go-gpt56luna.md b/changelog.d/fixes/12196-opencode-go-gpt56luna.md new file mode 100644 index 0000000000..26fa9396a0 --- /dev/null +++ b/changelog.d/fixes/12196-opencode-go-gpt56luna.md @@ -0,0 +1 @@ +- fix(providers): route opencode-go/gpt-5.6-luna to /responses instead of /chat/completions (#12196) diff --git a/open-sse/config/providers/registry/opencode/go/index.ts b/open-sse/config/providers/registry/opencode/go/index.ts index 645a828fed..2d364bd5fb 100644 --- a/open-sse/config/providers/registry/opencode/go/index.ts +++ b/open-sse/config/providers/registry/opencode/go/index.ts @@ -250,6 +250,16 @@ export const opencode_goProvider: RegistryEntry = { supportedThinkingEfforts: ["none", "low", "high", "max"], targetFormat: "openai-responses", }, + // #12196: the Go upstream serves this model only on /responses — + // /chat/completions 500s for it. github already declares the same model + // id with targetFormat:"openai-responses" (see github/index.ts). + { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + supportsReasoning: true, + targetFormat: "openai-responses", + maxOutputTokens: 128000, + }, // Console Go free GLM-tier model (live-verified 2026-08-23): the upstream // rejects every reasoning_effort outside {low, high, max} whenever tools // are present — "[1210] This model always engages in thinking and cannot diff --git a/tests/unit/issue-12196-opencode-go-gpt56luna.test.ts b/tests/unit/issue-12196-opencode-go-gpt56luna.test.ts new file mode 100644 index 0000000000..38631f0dc6 --- /dev/null +++ b/tests/unit/issue-12196-opencode-go-gpt56luna.test.ts @@ -0,0 +1,33 @@ +import assert from "node:assert/strict"; +import { test } from "node:test"; + +import { resolveOpencodeTargetFormat } from "../../open-sse/executors/opencode.ts"; + +// Issue #12196: opencode-go/gpt-5.6-luna is served by the Go upstream ONLY on +// /responses — /chat/completions 500s for this model. The github provider +// already declares targetFormat:"openai-responses" for the same model id, and +// opencode-go already does the same for deepseek-v4-pro/deepseek-v4-flash on +// this exact provider — but gpt-5.6-luna itself is missing from the +// opencode-go registry, so getModelTargetFormat() falls through to null and +// resolveOpencodeTargetFormat() defaults to "openai", which makes +// OpencodeExecutor.buildUrl() post to /chat/completions instead of /responses. +test("opencode-go/gpt-5.6-luna must resolve to the openai-responses target format", () => { + const resolved = resolveOpencodeTargetFormat("opencode-go", "gpt-5.6-luna"); + assert.equal( + resolved, + "openai-responses", + "opencode-go/gpt-5.6-luna resolved to '" + + resolved + + "' instead of 'openai-responses' — OpencodeExecutor.buildUrl() will post to " + + "/chat/completions, which the Go upstream 500s on for this model (issue #12196)" + ); +}); + +// Control: the sibling deepseek-v4-flash entry on the SAME opencode-go +// provider already declares targetFormat:"openai-responses" and must keep +// working — proves the assertion above isn't failing for an unrelated reason +// (e.g. a broken import or alias resolution). +test("control: opencode-go/deepseek-v4-flash already resolves to openai-responses", () => { + const resolved = resolveOpencodeTargetFormat("opencode-go", "deepseek-v4-flash"); + assert.equal(resolved, "openai-responses"); +});