Skip to content

Commit 4c05cdd

Browse files
RyanLee-Devclaude
andcommitted
Fix group help display, no-color propagation, and music lyrics validation
- `minimax auth` / `minimax quota` now shows group help instead of error - Propagate --no-color flag to printHelp in main.ts - music generate: require --lyrics upfront instead of warning and failing at API Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8c79e20 commit 4c05cdd

3 files changed

Lines changed: 103 additions & 78 deletions

File tree

src/commands/music/generate.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ export default defineCommand({
4949
}
5050

5151
if (!lyrics) {
52-
process.stderr.write('Warning: No lyrics provided. Use --lyrics or --lyrics-file to include lyrics.\n');
52+
throw new CLIError(
53+
'--lyrics or --lyrics-file is required.',
54+
ExitCode.USAGE,
55+
'minimax music generate --prompt <text> --lyrics <text> --out song.mp3',
56+
);
5357
}
5458

5559
const outFormat = (flags.outFormat as string) || 'hex';

src/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ async function main() {
1919
const { commandPath, flags } = parseArgs(args);
2020

2121
if (flags.help || commandPath.length === 0) {
22-
registry.printHelp(commandPath);
22+
const noColor = flags.noColor || process.env.NO_COLOR !== undefined;
23+
registry.printHelp(commandPath, noColor);
2324
process.exit(0);
2425
}
2526

src/registry.ts

Lines changed: 96 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,10 @@ class CommandRegistry {
6161
return { command: node.command, extra: commandPath.slice(matched.length) };
6262
}
6363

64-
// If we matched some path but no command, show help for that group
64+
// If we matched some path but no command, show group help and exit
6565
if (matched.length > 0 && node.children.size > 0) {
66-
const subcommands = Array.from(node.children.entries())
67-
.map(([name, n]) => {
68-
if (n.command) return ` ${matched.join(' ')} ${name} ${n.command.description}`;
69-
// Group with sub-children
70-
const subs = Array.from(n.children.keys()).join(', ');
71-
return ` ${matched.join(' ')} ${name} [${subs}]`;
72-
})
73-
.join('\n');
74-
throw new CLIError(
75-
`Unknown command: minimax ${commandPath.join(' ')}\n\nAvailable commands:\n${subcommands}`,
76-
ExitCode.USAGE,
77-
`minimax ${matched.join(' ')} --help`,
78-
);
66+
this.printHelp(matched, false);
67+
process.exit(0);
7968
}
8069

8170
throw new CLIError(
@@ -85,108 +74,139 @@ class CommandRegistry {
8574
);
8675
}
8776

88-
printHelp(commandPath: string[]): void {
77+
printHelp(commandPath: string[], noColor = false): void {
78+
const color = noColor || !process.stdout.isTTY
79+
? (s: string) => s
80+
: (s: string, code: string) => `\x1b[${code}m${s}\x1b[0m`;
81+
8982
if (commandPath.length === 0) {
90-
this.printRootHelp();
83+
this.printRootHelp(color);
9184
return;
9285
}
9386

9487
let node = this.root;
9588
for (const part of commandPath) {
9689
const child = node.children.get(part);
9790
if (!child) {
98-
this.printRootHelp();
91+
this.printRootHelp(color);
9992
return;
10093
}
10194
node = child;
10295
}
10396

10497
if (node.command) {
105-
this.printCommandHelp(node.command);
98+
this.printCommandHelp(node.command, color);
10699
return;
107100
}
108101

109102
// Group help
110-
console.log(`\nUsage: minimax ${commandPath.join(' ')} <command> [flags]\n`);
111-
console.log('Commands:');
112-
this.printChildren(node, commandPath.join(' '));
103+
console.log(`\n${color('Usage:', '1')} minimax ${commandPath.join(' ')} <command> [flags]\n`);
104+
console.log(color('Commands:', '1'));
105+
this.printChildren(node, commandPath.join(' '), color);
113106
console.log('');
114107
}
115108

116-
private printRootHelp(): void {
109+
private printRootHelp(color: (s: string, code: string) => string): void {
110+
const logo = [
111+
' __ __ ___ _ _ ___ __ __ _ __ __',
112+
' | \\/ |_ _| \\ | |_ _| \\/ | / \\ \\ \\/ /',
113+
' | |\\/| || || \\| || || |\\/| | / _ \\ \\ / ',
114+
' | | | || || |\\ || || | | |/ ___ \\/ \\ ',
115+
' |_| |_|___|_| \\_|___|_| |_/_/ \\_\\/_/\\',
116+
];
117+
118+
// Gradient: bright cyan → cyan → blue
119+
const gradient = ['96', '96', '36', '36', '34'];
120+
const coloredLogo = logo.map((line, i) => color(line, `1;${gradient[i]}`)).join('\n');
121+
122+
const dim = (s: string) => color(s, '2');
123+
const bold = (s: string) => color(s, '1');
124+
const cyan = (s: string) => color(s, '36');
125+
const yellow = (s: string) => color(s, '33');
126+
127+
const resources = [
128+
['auth', 'Authentication (login, status, refresh, logout)'],
129+
['text', 'Text generation (chat)'],
130+
['speech', 'Speech synthesis (synthesize)'],
131+
['image', 'Image generation (generate)'],
132+
['video', 'Video generation (generate, task get, download)'],
133+
['music', 'Music generation (generate)'],
134+
['search', 'Web search (query)'],
135+
['vision', 'Image understanding (describe)'],
136+
['quota', 'Usage quotas (show)'],
137+
['config', 'CLI configuration (show, set)'],
138+
['update', 'Update minimax to a newer version'],
139+
];
140+
141+
const flags = [
142+
['--api-key <key>', 'API key (overrides all other auth)'],
143+
['--region <region>', 'API region: global (default), cn'],
144+
['--base-url <url>', 'API base URL (overrides region)'],
145+
['--output <format>', 'Output format: text, json, yaml'],
146+
['--quiet', 'Suppress non-essential output'],
147+
['--verbose', 'Print HTTP request/response details'],
148+
['--timeout <seconds>', 'Request timeout (default: 300)'],
149+
['--no-color', 'Disable ANSI colors and spinners'],
150+
['--yes', 'Skip confirmation prompts'],
151+
['--dry-run', 'Show what would happen without executing'],
152+
['--version', 'Print version and exit'],
153+
['--help', 'Show help'],
154+
];
155+
156+
const rPad = 10;
157+
const fPad = Math.max(...flags.map(([f]) => f!.length)) + 2;
158+
117159
console.log(`
118-
__ __ ___ _ _ ___ __ __ _ __ __
119-
| \\/ |_ _| \\ | |_ _| \\/ | / \\ \\ \\/ /
120-
| |\\/| || || \\| || || |\\/| | / _ \\ \\ /
121-
| | | || || |\\ || || | | |/ ___ \\/ \\
122-
|_| |_|___|_| \\_|___|_| |_/_/ \\_\\/_/\\
123-
124-
Usage: minimax <resource> <command> [flags]
125-
126-
Resources:
127-
auth Authentication (login, status, refresh, logout)
128-
text Text generation (chat)
129-
speech Speech synthesis (synthesize)
130-
image Image generation (generate)
131-
video Video generation (generate, task get, download)
132-
music Music generation (generate)
133-
search Web search (query)
134-
vision Image understanding (describe)
135-
quota Usage quotas (show)
136-
config CLI configuration (show, set)
137-
update Update minimax to a newer version
138-
139-
Global Flags:
140-
--api-key <key> API key (overrides all other auth)
141-
--region <region> API region: global (default), cn
142-
--base-url <url> API base URL (overrides region)
143-
--output <format> Output format: text, json, yaml
144-
--quiet Suppress non-essential output
145-
--verbose Print HTTP request/response details
146-
--timeout <seconds> Request timeout (default: 300)
147-
--no-color Disable ANSI colors and spinners
148-
--yes Skip confirmation prompts
149-
--dry-run Show what would happen without executing
150-
--version Print version and exit
151-
--help Show help
152-
153-
Getting Help:
154-
Add --help after any command to see its full list of options, defaults,
155-
and usage examples. For example: minimax text chat --help
160+
${coloredLogo}
161+
162+
${bold('Usage:')} minimax <resource> <command> [flags]
163+
164+
${bold('Resources:')}
165+
${resources.map(([name, desc]) => ` ${cyan(name!.padEnd(rPad))} ${dim(desc!)}`).join('\n')}
166+
167+
${bold('Global Flags:')}
168+
${flags.map(([name, desc]) => ` ${yellow(name!.padEnd(fPad))} ${dim(desc!)}`).join('\n')}
169+
170+
${bold('Getting Help:')}
171+
${dim('Add --help after any command for options and examples.')}
172+
${dim('Example:')} minimax text chat --help
156173
`);
157174
}
158175

159-
private printCommandHelp(cmd: Command): void {
160-
console.log(`\n${cmd.description}\n`);
161-
if (cmd.usage) {
162-
console.log(`Usage: ${cmd.usage}\n`);
163-
}
176+
private printCommandHelp(cmd: Command, color: (s: string, code: string) => string): void {
177+
const bold = (s: string) => color(s, '1');
178+
const dim = (s: string) => color(s, '2');
179+
const cyan = (s: string) => color(s, '36');
180+
181+
console.log(`\n${bold(cmd.description)}\n`);
182+
if (cmd.usage) console.log(`${bold('Usage:')} ${cmd.usage}\n`);
183+
164184
if (cmd.options && cmd.options.length > 0) {
165185
const maxLen = Math.max(...cmd.options.map(o => o.flag.length));
166-
console.log('Options:');
186+
console.log(bold('Options:'));
167187
for (const opt of cmd.options) {
168-
console.log(` ${opt.flag.padEnd(maxLen + 2)} ${opt.description}`);
188+
console.log(` ${cyan(opt.flag.padEnd(maxLen + 2))} ${dim(opt.description)}`);
169189
}
170190
console.log('');
171191
}
172192
if (cmd.examples && cmd.examples.length > 0) {
173-
console.log('Examples:');
174-
for (const ex of cmd.examples) {
175-
console.log(` ${ex}`);
176-
}
193+
console.log(bold('Examples:'));
194+
for (const ex of cmd.examples) console.log(` ${dim(ex)}`);
177195
console.log('');
178196
}
179-
console.log(`Global flags (--api-key, --output, --quiet, etc.) are always available.`);
180-
console.log(`Run 'minimax --help' for the full list.\n`);
197+
console.log(`${dim('Global flags (--api-key, --output, --quiet, etc.) are always available.')}`);
198+
console.log(`${dim("Run 'minimax --help' for the full list.")}\n`);
181199
}
182200

183-
private printChildren(node: CommandNode, prefix: string): void {
201+
private printChildren(node: CommandNode, prefix: string, color: (s: string, code: string) => string): void {
202+
const cyan = (s: string) => color(s, '36');
203+
const dim = (s: string) => color(s, '2');
184204
for (const [name, child] of node.children) {
185205
if (child.command) {
186-
console.log(` ${prefix} ${name.padEnd(12)} ${child.command.description}`);
206+
console.log(` ${cyan((prefix + ' ' + name).padEnd(24))} ${dim(child.command.description)}`);
187207
}
188208
if (child.children.size > 0) {
189-
this.printChildren(child, `${prefix} ${name}`);
209+
this.printChildren(child, `${prefix} ${name}`, color);
190210
}
191211
}
192212
}

0 commit comments

Comments
 (0)