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/commands/text/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,19 +159,19 @@ export default defineCommand({
apiDocs: '/docs/api-reference/text-post',
usage: 'mmx text chat --message <text> [flags]',
options: [
{ flag: '--model <model>', description: 'Model ID (default: MiniMax-M2.7)' },
{ flag: '--model <model>', description: 'Model ID (default: MiniMax-M3)' },
{ flag: '--message <text>', description: 'Message text (repeatable, prefix role: to set role)', required: true, type: 'array' },
{ flag: '--messages-file <path>', description: 'JSON file with messages array (use - for stdin)' },
{ flag: '--system <text>', description: 'System prompt' },
{ flag: '--max-tokens <n>', description: 'Maximum tokens to generate (default: 4096)', type: 'number' },
{ flag: '--max-tokens <n>', description: 'Maximum tokens to generate (default: 8192)', type: 'number' },
{ flag: '--temperature <n>', description: 'Sampling temperature (0.0, 1.0]', type: 'number' },
{ flag: '--top-p <n>', description: 'Nucleus sampling threshold', type: 'number' },
{ flag: '--stream', description: 'Stream response tokens (default: on in TTY)' },
{ flag: '--tool <json-or-path>', description: 'Tool definition as JSON or file path (repeatable)', type: 'array' },
],
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',
Expand All @@ -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
Expand All @@ -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,
};

Expand Down
10 changes: 5 additions & 5 deletions src/commands/text/repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,15 +294,15 @@ export default defineCommand({
description: 'Start an interactive multi-turn chat session',
usage: 'mmx text repl [flags]',
options: [
{ flag: '--model <model>', description: 'Model ID (default: MiniMax-M2.7)' },
{ flag: '--model <model>', description: 'Model ID (default: MiniMax-M3)' },
{ flag: '--system <text>', description: 'System prompt' },
{ flag: '--max-tokens <n>', description: 'Maximum tokens per response (default: 4096)', type: 'number' },
{ flag: '--max-tokens <n>', description: 'Maximum tokens per response (default: 8192)', type: 'number' },
{ flag: '--temperature <n>', description: 'Sampling temperature (0.0, 1.0]', type: 'number' },
{ flag: '--top-p <n>', 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) {
Expand All @@ -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,
};
Expand Down
5 changes: 4 additions & 1 deletion src/output/quota-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/sdk/text/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
4 changes: 4 additions & 0 deletions src/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions test/commands/config/set.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions test/commands/config/show.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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');
Expand Down
8 changes: 4 additions & 4 deletions test/commands/text/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down
71 changes: 71 additions & 0 deletions test/output/quota-table.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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');
});
});
8 changes: 4 additions & 4 deletions test/utils/model-defaults.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Loading