Skip to content
Open
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
10 changes: 5 additions & 5 deletions src-tauri/src/commands/hermes_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ const P_MINIMAX: HermesProvider = HermesProvider {
id: "minimax",
name: "MiniMax (International)",
auth_type: AUTH_API_KEY,
base_url: "https://api.minimax.io/anthropic/v1",
base_url: "https://api.minimax.io/anthropic",
base_url_env_var: "MINIMAX_BASE_URL",
api_key_env_vars: &["MINIMAX_API_KEY"],
transport: TRANSPORT_ANTHROPIC,
models_probe: PROBE_ANTHROPIC,
models: &["MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
models: &["MiniMax-M3", "MiniMax-M2.7"],
is_aggregator: false,
cli_auth_hint: "",
};
Expand All @@ -235,12 +235,12 @@ const P_MINIMAX_CN: HermesProvider = HermesProvider {
id: "minimax-cn",
name: "MiniMax (China)",
auth_type: AUTH_API_KEY,
base_url: "https://api.minimaxi.com/v1",
base_url: "https://api.minimaxi.com/anthropic",
base_url_env_var: "MINIMAX_CN_BASE_URL",
api_key_env_vars: &["MINIMAX_CN_API_KEY"],
transport: TRANSPORT_ANTHROPIC,
models_probe: PROBE_ANTHROPIC,
models: &["MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
models: &["MiniMax-M3", "MiniMax-M2.7"],
is_aggregator: false,
cli_auth_hint: "",
};
Expand All @@ -254,7 +254,7 @@ const P_MINIMAX_OAUTH: HermesProvider = HermesProvider {
api_key_env_vars: &[],
transport: TRANSPORT_ANTHROPIC,
models_probe: PROBE_NONE,
models: &["MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
models: &["MiniMax-M3", "MiniMax-M2.7"],
is_aggregator: false,
cli_auth_hint: "hermes auth login minimax-oauth",
};
Expand Down
7 changes: 3 additions & 4 deletions src/lib/model-presets.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,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-M3 / M2.7 系列' },
{ key: 'minimax', label: 'MiniMax', baseUrl: 'https://api.minimax.io/v1', api: 'openai-completions', site: 'https://platform.minimax.io/docs/api-reference/api-overview', desc: 'Multimodal models with support for the MiniMax-M3 and M2.7 series' },
{ 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' },
Expand Down Expand Up @@ -107,9 +107,8 @@ 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-M3', name: 'MiniMax M3', contextWindow: 1000000, reasoning: true, input: ['text', 'image', 'video'], cost: { input: 0.6, output: 2.4, cacheRead: 0.12 } },
{ id: 'MiniMax-M2.7', name: 'MiniMax M2.7', contextWindow: 204800, reasoning: true, input: ['text'], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 } },
],
moonshot: [
{ id: 'kimi-k2.5', name: 'Kimi K2.5', contextWindow: 131072 },
Expand Down
20 changes: 20 additions & 0 deletions tests/minimax-provider-endpoints.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'

test('Hermes MiniMax providers use the regional Anthropic endpoints', async () => {
const source = await readFile(new URL('../src-tauri/src/commands/hermes_providers.rs', import.meta.url), 'utf8')
assert.match(source, /id: "minimax",[\s\S]*?base_url: "https:\/\/api\.minimax\.io\/anthropic"/)
assert.match(source, /id: "minimax-cn",[\s\S]*?base_url: "https:\/\/api\.minimaxi\.com\/anthropic"/)
})

test('Hermes MiniMax providers use the supported model list', async () => {
const source = await readFile(new URL('../src-tauri/src/commands/hermes_providers.rs', import.meta.url), 'utf8')

for (const id of ['minimax', 'minimax-cn', 'minimax-oauth']) {
const block = source.match(new RegExp(`id: "${id}",[\\s\\S]*?\\n};`))?.[0]
assert.ok(block, `missing Hermes provider ${id}`)
assert.match(block, /models: &\["MiniMax-M3", "MiniMax-M2\.7"\],/)
assert.doesNotMatch(block, /MiniMax-M2\.7-highspeed/)
}
})
24 changes: 10 additions & 14 deletions tests/model-presets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test('MiniMax provider preset uses correct API base URL', () => {

test('MiniMax provider preset has site and description', () => {
const minimax = PROVIDER_PRESETS.find(p => p.key === 'minimax')
assert.ok(minimax.site, 'MiniMax should have a site URL')
assert.equal(minimax.site, 'https://platform.minimax.io/docs/api-reference/api-overview')
assert.ok(minimax.desc, 'MiniMax should have a description')
})

Expand Down Expand Up @@ -79,11 +79,9 @@ 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 M3 and M2.7 variants', () => {
test('MiniMax model presets match the supported model list', () => {
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.deepEqual(ids, ['MiniMax-M3', 'MiniMax-M2.7'])
})

test('MiniMax M3 is listed as the new default (first entry)', () => {
Expand All @@ -99,17 +97,15 @@ test('MiniMax model presets have required fields', () => {
}
})

test('MiniMax M2.7 models have 1M context window', () => {
test('MiniMax models use current context windows and metadata', () => {
const m27 = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M2.7')
assert.equal(m27.contextWindow, 1000000)
const m27hs = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M2.7-highspeed')
assert.equal(m27hs.contextWindow, 1000000)
})

test('MiniMax M3 has 524K context window', () => {
assert.equal(m27.contextWindow, 204800)
assert.deepEqual(m27.input, ['text'])
assert.deepEqual(m27.cost, { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 })
const m3 = MODEL_PRESETS.minimax.find(m => m.id === 'MiniMax-M3')
assert.ok(m3, 'should include MiniMax-M3')
assert.equal(m3.contextWindow, 524288)
assert.equal(m3.contextWindow, 1000000)
assert.deepEqual(m3.input, ['text', 'image', 'video'])
assert.deepEqual(m3.cost, { input: 0.6, output: 2.4, cacheRead: 0.12 })
})

test('all model preset groups have valid structure', () => {
Expand Down
Loading