From 47b353f5d4aca61cc3c902bb84139e9976ee0564 Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Mon, 12 Oct 2026 13:58:55 -0400 Subject: [PATCH 1/3] feat: add Muse Wonder 1.0 support --- README.md | 25 ++-- ...odel-runtimes-and-credentials.explainer.md | 13 ++- ...option-templates-and-ci-workflows.guide.md | 7 +- src/__tests__/opencode.test.ts | 110 ++++++++++++++---- src/core/opencode.ts | 16 +++ templates/config.jsonc | 4 +- 6 files changed, 130 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index ca9f57c..dfe30c5 100644 --- a/README.md +++ b/README.md @@ -765,24 +765,27 @@ fallback key; `ecr doctor` diagnoses setup. } } ``` -- **Meta / Muse Spark 1.3 (public Model API).** Set the default model and any - model-pinned agent frontmatter to `meta/muse-spark-1.3`. ECR supplies the fixed - public Responses endpoint and the `@ai-sdk/openai` adapter; the generic - Chat-Completions compatibility adapter is intentionally not used because it - loses Muse's reasoning continuity across tool turns. Standard and Contributor - model ids are supported. +- **Meta / Muse Wonder 1.0 and Muse Spark (public Model API).** Set the default + model and any model-pinned agent frontmatter to `meta/muse-wonder-1.0`. ECR + supplies the fixed public Responses endpoint and the `@ai-sdk/openai` adapter; + the generic Chat-Completions compatibility adapter is intentionally not used + because it loses Muse's reasoning continuity across tool turns. Muse Spark + standard and Contributor model ids also remain supported. ```jsonc - "model": "meta/muse-spark-1.3", + "model": "meta/muse-wonder-1.0", "auth": { "providers": { "meta": { "mode": "api-key", "tokenEnv": "META_API_KEY" } } } ``` - Standard and Contributor 1.2/1.3 model ids have known capability metadata. Any - future model explicitly named as `meta/` is still routed to the fixed Meta - endpoint with neutral metadata, so a renamed family such as `meta/muse-foo` does - not require an ECR release; Meta validates an unknown id on its first request. + Muse Wonder 1.0 and standard/Contributor Muse Spark 1.2/1.3 model ids have known + capability metadata. Wonder uses a 1,048,576-token context and a practical + 131,072-token output cap, with text, image, PDF, video, and audio inputs. Existing + Spark configs remain supported; select `meta/muse-spark-1.3` to keep using Spark. + Any future model explicitly named as `meta/` is still routed to the fixed + Meta endpoint with neutral metadata, so a renamed family such as `meta/muse-foo` + does not require an ECR release; Meta validates an unknown id on its first request. Create the key in the [Meta AI developer portal](https://developer.meta.com/ai/). Locally, export it as `META_API_KEY`. In each review-running workflow, replace diff --git a/llp/0003-model-runtimes-and-credentials.explainer.md b/llp/0003-model-runtimes-and-credentials.explainer.md index cb9abf7..630d021 100644 --- a/llp/0003-model-runtimes-and-credentials.explainer.md +++ b/llp/0003-model-runtimes-and-credentials.explainer.md @@ -111,10 +111,15 @@ Completions path loses that continuity [observed: Provider selection is forward-compatible at the provider boundary, not coupled to the current Muse family name: every referenced non-empty `meta/` id is declared on -the synthesized Meta provider. Known Muse Spark 1.2 and 1.3 standard/Contributor ids -receive their published limits, multimodal inputs, high reasoning, and encrypted -reasoning inclusion from `META_MUSE_MODELS`; a future id such as `meta/muse-foo` is -declared with neutral metadata rather than guessed capabilities. This deliberately +the synthesized Meta provider. Known Muse Wonder 1.0 and Muse Spark 1.2/1.3 +standard/Contributor ids receive capability metadata, multimodal inputs, high +reasoning, and encrypted reasoning inclusion from `META_MUSE_MODELS`. Wonder's +1,048,576-token context and practical 131,072-token output cap follow the +[public models.dev catalog](https://github.com/anomalyco/models.dev/blob/949b366b555d42eced53e0870b994def848a797e/models/meta/muse-wonder-1.0.toml); +the output cap bounds reserved output TPM, not a separately published Meta maximum. +Its input modalities include audio in addition to text, images, PDFs, and video. +A future id such as `meta/muse-foo` is declared with neutral metadata rather than +guessed capabilities. This deliberately moves validation of an unknown-but-well-formed Meta id from OpenCode's local preflight to its first Meta request, in exchange for new Meta names working without an ECR release [observed: `opencode.ts` `META_MUSE_MODELS` / `buildOpencodeConfig`]. diff --git a/llp/0009-adoption-templates-and-ci-workflows.guide.md b/llp/0009-adoption-templates-and-ci-workflows.guide.md index 0234c2b..6601ac6 100644 --- a/llp/0009-adoption-templates-and-ci-workflows.guide.md +++ b/llp/0009-adoption-templates-and-ci-workflows.guide.md @@ -55,9 +55,10 @@ The three workflows share a posture built entirely around one fact: a reviewer j **Concurrency defaults by auth mode.** The commented `chunk.concurrency` default is 6 for an API key and 3 for a subscription (OAuth) credential, "one account handles many parallel streams poorly, and several PRs may review on the same credential at once" [observed: `templates/config.jsonc:28-30`]. -**Muse Spark is opt-in without weakening the default secret surface.** The root config -documents `meta/muse-spark-1.3` plus a `META_API_KEY` auth entry, and each -review-running workflow shows the corresponding secret line commented out. It is not +**Muse is opt-in without weakening the default secret surface.** The root config +documents `meta/muse-wonder-1.0` (or `meta/muse-spark-1.3`) plus a `META_API_KEY` +auth entry, and each review-running workflow shows the corresponding secret line +commented out. It is not forwarded by the default scaffold: adopters replace the Anthropic line and set `ECR_EXPECTED_TOKEN_ENV=META_API_KEY`, so the model process receives only the credential actually selected by trusted config. The default remains Anthropic and diff --git a/src/__tests__/opencode.test.ts b/src/__tests__/opencode.test.ts index d854285..6893ddc 100644 --- a/src/__tests__/opencode.test.ts +++ b/src/__tests__/opencode.test.ts @@ -12,6 +12,8 @@ import { buildOpencodeConfig, resolveEngineDispatch, resolveOpencodeCli, + CROSS_CUTTING_AGENT, + VERIFIER_AGENT, STACK_VERIFIER_AGENT, META_MODEL_API_BASE_URL, } from "../core/opencode.js"; @@ -385,32 +387,90 @@ test("Meta auth synthesizes the public Muse 1.3 Responses provider without embed expect(meta!.models["muse-spark-1.3-contributor"]?.reasoning).toBe(true); }); -test("a Meta-named upstream alias does not redirect the upstream credential to Meta", () => { - const config = configWith({ - agents: [{ id: "correctness", model: "meta/muse-spark-1.2" }], - coordinatorModel: "meta/muse-spark-1.2", - auth: [ - { - mode: "api-key", - provider: "meta", - tokenEnv: "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN", - upstream: "anthropic", +test.each(["reviewer", "coordinator"])( + "Meta auth registers Muse Wonder 1.0 metadata when used by the %s", + (role) => { + const wonder = "meta/muse-wonder-1.0"; + const spark = "meta/muse-spark-1.3"; + const reviewerModel = role === "reviewer" ? wonder : spark; + const coordinatorModel = role === "coordinator" ? wonder : spark; + const opencode = buildOpencodeConfig( + configWith({ + agents: [ + { id: "correctness", model: reviewerModel }, + { id: "security", model: "openai/muse-wonder-1.0" }, + ], + coordinatorModel, + auth: [{ mode: "api-key", provider: "meta", tokenEnv: "META_API_KEY" }], + }), + ) as { + agent: Record; + provider: Record }>; + }; + const meta = opencode.provider.meta!; + expect(meta.npm).toBe("@ai-sdk/openai"); + expect(meta.options).toEqual({ + baseURL: META_MODEL_API_BASE_URL, + apiKey: "{env:META_API_KEY}", + }); + expect(Object.keys(meta.models).sort()).toEqual(["muse-spark-1.3", "muse-wonder-1.0"]); + expect(meta.models["muse-wonder-1.0"]).toEqual({ + name: "Muse Wonder 1.0", + reasoning: true, + limit: { context: 1_048_576, output: 131_072 }, + modalities: { + input: ["text", "image", "pdf", "video", "audio"], + output: ["text"], }, - ], - }); - const opencode = buildOpencodeConfig(config) as { - provider?: Record< - string, - { npm: string; options: { apiKey: string; baseURL?: string }; models: object } - >; - }; - const alias = opencode.provider?.meta; - expect(alias).toBeDefined(); - expect(alias!.npm).toBe("@ai-sdk/anthropic"); - expect(alias!.options).toEqual({ apiKey: "{env:CLAUDE_CODE_REVIEW_SHARED_API_TOKEN}" }); - expect(alias!.options.baseURL).toBeUndefined(); - expect(Object.keys(alias!.models)).toEqual(["muse-spark-1.2"]); -}); + options: { + store: false, + reasoningEffort: "high", + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }, + }); + expect(meta.models["muse-spark-1.3"]).toMatchObject({ + reasoning: true, + limit: { context: 1_048_576, output: 1_048_576 }, + }); + for (const id of ["correctness", CROSS_CUTTING_AGENT, VERIFIER_AGENT, STACK_VERIFIER_AGENT]) { + expect(opencode.agent[id]!.model).toBe(reviewerModel); + } + expect(opencode.agent.coordinator!.model).toBe(coordinatorModel); + expect(opencode.agent.security!.model).toBe("openai/muse-wonder-1.0"); + expect(opencode.provider.openai).toBeUndefined(); + }, +); + +test.each(["muse-spark-1.2", "muse-wonder-1.0"])( + "a Meta-named upstream alias does not redirect the upstream credential to Meta for %s", + (model) => { + const config = configWith({ + agents: [{ id: "correctness", model: `meta/${model}` }], + coordinatorModel: `meta/${model}`, + auth: [ + { + mode: "api-key", + provider: "meta", + tokenEnv: "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN", + upstream: "anthropic", + }, + ], + }); + const opencode = buildOpencodeConfig(config) as { + provider?: Record< + string, + { npm: string; options: { apiKey: string; baseURL?: string }; models: object } + >; + }; + const alias = opencode.provider?.meta; + expect(alias).toBeDefined(); + expect(alias!.npm).toBe("@ai-sdk/anthropic"); + expect(alias!.options).toEqual({ apiKey: "{env:CLAUDE_CODE_REVIEW_SHARED_API_TOKEN}" }); + expect(alias!.options.baseURL).toBeUndefined(); + expect(Object.keys(alias!.models)).toEqual([model]); + }, +); test("Meta provider registers future model families neutrally and only for the meta prefix", () => { const config = configWith({ diff --git a/src/core/opencode.ts b/src/core/opencode.ts index 5ace65b..5274de6 100644 --- a/src/core/opencode.ts +++ b/src/core/opencode.ts @@ -85,6 +85,22 @@ export const META_MUSE_MODELS: Record> = { include: ["reasoning.encrypted_content"], }, }, + "muse-wonder-1.0": { + name: "Muse Wonder 1.0", + reasoning: true, + // models.dev's public catalog uses a practical output cap to bound reserved TPM. + limit: { context: 1_048_576, output: 131_072 }, + modalities: { + input: ["text", "image", "pdf", "video", "audio"], + output: ["text"], + }, + options: { + store: false, + reasoningEffort: "high", + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }, + }, }; /** diff --git a/templates/config.jsonc b/templates/config.jsonc index e9f841f..644a5c4 100644 --- a/templates/config.jsonc +++ b/templates/config.jsonc @@ -86,8 +86,8 @@ // store the key as a repo secret and pass it under that env var. // "auth": { "mode": "api-key", "provider": "openai", "tokenEnv": "OPENAI_API_KEY" } // - // Muse Spark via the public Meta Model API Responses endpoint: - // set models to `meta/muse-spark-1.3` and configure: + // Muse Wonder or Muse Spark via the public Meta Model API Responses endpoint: + // set models to `meta/muse-wonder-1.0` (or `meta/muse-spark-1.3`) and configure: // "auth": { "providers": { // "meta": { "mode": "api-key", "tokenEnv": "META_API_KEY" } // } } From f997d3457a5f441486f2319c1eac58aad9bb26ce Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Mon, 12 Oct 2026 14:02:31 -0400 Subject: [PATCH 2/3] docs: include Muse Wonder in credential setup help --- src/__tests__/setup-auth.test.ts | 9 +++++++-- src/commands/setup-auth.ts | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/__tests__/setup-auth.test.ts b/src/__tests__/setup-auth.test.ts index f25ebdc..55a990d 100644 --- a/src/__tests__/setup-auth.test.ts +++ b/src/__tests__/setup-auth.test.ts @@ -14,8 +14,13 @@ test("plan: the mixed setup needs one ChatGPT login and one manual key", () => { expect(plan.unsupported).toEqual([]); }); -test("plan: Meta Model API is a manual API key setup", () => { - const plan = planFromAuth([{ provider: "meta", mode: "api-key", tokenEnv: "META_API_KEY" }]); +test("plan: Meta Model API is a manual API key setup for Muse Wonder", () => { + const plan = planFromAuth( + [{ provider: "meta", mode: "api-key", tokenEnv: "META_API_KEY" }], + ["meta/muse-wonder-1.0"], + ); + expect(plan.chatgptLogin).toBeUndefined(); + expect(plan.claudeLogin).toBeUndefined(); expect(plan.manualKeys).toEqual([ { provider: "meta", tokenEnv: "META_API_KEY", upstream: undefined }, ]); diff --git a/src/commands/setup-auth.ts b/src/commands/setup-auth.ts index 94371c5..2b720fd 100644 --- a/src/commands/setup-auth.ts +++ b/src/commands/setup-auth.ts @@ -26,7 +26,8 @@ getting each credential: CI/headless runs. • an API key (api-key entries): prints where to create the key, the exact permissions it needs, and the export line to fill in. Meta Model API - (\`meta/muse-spark-…\`) uses META_API_KEY from the Meta AI developer portal. + (\`meta/muse-wonder-1.0\` or \`meta/muse-spark-…\`) uses META_API_KEY + from the Meta AI developer portal. Without a repo config, it offers the recommended ChatGPT/Codex subscription flow with the default env name. From c6b8c504eb0c6bc115947b1acc09e63d00fdf45e Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Mon, 12 Oct 2026 14:03:15 -0400 Subject: [PATCH 3/3] chore: limit Wonder support to runtime metadata --- README.md | 25 ++-- ...odel-runtimes-and-credentials.explainer.md | 13 +-- ...option-templates-and-ci-workflows.guide.md | 7 +- src/__tests__/opencode.test.ts | 110 ++++-------------- src/__tests__/setup-auth.test.ts | 9 +- src/commands/setup-auth.ts | 3 +- src/core/opencode.ts | 1 - templates/config.jsonc | 4 +- 8 files changed, 48 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index dfe30c5..ca9f57c 100644 --- a/README.md +++ b/README.md @@ -765,27 +765,24 @@ fallback key; `ecr doctor` diagnoses setup. } } ``` -- **Meta / Muse Wonder 1.0 and Muse Spark (public Model API).** Set the default - model and any model-pinned agent frontmatter to `meta/muse-wonder-1.0`. ECR - supplies the fixed public Responses endpoint and the `@ai-sdk/openai` adapter; - the generic Chat-Completions compatibility adapter is intentionally not used - because it loses Muse's reasoning continuity across tool turns. Muse Spark - standard and Contributor model ids also remain supported. +- **Meta / Muse Spark 1.3 (public Model API).** Set the default model and any + model-pinned agent frontmatter to `meta/muse-spark-1.3`. ECR supplies the fixed + public Responses endpoint and the `@ai-sdk/openai` adapter; the generic + Chat-Completions compatibility adapter is intentionally not used because it + loses Muse's reasoning continuity across tool turns. Standard and Contributor + model ids are supported. ```jsonc - "model": "meta/muse-wonder-1.0", + "model": "meta/muse-spark-1.3", "auth": { "providers": { "meta": { "mode": "api-key", "tokenEnv": "META_API_KEY" } } } ``` - Muse Wonder 1.0 and standard/Contributor Muse Spark 1.2/1.3 model ids have known - capability metadata. Wonder uses a 1,048,576-token context and a practical - 131,072-token output cap, with text, image, PDF, video, and audio inputs. Existing - Spark configs remain supported; select `meta/muse-spark-1.3` to keep using Spark. - Any future model explicitly named as `meta/` is still routed to the fixed - Meta endpoint with neutral metadata, so a renamed family such as `meta/muse-foo` - does not require an ECR release; Meta validates an unknown id on its first request. + Standard and Contributor 1.2/1.3 model ids have known capability metadata. Any + future model explicitly named as `meta/` is still routed to the fixed Meta + endpoint with neutral metadata, so a renamed family such as `meta/muse-foo` does + not require an ECR release; Meta validates an unknown id on its first request. Create the key in the [Meta AI developer portal](https://developer.meta.com/ai/). Locally, export it as `META_API_KEY`. In each review-running workflow, replace diff --git a/llp/0003-model-runtimes-and-credentials.explainer.md b/llp/0003-model-runtimes-and-credentials.explainer.md index 630d021..cb9abf7 100644 --- a/llp/0003-model-runtimes-and-credentials.explainer.md +++ b/llp/0003-model-runtimes-and-credentials.explainer.md @@ -111,15 +111,10 @@ Completions path loses that continuity [observed: Provider selection is forward-compatible at the provider boundary, not coupled to the current Muse family name: every referenced non-empty `meta/` id is declared on -the synthesized Meta provider. Known Muse Wonder 1.0 and Muse Spark 1.2/1.3 -standard/Contributor ids receive capability metadata, multimodal inputs, high -reasoning, and encrypted reasoning inclusion from `META_MUSE_MODELS`. Wonder's -1,048,576-token context and practical 131,072-token output cap follow the -[public models.dev catalog](https://github.com/anomalyco/models.dev/blob/949b366b555d42eced53e0870b994def848a797e/models/meta/muse-wonder-1.0.toml); -the output cap bounds reserved output TPM, not a separately published Meta maximum. -Its input modalities include audio in addition to text, images, PDFs, and video. -A future id such as `meta/muse-foo` is declared with neutral metadata rather than -guessed capabilities. This deliberately +the synthesized Meta provider. Known Muse Spark 1.2 and 1.3 standard/Contributor ids +receive their published limits, multimodal inputs, high reasoning, and encrypted +reasoning inclusion from `META_MUSE_MODELS`; a future id such as `meta/muse-foo` is +declared with neutral metadata rather than guessed capabilities. This deliberately moves validation of an unknown-but-well-formed Meta id from OpenCode's local preflight to its first Meta request, in exchange for new Meta names working without an ECR release [observed: `opencode.ts` `META_MUSE_MODELS` / `buildOpencodeConfig`]. diff --git a/llp/0009-adoption-templates-and-ci-workflows.guide.md b/llp/0009-adoption-templates-and-ci-workflows.guide.md index 6601ac6..0234c2b 100644 --- a/llp/0009-adoption-templates-and-ci-workflows.guide.md +++ b/llp/0009-adoption-templates-and-ci-workflows.guide.md @@ -55,10 +55,9 @@ The three workflows share a posture built entirely around one fact: a reviewer j **Concurrency defaults by auth mode.** The commented `chunk.concurrency` default is 6 for an API key and 3 for a subscription (OAuth) credential, "one account handles many parallel streams poorly, and several PRs may review on the same credential at once" [observed: `templates/config.jsonc:28-30`]. -**Muse is opt-in without weakening the default secret surface.** The root config -documents `meta/muse-wonder-1.0` (or `meta/muse-spark-1.3`) plus a `META_API_KEY` -auth entry, and each review-running workflow shows the corresponding secret line -commented out. It is not +**Muse Spark is opt-in without weakening the default secret surface.** The root config +documents `meta/muse-spark-1.3` plus a `META_API_KEY` auth entry, and each +review-running workflow shows the corresponding secret line commented out. It is not forwarded by the default scaffold: adopters replace the Anthropic line and set `ECR_EXPECTED_TOKEN_ENV=META_API_KEY`, so the model process receives only the credential actually selected by trusted config. The default remains Anthropic and diff --git a/src/__tests__/opencode.test.ts b/src/__tests__/opencode.test.ts index 6893ddc..d854285 100644 --- a/src/__tests__/opencode.test.ts +++ b/src/__tests__/opencode.test.ts @@ -12,8 +12,6 @@ import { buildOpencodeConfig, resolveEngineDispatch, resolveOpencodeCli, - CROSS_CUTTING_AGENT, - VERIFIER_AGENT, STACK_VERIFIER_AGENT, META_MODEL_API_BASE_URL, } from "../core/opencode.js"; @@ -387,90 +385,32 @@ test("Meta auth synthesizes the public Muse 1.3 Responses provider without embed expect(meta!.models["muse-spark-1.3-contributor"]?.reasoning).toBe(true); }); -test.each(["reviewer", "coordinator"])( - "Meta auth registers Muse Wonder 1.0 metadata when used by the %s", - (role) => { - const wonder = "meta/muse-wonder-1.0"; - const spark = "meta/muse-spark-1.3"; - const reviewerModel = role === "reviewer" ? wonder : spark; - const coordinatorModel = role === "coordinator" ? wonder : spark; - const opencode = buildOpencodeConfig( - configWith({ - agents: [ - { id: "correctness", model: reviewerModel }, - { id: "security", model: "openai/muse-wonder-1.0" }, - ], - coordinatorModel, - auth: [{ mode: "api-key", provider: "meta", tokenEnv: "META_API_KEY" }], - }), - ) as { - agent: Record; - provider: Record }>; - }; - const meta = opencode.provider.meta!; - expect(meta.npm).toBe("@ai-sdk/openai"); - expect(meta.options).toEqual({ - baseURL: META_MODEL_API_BASE_URL, - apiKey: "{env:META_API_KEY}", - }); - expect(Object.keys(meta.models).sort()).toEqual(["muse-spark-1.3", "muse-wonder-1.0"]); - expect(meta.models["muse-wonder-1.0"]).toEqual({ - name: "Muse Wonder 1.0", - reasoning: true, - limit: { context: 1_048_576, output: 131_072 }, - modalities: { - input: ["text", "image", "pdf", "video", "audio"], - output: ["text"], - }, - options: { - store: false, - reasoningEffort: "high", - reasoningSummary: "auto", - include: ["reasoning.encrypted_content"], +test("a Meta-named upstream alias does not redirect the upstream credential to Meta", () => { + const config = configWith({ + agents: [{ id: "correctness", model: "meta/muse-spark-1.2" }], + coordinatorModel: "meta/muse-spark-1.2", + auth: [ + { + mode: "api-key", + provider: "meta", + tokenEnv: "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN", + upstream: "anthropic", }, - }); - expect(meta.models["muse-spark-1.3"]).toMatchObject({ - reasoning: true, - limit: { context: 1_048_576, output: 1_048_576 }, - }); - for (const id of ["correctness", CROSS_CUTTING_AGENT, VERIFIER_AGENT, STACK_VERIFIER_AGENT]) { - expect(opencode.agent[id]!.model).toBe(reviewerModel); - } - expect(opencode.agent.coordinator!.model).toBe(coordinatorModel); - expect(opencode.agent.security!.model).toBe("openai/muse-wonder-1.0"); - expect(opencode.provider.openai).toBeUndefined(); - }, -); - -test.each(["muse-spark-1.2", "muse-wonder-1.0"])( - "a Meta-named upstream alias does not redirect the upstream credential to Meta for %s", - (model) => { - const config = configWith({ - agents: [{ id: "correctness", model: `meta/${model}` }], - coordinatorModel: `meta/${model}`, - auth: [ - { - mode: "api-key", - provider: "meta", - tokenEnv: "CLAUDE_CODE_REVIEW_SHARED_API_TOKEN", - upstream: "anthropic", - }, - ], - }); - const opencode = buildOpencodeConfig(config) as { - provider?: Record< - string, - { npm: string; options: { apiKey: string; baseURL?: string }; models: object } - >; - }; - const alias = opencode.provider?.meta; - expect(alias).toBeDefined(); - expect(alias!.npm).toBe("@ai-sdk/anthropic"); - expect(alias!.options).toEqual({ apiKey: "{env:CLAUDE_CODE_REVIEW_SHARED_API_TOKEN}" }); - expect(alias!.options.baseURL).toBeUndefined(); - expect(Object.keys(alias!.models)).toEqual([model]); - }, -); + ], + }); + const opencode = buildOpencodeConfig(config) as { + provider?: Record< + string, + { npm: string; options: { apiKey: string; baseURL?: string }; models: object } + >; + }; + const alias = opencode.provider?.meta; + expect(alias).toBeDefined(); + expect(alias!.npm).toBe("@ai-sdk/anthropic"); + expect(alias!.options).toEqual({ apiKey: "{env:CLAUDE_CODE_REVIEW_SHARED_API_TOKEN}" }); + expect(alias!.options.baseURL).toBeUndefined(); + expect(Object.keys(alias!.models)).toEqual(["muse-spark-1.2"]); +}); test("Meta provider registers future model families neutrally and only for the meta prefix", () => { const config = configWith({ diff --git a/src/__tests__/setup-auth.test.ts b/src/__tests__/setup-auth.test.ts index 55a990d..f25ebdc 100644 --- a/src/__tests__/setup-auth.test.ts +++ b/src/__tests__/setup-auth.test.ts @@ -14,13 +14,8 @@ test("plan: the mixed setup needs one ChatGPT login and one manual key", () => { expect(plan.unsupported).toEqual([]); }); -test("plan: Meta Model API is a manual API key setup for Muse Wonder", () => { - const plan = planFromAuth( - [{ provider: "meta", mode: "api-key", tokenEnv: "META_API_KEY" }], - ["meta/muse-wonder-1.0"], - ); - expect(plan.chatgptLogin).toBeUndefined(); - expect(plan.claudeLogin).toBeUndefined(); +test("plan: Meta Model API is a manual API key setup", () => { + const plan = planFromAuth([{ provider: "meta", mode: "api-key", tokenEnv: "META_API_KEY" }]); expect(plan.manualKeys).toEqual([ { provider: "meta", tokenEnv: "META_API_KEY", upstream: undefined }, ]); diff --git a/src/commands/setup-auth.ts b/src/commands/setup-auth.ts index 2b720fd..94371c5 100644 --- a/src/commands/setup-auth.ts +++ b/src/commands/setup-auth.ts @@ -26,8 +26,7 @@ getting each credential: CI/headless runs. • an API key (api-key entries): prints where to create the key, the exact permissions it needs, and the export line to fill in. Meta Model API - (\`meta/muse-wonder-1.0\` or \`meta/muse-spark-…\`) uses META_API_KEY - from the Meta AI developer portal. + (\`meta/muse-spark-…\`) uses META_API_KEY from the Meta AI developer portal. Without a repo config, it offers the recommended ChatGPT/Codex subscription flow with the default env name. diff --git a/src/core/opencode.ts b/src/core/opencode.ts index 5274de6..03b65de 100644 --- a/src/core/opencode.ts +++ b/src/core/opencode.ts @@ -88,7 +88,6 @@ export const META_MUSE_MODELS: Record> = { "muse-wonder-1.0": { name: "Muse Wonder 1.0", reasoning: true, - // models.dev's public catalog uses a practical output cap to bound reserved TPM. limit: { context: 1_048_576, output: 131_072 }, modalities: { input: ["text", "image", "pdf", "video", "audio"], diff --git a/templates/config.jsonc b/templates/config.jsonc index 644a5c4..e9f841f 100644 --- a/templates/config.jsonc +++ b/templates/config.jsonc @@ -86,8 +86,8 @@ // store the key as a repo secret and pass it under that env var. // "auth": { "mode": "api-key", "provider": "openai", "tokenEnv": "OPENAI_API_KEY" } // - // Muse Wonder or Muse Spark via the public Meta Model API Responses endpoint: - // set models to `meta/muse-wonder-1.0` (or `meta/muse-spark-1.3`) and configure: + // Muse Spark via the public Meta Model API Responses endpoint: + // set models to `meta/muse-spark-1.3` and configure: // "auth": { "providers": { // "meta": { "mode": "api-key", "tokenEnv": "META_API_KEY" } // } }