Skip to content
Closed
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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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

# MAX_TOKENS=4096 # Cap LLM completion tokens for compression / summarise calls

Expand Down
2 changes: 1 addition & 1 deletion src/cli/onboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
];

Expand Down
2 changes: 1 addition & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function detectProvider(env: Record<string, string>): ProviderConfig {
if (hasRealValue(env["MINIMAX_API_KEY"])) {
return {
provider: "minimax",
model: env["MINIMAX_MODEL"] || "MiniMax-M2.7",
model: env["MINIMAX_MODEL"] || "MiniMax-M3",
maxTokens,
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down
12 changes: 8 additions & 4 deletions src/providers/minimax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
*/
export class MinimaxProvider implements MemoryProvider {
name = 'minimax'
Expand All @@ -31,6 +31,10 @@ export class MinimaxProvider implements MemoryProvider {
getEnvVar('MINIMAX_BASE_URL') || 'https://api.minimax.io/anthropic'
}

private messagesUrl(): string {
return `${this.baseUrl.replace(/\/+$/, '')}/v1/messages`
}

async compress(systemPrompt: string, userPrompt: string): Promise<string> {
return this.call(systemPrompt, userPrompt)
}
Expand All @@ -40,7 +44,7 @@ export class MinimaxProvider implements MemoryProvider {
}

private async call(systemPrompt: string, userPrompt: string): Promise<string> {
const url = `${this.baseUrl}/v1/messages`
const url = this.messagesUrl()
const response = await fetchWithTimeout(url, {
method: 'POST',
headers: {
Expand Down
2 changes: 1 addition & 1 deletion test/fallback-model-resolution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion test/fetch-timeout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
Expand Down
14 changes: 11 additions & 3 deletions test/minimax-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,25 @@ 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 base URL", () => {
delete process.env["MINIMAX_BASE_URL"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore MINIMAX_BASE_URL after each test.

These tests mutate the process-wide environment without restoring its previous value, so later tests can become order-dependent or inherit the custom URL. Snapshot and restore the variable in afterEach (including the originally-undefined case).

Also applies to: 24-25, 32-33

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/minimax-provider.test.ts` at line 16, Update the test lifecycle around
the MINIMAX_BASE_URL mutations to snapshot its original value before each test
and restore it in afterEach, deleting the variable when it was initially
undefined. Apply this consistently to the affected tests and preserve their
existing setup behavior.

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",
);
});

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",
);
Comment on lines +23 to +28

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file list =="
git ls-files 'src/providers/minimax.ts' 'test/minimax-provider.test.ts' 'test/crystallize.test.ts'

echo
echo "== relevant source outline =="
ast-grep outline src/providers/minimax.ts --view expanded || true

echo
echo "== relevant test outline =="
ast-grep outline test/minimax-provider.test.ts --view expanded || true

echo
echo "== source excerpt =="
sed -n '1,220p' src/providers/minimax.ts | cat -n

echo
echo "== test excerpt =="
sed -n '1,220p' test/minimax-provider.test.ts | cat -n

echo
echo "== search for /v1/messages and base URL handling =="
rg -n 'v1/messages|BASE_URL|messagesUrl|MINIMAX_BASE_URL' src test

Repository: rohitg00/agentmemory

Length of output: 10942


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== MiniMax docs and references =="
rg -n -C 2 'MINIMAX_BASE_URL|MiniMax|minimax' README.md docs src test .github || true

echo
echo "== nearby provider normalization patterns =="
sed -n '1,220p' src/providers/openai.ts | cat -n
echo
sed -n '1,240p' src/providers/_openai-shared.ts | cat -n

Repository: rohitg00/agentmemory

Length of output: 27509


Handle /v1-suffixed MiniMax base URLs. src/providers/minimax.ts:messagesUrl() always appends /v1/messages, so MINIMAX_BASE_URL=https://custom.example.com/anthropic/v1 becomes /v1/v1/messages. Add a regression test for that case and strip a trailing /v1 before appending the route.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/minimax-provider.test.ts` around lines 23 - 28, Update
MinimaxProvider.messagesUrl() to remove a trailing /v1 from the configured
MINIMAX_BASE_URL before appending /v1/messages, while preserving handling of
trailing slashes and unsuffixed URLs. Extend the existing MiniMax URL tests with
a regression case for a base URL ending in /v1 and expect exactly one
/v1/messages suffix.

});

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);
const provider = new MinimaxProvider("test-key", "MiniMax-M3", 800);
expect((provider as unknown as { baseUrl: string }).baseUrl).toBe(
"https://custom.example.com/anthropic",
);
Expand Down