@zshuangmu/agenthub 0.4.14 → 0.4.16
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/LICENSE +21 -21
- package/README.md +268 -268
- package/package.json +41 -41
- package/src/api-server.js +518 -244
- package/src/cli.js +714 -671
- package/src/commands/api.js +9 -9
- package/src/commands/doctor.js +335 -335
- package/src/commands/info.js +15 -15
- package/src/commands/install.js +56 -56
- package/src/commands/list.js +78 -78
- package/src/commands/pack.js +249 -156
- package/src/commands/publish-remote.js +9 -9
- package/src/commands/publish.js +7 -7
- package/src/commands/rollback.js +59 -59
- package/src/commands/search.js +14 -14
- package/src/commands/serve.js +9 -9
- package/src/commands/stats.js +105 -105
- package/src/commands/uninstall.js +76 -76
- package/src/commands/update.js +54 -54
- package/src/commands/verify.js +133 -133
- package/src/commands/versions.js +75 -75
- package/src/commands/web.js +9 -9
- package/src/index.js +18 -18
- package/src/lib/auth.js +301 -0
- package/src/lib/bundle-transfer.js +58 -58
- package/src/lib/colors.js +60 -60
- package/src/lib/database.js +450 -244
- package/src/lib/debug.js +135 -135
- package/src/lib/fs-utils.js +107 -50
- package/src/lib/html.js +2163 -1824
- package/src/lib/http.js +168 -168
- package/src/lib/install.js +60 -60
- package/src/lib/manifest.js +124 -124
- package/src/lib/openclaw-config.js +40 -40
- package/src/lib/permissions.js +105 -0
- package/src/lib/privacy-engine.js +220 -0
- package/src/lib/registry.js +130 -130
- package/src/lib/remote.js +11 -11
- package/src/lib/security-scanner.js +233 -233
- package/src/lib/signing.js +158 -0
- package/src/lib/version-manager.js +77 -77
- package/src/server.js +176 -176
- package/src/web-server.js +135 -135
package/src/cli.js
CHANGED
|
@@ -1,671 +1,714 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* AgentHub CLI
|
|
4
|
-
* AI Agent 打包与分发平台
|
|
5
|
-
*
|
|
6
|
-
* 根据 PRD v1.1 规范实现
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
infoCommand,
|
|
11
|
-
installCommand,
|
|
12
|
-
verifyCommand,
|
|
13
|
-
formatVerifyOutput,
|
|
14
|
-
packCommand,
|
|
15
|
-
publishCommand,
|
|
16
|
-
publishRemoteCommand,
|
|
17
|
-
serveCommand,
|
|
18
|
-
searchCommand,
|
|
19
|
-
apiCommand,
|
|
20
|
-
webCommand,
|
|
21
|
-
updateCommand,
|
|
22
|
-
rollbackCommand,
|
|
23
|
-
listCommand,
|
|
24
|
-
formatListOutput,
|
|
25
|
-
statsCommand,
|
|
26
|
-
formatStatsOutput,
|
|
27
|
-
versionsCommand,
|
|
28
|
-
formatVersionsOutput,
|
|
29
|
-
doctorCommand,
|
|
30
|
-
} from "./index.js";
|
|
31
|
-
import { uninstallCommand, formatUninstallOutput } from "./commands/uninstall.js";
|
|
32
|
-
|
|
33
|
-
import { success, error, warning, info as infoColor, highlight, muted, symbols } from "./lib/colors.js";
|
|
34
|
-
import { setVerbose, debug } from "./lib/debug.js";
|
|
35
|
-
|
|
36
|
-
import { createRequire } from "node:module";
|
|
37
|
-
const require = createRequire(import.meta.url);
|
|
38
|
-
const VERSION = require("../package.json").version;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 验证必需参数,如果缺失则打印错误并设置退出码
|
|
42
|
-
* @param {string} arg - 要验证的参数
|
|
43
|
-
* @param {string} message - 错误消息
|
|
44
|
-
* @returns {boolean} 参数是否存在
|
|
45
|
-
*/
|
|
46
|
-
function requireArg(arg, message) {
|
|
47
|
-
if (!arg) {
|
|
48
|
-
console.error(error(message));
|
|
49
|
-
process.exitCode = 1;
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function printHelp() {
|
|
56
|
-
console.log(`
|
|
57
|
-
AgentHub v${VERSION} - AI Agent 打包与分发平台
|
|
58
|
-
|
|
59
|
-
用法:
|
|
60
|
-
agenthub <command> [options]
|
|
61
|
-
|
|
62
|
-
命令:
|
|
63
|
-
pack 打包 OpenClaw 工作区为 Agent Bundle
|
|
64
|
-
publish 发布 Bundle 到本地 Registry
|
|
65
|
-
publish-remote 发布 Bundle 到远程服务器
|
|
66
|
-
install 安装 Agent 到目标工作区(默认当前目录)
|
|
67
|
-
search 搜索 Registry 中的 Agent
|
|
68
|
-
info 查看 Agent 详情
|
|
69
|
-
list 列出当前目录/指定目录的已安装 Agent
|
|
70
|
-
uninstall 卸载已安装的 Agent
|
|
71
|
-
verify 校验已安装 Agent 是否完整可用
|
|
72
|
-
versions 查看 Agent 版本历史
|
|
73
|
-
update 更新已安装 Agent 到最新版
|
|
74
|
-
rollback 回滚已安装 Agent 到指定版本
|
|
75
|
-
stats 查看 Agent 统计信息
|
|
76
|
-
doctor 诊断 AgentHub 安装和环境问题
|
|
77
|
-
serve 启动 Web + API 服务
|
|
78
|
-
api 仅启动 API 后端服务
|
|
79
|
-
web 仅启动 Web 前端服务
|
|
80
|
-
|
|
81
|
-
选项:
|
|
82
|
-
--help, -h 显示帮助信息
|
|
83
|
-
--version, -v 显示版本号
|
|
84
|
-
--verbose 显示详细日志信息
|
|
85
|
-
|
|
86
|
-
详细帮助:
|
|
87
|
-
agenthub <command> --help
|
|
88
|
-
|
|
89
|
-
示例:
|
|
90
|
-
# 打包 Agent
|
|
91
|
-
agenthub pack --workspace ./my-workspace --config openclaw.json --output ./bundles
|
|
92
|
-
|
|
93
|
-
# 发布 Agent
|
|
94
|
-
agenthub publish ./bundles/my-agent.agent --registry ./.registry
|
|
95
|
-
|
|
96
|
-
# 安装 Agent
|
|
97
|
-
agenthub install my-agent --registry ./.registry --target-workspace ./workspace
|
|
98
|
-
|
|
99
|
-
# 搜索 Agent
|
|
100
|
-
agenthub search "code review" --registry ./.registry
|
|
101
|
-
|
|
102
|
-
# 启动完整服务(前端+后端)
|
|
103
|
-
agenthub serve --registry ./.registry --port 3000
|
|
104
|
-
|
|
105
|
-
`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function printCommandHelp(command) {
|
|
109
|
-
const helps = {
|
|
110
|
-
pack: `
|
|
111
|
-
agenthub pack - 打包 Agent
|
|
112
|
-
|
|
113
|
-
用法:
|
|
114
|
-
agenthub pack --workspace <dir> --config <file> --output <dir>
|
|
115
|
-
|
|
116
|
-
选项:
|
|
117
|
-
--workspace <dir> OpenClaw 工作区目录 (必需)
|
|
118
|
-
--config <file> openclaw.json 配置文件路径 (必需)
|
|
119
|
-
--output <dir> 输出目录 (默认: ./bundles)
|
|
120
|
-
--name <name> Agent 名称 (默认: 工作区目录名)
|
|
121
|
-
--version <ver> 版本号 (默认: 1.0.0)
|
|
122
|
-
--tags <tags> 标签,逗号分隔
|
|
123
|
-
--category <cat> 分类
|
|
124
|
-
--featured 标记为精选 Agent
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
agenthub
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
agenthub
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
agenthub search
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
agenthub
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
agenthub list
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
agenthub
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
agenthub uninstall
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
agenthub
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
agenthub
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
agenthub versions
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
agenthub
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
agenthub
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
agenthub
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
agenthub
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
agenthub publish-remote
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
agenthub
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
agenthub
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
agenthub
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return;
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const result = await
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
console.log(
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const result = await
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
console.log(
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const result = await
|
|
602
|
-
console.log(success(`Server listening at ${result.baseUrl}`));
|
|
603
|
-
console.log(`\n${highlight("🌐
|
|
604
|
-
console.log(` ${muted("地址:")} ${result.baseUrl}`);
|
|
605
|
-
console.log(` ${muted("API:")} ${
|
|
606
|
-
console.log(`\n${muted("按 Ctrl+C 停止服务")}\n`);
|
|
607
|
-
|
|
608
|
-
const shutdown = async () => {
|
|
609
|
-
process.off("SIGINT", shutdown);
|
|
610
|
-
process.off("SIGTERM", shutdown);
|
|
611
|
-
await result.close();
|
|
612
|
-
process.exit(0);
|
|
613
|
-
};
|
|
614
|
-
process.on("SIGINT", shutdown);
|
|
615
|
-
process.on("SIGTERM", shutdown);
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AgentHub CLI
|
|
4
|
+
* AI Agent 打包与分发平台
|
|
5
|
+
*
|
|
6
|
+
* 根据 PRD v1.1 规范实现
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
infoCommand,
|
|
11
|
+
installCommand,
|
|
12
|
+
verifyCommand,
|
|
13
|
+
formatVerifyOutput,
|
|
14
|
+
packCommand,
|
|
15
|
+
publishCommand,
|
|
16
|
+
publishRemoteCommand,
|
|
17
|
+
serveCommand,
|
|
18
|
+
searchCommand,
|
|
19
|
+
apiCommand,
|
|
20
|
+
webCommand,
|
|
21
|
+
updateCommand,
|
|
22
|
+
rollbackCommand,
|
|
23
|
+
listCommand,
|
|
24
|
+
formatListOutput,
|
|
25
|
+
statsCommand,
|
|
26
|
+
formatStatsOutput,
|
|
27
|
+
versionsCommand,
|
|
28
|
+
formatVersionsOutput,
|
|
29
|
+
doctorCommand,
|
|
30
|
+
} from "./index.js";
|
|
31
|
+
import { uninstallCommand, formatUninstallOutput } from "./commands/uninstall.js";
|
|
32
|
+
|
|
33
|
+
import { success, error, warning, info as infoColor, highlight, muted, symbols } from "./lib/colors.js";
|
|
34
|
+
import { setVerbose, debug } from "./lib/debug.js";
|
|
35
|
+
|
|
36
|
+
import { createRequire } from "node:module";
|
|
37
|
+
const require = createRequire(import.meta.url);
|
|
38
|
+
const VERSION = require("../package.json").version;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 验证必需参数,如果缺失则打印错误并设置退出码
|
|
42
|
+
* @param {string} arg - 要验证的参数
|
|
43
|
+
* @param {string} message - 错误消息
|
|
44
|
+
* @returns {boolean} 参数是否存在
|
|
45
|
+
*/
|
|
46
|
+
function requireArg(arg, message) {
|
|
47
|
+
if (!arg) {
|
|
48
|
+
console.error(error(message));
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function printHelp() {
|
|
56
|
+
console.log(`
|
|
57
|
+
AgentHub v${VERSION} - AI Agent 打包与分发平台
|
|
58
|
+
|
|
59
|
+
用法:
|
|
60
|
+
agenthub <command> [options]
|
|
61
|
+
|
|
62
|
+
命令:
|
|
63
|
+
pack 打包 OpenClaw 工作区为 Agent Bundle
|
|
64
|
+
publish 发布 Bundle 到本地 Registry
|
|
65
|
+
publish-remote 发布 Bundle 到远程服务器
|
|
66
|
+
install 安装 Agent 到目标工作区(默认当前目录)
|
|
67
|
+
search 搜索 Registry 中的 Agent
|
|
68
|
+
info 查看 Agent 详情
|
|
69
|
+
list 列出当前目录/指定目录的已安装 Agent
|
|
70
|
+
uninstall 卸载已安装的 Agent
|
|
71
|
+
verify 校验已安装 Agent 是否完整可用
|
|
72
|
+
versions 查看 Agent 版本历史
|
|
73
|
+
update 更新已安装 Agent 到最新版
|
|
74
|
+
rollback 回滚已安装 Agent 到指定版本
|
|
75
|
+
stats 查看 Agent 统计信息
|
|
76
|
+
doctor 诊断 AgentHub 安装和环境问题
|
|
77
|
+
serve 启动 Web + API 服务
|
|
78
|
+
api 仅启动 API 后端服务
|
|
79
|
+
web 仅启动 Web 前端服务
|
|
80
|
+
|
|
81
|
+
选项:
|
|
82
|
+
--help, -h 显示帮助信息
|
|
83
|
+
--version, -v 显示版本号
|
|
84
|
+
--verbose 显示详细日志信息
|
|
85
|
+
|
|
86
|
+
详细帮助:
|
|
87
|
+
agenthub <command> --help
|
|
88
|
+
|
|
89
|
+
示例:
|
|
90
|
+
# 打包 Agent
|
|
91
|
+
agenthub pack --workspace ./my-workspace --config openclaw.json --output ./bundles
|
|
92
|
+
|
|
93
|
+
# 发布 Agent
|
|
94
|
+
agenthub publish ./bundles/my-agent.agent --registry ./.registry
|
|
95
|
+
|
|
96
|
+
# 安装 Agent
|
|
97
|
+
agenthub install my-agent --registry ./.registry --target-workspace ./workspace
|
|
98
|
+
|
|
99
|
+
# 搜索 Agent
|
|
100
|
+
agenthub search "code review" --registry ./.registry
|
|
101
|
+
|
|
102
|
+
# 启动完整服务(前端+后端)
|
|
103
|
+
agenthub serve --registry ./.registry --port 3000
|
|
104
|
+
|
|
105
|
+
`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function printCommandHelp(command) {
|
|
109
|
+
const helps = {
|
|
110
|
+
pack: `
|
|
111
|
+
agenthub pack - 打包 Agent
|
|
112
|
+
|
|
113
|
+
用法:
|
|
114
|
+
agenthub pack --workspace <dir> --config <file> --output <dir>
|
|
115
|
+
|
|
116
|
+
选项:
|
|
117
|
+
--workspace <dir> OpenClaw 工作区目录 (必需)
|
|
118
|
+
--config <file> openclaw.json 配置文件路径 (必需)
|
|
119
|
+
--output <dir> 输出目录 (默认: ./bundles)
|
|
120
|
+
--name <name> Agent 名称 (默认: 工作区目录名)
|
|
121
|
+
--version <ver> 版本号 (默认: 1.0.0)
|
|
122
|
+
--tags <tags> 标签,逗号分隔
|
|
123
|
+
--category <cat> 分类
|
|
124
|
+
--featured 标记为精选 Agent
|
|
125
|
+
--strict 严格模式:发现高危敏感信息时中止打包
|
|
126
|
+
--no-strip-private 不自动剥离私有数据(默认自动剥离)
|
|
127
|
+
--skip-scan 跳过安全扫描
|
|
128
|
+
|
|
129
|
+
🛡️ 隐私防护(默认开启):
|
|
130
|
+
打包时自动排除 memory/private、.env、API Key 等敏感数据
|
|
131
|
+
使用 --strict 可在发现高危问题时中止打包
|
|
132
|
+
|
|
133
|
+
示例:
|
|
134
|
+
agenthub pack --workspace ./my-agent --config ./openclaw.json
|
|
135
|
+
agenthub pack --workspace ./my-agent --config ./openclaw.json --strict
|
|
136
|
+
agenthub pack --workspace ./my-agent --config ./openclaw.json --skip-scan
|
|
137
|
+
`,
|
|
138
|
+
publish: `
|
|
139
|
+
agenthub publish - 发布 Agent
|
|
140
|
+
|
|
141
|
+
用法:
|
|
142
|
+
agenthub publish <bundle-dir> --registry <dir>
|
|
143
|
+
|
|
144
|
+
选项:
|
|
145
|
+
--registry <dir> Registry 目录 (必需)
|
|
146
|
+
|
|
147
|
+
示例:
|
|
148
|
+
agenthub publish ./bundles/my-agent.agent --registry ./.registry
|
|
149
|
+
`,
|
|
150
|
+
install: `
|
|
151
|
+
agenthub install - 安装 Agent
|
|
152
|
+
|
|
153
|
+
用法:
|
|
154
|
+
agenthub install <agent-slug>[:version] [--registry <dir> | --server <url>] --target-workspace <dir>
|
|
155
|
+
|
|
156
|
+
选项:
|
|
157
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
158
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
159
|
+
--target-workspace <dir> 目标工作区目录 (必需)
|
|
160
|
+
--force 强制覆盖
|
|
161
|
+
|
|
162
|
+
示例:
|
|
163
|
+
agenthub install code-review-assistant --registry ./.registry --target-workspace ./workspace
|
|
164
|
+
agenthub install my-agent:1.0.0 --server https://agenthub.cyou --target-workspace ./workspace
|
|
165
|
+
agenthub install meeting-minutes-assistant --target-workspace ./workspace
|
|
166
|
+
`,
|
|
167
|
+
search: `
|
|
168
|
+
agenthub search - 搜索 Agent
|
|
169
|
+
|
|
170
|
+
用法:
|
|
171
|
+
agenthub search <query> --registry <dir>
|
|
172
|
+
|
|
173
|
+
选项:
|
|
174
|
+
--registry <dir> Registry 目录 (必需)
|
|
175
|
+
--json JSON 格式输出
|
|
176
|
+
|
|
177
|
+
示例:
|
|
178
|
+
agenthub search "code review" --registry ./.registry
|
|
179
|
+
agenthub search "" --registry ./.registry # 列出所有
|
|
180
|
+
agenthub search "code" --registry ./.registry --json
|
|
181
|
+
`,
|
|
182
|
+
list: `
|
|
183
|
+
agenthub list - 列出已安装 Agent
|
|
184
|
+
|
|
185
|
+
用法:
|
|
186
|
+
agenthub list [--target-workspace <dir>] [--json]
|
|
187
|
+
|
|
188
|
+
选项:
|
|
189
|
+
--target-workspace <dir> 指定工作区目录(可选)
|
|
190
|
+
--json JSON 格式输出
|
|
191
|
+
|
|
192
|
+
示例:
|
|
193
|
+
agenthub list
|
|
194
|
+
agenthub list --target-workspace ./my-workspace
|
|
195
|
+
agenthub list --json
|
|
196
|
+
agenthub list --target-workspace ./my-workspace
|
|
197
|
+
`,
|
|
198
|
+
uninstall: `
|
|
199
|
+
agenthub uninstall - 卸载已安装 Agent
|
|
200
|
+
|
|
201
|
+
用法:
|
|
202
|
+
agenthub uninstall <agent-slug> [--target-workspace <dir>]
|
|
203
|
+
|
|
204
|
+
选项:
|
|
205
|
+
--target-workspace <dir> 指定工作区目录(可选)
|
|
206
|
+
|
|
207
|
+
示例:
|
|
208
|
+
agenthub uninstall my-agent
|
|
209
|
+
agenthub uninstall my-agent --target-workspace ./my-workspace
|
|
210
|
+
`,
|
|
211
|
+
verify: `
|
|
212
|
+
agenthub verify - 校验已安装 Agent
|
|
213
|
+
|
|
214
|
+
用法:
|
|
215
|
+
agenthub verify [agent-slug] [--registry <dir> | --server <url>] [--target-workspace <dir>]
|
|
216
|
+
|
|
217
|
+
选项:
|
|
218
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
219
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
220
|
+
--target-workspace <dir> 目标工作区目录(默认当前目录)
|
|
221
|
+
|
|
222
|
+
示例:
|
|
223
|
+
agenthub verify workspace --registry ./.registry --target-workspace ./my-workspace
|
|
224
|
+
agenthub verify workspace --server https://agenthub.cyou --target-workspace ./my-workspace
|
|
225
|
+
`,
|
|
226
|
+
versions: `
|
|
227
|
+
agenthub versions - 查看版本历史
|
|
228
|
+
|
|
229
|
+
用法:
|
|
230
|
+
agenthub versions <agent-slug> [--registry <dir> | --server <url>]
|
|
231
|
+
|
|
232
|
+
选项:
|
|
233
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
234
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
235
|
+
|
|
236
|
+
示例:
|
|
237
|
+
agenthub versions workspace --registry ./.registry
|
|
238
|
+
agenthub versions workspace --server https://agenthub.cyou
|
|
239
|
+
`,
|
|
240
|
+
update: `
|
|
241
|
+
agenthub update - 更新 Agent 到最新版
|
|
242
|
+
|
|
243
|
+
用法:
|
|
244
|
+
agenthub update <agent-slug> [--registry <dir> | --server <url>] --target-workspace <dir>
|
|
245
|
+
|
|
246
|
+
选项:
|
|
247
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
248
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
249
|
+
--target-workspace <dir> 目标工作区目录 (必需)
|
|
250
|
+
|
|
251
|
+
示例:
|
|
252
|
+
agenthub update workspace --registry ./.registry --target-workspace ./my-workspace
|
|
253
|
+
agenthub update workspace --server https://agenthub.cyou --target-workspace ./my-workspace
|
|
254
|
+
`,
|
|
255
|
+
rollback: `
|
|
256
|
+
agenthub rollback - 回滚 Agent 到指定版本
|
|
257
|
+
|
|
258
|
+
用法:
|
|
259
|
+
agenthub rollback <agent-slug> --to <version> [--registry <dir> | --server <url>] --target-workspace <dir>
|
|
260
|
+
|
|
261
|
+
选项:
|
|
262
|
+
--to <version> 目标版本 (必需)
|
|
263
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
264
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
265
|
+
--target-workspace <dir> 目标工作区目录 (必需)
|
|
266
|
+
|
|
267
|
+
示例:
|
|
268
|
+
agenthub rollback workspace --to 1.0.0 --registry ./.registry --target-workspace ./my-workspace
|
|
269
|
+
agenthub rollback workspace --to 1.0.0 --server https://agenthub.cyou --target-workspace ./my-workspace
|
|
270
|
+
`,
|
|
271
|
+
info: `
|
|
272
|
+
agenthub info - 查看 Agent 详情
|
|
273
|
+
|
|
274
|
+
用法:
|
|
275
|
+
agenthub info <agent-slug> [--registry <dir> | --server <url>]
|
|
276
|
+
|
|
277
|
+
选项:
|
|
278
|
+
--registry <dir> 本地 Registry 目录(与 --server 二选一)
|
|
279
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
280
|
+
--json JSON 格式输出
|
|
281
|
+
|
|
282
|
+
示例:
|
|
283
|
+
agenthub info code-review-assistant --registry ./.registry
|
|
284
|
+
agenthub info my-agent --server https://agenthub.cyou --json
|
|
285
|
+
`,
|
|
286
|
+
"publish-remote": `
|
|
287
|
+
agenthub publish-remote - 发布 Agent 到远程服务器
|
|
288
|
+
|
|
289
|
+
用法:
|
|
290
|
+
agenthub publish-remote <bundle-dir> --server <url>
|
|
291
|
+
|
|
292
|
+
选项:
|
|
293
|
+
--server <url> 远程服务器地址(默认: https://agenthub.cyou)
|
|
294
|
+
|
|
295
|
+
示例:
|
|
296
|
+
agenthub publish-remote ./bundles/my-agent.agent
|
|
297
|
+
agenthub publish-remote ./bundles/my-agent.agent --server https://agenthub.cyou
|
|
298
|
+
`,
|
|
299
|
+
stats: `
|
|
300
|
+
agenthub stats - 查看 Agent 统计信息
|
|
301
|
+
|
|
302
|
+
用法:
|
|
303
|
+
agenthub stats <agent-slug> --registry <dir>
|
|
304
|
+
|
|
305
|
+
选项:
|
|
306
|
+
--registry <dir> Registry 目录 (必需)
|
|
307
|
+
|
|
308
|
+
示例:
|
|
309
|
+
agenthub stats workspace --registry ./.registry
|
|
310
|
+
`,
|
|
311
|
+
doctor: `
|
|
312
|
+
agenthub doctor - 诊断 AgentHub 安装和环境问题
|
|
313
|
+
|
|
314
|
+
用法:
|
|
315
|
+
agenthub doctor [options]
|
|
316
|
+
|
|
317
|
+
选项:
|
|
318
|
+
--full 运行完整诊断(包括测试套件)
|
|
319
|
+
--no-network 跳过网络连接检查
|
|
320
|
+
--server <url> 指定服务器地址检查(默认: https://agenthub.cyou)
|
|
321
|
+
|
|
322
|
+
示例:
|
|
323
|
+
agenthub doctor
|
|
324
|
+
agenthub doctor --full
|
|
325
|
+
agenthub doctor --no-network
|
|
326
|
+
`,
|
|
327
|
+
serve: `
|
|
328
|
+
agenthub serve - 启动完整服务(前端+后端)
|
|
329
|
+
|
|
330
|
+
用法:
|
|
331
|
+
agenthub serve --registry <dir> --port <port>
|
|
332
|
+
|
|
333
|
+
选项:
|
|
334
|
+
--registry <dir> Registry 目录 (必需)
|
|
335
|
+
--port <port> 前端端口号 (默认: 3000)
|
|
336
|
+
--api-port <port> 后端 API 端口号 (默认: 3001)
|
|
337
|
+
--host <host> 监听地址 (默认: 0.0.0.0)
|
|
338
|
+
|
|
339
|
+
示例:
|
|
340
|
+
agenthub serve --registry ./.registry --port 3000
|
|
341
|
+
agenthub serve --registry ./.registry --host 127.0.0.1
|
|
342
|
+
`,
|
|
343
|
+
api: `
|
|
344
|
+
agenthub api - 仅启动 API 后端服务
|
|
345
|
+
|
|
346
|
+
用法:
|
|
347
|
+
agenthub api --registry <dir> --port <port>
|
|
348
|
+
|
|
349
|
+
选项:
|
|
350
|
+
--registry <dir> Registry 目录 (必需)
|
|
351
|
+
--port <port> API 端口号 (默认: 3001)
|
|
352
|
+
--host <host> 监听地址 (默认: 0.0.0.0)
|
|
353
|
+
|
|
354
|
+
示例:
|
|
355
|
+
agenthub api --registry ./.registry --port 3001
|
|
356
|
+
`,
|
|
357
|
+
web: `
|
|
358
|
+
agenthub web - 仅启动 Web 前端服务
|
|
359
|
+
|
|
360
|
+
用法:
|
|
361
|
+
agenthub web --port <port> --api-base <url>
|
|
362
|
+
|
|
363
|
+
选项:
|
|
364
|
+
--port <port> Web 端口号 (默认: 3000)
|
|
365
|
+
--api-base <url> API 服务地址 (默认: http://127.0.0.1:3001)
|
|
366
|
+
--host <host> 监听地址 (默认: 0.0.0.0)
|
|
367
|
+
|
|
368
|
+
示例:
|
|
369
|
+
agenthub web --port 3000 --api-base http://127.0.0.1:3001
|
|
370
|
+
`,
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
console.log(helps[command] || `未知命令: ${command}`);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function parseArgs(argv) {
|
|
377
|
+
const positionals = [];
|
|
378
|
+
const options = {};
|
|
379
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
380
|
+
const token = argv[index];
|
|
381
|
+
if (token.startsWith("--")) {
|
|
382
|
+
const rawKey = token.slice(2);
|
|
383
|
+
const camelKey = rawKey.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
384
|
+
const value = argv[index + 1];
|
|
385
|
+
if (value && !value.startsWith("-")) {
|
|
386
|
+
options[rawKey] = value;
|
|
387
|
+
options[camelKey] = value;
|
|
388
|
+
index += 1;
|
|
389
|
+
} else {
|
|
390
|
+
options[rawKey] = true;
|
|
391
|
+
options[camelKey] = true;
|
|
392
|
+
}
|
|
393
|
+
} else if (token === "-h") {
|
|
394
|
+
options.help = true;
|
|
395
|
+
} else if (token === "-v") {
|
|
396
|
+
options.version = true;
|
|
397
|
+
} else {
|
|
398
|
+
positionals.push(token);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return { positionals, options };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async function main() {
|
|
405
|
+
const { positionals, options } = parseArgs(process.argv.slice(2));
|
|
406
|
+
const [command, ...rest] = positionals;
|
|
407
|
+
|
|
408
|
+
// 设置 verbose 模式
|
|
409
|
+
if (options.verbose) {
|
|
410
|
+
setVerbose(true);
|
|
411
|
+
debug("Verbose mode enabled");
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 全局选项 - only show version if --version/-v is a boolean flag, not a string value
|
|
415
|
+
if (options.version === true) {
|
|
416
|
+
console.log(`AgentHub v${VERSION}`);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (!command) {
|
|
421
|
+
printHelp();
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// 命令帮助
|
|
426
|
+
if (options.help) {
|
|
427
|
+
printCommandHelp(command);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// 命令路由
|
|
432
|
+
try {
|
|
433
|
+
switch (command) {
|
|
434
|
+
case "pack": {
|
|
435
|
+
if (!options.workspace || !options.config) {
|
|
436
|
+
console.error(error("错误: --workspace 和 --config 是必需的"));
|
|
437
|
+
console.log(muted("\n运行 'agenthub pack --help' 查看帮助"));
|
|
438
|
+
process.exitCode = 1;
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
// 处理 --no-strip-private 标志
|
|
442
|
+
if (options['no-strip-private'] || options.noStripPrivate) {
|
|
443
|
+
options.stripPrivate = false;
|
|
444
|
+
}
|
|
445
|
+
const result = await packCommand(options);
|
|
446
|
+
console.log(success(`\n${symbols.success} 打包完成: ${result.bundleDir}`));
|
|
447
|
+
// 输出隐私防护报告
|
|
448
|
+
if (result.privacy) {
|
|
449
|
+
console.log(` ${muted('🛡️ 隐私防护:')} ${result.privacy.stripped ? '已启用' : '未启用'}`);
|
|
450
|
+
console.log(` ${muted('📁 已复制:')} ${result.privacy.copiedFiles} 个文件`);
|
|
451
|
+
if (result.privacy.skippedFiles > 0) {
|
|
452
|
+
console.log(` ${warning('🚫 已剥离 ' + result.privacy.skippedFiles + ' 个文件/目录:')}`);
|
|
453
|
+
for (const skipped of result.privacy.skippedList) {
|
|
454
|
+
// 根据路径类型标注图标
|
|
455
|
+
let icon = ' ◦';
|
|
456
|
+
if (skipped.includes('memory/private') || skipped === 'memory/private') {
|
|
457
|
+
icon = ' 🔒';
|
|
458
|
+
} else if (skipped.startsWith('.env') || skipped === '.npmrc' || skipped === '.netrc') {
|
|
459
|
+
icon = ' 🔑';
|
|
460
|
+
} else if (skipped === '.git' || skipped === '.vscode' || skipped === '.idea') {
|
|
461
|
+
icon = ' 📂';
|
|
462
|
+
} else if (skipped === 'node_modules') {
|
|
463
|
+
icon = ' 📦';
|
|
464
|
+
}
|
|
465
|
+
console.log(` ${icon} ${muted(skipped)}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (result.security) {
|
|
470
|
+
if (result.security.findingsCount > 0) {
|
|
471
|
+
console.log(warning(` ⚠️ 安全扫描: 发现 ${result.security.findingsCount} 个潜在风险`));
|
|
472
|
+
for (const w of result.security.warnings.slice(0, 5)) {
|
|
473
|
+
console.log(` ${w}`);
|
|
474
|
+
}
|
|
475
|
+
} else {
|
|
476
|
+
console.log(` ${success('✅ 安全扫描: 未发现敏感信息')}`);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
case "publish": {
|
|
483
|
+
if (!requireArg(rest[0], "错误: 需要指定 bundle 目录")) return;
|
|
484
|
+
const result = await publishCommand(rest[0], options);
|
|
485
|
+
console.log(success(`${symbols.success} 已发布 ${highlight(`${result.slug}@${result.version}`)}`));
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
case "publish-remote": {
|
|
490
|
+
if (!requireArg(rest[0], "错误: 需要指定 bundle 目录")) return;
|
|
491
|
+
const result = await publishRemoteCommand(rest[0], options);
|
|
492
|
+
console.log(success(`${symbols.success} 已发布到远程 ${highlight(`${result.slug}@${result.version}`)}`));
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
case "search": {
|
|
497
|
+
const results = await searchCommand(rest[0] || "", options);
|
|
498
|
+
if (options.json) {
|
|
499
|
+
console.log(JSON.stringify({ agents: results, count: results.length, query: rest[0] || "" }, null, 2));
|
|
500
|
+
} else if (results.length === 0) {
|
|
501
|
+
console.log(warning("未找到匹配的 Agent"));
|
|
502
|
+
} else {
|
|
503
|
+
console.log(`\n${infoColor(`找到 ${results.length} 个 Agent:`)}\n`);
|
|
504
|
+
for (const entry of results) {
|
|
505
|
+
console.log(` ${highlight(entry.slug)}${muted("@")}${entry.version} ${muted("-")} ${entry.description || ""}`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
case "info": {
|
|
512
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
513
|
+
const result = await infoCommand(rest[0], options);
|
|
514
|
+
if (options.json) {
|
|
515
|
+
console.log(JSON.stringify(result, null, 2));
|
|
516
|
+
} else {
|
|
517
|
+
console.log(`\n${highlight("📦")} ${result.name} (${result.slug}@${result.version})`);
|
|
518
|
+
console.log(` ${result.description}`);
|
|
519
|
+
console.log(` ${muted("Runtime:")} ${result.runtime?.type || "openclaw"} ${result.runtime?.version || ""}`);
|
|
520
|
+
const mem = result.includes?.memory || {};
|
|
521
|
+
if (mem.count > 0) {
|
|
522
|
+
console.log(` ${muted("Memory:")} ${mem.count} 条 (public: ${mem.public}, portable: ${mem.portable})`);
|
|
523
|
+
}
|
|
524
|
+
console.log(`\n ${infoColor("安装命令:")} agenthub install ${result.slug}`);
|
|
525
|
+
}
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
case "install": {
|
|
530
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
531
|
+
console.log(`\n${infoColor("📥 正在安装")} ${highlight(rest[0])}...\n`);
|
|
532
|
+
const installResult = await installCommand(rest[0], options);
|
|
533
|
+
console.log(success(`${symbols.success} 已安装 ${highlight(`${installResult.manifest.slug}@${installResult.manifest.version}`)}`));
|
|
534
|
+
console.log(` ${muted("位置:")} ${options.targetWorkspace || "当前目录"}`);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
case "list": {
|
|
539
|
+
const list = await listCommand(options);
|
|
540
|
+
if (options.json) {
|
|
541
|
+
console.log(JSON.stringify({ agents: list, count: list.length }, null, 2));
|
|
542
|
+
} else {
|
|
543
|
+
console.log(formatListOutput(list));
|
|
544
|
+
}
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
case "uninstall": {
|
|
549
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
550
|
+
const result = await uninstallCommand(rest[0], options);
|
|
551
|
+
console.log(formatUninstallOutput(result));
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
case "verify": {
|
|
556
|
+
const result = await verifyCommand(rest[0], options);
|
|
557
|
+
console.log(formatVerifyOutput(result));
|
|
558
|
+
if (!result.verified) {
|
|
559
|
+
process.exitCode = 1;
|
|
560
|
+
}
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
case "versions": {
|
|
565
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
566
|
+
const versions = await versionsCommand(rest[0], options);
|
|
567
|
+
console.log(formatVersionsOutput(rest[0], versions));
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
case "update": {
|
|
572
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
573
|
+
const updateResult = await updateCommand(rest[0], options);
|
|
574
|
+
console.log(updateResult.message);
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
case "rollback": {
|
|
579
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
580
|
+
const rollbackResult = await rollbackCommand(rest[0], options);
|
|
581
|
+
console.log(rollbackResult.message);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
case "stats": {
|
|
586
|
+
if (!requireArg(rest[0], "错误: 需要指定 agent slug")) return;
|
|
587
|
+
const stats = await statsCommand(rest[0], options);
|
|
588
|
+
console.log(formatStatsOutput(stats));
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
case "doctor": {
|
|
593
|
+
const result = await doctorCommand(options);
|
|
594
|
+
if (!result.healthy) {
|
|
595
|
+
process.exitCode = 1;
|
|
596
|
+
}
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
case "serve": {
|
|
601
|
+
const result = await serveCommand(options);
|
|
602
|
+
console.log(success(`Server listening at ${result.baseUrl}`));
|
|
603
|
+
console.log(`\n${highlight("🌐 AgentHub 服务已启动")}`);
|
|
604
|
+
console.log(` ${muted("地址:")} ${result.baseUrl}`);
|
|
605
|
+
console.log(` ${muted("API:")} ${result.baseUrl}/api/agents`);
|
|
606
|
+
console.log(`\n${muted("按 Ctrl+C 停止服务")}\n`);
|
|
607
|
+
|
|
608
|
+
const shutdown = async () => {
|
|
609
|
+
process.off("SIGINT", shutdown);
|
|
610
|
+
process.off("SIGTERM", shutdown);
|
|
611
|
+
await result.close();
|
|
612
|
+
process.exit(0);
|
|
613
|
+
};
|
|
614
|
+
process.on("SIGINT", shutdown);
|
|
615
|
+
process.on("SIGTERM", shutdown);
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
case "api": {
|
|
620
|
+
const port = options.port || "3001";
|
|
621
|
+
const result = await apiCommand({ ...options, port });
|
|
622
|
+
console.log(success(`Server listening at ${result.baseUrl}`));
|
|
623
|
+
console.log(`\n${highlight("🔧 API 服务已启动")}`);
|
|
624
|
+
console.log(` ${muted("地址:")} ${result.baseUrl}`);
|
|
625
|
+
console.log(` ${muted("端点:")} ${result.baseUrl}/api/agents`);
|
|
626
|
+
console.log(` ${muted("统计:")} ${result.baseUrl}/api/stats`);
|
|
627
|
+
console.log(`\n${muted("按 Ctrl+C 停止服务")}\n`);
|
|
628
|
+
|
|
629
|
+
const shutdown = async () => {
|
|
630
|
+
process.off("SIGINT", shutdown);
|
|
631
|
+
process.off("SIGTERM", shutdown);
|
|
632
|
+
await result.close();
|
|
633
|
+
process.exit(0);
|
|
634
|
+
};
|
|
635
|
+
process.on("SIGINT", shutdown);
|
|
636
|
+
process.on("SIGTERM", shutdown);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
case "web": {
|
|
641
|
+
const port = options.port || "3000";
|
|
642
|
+
const apiBase = options.apiBase || "http://127.0.0.1:3001";
|
|
643
|
+
const host = options.host || "0.0.0.0";
|
|
644
|
+
const result = await webCommand({ port, apiBase, host });
|
|
645
|
+
console.log(success(`Server listening at ${result.baseUrl}`));
|
|
646
|
+
console.log(`\n${highlight("🌐 Web 服务已启动")}`);
|
|
647
|
+
console.log(` ${muted("地址:")} ${result.baseUrl}`);
|
|
648
|
+
console.log(` ${muted("API:")} ${apiBase}`);
|
|
649
|
+
console.log(`\n${muted("按 Ctrl+C 停止服务")}\n`);
|
|
650
|
+
|
|
651
|
+
const shutdown = async () => {
|
|
652
|
+
process.off("SIGINT", shutdown);
|
|
653
|
+
process.off("SIGTERM", shutdown);
|
|
654
|
+
await result.close();
|
|
655
|
+
process.exit(0);
|
|
656
|
+
};
|
|
657
|
+
process.on("SIGINT", shutdown);
|
|
658
|
+
process.on("SIGTERM", shutdown);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
default:
|
|
663
|
+
console.error(error(`未知命令: ${command}`));
|
|
664
|
+
console.log(muted("\n运行 'agenthub --help' 查看可用命令"));
|
|
665
|
+
process.exitCode = 1;
|
|
666
|
+
}
|
|
667
|
+
} catch (err) {
|
|
668
|
+
// 提取更详细的错误信息
|
|
669
|
+
const causeMsg = err.cause?.errors?.[0]?.message || err.cause?.message || "";
|
|
670
|
+
const detailMsg = causeMsg ? `${err.message}\n 原因: ${causeMsg}` : err.message;
|
|
671
|
+
console.error(`\n${error(`${symbols.error} 错误:`)} ${detailMsg}`);
|
|
672
|
+
|
|
673
|
+
// 提供友好的解决建议
|
|
674
|
+
const errMsg = err.message.toLowerCase();
|
|
675
|
+
if (errMsg.includes("not found") || errMsg.includes("does not exist") || errMsg.includes("enoent")) {
|
|
676
|
+
console.log(`\n${warning("建议:")}`);
|
|
677
|
+
console.log(` - 检查文件路径是否正确`);
|
|
678
|
+
console.log(` - 确认 workspace 目录存在`);
|
|
679
|
+
console.log(` - 运行 ${highlight("agenthub --help")} 查看命令用法`);
|
|
680
|
+
} else if (errMsg.includes("permission") || errMsg.includes("eacces")) {
|
|
681
|
+
console.log(`\n${warning("建议:")}`);
|
|
682
|
+
console.log(` - 检查文件权限`);
|
|
683
|
+
console.log(` - 尝试使用 ${highlight("sudo")} 命令`);
|
|
684
|
+
} else if (errMsg.includes("network") || errMsg.includes("econnrefused") || errMsg.includes("timeout") || errMsg.includes("fetch failed")) {
|
|
685
|
+
console.log(`\n${warning("建议:")}`);
|
|
686
|
+
console.log(` - 检查网络连接`);
|
|
687
|
+
console.log(` - 确认服务器地址正确`);
|
|
688
|
+
console.log(` - 使用 ${highlight("--registry")} 指定本地 registry`);
|
|
689
|
+
console.log(` - 运行 ${highlight("agenthub doctor")} 诊断环境问题`);
|
|
690
|
+
} else if (errMsg.includes("agent not found") || errMsg.includes("no agent")) {
|
|
691
|
+
console.log(`\n${warning("建议:")}`);
|
|
692
|
+
console.log(` - 运行 ${highlight("agenthub search")} 查看可用 Agent`);
|
|
693
|
+
console.log(` - 检查 Agent 名称拼写`);
|
|
694
|
+
console.log(` - 确认使用正确的 --registry 路径`);
|
|
695
|
+
} else if (errMsg.includes("invalid") || errMsg.includes("validation")) {
|
|
696
|
+
console.log(`\n${warning("建议:")}`);
|
|
697
|
+
console.log(` - 检查配置文件格式 (openclaw.json)`);
|
|
698
|
+
console.log(` - 确认 workspace 包含必需文件 (AGENTS.md, SOUL.md 等)`);
|
|
699
|
+
console.log(` - 运行 ${highlight("agenthub verify")} 检查安装完整性`);
|
|
700
|
+
} else if (errMsg.includes("version") || errMsg.includes("already")) {
|
|
701
|
+
console.log(`\n${warning("建议:")}`);
|
|
702
|
+
console.log(` - 运行 ${highlight("agenthub versions <agent>")} 查看可用版本`);
|
|
703
|
+
console.log(` - 使用 ${highlight("--force")} 强制覆盖安装`);
|
|
704
|
+
console.log(` - 运行 ${highlight("agenthub list")} 查看已安装的 Agent`);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
console.log(`\n${muted("如需更多帮助:")}`);
|
|
708
|
+
console.log(`${muted(" - 运行: agenthub <command> --help")}`);
|
|
709
|
+
console.log(`${muted(" - 诊断: agenthub doctor")}`);
|
|
710
|
+
process.exitCode = 1;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
main();
|