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
5 changes: 5 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,11 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
[OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
// Experimental DeepSeek vision preview — expected to merge into deepseek-v4-flash later.
[DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
// Muse Spark 1.2 Contributor is natively multimodal on Zen Go: it accepts input_image
// parts over /responses (probed 2026-08-26). Without this declaration the catalog
// advertises it text-only and the Codex app blocks image attachments client-side with
// "This model does not support image inputs" before the request ever reaches the proxy.
"muse-spark-1.2-contributor": ["text", "image"],
},
modelReasoningEfforts: {
"gpt-5.6-luna": OPENAI_API_GPT56_REASONING_EFFORTS,
Expand Down
51 changes: 51 additions & 0 deletions tests/opencode-go-muse-vision.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* OpenCode Go Muse Spark 1.2 Contributor multimodal regression.
*
* Muse Spark answers /responses on Zen Go and accepts input_image parts, but the
* registry declared no modelInputModalities for it, so the Codex catalog advertised
* it text-only. The app gates image attachments client-side on input_modalities,
* so a text-only entry blocks images ("This model does not support image inputs")
* before the request ever reaches the proxy. These tests lock the declaration in
* and prove the catalog advertises image input for Muse.
*/
import { describe, expect, test } from "bun:test";
import { applyProviderConfigHints } from "../src/codex/catalog";
import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../src/providers/registry";
import { providerConfigSeed } from "../src/providers/derive";
import type { OcxProviderConfig } from "../src/types";

const MUSE_MODEL = "muse-spark-1.2-contributor";

/** Seeded OpenCode Go provider config for the Muse Spark vision assertions. */
function opencodeGo(): OcxProviderConfig {
const entry = getProviderRegistryEntry("opencode-go");
if (!entry) throw new Error("missing opencode-go registry fixture");
return { ...providerConfigSeed(entry), apiKey: "test-key" };
}

describe("OpenCode Go Muse Spark image input (#vision)", () => {
test("registry declares Muse as text+image", () => {
const entry = PROVIDER_REGISTRY.find(e => e.id === "opencode-go");
expect(entry?.modelInputModalities?.[MUSE_MODEL]).toEqual(["text", "image"]);
});

test("the registry seed carries Muse as text+image", () => {
const prov = opencodeGo();
expect(prov.modelInputModalities?.[MUSE_MODEL]).toEqual(["text", "image"]);
});

test("applyProviderConfigHints advertises image input for Muse", () => {
const prov = opencodeGo();
const hinted = applyProviderConfigHints("opencode-go", prov, {
id: MUSE_MODEL,
provider: "opencode-go",
});
expect(hinted.inputModalities).toEqual(["text", "image"]);
});

test("Muse is NOT in noVisionModels (it is natively multimodal, not sidecar-only)", () => {
const prov = opencodeGo();
expect(prov.noVisionModels ?? []).not.toContain(MUSE_MODEL);
expect(prov.modelInputModalities?.[MUSE_MODEL]).toEqual(["text", "image"]);
});
});
Loading