@okclaw-build/cli 1.0.0-beta.4 → 1.0.0-beta.41

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 (65) hide show
  1. package/dist/commands/check.js +22 -6
  2. package/dist/commands/check.js.map +1 -1
  3. package/dist/commands/edit.d.ts +2 -7
  4. package/dist/commands/edit.js +28 -15
  5. package/dist/commands/edit.js.map +1 -1
  6. package/dist/commands/feed.d.ts +0 -9
  7. package/dist/commands/feed.js +80 -103
  8. package/dist/commands/feed.js.map +1 -1
  9. package/dist/commands/install.js +57 -9
  10. package/dist/commands/install.js.map +1 -1
  11. package/dist/commands/service.js +65 -12
  12. package/dist/commands/service.js.map +1 -1
  13. package/dist/commands/show.d.ts +13 -0
  14. package/dist/commands/show.js +70 -0
  15. package/dist/commands/show.js.map +1 -0
  16. package/dist/commands/skill.d.ts +1 -0
  17. package/dist/commands/skill.js +114 -0
  18. package/dist/commands/skill.js.map +1 -0
  19. package/dist/commands/uninstall.d.ts +1 -0
  20. package/dist/commands/uninstall.js +46 -0
  21. package/dist/commands/uninstall.js.map +1 -0
  22. package/dist/index.js +88 -5
  23. package/dist/index.js.map +1 -1
  24. package/dist/installers/base.d.ts +1 -0
  25. package/dist/installers/channel.d.ts +16 -1
  26. package/dist/installers/channel.js +139 -8
  27. package/dist/installers/channel.js.map +1 -1
  28. package/dist/installers/openclaw.d.ts +15 -0
  29. package/dist/installers/openclaw.js +171 -8
  30. package/dist/installers/openclaw.js.map +1 -1
  31. package/dist/installers/openviking-purge.d.ts +52 -0
  32. package/dist/installers/openviking-purge.js +380 -0
  33. package/dist/installers/openviking-purge.js.map +1 -0
  34. package/dist/installers/openviking.js +1 -2
  35. package/dist/installers/openviking.js.map +1 -1
  36. package/dist/installers/skill.d.ts +2 -0
  37. package/dist/installers/skill.js +35 -5
  38. package/dist/installers/skill.js.map +1 -1
  39. package/dist/output/mode.d.ts +11 -0
  40. package/dist/output/mode.js +27 -0
  41. package/dist/output/mode.js.map +1 -0
  42. package/dist/output/ndjson.d.ts +57 -0
  43. package/dist/output/ndjson.js +136 -0
  44. package/dist/output/ndjson.js.map +1 -0
  45. package/dist/utils/constants.d.ts +0 -2
  46. package/dist/utils/constants.js +1 -4
  47. package/dist/utils/constants.js.map +1 -1
  48. package/dist/utils/deps.d.ts +0 -5
  49. package/dist/utils/deps.js +1 -88
  50. package/dist/utils/deps.js.map +1 -1
  51. package/dist/utils/logger.d.ts +10 -0
  52. package/dist/utils/logger.js +31 -4
  53. package/dist/utils/logger.js.map +1 -1
  54. package/dist/utils/mirror.js +14 -0
  55. package/dist/utils/mirror.js.map +1 -1
  56. package/dist/utils/openclaw-config-cli.d.ts +19 -0
  57. package/dist/utils/openclaw-config-cli.js +81 -0
  58. package/dist/utils/openclaw-config-cli.js.map +1 -0
  59. package/dist/utils/openclaw-daemon.d.ts +23 -0
  60. package/dist/utils/openclaw-daemon.js +38 -0
  61. package/dist/utils/openclaw-daemon.js.map +1 -0
  62. package/dist/utils/shell.d.ts +12 -2
  63. package/dist/utils/shell.js +66 -3
  64. package/dist/utils/shell.js.map +1 -1
  65. package/package.json +3 -2
@@ -1,23 +1,76 @@
1
1
  import { shell, shellCapture } from '../utils/shell.js';
2
2
  import { info, success } from '../utils/logger.js';
