Skip to content
Merged
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
17 changes: 5 additions & 12 deletions src/agent/configurator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,7 @@ function updateHermesYaml(
`Hermes model override for ${candidate.id} must be an object.`,
);
}
const hermesContextWindow = candidate.id === 'MiniMax-M3.1-Flash-Preview'
|| candidate.id === 'MiniMax-M3'
? 1_000_000
: candidate.contextWindow;
const hermesContextWindow = 1_000_000;
document.setIn(
['model_overrides', provider, candidate.id, 'context_window'],
hermesContextWindow,
Expand Down Expand Up @@ -534,14 +531,10 @@ function prepareClaude(options: AgentSetupOptions, path: string): PreparedAgentF
const pickerOptions = MINIMAX_MODELS.map(candidate => ({
model: claudeModelId(candidate.id),
label: candidate.id,
description: candidate.id.endsWith('-highspeed')
? '204.8K context · faster inference'
: candidate.id === 'MiniMax-M3.1-Flash-Preview' || candidate.id === 'MiniMax-M3'
? candidate.id === options.model
? `1M supported · ${candidate.id === 'MiniMax-M3.1-Flash-Preview'
&& (options.m31ContextWindow ?? 524288) !== 1_000_000 ? '512K' : '1M'} compact`
: '1M supported'
: '204.8K context',
description: candidate.id === options.model
? `1M supported · ${candidate.id === 'MiniMax-M3.1-Flash-Preview'
&& (options.m31ContextWindow ?? 524288) !== 1_000_000 ? '512K' : '1M'} compact`
: '1M supported',
}));
const managedPickerModels = new Set(MINIMAX_MODELS.flatMap(candidate => [
candidate.id,
Expand Down
20 changes: 0 additions & 20 deletions src/agent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,6 @@ export const MINIMAX_MODELS = [
],
},
},
{
id: 'MiniMax-M2.7',
contextWindow: 204800,
maxTokens: 131072,
input: ['text'],
codex: {
defaultReasoningLevel: 'high',
supportedReasoningLevels: [{ effort: 'high', description: 'Always on' }],
},
},
{
id: 'MiniMax-M2.7-highspeed',
contextWindow: 204800,
maxTokens: 131072,
input: ['text'],
codex: {
defaultReasoningLevel: 'high',
supportedReasoningLevels: [{ effort: 'high', description: 'Always on' }],
},
},
] as const;

export const DEFAULT_MINIMAX_MODEL = MINIMAX_MODELS[0].id;
Expand Down
72 changes: 9 additions & 63 deletions test/agent/configurator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('agent configurator', () => {
'{\n "theme": "dark",\n "modelPicker": {\n'
+ ' "options": [\n'
+ ' { "model": "keep-model", "label": "Keep" },\n'
+ ' { "model": "MiniMax-M2.7", "label": "Old MiniMax" }\n'
+ ' { "model": "MiniMax-M3", "label": "Old MiniMax" }\n'
+ ' ],\n "replaceBuiltInOptions": false\n }\n}\n',
);
writeFileSync(join(home, '.codex', 'config.toml'), '[mcp_servers.keep]\ncommand = "keep"\n');
Expand Down Expand Up @@ -95,23 +95,6 @@ describe('agent configurator', () => {
}
});

it('does not add the 1M suffix when Claude Code uses M2.7', () => {
applyAgentConfigurations(prepareAgentConfigurations(setupOptions(
['claude-code'],
{ model: 'MiniMax-M2.7' },
)));

const claude = JSON.parse(readFileSync(join(home, '.claude', 'settings.json'), 'utf8'));
for (const key of [
'ANTHROPIC_MODEL',
'ANTHROPIC_DEFAULT_SONNET_MODEL',
'ANTHROPIC_DEFAULT_OPUS_MODEL',
'ANTHROPIC_DEFAULT_HAIKU_MODEL',
]) {
expect(claude.env[key]).toBe('MiniMax-M2.7');
}
});

it('applies the M3.1 window choice to Claude Code, Codex, and OpenCode', () => {
const options = setupOptions(['claude-code', 'codex', 'opencode'], {
model: 'MiniMax-M3.1-Flash-Preview',
Expand Down Expand Up @@ -181,12 +164,6 @@ describe('agent configurator', () => {
description: '1M supported',
},
{ model: 'MiniMax-M3[1m]', label: 'MiniMax-M3', description: '1M supported · 1M compact' },
{ model: 'MiniMax-M2.7', label: 'MiniMax-M2.7', description: '204.8K context' },
{
model: 'MiniMax-M2.7-highspeed',
label: 'MiniMax-M2.7-highspeed',
description: '204.8K context · faster inference',
},
],
replaceBuiltInOptions: false,
});
Expand All @@ -205,7 +182,7 @@ describe('agent configurator', () => {
readFileSync(join(home, '.codex', 'mmx-model-catalog.json'), 'utf8'),
);
expect(codexCatalog._managed_by).toBe('mmx agent setup');
expect(codexCatalog.models).toHaveLength(4);
expect(codexCatalog.models).toHaveLength(2);
expect(codexCatalog.models[0]).toMatchObject({
slug: 'MiniMax-M3.1-Flash-Preview',
description: 'MiniMax M3.1 Flash Preview',
Expand Down Expand Up @@ -251,17 +228,7 @@ describe('agent configurator', () => {
{ effort: 'high', description: 'Deep' },
],
});
expect(codexCatalog.models[2]).toMatchObject({
slug: 'MiniMax-M2.7',
priority: 2,
context_window: 204800,
max_context_window: 204800,
input_modalities: ['text'],
supported_reasoning_levels: [{ effort: 'high', description: 'Always on' }],
});
expect(codexCatalog.models[3].slug).toBe('MiniMax-M2.7-highspeed');
expect(codexCatalog.models[3].supported_reasoning_levels)
.toEqual([{ effort: 'high', description: 'Always on' }]);
expect(codexCatalog.models).toHaveLength(2);
expect(codexCatalog.models[1].apply_patch_tool_type).toBe('freeform');

const m31Home = join(tmpdir(), `mmx-agent-config-m31-${process.pid}-${Date.now()}`);
Expand All @@ -282,10 +249,6 @@ describe('agent configurator', () => {
.toBe('chat_completions');
expect((grok.model as Record<string, Record<string, unknown>>).minimax.max_completion_tokens)
.toBe(128000);
expect((grok.model as Record<string, Record<string, unknown>>)['minimax-m2-7'].model)
.toBe('MiniMax-M2.7');
expect((grok.model as Record<string, Record<string, unknown>>)['minimax-m2-7-highspeed'].model)
.toBe('MiniMax-M2.7-highspeed');

const openCodeText = readFileSync(join(home, '.config', 'opencode', 'opencode.json'), 'utf8');
const openCode = JSON.parse(openCodeText.replace(/^\s*\/\/.*$/gm, ''));
Expand All @@ -311,13 +274,8 @@ describe('agent configurator', () => {
for (const effort of ['low', 'medium', 'high', 'xhigh', 'max']) {
expect(m31OpenCode.variants[effort].reasoningEffort).toBe(effort);
}
expect(openCode.provider.minimax.models['MiniMax-M2.7'].attachment).toBe(false);
expect(openCode.provider.minimax.models['MiniMax-M2.7'].modalities)
.toEqual({ input: ['text'], output: ['text'] });
expect(openCode.provider.minimax.models['MiniMax-M2.7'].limit)
.toEqual({ context: 204800, output: 131072 });
expect(openCode.provider.minimax.models['MiniMax-M2.7-highspeed'].limit)
.toEqual({ context: 204800, output: 131072 });
expect(Object.keys(openCode.provider.minimax.models).sort())
.toEqual(['MiniMax-M3', 'MiniMax-M3.1-Flash-Preview', 'keep-model']);

const hermes = parseYaml(readFileSync(join(home, '.hermes', 'config.yaml'), 'utf8'));
expect(hermes.model.provider).toBe('minimax-cn');
Expand All @@ -328,19 +286,13 @@ describe('agent configurator', () => {
.toEqual([
'MiniMax-M3.1-Flash-Preview',
'MiniMax-M3',
'MiniMax-M2.7',
'MiniMax-M2.7-highspeed',
]);
expect(hermes.model_overrides['minimax-cn']['MiniMax-M3'].context_window)
.toBe(1_000_000);
expect(hermes.model_overrides['minimax-cn']['MiniMax-M3.1-Flash-Preview'].context_window)
.toBe(1_000_000);
expect(hermes.model_overrides['minimax-cn']['MiniMax-M2.7'].context_window)
.toBe(204800);
expect(hermes.model_overrides['minimax-cn']['MiniMax-M3'].supports_vision)
.toBe(true);
expect(hermes.model_overrides['minimax-cn']['MiniMax-M2.7'].supports_vision)
.toBe(false);
expect(readFileSync(join(home, '.hermes', '.env'), 'utf8'))
.toContain('MINIMAX_CN_API_KEY=sk-test-secret');

Expand All @@ -360,17 +312,13 @@ describe('agent configurator', () => {
expect(piModels.providers['minimax-cn'].models[1].compat)
.toEqual({ supportsStrictTools: true, forceAdaptiveThinking: true });
expect(piModels.providers['minimax-cn'].models[2].thinkingLevelMap).toEqual({ off: null });
expect(piModels.providers['minimax-cn'].models[3].thinkingLevelMap).toEqual({ off: null });
expect(piModels.providers['minimax-cn'].models[4].thinkingLevelMap).toEqual({ off: null });
expect(piModels.providers['minimax-cn'].api).toBe('anthropic-messages');
expect(piModels.providers['minimax-cn'].baseUrl).toBe('https://api.minimax.cn/anthropic');
expect(piModels.providers['minimax-cn'].models.map((model: { id: string }) => model.id))
.toEqual([
'keep-model',
'MiniMax-M3',
'MiniMax-M3.1-Flash-Preview',
'MiniMax-M2.7',
'MiniMax-M2.7-highspeed',
]);
expect(piSettings).toMatchObject({ defaultProvider: 'minimax-cn', defaultModel: 'MiniMax-M3' });

Expand All @@ -393,7 +341,7 @@ describe('agent configurator', () => {
expect(configured.model).toMatchObject({ default: 'MiniMax-M3', provider: 'minimax' });
});

it('uses 1M for Hermes M3.1 while keeping M2.7 at 204800', () => {
it('uses 1M for Hermes M3.1 and M3', () => {
applyAgentConfigurations(prepareAgentConfigurations(setupOptions(
['hermes'],
{ model: 'MiniMax-M3.1-Flash-Preview' },
Expand All @@ -403,10 +351,10 @@ describe('agent configurator', () => {

applyAgentConfigurations(prepareAgentConfigurations(setupOptions(
['hermes'],
{ model: 'MiniMax-M2.7' },
{ model: 'MiniMax-M3' },
)));
configured = parseYaml(readFileSync(join(home, '.hermes', 'config.yaml'), 'utf8'));
expect(configured.model.context_length).toBe(204800);
expect(configured.model.context_length).toBe(1_000_000);
});

it('preserves existing Hermes reasoning overrides', () => {
Expand Down Expand Up @@ -561,8 +509,6 @@ describe('agent configurator', () => {
.toEqual([
'MiniMax-M3.1-Flash-Preview',
'MiniMax-M3',
'MiniMax-M2.7',
'MiniMax-M2.7-highspeed',
]);
expect(configured.providers.minimax.models[0]).toMatchObject({
input: ['text', 'image'],
Expand Down Expand Up @@ -808,7 +754,7 @@ describe('agent configurator', () => {
'{\n "modelPicker": {\n "options": [\n'
+ ' // keep this custom model\n'
+ ' { "model": "keep-model", "label": "Keep" },\n'
+ ' { "model": "MiniMax-M2.7", "label": "Replace" }\n'
+ ' { "model": "MiniMax-M3", "label": "Replace" }\n'
+ ' ]\n }\n}\n',
);

Expand Down
8 changes: 4 additions & 4 deletions test/commands/agent/setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,10 +346,10 @@ describe('agent setup command', () => {
agent: ['codex'],
apiKey: 'sk-test-secret',
region: 'cn',
model: 'MiniMax-M2.7',
model: 'MiniMax-M3',
}),
));
expect(JSON.parse(output).verification.model).toBe('MiniMax-M2.7');
expect(JSON.parse(output).verification.model).toBe('MiniMax-M3');
});

it('uses MiniMax-M3.1-Flash-Preview when no model is specified', async () => {
Expand Down Expand Up @@ -396,9 +396,9 @@ describe('agent setup command', () => {
agent: ['codex'],
apiKey: 'sk-test-secret',
region: 'cn',
model: 'MiniMax-M2.5',
model: 'MiniMax-M2.7',
}),
)).rejects.toThrow('Unsupported MiniMax model "MiniMax-M2.5"');
)).rejects.toThrow('Unsupported MiniMax model "MiniMax-M2.7"');
});

it('accepts grok-build as an alias', async () => {
Expand Down
Loading