rl-rockcli 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +400 -0
  2. package/index.js +51 -21
  3. package/package.json +3 -2
  4. package/commands/log/core/constants.js +0 -237
  5. package/commands/log/core/display.js +0 -370
  6. package/commands/log/core/search.js +0 -330
  7. package/commands/log/core/tail.js +0 -216
  8. package/commands/log/core/utils.js +0 -424
  9. package/commands/log.js +0 -298
  10. package/commands/sandbox/core/log-bridge.js +0 -119
  11. package/commands/sandbox/core/replay/analyzer.js +0 -311
  12. package/commands/sandbox/core/replay/batch-orchestrator.js +0 -536
  13. package/commands/sandbox/core/replay/batch-task.js +0 -369
  14. package/commands/sandbox/core/replay/concurrent-display.js +0 -70
  15. package/commands/sandbox/core/replay/concurrent-orchestrator.js +0 -170
  16. package/commands/sandbox/core/replay/data-source.js +0 -86
  17. package/commands/sandbox/core/replay/display.js +0 -231
  18. package/commands/sandbox/core/replay/executor.js +0 -634
  19. package/commands/sandbox/core/replay/history-fetcher.js +0 -124
  20. package/commands/sandbox/core/replay/index.js +0 -338
  21. package/commands/sandbox/core/replay/loghouse-data-source.js +0 -177
  22. package/commands/sandbox/core/replay/pid-mapping.js +0 -26
  23. package/commands/sandbox/core/replay/request.js +0 -109
  24. package/commands/sandbox/core/replay/worker.js +0 -166
  25. package/commands/sandbox/core/session.js +0 -346
  26. package/commands/sandbox/log-bridge.js +0 -2
  27. package/commands/sandbox/ray.js +0 -2
  28. package/commands/sandbox/replay/analyzer.js +0 -311
  29. package/commands/sandbox/replay/batch-orchestrator.js +0 -536
  30. package/commands/sandbox/replay/batch-task.js +0 -369
  31. package/commands/sandbox/replay/concurrent-display.js +0 -70
  32. package/commands/sandbox/replay/concurrent-orchestrator.js +0 -170
  33. package/commands/sandbox/replay/display.js +0 -231
  34. package/commands/sandbox/replay/executor.js +0 -634
  35. package/commands/sandbox/replay/history-fetcher.js +0 -118
  36. package/commands/sandbox/replay/index.js +0 -338
  37. package/commands/sandbox/replay/pid-mapping.js +0 -26
  38. package/commands/sandbox/replay/request.js +0 -109
  39. package/commands/sandbox/replay/worker.js +0 -166
  40. package/commands/sandbox/replay.js +0 -2
  41. package/commands/sandbox/session.js +0 -2
  42. package/commands/sandbox-original.js +0 -1393
  43. package/commands/sandbox.js +0 -499
  44. package/help/help.json +0 -1071
  45. package/help/middleware.js +0 -71
  46. package/help/renderer.js +0 -800
  47. package/lib/plugin-context.js +0 -40
  48. package/sdks/sandbox/core/client.js +0 -845
  49. package/sdks/sandbox/core/config.js +0 -70
  50. package/sdks/sandbox/core/types.js +0 -74
  51. package/sdks/sandbox/httpLogger.js +0 -251
  52. package/sdks/sandbox/index.js +0 -9
  53. package/utils/asciiArt.js +0 -138
  54. package/utils/bun-compat.js +0 -59
  55. package/utils/ciPipelines.js +0 -138
  56. package/utils/cli.js +0 -17
  57. package/utils/command-router.js +0 -79
  58. package/utils/configManager.js +0 -503
  59. package/utils/dependency-resolver.js +0 -135
  60. package/utils/eagleeye_traceid.js +0 -151
  61. package/utils/envDetector.js +0 -78
  62. package/utils/execution_logger.js +0 -415
  63. package/utils/featureManager.js +0 -68
  64. package/utils/firstTimeTip.js +0 -44
  65. package/utils/hook-manager.js +0 -125
  66. package/utils/http-logger.js +0 -264
  67. package/utils/i18n.js +0 -139
  68. package/utils/image-progress.js +0 -159
  69. package/utils/logger.js +0 -154
  70. package/utils/plugin-loader.js +0 -124
  71. package/utils/plugin-manager.js +0 -348
  72. package/utils/ray_cli_wrapper.js +0 -746
  73. package/utils/sandbox-client.js +0 -419
  74. package/utils/terminal.js +0 -32
  75. package/utils/tips.js +0 -106
