From 602dfe2978a95e04bec2fe9ea71577009dbaf14c Mon Sep 17 00:00:00 2001 From: Daniil Koryto Date: Fri, 29 May 2026 21:27:54 +0300 Subject: [PATCH] feat: add MiniMax M2.7 model --- AGENTS.md | 1 + CHANGELOG.md | 1 + README.md | 1 + src/constants/models.ts | 7 +++++++ test/gonkagate-models.test.ts | 17 +++++++++++++++-- test/install-use-case.test.ts | 2 +- test/models.test.ts | 8 ++++++-- 7 files changed, 32 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7766b54..08406d9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,6 +80,7 @@ Current honest limitation: - the curated registry currently contains these supported models: - `qwen3-235b` -> `qwen/qwen3-235b-a22b-instruct-2507-fp8` - `kimi-k2.6` -> `moonshotai/kimi-k2.6` (default) + - `minimax-m2.7` -> `minimaxai/minimax-m2.7` ## What the Repo Does and Does Not Do diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cbf419..29a695a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ ## [Unreleased] +- Added `minimaxai/minimax-m2.7` to the curated GonkaGate model registry under the `minimax-m2.7` model key. - Added `moonshotai/kimi-k2.6` to the curated GonkaGate model registry under the `kimi-k2.6` model key and made it the default model. - The installer now fetches GonkaGate `GET /v1/models` after API key entry, requires every curated model to be live, and uses the live metadata for OpenClaw provider model catalog entries. - The installer now creates or updates `agents.defaults.models` with the curated GonkaGate allowlist so OpenClaw `/models` can switch between supported models. diff --git a/README.md b/README.md index 093b52c..2ba60e2 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Current curated registry in this package: - `qwen3-235b` -> `qwen/qwen3-235b-a22b-instruct-2507-fp8` - `kimi-k2.6` -> `moonshotai/kimi-k2.6` (default) +- `minimax-m2.7` -> `minimaxai/minimax-m2.7` ## What It Does diff --git a/src/constants/models.ts b/src/constants/models.ts index 4082b0b..86150c6 100644 --- a/src/constants/models.ts +++ b/src/constants/models.ts @@ -22,6 +22,13 @@ const curatedModelRegistry = [ modelId: "moonshotai/kimi-k2.6", description: "Recommended default for long-horizon coding and agentic workflows on GonkaGate.", isDefault: true + }, + { + key: "minimax-m2.7", + displayName: "MiniMax M2.7", + modelId: "minimaxai/minimax-m2.7", + description: "MiniMax model on GonkaGate.", + isDefault: false } ] as const satisfies readonly SupportedModelDefinition[]; diff --git a/test/gonkagate-models.test.ts b/test/gonkagate-models.test.ts index 8995bca..6a6b5b0 100644 --- a/test/gonkagate-models.test.ts +++ b/test/gonkagate-models.test.ts @@ -32,6 +32,11 @@ test("fetchCuratedGonkaGateModelCatalog fetches and maps live curated model meta name: "Unsupported", object: "model" }, + { + id: "minimaxai/minimax-m2.7", + name: "MiniMax M2.7 Live", + object: "model" + }, { context_length: 262144, id: "qwen/qwen3-235b-a22b-instruct-2507-fp8", @@ -47,7 +52,7 @@ test("fetchCuratedGonkaGateModelCatalog fetches and maps live curated model meta assert.equal(capturedUrl, "https://api.gonkagate.com/v1/models"); assert.equal(capturedAuthorization, "Bearer gp-test-key"); - assert.deepEqual(catalog.map((entry) => entry.model.key), ["qwen3-235b", "kimi-k2.6"]); + assert.deepEqual(catalog.map((entry) => entry.model.key), ["qwen3-235b", "kimi-k2.6", "minimax-m2.7"]); assert.deepEqual(catalog[0]?.providerModel, { contextWindow: 262144, id: "qwen/qwen3-235b-a22b-instruct-2507-fp8", @@ -57,6 +62,10 @@ test("fetchCuratedGonkaGateModelCatalog fetches and maps live curated model meta id: "moonshotai/kimi-k2.6", name: "Kimi K2.6 Live" }); + assert.deepEqual(catalog[2]?.providerModel, { + id: "minimaxai/minimax-m2.7", + name: "MiniMax M2.7 Live" + }); }); test("fetchCuratedGonkaGateModelCatalog retries temporary catalog unavailability", async () => { @@ -82,6 +91,9 @@ test("fetchCuratedGonkaGateModelCatalog retries temporary catalog unavailability }, { id: "qwen/qwen3-235b-a22b-instruct-2507-fp8" + }, + { + id: "minimaxai/minimax-m2.7" } ] }) @@ -92,7 +104,7 @@ test("fetchCuratedGonkaGateModelCatalog retries temporary catalog unavailability }); assert.equal(calls, 2); - assert.deepEqual(catalog.map((entry) => entry.model.key), ["qwen3-235b", DEFAULT_MODEL.key]); + assert.deepEqual(catalog.map((entry) => entry.model.key), ["qwen3-235b", DEFAULT_MODEL.key, "minimax-m2.7"]); }); test("fetchCuratedGonkaGateModelCatalog rejects invalid API keys before config writes", async () => { @@ -160,6 +172,7 @@ test("fetchCuratedGonkaGateModelCatalog rejects catalogs that omit a curated sup assert.ok(error instanceof GonkaGateModelsError); assert.equal(error.kind, "missing_supported_models"); assert.match(error.message, /moonshotai\/kimi-k2\.6/); + assert.match(error.message, /minimaxai\/minimax-m2\.7/); return true; } ); diff --git a/test/install-use-case.test.ts b/test/install-use-case.test.ts index 0352832..2a1396e 100644 --- a/test/install-use-case.test.ts +++ b/test/install-use-case.test.ts @@ -681,7 +681,7 @@ test("runInstallUseCase prompts with the curated models returned by the live Gon targetPath: "/tmp/openclaw.json" }, dependencies); - assert.deepEqual(promptModels, ["qwen3-235b", "kimi-k2.6"]); + assert.deepEqual(promptModels, ["qwen3-235b", "kimi-k2.6", "minimax-m2.7"]); assert.equal(promptDefaultModelKey, DEFAULT_MODEL_KEY); assert.equal(state.writeCalls, 1); assert.deepEqual(((state.writtenSettings?.agents as Record).defaults as Record).model, { diff --git a/test/models.test.ts b/test/models.test.ts index 0406833..ea2b8a8 100644 --- a/test/models.test.ts +++ b/test/models.test.ts @@ -9,16 +9,20 @@ import { toPrimaryModelRef } from "../src/constants/models.js"; -test("curated registry includes Kimi K2.6 as the default model", () => { +test("curated registry includes Kimi K2.6 as the default model and MiniMax M2.7", () => { assert.equal(DEFAULT_MODEL_KEY, "kimi-k2.6"); assert.equal(DEFAULT_MODEL.modelId, "moonshotai/kimi-k2.6"); - assert.deepEqual(SUPPORTED_MODEL_KEYS, ["qwen3-235b", "kimi-k2.6"]); + assert.deepEqual(SUPPORTED_MODEL_KEYS, ["qwen3-235b", "kimi-k2.6", "minimax-m2.7"]); const kimi = requireSupportedModel("kimi-k2.6"); + const minimax = requireSupportedModel("minimax-m2.7"); assert.equal(kimi.displayName, "Kimi K2.6"); assert.equal(kimi.modelId, "moonshotai/kimi-k2.6"); assert.equal(toPrimaryModelRef(kimi), "openai/moonshotai/kimi-k2.6"); + assert.equal(minimax.displayName, "MiniMax M2.7"); + assert.equal(minimax.modelId, "minimaxai/minimax-m2.7"); + assert.equal(toPrimaryModelRef(minimax), "openai/minimaxai/minimax-m2.7"); assert.equal(DEFAULT_MODEL, kimi); assert.equal(getSupportedModelByKey("missing-model"), undefined); });