3
- import { OPENVIKING_ENV } from '../utils/constants.js';
3
+ import { NdjsonEmitter, registerExitHandlers } from '../output/ndjson.js';
4
+ import { isNdjson } from '../output/mode.js';
5
+ async function runSimpleOp(op, step, humanVerb, action) {
6
+ const emitter = new NdjsonEmitter(op);
7
+ registerExitHandlers(emitter);
8
+ emitter.start(`${humanVerb} gateway`);
9
+ info(`${humanVerb} openclaw gateway...`);
10
+ try {
11
+ emitter.stepStart(step, `${humanVerb} gateway`);
12
+ await action();
13
+ emitter.stepDone(step, 'done');
14
+ success(`Gateway ${step}ed.`);
15
+ emitter.end(true, 0);
16
+ }
17
+ catch (e) {
18
+ const msg = e instanceof Error ? e.message : String(e);
19
+ emitter.end(false, 1, `E_${op.toUpperCase()}_FAILED`, { error: msg });
20
+ throw e;
21
+ }
22
+ }
23
+ // openclaw 是 supervisor:fork 出 openclaw-gateway 后自己 epoll_wait 不退。
24
+ // 直接 `nohup ... &` 会让外层 bash 在脚本末尾仍停在 wait4(-1) 上死等 supervisor,
25
+ // Node 的 child.on('close') 因此永远不触发。用 `( nohup ... & )` 子 shell 双 fork:
26
+ // 内层子 shell 背景化 supervisor 后立即退出,supervisor 被 init 收养,外层 bash
27
+ // 没有子进程可等,直接 exit。
28
+ const START_GATEWAY = "mkdir -p /root/.openclaw && ( nohup openclaw gateway </dev/null >/root/.openclaw/gateway.out 2>&1 & ) && sleep 3 && ps -C openclaw-gateway -o pid= >/dev/null";
29
+ // `pkill -f openclaw-gateway` 会按 cmdline substring 命中,误杀任何 cmdline 含此
30
+ // 字符串的进程(实测:bootstrap script 里跑 restart 时,其 bash -c 命令行也含
31
+ // 'openclaw-gateway',被自杀,导致 restart 命令 exit null/1)。
32
+ // `pkill -x openclaw-gateway` 用 comm 字段精确匹配,但 Linux comm 只 15 字符,
33
+ // 而 'openclaw-gateway' 16 字符,直接报错。
34
+ // 唯一稳的办法:`ps -C openclaw-gateway`(by command name,支持超 15 字符) →
35
+ // xargs kill,只杀真的 gateway 进程,不命中 cmdline substring。
36
+ const STOP_GATEWAY = "ps -C openclaw-gateway -o pid= 2>/dev/null | xargs -r kill 2>/dev/null || true";
4
37
  export async function startCommand() {
5
- info('Starting openclaw gateway...');
6
- await shell(`source ${OPENVIKING_ENV} 2>/dev/null || true; openclaw gateway start`);
7
- success('Gateway started.');
38
+ await runSimpleOp('start', 'start', 'Starting', async () => {
39
+ await shell(START_GATEWAY);
40
+ });
8
41
  }
9
42
  export async function stopCommand() {
10
- info('Stopping openclaw gateway...');
11
- await shell('openclaw gateway stop 2>/dev/null || true');
12
- success('Gateway stopped.');
43
+ await runSimpleOp('stop', 'stop', 'Stopping', async () => {
44
+ await shell(STOP_GATEWAY);
45
+ });
13
46
  }
14
47
  export async function restartCommand() {
15
- info('Restarting openclaw gateway...');
16
- await shell(`source ${OPENVIKING_ENV} 2>/dev/null || true; openclaw gateway restart`);
17
- success('Gateway restarted.');
48
+ await runSimpleOp('restart', 'restart', 'Restarting', async () => {
49
+ await shell(`${STOP_GATEWAY}; sleep 1; ${START_GATEWAY}`);
50
+ });
18
51
  }
