diff --git a/AGENTS.md b/AGENTS.md index 2f7524b..c92c75e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,7 @@ Current honest state: OpenCode config, and ends with plain `opencode` - the product docs, CI, package contract, and PRD are implemented and now describe the shipped runtime -- the public curated model picker is shipped and currently exposes two +- the public curated model picker is shipped and currently exposes three validated models - the installer writes every validated curated model into `provider.gonkagate.models` so OpenCode's `/models` command can switch @@ -201,8 +201,9 @@ These are implementation facts today, not future plans: diagnostics, and the end-to-end installer flow - the curated model registry under `src/constants/models.ts` now includes pinned public validated entries for - `qwen/qwen3-235b-a22b-instruct-2507-fp8` and - `moonshotai/Kimi-K2.6`, with Kimi K2.6 marked as the recommended default + `qwen/qwen3-235b-a22b-instruct-2507-fp8`, + `moonshotai/Kimi-K2.6`, and `minimaxai/minimax-m2.7`, with Kimi K2.6 marked + as the recommended default - a mirrored skill pack is present under `.agents/skills/` and `.claude/skills/`, imported from `codex-setup` as an initial shared engineering baseline diff --git a/CHANGELOG.md b/CHANGELOG.md index 81d8f32..10188d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,8 @@ ### Changed +- added `minimaxai/minimax-m2.7` to the public curated validated GonkaGate + model picker - added `moonshotai/Kimi-K2.6` to the public curated validated GonkaGate model picker as the recommended default - write the full validated GonkaGate model catalog into diff --git a/README.md b/README.md index ec60afd..a8b91ba 100644 --- a/README.md +++ b/README.md @@ -176,11 +176,12 @@ rely on inherited per-user ACLs instead of portable `chmod`-style enforcement. ## Current Product Truth -The current public curated model picker is shipped and currently exposes two +The current public curated model picker is shipped and currently exposes three validated models: - `qwen/qwen3-235b-a22b-instruct-2507-fp8` - `moonshotai/Kimi-K2.6` +- `minimaxai/minimax-m2.7` Interactive mode keeps the public curated model picker visible. `--yes` and safe non-interactive flows may auto-select the recommended validated model diff --git a/docs/how-it-works.md b/docs/how-it-works.md index 08683ad..db9f539 100644 --- a/docs/how-it-works.md +++ b/docs/how-it-works.md @@ -16,7 +16,7 @@ The runtime is implemented and shipped. Today the repository ships: - the public CLI -- the public curated model picker UI, which currently exposes two validated +- the public curated model picker UI, which currently exposes three validated models - a managed GonkaGate provider catalog that writes every validated curated model into `provider.gonkagate.models` so OpenCode's `/models` command can @@ -33,13 +33,14 @@ Current validated picker entries: - `qwen/qwen3-235b-a22b-instruct-2507-fp8` - `moonshotai/Kimi-K2.6` +- `minimaxai/minimax-m2.7` ## Install Flow 1. Check that `opencode` is available and that the installed version is at least `1.4.0`. 2. Show the public curated model picker in interactive mode. The current picker - contains two validated models and one recommended default. + contains three validated models and one recommended default. 3. Recommend `project` scope inside a git repository and `user` scope otherwise. 4. Accept a GonkaGate API key through: diff --git a/docs/model-validation.md b/docs/model-validation.md index 6d70d93..3d0903b 100644 --- a/docs/model-validation.md +++ b/docs/model-validation.md @@ -41,6 +41,15 @@ picker. - adapter package: `@ai-sdk/openai-compatible` - recommended: `true` +### MiniMax M2.7 + +- display name: `MiniMax M2.7` +- key: `minimax-m2.7` +- model id: `minimaxai/minimax-m2.7` +- transport: `chat_completions` +- adapter package: `@ai-sdk/openai-compatible` +- recommended: `false` + ## Notes - v1 explicitly writes both `model` and `small_model` to the same selected diff --git a/docs/show-and-tell-opencode-setup.md b/docs/show-and-tell-opencode-setup.md index 3934287..1c3b9b6 100644 --- a/docs/show-and-tell-opencode-setup.md +++ b/docs/show-and-tell-opencode-setup.md @@ -97,13 +97,14 @@ files, and does not mutate shell profiles. ## Models right now -The public picker is deliberately small right now. It has two validated +The public picker is deliberately small right now. It has three validated options: | Status | Model | | ---------------------------- | ---------------------------------------- | | Recommended validated option | `moonshotai/Kimi-K2.6` | | Additional validated option | `qwen/qwen3-235b-a22b-instruct-2507-fp8` | +| Additional validated option | `minimaxai/minimax-m2.7` | We are treating this as a curated list, not a free-form custom model box. More options can be added as they pass the same OpenCode validation path. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index b35e8e2..a7bb865 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -84,6 +84,7 @@ The current public validated entries are: - `qwen/qwen3-235b-a22b-instruct-2507-fp8` - `moonshotai/Kimi-K2.6` +- `minimaxai/minimax-m2.7` Interactive mode still keeps that public picker visible, so more validated models can be added later without changing the CLI contract. diff --git a/src/constants/models.ts b/src/constants/models.ts index 2acc20a..e48c5b2 100644 --- a/src/constants/models.ts +++ b/src/constants/models.ts @@ -111,6 +111,14 @@ export const CURATED_MODEL_REGISTRY = Object.freeze({ transport: "chat_completions", validationStatus: "validated", }, + "minimax-m2.7": { + adapterPackage: "@ai-sdk/openai-compatible", + displayName: "MiniMax M2.7", + modelId: "minimaxai/minimax-m2.7", + recommended: false, + transport: "chat_completions", + validationStatus: "validated", + }, } as const satisfies CuratedModelRegistry); function toCuratedModelRecord< diff --git a/test/cli.test.ts b/test/cli.test.ts index b9e98a4..3ab07dd 100644 --- a/test/cli.test.ts +++ b/test/cli.test.ts @@ -22,6 +22,7 @@ import { createInstallIntegrationHarness } from "./install/harness.js"; const MODEL_KEY = "qwen3-235b-a22b-instruct-2507-fp8" as const; const KIMI_MODEL_KEY = "kimi-k2.6" as const; +const MINIMAX_MODEL_KEY = "minimax-m2.7" as const; const RECOMMENDED_MODEL_KEY = KIMI_MODEL_KEY; type TestSelectOption = ( @@ -239,6 +240,7 @@ test("interactive runs show the public model picker with the validated models", assert.deepEqual(promptChoiceSnapshots[0], [ "Qwen3 235B A22B Instruct 2507 FP8", "Kimi K2.6 (Recommended)", + "MiniMax M2.7", ]); assert.match( promptMessages[1] ?? "", @@ -346,6 +348,34 @@ test("CLI accepts Kimi K2.6 as an explicit curated model selection", async () => } }); +test("CLI accepts MiniMax M2.7 as an explicit curated model selection", async () => { + const fixture = await createCliFixture({ + debugConfigPureOutput: createResolvedConfigFixture({ + modelKey: MINIMAX_MODEL_KEY, + }), + }); + + try { + const result = await run( + ["--json", "--yes", "--model", MINIMAX_MODEL_KEY], + { + dependencies: fixture.dependencies, + stderr: fixture.stderr, + stdout: fixture.stdout, + }, + ); + + assert.equal(result.exitCode, 0); + assert.match(fixture.stdout.contents, /"status": "success"/); + assert.match( + fixture.stdout.contents, + new RegExp(escapeRegExp('"modelRef": "gonkagate/minimax-m2.7"')), + ); + } finally { + await fixture.harness.cleanup(); + } +}); + test("CLI emits structured JSON success payloads for the real installer flow", async () => { const fixture = await createCliFixture(); diff --git a/test/docs-contract.test.ts b/test/docs-contract.test.ts index 42736c9..2ba2755 100644 --- a/test/docs-contract.test.ts +++ b/test/docs-contract.test.ts @@ -30,6 +30,7 @@ test("README captures the shipped runtime truth and current opencode contract", /public curated model picker/i, /qwen\/qwen3-235b-a22b-instruct-2507-fp8/, /moonshotai\/Kimi-K2\.6/, + /minimaxai\/minimax-m2\.7/, /rerunning the installer is the official safe update path/i, /lastDurableSetupAt/, /durably verified setup/i, @@ -78,6 +79,7 @@ test("AGENTS captures the repository contract anchors for the shipped runtime", /end-to-end public installer flow is implemented/i, /public curated model picker is shipped/i, /moonshotai\/Kimi-K2\.6/, + /minimaxai\/minimax-m2\.7/, /effective OpenCode config/i, /current session's runtime-resolved outcome/i, /lastDurableSetupAt/, @@ -130,6 +132,7 @@ test("implementation docs capture the shipped setup architecture and boundaries" /runtime is implemented and shipped/i, /public curated model picker/i, /moonshotai\/Kimi-K2\.6/, + /minimaxai\/minimax-m2\.7/, /rollback/i, /run directly on Windows|native Windows/i, /Windows CI|native Windows CI|integration tests/i, @@ -151,6 +154,7 @@ test("implementation docs capture the shipped setup architecture and boundaries" new RegExp(escapeRegExp(FUTURE_TRANSPORT)), /public model picker only show curated options/i, /moonshotai\/Kimi-K2\.6/, + /minimaxai\/minimax-m2\.7/, /durable plain-`opencode` result/i, /lastDurableSetupAt/, /scope.*--yes/i, @@ -271,6 +275,9 @@ test("model validation doc matches the shipped small_model and picker contract", /kimi-k2\.6/, /moonshotai\/Kimi-K2\.6/, /Kimi K2\.6[\s\S]*recommended: `true`/i, + /minimax-m2\.7/, + /minimaxai\/minimax-m2\.7/, + /MiniMax M2\.7[\s\S]*recommended: `false`/i, /@ai-sdk\/openai-compatible/, /writes both `model` and `small_model`/i, /provider\.gonkagate\.models[\s\S]*\/models|\/models[\s\S]*provider\.gonkagate\.models/i, diff --git a/test/install/managed-provider-config.test.ts b/test/install/managed-provider-config.test.ts index 7c00af7..8755cad 100644 --- a/test/install/managed-provider-config.test.ts +++ b/test/install/managed-provider-config.test.ts @@ -67,6 +67,11 @@ test("buildManagedProviderCatalogConfig exposes every validated model for OpenCo ); assert.ok(providerConfig.models["kimi-k2.6"] !== undefined); assert.equal(providerConfig.models["kimi-k2.6"]?.id, "moonshotai/Kimi-K2.6"); + assert.ok(providerConfig.models["minimax-m2.7"] !== undefined); + assert.equal( + providerConfig.models["minimax-m2.7"]?.id, + "minimaxai/minimax-m2.7", + ); }); test("buildManagedProviderConfig rejects compatibility metadata that conflicts with canonical provider keys", () => { diff --git a/test/install/models.test.ts b/test/install/models.test.ts index 28bb561..fa7696f 100644 --- a/test/install/models.test.ts +++ b/test/install/models.test.ts @@ -13,12 +13,15 @@ import { test("the default curated registry exposes validated entries through the validated-model helpers", () => { const validatedModels = getValidatedModels(); - assert.equal(validatedModels.length, 2); + assert.equal(validatedModels.length, 3); assert.equal(validatedModels[0]?.key, "qwen3-235b-a22b-instruct-2507-fp8"); assert.equal(validatedModels[0]?.validationStatus, "validated"); assert.equal(validatedModels[1]?.key, "kimi-k2.6"); assert.equal(validatedModels[1]?.modelId, "moonshotai/Kimi-K2.6"); assert.equal(validatedModels[1]?.validationStatus, "validated"); + assert.equal(validatedModels[2]?.key, "minimax-m2.7"); + assert.equal(validatedModels[2]?.modelId, "minimaxai/minimax-m2.7"); + assert.equal(validatedModels[2]?.validationStatus, "validated"); }); test("createCuratedModelIndex derives keyed records and picks the recommended validated model by metadata", () => { @@ -96,6 +99,10 @@ test("the formatted OpenCode model reference uses the stable provider/model key "gonkagate/qwen3-235b-a22b-instruct-2507-fp8", ); assert.equal(formatOpencodeModelRef("kimi-k2.6"), "gonkagate/kimi-k2.6"); + assert.equal( + formatOpencodeModelRef("minimax-m2.7"), + "gonkagate/minimax-m2.7", + ); }); test("the curated model contract can carry compatibility and migration metadata", () => { @@ -135,7 +142,8 @@ test("the curated model contract can carry compatibility and migration metadata" test("the shipped registry stays wired through the default derived index", () => { const index = createCuratedModelIndex(CURATED_MODEL_REGISTRY); - assert.equal(index.models.length, 2); + assert.equal(index.models.length, 3); assert.equal(index.models[0]?.key, "qwen3-235b-a22b-instruct-2507-fp8"); assert.equal(index.models[1]?.key, "kimi-k2.6"); + assert.equal(index.models[2]?.key, "minimax-m2.7"); }); diff --git a/test/install/verify-effective.test.ts b/test/install/verify-effective.test.ts index 22db0a2..06d440c 100644 --- a/test/install/verify-effective.test.ts +++ b/test/install/verify-effective.test.ts @@ -1098,7 +1098,7 @@ test("verifyEffectiveConfig requires the full GonkaGate model catalog", async () const provider = (config.provider as Record) .gonkagate as Record; const models = provider.models as Record; - delete models["kimi-k2.6"]; + delete models["minimax-m2.7"]; }), }); @@ -1117,7 +1117,7 @@ test("verifyEffectiveConfig requires the full GonkaGate model catalog", async () assert.equal( error.details.mismatches.some( (mismatch) => - mismatch.key === "provider.gonkagate.models.kimi-k2.6", + mismatch.key === "provider.gonkagate.models.minimax-m2.7", ), true, );