Skip to content

Commit 59b5fa9

Browse files
Merge pull request #8 from MiniMax-AI-Dev/fix/cli-bugs-polish
fix: resolve 8 CLI quality issues found during audit
2 parents 0a9d3fd + 5d3a6a8 commit 59b5fa9

8 files changed

Lines changed: 38 additions & 24 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "minimax-cli",
3-
"version": "0.1.0",
3+
"version": "0.3.1",
44
"private": true,
55
"description": "CLI for the MiniMax API Platform (Token Plan)",
66
"type": "module",

src/client/http.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@ export interface RequestOpts {
1616
authStyle?: 'bearer' | 'x-api-key';
1717
}
1818

19+
// Printed once per process invocation to avoid repeating on every request.
20+
let statusBarPrinted = false;
21+
1922
export async function request(
2023
config: Config,
2124
opts: RequestOpts,
2225
): Promise<Response> {
2326
const isFormData =
2427
typeof FormData !== 'undefined' && opts.body instanceof FormData;
2528

29+
const version = process.env.CLI_VERSION ?? '0.3.1';
2630
const headers: Record<string, string> = {
27-
'User-Agent': 'minimax-cli/0.1.0',
31+
'User-Agent': `minimax-cli/${version}`,
2832
...opts.headers,
2933
};
3034

@@ -47,7 +51,8 @@ export async function request(
4751
}
4852

4953
// ANSI 真彩色 (24-bit) 与基础排版
50-
if (!config.quiet && process.stderr.isTTY) {
54+
if (!config.quiet && !statusBarPrinted && process.stderr.isTTY) {
55+
statusBarPrinted = true;
5156
const reset = '\x1b[0m';
5257
const dim = '\x1b[2m';
5358
const bold = '\x1b[1m'; // 新增加粗效果

src/commands/auth/login.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export default defineCommand({
3030
'minimax auth login --method api-key --api-key sk-xxxxx',
3131
],
3232
async run(config: Config, flags: GlobalFlags) {
33-
// --- Phase 4: env key detection ---
3433
const envKey = process.env.MINIMAX_API_KEY;
3534
if (envKey) {
3635
const maskedEnvKey = envKey.length > 8 ? `${envKey.slice(0, 4)}...${envKey.slice(-4)}` : '***';
@@ -48,7 +47,6 @@ export default defineCommand({
4847
process.stderr.write(`Warning: MINIMAX_API_KEY is already set in environment.\n`);
4948
}
5049
}
51-
// --- Phase 4 end ---
5250

5351
const method = flags.apiKey ? 'api-key' : (flags.method as string) || 'oauth';
5452

src/commands/quota/show.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ export default defineCommand({
183183
const url = quotaEndpoint(config.baseUrl);
184184
const response = await requestJson<QuotaApiResponse>(config, { url });
185185
const models = response.model_remains || [];
186-
const format = detectOutputFormat(config.output);
186+
// Only honour explicit --output flag; ignore config-file output setting so the
187+
// rich HUD is shown by default in TTY even when the user has output: json globally.
188+
const format = detectOutputFormat(flags.output as string | undefined);
187189

188190
// Step 1: Non-text formats pass through as-is
189191
if (format !== 'text') {
@@ -208,9 +210,12 @@ export default defineCommand({
208210
const maxNameLen = models.length > 0
209211
? Math.max(...models.map(m => m.model_name.length))
210212
: 16;
211-
// Layout per row: name + 2 + usage(15) + 2 + bar(BAR_WIDTH) + 1 + pct(4) = name + BAR_WIDTH + 24
212-
// Box inner W = content + 2 (for "│ " and " │" padding)
213-
const W = Math.max(68, maxNameLen + BAR_WIDTH + 26);
213+
// color bar: BAR_WIDTH spaces + ' ' + pct(4) = BAR_WIDTH + 5 visible cols
214+
// no-color bar: '[' + BAR_WIDTH chars + '] ' + pct(4) = BAR_WIDTH + 7 visible cols
215+
const barVisLen = useColor ? BAR_WIDTH + 5 : BAR_WIDTH + 7;
216+
// line1 content = name(maxNameLen) + ' '(2) + usage(15) + ' '(2) + bar(barVisLen)
217+
// W must be content + 2 so boxRow borders ('| ' + ' |') have room
218+
const W = Math.max(68, maxNameLen + 2 + 15 + 2 + barVisLen + 2);
214219

215220
// ── Header row ──
216221
const weekRange = models.length > 0
@@ -264,8 +269,9 @@ export default defineCommand({
264269
const usageFrac = `${used.toLocaleString()} / ${limit.toLocaleString()}`;
265270
const bar = renderBar(usedPct, useColor);
266271

267-
// Visible columns: name(padded) + gap(2) + usage(15) + gap(2) + bar(BAR_WIDTH) + gap(1) + pct(4)
268-
const line1VisLen = maxNameLen + 2 + 15 + 2 + BAR_WIDTH + 1 + 4;
272+
// color bar: BAR_WIDTH spaces + gap(1) + pct(4) = BAR_WIDTH + 5
273+
// no-color bar: '[' + BAR_WIDTH chars + '] ' + pct(4) = BAR_WIDTH + 7
274+
const line1VisLen = maxNameLen + 2 + 15 + 2 + barVisLen;
269275

270276
let line1Styled: string;
271277
if (useColor) {

src/commands/text/chat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ function extractText(content: ContentBlock[]): string {
7979

8080
export default defineCommand({
8181
name: 'text chat',
82-
description: 'Send a chat completion (Anthropic Messages API)',
82+
description: 'Send a chat completion (MiniMax Messages API)',
8383
usage: 'minimax text chat --message <text> [flags]',
8484
options: [
8585
{ flag: '--model <model>', description: 'Model ID (default: MiniMax-M2.7)' },

src/errors/handler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { CLIError } from './base';
22
import { ExitCode } from './codes';
3+
import { detectOutputFormat } from '../output/formatter';
34

45
export function handleError(err: unknown): never {
56
if (err instanceof CLIError) {
6-
const isJson = process.env.MINIMAX_OUTPUT === 'json' ||
7-
(typeof process.stdout?.isTTY !== 'undefined' && !process.stdout.isTTY);
7+
const format = detectOutputFormat(process.env.MINIMAX_OUTPUT);
88

9-
if (isJson) {
9+
if (format === 'json') {
1010
process.stderr.write(JSON.stringify(err.toJSON(), null, 2) + '\n');
1111
} else {
1212
process.stderr.write(`\nError: ${err.message}\n`);

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { detectRegion, saveDetectedRegion } from './config/detect-region';
66
import { REGIONS } from './config/schema';
77
import { checkForUpdate, getPendingUpdateNotification } from './update/checker';
88

9-
const CLI_VERSION = process.env.CLI_VERSION ?? '0.1.0';
9+
const CLI_VERSION = process.env.CLI_VERSION ?? '0.3.1';
1010

1111
async function main() {
1212
const args = process.argv.slice(2);

src/registry.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import quotaShow from './commands/quota/show';
2020
import configShow from './commands/config/show';
2121
import configSet from './commands/config/set';
2222
import configExportSchema from './commands/config/export-schema';
23-
// ❄️ 暂时雪藏 File API (等待接口权限开放)
23+
// File API temporarily disabled (pending permission grant)
2424
// import fileUpload from './commands/file/upload';
2525
// import fileList from './commands/file/list';
2626
// import fileDelete from './commands/file/delete';
@@ -205,13 +205,18 @@ Getting Help:
205205
}
206206

207207
private printChildren(node: CommandNode, prefix: string, out: NodeJS.WriteStream): void {
208-
for (const [name, child] of node.children) {
209-
if (child.command) {
210-
out.write(` ${prefix} ${name.padEnd(12)} ${child.command.description}\n`);
211-
}
212-
if (child.children.size > 0) {
213-
this.printChildren(child, `${prefix} ${name}`, out);
208+
// Collect all leaf entries first so we can align the description column.
209+
const entries: Array<{ fullName: string; description: string }> = [];
210+
const collect = (n: CommandNode, p: string) => {
211+
for (const [name, child] of n.children) {
212+
if (child.command) entries.push({ fullName: `${p} ${name}`, description: child.command.description });
213+
if (child.children.size > 0) collect(child, `${p} ${name}`);
214214
}
215+
};
216+
collect(node, prefix);
217+
const maxLen = Math.max(...entries.map(e => e.fullName.length));
218+
for (const { fullName, description } of entries) {
219+
out.write(` ${fullName.padEnd(maxLen)} ${description}\n`);
215220
}
216221
}
217222
}
@@ -236,7 +241,7 @@ export const registry = new CommandRegistry({
236241
'config set': configSet,
237242
'config export-schema': configExportSchema,
238243

239-
// ❄️ 暂时雪藏 File API
244+
// File API temporarily disabled (pending permission grant)
240245
// 'file upload': fileUpload,
241246
// 'file list': fileList,
242247
// 'file delete': fileDelete,

0 commit comments

Comments
 (0)