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
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions docs/model-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion docs/show-and-tell-opencode-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions src/constants/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
30 changes: 30 additions & 0 deletions test/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <TValue extends string>(
Expand Down Expand Up @@ -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] ?? "",
Expand Down Expand Up @@ -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();

Expand Down
7 changes: 7 additions & 0 deletions test/docs-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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/,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions test/install/managed-provider-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
12 changes: 10 additions & 2 deletions test/install/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down Expand Up @@ -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", () => {
Expand Down Expand Up @@ -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");
});
4 changes: 2 additions & 2 deletions test/install/verify-effective.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ test("verifyEffectiveConfig requires the full GonkaGate model catalog", async ()
const provider = (config.provider as Record<string, unknown>)
.gonkagate as Record<string, unknown>;
const models = provider.models as Record<string, unknown>;
delete models["kimi-k2.6"];
delete models["minimax-m2.7"];
}),
});

Expand All @@ -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,
);
Expand Down
Loading