diff --git a/src/commands/text/chat.ts b/src/commands/text/chat.ts index 2d5065e5..2601f2df 100644 --- a/src/commands/text/chat.ts +++ b/src/commands/text/chat.ts @@ -159,11 +159,11 @@ export default defineCommand({ apiDocs: '/docs/api-reference/text-post', usage: 'mmx text chat --message [flags]', options: [ - { flag: '--model ', description: 'Model ID (default: MiniMax-M2.7)' }, + { flag: '--model ', description: 'Model ID (default: MiniMax-M3)' }, { flag: '--message ', description: 'Message text (repeatable, prefix role: to set role)', required: true, type: 'array' }, { flag: '--messages-file ', description: 'JSON file with messages array (use - for stdin)' }, { flag: '--system ', description: 'System prompt' }, - { flag: '--max-tokens ', description: 'Maximum tokens to generate (default: 4096)', type: 'number' }, + { flag: '--max-tokens ', description: 'Maximum tokens to generate (default: 8192)', type: 'number' }, { flag: '--temperature ', description: 'Sampling temperature (0.0, 1.0]', type: 'number' }, { flag: '--top-p ', description: 'Nucleus sampling threshold', type: 'number' }, { flag: '--stream', description: 'Stream response tokens (default: on in TTY)' }, @@ -171,7 +171,7 @@ export default defineCommand({ ], examples: [ 'mmx text chat --message "What is MiniMax?"', - 'mmx text chat --model MiniMax-M2.7-highspeed --system "You are a coding assistant." --message "Write fizzbuzz in Python"', + 'mmx text chat --system "You are a coding assistant." --message "Write fizzbuzz in Python"', 'mmx text chat --message "Hello" --message "assistant:Hi!" --message "How are you?"', 'cat conversation.json | mmx text chat --messages-file - --stream', 'mmx text chat --message "Hello" --output json', @@ -197,7 +197,7 @@ export default defineCommand({ const model = (flags.model as string) || config.defaultTextModel - || 'MiniMax-M2.7'; + || 'MiniMax-M3'; const format = detectOutputFormat(config.output); const shouldStream = flags.stream === true || ( flags.stream === undefined @@ -208,7 +208,7 @@ export default defineCommand({ const body: ChatRequest = { model, messages, - max_tokens: (flags.maxTokens as number) ?? 4096, + max_tokens: (flags.maxTokens as number) ?? 8192, stream: shouldStream, }; diff --git a/src/commands/text/repl.ts b/src/commands/text/repl.ts index 335c9c09..065a8910 100644 --- a/src/commands/text/repl.ts +++ b/src/commands/text/repl.ts @@ -294,15 +294,15 @@ export default defineCommand({ description: 'Start an interactive multi-turn chat session', usage: 'mmx text repl [flags]', options: [ - { flag: '--model ', description: 'Model ID (default: MiniMax-M2.7)' }, + { flag: '--model ', description: 'Model ID (default: MiniMax-M3)' }, { flag: '--system ', description: 'System prompt' }, - { flag: '--max-tokens ', description: 'Maximum tokens per response (default: 4096)', type: 'number' }, + { flag: '--max-tokens ', description: 'Maximum tokens per response (default: 8192)', type: 'number' }, { flag: '--temperature ', description: 'Sampling temperature (0.0, 1.0]', type: 'number' }, { flag: '--top-p ', description: 'Nucleus sampling threshold', type: 'number' }, ], examples: [ 'mmx text repl', - 'mmx text repl --model MiniMax-M2.7-highspeed --system "You are a coding assistant."', + 'mmx text repl --system "You are a coding assistant."', 'mmx text repl --temperature 0.7 --max-tokens 8192', ], async run(config: Config, flags: GlobalFlags) { @@ -325,8 +325,8 @@ export default defineCommand({ const state: ReplState = { messages: [], system: flags.system as string | undefined, - model: (flags.model as string) || config.defaultTextModel || 'MiniMax-M2.7', - maxTokens: (flags.maxTokens as number) ?? 4096, + model: (flags.model as string) || config.defaultTextModel || 'MiniMax-M3', + maxTokens: (flags.maxTokens as number) ?? 8192, temperature: flags.temperature !== undefined ? flags.temperature as number : undefined, topP: flags.topP !== undefined ? flags.topP as number : undefined, }; diff --git a/src/output/quota-table.ts b/src/output/quota-table.ts index 06113182..839c58d2 100644 --- a/src/output/quota-table.ts +++ b/src/output/quota-table.ts @@ -128,7 +128,10 @@ export function renderQuotaTable(models: QuotaModelRemain[], config: Config): vo const L = config.region === 'cn' ? LABELS_CN : LABELS_EN; const rows = models.map((m) => { - const displayName = displayModelName(m.model_name, config.region); + const baseName = displayModelName(m.model_name, config.region); + const boost = m.interval_boost_permille; + const boostTag = (boost && boost > 1000) ? ` ×${boost / 1000}` : ''; + const displayName = baseName + boostTag; const current = renderMetric( L.current, m.current_interval_usage_count, diff --git a/src/sdk/text/index.ts b/src/sdk/text/index.ts index 1242d3e8..fc29586a 100644 --- a/src/sdk/text/index.ts +++ b/src/sdk/text/index.ts @@ -56,8 +56,8 @@ export class TextSDK extends Client { return { ...params, - model: params.model ?? 'MiniMax-M2.7', - max_tokens: params.max_tokens ?? 4096, + model: params.model ?? 'MiniMax-M3', + max_tokens: params.max_tokens ?? 8192, } as ChatRequest; } } diff --git a/src/types/api.ts b/src/types/api.ts index ad59e02a..4c819036 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -253,9 +253,13 @@ export interface QuotaModelRemain { current_interval_total_count: number; current_interval_usage_count: number; current_interval_remaining_percent?: number; + current_interval_status?: number; current_weekly_total_count: number; current_weekly_usage_count: number; current_weekly_remaining_percent?: number; + current_weekly_status?: number; + interval_boost_permille?: number; + weekly_boost_permille?: number; weekly_start_time: number; weekly_end_time: number; weekly_remains_time: number; diff --git a/test/commands/config/set.test.ts b/test/commands/config/set.test.ts index 53f085e1..ea73132c 100644 --- a/test/commands/config/set.test.ts +++ b/test/commands/config/set.test.ts @@ -91,7 +91,7 @@ describe('config set command', () => { await expect( setCommand.execute(config, { key: 'default_text_model', - value: 'MiniMax-M2.7-highspeed', + value: 'MiniMax-M2.5', quiet: false, verbose: false, noColor: true, @@ -123,7 +123,7 @@ describe('config set command', () => { await expect( setCommand.execute(config, { key: 'default-text-model', - value: 'MiniMax-M2.7-highspeed', + value: 'MiniMax-M2.5', quiet: false, verbose: false, noColor: true, diff --git a/test/commands/config/show.test.ts b/test/commands/config/show.test.ts index e063b7c6..16e9b4c1 100644 --- a/test/commands/config/show.test.ts +++ b/test/commands/config/show.test.ts @@ -5,7 +5,7 @@ import { default as showCommand } from '../../../src/commands/config/show'; mock.module('../../../src/config/loader', () => ({ readConfigFile: () => ({ api_key: 'sk-cp-test-key', - default_text_model: 'MiniMax-M2.7-highspeed', + default_text_model: 'MiniMax-M2.5', default_speech_model: 'speech-2.8-hd', default_video_model: 'MiniMax-Hailuo-2.3-6s-768p', default_music_model: 'music-2.6', @@ -89,7 +89,7 @@ describe('config show command', () => { }); const parsed = JSON.parse(output); - expect(parsed.default_text_model).toBe('MiniMax-M2.7-highspeed'); + expect(parsed.default_text_model).toBe('MiniMax-M2.5'); expect(parsed.default_speech_model).toBe('speech-2.8-hd'); expect(parsed.default_video_model).toBe('MiniMax-Hailuo-2.3-6s-768p'); expect(parsed.default_music_model).toBe('music-2.6'); diff --git a/test/commands/text/chat.test.ts b/test/commands/text/chat.test.ts index 37ad0156..827bcb0e 100644 --- a/test/commands/text/chat.test.ts +++ b/test/commands/text/chat.test.ts @@ -96,7 +96,7 @@ describe('text chat command', () => { }); const parsed = JSON.parse(output); - expect(parsed.request.model).toBe('MiniMax-M2.7'); + expect(parsed.request.model).toBe('MiniMax-M3'); expect(parsed.request.messages).toHaveLength(1); } finally { console.log = originalLog; @@ -112,7 +112,7 @@ describe('text chat command', () => { baseUrl: 'https://api.mmx.io', output: 'json', timeout: 10, - defaultTextModel: 'MiniMax-M2.7-highspeed', + defaultTextModel: 'MiniMax-M2.5', verbose: false, quiet: false, noColor: true, @@ -140,7 +140,7 @@ describe('text chat command', () => { }); const parsed = JSON.parse(output); - expect(parsed.request.model).toBe('MiniMax-M2.7-highspeed'); + expect(parsed.request.model).toBe('MiniMax-M2.5'); } finally { console.log = originalLog; } @@ -268,7 +268,7 @@ describe('text chat command', () => { baseUrl: 'https://api.mmx.io', output: 'json', timeout: 10, - defaultTextModel: 'MiniMax-M2.7-highspeed', + defaultTextModel: 'MiniMax-M2.5', verbose: false, quiet: false, noColor: true, diff --git a/test/output/quota-table.test.ts b/test/output/quota-table.test.ts index 3c0a42cb..69d6e2a2 100644 --- a/test/output/quota-table.test.ts +++ b/test/output/quota-table.test.ts @@ -47,9 +47,13 @@ function createCodingPlanModels(): QuotaModelRemain[] { current_interval_total_count: 0, current_interval_usage_count: 0, current_interval_remaining_percent: 94, + current_interval_status: 1, current_weekly_total_count: 0, current_weekly_usage_count: 0, current_weekly_remaining_percent: 98, + current_weekly_status: 1, + interval_boost_permille: 2000, + weekly_boost_permille: 2000, weekly_start_time: Date.UTC(2026, 4, 31, 0, 0, 0), weekly_end_time: Date.UTC(2026, 5, 7, 0, 0, 0), weekly_remains_time: 6 * 24 * 60 * 60 * 1000, @@ -129,4 +133,71 @@ describe('renderQuotaTable', () => { expect(output).toContain('21 / 21'); expect(output).not.toContain('0 / 3'); }); + + it('renders boost multiplier when boost_permille > 1000', () => { + const lines: string[] = []; + const originalLog = console.log; + + console.log = (message?: unknown) => { + lines.push(String(message ?? '')); + }; + + try { + renderQuotaTable(createCodingPlanModels(), { + ...createConfig(), + region: 'cn', + noColor: true, + }); + } finally { + console.log = originalLog; + } + + const output = lines.join('\n'); + + // general model has interval_boost_permille=2000 => ×2 prefix + expect(output).toContain('通用 ×2'); + // video model has no boost field => no ×2 on its row + // ensure the video line is still present (so the negative check is meaningful) + expect(output).toContain('视频'); + }); + + it('omits boost multiplier when boost_permille is missing', () => { + const modelsNoBoost: QuotaModelRemain[] = [{ + model_name: 'general', + start_time: Date.UTC(2026, 4, 31, 0, 0, 0), + end_time: Date.UTC(2026, 4, 31, 2, 0, 0), + remains_time: 2 * 60 * 60 * 1000, + current_interval_total_count: 100, + current_interval_usage_count: 50, + current_interval_remaining_percent: 50, + current_weekly_total_count: 1000, + current_weekly_usage_count: 200, + current_weekly_remaining_percent: 80, + weekly_start_time: Date.UTC(2026, 4, 31, 0, 0, 0), + weekly_end_time: Date.UTC(2026, 5, 7, 0, 0, 0), + weekly_remains_time: 6 * 24 * 60 * 60 * 1000, + }]; + + const lines: string[] = []; + const originalLog = console.log; + + console.log = (message?: unknown) => { + lines.push(String(message ?? '')); + }; + + try { + renderQuotaTable(modelsNoBoost, { + ...createConfig(), + region: 'cn', + noColor: true, + }); + } finally { + console.log = originalLog; + } + + const output = lines.join('\n'); + + expect(output).toContain('通用'); + expect(output).not.toContain('×2'); + }); }); diff --git a/test/utils/model-defaults.test.ts b/test/utils/model-defaults.test.ts index bb6a9086..19ba14fc 100644 --- a/test/utils/model-defaults.test.ts +++ b/test/utils/model-defaults.test.ts @@ -33,13 +33,13 @@ function resolveModel( describe('model resolution (flag > config default > fallback)', () => { it('uses flag when provided', () => { - const model = resolveModel('defaultTextModel', 'MiniMax-M2.7', baseConfig, { model: 'MiniMax-M2.7-highspeed' }); - expect(model).toBe('MiniMax-M2.7-highspeed'); + const model = resolveModel('defaultTextModel', 'MiniMax-M2.7', baseConfig, { model: 'MiniMax-M2.5' }); + expect(model).toBe('MiniMax-M2.5'); }); it('falls back to config default when flag is absent', () => { - const model = resolveModel('defaultTextModel', 'MiniMax-M2.7', { ...baseConfig, defaultTextModel: 'MiniMax-M2.7-highspeed' }, {}); - expect(model).toBe('MiniMax-M2.7-highspeed'); + const model = resolveModel('defaultTextModel', 'MiniMax-M2.7', { ...baseConfig, defaultTextModel: 'MiniMax-M2.5' }, {}); + expect(model).toBe('MiniMax-M2.5'); }); it('falls back to hardcoded when neither flag nor config', () => {