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.
- package/README.md +400 -0
- package/index.js +51 -21
- package/package.json +3 -2
- package/commands/log/core/constants.js +0 -237
- package/commands/log/core/display.js +0 -370
- package/commands/log/core/search.js +0 -330
- package/commands/log/core/tail.js +0 -216
- package/commands/log/core/utils.js +0 -424
- package/commands/log.js +0 -298
- package/commands/sandbox/core/log-bridge.js +0 -119
- package/commands/sandbox/core/replay/analyzer.js +0 -311
- package/commands/sandbox/core/replay/batch-orchestrator.js +0 -536
- package/commands/sandbox/core/replay/batch-task.js +0 -369
- package/commands/sandbox/core/replay/concurrent-display.js +0 -70
- package/commands/sandbox/core/replay/concurrent-orchestrator.js +0 -170
- package/commands/sandbox/core/replay/data-source.js +0 -86
- package/commands/sandbox/core/replay/display.js +0 -231
- package/commands/sandbox/core/replay/executor.js +0 -634
- package/commands/sandbox/core/replay/history-fetcher.js +0 -124
- package/commands/sandbox/core/replay/index.js +0 -338
- package/commands/sandbox/core/replay/loghouse-data-source.js +0 -177
- package/commands/sandbox/core/replay/pid-mapping.js +0 -26
- package/commands/sandbox/core/replay/request.js +0 -109
- package/commands/sandbox/core/replay/worker.js +0 -166
- package/commands/sandbox/core/session.js +0 -346
- package/commands/sandbox/log-bridge.js +0 -2
- package/commands/sandbox/ray.js +0 -2
- package/commands/sandbox/replay/analyzer.js +0 -311
- package/commands/sandbox/replay/batch-orchestrator.js +0 -536
- package/commands/sandbox/replay/batch-task.js +0 -369
- package/commands/sandbox/replay/concurrent-display.js +0 -70
- package/commands/sandbox/replay/concurrent-orchestrator.js +0 -170
- package/commands/sandbox/replay/display.js +0 -231
- package/commands/sandbox/replay/executor.js +0 -634
- package/commands/sandbox/replay/history-fetcher.js +0 -118
- package/commands/sandbox/replay/index.js +0 -338
- package/commands/sandbox/replay/pid-mapping.js +0 -26
- package/commands/sandbox/replay/request.js +0 -109
- package/commands/sandbox/replay/worker.js +0 -166
- package/commands/sandbox/replay.js +0 -2
- package/commands/sandbox/session.js +0 -2
- package/commands/sandbox-original.js +0 -1393
- package/commands/sandbox.js +0 -499
- package/help/help.json +0 -1071
- package/help/middleware.js +0 -71
- package/help/renderer.js +0 -800
- package/lib/plugin-context.js +0 -40
- package/sdks/sandbox/core/client.js +0 -845
- package/sdks/sandbox/core/config.js +0 -70
- package/sdks/sandbox/core/types.js +0 -74
- package/sdks/sandbox/httpLogger.js +0 -251
- package/sdks/sandbox/index.js +0 -9
- package/utils/asciiArt.js +0 -138
- package/utils/bun-compat.js +0 -59
- package/utils/ciPipelines.js +0 -138
- package/utils/cli.js +0 -17
- package/utils/command-router.js +0 -79
- package/utils/configManager.js +0 -503
- package/utils/dependency-resolver.js +0 -135
- package/utils/eagleeye_traceid.js +0 -151
- package/utils/envDetector.js +0 -78
- package/utils/execution_logger.js +0 -415
- package/utils/featureManager.js +0 -68
- package/utils/firstTimeTip.js +0 -44
- package/utils/hook-manager.js +0 -125
- package/utils/http-logger.js +0 -264
- package/utils/i18n.js +0 -139
- package/utils/image-progress.js +0 -159
- package/utils/logger.js +0 -154
- package/utils/plugin-loader.js +0 -124
- package/utils/plugin-manager.js +0 -348
- package/utils/ray_cli_wrapper.js +0 -746
- package/utils/sandbox-client.js +0 -419
- package/utils/terminal.js +0 -32
- 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
|
-
};
|