From f6c81b23e305d5ac044963a3c96474c18f274da3 Mon Sep 17 00:00:00 2001 From: octo-patch <266937838+octo-patch@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:32:33 +0000 Subject: [PATCH 1/2] Update MiniMax defaults for MiniMax-M3 Use MiniMax-M3 as the provider default and align the Anthropic-compatible endpoint with MiniMax's /anthropic/v1 base so requests target the documented messages path. Co-Authored-By: Claude Opus 4.7 --- .env.example | 3 ++- src/cli/onboarding.ts | 2 +- src/config.ts | 2 +- src/providers/index.ts | 2 +- src/providers/minimax.ts | 14 +++++++++----- test/fallback-model-resolution.test.ts | 2 +- test/fetch-timeout.test.ts | 2 +- test/minimax-provider.test.ts | 20 ++++++++++++++------ 8 files changed, 30 insertions(+), 17 deletions(-) diff --git a/.env.example b/.env.example index 77ca0f3a3..784937b5b 100644 --- a/.env.example +++ b/.env.example @@ -41,7 +41,8 @@ # OPENROUTER_MODEL=anthropic/claude-sonnet-4-20250514 # MINIMAX_API_KEY=... -# MINIMAX_MODEL=MiniMax-M2.7 +# MINIMAX_MODEL=MiniMax-M3 +# MINIMAX_BASE_URL=https://api.minimax.io/anthropic/v1 # MAX_TOKENS=4096 # Cap LLM completion tokens for compression / summarise calls diff --git a/src/cli/onboarding.ts b/src/cli/onboarding.ts index 6d0493554..926cdbea9 100644 --- a/src/cli/onboarding.ts +++ b/src/cli/onboarding.ts @@ -53,7 +53,7 @@ const PROVIDERS: { value: string; label: string; envKey: string | null }[] = [ { value: "openai", label: "OpenAI — gpt", envKey: "OPENAI_API_KEY" }, { value: "gemini", label: "Google — gemini", envKey: "GEMINI_API_KEY" }, { value: "openrouter", label: "OpenRouter — multi-model", envKey: "OPENROUTER_API_KEY" }, - { value: "minimax", label: "MiniMax — minimax-m1", envKey: "MINIMAX_API_KEY" }, + { value: "minimax", label: "MiniMax — MiniMax-M3", envKey: "MINIMAX_API_KEY" }, { value: "skip", label: "Skip — BM25-only mode (no LLM key)", envKey: null }, ]; diff --git a/src/config.ts b/src/config.ts index 3348ac226..b9f3d2d2d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -67,7 +67,7 @@ function detectProvider(env: Record): ProviderConfig { if (hasRealValue(env["MINIMAX_API_KEY"])) { return { provider: "minimax", - model: env["MINIMAX_MODEL"] || "MiniMax-M2.7", + model: env["MINIMAX_MODEL"] || "MiniMax-M3", maxTokens, }; } diff --git a/src/providers/index.ts b/src/providers/index.ts index 0ec3feba0..35b2f3547 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -45,7 +45,7 @@ function defaultModelFor(providerType: ProviderConfig["provider"]): string { getEnvVar("OPENROUTER_MODEL") || "anthropic/claude-sonnet-4-20250514" ); case "minimax": - return getEnvVar("MINIMAX_MODEL") || "MiniMax-M2.7"; + return getEnvVar("MINIMAX_MODEL") || "MiniMax-M3"; case "agent-sdk": return "claude-sonnet-4-20250514"; case "noop": diff --git a/src/providers/minimax.ts b/src/providers/minimax.ts index 72fc9ec90..207050b84 100644 --- a/src/providers/minimax.ts +++ b/src/providers/minimax.ts @@ -10,11 +10,11 @@ import { fetchWithTimeout } from './_fetch.js' * * Required env vars (loaded from ~/.agentmemory/.env or process.env): * MINIMAX_API_KEY — your MiniMax API key - * MINIMAX_MODEL — model name (default: MiniMax-M2.7) - * MAX_TOKENS — max output tokens (default: 800; MiniMax-M2.7 needs ≤800) + * MINIMAX_MODEL — model name (default: MiniMax-M3) + * MAX_TOKENS — max output tokens (default: 4096) * * Optional: - * MINIMAX_BASE_URL — base URL without path (default: https://api.minimax.io/anthropic) + * MINIMAX_BASE_URL — Anthropic-compatible base URL (default: https://api.minimax.io/anthropic/v1) */ export class MinimaxProvider implements MemoryProvider { name = 'minimax' @@ -28,7 +28,11 @@ export class MinimaxProvider implements MemoryProvider { this.model = model this.maxTokens = maxTokens this.baseUrl = - getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic' + getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic/v1' + } + + private messagesUrl(): string { + return `${this.baseUrl.replace(/\/+$/, '')}/messages` } async compress(systemPrompt: string, userPrompt: string): Promise { @@ -40,7 +44,7 @@ export class MinimaxProvider implements MemoryProvider { } private async call(systemPrompt: string, userPrompt: string): Promise { - const url = `${this.baseUrl}/v1/messages` + const url = this.messagesUrl() const response = await fetchWithTimeout(url, { method: 'POST', headers: { diff --git a/test/fallback-model-resolution.test.ts b/test/fallback-model-resolution.test.ts index 91a821161..79c731a48 100644 --- a/test/fallback-model-resolution.test.ts +++ b/test/fallback-model-resolution.test.ts @@ -155,7 +155,7 @@ describe("Fallback provider model resolution (#778)", () => { const openai = captured.find((c) => c.provider === "openai"); const minimax = captured.find((c) => c.provider === "minimax"); expect(openai?.model).toBe("gpt-5"); - expect(minimax?.model).toBe("MiniMax-M2.7"); + expect(minimax?.model).toBe("MiniMax-M3"); // Neither inherits the Anthropic model name. expect(openai?.model).not.toBe("claude-sonnet-4-20250514"); expect(minimax?.model).not.toBe("claude-sonnet-4-20250514"); diff --git a/test/fetch-timeout.test.ts b/test/fetch-timeout.test.ts index 5b2cd7c9c..7e9536de6 100644 --- a/test/fetch-timeout.test.ts +++ b/test/fetch-timeout.test.ts @@ -91,7 +91,7 @@ describe("Provider hang regression — MinimaxProvider", () => { }); it("compress() aborts after timeout when upstream hangs", async () => { - const provider = new MinimaxProvider("test-key", "MiniMax-M2.7", 800); + const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); await expect(provider.compress("system", "user")).rejects.toThrow(); }); }); diff --git a/test/minimax-provider.test.ts b/test/minimax-provider.test.ts index 4167d4b37..46c5043a4 100644 --- a/test/minimax-provider.test.ts +++ b/test/minimax-provider.test.ts @@ -12,19 +12,27 @@ describe("MinimaxProvider — base URL resolution (#285)", () => { } }); - it("defaults to https://api.minimax.io/anthropic (not the legacy minimaxi.com host)", () => { + it("defaults to MiniMax's Anthropic-compatible /anthropic/v1 endpoint", () => { delete process.env["MINIMAX_BASE_URL"]; - const provider = new MinimaxProvider("test-key", "MiniMax-M2.7", 800); + const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); expect((provider as unknown as { baseUrl: string }).baseUrl).toBe( - "https://api.minimax.io/anthropic", + "https://api.minimax.io/anthropic/v1", + ); + }); + + it("posts messages directly under MINIMAX_BASE_URL without adding another /v1 segment", () => { + process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic/v1/"; + const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); + expect((provider as unknown as { messagesUrl: () => string }).messagesUrl()).toBe( + "https://custom.example.com/anthropic/v1/messages", ); }); it("honors MINIMAX_BASE_URL via getEnvVar (merged ~/.agentmemory/.env + process.env)", () => { - process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic"; - const provider = new MinimaxProvider("test-key", "MiniMax-M2.7", 800); + process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic/v1"; + const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); expect((provider as unknown as { baseUrl: string }).baseUrl).toBe( - "https://custom.example.com/anthropic", + "https://custom.example.com/anthropic/v1", ); }); }); From f439a69048581b724e455ce15604fc814f740e3f Mon Sep 17 00:00:00 2001 From: octo-patch <266937838+octo-patch@users.noreply.github.com> Date: Sun, 12 Jul 2026 17:23:34 +0800 Subject: [PATCH 2/2] Fix MiniMax Anthropic base URL --- .env.example | 2 +- src/providers/minimax.ts | 6 +++--- test/minimax-provider.test.ts | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 784937b5b..e8aa71633 100644 --- a/.env.example +++ b/.env.example @@ -42,7 +42,7 @@ # MINIMAX_API_KEY=... # MINIMAX_MODEL=MiniMax-M3 -# MINIMAX_BASE_URL=https://api.minimax.io/anthropic/v1 +# MINIMAX_BASE_URL=https://api.minimax.io/anthropic # MAX_TOKENS=4096 # Cap LLM completion tokens for compression / summarise calls diff --git a/src/providers/minimax.ts b/src/providers/minimax.ts index 207050b84..19c4ee021 100644 --- a/src/providers/minimax.ts +++ b/src/providers/minimax.ts @@ -14,7 +14,7 @@ import { fetchWithTimeout } from './_fetch.js' * MAX_TOKENS — max output tokens (default: 4096) * * Optional: - * MINIMAX_BASE_URL — Anthropic-compatible base URL (default: https://api.minimax.io/anthropic/v1) + * MINIMAX_BASE_URL — Anthropic-compatible base URL (default: https://api.minimax.io/anthropic) */ export class MinimaxProvider implements MemoryProvider { name = 'minimax' @@ -28,11 +28,11 @@ export class MinimaxProvider implements MemoryProvider { this.model = model this.maxTokens = maxTokens this.baseUrl = - getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic/v1' + getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic' } private messagesUrl(): string { - return `${this.baseUrl.replace(/\/+$/, '')}/messages` + return `${this.baseUrl.replace(/\/+$/, '')}/v1/messages` } async compress(systemPrompt: string, userPrompt: string): Promise { diff --git a/test/minimax-provider.test.ts b/test/minimax-provider.test.ts index 46c5043a4..a11bd9794 100644 --- a/test/minimax-provider.test.ts +++ b/test/minimax-provider.test.ts @@ -12,16 +12,16 @@ describe("MinimaxProvider — base URL resolution (#285)", () => { } }); - it("defaults to MiniMax's Anthropic-compatible /anthropic/v1 endpoint", () => { + it("defaults to MiniMax's Anthropic-compatible base URL", () => { delete process.env["MINIMAX_BASE_URL"]; const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); expect((provider as unknown as { baseUrl: string }).baseUrl).toBe( - "https://api.minimax.io/anthropic/v1", + "https://api.minimax.io/anthropic", ); }); - it("posts messages directly under MINIMAX_BASE_URL without adding another /v1 segment", () => { - process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic/v1/"; + it("appends /v1/messages to MINIMAX_BASE_URL", () => { + process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic/"; const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); expect((provider as unknown as { messagesUrl: () => string }).messagesUrl()).toBe( "https://custom.example.com/anthropic/v1/messages", @@ -29,10 +29,10 @@ describe("MinimaxProvider — base URL resolution (#285)", () => { }); it("honors MINIMAX_BASE_URL via getEnvVar (merged ~/.agentmemory/.env + process.env)", () => { - process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic/v1"; + process.env["MINIMAX_BASE_URL"] = "https://custom.example.com/anthropic"; const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800); expect((provider as unknown as { baseUrl: string }).baseUrl).toBe( - "https://custom.example.com/anthropic/v1", + "https://custom.example.com/anthropic", ); }); });