package/help/renderer.js DELETED
@@ -1,800 +0,0 @@
1
- /**
2
- * 帮助信息渲染器
3
- * 从 help.json 读取配置,输出 gh 风格的帮助文本
4
- */
5
-
6
- const path = require('path');
7
- const helpConfig = require('./help.json');
8
- const { isCommandEnabled } = require('../utils/featureManager');
9
- const { showAsciiArt } = require('../utils/asciiArt');
10
-
11
- // 格式化常量
12
- const INDENT = ' ';
13
- const CMD_WIDTH = 14; // 命令名列宽
14
- const FLAG_WIDTH = 32; // 选项列宽
15
-
16
- /**
17
- * 左对齐填充字符串
18
- */
19
- function padEnd(str, width) {
20
- return str.length >= width ? str + ' ' : str + ' '.repeat(width - str.length);
21
- }
22
-
23
- /**
24
- * 渲染帮助信息
25
- * @param {string[]} commandPath - 命令路径,如 ['sandbox', 'upload']
26
- * @param {Object} pluginManager - 插件管理器实例(可选)
27
- * @returns {string} 格式化的帮助文本
28
- */
29
- function renderHelp(commandPath, pluginManager = null) {
30
- if (!commandPath || commandPath.length === 0) {
31
- return renderRootHelp(pluginManager);
32
- }
33
-
34
- const [command, subcommand, ...rest] = commandPath;
35
-
36
- // 检查是否是插件命令(带有 helpConfig)
37
- if (pluginManager) {
38
- const pluginCommands = pluginManager.getRegisteredCommands();
39
-
40
- // 查找父命令(如 "log")
41
- const parentCmd = pluginCommands.find(cmd => cmd.command === command);
42
-
43
- if (parentCmd && parentCmd.helpConfig) {
44
- // 使用插件的 helpConfig 渲染帮助
45
- return renderPluginHelpConfig(command, parentCmd.helpConfig, subcommand, rest);
46
- }
47
-
48
- // 首先检查是否是插件一级命令(有子命令)
49
- const hasSubCommands = pluginCommands.some(cmd => cmd.command.startsWith(command + ' '));
50
-
51
- if (hasSubCommands && !subcommand) {
52
- // 这是一个有子命令的父命令,显示子命令列表
53
- const subCommands = pluginCommands.filter(cmd => cmd.command.startsWith(command + ' '));
54
- return renderPluginSubcommandsHelp(command, subCommands, pluginManager);
55
- }
56
-
57
- // 检查是否是插件二级命令
58
- if (hasSubCommands && subcommand) {
59
- const fullCommand = `${command} ${subcommand}`;
60
- const pluginCmd = pluginCommands.find(cmd => {
61
- // 精确匹配或匹配到参数变体
62
- return cmd.command === fullCommand || cmd.command.startsWith(fullCommand + ' ');
63
- });
64
-
65
- if (pluginCmd) {
66
- return renderPluginCommandHelp(pluginCmd, pluginManager);
67
- }
68
- }
69
-
70
- // 否则查找匹配的一级命令
71
- // 优先查找精确匹配的父命令(如 "formula"),而不是子命令(如 "formula list")
72
- let pluginCmd = pluginCommands.find(cmd => cmd.command === command);
73
-
74
- // 如果没有精确匹配,再查找命令名称匹配的
75
- if (!pluginCmd) {
76
- pluginCmd = pluginCommands.find(cmd => {
77
- // 移除参数部分,只保留命令名称
78
- const cmdName = cmd.command.split(' ')[0];
79
- return cmdName === command;
80
- });
81
- }
82
-
83
- if (pluginCmd) {
84
- return renderPluginCommandHelp(pluginCmd, pluginManager);
85
- }
86
- }
87
-
88
- if (!helpConfig.commands[command]) {
89
- return renderRootHelp(pluginManager);
90
- }
91
-
92
- if (!subcommand) {
93
- return renderCommandHelp(command);
94
- }
95
-
96
- // 处理嵌套子命令 (如 sandbox session create)
97
- const cmdConfig = helpConfig.commands[command];
98
- if (cmdConfig.subcommands) {
99
- // 首先尝试精确匹配子命令名
100
- if (cmdConfig.subcommands[subcommand]) {
101
- const subcmdConfig = cmdConfig.subcommands[subcommand];
102
- if (rest.length > 0 && subcmdConfig.subcommands && subcmdConfig.subcommands[rest[0]]) {
103
- return renderNestedSubcommandHelp(command, subcommand, rest[0]);
104
- }
105
- return renderSubcommandHelp(command, subcommand);
106
- }
107
-
108
- // 尝试匹配 <id> <subcommand> 格式的通配符子命令
109
- // 例如: sandbox abc123 exec -> 匹配 <id> exec
110
- if (rest.length > 0) {
111
- const wildcardKey = `<id> ${rest[0]}`;
112
- if (cmdConfig.subcommands[wildcardKey]) {
113
- const subcmdConfig = cmdConfig.subcommands[wildcardKey];
114
- // 检查是否有更深层的嵌套子命令 (如 <id> log search)
115
- if (rest.length > 1 && subcmdConfig.subcommands && subcmdConfig.subcommands[rest[1]]) {
116
- return renderNestedSubcommandHelp(command, wildcardKey, rest[1]);
117
- }
118
- return renderSubcommandHelp(command, wildcardKey);
119
- }
120
- }
121
- }
122
-
123
- return renderCommandHelp(command);
124
- }
125
-
126
- /**
127
- * Get ASCII logo with gradient colors
128
- */
129
- function getAsciiLogo() {
130
- return showAsciiArt();
131
- }
132
-
133
- /**
134
- * 渲染一级帮助(根帮助)
135
- */
136
- function renderRootHelp(pluginManager = null) {
137
- const lines = [];
138
-
139
- // Logo (with leading empty line like opencode)
140
- lines.push('');
141
- lines.push('');
142
- lines.push(getAsciiLogo());
143
- lines.push('');
144
-
145
- // 标题和描述
146
- lines.push(helpConfig.description);
147
- if (helpConfig.tagline) {
148
- lines.push(helpConfig.tagline);
149
- }
150
- lines.push('');
151
- lines.push('');
152
-
153
- // 用法
154
- lines.push('用法');
155
- lines.push(INDENT + helpConfig.usage);
156
- lines.push('');
157
-
158
- // 按分组渲染命令
159
- for (const group of helpConfig.groups) {
160
- // 过滤掉未启用的命令
161
- const visibleCommands = group.commands.filter(cmd => isCommandEnabled(cmd));
162
-
163
- if (visibleCommands.length === 0) continue; // 跳过空分组
164
-
165
- lines.push(group.name);
166
- for (const cmdName of visibleCommands) {
167
- const cmd = helpConfig.commands[cmdName];
168
- if (cmd) {
169
- lines.push(INDENT + padEnd(cmdName, CMD_WIDTH) + cmd.description);
170
- }
171
- }
172
- lines.push('');
173
- }
174
-
175
- // 渲染插件命令
176
- if (pluginManager) {
177
- const pluginCommands = pluginManager.getRegisteredCommands();
178
- const existingCommands = helpConfig.groups.flatMap(g => g.commands);
179
-
180
- // 按命令层级分组:一级命令和二级命令
181
- const topLevelCommands = [];
182
- const subCommands = new Map(); // key: parent command, value: sub commands list
183
-
184
- for (const cmd of pluginCommands) {
185
- const parts = cmd.command.split(' ');
186
-
187
- // 判断是否是一级命令
188
- // 如果只有一个部分,或者第二个部分以 [ 或 < 开头(参数),则是一级命令
189
- if (parts.length === 1 || (parts.length === 2 && (parts[1].startsWith('[') || parts[1].startsWith('<')))) {
190
- // 一级命令
191
- topLevelCommands.push(cmd);
192
- } else {
193
- // 二级命令
194
- const parent = parts[0];
195
- if (!subCommands.has(parent)) {
196
- subCommands.set(parent, []);
197
- }
198
- subCommands.get(parent).push(cmd);
199
- }
200
- }
201
-
202
- // 创建父命令的描述(用于显示)
203
- // 优先使用插件注册的父命令描述
204
- const parentCommandDescriptions = new Map();
205
- for (const [parent, subCmds] of subCommands.entries()) {
206
- if (subCmds.length > 0) {
207
- // 查找是否有插件注册了父命令描述
208
- const parentCmd = topLevelCommands.find(cmd => cmd.command === parent);
209
- if (parentCmd && parentCmd.describe) {
210
- parentCommandDescriptions.set(parent, parentCmd.describe);
211
- } else {
212
- // 使用通用描述
213
- parentCommandDescriptions.set(parent, '插件命令');
214
- }
215
- }
216
- }
217
-
218
- // 过滤掉与内置命令冲突的一级命令(排除纯父命令描述)
219
- const filteredTopLevel = topLevelCommands.filter(cmd => {
220
- const cmdName = cmd.command.split(' ')[0];
221
- return !existingCommands.includes(cmdName);
222
- });
223
-
224
- // 创建一个包含所有一级命令名称的集合(包括有子命令的父命令)
225
- const allTopLevelNames = new Set(filteredTopLevel.map(cmd => cmd.command.split(' ')[0]));
226
- subCommands.forEach((_, parent) => allTopLevelNames.add(parent));
227
-
228
- if (allTopLevelNames.size > 0) {
229
- lines.push('插件命令');
230
-
231
- // 按名称排序并显示所有一级命令
232
- const sortedNames = Array.from(allTopLevelNames).sort();
233
- for (const name of sortedNames) {
234
- // 查找匹配的命令
235
- const matchedCmd = filteredTopLevel.find(cmd => cmd.command.split(' ')[0] === name);
236
- if (matchedCmd) {
237
- // 显示完整的命令(包含参数)
238
- lines.push(INDENT + padEnd(matchedCmd.command, CMD_WIDTH) + (matchedCmd.describe || ''));
239
- } else {
240
- // 有子命令的父命令
241
- const desc = parentCommandDescriptions.get(name) || '';
242
- lines.push(INDENT + padEnd(name, CMD_WIDTH) + desc);
243
- }
244
- }
245
-
246
- lines.push('');
247
- }
248
- }
249
-
250
- // 全局选项
251
- lines.push('全局选项');
252
- for (const opt of helpConfig.globalOptions) {
253
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
254
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr);
255
- }
256
- lines.push('');
257
-
258
- // 示例
259
- if (helpConfig.examples && helpConfig.examples.length > 0) {
260
- lines.push('示例');
261
- for (const example of helpConfig.examples) {
262
- lines.push(INDENT + '# ' + example.desc);
263
- lines.push(INDENT + '$ ' + example.cmd);
264
- lines.push('');
265
- }
266
- }
267
-
268
- // 页脚
269
- lines.push(helpConfig.footer);
270
-
271
- return lines.join('\n');
272
- }
273
-
274
- /**
275
- * 渲染命令帮助(二级)
276
- */
277
- function renderCommandHelp(command) {
278
- const cmdConfig = helpConfig.commands[command];
279
- if (!cmdConfig) {
280
- return `未知命令: ${command}`;
281
- }
282
-
283
- const lines = [];
284
-
285
- // 描述
286
- lines.push(cmdConfig.description);
287
- lines.push('');
288
-
289
- // 用法
290
- lines.push('用法');
291
- lines.push(INDENT + cmdConfig.usage);
292
- lines.push('');
293
-
294
- // 备注
295
- if (cmdConfig.note) {
296
- lines.push('说明');
297
- lines.push(INDENT + cmdConfig.note);
298
- lines.push('');
299
- }
300
-
301
- // 子命令
302
- if (cmdConfig.subcommands) {
303
- lines.push('子命令');
304
- for (const [name, subcmd] of Object.entries(cmdConfig.subcommands)) {
305
- const aliasStr = subcmd.aliases ? ` (别名: ${subcmd.aliases.join(', ')})` : '';
306
- lines.push(INDENT + padEnd(name, CMD_WIDTH) + subcmd.description + aliasStr);
307
- }
308
- lines.push('');
309
- }
310
-
311
- // 通用选项
312
- if (cmdConfig.commonOptions && cmdConfig.commonOptions.length > 0) {
313
- lines.push('通用选项');
314
- for (const opt of cmdConfig.commonOptions) {
315
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
316
- const requiredStr = opt.required ? ' (必填)' : '';
317
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
318
- }
319
- lines.push('');
320
- }
321
-
322
- // 选项 (适用于无子命令的命令,如 config)
323
- if (cmdConfig.options && cmdConfig.options.length > 0) {
324
- lines.push('选项');
325
- for (const opt of cmdConfig.options) {
326
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
327
- const requiredStr = opt.required ? ' (必填)' : '';
328
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
329
- }
330
- lines.push('');
331
- }
332
-
333
- // 示例
334
- if (cmdConfig.examples && cmdConfig.examples.length > 0) {
335
- lines.push('示例');
336
- for (const example of cmdConfig.examples) {
337
- lines.push(INDENT + '# ' + example.desc);
338
- lines.push(INDENT + example.cmd);
339
- lines.push('');
340
- }
341
- }
342
-
343
- // 页脚
344
- if (cmdConfig.footer) {
345
- lines.push(cmdConfig.footer);
346
- }
347
-
348
- return lines.join('\n');
349
- }
350
-
351
- /**
352
- * 渲染子命令帮助(三级)
353
- */
354
- function renderSubcommandHelp(command, subcommand) {
355
- const cmdConfig = helpConfig.commands[command];
356
- if (!cmdConfig || !cmdConfig.subcommands || !cmdConfig.subcommands[subcommand]) {
357
- return `未知子命令: ${command} ${subcommand}`;
358
- }
359
-
360
- const subcmdConfig = cmdConfig.subcommands[subcommand];
361
- const lines = [];
362
-
363
- // 描述
364
- lines.push(subcmdConfig.description);
365
- if (subcmdConfig.aliases) {
366
- lines.push(`别名: ${subcmdConfig.aliases.join(', ')}`);
367
- }
368
- lines.push('');
369
-
370
- // 用法
371
- lines.push('用法');
372
- lines.push(INDENT + (subcmdConfig.usage || `rock-cli ${command} ${subcommand} [选项]`));
373
- lines.push('');
374
-
375
- // 嵌套子命令
376
- if (subcmdConfig.subcommands) {
377
- lines.push('子命令');
378
- for (const [name, nested] of Object.entries(subcmdConfig.subcommands)) {
379
- lines.push(INDENT + padEnd(name, CMD_WIDTH) + nested.description);
380
- }
381
- lines.push('');
382
- }
383
-
384
- // 选项
385
- if (subcmdConfig.options && subcmdConfig.options.length > 0) {
386
- lines.push('选项');
387
- for (const opt of subcmdConfig.options) {
388
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
389
- const requiredStr = opt.required ? ' (必填)' : '';
390
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
391
- }
392
- lines.push('');
393
- }
394
-
395
- // 示例
396
- if (subcmdConfig.examples && subcmdConfig.examples.length > 0) {
397
- lines.push('示例');
398
- for (const example of subcmdConfig.examples) {
399
- lines.push(INDENT + '# ' + example.desc);
400
- lines.push(INDENT + example.cmd);
401
- lines.push('');
402
- }
403
- }
404
-
405
- return lines.join('\n');
406
- }
407
-
408
- /**
409
- * 渲染嵌套子命令帮助(四级,如 sandbox session create)
410
- */
411
- function renderNestedSubcommandHelp(command, subcommand, nestedCmd) {
412
- const cmdConfig = helpConfig.commands[command];
413
- const subcmdConfig = cmdConfig?.subcommands?.[subcommand];
414
- const nestedConfig = subcmdConfig?.subcommands?.[nestedCmd];
415
-
416
- if (!nestedConfig) {
417
- return `未知命令: ${command} ${subcommand} ${nestedCmd}`;
418
- }
419
-
420
- const lines = [];
421
-
422
- lines.push(nestedConfig.description);
423
- lines.push('');
424
-
425
- lines.push('用法');
426
- lines.push(INDENT + (nestedConfig.usage || `rock-cli ${command} ${subcommand} ${nestedCmd} [选项]`));
427
- lines.push('');
428
-
429
- if (nestedConfig.options && nestedConfig.options.length > 0) {
430
- lines.push('选项');
431
- for (const opt of nestedConfig.options) {
432
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
433
- const requiredStr = opt.required ? ' (必填)' : '';
434
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
435
- }
436
- lines.push('');
437
- }
438
-
439
- if (nestedConfig.examples && nestedConfig.examples.length > 0) {
440
- lines.push('示例');
441
- for (const example of nestedConfig.examples) {
442
- lines.push(INDENT + '# ' + example.desc);
443
- lines.push(INDENT + example.cmd);
444
- lines.push('');
445
- }
446
- }
447
-
448
- return lines.join('\n');
449
- }
450
-
451
- /**
452
- * 渲染插件子命令帮助
453
- */
454
- function renderPluginSubcommandsHelp(command, subCommands, pluginManager) {
455
- const lines = [];
456
-
457
- // 检查是否有真正的子命令(不是参数变体)
458
- const hasRealSubcommands = subCommands.some(c => {
459
- const parts = c.command.split(' ');
460
- if (parts.length < 2) return false;
461
- const secondPart = parts[1];
462
- // 如果第二个部分以 [ 或 < 开头,则是参数变体,不是子命令
463
- return !secondPart.startsWith('[') && !secondPart.startsWith('<');
464
- });
465
-
466
- // 获取插件名称
467
- const pluginCmd = subCommands[0];
468
- const pluginName = pluginCmd.pluginName || 'unknown';
469
-
470
- // 尝试获取父命令描述
471
- let parentDescribe = '插件命令';
472
- if (pluginManager) {
473
- const allCommands = pluginManager.getRegisteredCommands();
474
- const parentCmd = allCommands.find(cmd => cmd.command === command);
475
- if (parentCmd && parentCmd.describe) {
476
- parentDescribe = parentCmd.describe;
477
- }
478
- }
479
-
480
- if (hasRealSubcommands) {
481
- // 有真正的子命令,显示子命令列表
482
- lines.push(parentDescribe);
483
- lines.push('');
484
-
485
- lines.push('用法');
486
- lines.push(INDENT + `rockcli ${command} <子命令> [选项]`);
487
- lines.push('');
488
-
489
- lines.push('子命令');
490
- for (const subCmd of subCommands) {
491
- const parts = subCmd.command.split(' ');
492
- // 只显示真正的子命令(不是参数变体)
493
- if (parts.length >= 2 && !parts[1].startsWith('[') && !parts[1].startsWith('<')) {
494
- const subCmdName = subCmd.command.substring(command.length + 1);
495
- lines.push(INDENT + padEnd(subCmdName, CMD_WIDTH) + (subCmd.describe || ''));
496
- }
497
- }
498
- lines.push('');
499
-
500
- lines.push('来源');
501
- lines.push(INDENT + `插件: ${pluginName}`);
502
- lines.push('');
503
- } else {
504
- // 没有真正的子命令,都是参数变体,显示命令列表
505
- lines.push('用法');
506
- subCommands.forEach(subCmd => {
507
- lines.push(INDENT + `rockcli ${subCmd.command}`);
508
- });
509
- lines.push('');
510
-
511
- // 显示第一个参数变体的选项
512
- if (subCommands[0].options) {
513
- lines.push('选项');
514
- for (const [name, opt] of Object.entries(subCommands[0].options)) {
515
- const aliasStr = opt.alias ? `, -${opt.alias}` : '';
516
- const defaultStr = opt.default !== undefined ? ` (默认: ${opt.default})` : '';
517
- lines.push(INDENT + padEnd(`--${name}${aliasStr}`, FLAG_WIDTH) + (opt.describe || '') + defaultStr);
518
- }
519
- lines.push('');
520
- }
521
-
522
- lines.push('来源');
523
- lines.push(INDENT + `插件: ${pluginName}`);
524
- lines.push('');
525
- }
526
-
527
- return lines.join('\n');
528
- }
529
-
530
- /**
531
- * 渲染插件命令帮助
532
- */
533
- function renderPluginCommandHelp(cmd, pluginManager = null) {
534
- const lines = [];
535
- const parts = cmd.command.split(' ');
536
-
537
- // 检查是否是父命令(有子命令)
538
- if (pluginManager && parts.length === 1) {
539
- const allPluginCommands = pluginManager.getRegisteredCommands();
540
- const relatedCommands = allPluginCommands.filter(c => c.command.startsWith(cmd.command + ' '));
541
-
542
- if (relatedCommands.length > 0) {
543
- // 检查这些相关命令的第二个部分是否都是参数标记(子命令还是参数变体)
544
- const hasRealSubcommands = relatedCommands.some(c => {
545
- const parts = c.command.split(' ');
546
- if (parts.length < 2) return false;
547
- const secondPart = parts[1];
548
- // 如果第二个部分以 [ 或 < 开头,则是参数变体,不是子命令
549
- return !secondPart.startsWith('[') && !secondPart.startsWith('<');
550
- });
551
-
552
- if (hasRealSubcommands) {
553
- // 有真正的子命令,显示子命令列表
554
- lines.push(cmd.describe || '插件命令');
555
- lines.push('');
556
-
557
- lines.push('用法');
558
- lines.push(INDENT + `rockcli ${cmd.command} <子命令> [选项]`);
559
- lines.push('');
560
-
561
- lines.push('子命令');
562
- for (const subCmd of relatedCommands) {
563
- const parts = subCmd.command.split(' ');
564
- // 只显示真正的子命令(不是参数变体)
565
- if (parts.length >= 2 && !parts[1].startsWith('[') && !parts[1].startsWith('<')) {
566
- const subCmdName = subCmd.command.substring(cmd.command.length + 1);
567
- lines.push(INDENT + padEnd(subCmdName, CMD_WIDTH) + (subCmd.describe || ''));
568
- }
569
- }
570
- lines.push('');
571
-
572
- if (cmd.pluginName) {
573
- lines.push('来源');
574
- lines.push(INDENT + `插件: ${cmd.pluginName}`);
575
- lines.push('');
576
- }
577
-
578
- return lines.join('\n');
579
- } else {
580
- // 没有真正的子命令,都是参数变体,显示命令列表
581
- lines.push('用法');
582
- relatedCommands.forEach(relCmd => {
583
- lines.push(INDENT + `rockcli ${relCmd.command}`);
584
- });
585
- lines.push('');
586
-
587
- // 显示第一个参数变体的选项
588
- if (relatedCommands[0].options) {
589
- lines.push('选项');
590
- for (const [name, opt] of Object.entries(relatedCommands[0].options)) {
591
- const aliasStr = opt.alias ? `, -${opt.alias}` : '';
592
- const defaultStr = opt.default !== undefined ? ` (默认: ${opt.default})` : '';
593
- lines.push(INDENT + padEnd(`--${name}${aliasStr}`, FLAG_WIDTH) + (opt.describe || '') + defaultStr);
594
- }
595
- lines.push('');
596
- }
597
-
598
- if (cmd.pluginName) {
599
- lines.push('来源');
600
- lines.push(INDENT + `插件: ${cmd.pluginName}`);
601
- lines.push('');
602
- }
603
-
604
- return lines.join('\n');
605
- }
606
- }
607
- }
608
-
609
- // 单个命令或没有子命令的情况
610
- lines.push(cmd.describe || '插件命令');
611
- lines.push('');
612
-
613
- lines.push('用法');
614
- lines.push(INDENT + `rockcli ${cmd.command}`);
615
- lines.push('');
616
-
617
- // 选项
618
- if (cmd.options) {
619
- lines.push('选项');
620
- for (const [name, opt] of Object.entries(cmd.options)) {
621
- const aliasStr = opt.alias ? `, -${opt.alias}` : '';
622
- const defaultStr = opt.default !== undefined ? ` (默认: ${opt.default})` : '';
623
- lines.push(INDENT + padEnd(`--${name}${aliasStr}`, FLAG_WIDTH) + (opt.describe || '') + defaultStr);
624
- }
625
- lines.push('');
626
- }
627
-
628
- // 插件来源
629
- if (cmd.pluginName) {
630
- lines.push('来源');
631
- lines.push(INDENT + `插件: ${cmd.pluginName}`);
632
- lines.push('');
633
- }
634
-
635
- return lines.join('\n');
636
- }
637
-
638
- /**
639
- * 渲染插件的帮助配置
640
- * @param {string} command - 命令名称
641
- * @param {Object} helpConfig - 插件的帮助配置
642
- * @param {string} [subcommand] - 子命令名称
643
- * @param {string[]} [rest] - 剩余的命令路径
644
- * @returns {string} 格式化的帮助文本
645
- */
646
- function renderPluginHelpConfig(command, helpConfig, subcommand, rest) {
647
- if (!subcommand) {
648
- // 渲染父命令帮助
649
- return renderPluginCommandHelpConfig(command, helpConfig);
650
- }
651
-
652
- // 渲染子命令帮助
653
- if (helpConfig.subcommands && helpConfig.subcommands[subcommand]) {
654
- const subcmdConfig = helpConfig.subcommands[subcommand];
655
-
656
- // 检查是否有更深层的嵌套子命令
657
- if (rest.length > 0 && subcmdConfig.subcommands && subcmdConfig.subcommands[rest[0]]) {
658
- return renderPluginNestedSubcommandHelpConfig(command, subcommand, rest[0], helpConfig);
659
- }
660
-
661
- return renderPluginSubcommandHelpConfig(command, subcommand, subcmdConfig);
662
- }
663
-
664
- // 没有找到子命令配置,回退到父命令
665
- return renderPluginCommandHelpConfig(command, helpConfig);
666
- }
667
-
668
- /**
669
- * 渲染插件父命令帮助
670
- */
671
- function renderPluginCommandHelpConfig(command, config) {
672
- const lines = [];
673
-
674
- lines.push(config.description || '插件命令');
675
- lines.push('');
676
-
677
- if (config.usage) {
678
- lines.push('用法');
679
- lines.push(INDENT + config.usage);
680
- lines.push('');
681
- }
682
-
683
- // 子命令
684
- if (config.subcommands) {
685
- lines.push('子命令');
686
- for (const [name, subcmd] of Object.entries(config.subcommands)) {
687
- lines.push(INDENT + padEnd(name, CMD_WIDTH) + subcmd.description);
688
- }
689
- lines.push('');
690
- }
691
-
692
- // 通用选项
693
- if (config.commonOptions && config.commonOptions.length > 0) {
694
- lines.push('通用选项');
695
- for (const opt of config.commonOptions) {
696
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
697
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr);
698
- }
699
- lines.push('');
700
- }
701
-
702
- if (config.footer) {
703
- lines.push(config.footer);
704
- }
705
-
706
- return lines.join('\n');
707
- }
708
-
709
- /**
710
- * 渲染插件子命令帮助
711
- */
712
- function renderPluginSubcommandHelpConfig(command, subcommand, config) {
713
- const lines = [];
714
-
715
- lines.push(config.description || '插件子命令');
716
- lines.push('');
717
-
718
- if (config.usage) {
719
- lines.push('用法');
720
- lines.push(INDENT + config.usage);
721
- lines.push('');
722
- }
723
-
724
- // 选项
725
- if (config.options && config.options.length > 0) {
726
- lines.push('选项');
727
- for (const opt of config.options) {
728
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
729
- const requiredStr = opt.required ? ' (必填)' : '';
730
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
731
- }
732
- lines.push('');
733
- }
734
-
735
- // 示例
736
- if (config.examples && config.examples.length > 0) {
737
- lines.push('示例');
738
- for (const example of config.examples) {
739
- lines.push(INDENT + '# ' + example.desc);
740
- lines.push(INDENT + example.cmd);
741
- lines.push('');
742
- }
743
- }
744
-
745
- return lines.join('\n');
746
- }
747
-
748
- /**
749
- * 渲染插件嵌套子命令帮助
750
- */
751
- function renderPluginNestedSubcommandHelpConfig(command, subcommand, nestedCmd, config) {
752
- const subcmdConfig = config.subcommands?.[subcommand];
753
- const nestedConfig = subcmdConfig?.subcommands?.[nestedCmd];
754
-
755
- if (!nestedConfig) {
756
- return `未知命令: ${command} ${subcommand} ${nestedCmd}`;
757
- }
758
-
759
- const lines = [];
760
-
761
- lines.push(nestedConfig.description || '插件嵌套子命令');
762
- lines.push('');
763
-
764
- if (nestedConfig.usage) {
765
- lines.push('用法');
766
- lines.push(INDENT + nestedConfig.usage);
767
- lines.push('');
768
- }
769
-
770
- if (nestedConfig.options && nestedConfig.options.length > 0) {
771
- lines.push('选项');
772
- for (const opt of nestedConfig.options) {
773
- const defaultStr = opt.default ? ` (默认: ${opt.default})` : '';
774
- const requiredStr = opt.required ? ' (必填)' : '';
775
- lines.push(INDENT + padEnd(opt.flags, FLAG_WIDTH) + opt.description + defaultStr + requiredStr);
776
- }
777
- lines.push('');
778
- }
779
-
780
- if (nestedConfig.examples && nestedConfig.examples.length > 0) {
781
- lines.push('示例');
782
- for (const example of nestedConfig.examples) {
783
- lines.push(INDENT + '# ' + example.desc);
784
- lines.push(INDENT + example.cmd);
785
- lines.push('');
786
- }
787
- }
788
-
789
- return lines.join('\n');
790
- }
791
-
792
- module.exports = {
793
- renderHelp,
794
- renderRootHelp,
795
- renderCommandHelp,
796
- renderSubcommandHelp,
797
- renderNestedSubcommandHelp,
798
- renderPluginCommandHelp,
799
- renderPluginHelpConfig
800
- };