fix(ai): prune deprecated direct minimax models
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed direct `minimax` and `minimax-cn` model catalogs to keep only `MiniMax-M2.7` and `MiniMax-M2.7-highspeed`, and updated MiniMax and abort coverage to current provider model IDs and usage behavior ([#2596](https://github.com/badlogic/pi-mono/pull/2596) by [@liyuan97](https://github.com/liyuan97))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed GitHub Copilot OpenAI Responses requests to omit the `reasoning` field entirely when no reasoning effort is requested, avoiding `400` errors from Copilot `gpt-5-mini` rejecting `reasoning: { effort: "none" }` during internal summary calls ([#2567](https://github.com/badlogic/pi-mono/issues/2567))
|
||||
|
||||
@@ -914,44 +914,26 @@ async function generateModels() {
|
||||
});
|
||||
}
|
||||
|
||||
const minimaxDirectProviders = ["minimax", "minimax-cn"] as const;
|
||||
const minimaxAnthropicIds = new Set([
|
||||
"MiniMax-M2",
|
||||
"MiniMax-M2.1",
|
||||
"MiniMax-M2.1-highspeed",
|
||||
"MiniMax-M2.5",
|
||||
"MiniMax-M2.5-highspeed",
|
||||
"MiniMax-M2.7",
|
||||
"MiniMax-M2.7-highspeed",
|
||||
]);
|
||||
const minimaxDirectSupportedIds = new Set(["MiniMax-M2.7", "MiniMax-M2.7-highspeed"]);
|
||||
|
||||
for (const candidate of allModels) {
|
||||
if (
|
||||
(candidate.provider === "minimax" || candidate.provider === "minimax-cn") &&
|
||||
minimaxAnthropicIds.has(candidate.id)
|
||||
minimaxDirectSupportedIds.has(candidate.id)
|
||||
) {
|
||||
candidate.contextWindow = 204800;
|
||||
candidate.maxTokens = 131072;
|
||||
}
|
||||
}
|
||||
|
||||
for (const provider of minimaxDirectProviders) {
|
||||
const baseModel = allModels.find((m) => m.provider === provider && m.id === "MiniMax-M2.1");
|
||||
if (!baseModel) continue;
|
||||
if (allModels.some((m) => m.provider === provider && m.id === "MiniMax-M2.1-highspeed")) continue;
|
||||
|
||||
allModels.push({
|
||||
...baseModel,
|
||||
id: "MiniMax-M2.1-highspeed",
|
||||
name: "MiniMax-M2.1-highspeed",
|
||||
cost: {
|
||||
...baseModel.cost,
|
||||
input: baseModel.cost.input * 2,
|
||||
output: baseModel.cost.output * 2,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
});
|
||||
for (let i = allModels.length - 1; i >= 0; i--) {
|
||||
const candidate = allModels[i];
|
||||
if (
|
||||
(candidate.provider === "minimax" || candidate.provider === "minimax-cn") &&
|
||||
!minimaxDirectSupportedIds.has(candidate.id)
|
||||
) {
|
||||
allModels.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAI Codex (ChatGPT OAuth) models
|
||||
|
||||
@@ -804,6 +804,23 @@ export const MODELS = {
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
"minimax.minimax-m2.5": {
|
||||
id: "minimax.minimax-m2.5",
|
||||
name: "MiniMax M2.5",
|
||||
api: "bedrock-converse-stream",
|
||||
provider: "amazon-bedrock",
|
||||
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 196608,
|
||||
maxTokens: 98304,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
"mistral.devstral-2-123b": {
|
||||
id: "mistral.devstral-2-123b",
|
||||
name: "Devstral 2 123B",
|
||||
@@ -1042,6 +1059,23 @@ export const MODELS = {
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
"nvidia.nemotron-super-3-120b": {
|
||||
id: "nvidia.nemotron-super-3-120b",
|
||||
name: "NVIDIA Nemotron 3 Super 120B A12B",
|
||||
api: "bedrock-converse-stream",
|
||||
provider: "amazon-bedrock",
|
||||
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.15,
|
||||
output: 0.65,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 262144,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
"openai.gpt-oss-120b-1:0": {
|
||||
id: "openai.gpt-oss-120b-1:0",
|
||||
name: "gpt-oss-120b",
|
||||
@@ -1416,6 +1450,23 @@ export const MODELS = {
|
||||
contextWindow: 200000,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
"zai.glm-5": {
|
||||
id: "zai.glm-5",
|
||||
name: "GLM-5",
|
||||
api: "bedrock-converse-stream",
|
||||
provider: "amazon-bedrock",
|
||||
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 1,
|
||||
output: 3.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 202752,
|
||||
maxTokens: 101376,
|
||||
} satisfies Model<"bedrock-converse-stream">,
|
||||
},
|
||||
"anthropic": {
|
||||
"claude-3-5-haiku-20241022": {
|
||||
@@ -4498,91 +4549,6 @@ export const MODELS = {
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
},
|
||||
"minimax": {
|
||||
"MiniMax-M2": {
|
||||
id: "MiniMax-M2",
|
||||
name: "MiniMax-M2",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.1": {
|
||||
id: "MiniMax-M2.1",
|
||||
name: "MiniMax-M2.1",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.1-highspeed": {
|
||||
id: "MiniMax-M2.1-highspeed",
|
||||
name: "MiniMax-M2.1-highspeed",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.6,
|
||||
output: 2.4,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.5": {
|
||||
id: "MiniMax-M2.5",
|
||||
name: "MiniMax-M2.5",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0.03,
|
||||
cacheWrite: 0.375,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.5-highspeed": {
|
||||
id: "MiniMax-M2.5-highspeed",
|
||||
name: "MiniMax-M2.5-highspeed",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax",
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.6,
|
||||
output: 2.4,
|
||||
cacheRead: 0.06,
|
||||
cacheWrite: 0.375,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.7": {
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax-M2.7",
|
||||
@@ -4619,91 +4585,6 @@ export const MODELS = {
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
},
|
||||
"minimax-cn": {
|
||||
"MiniMax-M2": {
|
||||
id: "MiniMax-M2",
|
||||
name: "MiniMax-M2",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax-cn",
|
||||
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.1": {
|
||||
id: "MiniMax-M2.1",
|
||||
name: "MiniMax-M2.1",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax-cn",
|
||||
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.1-highspeed": {
|
||||
id: "MiniMax-M2.1-highspeed",
|
||||
name: "MiniMax-M2.1-highspeed",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax-cn",
|
||||
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.6,
|
||||
output: 2.4,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.5": {
|
||||
id: "MiniMax-M2.5",
|
||||
name: "MiniMax-M2.5",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax-cn",
|
||||
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.3,
|
||||
output: 1.2,
|
||||
cacheRead: 0.03,
|
||||
cacheWrite: 0.375,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.5-highspeed": {
|
||||
id: "MiniMax-M2.5-highspeed",
|
||||
name: "MiniMax-M2.5-highspeed",
|
||||
api: "anthropic-messages",
|
||||
provider: "minimax-cn",
|
||||
baseUrl: "https://api.minimaxi.com/anthropic",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.6,
|
||||
output: 2.4,
|
||||
cacheRead: 0.06,
|
||||
cacheWrite: 0.375,
|
||||
},
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"MiniMax-M2.7": {
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax-M2.7",
|
||||
@@ -8295,13 +8176,13 @@ export const MODELS = {
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.55,
|
||||
output: 2.2,
|
||||
input: 0.5700000000000001,
|
||||
output: 2.3,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 131000,
|
||||
maxTokens: 4096,
|
||||
contextWindow: 131072,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"moonshotai/kimi-k2-0905": {
|
||||
id: "moonshotai/kimi-k2-0905",
|
||||
@@ -8363,8 +8244,8 @@ export const MODELS = {
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.27,
|
||||
output: 1,
|
||||
input: 0.135,
|
||||
output: 0.5,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
@@ -8450,7 +8331,7 @@ export const MODELS = {
|
||||
cost: {
|
||||
input: 0.09999999999999999,
|
||||
output: 0.5,
|
||||
cacheRead: 0.04,
|
||||
cacheRead: 0.09999999999999999,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 262144,
|
||||
@@ -9542,7 +9423,7 @@ export const MODELS = {
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 32768,
|
||||
maxTokens: 4096,
|
||||
maxTokens: 32768,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"qwen/qwen-max": {
|
||||
id: "qwen/qwen-max",
|
||||
@@ -10205,7 +10086,7 @@ export const MODELS = {
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 256000,
|
||||
maxTokens: 4096,
|
||||
maxTokens: 65536,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"qwen/qwen3.5-flash-02-23": {
|
||||
id: "qwen/qwen3.5-flash-02-23",
|
||||
@@ -10258,6 +10139,23 @@ export const MODELS = {
|
||||
contextWindow: 131072,
|
||||
maxTokens: 131072,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"reka/reka-edge": {
|
||||
id: "reka/reka-edge",
|
||||
name: "Reka Edge",
|
||||
api: "openai-completions",
|
||||
provider: "openrouter",
|
||||
baseUrl: "https://openrouter.ai/api/v1",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 0.19999999999999998,
|
||||
output: 0.19999999999999998,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 16384,
|
||||
maxTokens: 16384,
|
||||
} satisfies Model<"openai-completions">,
|
||||
"relace/relace-search": {
|
||||
id: "relace/relace-search",
|
||||
name: "Relace: Relace Search",
|
||||
@@ -10794,9 +10692,9 @@ export const MODELS = {
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 0.96,
|
||||
output: 3.1999999999999997,
|
||||
cacheRead: 0.192,
|
||||
input: 1.2,
|
||||
output: 4,
|
||||
cacheRead: 0.24,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 202752,
|
||||
@@ -12802,8 +12700,8 @@ export const MODELS = {
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 1,
|
||||
output: 1,
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
@@ -12819,8 +12717,8 @@ export const MODELS = {
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 3,
|
||||
output: 15,
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
@@ -13014,6 +12912,23 @@ export const MODELS = {
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 30000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-multi-agent": {
|
||||
id: "xai/grok-4.20-multi-agent",
|
||||
name: "Grok 4.20 Multi-Agent",
|
||||
api: "anthropic-messages",
|
||||
provider: "vercel-ai-gateway",
|
||||
baseUrl: "https://ai-gateway.vercel.sh",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: {
|
||||
input: 2,
|
||||
output: 6,
|
||||
cacheRead: 0.19999999999999998,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 2000000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-multi-agent-beta": {
|
||||
id: "xai/grok-4.20-multi-agent-beta",
|
||||
name: "Grok 4.20 Multi Agent Beta",
|
||||
@@ -13031,6 +12946,23 @@ export const MODELS = {
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 2000000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-non-reasoning": {
|
||||
id: "xai/grok-4.20-non-reasoning",
|
||||
name: "Grok 4.20 Non-Reasoning",
|
||||
api: "anthropic-messages",
|
||||
provider: "vercel-ai-gateway",
|
||||
baseUrl: "https://ai-gateway.vercel.sh",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 2,
|
||||
output: 6,
|
||||
cacheRead: 0.19999999999999998,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 2000000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-non-reasoning-beta": {
|
||||
id: "xai/grok-4.20-non-reasoning-beta",
|
||||
name: "Grok 4.20 Beta Non-Reasoning",
|
||||
@@ -13048,6 +12980,23 @@ export const MODELS = {
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 2000000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-reasoning": {
|
||||
id: "xai/grok-4.20-reasoning",
|
||||
name: "Grok 4.20 Reasoning",
|
||||
api: "anthropic-messages",
|
||||
provider: "vercel-ai-gateway",
|
||||
baseUrl: "https://ai-gateway.vercel.sh",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: {
|
||||
input: 2,
|
||||
output: 6,
|
||||
cacheRead: 0.19999999999999998,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
contextWindow: 2000000,
|
||||
maxTokens: 2000000,
|
||||
} satisfies Model<"anthropic-messages">,
|
||||
"xai/grok-4.20-reasoning-beta": {
|
||||
id: "xai/grok-4.20-reasoning-beta",
|
||||
name: "Grok 4.20 Beta Reasoning",
|
||||
|
||||
@@ -182,7 +182,7 @@ describe("AI Providers Abort Tests", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider Abort", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should abort mid-stream", { retry: 3 }, async () => {
|
||||
await testAbortSignal(llm);
|
||||
|
||||
@@ -436,8 +436,8 @@ describe("Context overflow error handling", () => {
|
||||
// =============================================================================
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax", () => {
|
||||
it("MiniMax-M2.1 - should detect overflow via isContextOverflow", async () => {
|
||||
const model = getModel("minimax", "MiniMax-M2.1");
|
||||
it("MiniMax-M2.7 - should detect overflow via isContextOverflow", async () => {
|
||||
const model = getModel("minimax", "MiniMax-M2.7");
|
||||
const result = await testContextOverflow(model, process.env.MINIMAX_API_KEY!);
|
||||
logResult(result);
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ const PROVIDER_MODEL_PAIRS: ProviderModelPair[] = [
|
||||
// Mistral
|
||||
{ provider: "mistral", model: "devstral-medium-latest", label: "mistral-devstral-medium" },
|
||||
// MiniMax
|
||||
{ provider: "minimax", model: "MiniMax-M2.1", label: "minimax-m2.1" },
|
||||
{ provider: "minimax", model: "MiniMax-M2.7", label: "minimax-m2.7" },
|
||||
// OpenCode Zen
|
||||
{ provider: "opencode", model: "big-pickle", label: "zen-big-pickle" },
|
||||
{ provider: "opencode", model: "claude-sonnet-4-5", label: "zen-claude-sonnet-4-5" },
|
||||
|
||||
@@ -369,7 +369,7 @@ describe("AI Providers Empty Message Tests", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider Empty Messages", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should handle empty content array", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testEmptyMessage(llm);
|
||||
|
||||
@@ -795,8 +795,8 @@ describe("Generate E2E Tests", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider (MiniMax-M2.1 via Anthropic Messages)", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider (MiniMax-M2.7 via Anthropic Messages)", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should complete basic text generation", { retry: 3 }, async () => {
|
||||
await basicTextGeneration(llm);
|
||||
|
||||
@@ -52,7 +52,7 @@ async function testTokensOnAbort<TApi extends Api>(llm: Model<TApi>, options: St
|
||||
|
||||
// OpenAI providers, OpenAI Codex, Gemini CLI, zai, Amazon Bedrock, and the GPT-OSS model on Antigravity only send usage in the final chunk,
|
||||
// so when aborted they have no token stats. Anthropic and Google send usage information early in the stream.
|
||||
// MiniMax reports input tokens but not output tokens when aborted.
|
||||
// MiniMax and Kimi report input tokens but not output tokens differently on aborted requests.
|
||||
if (
|
||||
llm.api === "openai-completions" ||
|
||||
llm.api === "mistral-conversations" ||
|
||||
@@ -68,7 +68,11 @@ async function testTokensOnAbort<TApi extends Api>(llm: Model<TApi>, options: St
|
||||
expect(msg.usage.input).toBe(0);
|
||||
expect(msg.usage.output).toBe(0);
|
||||
} else if (llm.provider === "minimax") {
|
||||
// MiniMax reports input tokens early but output tokens only in final chunk
|
||||
// MiniMax M2.7 does not report token usage for aborted requests.
|
||||
expect(msg.usage.input).toBe(0);
|
||||
expect(msg.usage.output).toBe(0);
|
||||
} else if (llm.provider === "kimi-coding") {
|
||||
// Kimi reports input tokens early but output tokens only in the final chunk.
|
||||
expect(msg.usage.input).toBeGreaterThan(0);
|
||||
expect(msg.usage.output).toBe(0);
|
||||
} else {
|
||||
@@ -106,10 +110,10 @@ describe("Token Statistics on Abort", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.OPENAI_API_KEY)("OpenAI Responses Provider", () => {
|
||||
const llm = getModel("openai", "gpt-5-mini");
|
||||
const llm = getModel("openai", "gpt-5.4-mini");
|
||||
|
||||
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testTokensOnAbort(llm);
|
||||
await testTokensOnAbort(llm, { reasoningEffort: "low" });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -124,7 +128,7 @@ describe("Token Statistics on Abort", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.ANTHROPIC_API_KEY)("Anthropic Provider", () => {
|
||||
const llm = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||
const llm = getModel("anthropic", "claude-sonnet-4-6");
|
||||
|
||||
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testTokensOnAbort(llm);
|
||||
@@ -148,7 +152,7 @@ describe("Token Statistics on Abort", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.CEREBRAS_API_KEY)("Cerebras Provider", () => {
|
||||
const llm = getModel("cerebras", "gpt-oss-120b");
|
||||
const llm = getModel("cerebras", "qwen-3-235b-a22b-instruct-2507");
|
||||
|
||||
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testTokensOnAbort(llm);
|
||||
@@ -180,7 +184,7 @@ describe("Token Statistics on Abort", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testTokensOnAbort(llm);
|
||||
@@ -188,7 +192,7 @@ describe("Token Statistics on Abort", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider", () => {
|
||||
const llm = getModel("kimi-coding", "kimi-k2-thinking");
|
||||
const llm = getModel("kimi-coding", "k2p5");
|
||||
|
||||
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testTokensOnAbort(llm);
|
||||
@@ -208,7 +212,7 @@ describe("Token Statistics on Abort", () => {
|
||||
// =========================================================================
|
||||
|
||||
describe("Anthropic OAuth Provider", () => {
|
||||
const llm = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||
const llm = getModel("anthropic", "claude-sonnet-4-6");
|
||||
|
||||
it.skipIf(!anthropicOAuthToken)(
|
||||
"should include token stats when aborted mid-stream",
|
||||
@@ -261,10 +265,10 @@ describe("Token Statistics on Abort", () => {
|
||||
);
|
||||
|
||||
it.skipIf(!antigravityToken)(
|
||||
"claude-sonnet-4-5 - should include token stats when aborted mid-stream",
|
||||
"claude-sonnet-4-6 - should include token stats when aborted mid-stream",
|
||||
{ retry: 3, timeout: 30000 },
|
||||
async () => {
|
||||
const llm = getModel("google-antigravity", "claude-sonnet-4-5");
|
||||
const llm = getModel("google-antigravity", "claude-sonnet-4-6");
|
||||
await testTokensOnAbort(llm, { apiKey: antigravityToken });
|
||||
},
|
||||
);
|
||||
|
||||
@@ -193,7 +193,7 @@ describe("Tool Call Without Result Tests", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider", () => {
|
||||
const model = getModel("minimax", "MiniMax-M2.1");
|
||||
const model = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should filter out tool calls without corresponding tool results", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testToolCallWithoutResult(model);
|
||||
|
||||
@@ -377,10 +377,10 @@ describe("totalTokens field", () => {
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax", () => {
|
||||
it(
|
||||
"MiniMax-M2.1 - should return totalTokens equal to sum of components",
|
||||
"MiniMax-M2.7 - should return totalTokens equal to sum of components",
|
||||
{ retry: 3, timeout: 60000 },
|
||||
async () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
console.log(`\nMiniMax / ${llm.id}:`);
|
||||
const { first, second } = await testTotalTokensWithCache(llm, { apiKey: process.env.MINIMAX_API_KEY });
|
||||
|
||||
@@ -660,7 +660,7 @@ describe("AI Providers Unicode Surrogate Pair Tests", () => {
|
||||
});
|
||||
|
||||
describe.skipIf(!process.env.MINIMAX_API_KEY)("MiniMax Provider Unicode Handling", () => {
|
||||
const llm = getModel("minimax", "MiniMax-M2.1");
|
||||
const llm = getModel("minimax", "MiniMax-M2.7");
|
||||
|
||||
it("should handle emoji in tool results", { retry: 3, timeout: 30000 }, async () => {
|
||||
await testEmojiInToolResults(llm);
|
||||
|
||||
Reference in New Issue
Block a user