19
52
  export async function statusCommand() {
20
- const result = await shellCapture('openclaw gateway status 2>&1 || true');
21
- console.log(result.stdout || result.stderr || 'No output');
53
+ const emitter = new NdjsonEmitter('status');
54
+ registerExitHandlers(emitter);
55
+ emitter.start('querying gateway status');
56
+ emitter.stepStart('status', 'checking openclaw gateway process');
57
+ try {
58
+ // ps -C(by command name): 支持超 15 字符 comm,且不会误命中 cmdline 含
59
+ // 'openclaw-gateway' 字符串的其它进程(对照 STOP_GATEWAY 的注释)
60
+ const result = await shellCapture("ps -C openclaw-gateway -o pid,etime,cmd 2>&1 || true");
61
+ const output = result.stdout || result.stderr || 'No gateway process found';
62
+ if (!isNdjson()) {
63
+ console.log(output);
64
+ }
65
+ // ps -C 没命中时输出只有 header,没有 PID 行;命中时 stdout 含 'openclaw-gateway'
66
+ const running = /openclaw-gateway/.test(result.stdout);
67
+ emitter.stepDone('status', 'status query done');
68
+ emitter.end(running, running ? 0 : 1, running ? undefined : 'E_STATUS_NOT_RUNNING', { running, rawOutput: output });
69
+ }
70
+ catch (e) {
71
+ const msg = e instanceof Error ? e.message : String(e);
72
+ emitter.end(false, 1, 'E_STATUS_FAILED', { error: msg });
73
+ throw e;
74
+ }
22
75
  }
