From cb44091ce95b63aabd6785ec06194129d32873ec Mon Sep 17 00:00:00 2001 From: octo-patch Date: Tue, 2 Jun 2026 02:54:33 +0800 Subject: [PATCH] feat: upgrade MiniMax default model to M3 - Add MiniMax-M3 to model presets, hermes provider registry, and dev-api - Set MiniMax-M3 as the new default (first entry in each list) - Retain MiniMax-M2.7 / M2.7-highspeed as available alternatives - Remove deprecated MiniMax-M2.5 / M2.1 / M2 variants from selection lists - Update model-presets unit tests to cover M3 and drop M2.5 assertions --- scripts/dev-api.js | 6 +++--- src-tauri/src/commands/hermes_providers.rs | 21 +++------------------ src/lib/model-presets.js | 5 ++--- tests/model-presets.test.js | 18 ++++++++++-------- 4 files changed, 18 insertions(+), 32 deletions(-) diff --git a/scripts/dev-api.js b/scripts/dev-api.js index 40200839..30de0e12 100644 --- a/scripts/dev-api.js +++ b/scripts/dev-api.js @@ -31,7 +31,7 @@ const HERMES_PROVIDER_REGISTRY = [ hermesProvider('gemini', 'Google AI Studio', 'api_key', 'https://generativelanguage.googleapis.com/v1beta/openai', 'GEMINI_BASE_URL', ['GOOGLE_API_KEY', 'GEMINI_API_KEY'], 'openai_chat', 'openai', ['gemini-3.1-pro-preview', 'gemini-3-flash-preview', 'gemini-3.1-flash-lite-preview', 'gemini-2.5-pro', 'gemini-2.5-flash', 'gemini-2.5-flash-lite', 'gemma-4-31b-it', 'gemma-4-26b-it']), hermesProvider('deepseek', 'DeepSeek', 'api_key', 'https://api.deepseek.com', 'DEEPSEEK_BASE_URL', ['DEEPSEEK_API_KEY'], 'openai_chat', 'openai', ['deepseek-chat', 'deepseek-reasoner']), hermesProvider('xai', 'xAI', 'api_key', 'https://api.x.ai/v1', 'XAI_BASE_URL', ['XAI_API_KEY'], 'openai_chat', 'openai', ['grok-4.20-reasoning', 'grok-4-1-fast-reasoning']), - hermesProvider('minimax', 'MiniMax (International)', 'api_key', 'https://api.minimax.io/anthropic/v1', 'MINIMAX_BASE_URL', ['MINIMAX_API_KEY'], 'anthropic_messages', 'anthropic', ['MiniMax-M2.7', 'MiniMax-M2.7-highspeed', 'MiniMax-M2.5', 'MiniMax-M2.5-highspeed', 'MiniMax-M2.1', 'MiniMax-M2.1-highspeed', 'MiniMax-M2', 'MiniMax-M2-highspeed']), + hermesProvider('minimax', 'MiniMax (International)', 'api_key', 'https://api.minimax.io/anthropic/v1', 'MINIMAX_BASE_URL', ['MINIMAX_API_KEY'], 'anthropic_messages', 'anthropic', ['MiniMax-M3', 'MiniMax-M2.7', 'MiniMax-M2.7-highspeed']), hermesProvider('huggingface', 'Hugging Face', 'api_key', 'https://router.huggingface.co/v1', 'HF_BASE_URL', ['HF_TOKEN'], 'openai_chat', 'openai', ['Qwen/Qwen3.5-397B-A17B', 'Qwen/Qwen3.5-35B-A3B', 'deepseek-ai/DeepSeek-V3.2', 'moonshotai/Kimi-K2.5', 'MiniMaxAI/MiniMax-M2.5', 'zai-org/GLM-5', 'XiaomiMiMo/MiMo-V2-Flash', 'moonshotai/Kimi-K2-Thinking'], true), hermesProvider('arcee', 'Arcee AI', 'api_key', 'https://api.arcee.ai/api/v1', 'ARCEE_BASE_URL', ['ARCEEAI_API_KEY'], 'openai_chat', 'openai', []), hermesProvider('azure-foundry', 'Azure Foundry', 'api_key', '', 'AZURE_FOUNDRY_BASE_URL', ['AZURE_FOUNDRY_API_KEY'], 'openai_chat', 'openai', [], true), @@ -45,7 +45,7 @@ const HERMES_PROVIDER_REGISTRY = [ hermesProvider('kimi-coding-cn', 'Kimi / Moonshot (China)', 'api_key', 'https://api.moonshot.cn/v1', '', ['KIMI_CN_API_KEY'], 'openai_chat', 'openai', ['kimi-for-coding', 'kimi-k2.6', 'kimi-k2.5', 'kimi-k2-thinking', 'kimi-k2-turbo-preview']), hermesProvider('alibaba', 'Alibaba Cloud (DashScope)', 'api_key', 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1', 'DASHSCOPE_BASE_URL', ['DASHSCOPE_API_KEY'], 'openai_chat', 'openai', ['qwen3.5-plus', 'qwen3-coder-plus', 'qwen3-coder-next', 'glm-5', 'glm-4.7', 'kimi-k2.5', 'MiniMax-M2.5']), hermesProvider('alibaba-coding-plan', 'Alibaba Cloud (Coding Plan)', 'api_key', 'https://coding-intl.dashscope.aliyuncs.com/v1', 'ALIBABA_CODING_PLAN_BASE_URL', ['ALIBABA_CODING_PLAN_API_KEY', 'DASHSCOPE_API_KEY'], 'openai_chat', 'openai', ['qwen3-coder-plus', 'qwen3-coder-next', 'qwen3.5-plus', 'qwen3.5-coder']), - hermesProvider('minimax-cn', 'MiniMax (China)', 'api_key', 'https://api.minimaxi.com/v1', 'MINIMAX_CN_BASE_URL', ['MINIMAX_CN_API_KEY'], 'anthropic_messages', 'anthropic', ['MiniMax-M2.7', 'MiniMax-M2.7-highspeed', 'MiniMax-M2.5', 'MiniMax-M2.5-highspeed', 'MiniMax-M2.1', 'MiniMax-M2.1-highspeed', 'MiniMax-M2', 'MiniMax-M2-highspeed']), + hermesProvider('minimax-cn', 'MiniMax (China)', 'api_key', 'https://api.minimaxi.com/v1', 'MINIMAX_CN_BASE_URL', ['MINIMAX_CN_API_KEY'], 'anthropic_messages', 'anthropic', ['MiniMax-M3', 'MiniMax-M2.7', 'MiniMax-M2.7-highspeed']), hermesProvider('xiaomi', 'Xiaomi MiMo', 'api_key', 'https://api.xiaomimimo.com/v1', 'XIAOMI_BASE_URL', ['XIAOMI_API_KEY'], 'openai_chat', 'openai', ['mimo-v2-pro', 'mimo-v2-omni', 'mimo-v2-flash']), hermesProvider('bedrock', 'AWS Bedrock', 'aws_sdk', 'https://bedrock-runtime.us-east-1.amazonaws.com', 'BEDROCK_BASE_URL', [], 'anthropic_messages', 'none', []), hermesProvider('openrouter', 'OpenRouter', 'api_key', 'https://openrouter.ai/api/v1', 'OPENAI_BASE_URL', ['OPENROUTER_API_KEY'], 'openai_chat', 'openai', [], true), @@ -57,7 +57,7 @@ const HERMES_PROVIDER_REGISTRY = [ hermesProvider('openai-codex', 'OpenAI Codex', 'oauth_external', 'https://chatgpt.com/backend-api/codex', '', [], 'codex_responses', 'none', ['gpt-5.5', 'gpt-5.4-mini', 'gpt-5.4', 'gpt-5.3-codex', 'gpt-5.2-codex', 'gpt-5.1-codex-max', 'gpt-5.1-codex-mini'], false, 'hermes auth login openai-codex'), hermesProvider('qwen-oauth', 'Qwen OAuth', 'oauth_external', 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1', '', [], 'openai_chat', 'none', ['qwen3.5-plus', 'qwen3-coder-plus', 'qwen3-coder-next'], false, 'hermes auth login qwen-oauth'), hermesProvider('google-gemini-cli', 'Google Gemini (OAuth)', 'oauth_external', 'https://generativelanguage.googleapis.com/v1beta/openai', '', [], 'openai_chat', 'none', ['gemini-2.5-pro', 'gemini-2.5-flash'], false, 'hermes auth login google-gemini-cli'), - hermesProvider('minimax-oauth', 'MiniMax (OAuth)', 'oauth_minimax', 'https://api.minimax.io/anthropic', '', [], 'anthropic_messages', 'none', ['MiniMax-M2.7', 'MiniMax-M2.7-highspeed', 'MiniMax-M2.5', 'MiniMax-M2.5-highspeed', 'MiniMax-M2.1', 'MiniMax-M2.1-highspeed', 'MiniMax-M2', 'MiniMax-M2-highspeed'], false, 'hermes auth login minimax-oauth'), + hermesProvider('minimax-oauth', 'MiniMax (OAuth)', 'oauth_minimax', 'https://api.minimax.io/anthropic', '', [], 'anthropic_messages', 'none', ['MiniMax-M3', 'MiniMax-M2.7', 'MiniMax-M2.7-highspeed'], false, 'hermes auth login minimax-oauth'), hermesProvider('copilot-acp', 'GitHub Copilot ACP', 'external_process', 'http://127.0.0.1:0', 'COPILOT_ACP_BASE_URL', [], 'openai_chat', 'none', ['gpt-4o', 'gpt-4.1', 'claude-3.5-sonnet', 'claude-3.7-sonnet'], false, 'hermes auth login copilot-acp'), hermesProvider('custom', 'Custom OpenAI-Compatible', 'api_key', '', 'OPENAI_BASE_URL', ['OPENAI_API_KEY', 'CUSTOM_API_KEY'], 'openai_chat', 'openai', [], true), ] diff --git a/src-tauri/src/commands/hermes_providers.rs b/src-tauri/src/commands/hermes_providers.rs index 2e2516ee..e690b9f0 100644 --- a/src-tauri/src/commands/hermes_providers.rs +++ b/src-tauri/src/commands/hermes_providers.rs @@ -222,14 +222,9 @@ const P_MINIMAX: HermesProvider = HermesProvider { transport: TRANSPORT_ANTHROPIC, models_probe: PROBE_ANTHROPIC, models: &[ + "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", - "MiniMax-M2-highspeed", ], is_aggregator: false, cli_auth_hint: "", @@ -245,14 +240,9 @@ const P_MINIMAX_CN: HermesProvider = HermesProvider { transport: TRANSPORT_ANTHROPIC, models_probe: PROBE_ANTHROPIC, models: &[ + "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", - "MiniMax-M2-highspeed", ], is_aggregator: false, cli_auth_hint: "", @@ -268,14 +258,9 @@ const P_MINIMAX_OAUTH: HermesProvider = HermesProvider { transport: TRANSPORT_ANTHROPIC, models_probe: PROBE_NONE, models: &[ + "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", - "MiniMax-M2-highspeed", ], is_aggregator: false, cli_auth_hint: "hermes auth login minimax-oauth", diff --git a/src/lib/model-presets.js b/src/lib/model-presets.js index 5a55037e..03a0541a 100644 --- a/src/lib/model-presets.js +++ b/src/lib/model-presets.js @@ -23,7 +23,7 @@ export const PROVIDER_PRESETS = [ { key: 'volcengine', label: '火山引擎', baseUrl: 'https://ark.cn-beijing.volces.com/api/v3', api: 'openai-completions', site: 'https://volcengine.com/L/Ph1OP5I3_GY', desc: '字节跳动旗下云平台,支持豆包等模型' }, { key: 'aliyun', label: '阿里云百炼', baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1', api: 'openai-completions', site: 'https://www.aliyun.com/benefit/ai/aistar?userCode=keahn2zr&clubBiz=subTask..12435175..10263..', desc: '阿里云 AI 大模型平台,支持通义千问全系列' }, { key: 'zhipu', label: '智谱 AI', baseUrl: 'https://open.bigmodel.cn/api/paas/v4', api: 'openai-completions', site: 'https://www.bigmodel.cn/glm-coding?ic=3F6F9XYKTS', desc: '国产大模型领军企业,支持 GLM-4 全系列' }, - { key: 'minimax', label: 'MiniMax', baseUrl: 'https://api.minimax.io/v1', api: 'openai-completions', site: 'https://platform.minimaxi.com/user-center/basic-information/interface-key', desc: '国产多模态大模型,支持 MiniMax-M2.7 / M2.5 系列' }, + { key: 'minimax', label: 'MiniMax', baseUrl: 'https://api.minimax.io/v1', api: 'openai-completions', site: 'https://platform.minimaxi.com/user-center/basic-information/interface-key', desc: '国产多模态大模型,支持 MiniMax-M3 / M2.7 系列' }, { key: 'moonshot', label: 'Moonshot / Kimi', baseUrl: 'https://api.moonshot.ai/v1', api: 'openai-completions', site: 'https://platform.moonshot.ai/console/api-keys', desc: 'Kimi 大模型平台,支持超长上下文' }, { key: 'openai', label: 'OpenAI 官方', baseUrl: 'https://api.openai.com/v1', api: 'openai-completions', site: 'https://platform.openai.com/api-keys' }, { key: 'anthropic', label: 'Anthropic 官方', baseUrl: 'https://api.anthropic.com/v1', api: 'anthropic-messages', site: 'https://console.anthropic.com/settings/keys' }, @@ -78,10 +78,9 @@ export const MODEL_PRESETS = { { id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', contextWindow: 1000000 }, ], minimax: [ + { id: 'MiniMax-M3', name: 'MiniMax M3', contextWindow: 524288 }, { id: 'MiniMax-M2.7', name: 'MiniMax M2.7', contextWindow: 1000000 }, { id: 'MiniMax-M2.7-highspeed', name: 'MiniMax M2.7 Highspeed', contextWindow: 1000000 }, - { id: 'MiniMax-M2.5', name: 'MiniMax M2.5', contextWindow: 204000 }, - { id: 'MiniMax-M2.5-highspeed', name: 'MiniMax M2.5 Highspeed', contextWindow: 204000 }, ], moonshot: [ { id: 'kimi-k2.5', name: 'Kimi K2.5', contextWindow: 131072 }, diff --git a/tests/model-presets.test.js b/tests/model-presets.test.js index ea8cdd3b..9ae3857e 100644 --- a/tests/model-presets.test.js +++ b/tests/model-presets.test.js @@ -52,12 +52,15 @@ test('MODEL_PRESETS contains MiniMax models', () => { assert.ok(MODEL_PRESETS.minimax.length >= 2, 'should have at least 2 MiniMax models') }) -test('MiniMax model presets include M2.7 and M2.5 variants', () => { +test('MiniMax model presets include M3 and M2.7 variants', () => { const ids = MODEL_PRESETS.minimax.map(m => m.id) + assert.ok(ids.includes('MiniMax-M3'), 'should include MiniMax-M3') assert.ok(ids.includes('MiniMax-M2.7'), 'should include MiniMax-M2.7') assert.ok(ids.includes('MiniMax-M2.7-highspeed'), 'should include MiniMax-M2.7-highspeed') - assert.ok(ids.includes('MiniMax-M2.5'), 'should include MiniMax-M2.5') - assert.ok(ids.includes('MiniMax-M2.5-highspeed'), 'should include MiniMax-M2.5-highspeed') +}) + +test('MiniMax M3 is listed as the new default (first entry)', () => { + assert.equal(MODEL_PRESETS.minimax[0].id, 'MiniMax-M3', 'MiniMax-M3 should be the first model') }) test('MiniMax model presets have required fields', () => { @@ -76,11 +79,10 @@ test('MiniMax M2.7 models have 1M context window', () => { assert.equal(m27hs.contextWindow, 1000000) }) -test('MiniMax M2.5 models have 204K context window', () => { - const m25 = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M2.5') - assert.equal(m25.contextWindow, 204000) - const m25hs = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M2.5-highspeed') - assert.equal(m25hs.contextWindow, 204000) +test('MiniMax M3 has 524K context window', () => { + const m3 = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M3') + assert.ok(m3, 'should include MiniMax-M3') + assert.equal(m3.contextWindow, 524288) }) test('all model preset groups have valid structure', () => {