From 76c0b1f81e85e6ad857317ce26ed3f772c6dbc2b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 18:16:34 +0000 Subject: [PATCH 1/3] fix(server): send OpenCode Go models as bare runtime IDs (#3571) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenCode looks up provider.models[modelID], so a duplicated opencode-go/ prefix on the model ID is rejected. Keep the application slug namespaced and strip the extra prefix at the OpenCode runtime seam. Inventory slugs now use the catalog map key so discovery matches that same request shape. Co-authored-by: Mats Varnskühler --- .../provider/Layers/OpenCodeAdapter.test.ts | 235 ++++++++++++++++++ .../provider/Layers/OpenCodeProvider.test.ts | 47 ++++ .../src/provider/Layers/OpenCodeProvider.ts | 9 +- .../opencodeRuntime.cliParsers.test.ts | 26 ++ apps/server/src/provider/opencodeRuntime.ts | 14 +- 5 files changed, 325 insertions(+), 6 deletions(-) diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts index eea328e05d1e..49d67371f390 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts @@ -388,6 +388,241 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { }), ); + it.effect("sends OpenCode Go models to the runtime as a bare modelID", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-opencode-go-deepseek"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "opencode-go/deepseek-v4-pro", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "opencode-go", + modelID: "deepseek-v4-pro", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("strips a duplicated OpenCode Go provider prefix before the runtime request", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-opencode-go-doubled"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "opencode-go/opencode-go/deepseek-v4-pro", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "opencode-go", + modelID: "deepseek-v4-pro", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("sends a second OpenCode Go model with the same bare runtime modelID shape", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-opencode-go-kimi"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "opencode-go/kimi-k2.7-code", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "opencode-go", + modelID: "kimi-k2.7-code", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("keeps a slash inside a non-OpenCode-Go model ID", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-openrouter-slash"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "openrouter/qwen/qwen3-coder", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "openrouter", + modelID: "qwen/qwen3-coder", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("passes an unknown provider/model slug through without rewriting it", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-custom-opencode-model"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "acme/custom-model", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "acme", + modelID: "custom-model", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("rejects a bare OpenCode model id that is missing the provider namespace", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-bare-opencode-model"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + const error = yield* adapter + .sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "deepseek-v4-pro", + ), + }) + .pipe(Effect.flip); + + NodeAssert.equal(error._tag, "ProviderAdapterValidationError"); + if (error._tag !== "ProviderAdapterValidationError") { + throw new Error("Unexpected error type"); + } + NodeAssert.equal( + error.issue, + "OpenCode model selection must use the 'provider/model' format.", + ); + NodeAssert.deepEqual(runtimeMock.state.promptCalls, []); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("normalizes a duplicated OpenCode Go slug on the resume sendTurn path", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-opencode-go-resume-model"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + resumeCursor: { schemaVersion: 1, sessionId: "ses_persisted" }, + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "opencode-go/opencode-go/kimi-k2.7-code", + ), + }); + + yield* adapter.sendTurn({ + threadId, + input: "continue", + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "ses_persisted", + model: { + providerID: "opencode-go", + modelID: "kimi-k2.7-code", + }, + parts: [{ type: "text", text: "continue" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + it.effect("falls back to a fresh session when the persisted session is gone", () => Effect.gen(function* () { const adapter = yield* OpenCodeAdapter; diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.test.ts b/apps/server/src/provider/Layers/OpenCodeProvider.test.ts index 41454b48b314..e8ac7d79465d 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.test.ts @@ -207,6 +207,53 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { }), ); + it.effect("builds OpenCode Go slugs from the inventory map key, not a namespaced model.id", () => + Effect.gen(function* () { + runtimeMock.state.inventory = { + providerList: { + connected: ["opencode-go", "anthropic"], + all: [ + { + id: "opencode-go", + name: "OpenCode Go", + models: { + "deepseek-v4-pro": { + id: "opencode-go/deepseek-v4-pro", + name: "DeepSeek V4 Pro", + }, + "kimi-k2.7-code": { + id: "kimi-k2.7-code", + name: "Kimi K2.7 Code", + }, + }, + }, + { + id: "anthropic", + name: "Anthropic", + models: { + "claude-sonnet-4-5": { + id: "claude-sonnet-4-5", + name: "Claude Sonnet 4.5", + }, + }, + }, + ], + default: {}, + }, + agents: [], + }; + + const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); + const slugs = snapshot.models.map((entry) => entry.slug).toSorted(); + + NodeAssert.deepEqual(slugs, [ + "anthropic/claude-sonnet-4-5", + "opencode-go/deepseek-v4-pro", + "opencode-go/kimi-k2.7-code", + ]); + }), + ); + it.effect("does not spawn a local server for health check (uses CLI instead)", () => Effect.gen(function* () { yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.ts b/apps/server/src/provider/Layers/OpenCodeProvider.ts index 21014e33f08b..20d2693a1273 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.ts @@ -226,15 +226,20 @@ function flattenOpenCodeModels(input: OpenCodeInventory): ReadonlyArray { NodeAssert.equal(model.id, "qwen/qwen3-coder"); NodeAssert.equal(model.providerID, "openrouter"); }); + + it("keys OpenCode Go models by the slug suffix even when JSON id is namespaced", () => { + const stdout = [ + "opencode-go/deepseek-v4-pro", + JSON.stringify({ + id: "opencode-go/deepseek-v4-pro", + providerID: "opencode-go", + name: "DeepSeek V4 Pro", + status: "active", + }), + "opencode-go/kimi-k2.7-code", + JSON.stringify({ + id: "kimi-k2.7-code", + providerID: "opencode-go", + name: "Kimi K2.7 Code", + status: "active", + }), + ].join("\n"); + + const result = parseModelsCliOutput(stdout); + const provider = result.providers.get("opencode-go")!; + NodeAssert.ok(provider); + NodeAssert.deepEqual([...result.connected], ["opencode-go"]); + NodeAssert.equal(provider.models["deepseek-v4-pro"]?.id, "opencode-go/deepseek-v4-pro"); + NodeAssert.equal(provider.models["kimi-k2.7-code"]?.id, "kimi-k2.7-code"); + }); }); describe("parseAgentListCliOutput", () => { diff --git a/apps/server/src/provider/opencodeRuntime.ts b/apps/server/src/provider/opencodeRuntime.ts index 399e7d6b3b0f..e2da36f64cd8 100644 --- a/apps/server/src/provider/opencodeRuntime.ts +++ b/apps/server/src/provider/opencodeRuntime.ts @@ -302,10 +302,16 @@ export function parseOpenCodeModelSlug( return null; } - return { - providerID: trimmed.slice(0, separator), - modelID: trimmed.slice(separator + 1), - }; + const providerID = trimmed.slice(0, separator); + let modelID = trimmed.slice(separator + 1); + const prefix = `${providerID}/`; + // Inventory or persisted slugs can repeat the provider (`opencode-go/opencode-go/…`). + // OpenCode looks up `provider.models[modelID]`, so the extra prefix must not ship. + while (modelID.startsWith(prefix) && modelID.length > prefix.length) { + modelID = modelID.slice(prefix.length); + } + + return { providerID, modelID }; } export function openCodeQuestionId( From 9f389b89a44c8d41156295fea16a7dd449f7ebb7 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 18:26:25 +0000 Subject: [PATCH 2/3] fix(server): strip duplicated OpenCode prefixes only for hosted catalogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit General duplicate-prefix stripping would rewrite a legitimate catalog key that starts with provider/ (huggingface/huggingface/CodeBERTa). Keep first-slash parsing for all providers, and only peel a repeated opencode or opencode-go prefix at the runtime seam. Inventory still uses the catalog map key. Co-authored-by: Mats Varnskühler --- .../provider/Layers/OpenCodeAdapter.test.ts | 66 +++++++++++++++++++ .../src/provider/Layers/OpenCodeAdapter.ts | 4 +- .../provider/Layers/OpenCodeProvider.test.ts | 30 +++++++++ .../opencodeRuntime.cliParsers.test.ts | 40 ++++++++++- apps/server/src/provider/opencodeRuntime.ts | 34 ++++++++-- .../textGeneration/OpenCodeTextGeneration.ts | 2 +- 6 files changed, 165 insertions(+), 11 deletions(-) diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts index 49d67371f390..6a83f2d033f6 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts @@ -487,6 +487,72 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { }), ); + it.effect("strips a duplicated OpenCode Zen provider prefix before the runtime request", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-opencode-zen-doubled"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "opencode/opencode/gpt-5.4", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "opencode", + modelID: "gpt-5.4", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("keeps a catalog key that starts with the same provider id", () => + Effect.gen(function* () { + const adapter = yield* OpenCodeAdapter; + const threadId = asThreadId("thread-huggingface-slash-key"); + + yield* adapter.startSession({ + provider: ProviderDriverKind.make("opencode"), + threadId, + runtimeMode: "full-access", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello", + modelSelection: createModelSelection( + ProviderInstanceId.make("opencode"), + "huggingface/huggingface/CodeBERTa", + ), + }); + + NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { + sessionID: "http://127.0.0.1:9999/session", + model: { + providerID: "huggingface", + modelID: "huggingface/CodeBERTa", + }, + parts: [{ type: "text", text: "hello" }], + }); + + yield* adapter.stopSession(threadId); + }), + ); + it.effect("keeps a slash inside a non-OpenCode-Go model ID", () => Effect.gen(function* () { const adapter = yield* OpenCodeAdapter; diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.ts index 8f7e42c11d7c..6dfddd30e15a 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.ts @@ -44,7 +44,7 @@ import { OpenCodeRuntimeError, openCodeQuestionId, openCodeRuntimeErrorDetail, - parseOpenCodeModelSlug, + toOpenCodeRuntimeModel, runOpenCodeSdk, toOpenCodeFileParts, toOpenCodePermissionReply, @@ -1446,7 +1446,7 @@ export function makeOpenCodeAdapter( issue: `OpenCode model selection is bound to instance '${modelSelection?.instanceId}', expected '${boundInstanceId}'.`, }); } - const parsedModel = parseOpenCodeModelSlug(modelSelection?.model); + const parsedModel = toOpenCodeRuntimeModel(modelSelection?.model); if (!parsedModel) { return yield* new ProviderAdapterValidationError({ provider: PROVIDER, diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.test.ts b/apps/server/src/provider/Layers/OpenCodeProvider.test.ts index e8ac7d79465d..54fbf8c46bb1 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.test.ts @@ -254,6 +254,36 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { }), ); + it.effect("keeps a catalog map key that already starts with the provider id", () => + Effect.gen(function* () { + runtimeMock.state.inventory = { + providerList: { + connected: ["huggingface"], + all: [ + { + id: "huggingface", + name: "Hugging Face", + models: { + "huggingface/CodeBERTa": { + id: "huggingface/CodeBERTa", + name: "CodeBERTa", + }, + }, + }, + ], + default: {}, + }, + agents: [], + }; + + const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); + NodeAssert.deepEqual( + snapshot.models.map((entry) => entry.slug), + ["huggingface/huggingface/CodeBERTa"], + ); + }), + ); + it.effect("does not spawn a local server for health check (uses CLI instead)", () => Effect.gen(function* () { yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); diff --git a/apps/server/src/provider/opencodeRuntime.cliParsers.test.ts b/apps/server/src/provider/opencodeRuntime.cliParsers.test.ts index 9c8cf4dda0e2..698a7d388a6c 100644 --- a/apps/server/src/provider/opencodeRuntime.cliParsers.test.ts +++ b/apps/server/src/provider/opencodeRuntime.cliParsers.test.ts @@ -2,7 +2,12 @@ import * as NodeAssert from "node:assert/strict"; import { describe, it } from "vite-plus/test"; -import { parseModelsCliOutput, parseAgentListCliOutput } from "./opencodeRuntime.ts"; +import { + parseAgentListCliOutput, + parseModelsCliOutput, + parseOpenCodeModelSlug, + toOpenCodeRuntimeModel, +} from "./opencodeRuntime.ts"; describe("parseModelsCliOutput", () => { it("parses a single model from a single provider", () => { @@ -278,3 +283,36 @@ describe("parseAgentListCliOutput", () => { NodeAssert.equal(result[1]!.hidden, false); }); }); + +describe("toOpenCodeRuntimeModel", () => { + it("splits on the first slash without rewriting a well-formed slug", () => { + NodeAssert.deepEqual(toOpenCodeRuntimeModel("opencode-go/deepseek-v4-pro"), { + providerID: "opencode-go", + modelID: "deepseek-v4-pro", + }); + NodeAssert.deepEqual(toOpenCodeRuntimeModel("openrouter/qwen/qwen3-coder"), { + providerID: "openrouter", + modelID: "qwen/qwen3-coder", + }); + }); + + it("strips a duplicated hosted OpenCode prefix and leaves other catalogs intact", () => { + NodeAssert.deepEqual(toOpenCodeRuntimeModel("opencode-go/opencode-go/deepseek-v4-pro"), { + providerID: "opencode-go", + modelID: "deepseek-v4-pro", + }); + NodeAssert.deepEqual(toOpenCodeRuntimeModel("opencode/opencode/gpt-5.4"), { + providerID: "opencode", + modelID: "gpt-5.4", + }); + NodeAssert.deepEqual(toOpenCodeRuntimeModel("huggingface/huggingface/CodeBERTa"), { + providerID: "huggingface", + modelID: "huggingface/CodeBERTa", + }); + }); + + it("rejects a bare model id the same way parseOpenCodeModelSlug does", () => { + NodeAssert.equal(parseOpenCodeModelSlug("deepseek-v4-pro"), null); + NodeAssert.equal(toOpenCodeRuntimeModel("deepseek-v4-pro"), null); + }); +}); diff --git a/apps/server/src/provider/opencodeRuntime.ts b/apps/server/src/provider/opencodeRuntime.ts index e2da36f64cd8..514bbf902b20 100644 --- a/apps/server/src/provider/opencodeRuntime.ts +++ b/apps/server/src/provider/opencodeRuntime.ts @@ -302,16 +302,36 @@ export function parseOpenCodeModelSlug( return null; } - const providerID = trimmed.slice(0, separator); - let modelID = trimmed.slice(separator + 1); - const prefix = `${providerID}/`; - // Inventory or persisted slugs can repeat the provider (`opencode-go/opencode-go/…`). - // OpenCode looks up `provider.models[modelID]`, so the extra prefix must not ship. + return { + providerID: trimmed.slice(0, separator), + modelID: trimmed.slice(separator + 1), + }; +} + +/** + * Hosted OpenCode catalogs (Zen and Go) key models by bare ID. A T3 inventory + * slug built from `model.id` can repeat that provider (`opencode-go/opencode-go/…`). + * Other providers may legitimately use a key that starts with `provider/`. + */ +const OPENCODE_HOSTED_PROVIDER_IDS = new Set(["opencode", "opencode-go"]); + +export function toOpenCodeRuntimeModel( + slug: string | null | undefined, +): ParsedOpenCodeModelSlug | null { + const parsed = parseOpenCodeModelSlug(slug); + if (!parsed) { + return null; + } + if (!OPENCODE_HOSTED_PROVIDER_IDS.has(parsed.providerID)) { + return parsed; + } + + const prefix = `${parsed.providerID}/`; + let modelID = parsed.modelID; while (modelID.startsWith(prefix) && modelID.length > prefix.length) { modelID = modelID.slice(prefix.length); } - - return { providerID, modelID }; + return { providerID: parsed.providerID, modelID }; } export function openCodeQuestionId( diff --git a/apps/server/src/textGeneration/OpenCodeTextGeneration.ts b/apps/server/src/textGeneration/OpenCodeTextGeneration.ts index e09c3db2cffc..7c5993f35154 100644 --- a/apps/server/src/textGeneration/OpenCodeTextGeneration.ts +++ b/apps/server/src/textGeneration/OpenCodeTextGeneration.ts @@ -366,7 +366,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration" readonly modelSelection: ModelSelection; readonly attachments?: ReadonlyArray | undefined; }) { - const parsedModel = OpenCodeRuntime.parseOpenCodeModelSlug(input.modelSelection.model); + const parsedModel = OpenCodeRuntime.toOpenCodeRuntimeModel(input.modelSelection.model); if (!parsedModel) { return yield* new TextGenerationError({ operation: input.operation, From fb8becd065f89baa955a2a53f8c6712aedaebdf3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 16 Aug 2026 20:02:11 +0000 Subject: [PATCH 3/3] test(server): keep OpenCode Go model tests to the distinctive cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop duplicate sendTurn copies that the runtime helper unit tests already cover, matching the smaller first-time contributor PRs that landed. Co-authored-by: Mats Varnskühler --- .../provider/Layers/OpenCodeAdapter.test.ts | 132 ------------------ 1 file changed, 132 deletions(-) diff --git a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts index 6a83f2d033f6..aa70476ab171 100644 --- a/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts +++ b/apps/server/src/provider/Layers/OpenCodeAdapter.test.ts @@ -454,72 +454,6 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { }), ); - it.effect("sends a second OpenCode Go model with the same bare runtime modelID shape", () => - Effect.gen(function* () { - const adapter = yield* OpenCodeAdapter; - const threadId = asThreadId("thread-opencode-go-kimi"); - - yield* adapter.startSession({ - provider: ProviderDriverKind.make("opencode"), - threadId, - runtimeMode: "full-access", - }); - - yield* adapter.sendTurn({ - threadId, - input: "hello", - modelSelection: createModelSelection( - ProviderInstanceId.make("opencode"), - "opencode-go/kimi-k2.7-code", - ), - }); - - NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { - sessionID: "http://127.0.0.1:9999/session", - model: { - providerID: "opencode-go", - modelID: "kimi-k2.7-code", - }, - parts: [{ type: "text", text: "hello" }], - }); - - yield* adapter.stopSession(threadId); - }), - ); - - it.effect("strips a duplicated OpenCode Zen provider prefix before the runtime request", () => - Effect.gen(function* () { - const adapter = yield* OpenCodeAdapter; - const threadId = asThreadId("thread-opencode-zen-doubled"); - - yield* adapter.startSession({ - provider: ProviderDriverKind.make("opencode"), - threadId, - runtimeMode: "full-access", - }); - - yield* adapter.sendTurn({ - threadId, - input: "hello", - modelSelection: createModelSelection( - ProviderInstanceId.make("opencode"), - "opencode/opencode/gpt-5.4", - ), - }); - - NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { - sessionID: "http://127.0.0.1:9999/session", - model: { - providerID: "opencode", - modelID: "gpt-5.4", - }, - parts: [{ type: "text", text: "hello" }], - }); - - yield* adapter.stopSession(threadId); - }), - ); - it.effect("keeps a catalog key that starts with the same provider id", () => Effect.gen(function* () { const adapter = yield* OpenCodeAdapter; @@ -553,72 +487,6 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { }), ); - it.effect("keeps a slash inside a non-OpenCode-Go model ID", () => - Effect.gen(function* () { - const adapter = yield* OpenCodeAdapter; - const threadId = asThreadId("thread-openrouter-slash"); - - yield* adapter.startSession({ - provider: ProviderDriverKind.make("opencode"), - threadId, - runtimeMode: "full-access", - }); - - yield* adapter.sendTurn({ - threadId, - input: "hello", - modelSelection: createModelSelection( - ProviderInstanceId.make("opencode"), - "openrouter/qwen/qwen3-coder", - ), - }); - - NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { - sessionID: "http://127.0.0.1:9999/session", - model: { - providerID: "openrouter", - modelID: "qwen/qwen3-coder", - }, - parts: [{ type: "text", text: "hello" }], - }); - - yield* adapter.stopSession(threadId); - }), - ); - - it.effect("passes an unknown provider/model slug through without rewriting it", () => - Effect.gen(function* () { - const adapter = yield* OpenCodeAdapter; - const threadId = asThreadId("thread-custom-opencode-model"); - - yield* adapter.startSession({ - provider: ProviderDriverKind.make("opencode"), - threadId, - runtimeMode: "full-access", - }); - - yield* adapter.sendTurn({ - threadId, - input: "hello", - modelSelection: createModelSelection( - ProviderInstanceId.make("opencode"), - "acme/custom-model", - ), - }); - - NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { - sessionID: "http://127.0.0.1:9999/session", - model: { - providerID: "acme", - modelID: "custom-model", - }, - parts: [{ type: "text", text: "hello" }], - }); - - yield* adapter.stopSession(threadId); - }), - ); - it.effect("rejects a bare OpenCode model id that is missing the provider namespace", () => Effect.gen(function* () { const adapter = yield* OpenCodeAdapter;