23
76
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,UAAU,cAAc,8CAA8C,CAAC,CAAC;IACpF,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACrC,MAAM,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACzD,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACvC,MAAM,KAAK,CAAC,UAAU,cAAc,gDAAgD,CAAC,CAAC;IACtF,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,sCAAsC,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * okclaw show <target...>
3
+ *
4
+ * 把 target 对应的文件内容原样输出到 stdout(text 模式);
5
+ * 在 ndjson 模式下,文件内容放到 end 事件的 fields.content(plan 决策 #16)。
6
+ *
7
+ * - 文件存在 → 输出文件内容,exit 0
8
+ * - 文件不存在 → 输出空内容,exit 0(视为尚未创建)
9
+ * - target 非法 → stderr 提示,exit 1
10
+ *
11
+ * `targets` 参数用于测试注入;生产调用不传第二个参数,使用 edit.ts 导出的 TARGETS。
12
+ */
13
+ export declare function showCommand(args: string[], targets?: Record<string, string>): Promise<void>;
@@ -0,0 +1,70 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { error } from '../utils/logger.js';
3
+ import { TARGETS as DEFAULT_TARGETS } from './edit.js';
4
+ import { NdjsonEmitter, registerExitHandlers } from '../output/ndjson.js';
5
+ import { isNdjson } from '../output/mode.js';
6
+ /**
7
+ * okclaw show <target...>
8
+ *
9
+ * 把 target 对应的文件内容原样输出到 stdout(text 模式);
10
+ * 在 ndjson 模式下,文件内容放到 end 事件的 fields.content(plan 决策 #16)。
11
+ *
12
+ * - 文件存在 → 输出文件内容,exit 0
13
+ * - 文件不存在 → 输出空内容,exit 0(视为尚未创建)
14
+ * - target 非法 → stderr 提示,exit 1
15
+ *
16
+ * `targets` 参数用于测试注入;生产调用不传第二个参数,使用 edit.ts 导出的 TARGETS。
17
+ */
18
+ export async function showCommand(args, targets = DEFAULT_TARGETS) {
19
+ const emitter = new NdjsonEmitter('file_read');
20
+ registerExitHandlers(emitter);
21
+ const requestedTargets = args.filter((arg) => !arg.startsWith('--'));
22
+ if (requestedTargets.length === 0 || requestedTargets.some((target) => !targets[target])) {
23
+ error(`Usage: okclaw show <${Object.keys(targets).join('|')}>`);
24
+ emitter.end(false, 1, 'E_USAGE');
25
+ process.exit(1);
26
+ }
27
+ if (!isNdjson() && requestedTargets.length > 1) {
28
+ error('Multiple targets are only supported with --output=ndjson');
29
+ emitter.end(false, 1, 'E_USAGE');
30
+ process.exit(1);
31
+ }
32
+ emitter.start(`reading ${requestedTargets.join(',')}`, { targets: requestedTargets });
33
+ try {
34
+ const files = [];
35
+ for (const target of requestedTargets) {
36
+ const path = targets[target];
37
+ emitter.stepStart(`read:${target}`, `reading ${path}`, { target, path });
38
+ const exists = existsSync(path);
39
+ const content = exists ? readFileSync(path, 'utf8') : '';
40
+ files.push({ fileKey: target, path, exists, content });
41
+ emitter.stepDone(`read:${target}`, exists ? 'read ok' : 'file not found, returning empty');
42
+ }
43
+ if (!isNdjson()) {
44
+ const { exists, content } = files[0];
45
+ if (exists) {
46
+ process.stdout.write(content);
47
+ }
48
+ }
49
+ // 单文件保持 content 兼容;批量读取用 files 数组承载返回值。
50
+ if (requestedTargets.length === 1) {
51
+ const file = files[0];
52
+ emitter.end(true, 0, undefined, {
53
+ target: file.fileKey,
54
+ path: file.path,
55
+ exists: file.exists,
56
+ content: file.content,
57
+ });
58
+ }
59
+ else {
60
+ emitter.end(true, 0, undefined, { files });
61
+ }
62
+ }
63
+ catch (e) {
64
+ const msg = e instanceof Error ? e.message : String(e);
65
+ error(msg);
66
+ emitter.end(false, 1, 'E_READ_FAILED', { error: msg });
67
+ process.exit(1);
68
+ }
69
+ }
70
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function skillCommand(args: string[]): Promise<void>;
@@ -0,0 +1,114 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { SkillInstaller } from '../installers/skill.js';
3
+ import { configureMirrors } from '../utils/mirror.js';
4
+ import { info, error, success } from '../utils/logger.js';
5
+ import { NdjsonEmitter, registerExitHandlers } from '../output/ndjson.js';
6
+ export async function skillCommand(args) {
7
+ const subCommand = args[0];
8
+ const skillName = args[1];
9
+ if (!subCommand || !['install', 'uninstall'].includes(subCommand)) {
10
+ const emitter = new NdjsonEmitter('skill_install');
11
+ registerExitHandlers(emitter);
12
+ error('Usage: okclaw skill <install|uninstall> <name> [options]');
13
+ emitter.end(false, 1, 'E_USAGE');
14
+ process.exit(1);
15
+ }
16
+ const op = subCommand === 'install' ? 'skill_install' : 'skill_uninstall';
17
+ const emitter = new NdjsonEmitter(op);
18
+ registerExitHandlers(emitter);
19
+ if (!skillName) {
20
+ error(`Usage: okclaw skill ${subCommand} <name>${subCommand === 'install' ? ' --version <ver> [--package-url <url>]' : ''}`);
21
+ emitter.end(false, 1, 'E_USAGE');
22
+ process.exit(1);
23
+ }
24
+ const installer = new SkillInstaller(skillName);
25
+ if (subCommand === 'uninstall') {
26
+ emitter.start(`uninstalling skill ${skillName}`, { skillName });
27
+ info(`Uninstalling skill ${skillName}...`);
28
+ try {
29
+ emitter.stepStart('validate', `validating skill name ${skillName}`);
30
+ // installer 内部校验名称,SkillInstaller.uninstall 会在目标不存在时快速返回
31
+ emitter.stepDone('validate', 'skill name ok');
32
+ emitter.stepStart('uninstall', `removing ${skillName}`);
33
+ await installer.uninstall();
34
+ emitter.stepDone('uninstall', 'skill removed');
35
+ success(`Skill ${skillName} uninstalled.`);
36
+ emitter.end(true, 0, undefined, { skillName });
37
+ }
38
+ catch (e) {
39
+ const msg = e instanceof Error ? e.message : String(e);
40
+ error(msg);
41
+ emitter.end(false, 1, 'E_SKILL_UNINSTALL_FAILED', { error: msg });
42
+ process.exit(1);
43
+ }
44
+ return;
45
+ }
46
+ // install
47
+ let version = '';
48
+ let config;
49
+ let packageUrl;
50
+ for (let i = 2; i < args.length; i++) {
51
+ const arg = args[i];
52
+ if ((arg === '--version' || arg.startsWith('--version=')) && !version) {
53
+ version = arg.includes('=') ? arg.split('=')[1] : args[++i];
54
+ continue;
55
+ }
56
+ if (arg === '--config' && args[i + 1]) {
57
+ try {
58
+ config = JSON.parse(args[++i]);
59
+ }
60
+ catch {
61
+ error('Invalid --config JSON');
62
+ emitter.end(false, 1, 'E_CONFIG_JSON');
63
+ process.exit(1);
64
+ }
65
+ continue;
66
+ }
67
+ if ((arg === '--config-file' || arg.startsWith('--config-file=')) && !config) {
68
+ const filePath = arg.includes('=') ? arg.split('=')[1] : args[++i];
69
+ try {
70
+ config = JSON.parse(readFileSync(filePath, 'utf8'));
71
+ }
72
+ catch (e) {
73
+ error(`Failed to read config file: ${e}`);
74
+ emitter.end(false, 1, 'E_CONFIG_FILE');
75
+ process.exit(1);
76
+ }
77
+ continue;
78
+ }
79
+ if ((arg === '--package-url' || arg.startsWith('--package-url=')) && !packageUrl) {
80
+ packageUrl = arg.includes('=') ? arg.split('=')[1] : args[++i];
81
+ continue;
82
+ }
83
+ }
84
+ if (!version) {
85
+ error('--version is required for install');
86
+ emitter.end(false, 1, 'E_VERSION_REQUIRED');
87
+ process.exit(1);
88
+ }
89
+ emitter.start(`installing skill ${skillName}@${version}`, { skillName, version });
90
+ info(`Installing skill ${skillName}@${version}...`);
91
+ try {
92
+ emitter.stepStart('validate', 'validating install args');
93
+ await installer.checkDeps();
94
+ emitter.stepDone('validate', 'args ok, deps ready');
95
+ emitter.stepStart('download', `downloading skill ${skillName}@${version}`);
96
+ await configureMirrors();
97
+ await installer.install(version, packageUrl);
98
+ emitter.stepDone('download', 'skill downloaded');
99
+ emitter.stepStart('install', `applying skill ${skillName}`);
100
+ if (config) {
101
+ await installer.configure(config);
102
+ }
103
+ emitter.stepDone('install', 'skill installed');
104
+ success(`Skill ${skillName}@${version} installed.`);
105
+ emitter.end(true, 0, undefined, { skillName, version });
106
+ }
107
+ catch (e) {
108
+ const msg = e instanceof Error ? e.message : String(e);
109
+ error(msg);
110
+ emitter.end(false, 1, 'E_SKILL_INSTALL_FAILED', { error: msg });
111
+ process.exit(1);
112
+ }
113
+ }
114
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function uninstallCommand(args: string[]): Promise<void>;
@@ -0,0 +1,46 @@
1
+ import { OpenclawInstaller } from '../installers/openclaw.js';
2
+ import { error, info, success } from '../utils/logger.js';
3
+ import { NdjsonEmitter, registerExitHandlers } from '../output/ndjson.js';
4
+ function getInstaller(component) {
5
+ switch (component) {
6
+ case 'openclaw': return new OpenclawInstaller();
7
+ default: return null;
8
+ }
9
+ }
10
+ export async function uninstallCommand(args) {
11
+ const emitter = new NdjsonEmitter('uninstall');
12
+ registerExitHandlers(emitter);
13
+ const component = args[0];
14
+ if (!component) {
15
+ error('Usage: okclaw uninstall <component>');
16
+ emitter.end(false, 1, 'E_USAGE');
17
+ process.exit(1);
18
+ }
19
+ const installer = getInstaller(component);
20
+ if (!installer) {
21
+ error(`Uninstall not supported for component: ${component}`);
22
+ emitter.end(false, 1, 'E_UNSUPPORTED');
23
+ process.exit(1);
24
+ }
25
+ if (!installer.uninstall) {
26
+ error(`Component ${component} does not support uninstall`);
27
+ emitter.end(false, 1, 'E_UNSUPPORTED');
28
+ process.exit(1);
29
+ }
30
+ emitter.start(`uninstalling ${component}`, { component });
31
+ info(`Uninstalling ${component}...`);
32
+ try {
33
+ emitter.stepStart('uninstall', `running uninstall for ${component}`);
34
+ await installer.uninstall();
35
+ emitter.stepDone('uninstall', `${component} uninstalled`);
36
+ success(`${component} uninstalled.`);
37
+ emitter.end(true, 0, undefined, { component });
38
+ }
39
+ catch (e) {
40
+ const msg = e instanceof Error ? e.message : String(e);
41
+ error(msg);
42
+ emitter.end(false, 1, 'E_UNINSTALL_FAILED', { error: msg });
43
+ process.exit(1);
44
+ }
45
+ }
46
+ //# sourceMappingURL=uninstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE1E,SAAS,YAAY,CAAC,SAAiB;IACrC,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,UAAU,CAAC,CAAC,OAAO,IAAI,iBAAiB,EAAE,CAAC;QAChD,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAc;IACnD,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;IAC/C,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,KAAK,CAAC,0CAA0C,SAAS,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;QACzB,KAAK,CAAC,aAAa,SAAS,6BAA6B,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1D,IAAI,CAAC,gBAAgB,SAAS,KAAK,CAAC,CAAC;IAErC,IAAI,CAAC;QACH,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,yBAAyB,SAAS,EAAE,CAAC,CAAC;QACrE,MAAM,SAAS,CAAC,SAAS,EAAE,CAAC;QAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,SAAS,cAAc,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,SAAS,eAAe,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/index.js CHANGED
@@ -1,21 +1,74 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { installCommand } from './commands/install.js';
3
+ import { uninstallCommand } from './commands/uninstall.js';
3
4
  import { checkCommand } from './commands/check.js';
4
5
  import { editCommand } from './commands/edit.js';
6
+ import { showCommand } from './commands/show.js';
5
7
  import { feedCommand } from './commands/feed.js';
6
8
  import { startCommand, stopCommand, restartCommand, statusCommand } from './commands/service.js';
9
+ import { skillCommand } from './commands/skill.js';
7
10
  import { ensureRoot } from './utils/shell.js';
8
11
  import { error } from './utils/logger.js';
9
- const [command, ...args] = process.argv.slice(2);
12
+ import { setNdjsonPath, setOutputMode, isNdjson } from './output/mode.js';
13
+ import { getActiveEmitter, NdjsonEmitter } from './output/ndjson.js';
14
+ /**
15
+ * 从 argv 里抽出全局 flag --output=<mode> 和 --op-id=<uuid>,返回剩余参数。
16
+ * 支持 "--flag=value" 与 "--flag value" 两种写法。
17
+ */
18
+ function extractGlobalFlags(argv) {
19
+ const rest = [];
20
+ let output = 'text';
21
+ let opId;
22
+ let ndjsonPath;
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const arg = argv[i];
25
+ if (arg === '--output' && argv[i + 1]) {
26
+ output = argv[++i] === 'ndjson' ? 'ndjson' : 'text';
27
+ continue;
28
+ }
29
+ if (arg.startsWith('--output=')) {
30
+ output = arg.slice('--output='.length) === 'ndjson' ? 'ndjson' : 'text';
31
+ continue;
32
+ }
33
+ if (arg === '--op-id' && argv[i + 1]) {
34
+ opId = argv[++i];
35
+ continue;
36
+ }
37
+ if (arg.startsWith('--op-id=')) {
38
+ opId = arg.slice('--op-id='.length);
39
+ continue;
40
+ }
41
+ if (arg === '--ndjson-path' && argv[i + 1]) {
42
+ ndjsonPath = argv[++i];
43
+ continue;
44
+ }
45
+ if (arg.startsWith('--ndjson-path=')) {
46
+ ndjsonPath = arg.slice('--ndjson-path='.length);
47
+ continue;
48
+ }
49
+ rest.push(arg);
50
+ }
51
+ return { rest, output, opId, ndjsonPath };
52
+ }
53
+ const { rest, output, opId, ndjsonPath } = extractGlobalFlags(process.argv.slice(2));
54
+ setOutputMode(output, opId);
55
+ setNdjsonPath(ndjsonPath);
56
+ const [command, ...args] = rest;
10
57
  async function main() {
11
58
  // All commands require root (or auto-sudo)
12
59
  if (command && command !== '--help' && command !== '-h' && command !== '--version' && command !== '-v') {
13
60
  ensureRoot();
14
61
  }
15
62
  switch (command) {
63
+ case 'skill':
64
+ await skillCommand(args);
65
+ break;
16
66
  case 'install':
17
67
  await installCommand(args);
18
68
  break;
69
+ case 'uninstall':
70
+ await uninstallCommand(args);
71
+ break;
19
72
  case 'check':
20
73
  await checkCommand();
21
74
  break;
@@ -34,6 +87,9 @@ async function main() {
34
87
  case 'edit':
35
88
  await editCommand(args);
36
89
  break;
90
+ case 'show':
91
+ await showCommand(args);
92
+ break;
37
93
  case 'feed':
38
94
  await feedCommand(args);
39
95
  break;
@@ -58,15 +114,24 @@ function printHelp() {
58
114
  console.log(`
59
115
  okclaw - OKClaw Deployment CLI
60
116
 
61
- Usage: okclaw <command> [args...]
117
+ Usage: okclaw [global-flags] <command> [args...]
118
+
119
+ Global flags (before the command):
120
+ --output text|ndjson Output mode (default: text)
121
+ --op-id <uuid> Operation id, echoed in every ndjson event's fields.opId
122
+ --ndjson-path <path> Append ndjson to file instead of stdout (used in detached mode)
62
123
 
124
+ okclaw skill install <name> --version <ver> [--package-url <url>] Install a skill
125
+ okclaw skill uninstall <name> Uninstall a skill
63
126
  okclaw install <component> --version <ver> [--config '<json>'] [--config-file <path>] [--package-url <url>]
127
+ okclaw uninstall <component> Uninstall a component (currently: openclaw)
64
128
  okclaw check Check & install system dependencies
65
129
  okclaw start Start openclaw gateway
66
130
  okclaw stop Stop openclaw gateway
67
131
  okclaw restart Restart openclaw gateway
68
132
  okclaw status Show gateway status
69
- okclaw edit <target> --file <path> Write config file (user/identity/soul/agents)
133
+ okclaw edit <target> --file <path> Write config file (user/identity/soul/agents/memory/tools/openclaw-json)
134
+ okclaw show <target...> Read config file content to stdout (batch requires --output=ndjson)
70
135
  okclaw feed --file <path> Feed file into knowledge base
71
136
 
72
137
  Components:
@@ -82,6 +147,9 @@ Examples:
82
147
  okclaw install openviking --version 0.2.15 --package-url /tmp/ov-plugin.tar.gz --config-file /root/okclaw/config/openviking.json
83
148
  okclaw install dingtalk --version 2.0.1 --config '{"clientId":"xxx","clientSecret":"xxx"}'
84
149
  okclaw install s3 --version 1.0.0 --package-url /tmp/channel-s3.tar.gz
150
+ okclaw uninstall openclaw
151
+ okclaw skill install my-skill --version 1.0.0 --package-url https://example.com/skill.zip
152
+ okclaw skill uninstall my-skill
85
153
  okclaw restart
86
154
  okclaw status
87
155
 
@@ -89,11 +157,26 @@ Notes:
89
157
  - All commands auto-elevate to root via sudo if needed
90
158
  - All paths are anchored to /root/ (forced HOME=/root)
91
159
  - npm uses npmmirror, pip uses tsinghua mirror (China acceleration)
92
- - Node.js >= 22.16 and Python >= 3.11 are auto-installed if missing
160
+ - Node.js >= 22.16 is auto-installed if missing
93
161
  `);
94
162
  }
95
163
  main().catch((err) => {
96
- error(String(err.message || err));
164
+ const msg = String(err?.message || err);
165
+ // bug#4 修:顶层 catch 兜底发 end,防止 os-api 永远等不到终态。
166
+ // 有活 emitter 就用它;没有(比如 extractGlobalFlags/ensureRoot 阶段崩)→ 直接写一行 fallback。
167
+ if (isNdjson()) {
168
+ const active = getActiveEmitter();
169
+ if (active && !active.hasEnded()) {
170
+ active.end(false, 1, 'E_TOPLEVEL', { error: msg });
171
+ }
172
+ else if (!active) {
173
+ // 没有任何 emitter 被注册过:手写一条 end 行
174
+ const fallback = new NdjsonEmitter('unknown');
175
+ fallback.start('top-level error');
176
+ fallback.end(false, 1, 'E_TOPLEVEL', { error: msg });
177
+ }
178
+ }
179
+ error(msg);
97
180
  process.exit(1);
98
181
  });
99
182
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEjD,KAAK,UAAU,IAAI;IACjB,2CAA2C;IAC3C,IAAI,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACvG,UAAU,EAAE,CAAC;IACf,CAAC;IAED,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,SAAS;YACZ,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM;QACR,KAAK,OAAO;YACV,MAAM,YAAY,EAAE,CAAC;YACrB,MAAM;QACR,KAAK,OAAO;YACV,MAAM,YAAY,EAAE,CAAC;YACrB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,cAAc,EAAE,CAAC;YACvB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,aAAa,EAAE,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,WAAW,CAAC;QACjB,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1F,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACzB,MAAM;QACR,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI,CAAC;QACV,KAAK,SAAS;YACZ,SAAS,EAAE,CAAC;YACZ,MAAM;QACR;YACE,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YACrC,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCb,CAAC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,5 @@ export interface Installer {
2
2
  checkDeps(): Promise<void>;
3
3
  install(version: string, packageUrl?: string): Promise<void>;
4
4
  configure(config: Record<string, unknown>): Promise<void>;
5
+ uninstall?(): Promise<void>;
5
6
  }
@@ -4,8 +4,17 @@ export declare class ChannelInstaller implements Installer {
4
4
  constructor(channelName: string);
5
5
  checkDeps(): Promise<void>;
6
6
  install(version: string, packageUrl?: string): Promise<void>;
7
+ private verifyInstalled;
7
8
  configure(config: Record<string, unknown>): Promise<void>;
8
- private removeExistingPlugin;
9
+ /**
10
+ * Clean up both filesystem state (extensions/<name>) and openclaw.json state
11
+ * (plugins.entries/installs/allow.<name> + channels.<name>) for this channel,
12
+ * atomically. Partial cleanup — e.g., rm-ing the dir but leaving the JSON refs —
13
+ * leaves openclaw's config validation broken and poisons all subsequent
14
+ * `openclaw ...` commands ("unknown channel id: <name>").
15
+ */
16
+ private cleanupStaleState;
17
+ private hasJsonRef;
9
18
  private installFromLocalPackage;
10
19
  /**
11
20
  * Download tgz from npm (npmmirror) first, then install locally.
@@ -13,5 +22,11 @@ export declare class ChannelInstaller implements Installer {
13
22
  */
14
23
  private installViaNpmPack;
15
24
  private addToPluginsAllow;
25
+ /**
26
+ * Push the absolute extension dir into plugins.load.paths so the gateway
27
+ * scans it on startup. Idempotent — dedup against trailing-slash variants
28
+ * (e.g. `/.../dingtalk` vs `/.../dingtalk/` both count as the same entry).
29
+ */
30
+ private addToLoadPaths;
16
31
  private applyConfig;
17
32
  }