diff --git a/docs-site/src/content/docs/guides/minimax.md b/docs-site/src/content/docs/guides/minimax.md index db01d782d7a..121bf88c9c1 100644 --- a/docs-site/src/content/docs/guides/minimax.md +++ b/docs-site/src/content/docs/guides/minimax.md @@ -13,7 +13,7 @@ the protocol boundary it actually exposes: ## MiniMax Code In the OpenCodex Models page, both MiniMax Coding Plan regions advertise image input for -`MiniMax-M3` and `MiniMax-M3.1-Flash-Preview`. A Combo's **Image / multimodal** switch is +`MiniMax-M3` and `MiniMax-M3.1-Flash`. A Combo's **Image / multimodal** switch is available only when every selected model supports image input. The switch controls image attachments; it does not enable video uploads. diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 8032797cb0f..c365b6c573b 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -891,17 +891,15 @@ attempt fails, while transient failures keep it. An unreadable or oversized body further attempts. Dollar credits show the included allowance only, excluding purchased credits, so an exhausted allowance stops routing to Ollama Cloud only when no purchased credit remains. -`MiniMax-M3.1-Flash-Preview` (1M context) is listed on both MiniMax presets. MiniMax serves it -only to Token Plan subscription keys and MiniMax Code for now, so a pay-as-you-go API key gets an -error for it. Thinking is always on: the effort picker offers `low` through `max` and defaults to -`max`, and there is no way to turn thinking off. MiniMax has not published a per-token price -for the preview; usage is drawn from your -[Token Plan quota](https://platform.minimax.io/docs/guides/pricing-token-plan), so OpenCodex -shows no estimated cost for it. MiniMax's `/models` endpoint does not list -the preview yet, so OpenCodex keeps it in the catalog from the preset. An install whose saved -MiniMax model list is still the previous default receives it on the next start; a list you edited -is left as it is; register the preview by hand with -`ocx models add minimax MiniMax-M3.1-Flash-Preview --context-window 1000000`. +`MiniMax-M3.1-Flash` (1M context, up to 524,288 output tokens) is the default model on both MiniMax +presets. MiniMax released it on 2026-10-19 and retired the `MiniMax-M3.1-Flash-Preview` id, so a +saved configuration that still names the preview is renamed to `MiniMax-M3.1-Flash` on the next +start. Thinking is always on: the effort picker offers `low` through `max` and defaults to `max`, +and there is no way to turn thinking off. MiniMax's `/models` endpoint does not list Flash, so +OpenCodex keeps it in the catalog from the preset. An install whose saved MiniMax model list is +still the previous default receives it on the next start; a list you edited is left as it is; +register it by hand with +`ocx models add minimax MiniMax-M3.1-Flash --context-window 1000000`. **OpenCode Go** routes `gemini-4-argon-contributor` through its Gemini API, including streaming and tool-result continuations. The existing `opencode-go` preset keeps its diff --git a/docs-site/src/content/docs/zh-cn/guides/minimax.md b/docs-site/src/content/docs/zh-cn/guides/minimax.md index d7baff5ceeb..ca0b375156e 100644 --- a/docs-site/src/content/docs/zh-cn/guides/minimax.md +++ b/docs-site/src/content/docs/zh-cn/guides/minimax.md @@ -11,7 +11,7 @@ MiniMax 发布两种不同的命令行产品。OpenCodex 在它们实际提供 ## MiniMax Code 在 OpenCodex 的模型管理页面,MiniMax Coding Plan 两个区域的 `MiniMax-M3` 和 -`MiniMax-M3.1-Flash-Preview` 均声明支持图片输入。只有所有选定模型均支持图片输入时, +`MiniMax-M3.1-Flash` 均声明支持图片输入。只有所有选定模型均支持图片输入时, Combo 的“图片 / 多模态”开关才可用。该开关控制图片附件,不提供视频上传能力。 先按照 MiniMax 的说明安装并登录 MiniMax Code,然后启动 OpenCodex 并连接可逆的文件集成: diff --git a/scripts/model-metadata.source.json b/scripts/model-metadata.source.json index 4c075688b60..9e6b6adc015 100644 --- a/scripts/model-metadata.source.json +++ b/scripts/model-metadata.source.json @@ -42160,9 +42160,9 @@ "maxLevel": "xhigh" } }, - "MiniMax-M3.1-Flash-Preview": { - "id": "MiniMax-M3.1-Flash-Preview", - "name": "MiniMax-M3.1-Flash-Preview", + "MiniMax-M3.1-Flash": { + "id": "MiniMax-M3.1-Flash", + "name": "MiniMax-M3.1-Flash", "api": "anthropic-messages", "provider": "minimax", "baseUrl": "https://api.minimax.io/anthropic", @@ -42172,7 +42172,14 @@ "image", "video" ], - "contextWindow": 1000000 + "contextWindow": 1000000, + "maxTokens": 524288, + "cost": { + "input": 0.15, + "output": 0.6, + "cacheRead": 0.015, + "cacheWrite": 0 + } } }, "minimax-cn": { @@ -42394,9 +42401,9 @@ "maxLevel": "xhigh" } }, - "MiniMax-M3.1-Flash-Preview": { - "id": "MiniMax-M3.1-Flash-Preview", - "name": "MiniMax-M3.1-Flash-Preview", + "MiniMax-M3.1-Flash": { + "id": "MiniMax-M3.1-Flash", + "name": "MiniMax-M3.1-Flash", "api": "anthropic-messages", "provider": "minimax-cn", "baseUrl": "https://api.minimaxi.com/anthropic", @@ -42406,7 +42413,14 @@ "image", "video" ], - "contextWindow": 1000000 + "contextWindow": 1000000, + "maxTokens": 524288, + "cost": { + "input": 0.15, + "output": 0.6, + "cacheRead": 0.015, + "cacheWrite": 0 + } } }, "minimax-code": { diff --git a/src/codex/catalog/model-hints.ts b/src/codex/catalog/model-hints.ts index 6d9a13d060f..67d515228c0 100644 --- a/src/codex/catalog/model-hints.ts +++ b/src/codex/catalog/model-hints.ts @@ -468,13 +468,13 @@ export const CALLABLE_CONFIGURED_COMPATIBILITY_MODELS: Readonly = { "cerebras": [["gemma-4-31b",131072,40960,"text,image",1,null,0.99,1.49,0,0],["gpt-oss-120b",131072,40960,"text",1,null,0.35,0.75,0,0],["llama3.1-8b",32000,8000,"text",0,null,0.1,0.1,0,0],["qwen-3-235b-a22b-instruct-2507",131000,32000,"text",0,null,0.6,1.2,0,0],["qwen-3-coder-480b",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.6",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.7",131072,40960,"text",1,null,2.25,2.75,2.25,0]], "deepseek": [["deepseek-v4-flash",1048576,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1048576,384000,"text",1,null,0.435,0.87,0.003625,0]], "google": [["deep-research-max-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["deep-research-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["gemini-1.5-flash",1000000,8192,"text,image",0,null,0.075,0.3,0.01875,0],["gemini-1.5-flash-8b",1000000,8192,"text,image",0,null,0.0375,0.15,0.01,0],["gemini-1.5-pro",1000000,8192,"text,image",0,null,1.25,5,0.3125,0],["gemini-2.0-flash",1048576,8192,"text,image",0,null,0.1,0.4,0.025,0],["gemini-2.0-flash-lite",1048576,8192,"text,image",0,null,0.075,0.3,0,0],["gemini-2.5-computer-use-preview-10-2025",131072,65536,"text,image",1,null,1.25,10,0,0],["gemini-2.5-flash",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-2.5-flash-lite",1048576,65536,"text,image",1,null,0.1,0.4,0.01,0],["gemini-2.5-flash-lite-preview-06-17",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-lite-preview-09-2025",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-preview-04-17",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-05-20",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-09-2025",1048576,65536,"text,image",1,null,0.3,2.5,0.075,0],["gemini-2.5-pro",1048576,65536,"text,image",1,null,1.25,10,0.125,0],["gemini-2.5-pro-preview-05-06",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-2.5-pro-preview-06-05",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-3-flash-preview",1048576,65536,"text,image",1,null,0.5,3,0.05,0],["gemini-3-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-flash-lite",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-lite-image",65536,65536,"text,image",1,null,0.25,30,0,0],["gemini-3.1-flash-lite-preview",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-live-preview",131072,65536,"text,image",1,null,0.75,4.5,0,0],["gemini-3.1-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-pro-preview-customtools",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.5-flash",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-3.5-flash-lite",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-3.6-flash",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0],["gemini-3.7-flash",1048576,65536,"text,image",1],["gemini-3.8-flash",1048576,65536,"text,image",1],["gemini-4-argon",1048576,65536,"text,image",1],["gemini-flash-latest",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-flash-lite-latest",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-live-2.5-flash",128000,8000,"text,image",1,null,0.5,2,0,0],["gemini-live-2.5-flash-preview-native-audio",131072,65536,"text",1,null,0.5,2,0,0],["gemini-robotics-er-1.6-preview",131072,65536,"text,image",1,null,1,5,0,0],["gemma-3-27b-it",131072,8192,"text,image",0,null,0,0,0,0],["gemma-4-26b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-26b-a4b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-26b-it",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-E2B-it",131072,8192,"text,image",1,null,0,0,0,0],["gemma-4-E4B-it",131072,8192,"text,image",1,null,0,0,0,0]], - "minimax": [["MiniMax-M2",196608,128000,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.1",204800,131072,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.5",204800,131072,"text",1,null,0.3,1.2,0.03,0.375],["MiniMax-M2.5-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["MiniMax-M2.5-lightning",204800,32000,"text",1,null,0.3,2.4,0,0],["MiniMax-M2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["MiniMax-M2.7-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.6,2.4,0.12,0],["MiniMax-M3",1000000,128000,"text,image,video",1,null,0.3,1.2,0.06,0],["MiniMax-M3.1-Flash-Preview",1000000,null,"text,image,video",1]], + "minimax": [["MiniMax-M2",196608,128000,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.1",204800,131072,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.5",204800,131072,"text",1,null,0.3,1.2,0.03,0.375],["MiniMax-M2.5-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["MiniMax-M2.5-lightning",204800,32000,"text",1,null,0.3,2.4,0,0],["MiniMax-M2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["MiniMax-M2.7-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.6,2.4,0.12,0],["MiniMax-M3",1000000,128000,"text,image,video",1,null,0.3,1.2,0.06,0],["MiniMax-M3.1-Flash",1000000,524288,"text,image,video",1,null,0.15,0.6,0.015,0]], "mistral": [["codestral-latest",256000,4096,"text",0,null,0.3,0.9,0,0],["devstral-2512",262144,262144,"text",0,null,0.4,2,0,0],["devstral-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-medium-2507",128000,128000,"text",0,null,0.4,2,0,0],["devstral-medium-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-small-2505",128000,128000,"text",0,null,0.1,0.3,0,0],["devstral-small-2507",128000,128000,"text",0,null,0.1,0.3,0,0],["labs-devstral-small-2512",256000,256000,"text,image",0,null,0,0,0,0],["magistral-medium-latest",128000,16384,"text",1,null,2,5,0,0],["magistral-small",128000,128000,"text",1,null,0.5,1.5,0,0],["ministral-3b-latest",128000,128000,"text",0,null,0.04,0.04,0,0],["ministral-8b-latest",128000,128000,"text",0,null,0.1,0.1,0,0],["mistral-large-2411",131072,16384,"text",0,null,2,6,0,0],["mistral-large-2512",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-large-latest",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-medium-2505",131072,131072,"text,image",0,null,0.4,2,0,0],["mistral-medium-2508",262144,262144,"text,image",0,null,0.4,2,0,0],["mistral-medium-2604",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-medium-latest",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["mistral-small-2506",128000,16384,"text,image",0,null,0.1,0.3,0,0],["mistral-small-2603",256000,256000,"text,image",1,null,0.15,0.6,0,0],["mistral-small-latest",256000,256000,"text,image",1,null,0.15,0.6,0,0],["open-mistral-7b",8000,8000,"text",0,null,0.25,0.25,0,0],["open-mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["open-mixtral-8x22b",64000,64000,"text",0,null,2,6,0,0],["open-mixtral-8x7b",32000,32000,"text",0,null,0.7,0.7,0,0],["pixtral-12b",128000,128000,"text,image",0,null,0.15,0.15,0,0],["pixtral-large-latest",128000,128000,"text,image",0,null,2,6,0,0]], "moonshot": [["kimi-k2.5",262144,65536,"text,image",1,null,0,0,0,0]], "openai": [["codex-mini-latest",200000,100000,"text",1,null,1.5,6,0.375,0],["gpt-4",8192,8192,"text",0,null,30,60,0,0],["gpt-4-turbo",128000,4096,"text,image",0,null,10,30,0,0],["gpt-4.1",1047576,32768,"text,image",0,null,2,8,0.5,0],["gpt-4.1-mini",1047576,32768,"text,image",0,null,0.4,1.6,0.1,0],["gpt-4.1-nano",1047576,32768,"text,image",0,null,0.1,0.4,0.025,0],["gpt-4o",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-2024-05-13",128000,4096,"text,image",0,null,5,15,0,0],["gpt-4o-2024-08-06",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-2024-11-20",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-mini",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["gpt-5",400000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-chat-latest",128000,16384,"text,image",0,null,1.25,10,0.125,0],["gpt-5-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5-mini",400000,128000,"text,image",1,null,0.25,2,0.025,0],["gpt-5-nano",400000,128000,"text,image",1,null,0.05,0.4,0.005,0],["gpt-5-pro",400000,272000,"text,image",1,null,15,120,0,0],["gpt-5.1",400000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-chat-latest",128000,16384,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-max",272000,128000,"text,image",1,null,1.25,10,0.125,0],["gpt-5.1-codex-mini",272000,128000,"text,image",1,null,0.25,2,0.025,0],["gpt-5.2",400000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-chat-latest",128000,16384,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.2-pro",400000,128000,"text,image",1,null,21,168,0,0],["gpt-5.3-chat-latest",128000,16384,"text,image",0,null,1.75,14,0.175,0],["gpt-5.3-codex",272000,128000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.3-codex-spark",128000,32000,"text,image",1,null,1.75,14,0.175,0],["gpt-5.4",1050000,128000,"text,image",1,null,2.5,15,0.25,0],["gpt-5.4-mini",400000,128000,"text,image",1,null,0.75,4.5,0.075,0],["gpt-5.4-nano",400000,128000,"text,image",1,null,0.2,1.25,0.02,0],["gpt-5.4-pro",1050000,128000,"text,image",1,null,30,180,0,0],["gpt-5.5",1050000,128000,"text,image",1,null,5,30,0.5,0],["gpt-5.5-pro",1050000,128000,"text,image",1,null,30,180,0,0],["gpt-5.6",1050000,128000,"text,image",1,null,5,30,0.5,6.25],["gpt-5.6-luna",1050000,128000,"text,image",1,null,0.2,1.2,0.02,0.25],["gpt-5.6-sol",1050000,128000,"text,image",1,null,5,30,0.5,6.25],["gpt-5.6-terra",1050000,128000,"text,image",1,null,2,12,0.2,2.5],["gpt-6-astra",1050000,128000,"text,image",1,null,10,50,1,12.5],["gpt-6-luna",1050000,128000,"text,image",1,null,0.1,0.5,0.01,0.125],["gpt-6-sol",1050000,128000,"text,image",1,null,2,10,0.2,2.5],["gpt-6.1-sol",1050000,128000,"text,image",1,null,2,10,0.1,2.5],["gpt-realtime-2.1",128000,32000,"text,image",1,null,4,24,0.4,0],["o1",200000,100000,"text,image",1,null,15,60,7.5,0],["o1-pro",200000,100000,"text,image",1,null,150,600,0,0],["o3",200000,100000,"text,image",1,null,2,8,0.5,0],["o3-deep-research",200000,100000,"text,image",1,null,10,40,2.5,0],["o3-mini",200000,100000,"text",1,null,1.1,4.4,0.55,0],["o3-pro",200000,100000,"text,image",1,null,20,80,0,0],["o4-mini",200000,100000,"text,image",1,null,1.1,4.4,0.275,0],["o4-mini-deep-research",200000,100000,"text,image",1,null,2,8,0.5,0]], diff --git a/src/providers/model-rename-migration.ts b/src/providers/model-rename-migration.ts index 37a778766a1..3b677a6d17d 100644 --- a/src/providers/model-rename-migration.ts +++ b/src/providers/model-rename-migration.ts @@ -19,6 +19,7 @@ // Everything else in the row is left alone. import { PROVIDER_REGISTRY, normalizedProviderEndpoint } from "./registry"; +import { MINIMAX_M31_FLASH, MINIMAX_M31_FLASH_PREVIEW_RETIRED } from "./registry/model-seeds"; import { MODEL_KEYED_RECORDS, MODEL_ID_LISTS, MODEL_ID_SCALARS, MODEL_NESTED_RECORDS } from "./model-rename-fields"; import { providerConfigSeed } from "./derive"; import type { OcxConfig, OcxProviderConfig } from "../types"; @@ -138,6 +139,15 @@ export const MODEL_RENAMES: readonly ModelRename[] = [ // may also hold one as a value. 3.8 resolves tiers from its own suffix ladder instead. dropReasoningEffortMap: true, })), + // MiniMax shipped M3.1-Flash as generally available on 2026-10-19 and retired the preview + // id, so a saved MiniMax-M3.1-Flash-Preview selection would answer model-not-found. The + // stale-roster refresh only matches exact old seeds; this repairs the preview id itself. + ...(["minimax", "minimax-cn"] as const).map(provider => ({ + provider, + from: MINIMAX_M31_FLASH_PREVIEW_RETIRED, + to: MINIMAX_M31_FLASH, + reason: "MiniMax shipped M3.1-Flash as generally available and retired the preview id", + })), ]; function renameInList(value: unknown, from: string, to: string): string[] | null { diff --git a/src/providers/registry/entries-extended.ts b/src/providers/registry/entries-extended.ts index 2d28b7f0756..211b94fe5e7 100644 --- a/src/providers/registry/entries-extended.ts +++ b/src/providers/registry/entries-extended.ts @@ -38,7 +38,7 @@ import { MINIMAX_MODEL_INPUT_MODALITIES, MINIMAX_M3_REASONING_EFFORTS, MINIMAX_M3_REASONING_EFFORT_MAP, - MINIMAX_M31_FLASH_PREVIEW, + MINIMAX_M31_FLASH, MINIMAX_M31_REASONING_EFFORTS, MINIMAX_M31_DEFAULT_REASONING_EFFORT, MINIMAX_REASONING_SPLIT_MODELS, @@ -1044,18 +1044,18 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [ }, { id: "minimax", label: "MiniMax — Coding Plan", baseUrl: "https://api.minimax.io/v1", adapter: "openai-chat", authKind: "key", - dashboardUrl: "https://platform.minimax.io", defaultModel: "MiniMax-M3", models: MINIMAX_MODELS, + dashboardUrl: "https://platform.minimax.io", defaultModel: MINIMAX_M31_FLASH, models: MINIMAX_MODELS, modelContextWindows: MINIMAX_MODEL_CONTEXT_WINDOWS, modelInputModalities: MINIMAX_MODEL_INPUT_MODALITIES, - modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS, [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_M31_REASONING_EFFORTS }, - modelDefaultReasoningEfforts: { "MiniMax-M3": "medium", [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, + modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS, [MINIMAX_M31_FLASH]: MINIMAX_M31_REASONING_EFFORTS }, + modelDefaultReasoningEfforts: { "MiniMax-M3": "medium", [MINIMAX_M31_FLASH]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP }, preserveReasoningContentModels: MINIMAX_MODELS, // MiniMax-M3 low effort maps to thinking disabled, so a legitimate tool // round can carry no reasoning at all; only replay real recorded text, // never a fabricated placeholder (chatgpt-codex-connector P2 on #1205). requiresReasoningPlaceholderModels: [], - // M3.1-Flash-Preview ignores reasoning_split and always answers with reasoning_content, + // M3.1-Flash ignores reasoning_split and always answers with reasoning_content, // so it stays off the split/details lists and replays as a reasoning_content string. reasoningSplitModels: MINIMAX_REASONING_SPLIT_MODELS, // With reasoning_split the upstream returns thinking as a structured @@ -1070,11 +1070,11 @@ export const PROVIDER_REGISTRY_EXTENDED: readonly ProviderRegistryEntry[] = [ }, { id: "minimax-cn", label: "MiniMax — Coding Plan (CN)", baseUrl: "https://api.minimaxi.com/v1", adapter: "openai-chat", authKind: "key", - dashboardUrl: "https://platform.minimaxi.com", defaultModel: "MiniMax-M3", models: MINIMAX_MODELS, + dashboardUrl: "https://platform.minimaxi.com", defaultModel: MINIMAX_M31_FLASH, models: MINIMAX_MODELS, modelContextWindows: MINIMAX_MODEL_CONTEXT_WINDOWS, modelInputModalities: MINIMAX_MODEL_INPUT_MODALITIES, - modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS, [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_M31_REASONING_EFFORTS }, - modelDefaultReasoningEfforts: { "MiniMax-M3": "medium", [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, + modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS, [MINIMAX_M31_FLASH]: MINIMAX_M31_REASONING_EFFORTS }, + modelDefaultReasoningEfforts: { "MiniMax-M3": "medium", [MINIMAX_M31_FLASH]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP }, preserveReasoningContentModels: MINIMAX_MODELS, requiresReasoningPlaceholderModels: [], diff --git a/src/providers/registry/model-seeds.ts b/src/providers/registry/model-seeds.ts index 0ef89283bc4..166e90e4752 100644 --- a/src/providers/registry/model-seeds.ts +++ b/src/providers/registry/model-seeds.ts @@ -155,30 +155,33 @@ export const ZAI_GLM_5X_REASONING_EFFORTS: Record = { }; // 260710 MiniMax models and context windows: Tier-2 evidence in // devlog/_plan/260710_provider_hardening/002_research_cn.md. -// 260930 MiniMax-M3.1-Flash-Preview: Token Plan / MiniMax Code only, 1M context, thinking -// always on (effort none or thinking disabled answers 400 code 2013), omitted effort = max. -// It returns thinking as reasoning_content and ignores reasoning_split. The live /v1/models -// roster does not list it yet. Evidence: devlog/_fin/260930_minimax_m31_flash_preview/. -export const MINIMAX_M31_FLASH_PREVIEW = "MiniMax-M3.1-Flash-Preview"; +// 261021 MiniMax-M3.1-Flash: current global/CN text route, 1M context, thinking always on +// (effort none or thinking disabled answers 400), omitted effort = max. It returns thinking as +// reasoning_content and ignores reasoning_split. The live /v1/models roster may omit it. +export const MINIMAX_M31_FLASH = "MiniMax-M3.1-Flash"; +/** The preview id MiniMax retired when M3.1-Flash went GA (2026-10-19); see MODEL_RENAMES. */ +export const MINIMAX_M31_FLASH_PREVIEW_RETIRED = "MiniMax-M3.1-Flash-Preview"; +/** MiniMax's published M3.1-Flash output ceiling (512K). */ +export const MINIMAX_M31_FLASH_MAX_OUTPUT_TOKENS = 524_288; export const MINIMAX_MODELS = [ - MINIMAX_M31_FLASH_PREVIEW, + MINIMAX_M31_FLASH, "MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed", "MiniMax-M2.5", "MiniMax-M2.5-highspeed", "MiniMax-M2.1", "MiniMax-M2.1-highspeed", "MiniMax-M2", ]; -/** The eight-id roster every MiniMax preset seeded from 2026-07-10 until the preview landed. */ -export const MINIMAX_MODELS_BEFORE_M31 = MINIMAX_MODELS.filter(id => id !== MINIMAX_M31_FLASH_PREVIEW); +/** The eight-id roster every MiniMax preset seeded before Flash landed. */ +export const MINIMAX_MODELS_BEFORE_M31 = MINIMAX_MODELS.filter(id => id !== MINIMAX_M31_FLASH); /** Models that honour reasoning_split and answer with structured reasoning_details. */ export const MINIMAX_REASONING_SPLIT_MODELS = MINIMAX_MODELS_BEFORE_M31; export const MINIMAX_MODEL_CONTEXT_WINDOWS: Record = Object.fromEntries( - MINIMAX_MODELS.map(id => [id, id === "MiniMax-M3" || id === MINIMAX_M31_FLASH_PREVIEW ? 1_000_000 : 204_800]), + MINIMAX_MODELS.map(id => [id, id === "MiniMax-M3" || id === MINIMAX_M31_FLASH ? 1_000_000 : 204_800]), ); /** MiniMax's OpenAI-compatible M3 endpoints accept image_url; keep video off Codex's input enum. */ export const MINIMAX_MODEL_INPUT_MODALITIES: Record = { "MiniMax-M3": ["text", "image"], - [MINIMAX_M31_FLASH_PREVIEW]: ["text", "image"], + [MINIMAX_M31_FLASH]: ["text", "image"], }; export const MINIMAX_M3_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"]; /** Identity efforts on the wire; no map, so none omits the field instead of disabling thinking. */ diff --git a/src/providers/stale-model-roster-migration.ts b/src/providers/stale-model-roster-migration.ts index 9ab1b24fc1a..599d8204921 100644 --- a/src/providers/stale-model-roster-migration.ts +++ b/src/providers/stale-model-roster-migration.ts @@ -31,7 +31,8 @@ import { META_MUSE_MODELS, META_MUSE_WONDER_MODEL, MINIMAX_M31_DEFAULT_REASONING_EFFORT, - MINIMAX_M31_FLASH_PREVIEW, + MINIMAX_M31_FLASH, + MINIMAX_M31_FLASH_MAX_OUTPUT_TOKENS, MINIMAX_MODELS, MINIMAX_MODELS_BEFORE_M31, MINIMAX_MODEL_CONTEXT_WINDOWS, @@ -80,8 +81,8 @@ const ALIBABA_INTL_TOKEN_PLAN_MODELS_BEFORE_1017 = [ ]; /** - * MiniMax-M3.1-Flash-Preview (2026-09-30). MiniMax's /v1/models roster does not list the - * preview, so live discovery cannot add it; the catalog keeps it only when it is configured. + * MiniMax-M3.1-Flash (2026-10-21). MiniMax's /v1/models roster does not list the + * Flash, so live discovery cannot add it; the catalog keeps it only when it is configured. */ export const STALE_MODEL_ROSTERS: readonly StaleModelRoster[] = [ { @@ -104,8 +105,9 @@ export const STALE_MODEL_ROSTERS: readonly StaleModelRoster[] = [ provider, from: MINIMAX_MODELS_BEFORE_M31, to: MINIMAX_MODELS, - contextWindows: { [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_MODEL_CONTEXT_WINDOWS[MINIMAX_M31_FLASH_PREVIEW]! }, - defaultReasoningEfforts: { [MINIMAX_M31_FLASH_PREVIEW]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, + contextWindows: { [MINIMAX_M31_FLASH]: MINIMAX_MODEL_CONTEXT_WINDOWS[MINIMAX_M31_FLASH]! }, + maxOutputTokens: { [MINIMAX_M31_FLASH]: MINIMAX_M31_FLASH_MAX_OUTPUT_TOKENS }, + defaultReasoningEfforts: { [MINIMAX_M31_FLASH]: MINIMAX_M31_DEFAULT_REASONING_EFFORT }, })), ...[ { provider: "alibaba-token-plan", from: ALIBABA_TOKEN_PLAN_MODELS_BEFORE_1017, to: ALIBABA_TOKEN_PLAN_MODELS }, diff --git a/structure/providers-and-adapters.md b/structure/providers-and-adapters.md index 85a331ebe4f..d75f07cd327 100644 --- a/structure/providers-and-adapters.md +++ b/structure/providers-and-adapters.md @@ -391,7 +391,7 @@ axis that outranks every source here, so it is where a deliberate text-only over (`ocx provider edit --model --text-only` writes it) and the one declaration a restart cannot take back. -When `/models` omits MiniMax-M3.1-Flash-Preview, `src/providers/stale-model-roster-migration.ts` replaces only a saved roster identical to the old seed and fills existing window and default-effort records during startup; `CALLABLE_CONFIGURED_COMPATIBILITY_MODELS` (`src/codex/catalog/model-hints.ts`) retains it in the live catalog. The same startup projection restores DeepSeek V4 Pro only for the exact previous native seed on the official destination and registry adapter, filling missing Pro context in existing maps. Operator lists (including empty lists), custom destinations and explicit context overrides remain unchanged; normal registry enrichment supplies Pro's reasoning metadata. +When `/models` omits MiniMax-M3.1-Flash, `src/providers/stale-model-roster-migration.ts` replaces only a saved roster identical to the old seed and fills existing window, output-limit and default-effort records during startup; `CALLABLE_CONFIGURED_COMPATIBILITY_MODELS` (`src/codex/catalog/model-hints.ts`) retains it in the live catalog. `MODEL_RENAMES` (`src/providers/model-rename-migration.ts`) repairs saved rows that still name the retired MiniMax-M3.1-Flash-Preview id. The same startup projection restores DeepSeek V4 Pro only for the exact previous native seed on the official destination and registry adapter, filling missing Pro context in existing maps. Operator lists (including empty lists), custom destinations and explicit context overrides remain unchanged; normal registry enrichment supplies Pro's reasoning metadata. Both MiniMax Coding Plan presets declare `text` and `image` for M3 and M3.1 in `src/providers/registry/model-seeds.ts`; registry enrichment fills missing saved declarations, so id-only live rows enable the Combo image switch when every target supports images. Explicit overrides still win; video is outside Codex's catalog input enum. diff --git a/tests/providers/minimax-combo-image-input.test.ts b/tests/providers/minimax-combo-image-input.test.ts index 4ae06470c62..abef19e950f 100644 --- a/tests/providers/minimax-combo-image-input.test.ts +++ b/tests/providers/minimax-combo-image-input.test.ts @@ -9,7 +9,7 @@ import { isModelVisionSidecarConsumer } from "../../src/vision/eligibility"; import type { CatalogModel, OcxConfig, OcxProviderConfig } from "../../src/types"; const M3 = "MiniMax-M3"; -const PREVIEW = "MiniMax-M3.1-Flash-Preview"; +const PREVIEW = "MiniMax-M3.1-Flash"; const REGIONS = ["minimax", "minimax-cn"] as const; const originalFetch = globalThis.fetch; diff --git a/tests/providers/minimax-reasoning-split.test.ts b/tests/providers/minimax-reasoning-split.test.ts index c2decc342b1..62287b58d84 100644 --- a/tests/providers/minimax-reasoning-split.test.ts +++ b/tests/providers/minimax-reasoning-split.test.ts @@ -376,11 +376,11 @@ describe("MiniMax split reasoning", () => { }); }); -describe("MiniMax-M3.1-Flash-Preview reasoning wire", () => { +describe("MiniMax-M3.1-Flash reasoning wire", () => { // Probed 2026-09-30: thinking cannot be turned off (effort none or thinking disabled // answers 400 code 2013), effort low..max is accepted as-is, reasoning_split is ignored // and thinking always returns as reasoning_content. - const PREVIEW = "MiniMax-M3.1-Flash-Preview"; + const PREVIEW = "MiniMax-M3.1-Flash"; test("Codex efforts go out as identity reasoning_effort and never disable thinking", () => { const route = minimaxRoute(PREVIEW); diff --git a/tests/providers/model-roster-seed-repair.test.ts b/tests/providers/model-roster-seed-repair.test.ts index 7d48fc2b229..399958c5693 100644 --- a/tests/providers/model-roster-seed-repair.test.ts +++ b/tests/providers/model-roster-seed-repair.test.ts @@ -16,7 +16,7 @@ import { PROVIDER_REGISTRY } from "../../src/providers/registry"; import { enrichProviderFromRegistry } from "../../src/providers/derive"; import type { OcxConfig, OcxProviderConfig } from "../../src/types"; -const PREVIEW = "MiniMax-M3.1-Flash-Preview"; +const PREVIEW = "MiniMax-M3.1-Flash"; describe("DeepSeek Pro saved roster refresh", () => { const before = ["deepseek-chat", "deepseek-reasoner", "deepseek-flash", "deepseek-v4-flash", "deepseek-v4-flash-vision-exp"]; @@ -140,6 +140,42 @@ describe("stale model roster migration", () => { expect(projection.config.providers!.minimax!.modelDefaultReasoningEfforts).toEqual({ [PREVIEW]: "low" }); }); + test("fills the Flash output limit into an existing partial output map", () => { + // Custom catalog rows read the saved map directly; without this the added id would + // publish with no output ceiling (CodeRabbit on #7739). + const projection = projectStaleModelRosters(minimaxConfig("minimax", { + models: [...MINIMAX_MODELS_BEFORE_M31], + modelMaxOutputTokens: { "MiniMax-M3": 128_000 }, + })); + expect(projection.config.providers!.minimax!.modelMaxOutputTokens).toEqual({ + "MiniMax-M3": 128_000, [PREVIEW]: 524_288, + }); + }); + + test("renames a saved MiniMax-M3.1-Flash-Preview selection to the GA id on both presets", () => { + const RETIRED = "MiniMax-M3.1-Flash-Preview"; + for (const [provider, baseUrl] of [["minimax", "https://api.minimax.io/v1"], ["minimax-cn", "https://api.minimaxi.com/v1"]] as const) { + const config = minimaxConfig(provider, { + baseUrl, + authMode: "key", + defaultModel: RETIRED, + models: MINIMAX_MODELS.map(id => (id === PREVIEW ? RETIRED : id)), + modelContextWindows: { [RETIRED]: 1_000_000, "MiniMax-M3": 1_000_000 }, + modelDefaultReasoningEfforts: { [RETIRED]: "high" }, + }); + const projection = projectStartupConfigRepairs(config); + const row = projection.config.providers![provider]!; + expect(projection.changed).toBe(true); + expect(JSON.stringify(projection.config)).not.toContain(RETIRED); + expect(row.models).toEqual(MINIMAX_MODELS); + expect(row.defaultModel).toBe(PREVIEW); + expect(row.modelContextWindows).toEqual({ [PREVIEW]: 1_000_000, "MiniMax-M3": 1_000_000 }); + // The user's saved effort survives the rename rather than being reset to the seed. + expect(row.modelDefaultReasoningEfforts).toEqual({ [PREVIEW]: "high" }); + expect(projectStartupConfigRepairs(structuredClone(projection.config)).changed).toBe(false); + } + }); + test("leaves a hand-edited roster alone", () => { const trimmed = MINIMAX_MODELS_BEFORE_M31.filter(id => id !== "MiniMax-M2"); const reordered = [...MINIMAX_MODELS_BEFORE_M31].reverse(); diff --git a/tests/providers/provider-registry-parity.test.ts b/tests/providers/provider-registry-parity.test.ts index b950f35b714..cf40389c886 100644 --- a/tests/providers/provider-registry-parity.test.ts +++ b/tests/providers/provider-registry-parity.test.ts @@ -201,7 +201,7 @@ describe("provider registry parity", () => { expect(KEY_LOGIN_PROVIDERS).toEqual(deriveKeyLoginMap()); expect(Object.keys(KEY_LOGIN_PROVIDERS)).toEqual(EXPECTED_KEY_PROVIDER_IDS); expect(Object.keys(deriveKeyLoginMap())).toEqual(EXPECTED_KEY_PROVIDER_IDS); - expect(KEY_LOGIN_PROVIDERS.minimax.defaultModel).toBe("MiniMax-M3"); + expect(KEY_LOGIN_PROVIDERS.minimax.defaultModel).toBe("MiniMax-M3.1-Flash"); expect(KEY_LOGIN_PROVIDERS.umans).toMatchObject({ label: "Umans AI Coding Plan", adapter: "anthropic", @@ -507,7 +507,7 @@ describe("provider registry parity", () => { }); const minimaxModels = [ - "MiniMax-M3.1-Flash-Preview", + "MiniMax-M3.1-Flash", "MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed", "MiniMax-M2.5", "MiniMax-M2.5-highspeed", @@ -519,16 +519,16 @@ describe("provider registry parity", () => { const entry = PROVIDER_REGISTRY.find(provider => provider.id === providerId); expect(entry?.adapter).toBe("openai-chat"); expect(entry?.baseUrl).toBe(providerId === "minimax" ? "https://api.minimax.io/v1" : "https://api.minimaxi.com/v1"); - expect(entry?.defaultModel).toBe("MiniMax-M3"); + expect(entry?.defaultModel).toBe("MiniMax-M3.1-Flash"); expect(entry?.models).toEqual(minimaxModels); expect(entry?.modelContextWindows?.["MiniMax-M3"]).toBe(1_000_000); - expect(entry?.modelContextWindows?.["MiniMax-M3.1-Flash-Preview"]).toBe(1_000_000); + expect(entry?.modelContextWindows?.["MiniMax-M3.1-Flash"]).toBe(1_000_000); expect(entry?.modelReasoningEfforts?.["MiniMax-M3"]).toEqual(["low", "medium", "high", "xhigh", "max"]); - expect(entry?.modelReasoningEfforts?.["MiniMax-M3.1-Flash-Preview"]).toEqual(["low", "medium", "high", "xhigh", "max"]); + expect(entry?.modelReasoningEfforts?.["MiniMax-M3.1-Flash"]).toEqual(["low", "medium", "high", "xhigh", "max"]); expect(entry?.modelDefaultReasoningEfforts?.["MiniMax-M3"]).toBe("medium"); - expect(entry?.modelDefaultReasoningEfforts?.["MiniMax-M3.1-Flash-Preview"]).toBe("max"); + expect(entry?.modelDefaultReasoningEfforts?.["MiniMax-M3.1-Flash"]).toBe("max"); expect(entry?.modelReasoningEffortMap?.["MiniMax-M3"]).toMatchObject({ low: "disabled", medium: "adaptive", high: "adaptive" }); - expect(entry?.modelReasoningEffortMap?.["MiniMax-M3.1-Flash-Preview"]).toBeUndefined(); + expect(entry?.modelReasoningEffortMap?.["MiniMax-M3.1-Flash"]).toBeUndefined(); expect(entry?.preserveReasoningContentModels).toEqual(minimaxModels); expect(entry?.reasoningSplitModels).toEqual(splitModels); expect(entry?.reasoningDetailsModels).toEqual(splitModels);