@yoooclaw/cli 0.0.1
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 +80 -0
- package/dist/bin.cjs +494 -0
- package/dist/bin.cjs.map +18 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/command-tree.d.ts +30 -0
- package/dist/command-tree.d.ts.map +1 -0
- package/dist/context.d.ts +20 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/errors.d.ts +48 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.cjs +491 -0
- package/dist/index.cjs.map +17 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/output/format.d.ts +19 -0
- package/dist/output/format.d.ts.map +1 -0
- package/dist/paths.d.ts +25 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/program.d.ts +13 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +60 -0
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 命令树声明 —— Service-oriented,对齐 lark-cli 形态与本仓 PRD「命令树总览」。
|
|
3
|
+
*
|
|
4
|
+
* 这是命令树的**单一事实来源**:program.ts 据此构建 commander 程序。
|
|
5
|
+
* 脚手架阶段每个 action 走统一 notImplemented 占位,后续按 service 逐个落地真实逻辑。
|
|
6
|
+
*
|
|
7
|
+
* daemon 依赖标记(仅文档用途,体现在 summary 里):
|
|
8
|
+
* 🟢 不需要 daemon 🟡 需要 daemon 在跑 🔵 进程类(管理 daemon 自身)
|
|
9
|
+
*/
|
|
10
|
+
export interface SubcommandSpec {
|
|
11
|
+
/** 子命令名 + 位置参数,如 `show <id>`、`api <method> <path>` */
|
|
12
|
+
name: string;
|
|
13
|
+
summary: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ShortcutSpec {
|
|
16
|
+
/** 含 `+` 前缀的快捷命令名,如 `+today` */
|
|
17
|
+
name: string;
|
|
18
|
+
summary: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ServiceSpec {
|
|
21
|
+
name: string;
|
|
22
|
+
summary: string;
|
|
23
|
+
/** 子命令列表。leaf 命令(直接执行,无子命令)省略此项并提供 `args`。 */
|
|
24
|
+
subcommands?: SubcommandSpec[];
|
|
25
|
+
/** leaf 命令的位置参数,如 `[keyword]`、`<method> <path>`。 */
|
|
26
|
+
args?: string;
|
|
27
|
+
shortcuts?: ShortcutSpec[];
|
|
28
|
+
}
|
|
29
|
+
export declare const COMMAND_TREE: ServiceSpec[];
|
|
30
|
+
//# sourceMappingURL=command-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-tree.d.ts","sourceRoot":"","sources":["../src/command-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,EAAE,WAAW,EA0KrC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ProfilePaths } from "./paths.js";
|
|
2
|
+
import { type OutputFormat } from "./output/format.js";
|
|
3
|
+
export interface GlobalFlags {
|
|
4
|
+
profile?: string;
|
|
5
|
+
format?: string;
|
|
6
|
+
quiet?: boolean;
|
|
7
|
+
color?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface CliContext {
|
|
10
|
+
profile: string;
|
|
11
|
+
paths: ProfilePaths;
|
|
12
|
+
format: OutputFormat;
|
|
13
|
+
quiet: boolean;
|
|
14
|
+
color: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** 解析当前 active profile:--profile > $YOOOCLAW_PROFILE > active-profile 文件 > default。 */
|
|
17
|
+
export declare function resolveActiveProfile(flagProfile?: string): string;
|
|
18
|
+
/** 把全局 flags 物化成贯穿命令的 CliContext。 */
|
|
19
|
+
export declare function buildContext(flags: GlobalFlags): CliContext;
|
|
20
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED,qCAAqC;AACrC,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,CAU3D"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 结构化错误码 —— 进入半正式契约,命名前缀统一 `YOOOCLAW_*`。
|
|
3
|
+
* 命令失败时统一以 `{ ok: false, error: { code, message, ... } }` 输出(见 output/format.ts)。
|
|
4
|
+
*/
|
|
5
|
+
export declare const ErrorCode: {
|
|
6
|
+
/** 通用 / 未归类错误 */
|
|
7
|
+
readonly UNKNOWN: "YOOOCLAW_UNKNOWN";
|
|
8
|
+
/** 参数校验失败 */
|
|
9
|
+
readonly INVALID_ARGUMENT: "YOOOCLAW_INVALID_ARGUMENT";
|
|
10
|
+
/** 该命令尚未实现(脚手架阶段占位) */
|
|
11
|
+
readonly NOT_IMPLEMENTED: "YOOOCLAW_NOT_IMPLEMENTED";
|
|
12
|
+
/** daemon 未运行 */
|
|
13
|
+
readonly DAEMON_NOT_RUNNING: "YOOOCLAW_DAEMON_NOT_RUNNING";
|
|
14
|
+
/** daemon 已在运行(单例保护) */
|
|
15
|
+
readonly DAEMON_ALREADY_RUNNING: "YOOOCLAW_DAEMON_ALREADY_RUNNING";
|
|
16
|
+
/** 鉴权失败 / token 不一致 */
|
|
17
|
+
readonly UNAUTHORIZED: "YOOOCLAW_UNAUTHORIZED";
|
|
18
|
+
/** 配置缺失或非法 */
|
|
19
|
+
readonly CONFIG_INVALID: "YOOOCLAW_CONFIG_INVALID";
|
|
20
|
+
/** profile 不存在 */
|
|
21
|
+
readonly PROFILE_NOT_FOUND: "YOOOCLAW_PROFILE_NOT_FOUND";
|
|
22
|
+
/** 图片尚未下载完成 */
|
|
23
|
+
readonly IMAGE_NOT_READY: "YOOOCLAW_IMAGE_NOT_READY";
|
|
24
|
+
/** 资源未找到 */
|
|
25
|
+
readonly NOT_FOUND: "YOOOCLAW_NOT_FOUND";
|
|
26
|
+
};
|
|
27
|
+
export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
28
|
+
export interface YoooclawErrorDetails {
|
|
29
|
+
hint?: string;
|
|
30
|
+
checkedPaths?: string[];
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 携带结构化错误码的错误。CLI 顶层捕获后按 `--format` 序列化为统一错误 schema。
|
|
35
|
+
*/
|
|
36
|
+
export declare class YoooclawError extends Error {
|
|
37
|
+
readonly code: ErrorCodeValue;
|
|
38
|
+
readonly details: YoooclawErrorDetails;
|
|
39
|
+
/** 进程退出码,默认 1 */
|
|
40
|
+
readonly exitCode: number;
|
|
41
|
+
constructor(code: ErrorCodeValue, message: string, details?: YoooclawErrorDetails, exitCode?: number);
|
|
42
|
+
toErrorPayload(): {
|
|
43
|
+
code: ErrorCodeValue;
|
|
44
|
+
message: string;
|
|
45
|
+
} & YoooclawErrorDetails;
|
|
46
|
+
}
|
|
47
|
+
export declare function notImplemented(command: string): YoooclawError;
|
|
48
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,SAAS;IACpB,iBAAiB;;IAEjB,aAAa;;IAEb,uBAAuB;;IAEvB,iBAAiB;;IAEjB,wBAAwB;;IAExB,uBAAuB;;IAEvB,cAAc;;IAEd,kBAAkB;;IAElB,eAAe;;IAEf,YAAY;;CAEJ,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,iBAAiB;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,EAClC,QAAQ,SAAI;IASd,cAAc,IAAI;QAChB,IAAI,EAAE,cAAc,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,oBAAoB;CAGzB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAM7D"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
function __accessProp(key) {
|
|
7
|
+
return this[key];
|
|
8
|
+
}
|
|
9
|
+
var __toCommonJS = (from) => {
|
|
10
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
11
|
+
if (entry)
|
|
12
|
+
return entry;
|
|
13
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (var key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(entry, key))
|
|
17
|
+
__defProp(entry, key, {
|
|
18
|
+
get: __accessProp.bind(from, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
__moduleCache.set(from, entry);
|
|
23
|
+
return entry;
|
|
24
|
+
};
|
|
25
|
+
var __moduleCache;
|
|
26
|
+
var __returnValue = (v) => v;
|
|
27
|
+
function __exportSetter(name, newValue) {
|
|
28
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
29
|
+
}
|
|
30
|
+
var __export = (target, all) => {
|
|
31
|
+
for (var name in all)
|
|
32
|
+
__defProp(target, name, {
|
|
33
|
+
get: all[name],
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
set: __exportSetter.bind(all, name)
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/index.ts
|
|
41
|
+
var exports_src = {};
|
|
42
|
+
__export(exports_src, {
|
|
43
|
+
run: () => run,
|
|
44
|
+
resolveFormat: () => resolveFormat,
|
|
45
|
+
resolveActiveProfile: () => resolveActiveProfile,
|
|
46
|
+
renderResult: () => renderResult,
|
|
47
|
+
renderError: () => renderError,
|
|
48
|
+
paths: () => exports_paths,
|
|
49
|
+
buildProgram: () => buildProgram,
|
|
50
|
+
buildContext: () => buildContext,
|
|
51
|
+
YoooclawError: () => YoooclawError,
|
|
52
|
+
ErrorCode: () => ErrorCode,
|
|
53
|
+
COMMAND_TREE: () => COMMAND_TREE,
|
|
54
|
+
CLI_VERSION: () => CLI_VERSION
|
|
55
|
+
});
|
|
56
|
+
module.exports = __toCommonJS(exports_src);
|
|
57
|
+
|
|
58
|
+
// src/program.ts
|
|
59
|
+
var import_commander = require("commander");
|
|
60
|
+
|
|
61
|
+
// src/command-tree.ts
|
|
62
|
+
var COMMAND_TREE = [
|
|
63
|
+
{
|
|
64
|
+
name: "config",
|
|
65
|
+
summary: "配置管理 \uD83D\uDFE2",
|
|
66
|
+
subcommands: [
|
|
67
|
+
{ name: "init", summary: "交互式首次向导,生成 config + gateway token" },
|
|
68
|
+
{ name: "show", summary: "显示当前 profile 配置(敏感字段遮罩)" },
|
|
69
|
+
{ name: "set <key> <value>", summary: "设置单个配置项(点号路径)" },
|
|
70
|
+
{ name: "unset <key>", summary: "删除单个配置项" }
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "profile",
|
|
75
|
+
summary: "多 profile 管理 \uD83D\uDFE2",
|
|
76
|
+
subcommands: [
|
|
77
|
+
{ name: "list", summary: "列出所有 profile,标注 active" },
|
|
78
|
+
{ name: "use <name>", summary: "切换 active profile" },
|
|
79
|
+
{ name: "create <name>", summary: "新建 profile(走 config init 向导)" },
|
|
80
|
+
{ name: "delete <name>", summary: "删除 profile(非 active,需 --yes)" }
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "auth",
|
|
85
|
+
summary: "凭据与鉴权 \uD83D\uDFE2/\uD83D\uDFE1",
|
|
86
|
+
subcommands: [
|
|
87
|
+
{ name: "set-api-key <key>", summary: "写入 account 级 api-key 到共享凭据文件 \uD83D\uDFE2" },
|
|
88
|
+
{ name: "token rotate", summary: "生成新 gateway token 并热重载 \uD83D\uDFE1" },
|
|
89
|
+
{ name: "status", summary: "显示鉴权状态(本地检查,不调 daemon)\uD83D\uDFE2" },
|
|
90
|
+
{ name: "check", summary: "端到端鉴权体检(调 daemon /daemon/status)\uD83D\uDFE1" }
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "daemon",
|
|
95
|
+
summary: "守护进程管理 \uD83D\uDD35",
|
|
96
|
+
subcommands: [
|
|
97
|
+
{ name: "start", summary: "启动 daemon(默认后台 detach)" },
|
|
98
|
+
{ name: "stop", summary: "停止 daemon(SIGTERM → 10s → SIGKILL)" },
|
|
99
|
+
{ name: "restart", summary: "stop + start,保留原启动参数" },
|
|
100
|
+
{ name: "status", summary: "打印 daemon 状态(PID/端口/relay/规则数...)" },
|
|
101
|
+
{ name: "logs", summary: "跟踪 daemon 日志" }
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "notification",
|
|
106
|
+
summary: "通知查询 \uD83D\uDFE2",
|
|
107
|
+
subcommands: [
|
|
108
|
+
{ name: "search", summary: "按筛选条件查询通知,时间倒序" },
|
|
109
|
+
{ name: "summary", summary: "聚合统计 + 样例摘要,供 Agent 总结" },
|
|
110
|
+
{ name: "stats", summary: "按维度聚合统计" },
|
|
111
|
+
{ name: "storage-path", summary: "打印 notifications 目录绝对路径" }
|
|
112
|
+
],
|
|
113
|
+
shortcuts: [
|
|
114
|
+
{ name: "+today", summary: "今日通知摘要" },
|
|
115
|
+
{ name: "+recent", summary: "最近 1 小时通知" },
|
|
116
|
+
{ name: "+unread", summary: "(预留)未读通知" }
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "sync",
|
|
121
|
+
summary: "通知同步给记忆系统 \uD83D\uDFE2",
|
|
122
|
+
subcommands: [
|
|
123
|
+
{ name: "scan", summary: "扫描未处理通知,返回各日期待同步摘要" },
|
|
124
|
+
{ name: "fetch", summary: "获取指定日期未处理通知详情" },
|
|
125
|
+
{ name: "commit", summary: "标记指定日期当前批次处理完成" }
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "recording",
|
|
130
|
+
summary: "录音管理 \uD83D\uDFE2/\uD83D\uDFE1",
|
|
131
|
+
subcommands: [
|
|
132
|
+
{ name: "list", summary: "列出所有录音 \uD83D\uDFE2" },
|
|
133
|
+
{ name: "status <id>", summary: "查看单条录音详情 \uD83D\uDFE2" },
|
|
134
|
+
{ name: "storage-path", summary: "打印录音存储目录绝对路径 \uD83D\uDFE2" },
|
|
135
|
+
{ name: "setup-asr", summary: "交互式配置 ASR 转写参数 \uD83D\uDFE2" }
|
|
136
|
+
],
|
|
137
|
+
shortcuts: [{ name: "+latest", summary: "展示最新一条录音详情" }]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "image",
|
|
141
|
+
summary: "图片管理 \uD83D\uDFE2",
|
|
142
|
+
subcommands: [
|
|
143
|
+
{ name: "list", summary: "列出所有图片" },
|
|
144
|
+
{ name: "status <id>", summary: "查看单张图片详情" },
|
|
145
|
+
{ name: "path <id>", summary: "打印图片本地文件绝对路径" },
|
|
146
|
+
{ name: "storage-path", summary: "打印图片存储目录绝对路径" }
|
|
147
|
+
],
|
|
148
|
+
shortcuts: [{ name: "+latest", summary: "展示最新一张图片详情" }]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "light",
|
|
152
|
+
summary: "灯效硬件控制 \uD83D\uDFE1",
|
|
153
|
+
subcommands: [
|
|
154
|
+
{ name: "send", summary: "发送灯效指令到硬件(--segments / --preset)" }
|
|
155
|
+
],
|
|
156
|
+
shortcuts: [{ name: "+blink", summary: "灯效连通性测试" }]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "lightrule",
|
|
160
|
+
summary: "灯效规则管理 \uD83D\uDFE1",
|
|
161
|
+
subcommands: [
|
|
162
|
+
{ name: "list", summary: "列出所有规则及状态" },
|
|
163
|
+
{ name: "show <id>", summary: "查看单条规则详情" },
|
|
164
|
+
{ name: "create", summary: "创建规则(--from-file / --intent ...)" },
|
|
165
|
+
{ name: "update <id>", summary: "更新现有规则" },
|
|
166
|
+
{ name: "delete <id>", summary: "删除规则(--yes)" },
|
|
167
|
+
{ name: "enable <id>", summary: "启用单条规则" },
|
|
168
|
+
{ name: "disable <id>", summary: "停用单条规则" }
|
|
169
|
+
],
|
|
170
|
+
shortcuts: [
|
|
171
|
+
{ name: "+on", summary: "启用所有规则" },
|
|
172
|
+
{ name: "+off", summary: "停用所有规则(保留定义)" }
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "monitor",
|
|
177
|
+
summary: "定时通知监控任务 \uD83D\uDFE1",
|
|
178
|
+
subcommands: [
|
|
179
|
+
{ name: "list", summary: "列出所有监控任务" },
|
|
180
|
+
{ name: "show <name>", summary: "查看监控任务详情" },
|
|
181
|
+
{ name: "create <name>", summary: "创建监控任务(cron 驱动)" },
|
|
182
|
+
{ name: "delete <name>", summary: "删除监控任务(--yes)" },
|
|
183
|
+
{ name: "enable <name>", summary: "启用监控任务" },
|
|
184
|
+
{ name: "disable <name>", summary: "暂停监控任务" }
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "tunnel",
|
|
189
|
+
summary: "Relay 隧道 \uD83D\uDFE1",
|
|
190
|
+
subcommands: [
|
|
191
|
+
{ name: "status", summary: "查询 Relay 连接状态" },
|
|
192
|
+
{ name: "reconnect", summary: "强制重连" }
|
|
193
|
+
],
|
|
194
|
+
shortcuts: [{ name: "+test", summary: "端到端联通性自检(echo 回环)" }]
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "log",
|
|
198
|
+
summary: "日志检索 \uD83D\uDFE2",
|
|
199
|
+
args: "[keyword]",
|
|
200
|
+
shortcuts: [{ name: "+errors", summary: "昨天起的 error 级日志" }]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: "gateway",
|
|
204
|
+
summary: "协议自检 \uD83D\uDFE2/\uD83D\uDFE1",
|
|
205
|
+
subcommands: [
|
|
206
|
+
{ name: "test", summary: "模拟手机端调 daemon /notifications,验证连通/鉴权/relay \uD83D\uDFE1" }
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: "api",
|
|
211
|
+
summary: "Raw HTTP escape hatch \uD83D\uDFE1",
|
|
212
|
+
args: "<method> <path>"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "migrate",
|
|
216
|
+
summary: "从 openclaw 插件迁移数据 \uD83D\uDFE2",
|
|
217
|
+
subcommands: [
|
|
218
|
+
{ name: "from-openclaw", summary: "迁移 notifications/recordings/规则/api-key 到 ~/.yoooclaw" }
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: "update",
|
|
223
|
+
summary: "版本检查 \uD83D\uDFE2",
|
|
224
|
+
subcommands: [
|
|
225
|
+
{ name: "self", summary: "检查 npm 最新版本并提示(不自动更新)" }
|
|
226
|
+
]
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
name: "doctor",
|
|
230
|
+
summary: "环境自检:Node/目录/keychain/daemon/relay \uD83D\uDFE2/\uD83D\uDFE1"
|
|
231
|
+
}
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
// src/context.ts
|
|
235
|
+
var import_node_fs = require("node:fs");
|
|
236
|
+
|
|
237
|
+
// src/paths.ts
|
|
238
|
+
var exports_paths = {};
|
|
239
|
+
__export(exports_paths, {
|
|
240
|
+
sharedCredentialsPath: () => sharedCredentialsPath,
|
|
241
|
+
rootDir: () => rootDir,
|
|
242
|
+
profilePaths: () => profilePaths,
|
|
243
|
+
profileDir: () => profileDir,
|
|
244
|
+
activeProfilePath: () => activeProfilePath,
|
|
245
|
+
DEFAULT_PROFILE: () => DEFAULT_PROFILE
|
|
246
|
+
});
|
|
247
|
+
var import_node_os = require("node:os");
|
|
248
|
+
var import_node_path = require("node:path");
|
|
249
|
+
var DEFAULT_PROFILE = "default";
|
|
250
|
+
function rootDir() {
|
|
251
|
+
return process.env.YOOOCLAW_HOME?.trim() || import_node_path.join(import_node_os.homedir(), ".yoooclaw");
|
|
252
|
+
}
|
|
253
|
+
function sharedCredentialsPath() {
|
|
254
|
+
return import_node_path.join(rootDir(), "credentials.json");
|
|
255
|
+
}
|
|
256
|
+
function activeProfilePath() {
|
|
257
|
+
return import_node_path.join(rootDir(), "active-profile");
|
|
258
|
+
}
|
|
259
|
+
function profileDir(profile) {
|
|
260
|
+
return import_node_path.join(rootDir(), "profiles", profile);
|
|
261
|
+
}
|
|
262
|
+
function profilePaths(profile) {
|
|
263
|
+
const dir = profileDir(profile);
|
|
264
|
+
return {
|
|
265
|
+
profile,
|
|
266
|
+
dir,
|
|
267
|
+
config: import_node_path.join(dir, "config.json"),
|
|
268
|
+
credentials: import_node_path.join(dir, "credentials.json"),
|
|
269
|
+
daemonLock: import_node_path.join(dir, "daemon.lock"),
|
|
270
|
+
daemonLog: import_node_path.join(dir, "daemon.log"),
|
|
271
|
+
notifications: import_node_path.join(dir, "notifications"),
|
|
272
|
+
recordings: import_node_path.join(dir, "recordings"),
|
|
273
|
+
images: import_node_path.join(dir, "images"),
|
|
274
|
+
lightRules: import_node_path.join(dir, "light-rules"),
|
|
275
|
+
state: import_node_path.join(dir, "state")
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// src/errors.ts
|
|
280
|
+
var ErrorCode = {
|
|
281
|
+
UNKNOWN: "YOOOCLAW_UNKNOWN",
|
|
282
|
+
INVALID_ARGUMENT: "YOOOCLAW_INVALID_ARGUMENT",
|
|
283
|
+
NOT_IMPLEMENTED: "YOOOCLAW_NOT_IMPLEMENTED",
|
|
284
|
+
DAEMON_NOT_RUNNING: "YOOOCLAW_DAEMON_NOT_RUNNING",
|
|
285
|
+
DAEMON_ALREADY_RUNNING: "YOOOCLAW_DAEMON_ALREADY_RUNNING",
|
|
286
|
+
UNAUTHORIZED: "YOOOCLAW_UNAUTHORIZED",
|
|
287
|
+
CONFIG_INVALID: "YOOOCLAW_CONFIG_INVALID",
|
|
288
|
+
PROFILE_NOT_FOUND: "YOOOCLAW_PROFILE_NOT_FOUND",
|
|
289
|
+
IMAGE_NOT_READY: "YOOOCLAW_IMAGE_NOT_READY",
|
|
290
|
+
NOT_FOUND: "YOOOCLAW_NOT_FOUND"
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
class YoooclawError extends Error {
|
|
294
|
+
code;
|
|
295
|
+
details;
|
|
296
|
+
exitCode;
|
|
297
|
+
constructor(code, message, details = {}, exitCode = 1) {
|
|
298
|
+
super(message);
|
|
299
|
+
this.name = "YoooclawError";
|
|
300
|
+
this.code = code;
|
|
301
|
+
this.details = details;
|
|
302
|
+
this.exitCode = exitCode;
|
|
303
|
+
}
|
|
304
|
+
toErrorPayload() {
|
|
305
|
+
return { code: this.code, message: this.message, ...this.details };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function notImplemented(command) {
|
|
309
|
+
return new YoooclawError(ErrorCode.NOT_IMPLEMENTED, `命令 \`${command}\` 尚未实现`, { hint: "该命令处于脚手架阶段,后续按 imp 文档逐步落地" });
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/output/format.ts
|
|
313
|
+
var OUTPUT_FORMATS = [
|
|
314
|
+
"json",
|
|
315
|
+
"pretty",
|
|
316
|
+
"table",
|
|
317
|
+
"ndjson"
|
|
318
|
+
];
|
|
319
|
+
function resolveFormat(requested, isTty = process.stdout.isTTY ?? false) {
|
|
320
|
+
if (requested && requested !== "auto") {
|
|
321
|
+
if (OUTPUT_FORMATS.includes(requested)) {
|
|
322
|
+
return requested;
|
|
323
|
+
}
|
|
324
|
+
throw new YoooclawError("YOOOCLAW_INVALID_ARGUMENT", `不支持的输出格式:${requested}`, { hint: `可选值:${OUTPUT_FORMATS.join(" | ")} | auto` });
|
|
325
|
+
}
|
|
326
|
+
return isTty ? "pretty" : "json";
|
|
327
|
+
}
|
|
328
|
+
function write(stream, text) {
|
|
329
|
+
stream.write(text.endsWith(`
|
|
330
|
+
`) ? text : text + `
|
|
331
|
+
`);
|
|
332
|
+
}
|
|
333
|
+
function renderResult(data, opts) {
|
|
334
|
+
const stream = opts.stream ?? process.stdout;
|
|
335
|
+
switch (opts.format) {
|
|
336
|
+
case "json":
|
|
337
|
+
write(stream, JSON.stringify(data));
|
|
338
|
+
return;
|
|
339
|
+
case "pretty":
|
|
340
|
+
write(stream, JSON.stringify(data, null, 2));
|
|
341
|
+
return;
|
|
342
|
+
case "ndjson": {
|
|
343
|
+
const rows = Array.isArray(data) ? data : [data];
|
|
344
|
+
for (const row of rows)
|
|
345
|
+
stream.write(JSON.stringify(row) + `
|
|
346
|
+
`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
case "table":
|
|
350
|
+
write(stream, renderTable(data));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function renderError(err, opts) {
|
|
355
|
+
const stream = opts.stream ?? process.stdout;
|
|
356
|
+
const error = err instanceof YoooclawError ? err.toErrorPayload() : {
|
|
357
|
+
code: "YOOOCLAW_UNKNOWN",
|
|
358
|
+
message: err instanceof Error ? err.message : String(err)
|
|
359
|
+
};
|
|
360
|
+
const payload = { ok: false, error };
|
|
361
|
+
const text = opts.format === "pretty" ? JSON.stringify(payload, null, 2) : JSON.stringify(payload);
|
|
362
|
+
write(stream, text);
|
|
363
|
+
}
|
|
364
|
+
function renderTable(data) {
|
|
365
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
366
|
+
return JSON.stringify(data, null, 2);
|
|
367
|
+
}
|
|
368
|
+
const rows = data.filter((r) => typeof r === "object" && r !== null && !Array.isArray(r));
|
|
369
|
+
if (rows.length !== data.length) {
|
|
370
|
+
return JSON.stringify(data, null, 2);
|
|
371
|
+
}
|
|
372
|
+
const columns = Array.from(rows.reduce((set, row) => {
|
|
373
|
+
for (const key of Object.keys(row))
|
|
374
|
+
set.add(key);
|
|
375
|
+
return set;
|
|
376
|
+
}, new Set));
|
|
377
|
+
const cell = (v) => v === null || v === undefined ? "" : typeof v === "object" ? JSON.stringify(v) : String(v);
|
|
378
|
+
const widths = columns.map((col) => Math.max(col.length, ...rows.map((row) => cell(row[col]).length)));
|
|
379
|
+
const pad = (text, width) => text.padEnd(width);
|
|
380
|
+
const header = columns.map((col, i) => pad(col, widths[i])).join(" ");
|
|
381
|
+
const divider = widths.map((w) => "-".repeat(w)).join(" ");
|
|
382
|
+
const body = rows.map((row) => columns.map((col, i) => pad(cell(row[col]), widths[i])).join(" ")).join(`
|
|
383
|
+
`);
|
|
384
|
+
return [header, divider, body].join(`
|
|
385
|
+
`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/context.ts
|
|
389
|
+
function resolveActiveProfile(flagProfile) {
|
|
390
|
+
if (flagProfile?.trim())
|
|
391
|
+
return flagProfile.trim();
|
|
392
|
+
const envProfile = process.env.YOOOCLAW_PROFILE?.trim();
|
|
393
|
+
if (envProfile)
|
|
394
|
+
return envProfile;
|
|
395
|
+
const file = activeProfilePath();
|
|
396
|
+
if (import_node_fs.existsSync(file)) {
|
|
397
|
+
const name = import_node_fs.readFileSync(file, "utf-8").trim();
|
|
398
|
+
if (name)
|
|
399
|
+
return name;
|
|
400
|
+
}
|
|
401
|
+
return DEFAULT_PROFILE;
|
|
402
|
+
}
|
|
403
|
+
function buildContext(flags) {
|
|
404
|
+
const profile = resolveActiveProfile(flags.profile);
|
|
405
|
+
return {
|
|
406
|
+
profile,
|
|
407
|
+
paths: profilePaths(profile),
|
|
408
|
+
format: resolveFormat(flags.format),
|
|
409
|
+
quiet: flags.quiet ?? false,
|
|
410
|
+
color: flags.color ?? true
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/version.ts
|
|
415
|
+
var import_node_fs2 = require("node:fs");
|
|
416
|
+
function readBuildInjectedVersion() {
|
|
417
|
+
if (false) {}
|
|
418
|
+
const version = "0.0.1".trim();
|
|
419
|
+
return version || undefined;
|
|
420
|
+
}
|
|
421
|
+
function readVersionFromPackageJson() {
|
|
422
|
+
try {
|
|
423
|
+
const packageJsonUrl = new URL("../package.json", "file:///Users/cobb/github/openclaw-plugin/packages/cli/src/version.ts");
|
|
424
|
+
const packageJson = JSON.parse(import_node_fs2.readFileSync(packageJsonUrl, "utf-8"));
|
|
425
|
+
const version = packageJson.version?.trim();
|
|
426
|
+
return version || undefined;
|
|
427
|
+
} catch {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
var CLI_VERSION = readBuildInjectedVersion() ?? readVersionFromPackageJson() ?? "unknown";
|
|
432
|
+
|
|
433
|
+
// src/program.ts
|
|
434
|
+
function wrapAction(handler) {
|
|
435
|
+
return async (...rawArgs) => {
|
|
436
|
+
const command = rawArgs.at(-1);
|
|
437
|
+
const opts = rawArgs.at(-2);
|
|
438
|
+
const positionals = rawArgs.slice(0, -2);
|
|
439
|
+
const globals = command.optsWithGlobals();
|
|
440
|
+
let ctx;
|
|
441
|
+
try {
|
|
442
|
+
ctx = buildContext(globals);
|
|
443
|
+
const result = await handler(ctx, positionals, opts);
|
|
444
|
+
renderResult(result, { format: ctx.format });
|
|
445
|
+
} catch (err) {
|
|
446
|
+
const format = ctx?.format ?? "json";
|
|
447
|
+
renderError(err, { format });
|
|
448
|
+
process.exitCode = err instanceof YoooclawError ? err.exitCode : 1;
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function stubHandler(commandPath) {
|
|
453
|
+
return () => {
|
|
454
|
+
throw notImplemented(commandPath);
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function attachService(program, spec) {
|
|
458
|
+
const service = program.command(spec.name).description(spec.summary);
|
|
459
|
+
if (!spec.subcommands || spec.subcommands.length === 0) {
|
|
460
|
+
if (spec.args) {
|
|
461
|
+
service.arguments(spec.args);
|
|
462
|
+
}
|
|
463
|
+
service.action(wrapAction(stubHandler(spec.name)));
|
|
464
|
+
} else {
|
|
465
|
+
for (const sub of spec.subcommands) {
|
|
466
|
+
const path = `${spec.name} ${sub.name}`;
|
|
467
|
+
service.command(sub.name).description(sub.summary).action(wrapAction(stubHandler(path)));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
for (const shortcut of spec.shortcuts ?? []) {
|
|
471
|
+
const path = `${spec.name} ${shortcut.name}`;
|
|
472
|
+
service.command(shortcut.name).description(shortcut.summary).action(wrapAction(stubHandler(path)));
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function buildProgram() {
|
|
476
|
+
const program = new import_commander.Command;
|
|
477
|
+
program.name("yoooclaw").description("yoooclaw —— 独立守护进程 + CLI:接收手机通知、Relay 隧道、灯效规则评估(Agent-Native)").version(CLI_VERSION, "-v, --version", "显示 CLI 版本号").option("--profile <name>", "切换 profile(默认 default)").option("--format <format>", "输出格式:json|pretty|table|ndjson(TTY 默认 pretty,管道默认 json)").option("--quiet", "抑制进度日志,只输出最终结果").option("--no-color", "关闭终端颜色").showHelpAfterError();
|
|
478
|
+
for (const spec of COMMAND_TREE) {
|
|
479
|
+
attachService(program, spec);
|
|
480
|
+
}
|
|
481
|
+
return program;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// src/index.ts
|
|
485
|
+
async function run(argv = process.argv) {
|
|
486
|
+
const program = buildProgram();
|
|
487
|
+
await program.parseAsync(argv);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
//# debugId=27C0FB5737ECE95F64756E2164756E21
|
|
491
|
+
//# sourceMappingURL=index.cjs.map
|