MiniMax: add M2.7 models and update default to M2.7 (#49691)
* MiniMax: add M2.7 models and update default to M2.7 - Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to provider catalog and model definitions - Update default model from MiniMax-M2.5 to MiniMax-M2.7 across onboard, portal, and provider configs - Update isModernMiniMaxModel to recognize M2.7 prefix - Update all test fixtures to reflect M2.7 as default Made-with: Cursor * MiniMax: add extension test for model definitions * update 2.7 * feat: add MiniMax M2.7 models and update default (#49691) (thanks @liyuan97) --------- Co-authored-by: George Zhang <georgezhangtj97@gmail.com>
This commit is contained in:
parent
823a09acbe
commit
b64f4e313d
@ -42,6 +42,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Control UI/appearance: unify theme border radii across Claw, Knot, and Dash, and add a Roundness slider to the Appearance settings so users can adjust corner radius from sharp to fully rounded. Thanks @BunsDev.
|
||||
- Control UI/chat: add an expand-to-canvas button on assistant chat bubbles and in-app session navigation from Sessions and Cron views. Thanks @BunsDev.
|
||||
- Plugins/context engines: expose `delegateCompactionToRuntime(...)` on the public plugin SDK, refactor the legacy engine to use the shared helper, and clarify `ownsCompaction` delegation semantics for non-owning engines. (#49061) Thanks @jalehman.
|
||||
- Plugins/MiniMax: add MiniMax-M2.7 and MiniMax-M2.7-highspeed models and update the default model from M2.5 to M2.7. (#49691) Thanks @liyuan97.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ import { buildMinimaxPortalProvider, buildMinimaxProvider } from "./provider-cat
|
||||
const API_PROVIDER_ID = "minimax";
|
||||
const PORTAL_PROVIDER_ID = "minimax-portal";
|
||||
const PROVIDER_LABEL = "MiniMax";
|
||||
const DEFAULT_MODEL = "MiniMax-M2.5";
|
||||
const DEFAULT_MODEL = "MiniMax-M2.7";
|
||||
const DEFAULT_BASE_URL_CN = "https://api.minimaxi.com/anthropic";
|
||||
const DEFAULT_BASE_URL_GLOBAL = "https://api.minimax.io/anthropic";
|
||||
|
||||
@ -40,7 +40,8 @@ function portalModelRef(modelId: string): string {
|
||||
}
|
||||
|
||||
function isModernMiniMaxModel(modelId: string): boolean {
|
||||
return modelId.trim().toLowerCase().startsWith("minimax-m2.5");
|
||||
const lower = modelId.trim().toLowerCase();
|
||||
return lower.startsWith("minimax-m2.7") || lower.startsWith("minimax-m2.5");
|
||||
}
|
||||
|
||||
function buildPortalProviderCatalog(params: { baseUrl: string; apiKey: string }) {
|
||||
@ -129,6 +130,10 @@ function createOAuthHandler(region: MiniMaxRegion) {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
[portalModelRef("MiniMax-M2.7")]: { alias: "minimax-m2.7" },
|
||||
[portalModelRef("MiniMax-M2.7-highspeed")]: {
|
||||
alias: "minimax-m2.7-highspeed",
|
||||
},
|
||||
[portalModelRef("MiniMax-M2.5")]: { alias: "minimax-m2.5" },
|
||||
[portalModelRef("MiniMax-M2.5-highspeed")]: {
|
||||
alias: "minimax-m2.5-highspeed",
|
||||
@ -190,7 +195,7 @@ export default definePluginEntry({
|
||||
choiceHint: "Global endpoint - api.minimax.io",
|
||||
groupId: "minimax",
|
||||
groupLabel: "MiniMax",
|
||||
groupHint: "M2.5 (recommended)",
|
||||
groupHint: "M2.7 (recommended)",
|
||||
},
|
||||
}),
|
||||
createProviderApiKeyAuthMethod({
|
||||
@ -214,7 +219,7 @@ export default definePluginEntry({
|
||||
choiceHint: "CN endpoint - api.minimaxi.com",
|
||||
groupId: "minimax",
|
||||
groupLabel: "MiniMax",
|
||||
groupHint: "M2.5 (recommended)",
|
||||
groupHint: "M2.7 (recommended)",
|
||||
},
|
||||
}),
|
||||
],
|
||||
@ -253,7 +258,7 @@ export default definePluginEntry({
|
||||
choiceHint: "Global endpoint - api.minimax.io",
|
||||
groupId: "minimax",
|
||||
groupLabel: "MiniMax",
|
||||
groupHint: "M2.5 (recommended)",
|
||||
groupHint: "M2.7 (recommended)",
|
||||
},
|
||||
run: createOAuthHandler("global"),
|
||||
},
|
||||
@ -268,7 +273,7 @@ export default definePluginEntry({
|
||||
choiceHint: "CN endpoint - api.minimaxi.com",
|
||||
groupId: "minimax",
|
||||
groupLabel: "MiniMax",
|
||||
groupHint: "M2.5 (recommended)",
|
||||
groupHint: "M2.7 (recommended)",
|
||||
},
|
||||
run: createOAuthHandler("cn"),
|
||||
},
|
||||
|
||||
42
extensions/minimax/model-definitions.test.ts
Normal file
42
extensions/minimax/model-definitions.test.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
buildMinimaxApiModelDefinition,
|
||||
buildMinimaxModelDefinition,
|
||||
DEFAULT_MINIMAX_CONTEXT_WINDOW,
|
||||
DEFAULT_MINIMAX_MAX_TOKENS,
|
||||
MINIMAX_API_COST,
|
||||
MINIMAX_HOSTED_MODEL_ID,
|
||||
} from "./model-definitions.js";
|
||||
|
||||
describe("minimax model definitions", () => {
|
||||
it("uses M2.7 as default hosted model", () => {
|
||||
expect(MINIMAX_HOSTED_MODEL_ID).toBe("MiniMax-M2.7");
|
||||
});
|
||||
|
||||
it("builds catalog model with name and reasoning from catalog", () => {
|
||||
const model = buildMinimaxModelDefinition({
|
||||
id: "MiniMax-M2.7",
|
||||
cost: MINIMAX_API_COST,
|
||||
contextWindow: DEFAULT_MINIMAX_CONTEXT_WINDOW,
|
||||
maxTokens: DEFAULT_MINIMAX_MAX_TOKENS,
|
||||
});
|
||||
expect(model).toMatchObject({
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("builds API model definition with standard cost", () => {
|
||||
const model = buildMinimaxApiModelDefinition("MiniMax-M2.7");
|
||||
expect(model.cost).toEqual(MINIMAX_API_COST);
|
||||
expect(model.contextWindow).toBe(DEFAULT_MINIMAX_CONTEXT_WINDOW);
|
||||
expect(model.maxTokens).toBe(DEFAULT_MINIMAX_MAX_TOKENS);
|
||||
});
|
||||
|
||||
it("falls back to generated name for unknown model id", () => {
|
||||
const model = buildMinimaxApiModelDefinition("MiniMax-Future");
|
||||
expect(model.name).toBe("MiniMax MiniMax-Future");
|
||||
expect(model.reasoning).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -3,7 +3,7 @@ import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-models"
|
||||
export const DEFAULT_MINIMAX_BASE_URL = "https://api.minimax.io/v1";
|
||||
export const MINIMAX_API_BASE_URL = "https://api.minimax.io/anthropic";
|
||||
export const MINIMAX_CN_API_BASE_URL = "https://api.minimaxi.com/anthropic";
|
||||
export const MINIMAX_HOSTED_MODEL_ID = "MiniMax-M2.5";
|
||||
export const MINIMAX_HOSTED_MODEL_ID = "MiniMax-M2.7";
|
||||
export const MINIMAX_HOSTED_MODEL_REF = `minimax/${MINIMAX_HOSTED_MODEL_ID}`;
|
||||
export const DEFAULT_MINIMAX_CONTEXT_WINDOW = 200000;
|
||||
export const DEFAULT_MINIMAX_MAX_TOKENS = 8192;
|
||||
@ -28,6 +28,8 @@ export const MINIMAX_LM_STUDIO_COST = {
|
||||
};
|
||||
|
||||
const MINIMAX_MODEL_CATALOG = {
|
||||
"MiniMax-M2.7": { name: "MiniMax M2.7", reasoning: true },
|
||||
"MiniMax-M2.7-highspeed": { name: "MiniMax M2.7 Highspeed", reasoning: true },
|
||||
"MiniMax-M2.5": { name: "MiniMax M2.5", reasoning: true },
|
||||
"MiniMax-M2.5-highspeed": { name: "MiniMax M2.5 Highspeed", reasoning: true },
|
||||
} as const;
|
||||
|
||||
@ -61,7 +61,7 @@ function applyMinimaxApiConfigWithBaseUrl(
|
||||
|
||||
export function applyMinimaxApiProviderConfig(
|
||||
cfg: OpenClawConfig,
|
||||
modelId: string = "MiniMax-M2.5",
|
||||
modelId: string = "MiniMax-M2.7",
|
||||
): OpenClawConfig {
|
||||
return applyMinimaxApiProviderConfigWithBaseUrl(cfg, {
|
||||
providerId: "minimax",
|
||||
@ -72,7 +72,7 @@ export function applyMinimaxApiProviderConfig(
|
||||
|
||||
export function applyMinimaxApiConfig(
|
||||
cfg: OpenClawConfig,
|
||||
modelId: string = "MiniMax-M2.5",
|
||||
modelId: string = "MiniMax-M2.7",
|
||||
): OpenClawConfig {
|
||||
return applyMinimaxApiConfigWithBaseUrl(cfg, {
|
||||
providerId: "minimax",
|
||||
@ -83,7 +83,7 @@ export function applyMinimaxApiConfig(
|
||||
|
||||
export function applyMinimaxApiProviderConfigCn(
|
||||
cfg: OpenClawConfig,
|
||||
modelId: string = "MiniMax-M2.5",
|
||||
modelId: string = "MiniMax-M2.7",
|
||||
): OpenClawConfig {
|
||||
return applyMinimaxApiProviderConfigWithBaseUrl(cfg, {
|
||||
providerId: "minimax",
|
||||
@ -94,7 +94,7 @@ export function applyMinimaxApiProviderConfigCn(
|
||||
|
||||
export function applyMinimaxApiConfigCn(
|
||||
cfg: OpenClawConfig,
|
||||
modelId: string = "MiniMax-M2.5",
|
||||
modelId: string = "MiniMax-M2.7",
|
||||
): OpenClawConfig {
|
||||
return applyMinimaxApiConfigWithBaseUrl(cfg, {
|
||||
providerId: "minimax",
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"choiceHint": "Global endpoint - api.minimax.io",
|
||||
"groupId": "minimax",
|
||||
"groupLabel": "MiniMax",
|
||||
"groupHint": "M2.5 (recommended)"
|
||||
"groupHint": "M2.7 (recommended)"
|
||||
},
|
||||
{
|
||||
"provider": "minimax",
|
||||
@ -24,7 +24,7 @@
|
||||
"choiceHint": "Global endpoint - api.minimax.io",
|
||||
"groupId": "minimax",
|
||||
"groupLabel": "MiniMax",
|
||||
"groupHint": "M2.5 (recommended)",
|
||||
"groupHint": "M2.7 (recommended)",
|
||||
"optionKey": "minimaxApiKey",
|
||||
"cliFlag": "--minimax-api-key",
|
||||
"cliOption": "--minimax-api-key <key>",
|
||||
@ -38,7 +38,7 @@
|
||||
"choiceHint": "CN endpoint - api.minimaxi.com",
|
||||
"groupId": "minimax",
|
||||
"groupLabel": "MiniMax",
|
||||
"groupHint": "M2.5 (recommended)"
|
||||
"groupHint": "M2.7 (recommended)"
|
||||
},
|
||||
{
|
||||
"provider": "minimax",
|
||||
@ -48,7 +48,7 @@
|
||||
"choiceHint": "CN endpoint - api.minimaxi.com",
|
||||
"groupId": "minimax",
|
||||
"groupLabel": "MiniMax",
|
||||
"groupHint": "M2.5 (recommended)",
|
||||
"groupHint": "M2.7 (recommended)",
|
||||
"optionKey": "minimaxApiKey",
|
||||
"cliFlag": "--minimax-api-key",
|
||||
"cliOption": "--minimax-api-key <key>",
|
||||
|
||||
@ -4,7 +4,7 @@ import type {
|
||||
} from "openclaw/plugin-sdk/provider-models";
|
||||
|
||||
const MINIMAX_PORTAL_BASE_URL = "https://api.minimax.io/anthropic";
|
||||
export const MINIMAX_DEFAULT_MODEL_ID = "MiniMax-M2.5";
|
||||
export const MINIMAX_DEFAULT_MODEL_ID = "MiniMax-M2.7";
|
||||
const MINIMAX_DEFAULT_VISION_MODEL_ID = "MiniMax-VL-01";
|
||||
const MINIMAX_DEFAULT_CONTEXT_WINDOW = 200000;
|
||||
const MINIMAX_DEFAULT_MAX_TOKENS = 8192;
|
||||
@ -50,6 +50,16 @@ function buildMinimaxCatalog(): ModelDefinitionConfig[] {
|
||||
}),
|
||||
buildMinimaxTextModel({
|
||||
id: MINIMAX_DEFAULT_MODEL_ID,
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: true,
|
||||
}),
|
||||
buildMinimaxTextModel({
|
||||
id: "MiniMax-M2.7-highspeed",
|
||||
name: "MiniMax M2.7 Highspeed",
|
||||
reasoning: true,
|
||||
}),
|
||||
buildMinimaxTextModel({
|
||||
id: "MiniMax-M2.5",
|
||||
name: "MiniMax M2.5",
|
||||
reasoning: true,
|
||||
}),
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
describe("live model error helpers", () => {
|
||||
it("detects generic model-not-found messages", () => {
|
||||
expect(isModelNotFoundErrorMessage('{"code":404,"message":"model not found"}')).toBe(true);
|
||||
expect(isModelNotFoundErrorMessage("model: MiniMax-M2.5-highspeed not found")).toBe(true);
|
||||
expect(isModelNotFoundErrorMessage("model: MiniMax-M2.7-highspeed not found")).toBe(true);
|
||||
expect(isModelNotFoundErrorMessage("request ended without sending any chunks")).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { isTruthyEnvValue } from "../infra/env.js";
|
||||
|
||||
const MINIMAX_KEY = process.env.MINIMAX_API_KEY ?? "";
|
||||
const MINIMAX_BASE_URL = process.env.MINIMAX_BASE_URL?.trim() || "https://api.minimax.io/anthropic";
|
||||
const MINIMAX_MODEL = process.env.MINIMAX_MODEL?.trim() || "MiniMax-M2.5";
|
||||
const MINIMAX_MODEL = process.env.MINIMAX_MODEL?.trim() || "MiniMax-M2.7";
|
||||
const LIVE = isTruthyEnvValue(process.env.MINIMAX_LIVE_TEST) || isTruthyEnvValue(process.env.LIVE);
|
||||
|
||||
const describeLive = LIVE && MINIMAX_KEY ? describe : describe.skip;
|
||||
|
||||
@ -368,14 +368,14 @@ describe("isModernModelRef", () => {
|
||||
expect(isModernModelRef({ provider: "opencode", id: "gemini-3-pro" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode-go", id: "kimi-k2.5" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode-go", id: "glm-5" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode-go", id: "minimax-m2.5" })).toBe(true);
|
||||
expect(isModernModelRef({ provider: "opencode-go", id: "minimax-m2.7" })).toBe(true);
|
||||
});
|
||||
|
||||
it("excludes provider-declined modern models", () => {
|
||||
providerRuntimeMocks.resolveProviderModernModelRef.mockImplementation(({ provider, context }) =>
|
||||
provider === "opencode" && context.modelId === "minimax-m2.5" ? false : undefined,
|
||||
provider === "opencode" && context.modelId === "minimax-m2.7" ? false : undefined,
|
||||
);
|
||||
|
||||
expect(isModernModelRef({ provider: "opencode", id: "minimax-m2.5" })).toBe(false);
|
||||
expect(isModernModelRef({ provider: "opencode", id: "minimax-m2.7" })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@ -308,8 +308,8 @@ describe("models-config", () => {
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "MiniMax-M2.5",
|
||||
name: "MiniMax M2.5",
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
@ -454,7 +454,7 @@ describe("models-config", () => {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
apiKey: "STALE_AGENT_KEY", // pragma: allowlist secret
|
||||
api: "anthropic-messages",
|
||||
models: [{ id: "MiniMax-M2.5", name: "MiniMax M2.5", input: ["text"] }],
|
||||
models: [{ id: "MiniMax-M2.7", name: "MiniMax M2.7", input: ["text"] }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -21,7 +21,7 @@ type ModelsJson = {
|
||||
};
|
||||
|
||||
const MINIMAX_ENV_KEY = "MINIMAX_API_KEY";
|
||||
const MINIMAX_MODEL_ID = "MiniMax-M2.5";
|
||||
const MINIMAX_MODEL_ID = "MiniMax-M2.7";
|
||||
const MINIMAX_TEST_KEY = "sk-minimax-test";
|
||||
|
||||
const baseMinimaxProvider = {
|
||||
@ -50,8 +50,8 @@ async function generateAndReadMinimaxModel(cfg: OpenClawConfig): Promise<ModelEn
|
||||
}
|
||||
|
||||
describe("models-config: explicit reasoning override", () => {
|
||||
it("preserves user reasoning:false when built-in catalog has reasoning:true (MiniMax-M2.5)", async () => {
|
||||
// MiniMax-M2.5 has reasoning:true in the built-in catalog.
|
||||
it("preserves user reasoning:false when built-in catalog has reasoning:true (MiniMax-M2.7)", async () => {
|
||||
// MiniMax-M2.7 has reasoning:true in the built-in catalog.
|
||||
// User explicitly sets reasoning:false to avoid message-ordering conflicts.
|
||||
await withTempHome(async () => {
|
||||
await withMinimaxApiKey(async () => {
|
||||
@ -63,7 +63,7 @@ describe("models-config: explicit reasoning override", () => {
|
||||
models: [
|
||||
{
|
||||
id: MINIMAX_MODEL_ID,
|
||||
name: "MiniMax M2.5",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: false, // explicit override: user wants to disable reasoning
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
@ -84,15 +84,15 @@ describe("models-config: explicit reasoning override", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to built-in reasoning:true when user omits the field (MiniMax-M2.5)", async () => {
|
||||
it("falls back to built-in reasoning:true when user omits the field (MiniMax-M2.7)", async () => {
|
||||
// When the user does not set reasoning at all, the built-in catalog value
|
||||
// (true for MiniMax-M2.5) should be used so the model works out of the box.
|
||||
// (true for MiniMax-M2.7) should be used so the model works out of the box.
|
||||
await withTempHome(async () => {
|
||||
await withMinimaxApiKey(async () => {
|
||||
// Omit 'reasoning' to simulate a user config that doesn't set it.
|
||||
const modelWithoutReasoning = {
|
||||
id: MINIMAX_MODEL_ID,
|
||||
name: "MiniMax M2.5",
|
||||
name: "MiniMax M2.7",
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 1_000_000,
|
||||
|
||||
@ -37,11 +37,15 @@ describe("minimax provider catalog", () => {
|
||||
const providers = await resolveImplicitProvidersForTest({ agentDir });
|
||||
expect(providers?.minimax?.models?.map((model) => model.id)).toEqual([
|
||||
"MiniMax-VL-01",
|
||||
"MiniMax-M2.7",
|
||||
"MiniMax-M2.7-highspeed",
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.5-highspeed",
|
||||
]);
|
||||
expect(providers?.["minimax-portal"]?.models?.map((model) => model.id)).toEqual([
|
||||
"MiniMax-VL-01",
|
||||
"MiniMax-M2.7",
|
||||
"MiniMax-M2.7-highspeed",
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.5-highspeed",
|
||||
]);
|
||||
|
||||
@ -98,7 +98,7 @@ describe("models-config", () => {
|
||||
providerKey: "minimax",
|
||||
expectedBaseUrl: "https://api.minimax.io/anthropic",
|
||||
expectedApiKeyRef: "MINIMAX_API_KEY", // pragma: allowlist secret
|
||||
expectedModelIds: ["MiniMax-M2.5", "MiniMax-VL-01"],
|
||||
expectedModelIds: ["MiniMax-M2.7", "MiniMax-VL-01"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -199,11 +199,11 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
await expectSpawnUsesConfiguredModel({
|
||||
config: {
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
agents: { defaults: { subagents: { model: "minimax/MiniMax-M2.5" } } },
|
||||
agents: { defaults: { subagents: { model: "minimax/MiniMax-M2.7" } } },
|
||||
},
|
||||
runId: "run-default-model",
|
||||
callId: "call-default-model",
|
||||
expectedModel: "minimax/MiniMax-M2.5",
|
||||
expectedModel: "minimax/MiniMax-M2.7",
|
||||
});
|
||||
});
|
||||
|
||||
@ -220,7 +220,7 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
config: {
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
agents: {
|
||||
defaults: { subagents: { model: "minimax/MiniMax-M2.5" } },
|
||||
defaults: { subagents: { model: "minimax/MiniMax-M2.7" } },
|
||||
list: [{ id: "research", subagents: { model: "opencode/claude" } }],
|
||||
},
|
||||
},
|
||||
@ -235,7 +235,7 @@ describe("openclaw-tools: subagents (sessions_spawn model + thinking)", () => {
|
||||
config: {
|
||||
session: { mainKey: "main", scope: "per-sender" },
|
||||
agents: {
|
||||
defaults: { model: { primary: "minimax/MiniMax-M2.5" } },
|
||||
defaults: { model: { primary: "minimax/MiniMax-M2.7" } },
|
||||
list: [{ id: "research", model: { primary: "opencode/claude" } }],
|
||||
},
|
||||
},
|
||||
|
||||
@ -685,7 +685,7 @@ describe("applyExtraParamsToAgent", () => {
|
||||
agent,
|
||||
undefined,
|
||||
"siliconflow",
|
||||
"Pro/MiniMaxAI/MiniMax-M2.5",
|
||||
"Pro/MiniMaxAI/MiniMax-M2.7",
|
||||
undefined,
|
||||
"off",
|
||||
);
|
||||
@ -693,7 +693,7 @@ describe("applyExtraParamsToAgent", () => {
|
||||
const model = {
|
||||
api: "openai-completions",
|
||||
provider: "siliconflow",
|
||||
id: "Pro/MiniMaxAI/MiniMax-M2.5",
|
||||
id: "Pro/MiniMaxAI/MiniMax-M2.7",
|
||||
} as Model<"openai-completions">;
|
||||
const context: Context = { messages: [] };
|
||||
void agent.streamFn?.(model, context, {});
|
||||
|
||||
@ -142,7 +142,7 @@ function createMinimaxImageConfig(): OpenClawConfig {
|
||||
return {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.5" },
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
imageModel: { primary: "minimax/MiniMax-VL-01" },
|
||||
},
|
||||
},
|
||||
@ -272,7 +272,7 @@ describe("image tool implicit imageModel config", () => {
|
||||
vi.stubEnv("OPENAI_API_KEY", "openai-test");
|
||||
vi.stubEnv("ANTHROPIC_API_KEY", "anthropic-test");
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.5" } } },
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.7" } } },
|
||||
};
|
||||
expect(resolveImageModelConfigForTool({ cfg, agentDir })).toEqual(
|
||||
createDefaultImageFallbackExpectation("minimax/MiniMax-VL-01"),
|
||||
@ -298,7 +298,7 @@ describe("image tool implicit imageModel config", () => {
|
||||
vi.stubEnv("OPENAI_API_KEY", "openai-test");
|
||||
vi.stubEnv("ANTHROPIC_API_KEY", "anthropic-test");
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: "minimax-portal/MiniMax-M2.5" } } },
|
||||
agents: { defaults: { model: { primary: "minimax-portal/MiniMax-M2.7" } } },
|
||||
};
|
||||
expect(resolveImageModelConfigForTool({ cfg, agentDir })).toEqual(
|
||||
createDefaultImageFallbackExpectation("minimax-portal/MiniMax-VL-01"),
|
||||
@ -356,7 +356,7 @@ describe("image tool implicit imageModel config", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.5" },
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
imageModel: { primary: "openai/gpt-5-mini" },
|
||||
},
|
||||
},
|
||||
@ -584,7 +584,7 @@ describe("image tool implicit imageModel config", () => {
|
||||
|
||||
vi.stubEnv("OPENAI_API_KEY", "openai-test");
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.5" } } },
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.7" } } },
|
||||
};
|
||||
const tool = createRequiredImageTool({ config: cfg, agentDir, sandbox });
|
||||
|
||||
@ -651,7 +651,7 @@ describe("image tool implicit imageModel config", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.5" },
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
imageModel: { primary: "minimax/MiniMax-VL-01" },
|
||||
},
|
||||
},
|
||||
@ -704,7 +704,7 @@ describe("image tool MiniMax VLM routing", () => {
|
||||
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-minimax-vlm-"));
|
||||
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
|
||||
const cfg: OpenClawConfig = {
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.5" } } },
|
||||
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.7" } } },
|
||||
};
|
||||
const tool = createRequiredImageTool({ config: cfg, agentDir });
|
||||
return { fetch, tool };
|
||||
|
||||
@ -183,7 +183,7 @@ describe("directive behavior", () => {
|
||||
primary: "anthropic/claude-opus-4-5",
|
||||
fallbacks: ["openai/gpt-4.1-mini"],
|
||||
},
|
||||
imageModel: { primary: "minimax/MiniMax-M2.5" },
|
||||
imageModel: { primary: "minimax/MiniMax-M2.7" },
|
||||
models: undefined,
|
||||
},
|
||||
});
|
||||
@ -206,7 +206,7 @@ describe("directive behavior", () => {
|
||||
models: {
|
||||
"anthropic/claude-opus-4-5": {},
|
||||
"openai/gpt-4.1-mini": {},
|
||||
"minimax/MiniMax-M2.5": { alias: "minimax" },
|
||||
"minimax/MiniMax-M2.7": { alias: "minimax" },
|
||||
},
|
||||
},
|
||||
extra: {
|
||||
@ -216,14 +216,17 @@ describe("directive behavior", () => {
|
||||
minimax: {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
api: "anthropic-messages",
|
||||
models: [{ id: "MiniMax-M2.5", name: "MiniMax M2.5" }],
|
||||
models: [
|
||||
{ id: "MiniMax-M2.7", name: "MiniMax M2.7" },
|
||||
{ id: "MiniMax-M2.5", name: "MiniMax M2.5" },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(configOnlyProviderText).toContain("Models (minimax");
|
||||
expect(configOnlyProviderText).toContain("minimax/MiniMax-M2.5");
|
||||
expect(configOnlyProviderText).toContain("minimax/MiniMax-M2.7");
|
||||
|
||||
const missingAuthText = await runModelDirectiveText(home, "/model list", {
|
||||
defaults: {
|
||||
|
||||
@ -119,9 +119,10 @@ describe("directive behavior", () => {
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.5" },
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
workspace: path.join(home, "openclaw"),
|
||||
models: {
|
||||
"minimax/MiniMax-M2.7": {},
|
||||
"minimax/MiniMax-M2.5": {},
|
||||
"minimax/MiniMax-M2.5-highspeed": {},
|
||||
"lmstudio/minimax-m2.5-gs32": {},
|
||||
@ -135,7 +136,10 @@ describe("directive behavior", () => {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
apiKey: "sk-test", // pragma: allowlist secret
|
||||
api: "anthropic-messages",
|
||||
models: [makeModelDefinition("MiniMax-M2.5", "MiniMax M2.5")],
|
||||
models: [
|
||||
makeModelDefinition("MiniMax-M2.7", "MiniMax M2.7"),
|
||||
makeModelDefinition("MiniMax-M2.5", "MiniMax M2.5"),
|
||||
],
|
||||
},
|
||||
lmstudio: {
|
||||
baseUrl: "http://127.0.0.1:1234/v1",
|
||||
@ -153,9 +157,10 @@ describe("directive behavior", () => {
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.5" },
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
workspace: path.join(home, "openclaw"),
|
||||
models: {
|
||||
"minimax/MiniMax-M2.7": {},
|
||||
"minimax/MiniMax-M2.5": {},
|
||||
"minimax/MiniMax-M2.5-highspeed": {},
|
||||
},
|
||||
@ -169,6 +174,7 @@ describe("directive behavior", () => {
|
||||
apiKey: "sk-test", // pragma: allowlist secret
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
makeModelDefinition("MiniMax-M2.7", "MiniMax M2.7"),
|
||||
makeModelDefinition("MiniMax-M2.5", "MiniMax M2.5"),
|
||||
makeModelDefinition("MiniMax-M2.5-highspeed", "MiniMax M2.5 Highspeed"),
|
||||
],
|
||||
|
||||
@ -80,7 +80,7 @@ const modelCatalogMocks = vi.hoisted(() => ({
|
||||
{ provider: "openai", id: "gpt-4.1-mini", name: "GPT-4.1 mini" },
|
||||
{ provider: "openai", id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ provider: "openai-codex", id: "gpt-5.2", name: "GPT-5.2 (Codex)" },
|
||||
{ provider: "minimax", id: "MiniMax-M2.5", name: "MiniMax M2.5" },
|
||||
{ provider: "minimax", id: "MiniMax-M2.7", name: "MiniMax M2.7" },
|
||||
]),
|
||||
resetModelCatalogCacheForTest: vi.fn(),
|
||||
}));
|
||||
|
||||
@ -24,7 +24,7 @@ vi.mock("../../agents/session-write-lock.js", () => ({
|
||||
|
||||
vi.mock("../../agents/model-catalog.js", () => ({
|
||||
loadModelCatalog: vi.fn(async () => [
|
||||
{ provider: "minimax", id: "m2.5", name: "M2.5" },
|
||||
{ provider: "minimax", id: "m2.7", name: "M2.7" },
|
||||
{ provider: "openai", id: "gpt-4o-mini", name: "GPT-4o mini" },
|
||||
]),
|
||||
}));
|
||||
@ -1288,7 +1288,7 @@ describe("applyResetModelOverride", () => {
|
||||
});
|
||||
|
||||
expect(sessionEntry.providerOverride).toBe("minimax");
|
||||
expect(sessionEntry.modelOverride).toBe("m2.5");
|
||||
expect(sessionEntry.modelOverride).toBe("m2.7");
|
||||
expect(sessionCtx.BodyStripped).toBe("summarize");
|
||||
});
|
||||
|
||||
|
||||
@ -1423,7 +1423,7 @@ describe("applyAuthChoice", () => {
|
||||
profileId: "minimax-portal:default",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
api: "anthropic-messages",
|
||||
defaultModel: "minimax-portal/MiniMax-M2.5",
|
||||
defaultModel: "minimax-portal/MiniMax-M2.7",
|
||||
apiKey: "minimax-oauth", // pragma: allowlist secret
|
||||
},
|
||||
];
|
||||
|
||||
@ -88,7 +88,7 @@ function createApplyAuthChoiceConfig(includeMinimaxProvider = false) {
|
||||
minimax: {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
api: "anthropic-messages",
|
||||
models: [{ id: "MiniMax-M2.5", name: "MiniMax M2.5" }],
|
||||
models: [{ id: "MiniMax-M2.7", name: "MiniMax M2.7" }],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
@ -127,7 +127,7 @@ describe("promptAuthConfig", () => {
|
||||
"anthropic/claude-sonnet-4",
|
||||
]);
|
||||
expect(result.models?.providers?.minimax?.models?.map((model) => model.id)).toEqual([
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.7",
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@ -386,8 +386,8 @@ describe("applyMinimaxApiConfig", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps reasoning enabled for MiniMax-M2.5", () => {
|
||||
const cfg = applyMinimaxApiConfig({}, "MiniMax-M2.5");
|
||||
it("keeps reasoning enabled for MiniMax-M2.7", () => {
|
||||
const cfg = applyMinimaxApiConfig({}, "MiniMax-M2.7");
|
||||
expect(cfg.models?.providers?.minimax?.models[0]?.reasoning).toBe(true);
|
||||
});
|
||||
|
||||
@ -397,7 +397,7 @@ describe("applyMinimaxApiConfig", () => {
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
"minimax/MiniMax-M2.5": {
|
||||
"minimax/MiniMax-M2.7": {
|
||||
alias: "MiniMax",
|
||||
params: { custom: "value" },
|
||||
},
|
||||
@ -405,9 +405,9 @@ describe("applyMinimaxApiConfig", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.7",
|
||||
);
|
||||
expect(cfg.agents?.defaults?.models?.["minimax/MiniMax-M2.5"]).toMatchObject({
|
||||
expect(cfg.agents?.defaults?.models?.["minimax/MiniMax-M2.7"]).toMatchObject({
|
||||
alias: "Minimax",
|
||||
params: { custom: "value" },
|
||||
});
|
||||
@ -426,7 +426,7 @@ describe("applyMinimaxApiConfig", () => {
|
||||
expect(cfg.models?.providers?.minimax?.apiKey).toBe("old-key");
|
||||
expect(cfg.models?.providers?.minimax?.models.map((m) => m.id)).toEqual([
|
||||
"old-model",
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.7",
|
||||
]);
|
||||
});
|
||||
|
||||
@ -669,8 +669,8 @@ describe("provider alias defaults", () => {
|
||||
it("adds expected alias for provider defaults", () => {
|
||||
const aliasCases = [
|
||||
{
|
||||
applyConfig: () => applyMinimaxApiConfig({}, "MiniMax-M2.5"),
|
||||
modelRef: "minimax/MiniMax-M2.5",
|
||||
applyConfig: () => applyMinimaxApiConfig({}, "MiniMax-M2.7"),
|
||||
modelRef: "minimax/MiniMax-M2.7",
|
||||
alias: "Minimax",
|
||||
},
|
||||
{
|
||||
|
||||
@ -236,7 +236,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
expect(cfg.auth?.profiles?.["minimax:global"]?.provider).toBe("minimax");
|
||||
expect(cfg.auth?.profiles?.["minimax:global"]?.mode).toBe("api_key");
|
||||
expect(cfg.models?.providers?.minimax?.baseUrl).toBe(MINIMAX_API_BASE_URL);
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("minimax/MiniMax-M2.5");
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("minimax/MiniMax-M2.7");
|
||||
await expectApiKeyProfile({
|
||||
profileId: "minimax:global",
|
||||
provider: "minimax",
|
||||
@ -255,7 +255,7 @@ describe("onboard (non-interactive): provider auth", () => {
|
||||
expect(cfg.auth?.profiles?.["minimax:cn"]?.provider).toBe("minimax");
|
||||
expect(cfg.auth?.profiles?.["minimax:cn"]?.mode).toBe("api_key");
|
||||
expect(cfg.models?.providers?.minimax?.baseUrl).toBe(MINIMAX_CN_API_BASE_URL);
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("minimax/MiniMax-M2.5");
|
||||
expect(cfg.agents?.defaults?.model?.primary).toBe("minimax/MiniMax-M2.7");
|
||||
await expectApiKeyProfile({
|
||||
profileId: "minimax:cn",
|
||||
provider: "minimax",
|
||||
|
||||
@ -131,8 +131,8 @@ describe("config identity defaults", () => {
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "MiniMax-M2.5",
|
||||
name: "MiniMax M2.5",
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
|
||||
@ -415,7 +415,7 @@ describe("resolveSessionModelRef", () => {
|
||||
|
||||
test("preserves openrouter provider when model contains vendor prefix", () => {
|
||||
const cfg = createModelDefaultsConfig({
|
||||
primary: "openrouter/minimax/minimax-m2.5",
|
||||
primary: "openrouter/minimax/minimax-m2.7",
|
||||
});
|
||||
|
||||
const resolved = resolveSessionModelRef(cfg, {
|
||||
|
||||
@ -458,7 +458,7 @@ describe("provider discovery contract", () => {
|
||||
authHeader: true,
|
||||
apiKey: "minimax-key",
|
||||
models: expect.arrayContaining([
|
||||
expect.objectContaining({ id: "MiniMax-M2.5" }),
|
||||
expect.objectContaining({ id: "MiniMax-M2.7" }),
|
||||
expect.objectContaining({ id: "MiniMax-VL-01" }),
|
||||
]),
|
||||
},
|
||||
@ -499,7 +499,7 @@ describe("provider discovery contract", () => {
|
||||
api: "anthropic-messages",
|
||||
authHeader: true,
|
||||
apiKey: "minimax-oauth",
|
||||
models: expect.arrayContaining([expect.objectContaining({ id: "MiniMax-M2.5" })]),
|
||||
models: expect.arrayContaining([expect.objectContaining({ id: "MiniMax-M2.7" })]),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -104,7 +104,7 @@ describe("tui session actions", () => {
|
||||
sessions: [
|
||||
{
|
||||
key: "agent:main:main",
|
||||
model: "Minimax-M2.5",
|
||||
model: "Minimax-M2.7",
|
||||
modelProvider: "minimax",
|
||||
},
|
||||
],
|
||||
@ -112,7 +112,7 @@ describe("tui session actions", () => {
|
||||
|
||||
await second;
|
||||
|
||||
expect(state.sessionInfo.model).toBe("Minimax-M2.5");
|
||||
expect(state.sessionInfo.model).toBe("Minimax-M2.7");
|
||||
expect(updateAutocompleteProvider).toHaveBeenCalledTimes(2);
|
||||
expect(updateFooter).toHaveBeenCalledTimes(2);
|
||||
expect(requestRender).toHaveBeenCalledTimes(2);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user