@yoooclaw/cli 0.0.1 → 0.0.2

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/dist/bin.cjs.map CHANGED
@@ -1,18 +1,63 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/program.ts", "../src/command-tree.ts", "../src/context.ts", "../src/paths.ts", "../src/errors.ts", "../src/output/format.ts", "../src/version.ts", "../src/index.ts", "../src/bin.ts"],
3
+ "sources": ["../src/program.ts", "../src/command-tree.ts", "../src/context.ts", "../src/paths.ts", "../src/errors.ts", "../src/output/format.ts", "../src/version.ts", "../src/fs-utils.ts", "../src/prompt.ts", "../src/config/store.ts", "../src/config/schema.ts", "../src/credentials/store.ts", "../src/credentials/keychain.ts", "../src/credentials/refs.ts", "../src/commands/config.ts", "../src/commands/profile.ts", "../src/daemon/lock.ts", "../src/daemon/client.ts", "../src/commands/auth.ts", "../src/notification/query.ts", "../../phone-notifications/src/cli/helpers.ts", "../../phone-notifications/src/cli/ntf-query.ts", "../../phone-notifications/src/notification/storage.ts", "../../phone-notifications/src/notification/feishu-normalize.ts", "../../phone-notifications/src/plugin/notifications.ts", "../../phone-notifications/src/tunnel/http-proxy.ts", "../../phone-notifications/src/plugin/shared.ts", "../../phone-notifications/src/light-rules/storage.ts", "../../phone-notifications/src/light/repeat.ts", "../../phone-notifications/src/light-rules/registry.ts", "../../phone-notifications/src/light/validators.ts", "../../phone-notifications/src/light-rules/names.ts", "../../phone-notifications/src/light-rules/gateway.ts", "../src/commands/notification.ts", "../src/notification/sync.ts", "../src/commands/sync.ts", "../src/commands/recording.ts", "../src/image/storage.ts", "../src/commands/image.ts", "../src/log/reader.ts", "../src/commands/log.ts", "../src/commands/migrate.ts", "../src/commands/update.ts", "../src/commands/doctor.ts", "../src/commands/daemon.ts", "../src/daemon/main.ts", "../src/daemon/logger.ts", "../src/daemon/runtime.ts", "../src/image/channel.ts", "../src/monitor/store.ts", "../src/commands/daemon-services.ts", "../src/commands/registry.ts", "../src/index.ts", "../src/bin.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * 构建 yoooclaw 的 commander 程序。\n *\n * 命令树来自 command-tree.ts(单一事实来源)。脚手架阶段所有 action 走 notImplemented\n * 占位,但已贯通全局 flags、CliContext 解析与统一输出/错误层 —— 后续替换 action 体即可。\n */\nimport { Command } from \"commander\";\nimport { COMMAND_TREE, type ServiceSpec } from \"./command-tree.js\";\nimport { buildContext, type CliContext, type GlobalFlags } from \"./context.js\";\nimport { renderError, renderResult } from \"./output/format.js\";\nimport { YoooclawError, notImplemented } from \"./errors.js\";\nimport { CLI_VERSION } from \"./version.js\";\n\n/** 命令处理器签名:拿到上下文 + commander 解析后的参数/选项,返回可序列化结果。 */\nexport type CommandHandler = (\n ctx: CliContext,\n args: unknown[],\n opts: Record<string, unknown>,\n) => unknown;\n\n/** 把 handler 包成 commander action:解析 ctx → 执行 → 统一渲染结果 / 错误。 */\nfunction wrapAction(handler: CommandHandler) {\n return async (...rawArgs: unknown[]): Promise<void> => {\n // commander 传参:[...positional, options, command]\n const command = rawArgs.at(-1) as Command;\n const opts = rawArgs.at(-2) as Record<string, unknown>;\n const positionals = rawArgs.slice(0, -2);\n const globals = command.optsWithGlobals() as GlobalFlags;\n\n let ctx: CliContext | undefined;\n try {\n ctx = buildContext(globals);\n const result = await handler(ctx, positionals, opts);\n renderResult(result, { format: ctx.format });\n } catch (err) {\n const format = ctx?.format ?? \"json\";\n renderError(err, { format });\n process.exitCode = err instanceof YoooclawError ? err.exitCode : 1;\n }\n };\n}\n\n/** 脚手架阶段的占位 handler */\nfunction stubHandler(commandPath: string): CommandHandler {\n return () => {\n throw notImplemented(commandPath);\n };\n}\n\nfunction attachService(program: Command, spec: ServiceSpec): void {\n const service = program.command(spec.name).description(spec.summary);\n\n // leaf 命令:直接挂 action(如 `yoooclaw doctor` / `yoooclaw api <method> <path>`)\n if (!spec.subcommands || spec.subcommands.length === 0) {\n if (spec.args) {\n // commander 的位置参数声明随命令名给出\n service.arguments(spec.args);\n }\n service.action(wrapAction(stubHandler(spec.name)));\n } else {\n for (const sub of spec.subcommands) {\n const path = `${spec.name} ${sub.name}`;\n service\n .command(sub.name)\n .description(sub.summary)\n .action(wrapAction(stubHandler(path)));\n }\n }\n\n // shortcuts(`+` 前缀)作为该 service 下的子命令注册\n for (const shortcut of spec.shortcuts ?? []) {\n const path = `${spec.name} ${shortcut.name}`;\n service\n .command(shortcut.name)\n .description(shortcut.summary)\n .action(wrapAction(stubHandler(path)));\n }\n}\n\n/** 构建并返回顶层 commander 程序。 */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"yoooclaw\")\n .description(\n \"yoooclaw —— 独立守护进程 + CLI:接收手机通知、Relay 隧道、灯效规则评估(Agent-Native)\",\n )\n .version(CLI_VERSION, \"-v, --version\", \"显示 CLI 版本号\")\n // 全局 flags(对所有命令生效)\n .option(\"--profile <name>\", \"切换 profile(默认 default)\")\n .option(\n \"--format <format>\",\n \"输出格式:json|pretty|table|ndjson(TTY 默认 pretty,管道默认 json)\",\n )\n .option(\"--quiet\", \"抑制进度日志,只输出最终结果\")\n .option(\"--no-color\", \"关闭终端颜色\")\n // 顶层无子命令时打印帮助\n .showHelpAfterError();\n\n for (const spec of COMMAND_TREE) {\n attachService(program, spec);\n }\n\n return program;\n}\n",
6
- "/**\n * 命令树声明 —— Service-oriented,对齐 lark-cli 形态与本仓 PRD「命令树总览」。\n *\n * 这是命令树的**单一事实来源**:program.ts 据此构建 commander 程序。\n * 脚手架阶段每个 action 走统一 notImplemented 占位,后续按 service 逐个落地真实逻辑。\n *\n * daemon 依赖标记(仅文档用途,体现在 summary 里):\n * 🟢 不需要 daemon 🟡 需要 daemon 在跑 🔵 进程类(管理 daemon 自身)\n */\n\nexport interface SubcommandSpec {\n /** 子命令名 + 位置参数,如 `show <id>`、`api <method> <path>` */\n name: string;\n summary: string;\n}\n\nexport interface ShortcutSpec {\n /** 含 `+` 前缀的快捷命令名,如 `+today` */\n name: string;\n summary: string;\n}\n\nexport interface ServiceSpec {\n name: string;\n summary: string;\n /** 子命令列表。leaf 命令(直接执行,无子命令)省略此项并提供 `args`。 */\n subcommands?: SubcommandSpec[];\n /** leaf 命令的位置参数,如 `[keyword]`、`<method> <path>`。 */\n args?: string;\n shortcuts?: ShortcutSpec[];\n}\n\nexport const COMMAND_TREE: ServiceSpec[] = [\n {\n name: \"config\",\n summary: \"配置管理 🟢\",\n subcommands: [\n { name: \"init\", summary: \"交互式首次向导,生成 config + gateway token\" },\n { name: \"show\", summary: \"显示当前 profile 配置(敏感字段遮罩)\" },\n { name: \"set <key> <value>\", summary: \"设置单个配置项(点号路径)\" },\n { name: \"unset <key>\", summary: \"删除单个配置项\" },\n ],\n },\n {\n name: \"profile\",\n summary: \"多 profile 管理 🟢\",\n subcommands: [\n { name: \"list\", summary: \"列出所有 profile,标注 active\" },\n { name: \"use <name>\", summary: \"切换 active profile\" },\n { name: \"create <name>\", summary: \"新建 profile(走 config init 向导)\" },\n { name: \"delete <name>\", summary: \"删除 profile(非 active,需 --yes)\" },\n ],\n },\n {\n name: \"auth\",\n summary: \"凭据与鉴权 🟢/🟡\",\n subcommands: [\n { name: \"set-api-key <key>\", summary: \"写入 account 级 api-key 到共享凭据文件 🟢\" },\n { name: \"token rotate\", summary: \"生成新 gateway token 并热重载 🟡\" },\n { name: \"status\", summary: \"显示鉴权状态(本地检查,不调 daemon)🟢\" },\n { name: \"check\", summary: \"端到端鉴权体检(调 daemon /daemon/status)🟡\" },\n ],\n },\n {\n name: \"daemon\",\n summary: \"守护进程管理 🔵\",\n subcommands: [\n { name: \"start\", summary: \"启动 daemon(默认后台 detach)\" },\n { name: \"stop\", summary: \"停止 daemon(SIGTERM → 10s → SIGKILL)\" },\n { name: \"restart\", summary: \"stop + start,保留原启动参数\" },\n { name: \"status\", summary: \"打印 daemon 状态(PID/端口/relay/规则数...)\" },\n { name: \"logs\", summary: \"跟踪 daemon 日志\" },\n ],\n },\n {\n name: \"notification\",\n summary: \"通知查询 🟢\",\n subcommands: [\n { name: \"search\", summary: \"按筛选条件查询通知,时间倒序\" },\n { name: \"summary\", summary: \"聚合统计 + 样例摘要,供 Agent 总结\" },\n { name: \"stats\", summary: \"按维度聚合统计\" },\n { name: \"storage-path\", summary: \"打印 notifications 目录绝对路径\" },\n ],\n shortcuts: [\n { name: \"+today\", summary: \"今日通知摘要\" },\n { name: \"+recent\", summary: \"最近 1 小时通知\" },\n { name: \"+unread\", summary: \"(预留)未读通知\" },\n ],\n },\n {\n name: \"sync\",\n summary: \"通知同步给记忆系统 🟢\",\n subcommands: [\n { name: \"scan\", summary: \"扫描未处理通知,返回各日期待同步摘要\" },\n { name: \"fetch\", summary: \"获取指定日期未处理通知详情\" },\n { name: \"commit\", summary: \"标记指定日期当前批次处理完成\" },\n ],\n },\n {\n name: \"recording\",\n summary: \"录音管理 🟢/🟡\",\n subcommands: [\n { name: \"list\", summary: \"列出所有录音 🟢\" },\n { name: \"status <id>\", summary: \"查看单条录音详情 🟢\" },\n { name: \"storage-path\", summary: \"打印录音存储目录绝对路径 🟢\" },\n { name: \"setup-asr\", summary: \"交互式配置 ASR 转写参数 🟢\" },\n ],\n shortcuts: [{ name: \"+latest\", summary: \"展示最新一条录音详情\" }],\n },\n {\n name: \"image\",\n summary: \"图片管理 🟢\",\n subcommands: [\n { name: \"list\", summary: \"列出所有图片\" },\n { name: \"status <id>\", summary: \"查看单张图片详情\" },\n { name: \"path <id>\", summary: \"打印图片本地文件绝对路径\" },\n { name: \"storage-path\", summary: \"打印图片存储目录绝对路径\" },\n ],\n shortcuts: [{ name: \"+latest\", summary: \"展示最新一张图片详情\" }],\n },\n {\n name: \"light\",\n summary: \"灯效硬件控制 🟡\",\n subcommands: [\n { name: \"send\", summary: \"发送灯效指令到硬件(--segments / --preset)\" },\n ],\n shortcuts: [{ name: \"+blink\", summary: \"灯效连通性测试\" }],\n },\n {\n name: \"lightrule\",\n summary: \"灯效规则管理 🟡\",\n subcommands: [\n { name: \"list\", summary: \"列出所有规则及状态\" },\n { name: \"show <id>\", summary: \"查看单条规则详情\" },\n { name: \"create\", summary: \"创建规则(--from-file / --intent ...)\" },\n { name: \"update <id>\", summary: \"更新现有规则\" },\n { name: \"delete <id>\", summary: \"删除规则(--yes)\" },\n { name: \"enable <id>\", summary: \"启用单条规则\" },\n { name: \"disable <id>\", summary: \"停用单条规则\" },\n ],\n shortcuts: [\n { name: \"+on\", summary: \"启用所有规则\" },\n { name: \"+off\", summary: \"停用所有规则(保留定义)\" },\n ],\n },\n {\n name: \"monitor\",\n summary: \"定时通知监控任务 🟡\",\n subcommands: [\n { name: \"list\", summary: \"列出所有监控任务\" },\n { name: \"show <name>\", summary: \"查看监控任务详情\" },\n { name: \"create <name>\", summary: \"创建监控任务(cron 驱动)\" },\n { name: \"delete <name>\", summary: \"删除监控任务(--yes)\" },\n { name: \"enable <name>\", summary: \"启用监控任务\" },\n { name: \"disable <name>\", summary: \"暂停监控任务\" },\n ],\n },\n {\n name: \"tunnel\",\n summary: \"Relay 隧道 🟡\",\n subcommands: [\n { name: \"status\", summary: \"查询 Relay 连接状态\" },\n { name: \"reconnect\", summary: \"强制重连\" },\n ],\n shortcuts: [{ name: \"+test\", summary: \"端到端联通性自检(echo 回环)\" }],\n },\n {\n name: \"log\",\n summary: \"日志检索 🟢\",\n args: \"[keyword]\",\n shortcuts: [{ name: \"+errors\", summary: \"昨天起的 error 级日志\" }],\n },\n {\n name: \"gateway\",\n summary: \"协议自检 🟢/🟡\",\n subcommands: [\n { name: \"test\", summary: \"模拟手机端调 daemon /notifications,验证连通/鉴权/relay 🟡\" },\n ],\n },\n {\n name: \"api\",\n summary: \"Raw HTTP escape hatch 🟡\",\n args: \"<method> <path>\",\n },\n {\n name: \"migrate\",\n summary: \"从 openclaw 插件迁移数据 🟢\",\n subcommands: [\n { name: \"from-openclaw\", summary: \"迁移 notifications/recordings/规则/api-key 到 ~/.yoooclaw\" },\n ],\n },\n {\n name: \"update\",\n summary: \"版本检查 🟢\",\n subcommands: [\n { name: \"self\", summary: \"检查 npm 最新版本并提示(不自动更新)\" },\n ],\n },\n {\n name: \"doctor\",\n summary: \"环境自检:Node/目录/keychain/daemon/relay 🟢/🟡\",\n },\n];\n",
5
+ "/**\n * 构建 yoooclaw 的 commander 程序。\n *\n * 命令树结构(service / subcommand / shortcut / options)来自 command-tree.ts;\n * 实现体由 commands/registry.ts path(如 `config init`)提供,未注册则回落 notImplemented。\n */\nimport { Command } from \"commander\";\nimport {\n COMMAND_TREE,\n type OptionSpec,\n type ServiceSpec,\n} from \"./command-tree.js\";\nimport { buildContext, type CliContext, type GlobalFlags } from \"./context.js\";\nimport { renderError, renderResult } from \"./output/format.js\";\nimport { YoooclawError, notImplemented } from \"./errors.js\";\nimport { CLI_VERSION } from \"./version.js\";\nimport { HANDLERS } from \"./commands/registry.js\";\n\n/** 命令处理器签名:拿到上下文 + commander 解析后的参数/选项,返回可序列化结果。 */\nexport type CommandHandler = (\n ctx: CliContext,\n args: unknown[],\n opts: Record<string, unknown>,\n) => unknown;\n\n/** 把 handler 包成 commander action:解析 ctx → 执行 → 统一渲染结果 / 错误。 */\nfunction wrapAction(handler: CommandHandler) {\n return async (...rawArgs: unknown[]): Promise<void> => {\n // commander 传参:[...positional, options, command]\n const command = rawArgs.at(-1) as Command;\n const opts = rawArgs.at(-2) as Record<string, unknown>;\n const positionals = rawArgs.slice(0, -2);\n const globals = command.optsWithGlobals() as GlobalFlags;\n\n let ctx: CliContext | undefined;\n try {\n ctx = buildContext(globals);\n const result = await handler(ctx, positionals, opts);\n renderResult(result, { format: ctx.format });\n } catch (err) {\n const format = ctx?.format ?? \"json\";\n renderError(err, { format });\n process.exitCode = err instanceof YoooclawError ? err.exitCode : 1;\n }\n };\n}\n\n/** 解析某个 path 的 handler,未注册则给 notImplemented 占位。 */\nfunction resolveHandler(path: string): CommandHandler {\n const handler = HANDLERS[path];\n if (handler) return handler;\n return () => {\n throw notImplemented(path);\n };\n}\n\nfunction applyOptions(cmd: Command, options: OptionSpec[] | undefined): void {\n for (const opt of options ?? []) {\n if (opt.default !== undefined) {\n cmd.option(opt.flags, opt.summary, opt.default);\n } else {\n cmd.option(opt.flags, opt.summary);\n }\n }\n}\n\nfunction attachService(program: Command, spec: ServiceSpec): void {\n const service = program.command(spec.name).description(spec.summary);\n\n // leaf 命令:直接挂 action(如 `yoooclaw doctor` / `yoooclaw api <method> <path>`)\n if (!spec.subcommands || spec.subcommands.length === 0) {\n if (spec.args) {\n service.arguments(spec.args);\n }\n applyOptions(service, spec.options);\n service.action(wrapAction(resolveHandler(spec.name)));\n } else {\n for (const sub of spec.subcommands) {\n const subCmd = service.command(sub.name).description(sub.summary);\n applyOptions(subCmd, sub.options);\n // path 的注册 key 用「服务名 + 子命令名(去掉位置参数占位)」\n subCmd.action(wrapAction(resolveHandler(handlerKey(spec.name, sub.name))));\n }\n }\n\n // shortcuts(`+` 前缀)作为该 service 下的子命令注册\n for (const shortcut of spec.shortcuts ?? []) {\n const shortcutCmd = service\n .command(shortcut.name)\n .description(shortcut.summary);\n applyOptions(shortcutCmd, shortcut.options);\n shortcutCmd.action(\n wrapAction(resolveHandler(handlerKey(spec.name, shortcut.name))),\n );\n }\n}\n\n/** 注册表的 path key:去掉子命令名里的位置参数占位(`show <id>` → `show`)。 */\nexport function handlerKey(service: string, subName: string): string {\n const bare = subName.split(/\\s+/)[0];\n return `${service} ${bare}`;\n}\n\n/** 构建并返回顶层 commander 程序。 */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"yoooclaw\")\n .description(\n \"yoooclaw —— 独立守护进程 + CLI:接收手机通知、Relay 隧道、灯效规则评估(Agent-Native)\",\n )\n .version(CLI_VERSION, \"-v, --version\", \"显示 CLI 版本号\")\n // 全局 flags(对所有命令生效)\n .option(\"--profile <name>\", \"切换 profile(默认 default)\")\n .option(\n \"--format <format>\",\n \"输出格式:json|pretty|table|ndjson(TTY 默认 pretty,管道默认 json)\",\n )\n .option(\"--quiet\", \"抑制进度日志,只输出最终结果\")\n .option(\"--no-color\", \"关闭终端颜色\")\n .showHelpAfterError();\n\n for (const spec of COMMAND_TREE) {\n attachService(program, spec);\n }\n\n return program;\n}\n",
6
+ "/**\n * 命令树声明 —— Service-oriented,对齐 lark-cli 形态与本仓 PRD「命令树总览」。\n *\n * 这是命令树的**单一事实来源**:program.ts 据此构建 commander 程序(结构 + options),\n * 实现体由 commands/registry.ts 按 path 提供;未注册的 path 回落 notImplemented 占位。\n *\n * daemon 依赖标记(仅文档用途,体现在 summary 里):\n * 🟢 不需要 daemon 🟡 需要 daemon 在跑 🔵 进程类(管理 daemon 自身)\n */\n\nexport interface OptionSpec {\n /** commander flags,如 `--from <iso8601>`、`--follow` */\n flags: string;\n summary: string;\n /** 默认值(仅对带值的 option 有意义) */\n default?: string;\n}\n\nexport interface SubcommandSpec {\n /** 子命令名 + 位置参数,如 `show <id>`、`api <method> <path>` */\n name: string;\n summary: string;\n options?: OptionSpec[];\n}\n\nexport interface ShortcutSpec {\n /** 含 `+` 前缀的快捷命令名,如 `+today` */\n name: string;\n summary: string;\n options?: OptionSpec[];\n}\n\nexport interface ServiceSpec {\n name: string;\n summary: string;\n /** 子命令列表。leaf 命令(直接执行,无子命令)省略此项并提供 `args`。 */\n subcommands?: SubcommandSpec[];\n /** leaf 命令的位置参数,如 `[keyword]`、`<method> <path>`。 */\n args?: string;\n /** leaf 命令的 options。 */\n options?: OptionSpec[];\n shortcuts?: ShortcutSpec[];\n}\n\nconst NOTIFICATION_QUERY_OPTIONS: OptionSpec[] = [\n { flags: \"--from <iso8601>\", summary: \"开始时间,如 2026-03-01T09:00:00+08:00\" },\n { flags: \"--to <iso8601>\", summary: \"结束时间\" },\n { flags: \"--app <name>\", summary: \"按应用过滤(支持中英文别名)\" },\n { flags: \"--sender <name>\", summary: \"按发送人/标题过滤\" },\n { flags: \"--conversation-type <type>\", summary: \"会话类型 group|private\" },\n { flags: \"--keyword <text>\", summary: \"在标题/内容/发送人/会话名中搜索\" },\n { flags: \"--limit <n>\", summary: \"最大返回条数\", default: \"100\" },\n];\n\nexport const COMMAND_TREE: ServiceSpec[] = [\n {\n name: \"config\",\n summary: \"配置管理 🟢\",\n subcommands: [\n {\n name: \"init\",\n summary: \"交互式首次向导,生成 config + gateway token\",\n options: [\n { flags: \"--non-interactive\", summary: \"跳过向导(配合 --from-file)\" },\n { flags: \"--from-file <path>\", summary: \"从 JSON 文件导入配置(- 为 stdin)\" },\n { flags: \"--force\", summary: \"已存在 config 时覆盖\" },\n ],\n },\n {\n name: \"show\",\n summary: \"显示当前 profile 配置(敏感字段遮罩)\",\n options: [{ flags: \"--show-secrets\", summary: \"输出敏感字段明文(需 TTY)\" }],\n },\n { name: \"set <key> <value>\", summary: \"设置单个配置项(点号路径)\" },\n { name: \"unset <key>\", summary: \"删除单个配置项\" },\n ],\n },\n {\n name: \"profile\",\n summary: \"多 profile 管理 🟢\",\n subcommands: [\n { name: \"list\", summary: \"列出所有 profile,标注 active\" },\n { name: \"use <name>\", summary: \"切换 active profile\" },\n { name: \"create <name>\", summary: \"新建 profile(走 config init 向导)\" },\n {\n name: \"delete <name>\",\n summary: \"删除 profile(非 active,需 --yes)\",\n options: [{ flags: \"--yes\", summary: \"跳过确认\" }],\n },\n ],\n },\n {\n name: \"auth\",\n summary: \"凭据与鉴权 🟢/🟡\",\n subcommands: [\n {\n name: \"set-api-key <key>\",\n summary: \"写入 account 级 api-key 到共享凭据文件(- 从 stdin 读)🟢\",\n options: [{ flags: \"--keychain\", summary: \"写入 OS keychain 而非文件\" }],\n },\n {\n name: \"token-rotate\",\n summary: \"生成新 gateway token 并热重载 🟡\",\n options: [{ flags: \"--length <n>\", summary: \"token 字节长度\", default: \"32\" }],\n },\n { name: \"status\", summary: \"显示鉴权状态(本地检查,不调 daemon)🟢\" },\n { name: \"check\", summary: \"端到端鉴权体检(调 daemon /daemon/status)🟡\" },\n ],\n },\n {\n name: \"daemon\",\n summary: \"守护进程管理 🔵\",\n subcommands: [\n {\n name: \"start\",\n summary: \"启动 daemon(默认后台 detach)\",\n options: [\n { flags: \"--bind <host>\", summary: \"监听地址(默认 config.daemon.bind)\" },\n { flags: \"--port <n>\", summary: \"监听端口(默认 config.daemon.port)\" },\n { flags: \"--no-detach\", summary: \"前台运行(systemd/launchd 用)\" },\n { flags: \"--log-level <level>\", summary: \"error|warn|info|debug|trace\" },\n ],\n },\n { name: \"stop\", summary: \"停止 daemon(SIGTERM → 10s → SIGKILL)\" },\n { name: \"restart\", summary: \"stop + start,保留原启动参数\" },\n { name: \"status\", summary: \"打印 daemon 状态(PID/端口/relay/规则数...)\" },\n {\n name: \"logs\",\n summary: \"跟踪 daemon 日志\",\n options: [\n { flags: \"-f, --follow\", summary: \"持续 tail\" },\n { flags: \"--lines <n>\", summary: \"初始展示行数\", default: \"100\" },\n { flags: \"--level <level>\", summary: \"过滤日志级别\" },\n ],\n },\n {\n name: \"run-foreground\",\n summary: \"(内部)前台运行 daemon 主循环,供 detach 子进程调用\",\n options: [\n { flags: \"--bind <host>\", summary: \"监听地址\" },\n { flags: \"--port <n>\", summary: \"监听端口\" },\n { flags: \"--log-level <level>\", summary: \"日志级别\" },\n ],\n },\n ],\n },\n {\n name: \"notification\",\n summary: \"通知查询 🟢\",\n subcommands: [\n { name: \"search\", summary: \"按筛选条件查询通知,时间倒序\", options: NOTIFICATION_QUERY_OPTIONS },\n {\n name: \"summary\",\n summary: \"聚合统计 + 样例摘要,供 Agent 总结\",\n options: [\n ...NOTIFICATION_QUERY_OPTIONS,\n { flags: \"--sample <n>\", summary: \"返回最近样例条数\", default: \"30\" },\n { flags: \"--top <n>\", summary: \"聚合榜单条数\", default: \"10\" },\n ],\n },\n {\n name: \"stats\",\n summary: \"按维度聚合统计\",\n options: [\n { flags: \"--from <date>\", summary: \"YYYY-MM-DD,默认 7 天前\" },\n { flags: \"--to <date>\", summary: \"YYYY-MM-DD,默认今天\" },\n { flags: \"--app <name>\", summary: \"仅统计指定应用\" },\n { flags: \"--dim <dim>\", summary: \"date|app|sender|hour|all\", default: \"all\" },\n ],\n },\n { name: \"storage-path\", summary: \"打印 notifications 目录绝对路径\" },\n ],\n shortcuts: [\n { name: \"+today\", summary: \"今日通知摘要\" },\n { name: \"+recent\", summary: \"最近 1 小时通知\" },\n { name: \"+unread\", summary: \"(预留)未读通知\" },\n ],\n },\n {\n name: \"sync\",\n summary: \"通知同步给记忆系统 🟢\",\n subcommands: [\n { name: \"scan\", summary: \"扫描未处理通知,返回各日期待同步摘要\" },\n {\n name: \"fetch\",\n summary: \"获取指定日期未处理通知详情\",\n options: [\n { flags: \"--date <YYYY-MM-DD>\", summary: \"目标日期(必填)\" },\n { flags: \"--max-end-index <index>\", summary: \"本次快照允许读取的最大 endIndex\" },\n ],\n },\n {\n name: \"commit\",\n summary: \"标记指定日期当前批次处理完成\",\n options: [\n { flags: \"--date <YYYY-MM-DD>\", summary: \"目标日期(必填)\" },\n { flags: \"--end-index <index>\", summary: \"本批次 fetch 返回的 endIndex\" },\n ],\n },\n ],\n },\n {\n name: \"recording\",\n summary: \"录音管理 🟢/🟡\",\n subcommands: [\n {\n name: \"list\",\n summary: \"列出所有录音 🟢\",\n options: [{ flags: \"--status <status>\", summary: \"按传输状态过滤\" }],\n },\n { name: \"status <id>\", summary: \"查看单条录音详情 🟢\" },\n { name: \"storage-path\", summary: \"打印录音存储目录绝对路径 🟢\" },\n {\n name: \"setup-asr\",\n summary: \"交互式配置 ASR 转写参数 🟢\",\n options: [\n { flags: \"--provider <name>\", summary: \"volcengine | whisper-local | ...\" },\n { flags: \"--api-key <key>\", summary: \"非交互模式直接传入\" },\n { flags: \"--non-interactive\", summary: \"跳过向导,从参数构造配置\" },\n ],\n },\n ],\n shortcuts: [{ name: \"+latest\", summary: \"展示最新一条录音详情\" }],\n },\n {\n name: \"image\",\n summary: \"图片管理 🟢\",\n subcommands: [\n {\n name: \"list\",\n summary: \"列出所有图片\",\n options: [\n { flags: \"--status <status>\", summary: \"syncing|synced|sync_failed\" },\n { flags: \"--app <name>\", summary: \"按来源应用过滤\" },\n { flags: \"--from <iso8601>\", summary: \"created_at 起\" },\n { flags: \"--to <iso8601>\", summary: \"created_at 止\" },\n { flags: \"--limit <n>\", summary: \"最大返回条数\", default: \"100\" },\n ],\n },\n { name: \"status <id>\", summary: \"查看单张图片详情\" },\n {\n name: \"path <id>\",\n summary: \"打印图片本地文件绝对路径\",\n options: [{ flags: \"--thumbnail\", summary: \"返回缩略图路径(若有)\" }],\n },\n { name: \"storage-path\", summary: \"打印图片存储目录绝对路径\" },\n ],\n shortcuts: [{ name: \"+latest\", summary: \"展示最新一张图片详情\" }],\n },\n {\n name: \"light\",\n summary: \"灯效硬件控制 🟡\",\n subcommands: [\n {\n name: \"send\",\n summary: \"发送灯效指令到硬件(--segments / --preset)\",\n options: [\n { flags: \"--segments <json>\", summary: \"灯效参数 JSON\" },\n { flags: \"--preset <name>\", summary: \"预设名,如 red-blink\" },\n { flags: \"--repeat\", summary: \"无限循环播放\" },\n { flags: \"--repeat-times <n>\", summary: \"整条组合重复次数(0=无限)\" },\n ],\n },\n ],\n shortcuts: [{ name: \"+blink\", summary: \"灯效连通性测试\" }],\n },\n {\n name: \"lightrule\",\n summary: \"灯效规则管理 🟡\",\n subcommands: [\n { name: \"list\", summary: \"列出所有规则及状态\" },\n { name: \"show <id>\", summary: \"查看单条规则详情\" },\n {\n name: \"create\",\n summary: \"创建规则(--from-file / --intent ...)\",\n options: [\n { flags: \"--from-file <path>\", summary: \"从 JSON/YAML 读规则(- 为 stdin)\" },\n { flags: \"--name <text>\", summary: \"规则名\" },\n { flags: \"--intent <text>\", summary: \"自然语言意图描述\" },\n { flags: \"--light-action <json>\", summary: \"命中后的 light 动作 JSON\" },\n { flags: \"--match-rules <json>\", summary: \"前置硬过滤规则 JSON\" },\n ],\n },\n {\n name: \"update <id>\",\n summary: \"更新现有规则\",\n options: [\n { flags: \"--from-file <path>\", summary: \"从 JSON/YAML 读规则(- 为 stdin)\" },\n { flags: \"--name <text>\", summary: \"规则名\" },\n { flags: \"--intent <text>\", summary: \"自然语言意图描述\" },\n { flags: \"--light-action <json>\", summary: \"命中后的 light 动作 JSON\" },\n { flags: \"--match-rules <json>\", summary: \"前置硬过滤规则 JSON\" },\n ],\n },\n {\n name: \"delete <id>\",\n summary: \"删除规则(--yes)\",\n options: [{ flags: \"--yes\", summary: \"跳过确认\" }],\n },\n { name: \"enable <id>\", summary: \"启用单条规则\" },\n { name: \"disable <id>\", summary: \"停用单条规则\" },\n ],\n shortcuts: [\n { name: \"+on\", summary: \"启用所有规则\" },\n { name: \"+off\", summary: \"停用所有规则(保留定义)\" },\n ],\n },\n {\n name: \"monitor\",\n summary: \"定时通知监控任务 🟡\",\n subcommands: [\n { name: \"list\", summary: \"列出所有监控任务\" },\n { name: \"show <name>\", summary: \"查看监控任务详情\" },\n {\n name: \"create <name>\",\n summary: \"创建监控任务(cron 驱动)\",\n options: [\n { flags: \"--description <text>\", summary: \"任务描述(必填)\" },\n { flags: \"--match-rules <json>\", summary: \"匹配规则 JSON(必填)\" },\n { flags: \"--schedule <cron>\", summary: \"cron 表达式(必填)\" },\n ],\n },\n {\n name: \"delete <name>\",\n summary: \"删除监控任务(--yes)\",\n options: [{ flags: \"--yes\", summary: \"跳过确认\" }],\n },\n { name: \"enable <name>\", summary: \"启用监控任务\" },\n { name: \"disable <name>\", summary: \"暂停监控任务\" },\n ],\n },\n {\n name: \"tunnel\",\n summary: \"Relay 隧道 🟡\",\n subcommands: [\n { name: \"status\", summary: \"查询 Relay 连接状态\" },\n { name: \"reconnect\", summary: \"强制重连\" },\n ],\n shortcuts: [{ name: \"+test\", summary: \"端到端联通性自检(echo 回环)\" }],\n },\n {\n name: \"log\",\n summary: \"日志检索 🟢\",\n args: \"[keyword]\",\n options: [\n { flags: \"--from <date>\", summary: \"YYYY-MM-DD,默认 7 天前\" },\n { flags: \"--to <date>\", summary: \"YYYY-MM-DD,默认今天\" },\n { flags: \"--limit <n>\", summary: \"最大返回条数\", default: \"50\" },\n { flags: \"--level <level>\", summary: \"过滤日志级别\" },\n ],\n shortcuts: [{ name: \"+errors\", summary: \"昨天起的 error 级日志\" }],\n },\n {\n name: \"gateway\",\n summary: \"协议自检 🟢/🟡\",\n subcommands: [\n {\n name: \"test\",\n summary: \"模拟手机端调 daemon /notifications,验证连通/鉴权/relay 🟡\",\n options: [\n { flags: \"--from-phone-ip <ip>\", summary: \"模拟来源 IP\" },\n { flags: \"--via-relay\", summary: \"强制走 Relay 隧道\" },\n ],\n },\n ],\n },\n {\n name: \"api\",\n summary: \"Raw HTTP escape hatch 🟡\",\n args: \"<method> <path>\",\n options: [\n { flags: \"--data <json>\", summary: \"请求体(@file 读文件、- 读 stdin)\" },\n { flags: \"--header <key:value>\", summary: \"追加 header(可重复)\" },\n ],\n },\n {\n name: \"migrate\",\n summary: \"从 openclaw 插件迁移数据 🟢\",\n subcommands: [\n {\n name: \"from-openclaw\",\n summary: \"迁移 notifications/recordings/规则/api-key 到 ~/.yoooclaw\",\n options: [\n { flags: \"--dry-run\", summary: \"只打印迁移计划,不写入\" },\n { flags: \"--source <path>\", summary: \"自定义源目录,默认 ~/.openclaw\" },\n ],\n },\n ],\n },\n {\n name: \"update\",\n summary: \"版本检查 🟢\",\n subcommands: [\n {\n name: \"self\",\n summary: \"检查 npm 最新版本并提示(不自动更新)\",\n options: [\n { flags: \"--beta\", summary: \"检查 beta channel\" },\n { flags: \"--json\", summary: \"只输出版本信息 JSON\" },\n ],\n },\n ],\n },\n {\n name: \"doctor\",\n summary: \"环境自检:Node/目录/keychain/daemon/relay 🟢/🟡\",\n options: [\n { flags: \"--json\", summary: \"JSON 输出(给脚本用)\" },\n { flags: \"--fix\", summary: \"自动修复可修复的问题\" },\n ],\n },\n];\n",
7
7
  "/**\n * 全局执行上下文 —— 由全局 flags 解析得到,贯穿所有命令。\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport {\n DEFAULT_PROFILE,\n activeProfilePath,\n profilePaths,\n type ProfilePaths,\n} from \"./paths.js\";\nimport { resolveFormat, type OutputFormat } from \"./output/format.js\";\n\nexport interface GlobalFlags {\n profile?: string;\n format?: string;\n quiet?: boolean;\n color?: boolean;\n}\n\nexport interface CliContext {\n profile: string;\n paths: ProfilePaths;\n format: OutputFormat;\n quiet: boolean;\n color: boolean;\n}\n\n/** 解析当前 active profile:--profile > $YOOOCLAW_PROFILE > active-profile 文件 > default。 */\nexport function resolveActiveProfile(flagProfile?: string): string {\n if (flagProfile?.trim()) return flagProfile.trim();\n const envProfile = process.env.YOOOCLAW_PROFILE?.trim();\n if (envProfile) return envProfile;\n const file = activeProfilePath();\n if (existsSync(file)) {\n const name = readFileSync(file, \"utf-8\").trim();\n if (name) return name;\n }\n return DEFAULT_PROFILE;\n}\n\n/** 把全局 flags 物化成贯穿命令的 CliContext。 */\nexport function buildContext(flags: GlobalFlags): CliContext {\n const profile = resolveActiveProfile(flags.profile);\n return {\n profile,\n paths: profilePaths(profile),\n format: resolveFormat(flags.format),\n quiet: flags.quiet ?? false,\n // commander 对 --no-color 解析为 color:false;缺省 true\n color: flags.color ?? true,\n };\n}\n",
8
- "/**\n * `~/.yoooclaw/` 目录布局解析(对齐 PRD「数据模型 / 目录布局」)。\n *\n * ~/.yoooclaw/\n * credentials.json account 级共享凭据(api-key),跨 profile 且与插件共享\n * active-profile 当前 active profile 名(文本)\n * profiles/<profile>/\n * config.json\n * credentials.json instance 级密文(gateway token / webhook secret)\n * daemon.lock / daemon.log\n * notifications/ recordings/ images/ light-rules/ state/\n */\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const DEFAULT_PROFILE = \"default\";\n\n/** CLI 根数据目录。可用 `YOOOCLAW_HOME` 覆盖(测试 / 多实例隔离)。 */\nexport function rootDir(): string {\n return process.env.YOOOCLAW_HOME?.trim() || join(homedir(), \".yoooclaw\");\n}\n\n/** account 级共享凭据文件(顶层,跨 profile + 插件共享)。 */\nexport function sharedCredentialsPath(): string {\n return join(rootDir(), \"credentials.json\");\n}\n\n/** 记录当前 active profile 的文本文件。 */\nexport function activeProfilePath(): string {\n return join(rootDir(), \"active-profile\");\n}\n\n/** 某个 profile 的目录。 */\nexport function profileDir(profile: string): string {\n return join(rootDir(), \"profiles\", profile);\n}\n\nexport interface ProfilePaths {\n profile: string;\n dir: string;\n config: string;\n credentials: string;\n daemonLock: string;\n daemonLog: string;\n notifications: string;\n recordings: string;\n images: string;\n lightRules: string;\n state: string;\n}\n\n/** 解析某个 profile 下的全部关键路径。 */\nexport function profilePaths(profile: string): ProfilePaths {\n const dir = profileDir(profile);\n return {\n profile,\n dir,\n config: join(dir, \"config.json\"),\n credentials: join(dir, \"credentials.json\"),\n daemonLock: join(dir, \"daemon.lock\"),\n daemonLog: join(dir, \"daemon.log\"),\n notifications: join(dir, \"notifications\"),\n recordings: join(dir, \"recordings\"),\n images: join(dir, \"images\"),\n lightRules: join(dir, \"light-rules\"),\n state: join(dir, \"state\"),\n };\n}\n",
9
- "/**\n * 结构化错误码 —— 进入半正式契约,命名前缀统一 `YOOOCLAW_*`。\n * 命令失败时统一以 `{ ok: false, error: { code, message, ... } }` 输出(见 output/format.ts)。\n */\nexport const ErrorCode = {\n /** 通用 / 未归类错误 */\n UNKNOWN: \"YOOOCLAW_UNKNOWN\",\n /** 参数校验失败 */\n INVALID_ARGUMENT: \"YOOOCLAW_INVALID_ARGUMENT\",\n /** 该命令尚未实现(脚手架阶段占位) */\n NOT_IMPLEMENTED: \"YOOOCLAW_NOT_IMPLEMENTED\",\n /** daemon 未运行 */\n DAEMON_NOT_RUNNING: \"YOOOCLAW_DAEMON_NOT_RUNNING\",\n /** daemon 已在运行(单例保护) */\n DAEMON_ALREADY_RUNNING: \"YOOOCLAW_DAEMON_ALREADY_RUNNING\",\n /** 鉴权失败 / token 不一致 */\n UNAUTHORIZED: \"YOOOCLAW_UNAUTHORIZED\",\n /** 配置缺失或非法 */\n CONFIG_INVALID: \"YOOOCLAW_CONFIG_INVALID\",\n /** profile 不存在 */\n PROFILE_NOT_FOUND: \"YOOOCLAW_PROFILE_NOT_FOUND\",\n /** 图片尚未下载完成 */\n IMAGE_NOT_READY: \"YOOOCLAW_IMAGE_NOT_READY\",\n /** 资源未找到 */\n NOT_FOUND: \"YOOOCLAW_NOT_FOUND\",\n} as const;\n\nexport type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface YoooclawErrorDetails {\n hint?: string;\n checkedPaths?: string[];\n [key: string]: unknown;\n}\n\n/**\n * 携带结构化错误码的错误。CLI 顶层捕获后按 `--format` 序列化为统一错误 schema。\n */\nexport class YoooclawError extends Error {\n readonly code: ErrorCodeValue;\n readonly details: YoooclawErrorDetails;\n /** 进程退出码,默认 1 */\n readonly exitCode: number;\n\n constructor(\n code: ErrorCodeValue,\n message: string,\n details: YoooclawErrorDetails = {},\n exitCode = 1,\n ) {\n super(message);\n this.name = \"YoooclawError\";\n this.code = code;\n this.details = details;\n this.exitCode = exitCode;\n }\n\n toErrorPayload(): {\n code: ErrorCodeValue;\n message: string;\n } & YoooclawErrorDetails {\n return { code: this.code, message: this.message, ...this.details };\n }\n}\n\nexport function notImplemented(command: string): YoooclawError {\n return new YoooclawError(\n ErrorCode.NOT_IMPLEMENTED,\n `命令 \\`${command}\\` 尚未实现`,\n { hint: \"该命令处于脚手架阶段,后续按 imp 文档逐步落地\" },\n );\n}\n",
8
+ "/**\n * `~/.yoooclaw/` 目录布局解析(对齐 PRD「数据模型 / 目录布局」)。\n *\n * ~/.yoooclaw/\n * credentials.json account 级共享凭据(api-key),跨 profile 且与插件共享\n * active-profile 当前 active profile 名(文本)\n * profiles/<profile>/\n * config.json\n * credentials.json instance 级密文(gateway token / webhook secret)\n * daemon.lock / daemon.log\n * notifications/ recordings/ images/ light-rules/ state/\n */\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const DEFAULT_PROFILE = \"default\";\n\n/** CLI 根数据目录。可用 `YOOOCLAW_HOME` 覆盖(测试 / 多实例隔离)。 */\nexport function rootDir(): string {\n return process.env.YOOOCLAW_HOME?.trim() || join(homedir(), \".yoooclaw\");\n}\n\n/** account 级共享凭据文件(顶层,跨 profile + 插件共享)。 */\nexport function sharedCredentialsPath(): string {\n return join(rootDir(), \"credentials.json\");\n}\n\n/** 记录当前 active profile 的文本文件。 */\nexport function activeProfilePath(): string {\n return join(rootDir(), \"active-profile\");\n}\n\n/** 某个 profile 的目录。 */\nexport function profileDir(profile: string): string {\n return join(rootDir(), \"profiles\", profile);\n}\n\nexport interface ProfilePaths {\n profile: string;\n dir: string;\n config: string;\n credentials: string;\n daemonLock: string;\n daemonLog: string;\n notifications: string;\n recordings: string;\n images: string;\n lightRules: string;\n state: string;\n}\n\n/** profiles/ 根目录。 */\nexport function profilesRoot(): string {\n return join(rootDir(), \"profiles\");\n}\n\n/** 列出已存在的 profile 名(profiles/ 下的目录)。 */\nexport function listProfileNames(): string[] {\n const root = profilesRoot();\n if (!existsSync(root)) return [];\n return readdirSync(root, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => e.name)\n .sort((a, b) => a.localeCompare(b));\n}\n\n/** 读取 active-profile 文件内容(不存在返回 undefined)。 */\nexport function readActiveProfile(): string | undefined {\n const file = activeProfilePath();\n if (!existsSync(file)) return undefined;\n const name = readFileSync(file, \"utf-8\").trim();\n return name || undefined;\n}\n\n/** 解析某个 profile 下的全部关键路径。 */\nexport function profilePaths(profile: string): ProfilePaths {\n const dir = profileDir(profile);\n return {\n profile,\n dir,\n config: join(dir, \"config.json\"),\n credentials: join(dir, \"credentials.json\"),\n daemonLock: join(dir, \"daemon.lock\"),\n daemonLog: join(dir, \"daemon.log\"),\n notifications: join(dir, \"notifications\"),\n recordings: join(dir, \"recordings\"),\n images: join(dir, \"images\"),\n lightRules: join(dir, \"light-rules\"),\n state: join(dir, \"state\"),\n };\n}\n",
9
+ "/**\n * 结构化错误码 —— 进入半正式契约,命名前缀统一 `YOOOCLAW_*`。\n * 命令失败时统一以 `{ ok: false, error: { code, message, ... } }` 输出(见 output/format.ts)。\n */\nexport const ErrorCode = {\n /** 通用 / 未归类错误 */\n UNKNOWN: \"YOOOCLAW_UNKNOWN\",\n /** 参数校验失败 */\n INVALID_ARGUMENT: \"YOOOCLAW_INVALID_ARGUMENT\",\n /** 该命令尚未实现(脚手架阶段占位) */\n NOT_IMPLEMENTED: \"YOOOCLAW_NOT_IMPLEMENTED\",\n /** daemon 未运行 */\n DAEMON_NOT_RUNNING: \"YOOOCLAW_DAEMON_NOT_RUNNING\",\n /** daemon 已在运行(单例保护) */\n DAEMON_ALREADY_RUNNING: \"YOOOCLAW_DAEMON_ALREADY_RUNNING\",\n /** 鉴权失败 / token 不一致 */\n UNAUTHORIZED: \"YOOOCLAW_UNAUTHORIZED\",\n /** 配置缺失或非法 */\n CONFIG_INVALID: \"YOOOCLAW_CONFIG_INVALID\",\n /** profile 不存在 */\n PROFILE_NOT_FOUND: \"YOOOCLAW_PROFILE_NOT_FOUND\",\n /** 图片尚未下载完成 */\n IMAGE_NOT_READY: \"YOOOCLAW_IMAGE_NOT_READY\",\n /** 资源未找到 */\n NOT_FOUND: \"YOOOCLAW_NOT_FOUND\",\n /** 资源已存在(如 profile 重名) */\n ALREADY_EXISTS: \"YOOOCLAW_ALREADY_EXISTS\",\n /** 存储目录不可用 */\n STORAGE_UNAVAILABLE: \"YOOOCLAW_STORAGE_UNAVAILABLE\",\n /** 凭据缺失 */\n CREDENTIAL_MISSING: \"YOOOCLAW_CREDENTIAL_MISSING\",\n /** OS keychain 不可用 */\n KEYCHAIN_UNAVAILABLE: \"YOOOCLAW_KEYCHAIN_UNAVAILABLE\",\n /** 网络 / 出站调用失败 */\n NETWORK_ERROR: \"YOOOCLAW_NETWORK_ERROR\",\n /** 操作被用户取消或需要确认 */\n CONFIRMATION_REQUIRED: \"YOOOCLAW_CONFIRMATION_REQUIRED\",\n /** 需要 TTY 交互但当前非交互环境 */\n NOT_INTERACTIVE: \"YOOOCLAW_NOT_INTERACTIVE\",\n} as const;\n\nexport type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface YoooclawErrorDetails {\n hint?: string;\n checkedPaths?: string[];\n [key: string]: unknown;\n}\n\n/**\n * 携带结构化错误码的错误。CLI 顶层捕获后按 `--format` 序列化为统一错误 schema。\n */\nexport class YoooclawError extends Error {\n readonly code: ErrorCodeValue;\n readonly details: YoooclawErrorDetails;\n /** 进程退出码,默认 1 */\n readonly exitCode: number;\n\n constructor(\n code: ErrorCodeValue,\n message: string,\n details: YoooclawErrorDetails = {},\n exitCode = 1,\n ) {\n super(message);\n this.name = \"YoooclawError\";\n this.code = code;\n this.details = details;\n this.exitCode = exitCode;\n }\n\n toErrorPayload(): {\n code: ErrorCodeValue;\n message: string;\n } & YoooclawErrorDetails {\n return { code: this.code, message: this.message, ...this.details };\n }\n}\n\nexport function notImplemented(command: string): YoooclawError {\n return new YoooclawError(\n ErrorCode.NOT_IMPLEMENTED,\n `命令 \\`${command}\\` 尚未实现`,\n { hint: \"该命令处于脚手架阶段,后续按 imp 文档逐步落地\" },\n );\n}\n",
10
10
  "/**\n * 统一输出层 —— 所有命令的 stdout 走这里序列化。\n *\n * 支持 `--format json|pretty|table|ndjson`:\n * - json JSON.stringify(data) 单行 (非 TTY / 管道默认)\n * - pretty JSON.stringify(data, null, 2) (TTY 默认;后续可加颜色)\n * - table 表格输出(结果为数组时)\n * - ndjson 每条结果一行 JSON,无包裹数组 (流式 / Agent 消费)\n *\n * 错误与正常输出共用同一 schema:`{ ok: false, error: { code, message, ... } }`。\n */\nimport { YoooclawError, type ErrorCodeValue } from \"../errors.js\";\n\nexport type OutputFormat = \"json\" | \"pretty\" | \"table\" | \"ndjson\";\nexport const OUTPUT_FORMATS: OutputFormat[] = [\n \"json\",\n \"pretty\",\n \"table\",\n \"ndjson\",\n];\n\n/** 解析用户传入的 --format;`auto` / 缺省时按 TTY 判定。 */\nexport function resolveFormat(\n requested: string | undefined,\n isTty = process.stdout.isTTY ?? false,\n): OutputFormat {\n if (requested && requested !== \"auto\") {\n if ((OUTPUT_FORMATS as string[]).includes(requested)) {\n return requested as OutputFormat;\n }\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\" as ErrorCodeValue,\n `不支持的输出格式:${requested}`,\n { hint: `可选值:${OUTPUT_FORMATS.join(\" | \")} | auto` },\n );\n }\n return isTty ? \"pretty\" : \"json\";\n}\n\ninterface RenderOptions {\n format: OutputFormat;\n /** 写出目标,默认 process.stdout。便于测试。 */\n stream?: NodeJS.WritableStream;\n}\n\nfunction write(stream: NodeJS.WritableStream, text: string): void {\n stream.write(text.endsWith(\"\\n\") ? text : text + \"\\n\");\n}\n\n/** 渲染一次成功结果。data 任意结构;table/ndjson 在数组时逐行展开。 */\nexport function renderResult(data: unknown, opts: RenderOptions): void {\n const stream = opts.stream ?? process.stdout;\n switch (opts.format) {\n case \"json\":\n write(stream, JSON.stringify(data));\n return;\n case \"pretty\":\n write(stream, JSON.stringify(data, null, 2));\n return;\n case \"ndjson\": {\n const rows = Array.isArray(data) ? data : [data];\n for (const row of rows) stream.write(JSON.stringify(row) + \"\\n\");\n return;\n }\n case \"table\":\n write(stream, renderTable(data));\n return;\n }\n}\n\n/**\n * 渲染错误。统一 schema:{ ok: false, error: {...} }。\n * 默认写 stdout —— 与正常输出同一通道,让 `--format json | jq` 等 Agent 管道能读到错误体;\n * 失败由非零退出码表达。\n */\nexport function renderError(err: unknown, opts: RenderOptions): void {\n const stream = opts.stream ?? process.stdout;\n const error =\n err instanceof YoooclawError\n ? err.toErrorPayload()\n : {\n code: \"YOOOCLAW_UNKNOWN\",\n message: err instanceof Error ? err.message : String(err),\n };\n const payload = { ok: false, error };\n const text =\n opts.format === \"pretty\"\n ? JSON.stringify(payload, null, 2)\n : JSON.stringify(payload);\n write(stream, text);\n}\n\n/** 极简表格渲染:对象数组 → 列对齐文本;其余 fallback 到 pretty JSON。 */\nfunction renderTable(data: unknown): string {\n if (!Array.isArray(data) || data.length === 0) {\n return JSON.stringify(data, null, 2);\n }\n const rows = data.filter(\n (r): r is Record<string, unknown> =>\n typeof r === \"object\" && r !== null && !Array.isArray(r),\n );\n if (rows.length !== data.length) {\n return JSON.stringify(data, null, 2);\n }\n const columns = Array.from(\n rows.reduce<Set<string>>((set, row) => {\n for (const key of Object.keys(row)) set.add(key);\n return set;\n }, new Set()),\n );\n const cell = (v: unknown): string =>\n v === null || v === undefined\n ? \"\"\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v);\n const widths = columns.map((col) =>\n Math.max(col.length, ...rows.map((row) => cell(row[col]).length)),\n );\n const pad = (text: string, width: number) => text.padEnd(width);\n const header = columns.map((col, i) => pad(col, widths[i])).join(\" \");\n const divider = widths.map((w) => \"-\".repeat(w)).join(\" \");\n const body = rows\n .map((row) =>\n columns.map((col, i) => pad(cell(row[col]), widths[i])).join(\" \"),\n )\n .join(\"\\n\");\n return [header, divider, body].join(\"\\n\");\n}\n",
11
11
  "import { readFileSync } from \"node:fs\";\n\ndeclare const __CLI_VERSION__: string | undefined;\n\ninterface PackageJson {\n version?: string;\n}\n\nfunction readBuildInjectedVersion(): string | undefined {\n if (typeof __CLI_VERSION__ !== \"string\") {\n return undefined;\n }\n const version = __CLI_VERSION__.trim();\n return version || undefined;\n}\n\nfunction readVersionFromPackageJson(): string | undefined {\n try {\n const packageJsonUrl = new URL(\"../package.json\", import.meta.url);\n const packageJson = JSON.parse(\n readFileSync(packageJsonUrl, \"utf-8\"),\n ) as PackageJson;\n const version = packageJson.version?.trim();\n return version || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport const CLI_VERSION =\n readBuildInjectedVersion() ?? readVersionFromPackageJson() ?? \"unknown\";\n",
12
+ "/**\n * 文件系统工具 —— 统一目录/文件权限与原子写。\n *\n * 凭据与配置落盘的安全约束(PRD「非功能需求 / 安全」):\n * - 目录 0700、敏感文件 0600;\n * - 写入走「临时文件 + rename」原子替换,避免半截写。\n */\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { YoooclawError } from \"./errors.js\";\n\n/** 目录默认权限(私有)。 */\nexport const DIR_MODE = 0o700;\n/** 敏感文件权限(仅属主可读写)。 */\nexport const SECRET_FILE_MODE = 0o600;\n/** 普通配置文件权限。 */\nexport const CONFIG_FILE_MODE = 0o644;\n\n/** 确保目录存在并尽力收紧权限(Windows 上 chmod 基本 no-op)。 */\nexport function ensureDir(dir: string, mode: number = DIR_MODE): void {\n mkdirSync(dir, { recursive: true, mode });\n try {\n chmodSync(dir, mode);\n } catch {\n // Windows / 受限文件系统:忽略\n }\n}\n\n/** 原子写文件:先写临时文件再 rename,最后 chmod。 */\nexport function writeFileAtomic(\n filePath: string,\n contents: string,\n mode: number = CONFIG_FILE_MODE,\n): void {\n ensureDir(dirname(filePath));\n const tmp = join(\n dirname(filePath),\n `.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`,\n );\n writeFileSync(tmp, contents, { mode });\n renameSync(tmp, filePath);\n try {\n chmodSync(filePath, mode);\n } catch {\n // 忽略\n }\n}\n\n/** 写 JSON(两空格缩进 + 末尾换行)。 */\nexport function writeJsonFile(\n filePath: string,\n data: unknown,\n mode: number = CONFIG_FILE_MODE,\n): void {\n writeFileAtomic(filePath, JSON.stringify(data, null, 2) + \"\\n\", mode);\n}\n\n/** 读 JSON;文件不存在返回 undefined;解析失败抛 CONFIG_INVALID。 */\nexport function readJsonFile<T = unknown>(filePath: string): T | undefined {\n if (!existsSync(filePath)) return undefined;\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch (err) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `读取文件失败:${filePath}`,\n { cause: err instanceof Error ? err.message : String(err) },\n );\n }\n try {\n return JSON.parse(raw) as T;\n } catch {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `文件不是合法 JSON:${filePath}`,\n { hint: \"可手动修复或删除后重新生成\" },\n );\n }\n}\n",
13
+ "/**\n * 交互式输入工具(config init / setup-asr / 删除确认等)。\n *\n * 非 TTY 环境调用任何 prompt 都抛 NOT_INTERACTIVE,避免在管道里挂起。\n */\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin, stdout } from \"node:process\";\nimport { YoooclawError } from \"./errors.js\";\n\nexport function isInteractive(): boolean {\n return Boolean(stdin.isTTY && stdout.isTTY);\n}\n\nfunction ensureInteractive(): void {\n if (!isInteractive()) {\n throw new YoooclawError(\n \"YOOOCLAW_NOT_INTERACTIVE\",\n \"当前为非交互环境,无法进行交互式输入\",\n { hint: \"改用 --non-interactive --from-file,或在 TTY 中运行\" },\n );\n }\n}\n\n/** 提一个问题,返回去空白后的回答;提供 defaultValue 时回车采用默认。 */\nexport async function ask(question: string, defaultValue?: string): Promise<string> {\n ensureInteractive();\n const suffix = defaultValue ? ` [${defaultValue}]` : \"\";\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n const answer = (await rl.question(`${question}${suffix}: `)).trim();\n return answer || defaultValue || \"\";\n } finally {\n rl.close();\n }\n}\n\n/** Yes/No 确认,默认值由 defaultYes 决定。 */\nexport async function confirm(question: string, defaultYes = false): Promise<boolean> {\n const hint = defaultYes ? \"Y/n\" : \"y/N\";\n const answer = (await ask(`${question} (${hint})`)).toLowerCase();\n if (!answer) return defaultYes;\n return answer === \"y\" || answer === \"yes\";\n}\n\n/** 读取 stdin 全部内容(用于 `--from-file -` / `set-api-key -`)。 */\nexport async function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stdin) {\n chunks.push(Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n",
14
+ "/**\n * config.json 读写 + 点号路径 get/set/unset + 敏感字段遮罩。\n */\nimport { existsSync } from \"node:fs\";\nimport type { ProfilePaths } from \"../paths.js\";\nimport { readJsonFile, writeJsonFile, CONFIG_FILE_MODE } from \"../fs-utils.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport {\n defaultConfig,\n SECRET_REF_PATHS,\n type YoooclawConfig,\n} from \"./schema.js\";\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** 深合并:用 source 覆盖 target(仅对象递归,数组/标量整体替换)。 */\nexport function deepMerge<T>(target: T, source: unknown): T {\n if (!isPlainObject(source)) return target;\n const out: PlainObject = isPlainObject(target) ? { ...target } : {};\n for (const [key, value] of Object.entries(source)) {\n const prev = out[key];\n out[key] = isPlainObject(value) && isPlainObject(prev)\n ? deepMerge(prev, value)\n : value;\n }\n return out as T;\n}\n\nexport function configExists(paths: ProfilePaths): boolean {\n return existsSync(paths.config);\n}\n\n/** 读取 config;缺失字段用默认值补齐。文件不存在则返回纯默认。 */\nexport function loadConfig(paths: ProfilePaths): YoooclawConfig {\n const base = defaultConfig(paths.credentials);\n const stored = readJsonFile<Partial<YoooclawConfig>>(paths.config);\n if (!stored) return base;\n return deepMerge(base, stored);\n}\n\n/** 要求 config 必须已存在(如 daemon 启动场景),否则报错。 */\nexport function requireConfig(paths: ProfilePaths): YoooclawConfig {\n if (!configExists(paths)) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `profile \\`${paths.profile}\\` 尚未初始化`,\n { hint: \"先运行 yoooclaw config init\", checkedPaths: [paths.config] },\n );\n }\n return loadConfig(paths);\n}\n\nexport function saveConfig(paths: ProfilePaths, config: YoooclawConfig): void {\n writeJsonFile(paths.config, config, CONFIG_FILE_MODE);\n}\n\n/** 按点号路径取值。 */\nexport function getByPath(obj: unknown, path: string): unknown {\n const segments = path.split(\".\");\n let cursor: unknown = obj;\n for (const seg of segments) {\n if (!isPlainObject(cursor)) return undefined;\n cursor = cursor[seg];\n }\n return cursor;\n}\n\n/** 按点号路径设值(中间缺失对象自动创建)。返回新对象(原地修改 obj 的拷贝语义由调用方保证)。 */\nexport function setByPath(obj: PlainObject, path: string, value: unknown): void {\n const segments = path.split(\".\");\n let cursor: PlainObject = obj;\n for (let i = 0; i < segments.length - 1; i += 1) {\n const seg = segments[i];\n if (!isPlainObject(cursor[seg])) cursor[seg] = {};\n cursor = cursor[seg] as PlainObject;\n }\n cursor[segments.at(-1)!] = value;\n}\n\n/** 按点号路径删除;返回是否删除了字段。 */\nexport function unsetByPath(obj: PlainObject, path: string): boolean {\n const segments = path.split(\".\");\n let cursor: PlainObject = obj;\n for (let i = 0; i < segments.length - 1; i += 1) {\n const seg = segments[i];\n if (!isPlainObject(cursor[seg])) return false;\n cursor = cursor[seg] as PlainObject;\n }\n const last = segments.at(-1)!;\n if (!(last in cursor)) return false;\n delete cursor[last];\n return true;\n}\n\nconst NUMBER_PATHS = new Set([\n \"daemon.port\",\n \"relay.heartbeatSec\",\n \"relay.reconnectBackoffMs\",\n \"notification.retentionDays\",\n \"lightRules.evaluator.timeoutMs\",\n \"lightRules.evaluator.retries\",\n \"image.maxBytes\",\n]);\nconst BOOLEAN_PATHS = new Set([\n \"daemon.detach\",\n \"relay.enabled\",\n \"lightRules.enabled\",\n \"autoUpdate.enabled\",\n]);\nconst ARRAY_PATHS = new Set([\"notification.ignoredApps\"]);\n\n/** 把命令行字符串值按目标字段类型强转。 */\nexport function coerceConfigValue(path: string, raw: string): unknown {\n if (NUMBER_PATHS.has(path)) {\n if (path === \"notification.retentionDays\" && (raw === \"null\" || raw === \"\")) {\n return null;\n }\n const n = Number(raw);\n if (!Number.isFinite(n)) {\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n `${path} 需要数字,收到:${raw}`,\n );\n }\n return n;\n }\n if (BOOLEAN_PATHS.has(path)) {\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n `${path} 需要 true/false,收到:${raw}`,\n );\n }\n if (ARRAY_PATHS.has(path)) {\n return raw.split(\",\").map((s) => s.trim()).filter(Boolean);\n }\n return raw;\n}\n\n/** 深拷贝并遮罩敏感字段,供 `config show` 用。inline: 引用整体遮罩。 */\nexport function maskConfig(config: YoooclawConfig): YoooclawConfig {\n const clone = structuredClone(config);\n for (const path of SECRET_REF_PATHS) {\n const value = getByPath(clone, path);\n if (typeof value === \"string\" && value.startsWith(\"inline:\")) {\n setByPath(clone as unknown as PlainObject, path, \"inline:****\");\n }\n }\n return clone;\n}\n",
15
+ "/**\n * yoooclaw daemon 配置 schema(per-profile `config.json`)。\n *\n * 对齐 PRD「数据模型 / config.json 结构」。敏感字段(gateway token / webhook secret)\n * 不直接落在这里,而是用 `*Ref` 抽象引用指向 credentials 文件 / keychain / env。\n */\n\nexport const CONFIG_VERSION = 1;\n\nexport type LogLevel = \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\";\nexport type OutputDefaultFormat = \"auto\" | \"json\" | \"pretty\" | \"table\" | \"ndjson\";\n\nexport interface DaemonSection {\n bind: string;\n port: number;\n logLevel: LogLevel;\n detach: boolean;\n}\n\nexport interface AuthSection {\n mode: \"token\";\n /** gateway token 的抽象引用(env: / file: / keychain: / inline:)。 */\n tokenRef: string;\n}\n\nexport interface RelaySection {\n url: string;\n heartbeatSec: number;\n reconnectBackoffMs: number;\n enabled: boolean;\n}\n\nexport interface NotificationSection {\n /** 本地保留天数;null 表示永久保存。 */\n retentionDays: number | null;\n ignoredApps: string[];\n}\n\nexport interface WebhookEvaluatorSection {\n mode: \"webhook\";\n webhookUrl: string;\n /** webhook secret 的抽象引用。 */\n webhookSecretRef: string;\n timeoutMs: number;\n retries: number;\n}\n\nexport interface LightRulesSection {\n enabled: boolean;\n evaluator?: WebhookEvaluatorSection;\n}\n\nexport interface AutoUpdateSection {\n enabled: boolean;\n channel: \"stable\" | \"beta\";\n}\n\nexport interface OutputSection {\n defaultFormat: OutputDefaultFormat;\n}\n\nexport interface ImageSection {\n /** 单文件下载上限(字节),超限拒绝下载并标记 sync_failed。 */\n maxBytes: number;\n}\n\nexport interface YoooclawConfig {\n version: number;\n daemon: DaemonSection;\n auth: AuthSection;\n relay: RelaySection;\n notification: NotificationSection;\n lightRules: LightRulesSection;\n autoUpdate: AutoUpdateSection;\n output: OutputSection;\n image: ImageSection;\n}\n\nexport const DEFAULT_RELAY_URL = \"wss://relay.yoooclaw.com/tunnel\";\nexport const DEFAULT_PORT = 18789;\nexport const DEFAULT_BIND = \"127.0.0.1\";\nexport const DEFAULT_IMAGE_MAX_BYTES = 20 * 1024 * 1024;\n\n/** 生成某个 profile 的默认 config。tokenRef/secretRef 默认指向该 profile 的 credentials 文件。 */\nexport function defaultConfig(credentialsPath: string): YoooclawConfig {\n return {\n version: CONFIG_VERSION,\n daemon: {\n bind: DEFAULT_BIND,\n port: DEFAULT_PORT,\n logLevel: \"info\",\n detach: true,\n },\n auth: {\n mode: \"token\",\n tokenRef: `file:${credentialsPath}#gatewayToken`,\n },\n relay: {\n url: DEFAULT_RELAY_URL,\n heartbeatSec: 10,\n reconnectBackoffMs: 2000,\n enabled: true,\n },\n notification: {\n retentionDays: null,\n ignoredApps: [],\n },\n lightRules: {\n enabled: true,\n },\n autoUpdate: {\n enabled: true,\n channel: \"stable\",\n },\n output: {\n defaultFormat: \"auto\",\n },\n image: {\n maxBytes: DEFAULT_IMAGE_MAX_BYTES,\n },\n };\n}\n\n/** 默认 webhook 评估器(config init 启用灯效评估时填充)。 */\nexport function defaultEvaluator(credentialsPath: string): WebhookEvaluatorSection {\n return {\n mode: \"webhook\",\n webhookUrl: \"\",\n webhookSecretRef: `file:${credentialsPath}#evaluatorSecret`,\n timeoutMs: 5000,\n retries: 1,\n };\n}\n\n/** config.json 里需要遮罩展示的敏感引用字段(点号路径)。 */\nexport const SECRET_REF_PATHS = [\n \"auth.tokenRef\",\n \"lightRules.evaluator.webhookSecretRef\",\n];\n",
16
+ "/**\n * 凭据存取 —— account 级 api-key(共享)与 instance 级 gateway token(per-profile)。\n *\n * api-key 分层解析(PRD「凭据解析顺序与插件共享」),命中即停:\n * 1. env YOOOCLAW_API_KEY —— 显式覆盖\n * 2. keychain yoooclaw/api-key —— 可选加固\n * 3. file ~/.yoooclaw/credentials.json#apiKey —— 默认共享底座(与插件共用)\n */\nimport { randomBytes } from \"node:crypto\";\nimport { sharedCredentialsPath } from \"../paths.js\";\nimport { readJsonFile, writeJsonFile, SECRET_FILE_MODE } from \"../fs-utils.js\";\nimport { keychainAvailable, keychainGet, keychainSet } from \"./keychain.js\";\nimport { resolveRef, writeRef, type ResolvedRef } from \"./refs.js\";\nimport type { YoooclawConfig } from \"../config/schema.js\";\nimport { YoooclawError } from \"../errors.js\";\n\nexport const API_KEY_ENV = \"YOOOCLAW_API_KEY\";\nexport const KEYCHAIN_SERVICE = \"yoooclaw\";\nexport const KEYCHAIN_API_KEY_ACCOUNT = \"api-key\";\nexport const API_KEY_FIELD = \"apiKey\";\n\nexport interface ApiKeyResolution {\n value?: string;\n source: \"env\" | \"keychain\" | \"file\" | \"none\";\n location?: string;\n}\n\n/** 按分层顺序解析 account 级 api-key。 */\nexport function resolveApiKey(): ApiKeyResolution {\n const env = process.env[API_KEY_ENV]?.trim();\n if (env) return { value: env, source: \"env\", location: API_KEY_ENV };\n\n if (keychainAvailable()) {\n const r = keychainGet(KEYCHAIN_SERVICE, KEYCHAIN_API_KEY_ACCOUNT);\n if (r.value) {\n return { value: r.value, source: \"keychain\", location: `${KEYCHAIN_SERVICE}/${KEYCHAIN_API_KEY_ACCOUNT}` };\n }\n }\n\n const file = sharedCredentialsPath();\n const data = readJsonFile<Record<string, unknown>>(file);\n const value = data?.[API_KEY_FIELD];\n if (typeof value === \"string\" && value) {\n return { value, source: \"file\", location: file };\n }\n\n return { source: \"none\" };\n}\n\n/** 写入 account 级 api-key。默认写共享文件;--keychain 时写 OS keychain。 */\nexport function setApiKey(key: string, useKeychain: boolean): ApiKeyResolution {\n if (useKeychain) {\n if (!keychainSet(KEYCHAIN_SERVICE, KEYCHAIN_API_KEY_ACCOUNT, key)) {\n throw new YoooclawError(\n \"YOOOCLAW_KEYCHAIN_UNAVAILABLE\",\n \"当前平台无法写入 keychain,请去掉 --keychain 改写共享文件\",\n );\n }\n return { value: key, source: \"keychain\", location: `${KEYCHAIN_SERVICE}/${KEYCHAIN_API_KEY_ACCOUNT}` };\n }\n const file = sharedCredentialsPath();\n const data = readJsonFile<Record<string, unknown>>(file) ?? {};\n data[API_KEY_FIELD] = key;\n writeJsonFile(file, data, SECRET_FILE_MODE);\n return { value: key, source: \"file\", location: file };\n}\n\n/** 解析当前 profile 的 gateway token(按 config.auth.tokenRef)。 */\nexport function resolveGatewayToken(config: YoooclawConfig): ResolvedRef {\n return resolveRef(config.auth.tokenRef);\n}\n\n/** 写入/轮换 gateway token(按 config.auth.tokenRef 的 scheme)。 */\nexport function writeGatewayToken(config: YoooclawConfig, value: string): ResolvedRef {\n return writeRef(config.auth.tokenRef, value);\n}\n\n/** 生成一个随机 token(hex)。 */\nexport function generateToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"hex\");\n}\n",
17
+ "/**\n * OS keychain 适配(可选加固,默认不强制)。\n *\n * - macOS:`security`(generic password)\n * - Linux:`secret-tool`(libsecret / Secret Service)\n * - Windows:暂无可明文取回的内置 CLI → 视为不可用,调用方降级到文件\n *\n * 任何工具缺失 / 调用失败都返回 `unavailable`,绝不抛崩溃,保证 CI 无 keychain 时的确定性。\n */\nimport { spawnSync } from \"node:child_process\";\nimport { platform } from \"node:os\";\n\nexport interface KeychainResult {\n available: boolean;\n value?: string;\n}\n\nfunction hasCommand(cmd: string): boolean {\n const probe = spawnSync(process.platform === \"win32\" ? \"where\" : \"which\", [cmd], {\n encoding: \"utf-8\",\n });\n return probe.status === 0;\n}\n\n/** keychain 在当前平台是否可用(工具存在)。 */\nexport function keychainAvailable(): boolean {\n switch (platform()) {\n case \"darwin\":\n return hasCommand(\"security\");\n case \"linux\":\n return hasCommand(\"secret-tool\");\n default:\n return false;\n }\n}\n\n/** 读取 keychain 条目;不可用或未命中返回 { available, value: undefined }。 */\nexport function keychainGet(service: string, account: string): KeychainResult {\n switch (platform()) {\n case \"darwin\": {\n if (!hasCommand(\"security\")) return { available: false };\n const r = spawnSync(\n \"security\",\n [\"find-generic-password\", \"-s\", service, \"-a\", account, \"-w\"],\n { encoding: \"utf-8\" },\n );\n if (r.status !== 0) return { available: true, value: undefined };\n return { available: true, value: r.stdout.replace(/\\n$/, \"\") };\n }\n case \"linux\": {\n if (!hasCommand(\"secret-tool\")) return { available: false };\n const r = spawnSync(\n \"secret-tool\",\n [\"lookup\", \"service\", service, \"account\", account],\n { encoding: \"utf-8\" },\n );\n if (r.status !== 0) return { available: true, value: undefined };\n return { available: true, value: r.stdout.replace(/\\n$/, \"\") };\n }\n default:\n return { available: false };\n }\n}\n\n/** 写入 keychain 条目;返回是否成功。 */\nexport function keychainSet(\n service: string,\n account: string,\n value: string,\n): boolean {\n switch (platform()) {\n case \"darwin\": {\n if (!hasCommand(\"security\")) return false;\n const r = spawnSync(\n \"security\",\n [\"add-generic-password\", \"-U\", \"-s\", service, \"-a\", account, \"-w\", value],\n { encoding: \"utf-8\" },\n );\n return r.status === 0;\n }\n case \"linux\": {\n if (!hasCommand(\"secret-tool\")) return false;\n const r = spawnSync(\n \"secret-tool\",\n [\"store\", \"--label\", `${service}:${account}`, \"service\", service, \"account\", account],\n { encoding: \"utf-8\", input: value },\n );\n return r.status === 0;\n }\n default:\n return false;\n }\n}\n",
18
+ "/**\n * 凭据抽象引用(`*Ref`)解析与写入。\n *\n * 支持 scheme(PRD「config.json 结构」):\n * - env:<VAR> 从环境变量读(最高优先级覆盖)\n * - file:<path>#<jsonField> 从 JSON 文件某字段读/写(默认落点,0600)\n * - keychain:<service>/<acct> 从 OS keychain 读/写(可选加固)\n * - inline:<base64> 直接内嵌(既不支持 keychain 也不便用文件时)\n */\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { readJsonFile, writeJsonFile, SECRET_FILE_MODE } from \"../fs-utils.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { keychainGet, keychainSet } from \"./keychain.js\";\n\nexport type RefSource = \"env\" | \"file\" | \"keychain\" | \"inline\";\n\nexport interface ResolvedRef {\n value?: string;\n source: RefSource;\n /** file: scheme 时的具体路径,用于错误诊断。 */\n location?: string;\n}\n\nfunction expandHome(path: string): string {\n if (path === \"~\") return homedir();\n if (path.startsWith(\"~/\")) return join(homedir(), path.slice(2));\n return path;\n}\n\ninterface ParsedFileRef {\n path: string;\n field: string;\n}\ninterface ParsedKeychainRef {\n service: string;\n account: string;\n}\n\nfunction parseFileRef(rest: string): ParsedFileRef {\n const hashIdx = rest.lastIndexOf(\"#\");\n if (hashIdx < 0) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `file: 引用缺少 #字段:${rest}`,\n { hint: \"格式应为 file:<path>#<jsonField>\" },\n );\n }\n return {\n path: expandHome(rest.slice(0, hashIdx)),\n field: rest.slice(hashIdx + 1),\n };\n}\n\nfunction parseKeychainRef(rest: string): ParsedKeychainRef {\n const slashIdx = rest.indexOf(\"/\");\n if (slashIdx < 0) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `keychain: 引用缺少 /account:${rest}`,\n { hint: \"格式应为 keychain:<service>/<account>\" },\n );\n }\n return {\n service: rest.slice(0, slashIdx),\n account: rest.slice(slashIdx + 1),\n };\n}\n\n/** 解析一个 ref,返回当前值(可能 undefined)与来源。 */\nexport function resolveRef(ref: string): ResolvedRef {\n const colonIdx = ref.indexOf(\":\");\n if (colonIdx < 0) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `非法凭据引用:${ref}`,\n { hint: \"支持 env: / file: / keychain: / inline:\" },\n );\n }\n const scheme = ref.slice(0, colonIdx);\n const rest = ref.slice(colonIdx + 1);\n\n switch (scheme) {\n case \"env\": {\n const value = process.env[rest]?.trim();\n return { source: \"env\", value: value || undefined, location: rest };\n }\n case \"file\": {\n const { path, field } = parseFileRef(rest);\n const data = readJsonFile<Record<string, unknown>>(path);\n const value = data?.[field];\n return {\n source: \"file\",\n value: typeof value === \"string\" && value ? value : undefined,\n location: path,\n };\n }\n case \"keychain\": {\n const { service, account } = parseKeychainRef(rest);\n const r = keychainGet(service, account);\n return { source: \"keychain\", value: r.value, location: `${service}/${account}` };\n }\n case \"inline\": {\n const decoded = Buffer.from(rest, \"base64\").toString(\"utf-8\");\n return { source: \"inline\", value: decoded || undefined };\n }\n default:\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `不支持的凭据引用 scheme:${scheme}`,\n { hint: \"支持 env: / file: / keychain: / inline:\" },\n );\n }\n}\n\n/** 把值写入 ref 指向的后端。env/inline 不可持久写入(抛错)。 */\nexport function writeRef(ref: string, value: string): ResolvedRef {\n const colonIdx = ref.indexOf(\":\");\n const scheme = ref.slice(0, colonIdx);\n const rest = ref.slice(colonIdx + 1);\n\n switch (scheme) {\n case \"file\": {\n const { path, field } = parseFileRef(rest);\n const data = readJsonFile<Record<string, unknown>>(path) ?? {};\n data[field] = value;\n writeJsonFile(path, data, SECRET_FILE_MODE);\n return { source: \"file\", value, location: path };\n }\n case \"keychain\": {\n const { service, account } = parseKeychainRef(rest);\n if (!keychainSet(service, account, value)) {\n throw new YoooclawError(\n \"YOOOCLAW_KEYCHAIN_UNAVAILABLE\",\n `keychain 写入失败:${service}/${account}`,\n { hint: \"当前平台可能没有可用的 keychain 工具,请改用 file: 引用\" },\n );\n }\n return { source: \"keychain\", value, location: `${service}/${account}` };\n }\n case \"env\":\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n \"env: 引用无法持久化写入;请改用 file: 或 keychain:\",\n );\n case \"inline\":\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n \"inline: 引用需直接写进 config,不通过 writeRef\",\n );\n default:\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `不支持的凭据引用 scheme:${scheme}`,\n );\n }\n}\n",
19
+ "/**\n * config service —— init / show / set / unset。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { readJsonFile, ensureDir } from \"../fs-utils.js\";\nimport { readStdin, ask, confirm, isInteractive } from \"../prompt.js\";\nimport {\n configExists,\n loadConfig,\n saveConfig,\n coerceConfigValue,\n deepMerge,\n getByPath,\n setByPath,\n unsetByPath,\n maskConfig,\n} from \"../config/store.js\";\nimport { defaultConfig, defaultEvaluator, type YoooclawConfig } from \"../config/schema.js\";\nimport { writeGatewayToken, generateToken } from \"../credentials/store.js\";\n\ninterface InitOpts {\n nonInteractive?: boolean;\n fromFile?: string;\n force?: boolean;\n}\n\n/** 手机端配置摘要 + 关键路径,作为 init 的返回结果。 */\nfunction phoneSummary(ctx: CliContext, config: YoooclawConfig, token: string) {\n return {\n ok: true,\n profile: ctx.profile,\n daemon: {\n bind: config.daemon.bind,\n port: config.daemon.port,\n localUrl: `http://${config.daemon.bind}:${config.daemon.port}`,\n },\n relay: { url: config.relay.url, enabled: config.relay.enabled },\n gatewayToken: token,\n configPath: ctx.paths.config,\n hint: \"在手机 App 中填入上面的地址与 token;公网部署请用 cloudflared / tailscale serve 反代到 localUrl\",\n };\n}\n\nexport async function configInit(\n ctx: CliContext,\n _args: unknown[],\n opts: InitOpts,\n): Promise<unknown> {\n if (configExists(ctx.paths) && !opts.force) {\n throw new YoooclawError(\n \"YOOOCLAW_ALREADY_EXISTS\",\n `profile \\`${ctx.profile}\\` 已初始化`,\n { hint: \"加 --force 覆盖,或换一个 --profile\", checkedPaths: [ctx.paths.config] },\n );\n }\n\n ensureDir(ctx.paths.dir);\n let config = defaultConfig(ctx.paths.credentials);\n\n if (opts.nonInteractive || !isInteractive()) {\n if (!opts.fromFile) {\n throw new YoooclawError(\n \"YOOOCLAW_NOT_INTERACTIVE\",\n \"非交互模式必须提供 --from-file <config.json>(- 为 stdin)\",\n );\n }\n const raw = opts.fromFile === \"-\" ? await readStdin() : undefined;\n const imported = raw\n ? (JSON.parse(raw) as Partial<YoooclawConfig>)\n : readJsonFile<Partial<YoooclawConfig>>(opts.fromFile);\n if (!imported) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", `无法读取配置文件:${opts.fromFile}`);\n }\n config = deepMerge(config, imported);\n config.version = defaultConfig(ctx.paths.credentials).version;\n } else {\n config.daemon.bind = await ask(\"daemon 监听地址\", config.daemon.bind);\n config.daemon.port = Number(await ask(\"daemon 监听端口\", String(config.daemon.port)));\n config.relay.url = await ask(\"Relay 地址\", config.relay.url);\n config.relay.enabled = await confirm(\"启用 Relay 隧道?\", config.relay.enabled);\n const enableEval = await confirm(\"启用灯效 webhook 评估器?\", false);\n if (enableEval) {\n const evaluator = defaultEvaluator(ctx.paths.credentials);\n evaluator.webhookUrl = await ask(\"评估器 webhook URL\");\n config.lightRules.evaluator = evaluator;\n }\n }\n\n // 生成并落 gateway token(按 config.auth.tokenRef,默认 per-profile credentials.json)\n const token = generateToken();\n saveConfig(ctx.paths, config);\n writeGatewayToken(config, token);\n\n return phoneSummary(ctx, config, token);\n}\n\ninterface ShowOpts {\n showSecrets?: boolean;\n}\n\nexport async function configShow(\n ctx: CliContext,\n _args: unknown[],\n opts: ShowOpts,\n): Promise<unknown> {\n if (!configExists(ctx.paths)) {\n throw new YoooclawError(\n \"YOOOCLAW_CONFIG_INVALID\",\n `profile \\`${ctx.profile}\\` 尚未初始化`,\n { hint: \"先运行 yoooclaw config init\", checkedPaths: [ctx.paths.config] },\n );\n }\n const config = loadConfig(ctx.paths);\n if (opts.showSecrets) {\n if (!isInteractive()) {\n throw new YoooclawError(\n \"YOOOCLAW_NOT_INTERACTIVE\",\n \"--show-secrets 需要在 TTY 中运行\",\n );\n }\n if (!(await confirm(\"确认明文输出敏感字段?\", false))) {\n throw new YoooclawError(\"YOOOCLAW_CONFIRMATION_REQUIRED\", \"已取消\");\n }\n return config;\n }\n return maskConfig(config);\n}\n\nexport function configSet(\n ctx: CliContext,\n args: unknown[],\n _opts: unknown,\n): unknown {\n const [key, value] = args as [string, string];\n if (key === \"version\") {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"version 字段不可修改\");\n }\n const config = loadConfig(ctx.paths) as unknown as Record<string, unknown>;\n setByPath(config, key, coerceConfigValue(key, value));\n saveConfig(ctx.paths, config as unknown as YoooclawConfig);\n return { ok: true, key, value: getByPath(config, key) };\n}\n\nexport function configUnset(\n ctx: CliContext,\n args: unknown[],\n _opts: unknown,\n): unknown {\n const [key] = args as [string];\n const config = loadConfig(ctx.paths) as unknown as Record<string, unknown>;\n const removed = unsetByPath(config, key);\n if (removed) saveConfig(ctx.paths, config as unknown as YoooclawConfig);\n return { ok: true, key, removed };\n}\n",
20
+ "/**\n * profile service —— list / use / create / delete。\n */\nimport { existsSync, rmSync } from \"node:fs\";\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { writeFileAtomic } from \"../fs-utils.js\";\nimport { confirm } from \"../prompt.js\";\nimport {\n DEFAULT_PROFILE,\n activeProfilePath,\n listProfileNames,\n profilePaths,\n readActiveProfile,\n} from \"../paths.js\";\nimport { configExists } from \"../config/store.js\";\nimport { configInit } from \"./config.js\";\n\nexport function profileList(ctx: CliContext): unknown {\n const active = readActiveProfile() ?? DEFAULT_PROFILE;\n const names = listProfileNames();\n // active / default 即便目录还没建出来也列出来,避免空列表误导\n for (const implied of [active, DEFAULT_PROFILE]) {\n if (!names.includes(implied)) names.push(implied);\n }\n return names\n .sort((a, b) => a.localeCompare(b))\n .map((name) => ({\n name,\n active: name === active,\n initialized: configExists(profilePaths(name)),\n }));\n}\n\nexport function profileUse(_ctx: CliContext, args: unknown[]): unknown {\n const [name] = args as [string];\n const paths = profilePaths(name);\n if (!existsSync(paths.dir)) {\n throw new YoooclawError(\n \"YOOOCLAW_PROFILE_NOT_FOUND\",\n `profile \\`${name}\\` 不存在`,\n { hint: \"用 yoooclaw profile create 新建\", checkedPaths: [paths.dir] },\n );\n }\n writeFileAtomic(activeProfilePath(), `${name}\\n`);\n return { ok: true, active: name };\n}\n\nexport async function profileCreate(\n ctx: CliContext,\n args: unknown[],\n opts: Record<string, unknown>,\n): Promise<unknown> {\n const [name] = args as [string];\n const paths = profilePaths(name);\n if (configExists(paths)) {\n throw new YoooclawError(\n \"YOOOCLAW_ALREADY_EXISTS\",\n `profile \\`${name}\\` 已存在`,\n );\n }\n // 在目标 profile 的上下文里跑 init 向导\n const subCtx: CliContext = { ...ctx, profile: name, paths };\n return configInit(subCtx, [], opts as never);\n}\n\nexport async function profileDelete(\n ctx: CliContext,\n args: unknown[],\n opts: { yes?: boolean },\n): Promise<unknown> {\n const [name] = args as [string];\n const active = readActiveProfile() ?? DEFAULT_PROFILE;\n if (name === active) {\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n `不能删除当前 active profile \\`${name}\\``,\n { hint: \"先 yoooclaw profile use <其他 profile> 再删除\" },\n );\n }\n const paths = profilePaths(name);\n if (!existsSync(paths.dir)) {\n throw new YoooclawError(\"YOOOCLAW_PROFILE_NOT_FOUND\", `profile \\`${name}\\` 不存在`);\n }\n if (!opts.yes && !(await confirm(`确认删除 profile \\`${name}\\` 及其全部数据?`, false))) {\n throw new YoooclawError(\"YOOOCLAW_CONFIRMATION_REQUIRED\", \"已取消\");\n }\n rmSync(paths.dir, { recursive: true, force: true });\n return { ok: true, deleted: name };\n}\n",
21
+ "/**\n * daemon 进程锁(单实例保护)。\n *\n * daemon.lock 内容:{ pid, startedAt, bind, port, logLevel }。\n * 通过 `process.kill(pid, 0)` 探活;陈旧锁(进程已死)会被视为未运行。\n */\nimport { existsSync, rmSync } from \"node:fs\";\nimport type { ProfilePaths } from \"../paths.js\";\nimport { readJsonFile, writeJsonFile } from \"../fs-utils.js\";\n\nexport interface DaemonLock {\n pid: number;\n startedAt: string;\n bind: string;\n port: number;\n logLevel?: string;\n}\n\n/** 进程是否存活(signal 0 探测)。 */\nexport function isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n // EPERM = 存在但无权限(仍算存活);ESRCH = 不存在\n return (err as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n\nexport function readLock(paths: ProfilePaths): DaemonLock | undefined {\n if (!existsSync(paths.daemonLock)) return undefined;\n return readJsonFile<DaemonLock>(paths.daemonLock);\n}\n\nexport interface DaemonRunningState {\n running: boolean;\n lock?: DaemonLock;\n /** 锁存在但进程已死。 */\n stale: boolean;\n}\n\nexport function daemonState(paths: ProfilePaths): DaemonRunningState {\n const lock = readLock(paths);\n if (!lock) return { running: false, stale: false };\n const alive = isProcessAlive(lock.pid);\n return { running: alive, lock, stale: !alive };\n}\n\nexport function writeLock(paths: ProfilePaths, lock: DaemonLock): void {\n writeJsonFile(paths.daemonLock, lock);\n}\n\nexport function removeLock(paths: ProfilePaths): void {\n rmSync(paths.daemonLock, { force: true });\n}\n",
22
+ "/**\n * daemon ↔ CLI 客户端的内部 RPC(localhost HTTP)。\n *\n * 鉴权:从 config.auth.tokenRef 解析 gateway token,加 `Authorization: Bearer`。\n * daemon 未运行(连接被拒)时统一抛 YOOOCLAW_DAEMON_NOT_RUNNING。\n */\nimport type { ProfilePaths } from \"../paths.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { loadConfig } from \"../config/store.js\";\nimport { resolveGatewayToken } from \"../credentials/store.js\";\nimport { daemonState } from \"./lock.js\";\n\nexport interface DaemonClientOptions {\n /** 覆盖 base URL(默认按 lock / config 推导)。 */\n baseUrl?: string;\n timeoutMs?: number;\n}\n\nexport class DaemonClient {\n readonly baseUrl: string;\n private readonly token?: string;\n private readonly timeoutMs: number;\n\n constructor(\n private readonly paths: ProfilePaths,\n opts: DaemonClientOptions = {},\n ) {\n const config = loadConfig(paths);\n const state = daemonState(paths);\n const bind = state.lock?.bind ?? config.daemon.bind;\n // 0.0.0.0 监听时,本机用 127.0.0.1 连接\n const host = bind === \"0.0.0.0\" ? \"127.0.0.1\" : bind;\n const port = state.lock?.port ?? config.daemon.port;\n this.baseUrl = opts.baseUrl ?? `http://${host}:${port}`;\n this.token = resolveGatewayToken(config).value;\n this.timeoutMs = opts.timeoutMs ?? 10_000;\n }\n\n async request<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<{ status: number; body: T }> {\n const headers: Record<string, string> = { ...extraHeaders };\n if (this.token) headers[\"Authorization\"] = `Bearer ${this.token}`;\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"Content-Type\"] ??= \"application/json\";\n payload = typeof body === \"string\" ? body : JSON.stringify(body);\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n let res: Response;\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: payload,\n signal: controller.signal,\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ECONNREFUSED\" || (err as Error).name === \"AbortError\") {\n throw new YoooclawError(\n \"YOOOCLAW_DAEMON_NOT_RUNNING\",\n \"daemon 未启动或无响应\",\n { hint: \"先执行 yoooclaw daemon start\", baseUrl: this.baseUrl },\n );\n }\n throw new YoooclawError(\"YOOOCLAW_NETWORK_ERROR\", `调用 daemon 失败:${(err as Error).message}`);\n } finally {\n clearTimeout(timer);\n }\n\n const text = await res.text();\n let parsed: unknown = text;\n if (text) {\n try {\n parsed = JSON.parse(text);\n } catch {\n /* 非 JSON 响应原样返回 */\n }\n }\n if (res.status === 401 || res.status === 403) {\n throw new YoooclawError(\"YOOOCLAW_UNAUTHORIZED\", \"daemon 拒绝鉴权(token 不一致)\", {\n status: res.status,\n });\n }\n return { status: res.status, body: parsed as T };\n }\n\n get<T = unknown>(path: string): Promise<{ status: number; body: T }> {\n return this.request<T>(\"GET\", path);\n }\n\n post<T = unknown>(path: string, body?: unknown): Promise<{ status: number; body: T }> {\n return this.request<T>(\"POST\", path, body);\n }\n}\n\n/** 确保 daemon 在运行,否则抛 DAEMON_NOT_RUNNING(用于 🟡 命令前置检查)。 */\nexport function assertDaemonRunning(paths: ProfilePaths): void {\n const state = daemonState(paths);\n if (!state.running) {\n throw new YoooclawError(\n \"YOOOCLAW_DAEMON_NOT_RUNNING\",\n \"daemon 未运行\",\n { hint: \"先执行 yoooclaw daemon start\", stale: state.stale },\n );\n }\n}\n",
23
+ "/**\n * auth service —— set-api-key / status / token-rotate / check。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { readStdin } from \"../prompt.js\";\nimport { loadConfig, configExists } from \"../config/store.js\";\nimport {\n resolveApiKey,\n setApiKey,\n resolveGatewayToken,\n writeGatewayToken,\n generateToken,\n} from \"../credentials/store.js\";\nimport { daemonState } from \"../daemon/lock.js\";\nimport { DaemonClient, assertDaemonRunning } from \"../daemon/client.js\";\n\nfunction mask(value: string | undefined): string | undefined {\n if (!value) return undefined;\n if (value.length <= 8) return \"***\";\n return `${value.slice(0, 4)}***${value.slice(-4)}`;\n}\n\nexport async function authSetApiKey(\n ctx: CliContext,\n args: unknown[],\n opts: { keychain?: boolean },\n): Promise<unknown> {\n let [key] = args as [string];\n if (key === \"-\") {\n key = (await readStdin()).trim();\n }\n if (!key) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"api-key 不能为空\");\n }\n const result = setApiKey(key, Boolean(opts.keychain));\n return {\n ok: true,\n source: result.source,\n location: result.location,\n masked: mask(result.value),\n hint: \"插件 / CLI / daemon 共用同一份;daemon 在跑时会经文件 watch 热生效\",\n };\n}\n\nexport function authStatus(ctx: CliContext): unknown {\n const apiKey = resolveApiKey();\n const config = configExists(ctx.paths) ? loadConfig(ctx.paths) : undefined;\n const token = config ? resolveGatewayToken(config) : undefined;\n const state = daemonState(ctx.paths);\n return {\n ok: true,\n profile: ctx.profile,\n apiKey: {\n present: Boolean(apiKey.value),\n source: apiKey.source,\n location: apiKey.location,\n masked: mask(apiKey.value),\n },\n gatewayToken: {\n present: Boolean(token?.value),\n source: token?.source,\n location: token?.location,\n masked: mask(token?.value),\n },\n daemon: {\n running: state.running,\n pid: state.lock?.pid,\n stale: state.stale,\n },\n };\n}\n\nexport function authTokenRotate(\n ctx: CliContext,\n _args: unknown[],\n opts: { length?: string },\n): unknown {\n if (!configExists(ctx.paths)) {\n throw new YoooclawError(\"YOOOCLAW_CONFIG_INVALID\", `profile \\`${ctx.profile}\\` 尚未初始化`, {\n hint: \"先运行 yoooclaw config init\",\n });\n }\n const config = loadConfig(ctx.paths);\n const bytes = opts.length ? Number(opts.length) : 32;\n if (!Number.isInteger(bytes) || bytes < 16) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--length 至少 16 字节\");\n }\n const token = generateToken(bytes);\n const written = writeGatewayToken(config, token);\n const state = daemonState(ctx.paths);\n // daemon 在跑时尝试热重载(best-effort,失败不影响 token 已写入)\n let hotReload: string;\n if (state.running) {\n hotReload = \"daemon 在运行:请执行 yoooclaw daemon restart 使新 token 生效\";\n } else {\n hotReload = \"daemon 未运行:下次启动即用新 token\";\n }\n return {\n ok: true,\n token,\n source: written.source,\n location: written.location,\n hint: hotReload,\n };\n}\n\nexport async function authCheck(ctx: CliContext): Promise<unknown> {\n assertDaemonRunning(ctx.paths);\n const client = new DaemonClient(ctx.paths);\n const res = await client.get(\"/daemon/status\");\n return {\n ok: res.status >= 200 && res.status < 300,\n profile: ctx.profile,\n daemonReachable: true,\n status: res.status,\n daemon: res.body,\n };\n}\n",
24
+ "/**\n * 通知查询 —— 复用 phone-notifications 共享的匹配/收集逻辑,CLI 侧负责参数解析与错误。\n */\nimport { existsSync } from \"node:fs\";\nimport type { ProfilePaths } from \"../paths.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport {\n collectMatchingNotifications,\n type NotificationQueryOptions,\n type StoredNotification,\n} from \"../shared.js\";\n\nconst ISO_RE =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,3})?)?(Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseIso(value: string, name: string): number {\n if (!ISO_RE.test(value)) {\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n `${name} 必须是 ISO 8601 时间,例如 2026-03-01T09:00:00+08:00`,\n );\n }\n const ts = Date.parse(value);\n if (Number.isNaN(ts)) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", `${name} 不是合法时间`);\n }\n return ts;\n}\n\nfunction parseLimit(raw: string | undefined, fallback: number): number {\n if (raw === undefined) return fallback;\n if (!/^\\d+$/.test(raw) || Number(raw) <= 0) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--limit 必须是大于 0 的整数\");\n }\n return Number(raw);\n}\n\nexport interface RawQueryOpts {\n from?: string;\n to?: string;\n app?: string;\n sender?: string;\n conversationType?: string;\n keyword?: string;\n limit?: string;\n}\n\nexport function buildQueryOptions(\n opts: RawQueryOpts,\n defaultLimit = 100,\n): NotificationQueryOptions {\n if (\n opts.conversationType &&\n opts.conversationType !== \"group\" &&\n opts.conversationType !== \"private\"\n ) {\n throw new YoooclawError(\n \"YOOOCLAW_INVALID_ARGUMENT\",\n \"--conversation-type 只能是 group 或 private\",\n );\n }\n const fromTs = opts.from ? parseIso(opts.from, \"--from\") : null;\n const toTs = opts.to ? parseIso(opts.to, \"--to\") : null;\n if (fromTs !== null && toTs !== null && fromTs > toTs) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--from 不能晚于 --to\");\n }\n return {\n from: opts.from,\n to: opts.to,\n app: opts.app,\n sender: opts.sender,\n conversationType: opts.conversationType,\n keyword: opts.keyword,\n limit: parseLimit(opts.limit, defaultLimit),\n fromTs,\n toTs,\n fromDateKey: opts.from ? opts.from.slice(0, 10) : null,\n toDateKey: opts.to ? opts.to.slice(0, 10) : null,\n };\n}\n\n/** 收集匹配的通知;通知目录不存在时返回空数组(无 daemon / 尚无数据是正常态)。 */\nexport async function queryNotifications(\n paths: ProfilePaths,\n options: NotificationQueryOptions,\n): Promise<StoredNotification[]> {\n if (!existsSync(paths.notifications)) return [];\n return collectMatchingNotifications(paths.notifications, options);\n}\n",
25
+ "import { existsSync, readFileSync, readdirSync, mkdirSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { StoredNotification } from \"../notification/storage.js\";\n\n/**\n * Minimal Commander.js Command interface.\n * The real `Command` instance comes from the openclaw runtime at registration time;\n * we only declare the subset we use so that `commander` need not be a direct dep.\n */\nexport interface CliCommand {\n command(nameAndArgs: string): CliCommand;\n description(str: string): CliCommand;\n version(str: string, flags?: string, description?: string): CliCommand;\n option(flags: string, description: string, defaultValue?: string): CliCommand;\n requiredOption(flags: string, description: string): CliCommand;\n action(fn: (...args: any[]) => void | Promise<void>): CliCommand;\n}\n\nexport interface CliContext {\n workspaceDir?: string;\n stateDir?: string;\n}\n\n/** Resolve the notifications storage directory (stateDir → workspace fallback) */\nexport function resolveNotificationsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"notifications\",\n );\n if (existsSync(dir)) return dir;\n }\n if (ctx.workspaceDir) {\n const dir = join(ctx.workspaceDir, \"notifications\");\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** List available date keys (YYYY-MM-DD) sorted descending */\nexport function listDateKeys(dir: string): string[] {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.json$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Read notifications for a specific date */\nexport function readDateFile(\n dir: string,\n dateKey: string,\n): StoredNotification[] {\n const filePath = join(dir, `${dateKey}.json`);\n if (!existsSync(filePath)) return [];\n try {\n return JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch {\n return [];\n }\n}\n\n/** Format today as YYYY-MM-DD */\nexport function today(): string {\n return formatDate(new Date());\n}\n\n/** Format a Date as YYYY-MM-DD */\nexport function formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${day}`;\n}\n\n/** Get date N days ago as YYYY-MM-DD */\nexport function daysAgo(n: number): string {\n const d = new Date();\n d.setDate(d.getDate() - n);\n return formatDate(d);\n}\n\n/** Filter date keys to a [from, to] range (inclusive) */\nexport function filterDateRange(\n keys: string[],\n from: string,\n to: string,\n): string[] {\n return keys.filter((k) => k >= from && k <= to);\n}\n\n/** Parse an ISO 8601 timestamp and exit with a CLI error on invalid input */\nexport function parseIsoTime(\n value: string,\n optionName: \"--from\" | \"--to\",\n): number {\n const isoPattern =\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,3})?)?(Z|[+-]\\d{2}:\\d{2})$/;\n if (!isoPattern.test(value)) {\n exitError(\n \"INVALID_TIME\",\n `${optionName} 必须是 ISO 8601 时间,例如 2026-03-01T09:00:00+08:00`,\n );\n }\n\n const ts = Date.parse(value);\n if (Number.isNaN(ts)) {\n exitError(\n \"INVALID_TIME\",\n `${optionName} 不是合法时间,例如 2026-03-01T09:00:00+08:00`,\n );\n }\n return ts;\n}\n\n/** Sort notifications by timestamp descending (newest first) */\nexport function sortNotificationsByTimestampDesc(\n items: StoredNotification[],\n): StoredNotification[] {\n return items.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));\n}\n\nconst APP_ALIAS_GROUPS = [\n [\"微信\", \"wechat\", \"weixin\", \"com.tencent.mm\", \"com.tencent.xin\"],\n [\"企业微信\", \"wecom\", \"wxwork\", \"com.tencent.wework\"],\n [\"飞书\", \"feishu\", \"lark\", \"com.ss.android.lark\", \"com.bytedance.ee.lark\", \"com.larksuite.suite\"],\n [\"钉钉\", \"dingtalk\", \"com.alibaba.android.rimet\"],\n [\"qq\", \"腾讯qq\", \"com.tencent.mobileqq\"],\n];\n\nfunction normalizeLookupText(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction appAliasGroup(value: string): string[] | null {\n const normalized = normalizeLookupText(value);\n if (!normalized) return null;\n return APP_ALIAS_GROUPS.find((group) =>\n group.some((candidate) => normalizeLookupText(candidate) === normalized),\n ) ?? null;\n}\n\nexport function matchesNotificationAppFilter(\n item: StoredNotification,\n app: string,\n): boolean {\n const filter = normalizeLookupText(app);\n if (!filter) return true;\n\n const candidates = [item.appName, item.appDisplayName]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0);\n if (candidates.some((candidate) => normalizeLookupText(candidate) === filter)) {\n return true;\n }\n\n const filterGroup = appAliasGroup(app);\n if (!filterGroup) return false;\n return candidates.some((candidate) => appAliasGroup(candidate) === filterGroup);\n}\n\n/** Async version of listDateKeys */\nexport async function listDateKeysAsync(dir: string): Promise<string[]> {\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.json$/;\n const keys: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort().reverse();\n}\n\n/** Async version of readDateFile */\nexport async function readDateFileAsync(\n dir: string,\n dateKey: string,\n): Promise<StoredNotification[]> {\n const filePath = join(dir, `${dateKey}.json`);\n if (!existsSync(filePath)) return [];\n try {\n const content = await readFile(filePath, \"utf-8\");\n return JSON.parse(content);\n } catch {\n return [];\n }\n}\n\n/** Write progress message to stderr (visible to caller, won't pollute JSON stdout) */\nexport function progress(message: string): void {\n process.stderr.write(message + \"\\n\");\n}\n\n/** Print JSON result to stdout */\nexport function output(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\n/** Print error JSON and exit with code 1 */\nexport function exitError(code: string, message: string): never {\n output({ ok: false, error: { code, message } });\n process.exit(1);\n}\n\n/** Resolve the recordings storage directory (stateDir → workspace fallback) */\nexport function resolveRecordingsDir(ctx: CliContext): string | null {\n if (ctx.stateDir) {\n const dir = join(\n ctx.stateDir,\n \"plugins\",\n \"phone-notifications\",\n \"recordings\",\n );\n if (existsSync(dir)) return dir;\n }\n if (ctx.workspaceDir) {\n const dir = join(ctx.workspaceDir, \"recordings\");\n if (existsSync(dir)) return dir;\n }\n return null;\n}\n\n/** Recording index entry (mirrors RecordingIndexEntry from storage.ts) */\nexport interface CliRecordingEntry {\n id: string;\n metadata: {\n name: string;\n duration_sec: number;\n file_size_bytes: number;\n created_at: string;\n transfer_status: string;\n [key: string]: unknown;\n };\n status: string;\n audioFile?: string;\n srtFile?: string;\n transcriptDataFile?: string;\n transcriptFile?: string;\n summaryFile?: string;\n title?: string;\n lastError?: string;\n ingestedAt: string;\n updatedAt: string;\n}\n\n/** Resolve the asr-config.json path; creates parent dirs if needed */\nexport function resolveAsrConfigPath(ctx: CliContext): string {\n let base: string;\n if (ctx.stateDir) {\n base = join(ctx.stateDir, \"plugins\", \"phone-notifications\", \"recordings\");\n } else if (ctx.workspaceDir) {\n base = join(ctx.workspaceDir, \"recordings\");\n } else {\n exitError(\n \"STORAGE_UNAVAILABLE\",\n \"无法确定录音存储目录:stateDir 和 workspaceDir 均未设置\",\n );\n }\n mkdirSync(base, { recursive: true });\n return join(base, \"asr-config.json\");\n}\n\n/** Mask an API key, keeping first 4 and last 4 chars */\nexport function maskApiKey(key: string): string {\n if (key.length <= 8) return \"***\";\n return `${key.slice(0, 4)}***${key.slice(-4)}`;\n}\n\n/** Read recording index.json */\nexport function readRecordingIndex(\n dir: string,\n): CliRecordingEntry[] {\n const indexPath = join(dir, \"index.json\");\n if (!existsSync(indexPath)) return [];\n try {\n const raw = JSON.parse(readFileSync(indexPath, \"utf-8\"));\n return Array.isArray(raw?.recordings) ? raw.recordings : [];\n } catch {\n return [];\n }\n}\n",
26
+ "import type { StoredNotification } from \"../notification/storage.js\";\nimport {\n exitError,\n listDateKeysAsync,\n parseIsoTime,\n readDateFileAsync,\n sortNotificationsByTimestampDesc,\n matchesNotificationAppFilter,\n} from \"./helpers.js\";\n\nexport interface RawNotificationQueryOptions {\n from?: string;\n to?: string;\n app?: string;\n sender?: string;\n conversationType?: string;\n keyword?: string;\n limit?: string;\n}\n\nexport interface NotificationQueryOptions {\n from?: string;\n to?: string;\n app?: string;\n sender?: string;\n conversationType?: string;\n keyword?: string;\n limit: number;\n fromTs: number | null;\n toTs: number | null;\n fromDateKey: string | null;\n toDateKey: string | null;\n}\n\nexport function parsePositiveIntegerOption(\n rawValue: string | undefined,\n defaultValue: number,\n optionName: string,\n errorCode: string,\n): number {\n const value = rawValue && rawValue.length > 0 ? rawValue : String(defaultValue);\n if (!/^\\d+$/.test(value)) {\n exitError(errorCode, `${optionName} 必须是大于 0 的整数`);\n }\n\n const parsed = Number.parseInt(value, 10);\n if (parsed <= 0) {\n exitError(errorCode, `${optionName} 必须是大于 0 的整数`);\n }\n return parsed;\n}\n\nexport function parseNotificationQueryOptions(\n opts: RawNotificationQueryOptions,\n defaultLimit = 100,\n): NotificationQueryOptions {\n const limit = parsePositiveIntegerOption(\n opts.limit,\n defaultLimit,\n \"--limit\",\n \"INVALID_LIMIT\",\n );\n\n if (\n opts.conversationType\n && opts.conversationType !== \"group\"\n && opts.conversationType !== \"private\"\n ) {\n exitError(\n \"INVALID_CONVERSATION_TYPE\",\n \"--conversation-type 只能是 group 或 private\",\n );\n }\n\n const hasFrom = typeof opts.from === \"string\" && opts.from.length > 0;\n const hasTo = typeof opts.to === \"string\" && opts.to.length > 0;\n const fromTs = hasFrom ? parseIsoTime(opts.from!, \"--from\") : null;\n const toTs = hasTo ? parseIsoTime(opts.to!, \"--to\") : null;\n\n if (fromTs !== null && toTs !== null && fromTs > toTs) {\n exitError(\"INVALID_TIME_RANGE\", \"--from 不能晚于 --to\");\n }\n\n return {\n from: opts.from,\n to: opts.to,\n app: opts.app,\n sender: opts.sender,\n conversationType: opts.conversationType,\n keyword: opts.keyword,\n limit,\n fromTs,\n toTs,\n fromDateKey: hasFrom ? opts.from!.slice(0, 10) : null,\n toDateKey: hasTo ? opts.to!.slice(0, 10) : null,\n };\n}\n\nexport function matchesNotificationQuery(\n item: StoredNotification,\n opts: NotificationQueryOptions,\n): boolean {\n if (opts.app && !matchesNotificationAppFilter(item, opts.app)) return false;\n if (\n opts.conversationType\n && item.conversationType !== opts.conversationType\n ) {\n return false;\n }\n\n const senderHaystack = [item.senderName, item.title]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\"\\n\");\n if (opts.sender && !senderHaystack.includes(opts.sender)) return false;\n\n const keywordHaystack = [\n item.title,\n item.content,\n item.senderName,\n item.conversationName,\n ]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\"\\n\");\n if (opts.keyword && !keywordHaystack.includes(opts.keyword)) return false;\n\n const itemTs = Date.parse(item.timestamp);\n if (Number.isNaN(itemTs)) return false;\n if (opts.fromTs !== null && itemTs < opts.fromTs) return false;\n if (opts.toTs !== null && itemTs > opts.toTs) return false;\n\n return true;\n}\n\nexport async function collectMatchingNotifications(\n dir: string,\n opts: NotificationQueryOptions,\n): Promise<StoredNotification[]> {\n const keys = await listDateKeysAsync(dir);\n const results: StoredNotification[] = [];\n const canStopAfterLimit = opts.fromTs === null && opts.toTs === null;\n\n for (const dateKey of keys) {\n if (opts.fromDateKey && dateKey < opts.fromDateKey) continue;\n if (opts.toDateKey && dateKey > opts.toDateKey) continue;\n\n const items = sortNotificationsByTimestampDesc([\n ...(await readDateFileAsync(dir, dateKey)),\n ]);\n for (const item of items) {\n if (!matchesNotificationQuery(item, opts)) continue;\n results.push(item);\n if (canStopAfterLimit && results.length >= opts.limit) {\n return results;\n }\n }\n }\n\n return sortNotificationsByTimestampDesc(results).slice(0, opts.limit);\n}\n",
27
+ "import {\n accessSync,\n mkdirSync,\n appendFileSync,\n readdirSync,\n readFileSync,\n writeFileSync,\n existsSync,\n rmSync,\n constants,\n} from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { PluginConfig, RawNotification } from \"../types.js\";\nimport { normalizeFeishuFields } from \"./feishu-normalize.js\";\n\ninterface Logger {\n info: (message: string) => void;\n warn: (message: string) => void;\n}\n\nexport type NotificationConversationType = \"private\" | \"group\";\n\nexport interface StorageContext {\n stateDir: string;\n workspaceDir?: string;\n}\n\n/** Stored notification entry (JSON format, append-only) */\nexport interface StoredNotification {\n /** 包名 */\n appName: string;\n /** 应用显示名(由映射补全),缺省时与 appName 一致 */\n appDisplayName?: string;\n title: string;\n content: string;\n /** ISO 8601 with timezone, e.g. \"2026-03-02T08:30:00+08:00\" */\n timestamp: string;\n /**\n * 结构化发送人。当前主要用于飞书消息:\n * iOS 通知里 title 通常是发送人,subtitle 用来区分群聊名。\n */\n senderName?: string;\n /** 结构化会话类型。当前主要用于飞书消息区分群聊/私聊。 */\n conversationType?: NotificationConversationType;\n /** 结构化会话名。当前主要用于飞书群聊名(通常来自 subtitle)。 */\n conversationName?: string;\n}\n\nconst NOTIFICATION_DIR_NAME = \"notifications\";\nconst ID_INDEX_DIR_NAME = \".ids\";\nconst CONTENT_KEY_INDEX_DIR_NAME = \".keys\";\n\nexport interface NotificationIngestResult {\n received: number;\n ingested: number;\n dedupedById: number;\n dedupedByContent: number;\n invalid: number;\n /**\n * 本次 ingest 实际新写入的条目(去重 / 非法之后的产物)。\n * 用于后续事件驱动链路(如 light-rule agent 评估)拿到本次新增的通知列表,\n * 不需要重新读盘。\n */\n inserted: StoredNotification[];\n}\n\ntype WriteOutcome =\n | { kind: \"ingested\"; entry: StoredNotification }\n | { kind: \"dedupedById\" }\n | { kind: \"dedupedByContent\" }\n | { kind: \"invalid\" };\n\nexport function getStateFallbackNotificationDir(stateDir: string): string {\n return join(stateDir, \"plugins\", \"phone-notifications\", NOTIFICATION_DIR_NAME);\n}\n\nfunction computeLagMs(timestamp: string | undefined): number | null {\n if (!timestamp) return null;\n const t = new Date(timestamp).getTime();\n if (Number.isNaN(t)) return null;\n return Date.now() - t;\n}\n\nfunction buildFallbackContent(n: RawNotification): string {\n const body = n.body?.trim();\n if (body) {\n return body;\n }\n\n const fallback: string[] = [];\n if (n.category) {\n fallback.push(`category:${n.category}`);\n }\n if (n.metadata && Object.keys(n.metadata).length > 0) {\n fallback.push(`metadata:${JSON.stringify(n.metadata)}`);\n }\n return fallback.join(\" ; \") || \"-\";\n}\n\nfunction ensureWritableDirectory(dir: string): boolean {\n try {\n mkdirSync(dir, { recursive: true });\n accessSync(dir, constants.R_OK | constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolveNotificationStorageDir(\n ctx: StorageContext,\n logger: Pick<Logger, \"info\" | \"warn\">,\n): string {\n // 优先使用 stateDir(插件私有稳定路径),避免通知随 workspace 切换而分散\n const stateNotifDir = getStateFallbackNotificationDir(ctx.stateDir);\n\n if (ensureWritableDirectory(stateNotifDir)) {\n logger.info(`通知将写入 stateDir 路径: ${stateNotifDir}`);\n return stateNotifDir;\n }\n\n // stateDir 不可用时回退到 workspaceDir\n if (ctx.workspaceDir) {\n const workspaceDir = join(ctx.workspaceDir, NOTIFICATION_DIR_NAME);\n if (ensureWritableDirectory(workspaceDir)) {\n logger.warn(\n `stateDir 不可用,通知已回退到 workspace 路径: ${workspaceDir}`,\n );\n return workspaceDir;\n }\n }\n\n throw new Error(`通知存储目录不可用: ${stateNotifDir}`);\n}\n\n/** 包名 → 应用显示名(异步,未命中时内部可拉取后返回);不提供则落库仅用 appName */\nexport type ResolveDisplayName = (packageName: string) => Promise<string>;\n\nexport class NotificationStorage {\n private dir: string;\n private idIndexDir: string;\n private contentKeyIndexDir: string;\n private idCache = new Map<string, Set<string>>();\n private contentKeyCache = new Map<string, Set<string>>();\n private dateWriteChains = new Map<string, Promise<void>>();\n private resolveDisplayName: ResolveDisplayName | undefined;\n\n constructor(\n dir: string,\n private config: PluginConfig,\n private logger: Logger,\n resolveDisplayName?: ResolveDisplayName,\n ) {\n this.dir = dir;\n this.idIndexDir = join(dir, ID_INDEX_DIR_NAME);\n this.contentKeyIndexDir = join(dir, CONTENT_KEY_INDEX_DIR_NAME);\n this.resolveDisplayName = resolveDisplayName;\n }\n\n async init() {\n mkdirSync(this.dir, { recursive: true });\n mkdirSync(this.idIndexDir, { recursive: true });\n rmSync(this.contentKeyIndexDir, { recursive: true, force: true });\n mkdirSync(this.contentKeyIndexDir, { recursive: true });\n }\n\n async ingest(\n items: RawNotification[],\n ingestId?: string,\n ): Promise<NotificationIngestResult> {\n const result: NotificationIngestResult = {\n received: items.length,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n inserted: [],\n };\n\n const traceTag = ingestId ? `[${ingestId}]` : \"\";\n for (const n of items) {\n const outcome = await this.writeNotification(n);\n const lagMs = computeLagMs(n.timestamp);\n const lagPart = lagMs === null ? \"lag=?\" : `lag=${lagMs}ms`;\n this.logger.info(\n `ingest${traceTag}: app=${n.app ?? \"Unknown\"} id=${n.id ?? \"-\"} ts=${n.timestamp} ${lagPart} outcome=${outcome.kind}`,\n );\n switch (outcome.kind) {\n case \"ingested\":\n result.ingested += 1;\n result.inserted.push(outcome.entry);\n break;\n case \"dedupedById\":\n result.dedupedById += 1;\n break;\n case \"dedupedByContent\":\n result.dedupedByContent += 1;\n break;\n case \"invalid\":\n result.invalid += 1;\n break;\n }\n }\n this.prune();\n return result;\n }\n\n private async writeNotification(n: RawNotification): Promise<WriteOutcome> {\n const ts = new Date(n.timestamp);\n if (Number.isNaN(ts.getTime())) {\n this.logger.warn(`忽略非法 timestamp 的通知: ${n.id}`);\n return { kind: \"invalid\" };\n }\n\n const dateKey = this.formatDate(ts);\n const filePath = join(this.dir, `${dateKey}.json`);\n const normalizedId = typeof n.id === \"string\" ? n.id.trim() : \"\";\n const entry = this.buildStoredNotification(n);\n\n return this.withDateWriteLock(dateKey, async () => {\n if (normalizedId && this.hasNotificationId(dateKey, normalizedId)) {\n return { kind: \"dedupedById\" };\n }\n\n if (this.hasNotificationContentKey(dateKey, filePath, entry)) {\n return { kind: \"dedupedByContent\" };\n }\n\n const appDisplayName = this.resolveDisplayName\n ? await this.resolveDisplayName(entry.appName)\n : entry.appName;\n\n const storedEntry: StoredNotification = {\n ...entry,\n appDisplayName,\n };\n\n const arr = this.readStoredNotifications(filePath);\n arr.push(storedEntry);\n writeFileSync(filePath, JSON.stringify(arr, null, 2), \"utf-8\");\n\n if (normalizedId) {\n this.recordNotificationId(dateKey, normalizedId);\n }\n this.recordNotificationContentKey(dateKey, filePath, storedEntry);\n return { kind: \"ingested\", entry: storedEntry };\n });\n }\n\n private buildStoredNotification(n: RawNotification): StoredNotification {\n const appName = typeof n.app === \"string\" && n.app ? n.app : \"Unknown\";\n const feishu = normalizeFeishuFields(n);\n if (feishu) {\n return {\n appName,\n title: feishu.title,\n content: feishu.content || buildFallbackContent(n),\n timestamp: n.timestamp,\n ...feishu.structured,\n };\n }\n return {\n appName,\n title: typeof n.title === \"string\" ? n.title : \"\",\n content: buildFallbackContent(n),\n timestamp: n.timestamp,\n };\n }\n\n private formatDate(d: Date): string {\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, \"0\");\n const day = String(d.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n }\n\n private getIdIndexPath(dateKey: string): string {\n return join(this.idIndexDir, `${dateKey}.ids`);\n }\n\n private getIdSet(dateKey: string): Set<string> {\n const cached = this.idCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const idPath = this.getIdIndexPath(dateKey);\n const ids = new Set<string>();\n if (existsSync(idPath)) {\n const lines = readFileSync(idPath, \"utf-8\").split(/\\r?\\n/);\n for (const line of lines) {\n const id = line.trim();\n if (id) {\n ids.add(id);\n }\n }\n }\n\n this.idCache.set(dateKey, ids);\n return ids;\n }\n\n private hasNotificationId(dateKey: string, id: string): boolean {\n return this.getIdSet(dateKey).has(id);\n }\n\n private getContentKeyIndexPath(dateKey: string): string {\n return join(this.contentKeyIndexDir, `${dateKey}.keys`);\n }\n\n private getContentKeySet(dateKey: string, filePath: string): Set<string> {\n const cached = this.contentKeyCache.get(dateKey);\n if (cached) {\n return cached;\n }\n\n const keyPath = this.getContentKeyIndexPath(dateKey);\n const keys = new Set<string>();\n\n if (existsSync(filePath)) {\n for (const item of this.readStoredNotifications(filePath)) {\n keys.add(this.buildNotificationContentKey(item));\n }\n }\n\n if (keys.size > 0) {\n writeFileSync(keyPath, `${Array.from(keys).join(\"\\n\")}\\n`, \"utf-8\");\n } else if (existsSync(keyPath)) {\n rmSync(keyPath, { force: true });\n }\n\n this.contentKeyCache.set(dateKey, keys);\n return keys;\n }\n\n private hasNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\" | \"timestamp\">,\n ): boolean {\n return this.getContentKeySet(dateKey, filePath).has(\n this.buildNotificationContentKey(entry),\n );\n }\n\n private recordNotificationId(dateKey: string, id: string) {\n const ids = this.getIdSet(dateKey);\n if (ids.has(id)) {\n return;\n }\n\n appendFileSync(this.getIdIndexPath(dateKey), `${id}\\n`, \"utf-8\");\n ids.add(id);\n }\n\n private recordNotificationContentKey(\n dateKey: string,\n filePath: string,\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\" | \"timestamp\">,\n ) {\n const keys = this.getContentKeySet(dateKey, filePath);\n const key = this.buildNotificationContentKey(entry);\n\n if (keys.has(key)) {\n return;\n }\n\n appendFileSync(this.getContentKeyIndexPath(dateKey), `${key}\\n`, \"utf-8\");\n keys.add(key);\n }\n\n private buildNotificationContentKey(\n entry: Pick<StoredNotification, \"appName\" | \"title\" | \"content\" | \"timestamp\">,\n ): string {\n return createHash(\"sha256\")\n .update(entry.appName)\n .update(\"\\x1f\")\n .update(entry.title)\n .update(\"\\x1f\")\n .update(entry.content)\n .update(\"\\x1f\")\n .update(entry.timestamp)\n .digest(\"hex\");\n }\n\n private readStoredNotifications(filePath: string): StoredNotification[] {\n if (!existsSync(filePath)) {\n return [];\n }\n\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n private async withDateWriteLock<T>(\n dateKey: string,\n task: () => Promise<T>,\n ): Promise<T> {\n const previous = this.dateWriteChains.get(dateKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const chain = previous.then(() => current);\n this.dateWriteChains.set(dateKey, chain);\n\n await previous;\n try {\n return await task();\n } finally {\n release();\n if (this.dateWriteChains.get(dateKey) === chain) {\n this.dateWriteChains.delete(dateKey);\n }\n }\n }\n\n private prune() {\n const retentionDays = this.config.retentionDays;\n if (retentionDays === undefined) {\n return;\n }\n\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;\n const cutoffDate = this.formatDate(new Date(cutoffMs));\n\n this.pruneDataFiles(cutoffDate);\n this.pruneIdIndex(cutoffDate);\n this.pruneContentKeyIndex(cutoffDate);\n }\n\n /** Remove expired .json, legacy .md files, and legacy date directories */\n private pruneDataFiles(cutoffDate: string) {\n const dateFilePattern = /^(\\d{4}-\\d{2}-\\d{2})\\.(json|md)$/;\n const dateDirPattern = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n try {\n for (const entry of readdirSync(this.dir, { withFileTypes: true })) {\n if (entry.isFile()) {\n const match = dateFilePattern.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.dir, entry.name), { force: true });\n }\n } else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {\n rmSync(join(this.dir, entry.name), { recursive: true, force: true });\n }\n }\n } catch {\n // ignore\n }\n }\n\n /** Remove expired .ids index files */\n private pruneIdIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.idIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.ids$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.idIndexDir, entry.name), { force: true });\n this.idCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n private pruneContentKeyIndex(cutoffDate: string) {\n try {\n for (const entry of readdirSync(this.contentKeyIndexDir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const match = /^(\\d{4}-\\d{2}-\\d{2})\\.keys$/.exec(entry.name);\n if (match && match[1] < cutoffDate) {\n rmSync(join(this.contentKeyIndexDir, entry.name), { force: true });\n this.contentKeyCache.delete(match[1]);\n }\n }\n } catch {\n // ignore\n }\n }\n\n async close() {\n this.idCache.clear();\n this.contentKeyCache.clear();\n this.dateWriteChains.clear();\n }\n}\n",
28
+ "import type { RawNotification } from \"../types.js\";\nimport type { NotificationConversationType } from \"./storage.js\";\n\nexport interface FeishuStructuredFields {\n senderName?: string;\n conversationType?: NotificationConversationType;\n conversationName?: string;\n}\n\nexport interface FeishuNormalizedNotification {\n title: string;\n content: string;\n structured: FeishuStructuredFields;\n}\n\nfunction normalizeOptionalText(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction isFeishuApp(appName: string): boolean {\n const normalized = appName.trim().toLowerCase();\n if (!normalized) {\n return false;\n }\n return (\n normalized === \"飞书\"\n || normalized === \"feishu\"\n || normalized === \"lark\"\n || normalized === \"com.ss.android.lark\"\n || normalized === \"com.bytedance.ee.lark\"\n || normalized === \"com.larksuite.suite\"\n || normalized.includes(\"feishu\")\n || normalized.includes(\"lark\")\n || normalized.includes(\"飞书\")\n );\n}\n\nfunction isFeishuAppLabel(text: string): boolean {\n const t = text.trim().toLowerCase();\n return t === \"飞书\" || t === \"lark\" || t === \"feishu\";\n}\n\nfunction extractColonSender(body: string): string | undefined {\n if (!body) return undefined;\n const candidates = [body.indexOf(\":\"), body.indexOf(\":\")].filter((i) => i > 0);\n if (candidates.length === 0) return undefined;\n const idx = Math.min(...candidates);\n const senderName = body.slice(0, idx).trim();\n return senderName || undefined;\n}\n\nfunction findMetadataTextByKey(\n value: unknown,\n targetKey: string,\n depth = 0,\n): { found: boolean; value?: string } {\n if (!value || typeof value !== \"object\" || depth > 4) {\n return { found: false };\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const match = findMetadataTextByKey(item, targetKey, depth + 1);\n if (match.found) {\n return match;\n }\n }\n return { found: false };\n }\n\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n if (key.trim().toLowerCase() === targetKey) {\n return { found: true, value: normalizeOptionalText(child) };\n }\n }\n\n for (const child of Object.values(value as Record<string, unknown>)) {\n const match = findMetadataTextByKey(child, targetKey, depth + 1);\n if (match.found) {\n return match;\n }\n }\n\n return { found: false };\n}\n\nfunction deriveStructured(n: RawNotification): FeishuStructuredFields {\n const subtitle = findMetadataTextByKey(n.metadata, \"subtitle\");\n\n // iOS 路径:通知元数据带 subtitle key(群聊为群名,私聊为空)。\n if (subtitle.found) {\n const senderName = normalizeOptionalText(n.title);\n const structured: FeishuStructuredFields = {\n conversationType: subtitle.value ? \"group\" : \"private\",\n };\n if (senderName) {\n structured.senderName = senderName;\n }\n if (subtitle.value) {\n structured.conversationName = subtitle.value;\n }\n return structured;\n }\n\n // Android 路径:title 退化为 app 名(如 \"飞书\"),实际发送人在 body 里以 \"name: content\" 形式出现。\n const rawTitle = typeof n.title === \"string\" ? n.title : \"\";\n if (isFeishuAppLabel(rawTitle)) {\n const senderName = extractColonSender(n.body ?? \"\");\n if (senderName) {\n return {\n senderName,\n conversationType: \"private\",\n };\n }\n }\n\n return {};\n}\n\nfunction buildTitle(n: RawNotification, structured: FeishuStructuredFields): string {\n if (structured.conversationType === \"group\" && structured.conversationName) {\n return structured.conversationName;\n }\n // Android 私聊 title 是 app 名,用 body 解析出的 senderName 顶上去,跟 iOS 对齐。\n if (structured.conversationType === \"private\" && structured.senderName) {\n return structured.senderName;\n }\n return typeof n.title === \"string\" ? n.title : \"\";\n}\n\nfunction buildContent(n: RawNotification, structured: FeishuStructuredFields): string {\n const body = n.body?.trim();\n\n if (structured.conversationType === \"group\" && structured.senderName && body) {\n const half = `${structured.senderName}:`;\n const full = `${structured.senderName}:`;\n return body.startsWith(half) || body.startsWith(full)\n ? body\n : `${structured.senderName}: ${body}`;\n }\n\n if (structured.conversationType === \"private\" && structured.senderName && body) {\n const half = `${structured.senderName}:`;\n const full = `${structured.senderName}:`;\n if (body.startsWith(half)) return body.slice(half.length).trimStart();\n if (body.startsWith(full)) return body.slice(full.length).trimStart();\n return body;\n }\n\n return body ?? \"\";\n}\n\nexport function normalizeFeishuFields(\n n: RawNotification,\n): FeishuNormalizedNotification | undefined {\n const appName = typeof n.app === \"string\" ? n.app : \"\";\n if (!isFeishuApp(appName)) {\n return undefined;\n }\n\n const structured = deriveStructured(n);\n\n // Feishu 通知但任何规则都没命中:让 caller 走默认归一化路径,避免与非 Feishu 通知行为分裂。\n if (\n structured.senderName === undefined\n && structured.conversationType === undefined\n && structured.conversationName === undefined\n ) {\n return undefined;\n }\n\n return {\n title: buildTitle(n, structured),\n content: buildContent(n, structured),\n structured,\n };\n}\n",
29
+ "import { randomBytes } from \"node:crypto\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { Logger } from \"../logger.js\";\nimport {\n type NotificationIngestResult,\n NotificationStorage,\n type StoredNotification,\n} from \"../notification/storage.js\";\nimport { RELAY_INTERNAL_HTTP_HEADER } from \"../tunnel/http-proxy.js\";\nimport type { RelayTunnelService } from \"../tunnel/service.js\";\nimport type {\n HttpNotificationBody,\n NotificationPushParams,\n RawNotification,\n} from \"../types.js\";\nimport {\n readBody,\n type GatewayMethodRegistrar,\n} from \"./shared.js\";\n\nfunction newIngestId(): string {\n return `ing_${randomBytes(4).toString(\"hex\")}`;\n}\n\nfunction summarizeIncomingBatch(items: RawNotification[]): string {\n const total = items.length;\n if (total === 0) return \"items=0\";\n const now = Date.now();\n let earliest = Number.POSITIVE_INFINITY;\n let latest = Number.NEGATIVE_INFINITY;\n for (const n of items) {\n const t = new Date(n.timestamp).getTime();\n if (Number.isNaN(t)) continue;\n if (t < earliest) earliest = t;\n if (t > latest) latest = t;\n }\n if (!Number.isFinite(earliest)) {\n return `items=${total} (all ts invalid)`;\n }\n const maxLag = now - earliest;\n const minLag = now - latest;\n return `items=${total} earliestTs=${new Date(earliest).toISOString()} lag=${minLag}..${maxLag}ms`;\n}\n\nfunction createEmptyIngestResult(): NotificationIngestResult {\n return {\n received: 0,\n ingested: 0,\n dedupedById: 0,\n dedupedByContent: 0,\n invalid: 0,\n inserted: [],\n };\n}\n\nfunction isRelayInternalHttpRequest(req: IncomingMessage): boolean {\n const header = req.headers?.[RELAY_INTERNAL_HTTP_HEADER];\n if (Array.isArray(header)) {\n return header.includes(\"1\");\n }\n return header === \"1\";\n}\n\n/**\n * 将 ingest 内部结果转成对外响应:丢弃 `inserted` 字段,\n * 它只供插件内部下游链路(如 light-rule agent 评估)使用,\n * 不应该出现在 gateway / HTTP 响应里。\n */\nfunction toIngestResponse(\n result: NotificationIngestResult,\n): Omit<NotificationIngestResult, \"inserted\"> {\n const { inserted: _inserted, ...rest } = result;\n return rest;\n}\n\ninterface NotificationInterfaceDeps {\n api: OpenClawPluginApi;\n logger: Logger;\n getStorage: () => NotificationStorage | null;\n filterNotifications: (items: RawNotification[]) => RawNotification[];\n registerGatewayMethod: GatewayMethodRegistrar;\n tunnelService?: RelayTunnelService | null;\n /** 通知落盘后的钩子,用于触发灯效规则评估。 */\n onAfterIngest?: (\n inserted: StoredNotification[],\n ingestId: string,\n ) => void | Promise<void>;\n}\n\nexport function registerNotificationInterfaces(\n deps: NotificationInterfaceDeps,\n): void {\n const {\n api,\n logger,\n getStorage,\n filterNotifications,\n registerGatewayMethod,\n tunnelService,\n onAfterIngest,\n } = deps;\n\n function triggerAfterIngest(\n inserted: StoredNotification[],\n ingestId: string,\n ): void {\n if (inserted.length === 0 || !onAfterIngest) return;\n logger.info(\n `notifications[${ingestId}]: enqueue ${inserted.length} for light-rule evaluation`,\n );\n void Promise.resolve()\n .then(() => onAfterIngest(inserted, ingestId))\n .catch((err) =>\n logger.warn(\n `notifications[${ingestId}]: onAfterIngest failed: ${err?.message ?? err}`,\n ),\n );\n }\n\n registerGatewayMethod(\n \"notifications.push\",\n async ({ params, respond }) => {\n const storage = getStorage();\n if (!storage) {\n respond(false, null, {\n code: \"NOT_READY\",\n message: \"Storage service not ready\",\n });\n return;\n }\n\n const { items } = params as unknown as NotificationPushParams;\n if (!Array.isArray(items)) {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"items must be an array\",\n });\n return;\n }\n\n const ingestId = newIngestId();\n const startMs = Date.now();\n logger.info(\n `notifications[${ingestId}]: gateway notifications.push received ${summarizeIncomingBatch(items)}`,\n );\n\n const filtered = filterNotifications(items);\n if (filtered.length !== items.length) {\n logger.info(\n `notifications[${ingestId}]: filtered ${items.length - filtered.length} ignored-app item(s), kept=${filtered.length}`,\n );\n }\n const result = filtered.length\n ? await storage.ingest(filtered, ingestId)\n : createEmptyIngestResult();\n\n logger.info(\n `notifications[${ingestId}]: ingest done in ${Date.now() - startMs}ms ` +\n `(received=${result.received} ingested=${result.ingested} ` +\n `dedupedById=${result.dedupedById} dedupedByContent=${result.dedupedByContent} invalid=${result.invalid})`,\n );\n\n // 主响应先返回,不阻塞灯效评估\n respond(true, toIngestResponse(result));\n\n // 落盘后异步触发灯效评估(fire-and-forget)\n triggerAfterIngest(result.inserted, ingestId);\n },\n );\n\n api.registerHttpRoute({\n path: \"/notifications\",\n auth: \"gateway\",\n async handler(req: IncomingMessage, res: ServerResponse) {\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Method Not Allowed\" }));\n return;\n }\n\n if (!isRelayInternalHttpRequest(req)) {\n await tunnelService?.deactivateForExternalTunnel(\"POST /notifications\");\n }\n\n const storage = getStorage();\n if (!storage) {\n res.writeHead(503, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Service Not Ready\" }));\n return;\n }\n\n let body: HttpNotificationBody;\n try {\n const raw = await readBody(req);\n body = JSON.parse(raw);\n } catch {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Invalid JSON\" }));\n return;\n }\n\n if (!Array.isArray(body.notifications)) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n ok: false,\n error: \"notifications must be an array\",\n }),\n );\n return;\n }\n\n const ingestId = newIngestId();\n const startMs = Date.now();\n logger.info(\n `notifications[${ingestId}]: HTTP POST /notifications received ${summarizeIncomingBatch(body.notifications)}`,\n );\n\n const filtered = filterNotifications(body.notifications);\n if (filtered.length !== body.notifications.length) {\n logger.info(\n `notifications[${ingestId}]: filtered ${body.notifications.length - filtered.length} ignored-app item(s), kept=${filtered.length}`,\n );\n }\n const result = filtered.length\n ? await storage.ingest(filtered, ingestId)\n : createEmptyIngestResult();\n\n logger.info(\n `notifications[${ingestId}]: ingest done in ${Date.now() - startMs}ms ` +\n `(received=${result.received} ingested=${result.ingested} ` +\n `dedupedById=${result.dedupedById} dedupedByContent=${result.dedupedByContent} invalid=${result.invalid})`,\n );\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, ...toIngestResponse(result) }));\n\n // Relay tunnel 会把手机通知转发到 HTTP 端点;这里也要触发事件驱动灯效评估。\n triggerAfterIngest(result.inserted, ingestId);\n },\n });\n\n logger.info(\"Gateway 通知方法已注册: notifications.push\");\n logger.info(\"HTTP 通知端点已注册: POST /notifications\");\n}\n",
30
+ "import type { RelayClient } from \"./relay-client.js\";\nimport type { RequestFrame } from \"./types.js\";\nimport { previewText, summarizeRequestHeaders } from \"./utils.js\";\n\nexport const RELAY_INTERNAL_HTTP_HEADER = \"x-openclaw-relay-internal\";\n\nexport interface HttpProxyOptions {\n gatewayBaseUrl: string;\n gatewayAuthMode?: \"token\" | \"password\";\n gatewayToken?: string;\n gatewayPassword?: string;\n abortSignal?: AbortSignal;\n client: RelayClient;\n logger: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n };\n}\n\n// ─── 路径映射 ───\n\nconst PATH_MAP: Record<string, string> = {\n \"/api/message/messageBridge/send\": \"/notifications\",\n};\n\nexport function mapPath(p: string): string {\n return PATH_MAP[p] ?? p;\n}\n\n// ─── Auth helpers ───\n\nfunction resolveGatewayConnectAuth(opts: HttpProxyOptions):\n | { token?: string; password?: string }\n | undefined {\n const token = opts.gatewayToken?.trim() || undefined;\n const password = opts.gatewayPassword?.trim() || undefined;\n if (!token && !password) return undefined;\n return { token, password };\n}\n\nexport function buildLocalGatewayAuthAttempts(\n opts: HttpProxyOptions,\n baseHeaders: Record<string, string>,\n): Array<{ label: string; headers: Record<string, string> }> {\n const auth = resolveGatewayConnectAuth(opts);\n const attempts: Array<{ label: string; headers: Record<string, string> }> = [];\n const seen = new Set<string>();\n const authMode = opts.gatewayAuthMode;\n\n const addAttempt = (kind: \"token\" | \"password\", secret?: string): void => {\n if (!secret) return;\n\n const dedupeKey = `${kind}:${secret}`;\n if (seen.has(dedupeKey)) return;\n seen.add(dedupeKey);\n\n const headers = { ...baseHeaders };\n headers.authorization = `Bearer ${secret}`;\n\n if (kind === \"password\") {\n headers[\"x-openclaw-password\"] = secret;\n } else {\n delete headers[\"x-openclaw-password\"];\n }\n\n attempts.push({\n label: kind === \"token\" ? \"gateway-token\" : \"gateway-password\",\n headers,\n });\n };\n\n if (authMode === \"password\") {\n addAttempt(\"password\", auth?.password);\n addAttempt(\"token\", auth?.token);\n } else {\n addAttempt(\"token\", auth?.token);\n addAttempt(\"password\", auth?.password);\n }\n\n if (attempts.length === 0) {\n attempts.push({\n label: \"no-auth\",\n headers: { ...baseHeaders },\n });\n }\n\n return attempts;\n}\n\n// ─── HTTP request proxy ───\n\nexport async function handleHttpRequest(\n opts: HttpProxyOptions,\n frame: RequestFrame,\n): Promise<void> {\n const mappedPath = mapPath(frame.path);\n const url = new URL(mappedPath, opts.gatewayBaseUrl);\n const startedAtMs = Date.now();\n\n // 代理到本地 gateway 时,替换外部鉴权头为本地 gateway token/password。\n const localHeaders: Record<string, string> = {};\n for (const [k, v] of Object.entries(frame.headers ?? {})) {\n const lower = k.toLowerCase();\n if (lower !== \"authorization\" && lower !== \"x-openclaw-password\") {\n localHeaders[k] = v;\n }\n }\n localHeaders[RELAY_INTERNAL_HTTP_HEADER] = \"1\";\n\n const authAttempts = buildLocalGatewayAuthAttempts(opts, localHeaders);\n opts.logger.info(\n `TunnelProxy: HTTP id=${frame.id} ${frame.method} ${frame.path} → ${url.toString()}${summarizeRequestHeaders(frame.headers)}, authAttempts=${authAttempts.map((a) => a.label).join(\" -> \")}, body=${previewText(frame.body)}`,\n );\n\n try {\n for (let attemptIndex = 0; attemptIndex < authAttempts.length; attemptIndex++) {\n const attempt = authAttempts[attemptIndex];\n opts.logger.info(\n `TunnelProxy: HTTP id=${frame.id} attempt ${attemptIndex + 1}/${authAttempts.length} auth=${attempt.label}`,\n );\n const res = await fetch(url.toString(), {\n method: frame.method,\n headers: attempt.headers,\n signal: opts.abortSignal,\n body:\n frame.method !== \"GET\" && frame.method !== \"HEAD\"\n ? frame.body\n : undefined,\n });\n\n const hasFallback = attemptIndex < authAttempts.length - 1;\n if (res.status === 401 && hasFallback) {\n const body = await res.text();\n opts.logger.warn(\n `TunnelProxy: HTTP id=${frame.id} local gateway auth via ${attempt.label} returned 401 after ${Date.now() - startedAtMs}ms, retrying next credential${body ? `, body=${previewText(body)}` : \"\"}`,\n );\n continue;\n }\n\n await sendHttpResponse(opts, {\n frameId: frame.id,\n method: frame.method,\n path: mappedPath,\n authLabel: attempt.label,\n startedAtMs,\n res,\n });\n return;\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n opts.logger.error(\n `TunnelProxy: HTTP id=${frame.id} ${frame.method} ${mappedPath} failed after ${Date.now() - startedAtMs}ms: ${message}`,\n );\n opts.client.send({\n type: \"proxy_error\",\n id: frame.id,\n status: 502,\n message: `gateway unreachable: ${message}`,\n });\n }\n}\n\n// ─── Response helpers ───\n\nasync function sendHttpResponse(\n opts: HttpProxyOptions,\n params: {\n frameId: string;\n method: string;\n path: string;\n authLabel: string;\n startedAtMs: number;\n res: Response;\n },\n): Promise<void> {\n const { frameId, method, path, authLabel, startedAtMs, res } = params;\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n const isStreaming = contentType.includes(\"text/event-stream\");\n const elapsedMs = Date.now() - startedAtMs;\n\n opts.logger.info(\n `TunnelProxy: HTTP id=${frameId} ${method} ${path} <= ${res.status} (${elapsedMs}ms, auth=${authLabel}, content-type=${contentType}, streaming=${isStreaming})`,\n );\n\n if (isStreaming && res.body) {\n await streamResponse(opts, frameId, res, startedAtMs);\n return;\n }\n\n const body = await res.text();\n opts.logger.info(\n `TunnelProxy: HTTP id=${frameId} response body=${previewText(body)}`,\n );\n const headers: Record<string, string> = {};\n res.headers.forEach((value, key) => {\n headers[key] = value;\n });\n\n opts.client.send({\n type: \"proxy_response\",\n id: frameId,\n status: res.status,\n headers,\n body,\n });\n}\n\nasync function streamResponse(\n opts: HttpProxyOptions,\n requestId: string,\n res: Response,\n startedAtMs: number,\n): Promise<void> {\n const reader = res.body!.getReader();\n const decoder = new TextDecoder();\n let chunkCount = 0;\n\n opts.logger.info(`TunnelProxy: stream start id=${requestId}`);\n\n try {\n while (true) {\n if (opts.abortSignal?.aborted) {\n throw new DOMException(\"relay tunnel disconnected\", \"AbortError\");\n }\n const { done, value } = await reader.read();\n if (done) break;\n\n chunkCount++;\n const chunk = decoder.decode(value, { stream: true });\n opts.logger.info(\n `TunnelProxy: stream delta id=${requestId} chunk#${chunkCount} (${chunk.length} chars)`,\n );\n opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"delta\",\n data: chunk,\n });\n }\n\n opts.logger.info(\n `TunnelProxy: stream end id=${requestId}, total chunks=${chunkCount}, totalElapsedMs=${Date.now() - startedAtMs}`,\n );\n opts.client.send({\n type: \"stream\",\n id: requestId,\n state: \"end\",\n data: \"\",\n });\n } catch (err) {\n opts.logger.error(\n `TunnelProxy: stream error id=${requestId} after ${chunkCount} chunks and ${Date.now() - startedAtMs}ms: ${err instanceof Error ? err.message : String(err)}`,\n );\n opts.client.send({\n type: \"proxy_error\",\n id: requestId,\n status: 502,\n message: `stream error: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n}\n",
31
+ "import type { IncomingMessage } from \"node:http\";\nimport type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\n\nexport type GatewayHandler = Parameters<OpenClawPluginApi[\"registerGatewayMethod\"]>[1];\n\nexport type GatewayMethodRegistrar = (\n method: string,\n handler: GatewayHandler,\n) => void;\n\nexport function readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n req.on(\"end\", () => resolve(Buffer.concat(chunks).toString()));\n req.on(\"error\", reject);\n });\n}\n\nexport function trimToUndefined(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n",
32
+ "import {\n existsSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n rmSync,\n readdirSync,\n statSync,\n} from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport type { LightSegment } from \"../types.js\";\nimport type { LightRuleMeta } from \"./types.js\";\nimport { assertAncsRepeatTimes, normalizeRepeatTimes } from \"../light/repeat.js\";\n\nexport interface LightRuleStorageContext {\n workspaceDir?: string;\n stateDir?: string;\n}\n\nfunction resolveBaseDir(ctx: LightRuleStorageContext): string {\n if (ctx.workspaceDir) return ctx.workspaceDir;\n\n if (ctx.stateDir) {\n const inferredWorkspaceDir = join(ctx.stateDir, \"workspace\");\n if (existsSync(inferredWorkspaceDir)) return inferredWorkspaceDir;\n return ctx.stateDir;\n }\n\n throw new Error(\"workspaceDir and stateDir both unavailable\");\n}\n\nfunction tasksDir(ctx: LightRuleStorageContext): string {\n return join(resolveBaseDir(ctx), \"tasks\");\n}\n\nfunction normalizeLightRuleLookupName(name: string): string {\n return name.trim().replace(/\\.json$/i, \"\");\n}\n\nfunction resolveLightRuleTask(\n ctx: LightRuleStorageContext,\n name: string,\n): { taskDir: string; meta: LightRuleMeta } | null {\n const dir = tasksDir(ctx);\n const normalizedName = normalizeLightRuleLookupName(name);\n if (!normalizedName) return null;\n\n const directTaskDir = join(dir, normalizedName);\n const directMeta = readMeta(directTaskDir);\n if (directMeta) {\n return {\n taskDir: directTaskDir,\n meta: directMeta,\n };\n }\n\n if (!existsSync(dir)) return null;\n\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n\n const taskDir = join(dir, entry.name);\n const meta = readMeta(taskDir);\n if (meta?.name === normalizedName) {\n return {\n taskDir,\n meta,\n };\n }\n }\n\n return null;\n}\n\nfunction readOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed || undefined;\n}\n\nfunction readMeta(taskDir: string): LightRuleMeta | null {\n const metaPath = join(taskDir, \"meta.json\");\n if (!existsSync(metaPath)) return null;\n try {\n const raw = JSON.parse(readFileSync(metaPath, \"utf-8\"));\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return null;\n if (raw.type !== \"light-rule\") return null;\n if (!Array.isArray(raw.segments)) return null;\n const name = readOptionalString(raw.name) ?? basename(taskDir);\n const title = readOptionalString(raw.title) ?? name;\n const description = readOptionalString(raw.description) ?? name;\n const createdAt =\n readOptionalString(raw.createdAt) ?? statSync(metaPath).birthtime.toISOString();\n const enabled = typeof raw.enabled === \"boolean\" ? raw.enabled : true;\n const repeatTimes = normalizeRepeatTimes({\n repeat: raw.repeat,\n repeat_times: raw.repeat_times,\n });\n assertAncsRepeatTimes(repeatTimes);\n return {\n ...raw,\n name,\n title,\n type: \"light-rule\",\n description,\n segments: raw.segments,\n repeat_times: repeatTimes,\n enabled,\n createdAt,\n } as LightRuleMeta;\n } catch {\n return null;\n }\n}\n\nfunction writeMeta(taskDir: string, meta: LightRuleMeta): void {\n writeFileSync(join(taskDir, \"meta.json\"), JSON.stringify(meta, null, 2), \"utf-8\");\n}\n\nexport function listLightRules(ctx: LightRuleStorageContext): LightRuleMeta[] {\n const dir = tasksDir(ctx);\n if (!existsSync(dir)) return [];\n\n const rules: LightRuleMeta[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const meta = readMeta(join(dir, entry.name));\n if (meta) rules.push(meta);\n }\n return rules;\n}\n\nexport function getLightRule(\n ctx: LightRuleStorageContext,\n name: string,\n): LightRuleMeta | null {\n return resolveLightRuleTask(ctx, name)?.meta ?? null;\n}\n\nexport function createLightRule(\n ctx: LightRuleStorageContext,\n params: {\n name: string;\n title: string;\n description: string;\n segments: LightSegment[];\n repeat_times?: number;\n repeat?: boolean;\n },\n): { meta: LightRuleMeta } {\n const dir = tasksDir(ctx);\n const taskDir = join(dir, params.name);\n\n if (existsSync(taskDir)) {\n throw new LightRuleError(\"ALREADY_EXISTS\", `灯效规则 '${params.name}' 已存在`);\n }\n\n mkdirSync(taskDir, { recursive: true });\n\n const repeatTimes = normalizeRepeatTimes({\n repeat: params.repeat,\n repeat_times: params.repeat_times,\n });\n assertAncsRepeatTimes(repeatTimes);\n\n const meta: LightRuleMeta = {\n name: params.name,\n title: params.title,\n type: \"light-rule\",\n description: params.description,\n segments: params.segments,\n repeat_times: repeatTimes,\n enabled: true,\n createdAt: new Date().toISOString(),\n };\n\n writeMeta(taskDir, meta);\n\n return { meta };\n}\n\nexport function updateLightRule(\n ctx: LightRuleStorageContext,\n params: {\n name: string;\n title?: string;\n description?: string;\n segments?: LightSegment[];\n repeat_times?: number;\n repeat?: boolean;\n enabled?: boolean;\n },\n): { meta: LightRuleMeta } {\n const resolved = resolveLightRuleTask(ctx, params.name);\n const taskDir = resolved?.taskDir;\n const meta = resolved?.meta;\n\n if (!taskDir || !meta) {\n throw new LightRuleError(\"NOT_FOUND\", `灯效规则 '${params.name}' 不存在`);\n }\n\n if (params.description !== undefined) {\n meta.description = params.description;\n }\n if (params.title !== undefined) {\n meta.title = params.title;\n }\n if (params.segments !== undefined) {\n meta.segments = params.segments;\n }\n if (params.repeat !== undefined || params.repeat_times !== undefined) {\n meta.repeat_times = normalizeRepeatTimes({\n repeat: params.repeat,\n repeat_times: params.repeat_times,\n });\n assertAncsRepeatTimes(meta.repeat_times);\n }\n if (params.enabled !== undefined) {\n meta.enabled = params.enabled;\n }\n\n meta.updatedAt = new Date().toISOString();\n writeMeta(taskDir, meta);\n\n return { meta };\n}\n\nexport function deleteLightRule(\n ctx: LightRuleStorageContext,\n name: string,\n): { name: string } {\n const resolved = resolveLightRuleTask(ctx, name);\n const taskDir = resolved?.taskDir;\n const meta = resolved?.meta;\n\n if (!taskDir || !meta) {\n throw new LightRuleError(\"NOT_FOUND\", `灯效规则 '${name}' 不存在`);\n }\n\n rmSync(taskDir, { recursive: true, force: true });\n\n return { name: meta.name };\n}\n\nexport class LightRuleError extends Error {\n constructor(\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = \"LightRuleError\";\n }\n}\n",
33
+ "export interface RepeatConfig {\n repeat?: boolean;\n repeat_times?: number;\n}\n\nexport type RepeatArgument = RepeatConfig | boolean | number | undefined;\n\nexport function normalizeRepeatTimes(input?: RepeatArgument): number {\n if (typeof input === \"boolean\") {\n return input ? 0 : 1;\n }\n\n if (typeof input === \"number\") {\n return validateRepeatTimes(input);\n }\n\n if (!input) {\n return 1;\n }\n\n if (input.repeat_times !== undefined) {\n return validateRepeatTimes(input.repeat_times);\n }\n\n if (input.repeat !== undefined) {\n return input.repeat ? 0 : 1;\n }\n\n return 1;\n}\n\nexport function assertAncsRepeatTimes(repeatTimes: number): void {\n if (repeatTimes !== 0 && repeatTimes !== 1) {\n throw new Error(\n \"当前 ANCS 路径仅支持 repeat_times=0(无限循环)或 1(播放一轮);N>=2 需非 ANCS 路径\",\n );\n }\n}\n\nfunction validateRepeatTimes(value: number): number {\n if (!Number.isInteger(value) || value < 0) {\n throw new Error(\"repeat_times 必须是 >=0 的整数\");\n }\n\n return value;\n}\n",
34
+ "/**\n * LightRuleRegistry —— 灯效规则的内存索引 + CRUD 包装\n *\n * 角色定位:\n * - 在事件驱动重构方案下,每条通知到达时都需要拿到\"当前 enabled 的全部规则\"\n * 用来拼装 Agent 的 system prompt。如果每次都扫盘 N 个 meta.json,\n * 5 秒延迟预算会被磨穿,所以引入这个常驻内存的 index。\n * - 同时它是 storage.ts 的 CRUD 包装:所有 create/update/delete 都会先落盘、\n * 再更新内存 Map,保证两者一致。\n *\n * 本类**不**做规则匹配 —— 匹配交给 Agent。registry 只负责\"有哪些规则\"和\n * \"按需拼装 prompt\"。\n *\n * 写路径用一个 promise 链做串行化(最朴素的 mutex),保证并发 CRUD\n * 不会出现\"内存和磁盘交错\"的状态。\n *\n * 见 prd-lightrules-event-driven-refactor.md §数据模型 / §触发流程\n */\n\nimport {\n createLightRule,\n deleteLightRule,\n listLightRules,\n updateLightRule,\n type LightRuleStorageContext,\n} from \"./storage.js\";\nimport type { LightRuleMeta } from \"./types.js\";\n\nexport { LightRuleError } from \"./storage.js\";\n\ntype CreateParams = Parameters<typeof createLightRule>[1];\ntype UpdateParams = Parameters<typeof updateLightRule>[1];\ntype CreateResult = ReturnType<typeof createLightRule>;\ntype UpdateResult = ReturnType<typeof updateLightRule>;\ntype DeleteResult = ReturnType<typeof deleteLightRule>;\n\nexport class LightRuleRegistry {\n private readonly ctx: LightRuleStorageContext;\n /** name → meta 的内存索引;落盘成功后才更新 */\n private readonly index = new Map<string, LightRuleMeta>();\n /** 写路径串行化锁:每次 mutate 都 chain 在前一次之后 */\n private writeChain: Promise<unknown> = Promise.resolve();\n\n constructor(ctx: LightRuleStorageContext) {\n this.ctx = ctx;\n this.reload();\n }\n\n /**\n * 从磁盘重新加载全部规则到内存。仅在构造时和外部显式触发时使用。\n * 正常 CRUD 路径不应该调用本方法 —— 通过 create/update/delete 增量维护即可。\n */\n reload(): void {\n this.index.clear();\n for (const meta of listLightRules(this.ctx)) {\n this.index.set(meta.name, meta);\n }\n }\n\n /** 全部规则(包含 disabled),调用方不要改返回值。 */\n list(): LightRuleMeta[] {\n return Array.from(this.index.values());\n }\n\n /** 仅 enabled 的规则。事件驱动评估链路使用。 */\n getEnabled(): LightRuleMeta[] {\n return this.list().filter((rule) => rule.enabled);\n }\n\n /** 按名字精确查找;不存在返回 null。 */\n get(name: string): LightRuleMeta | null {\n return this.index.get(name) ?? null;\n }\n\n /**\n * 创建规则。落盘成功后再写入内存索引。\n * 失败时 storage 抛 LightRuleError,内存索引保持不变。\n */\n async create(params: CreateParams): Promise<CreateResult> {\n return this.runExclusive(() => {\n const result = createLightRule(this.ctx, params);\n this.index.set(result.meta.name, result.meta);\n return result;\n });\n }\n\n /**\n * 更新规则。落盘成功后再刷新内存条目。\n */\n async update(params: UpdateParams): Promise<UpdateResult> {\n return this.runExclusive(() => {\n const result = updateLightRule(this.ctx, params);\n this.index.set(result.meta.name, result.meta);\n return result;\n });\n }\n\n /**\n * 删除规则。落盘成功后再从内存索引移除。\n */\n async delete(name: string): Promise<DeleteResult> {\n return this.runExclusive(() => {\n const result = deleteLightRule(this.ctx, name);\n this.index.delete(result.name);\n return result;\n });\n }\n\n /**\n * 拼装 Agent 评估用的 system prompt。\n *\n * 当前实现是一个最小可用骨架:列出全部 enabled 规则的 title + name + description。\n * M3 接入真实 Agent 链路时,会按 prd-lightrules-event-driven-refactor.md §Prompt 拼装\n * 的模板补齐\"任务说明 / 输出约束\"等段落。\n *\n * 现在先把方法签名冻结,避免后续散落在多个调用点。\n */\n buildSystemPrompt(): string {\n const enabled = this.getEnabled();\n if (enabled.length === 0) {\n return \"当前没有启用任何灯效规则。\";\n }\n\n const lines: string[] = [\n '你是一个判断\"通知 → 灯效规则\"是否命中的助手。',\n \"\",\n \"下面是用户当前启用的全部灯效规则(按创建时间倒序):\",\n \"\",\n ];\n\n const sorted = [...enabled].sort((a, b) =>\n (b.createdAt ?? \"\").localeCompare(a.createdAt ?? \"\"),\n );\n\n sorted.forEach((rule, idx) => {\n lines.push(\n `[${idx + 1}] title: ${rule.title}`,\n ` name: ${rule.name}`,\n ` description: ${rule.description}`,\n \"\",\n );\n });\n\n lines.push(\n '任务:根据用户接下来发给你的\"通知\"内容,判断哪些规则被命中。',\n \"- 命中 0 条:不调用任何工具,直接结束。\",\n \"- 命中 1 条或多条:对每一条命中的规则调用一次 trigger_light(rule_name)。\",\n \"- 不要回复任何自由文本;判定结果**只**通过 tool calling 表达。\",\n '- 拿不准的时候倾向于\"不触发\",避免骚扰用户。',\n );\n\n return lines.join(\"\\n\");\n }\n\n /**\n * 把一段同步操作排队进 write chain,保证 mutate 串行执行。\n *\n * 用 promise 链做 mutex 是最简单的方案:每次 runExclusive 都把\n * `writeChain` 推进一步。即使前一个任务失败,链也会继续往下走,\n * 后续任务不会被永久阻塞。\n */\n private runExclusive<T>(fn: () => T): Promise<T> {\n const next = this.writeChain.then(\n () => fn(),\n () => fn(),\n );\n // 不让链上的失败传播下去(已在 then 的 onRejected 回调里吸收)\n this.writeChain = next.catch(() => undefined);\n return next;\n }\n}\n",
35
+ "import type { LightPixelFramePixel, LightSegment } from \"../types.js\";\nimport { output, exitError } from \"../cli/helpers.js\";\n\nexport const VALID_MODES = [\n \"wave\",\n \"breath\",\n \"strobe\",\n \"steady\",\n \"color_flow\",\n \"pixel_frame\",\n] as const;\nexport const MAX_SEGMENTS = 12;\n\nexport interface ValidationError {\n field: string;\n message: string;\n}\n\nexport interface ValidationWarning {\n field: string;\n code: string;\n message: string;\n}\n\nexport type ValidationResult =\n | { valid: true; segments: LightSegment[]; warnings: ValidationWarning[] }\n | { valid: false; errors: ValidationError[] };\n\nexport function validateSegments(segments: unknown): ValidationResult {\n if (!Array.isArray(segments)) {\n return { valid: false, errors: [{ field: \"segments\", message: \"必须是数组\" }] };\n }\n if (segments.length === 0) {\n return { valid: false, errors: [{ field: \"segments\", message: \"不能为空\" }] };\n }\n if (segments.length > MAX_SEGMENTS) {\n return {\n valid: false,\n errors: [{ field: \"segments\", message: `最多 ${MAX_SEGMENTS} 段` }],\n };\n }\n\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n for (let i = 0; i < segments.length; i++) {\n validateSegment(segments[i], `segments[${i}]`, errors, warnings);\n }\n\n if (errors.length > 0) return { valid: false, errors };\n return { valid: true, segments: segments as LightSegment[], warnings };\n}\n\n/**\n * 解析 JSON 字符串并校验 segments,失败时直接 exitError。\n * 适用于 CLI action 中的统一入口。\n */\nexport function parseAndValidateSegments(json: string): LightSegment[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n exitError(\"VALIDATION_FAILED\", \"segments 必须是合法的 JSON\");\n }\n\n const result = validateSegments(parsed);\n if (!result.valid) {\n output({ ok: false, error: { code: \"VALIDATION_FAILED\", details: result.errors } });\n process.exit(1);\n }\n\n return result.segments;\n}\n\nfunction validateSegment(\n seg: unknown,\n prefix: string,\n errors: ValidationError[],\n warnings: ValidationWarning[],\n): void {\n if (!isRecord(seg)) {\n errors.push({ field: prefix, message: \"必须是对象\" });\n return;\n }\n\n const mode = seg.mode;\n if (!VALID_MODES.includes(mode as (typeof VALID_MODES)[number])) {\n errors.push({\n field: `${prefix}.mode`,\n message: `不支持的模式 '${String(mode)}',可选:${VALID_MODES.join(\"/\")}`,\n });\n }\n\n validateNonNegativeNumber(seg.duration_s, `${prefix}.duration_s`, errors, \"必须是 ≥0 的数字(0 表示无限时长)\");\n\n switch (mode) {\n case \"wave\":\n validateForegroundSegment(seg, prefix, errors);\n validateOptionalNonNegativeNumber(seg.interval_ms, `${prefix}.interval_ms`, errors);\n validateOptionalDirection(seg.direction, `${prefix}.direction`, errors);\n validateOptionalWindow(seg.window, `${prefix}.window`, errors);\n validateOptionalBackground(seg.background, `${prefix}.background`, errors);\n break;\n case \"color_flow\":\n validateForegroundSegment(seg, prefix, errors);\n validateOptionalNonNegativeNumber(seg.interval_ms, `${prefix}.interval_ms`, errors);\n validateOptionalDirection(seg.direction, `${prefix}.direction`, errors);\n validateOptionalWindow(seg.window, `${prefix}.window`, errors);\n validateOptionalBackground(seg.background, `${prefix}.background`, errors);\n type RgbLike = Parameters<typeof hasNonZeroRgb>[0];\n if (!hasNonZeroRgb(seg.color as RgbLike) && !hasNonZeroRgb(seg.background as RgbLike)) {\n errors.push({\n field: prefix,\n message: \"color_flow 至少需要一组非零颜色锚点(color 或 background)\",\n });\n }\n detectColorFlowSingleAnchorMisuse(seg, prefix, warnings);\n break;\n case \"breath\":\n validateForegroundSegment(seg, prefix, errors);\n validateOptionalBreathTiming(seg.breath_timing, `${prefix}.breath_timing`, errors);\n break;\n case \"strobe\":\n validateForegroundSegment(seg, prefix, errors);\n validateOptionalNonNegativeNumber(seg.interval_ms, `${prefix}.interval_ms`, errors);\n break;\n case \"steady\":\n validateForegroundSegment(seg, prefix, errors);\n break;\n case \"pixel_frame\":\n validatePixelFrame(seg.pixels, `${prefix}.pixels`, errors);\n break;\n default:\n validateOptionalNonNegativeNumber(seg.brightness, `${prefix}.brightness`, errors);\n validateOptionalColor(seg.color, `${prefix}.color`, errors);\n validateOptionalNonNegativeNumber(seg.interval_ms, `${prefix}.interval_ms`, errors);\n validateOptionalDirection(seg.direction, `${prefix}.direction`, errors);\n validateOptionalWindow(seg.window, `${prefix}.window`, errors);\n validateOptionalBreathTiming(seg.breath_timing, `${prefix}.breath_timing`, errors);\n validateOptionalBackground(seg.background, `${prefix}.background`, errors);\n }\n}\n\nfunction validateForegroundSegment(\n seg: Record<string, unknown>,\n prefix: string,\n errors: ValidationError[],\n): void {\n validateNumberInRange(\n seg.brightness,\n `${prefix}.brightness`,\n errors,\n 0,\n 255,\n \"必须是 0–255 的数字\",\n );\n validateColor(seg.color, `${prefix}.color`, errors);\n\n if (seg.mode !== \"steady\" && seg.brightness === 0) {\n errors.push({\n field: `${prefix}.brightness`,\n message: \"brightness=0 仅 steady 模式允许;其它模式会在固件侧被过滤\",\n });\n }\n}\n\nfunction validatePixelFrame(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (!Array.isArray(value)) {\n errors.push({ field, message: \"pixel_frame 必须提供 pixels 数组(1–7 项)\" });\n return;\n }\n\n if (value.length < 1 || value.length > 7) {\n errors.push({ field, message: \"pixels 必须为 1–7 项\" });\n }\n\n const seen = new Set<number>();\n for (let i = 0; i < value.length; i++) {\n const pixel = value[i];\n const prefix = `${field}[${i}]`;\n if (!isRecord(pixel)) {\n errors.push({ field: prefix, message: \"必须是对象\" });\n continue;\n }\n\n const idx = pixel.index;\n if (!Number.isInteger(idx) || (idx as number) < 0 || (idx as number) > 6) {\n errors.push({ field: `${prefix}.index`, message: \"index 必须是 0–6 的整数\" });\n } else if (seen.has(idx as number)) {\n errors.push({ field: `${prefix}.index`, message: `index=${idx} 重复` });\n } else {\n seen.add(idx as number);\n }\n\n validateNumberInRange(\n pixel.brightness,\n `${prefix}.brightness`,\n errors,\n 0,\n 255,\n \"必须是 0–255 的数字\",\n );\n validateColor(pixel.color, `${prefix}.color`, errors);\n }\n}\n\nfunction validateOptionalBreathTiming(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n if (!isRecord(value)) {\n errors.push({ field, message: \"必须是对象\" });\n return;\n }\n\n validatePositiveNumber(\n value.rise_ms,\n `${field}.rise_ms`,\n errors,\n \"rise_ms 必须是 >0 的数字(不支持 0ms)\",\n );\n validateNonNegativeNumber(\n value.hold_ms,\n `${field}.hold_ms`,\n errors,\n \"hold_ms 必须是 ≥0 的数字\",\n );\n validatePositiveNumber(\n value.fall_ms,\n `${field}.fall_ms`,\n errors,\n \"fall_ms 必须是 >0 的数字(不支持 0ms)\",\n );\n validateNonNegativeNumber(\n value.off_ms,\n `${field}.off_ms`,\n errors,\n \"off_ms 必须是 ≥0 的数字\",\n );\n}\n\nfunction validateOptionalBackground(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n if (!isRecord(value)) {\n errors.push({ field, message: \"必须包含 r/g/b/brightness 数值\" });\n return;\n }\n\n validateColor(value, field, errors);\n validateNumberInRange(\n value.brightness,\n `${field}.brightness`,\n errors,\n 0,\n 255,\n \"必须是 0–255 的数字\",\n );\n}\n\nfunction validateOptionalColor(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n validateColor(value, field, errors);\n}\n\nfunction validateColor(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (!isRecord(value)) {\n errors.push({ field, message: \"必须包含 r/g/b 数值\" });\n return;\n }\n\n validateNumberInRange(value.r, `${field}.r`, errors, 0, 255, \"必须是 0–255 的数字\");\n validateNumberInRange(value.g, `${field}.g`, errors, 0, 255, \"必须是 0–255 的数字\");\n validateNumberInRange(value.b, `${field}.b`, errors, 0, 255, \"必须是 0–255 的数字\");\n}\n\nfunction validateOptionalDirection(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n if (value !== \"ltr\" && value !== \"rtl\") {\n errors.push({ field, message: \"direction 必须是 ltr 或 rtl\" });\n }\n}\n\nfunction validateOptionalWindow(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n if (value !== 1 && value !== 2 && value !== 3) {\n errors.push({ field, message: \"window 仅支持 1/2/3\" });\n }\n}\n\nfunction validateOptionalNonNegativeNumber(\n value: unknown,\n field: string,\n errors: ValidationError[],\n): void {\n if (value === undefined) return;\n validateNonNegativeNumber(value, field, errors, \"必须是 ≥0 的数字\");\n}\n\nfunction validatePositiveNumber(\n value: unknown,\n field: string,\n errors: ValidationError[],\n message: string,\n): void {\n if (value === undefined) return;\n if (!isFiniteNumber(value) || value <= 0) {\n errors.push({ field, message });\n }\n}\n\nfunction validateNonNegativeNumber(\n value: unknown,\n field: string,\n errors: ValidationError[],\n message: string,\n): void {\n if (!isFiniteNumber(value) || value < 0) {\n errors.push({ field, message });\n }\n}\n\nfunction validateNumberInRange(\n value: unknown,\n field: string,\n errors: ValidationError[],\n min: number,\n max: number,\n message: string,\n): void {\n if (!isFiniteNumber(value) || value < min || value > max) {\n errors.push({ field, message });\n }\n}\n\nfunction hasNonZeroRgb(\n value: Pick<LightPixelFramePixel[\"color\"], \"r\" | \"g\" | \"b\"> | { r?: unknown; g?: unknown; b?: unknown } | undefined,\n): boolean {\n if (!value) return false;\n return [value.r, value.g, value.b].some((channel) => isFiniteNumber(channel) && channel > 0);\n}\n\n/**\n * color_flow 是「调色板沿圆周流动」,由 1~2 个颜色锚点插值得到。\n * 当用户/模型只给单一极端纯色锚点(如纯红 R=255、G=B=0)且没有底色锚点时,\n * 实际效果是「同色系亮暗环状流动」(红→暗红),而不是多色调色板流动。\n * 这是已知的 bug 模式(详见 imp-custom-led-ai-read.md「模式选择易错对照」):\n * 上层往往是把用户的\"单色波浪\"误映射到 color_flow,应该改用 wave 模式。\n * 此处不阻塞,只 push 一条 warning 让前端/审计可见。\n */\nfunction detectColorFlowSingleAnchorMisuse(\n seg: Record<string, unknown>,\n prefix: string,\n warnings: ValidationWarning[],\n): void {\n const color = seg.color as { r?: unknown; g?: unknown; b?: unknown } | undefined;\n const background = seg.background as\n | { r?: unknown; g?: unknown; b?: unknown; brightness?: unknown }\n | undefined;\n\n const fgChannels = extractChannels(color);\n const bgChannels = extractChannels(background);\n if (!fgChannels) return;\n\n const bgBrightnessRaw = background?.brightness;\n const bgBrightness = isFiniteNumber(bgBrightnessRaw) ? bgBrightnessRaw : 0;\n const bgActive = !!bgChannels && bgChannels.some((c) => c > 0) && bgBrightness > 0;\n if (bgActive) return;\n\n const fgActiveChannels = fgChannels.filter((c) => c > 0);\n if (fgActiveChannels.length !== 1) return;\n if (fgActiveChannels[0] < 192) return;\n\n warnings.push({\n field: prefix,\n code: \"COLOR_FLOW_SINGLE_ANCHOR_MISUSE\",\n message:\n \"color_flow 仅设置了单一极端纯色前景锚点(无有效底色锚点),实际效果是同色系亮暗环状流动,不是多色调色板流动。\" +\n \"若用户期望的是\\\"单色波浪\\\",请改用 mode='wave';若期望多色流动,请同时设置 background 作为第二锚点。\",\n });\n}\n\nfunction extractChannels(\n value: { r?: unknown; g?: unknown; b?: unknown } | undefined,\n): [number, number, number] | null {\n if (!value) return null;\n const r = isFiniteNumber(value.r) ? value.r : 0;\n const g = isFiniteNumber(value.g) ? value.g : 0;\n const b = isFiniteNumber(value.b) ? value.b : 0;\n return [r, g, b];\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n",
36
+ "export const LIGHT_RULE_GATEWAY_METHODS = {\n list: \"lightrules.list\",\n create: \"lightrules.create\",\n update: \"lightrules.update\",\n delete: \"lightrules.delete\",\n} as const;\n\nexport const LIGHT_RULE_GATEWAY_METHOD_LIST = [\n LIGHT_RULE_GATEWAY_METHODS.list,\n LIGHT_RULE_GATEWAY_METHODS.create,\n LIGHT_RULE_GATEWAY_METHODS.update,\n LIGHT_RULE_GATEWAY_METHODS.delete,\n] as const;\n\nexport const LIGHT_RULE_TOOL_NAMES = {\n list: \"lightrules_list\",\n create: \"lightrules_create\",\n update: \"lightrules_update\",\n delete: \"lightrules_delete\",\n} as const;\n\nexport const LIGHT_RULE_TOOL_NAME_LIST = [\n LIGHT_RULE_TOOL_NAMES.list,\n LIGHT_RULE_TOOL_NAMES.create,\n LIGHT_RULE_TOOL_NAMES.update,\n LIGHT_RULE_TOOL_NAMES.delete,\n] as const;\n",
37
+ "import type { OpenClawPluginApi } from \"openclaw/plugin-sdk\";\nimport type { Logger } from \"../logger.js\";\nimport { assertAncsRepeatTimes, normalizeRepeatTimes } from \"../light/repeat.js\";\nimport { validateSegments } from \"../light/validators.js\";\nimport { LIGHT_RULE_GATEWAY_METHODS } from \"./names.js\";\nimport type { LightSegment } from \"../types.js\";\nimport type { BroadcastFn } from \"../update/types.js\";\nimport type {\n LightRuleCreateParams,\n LightRuleUpdateParams,\n LightRuleDeleteParams,\n} from \"./types.js\";\nimport { LightRuleError } from \"./storage.js\";\nimport type { LightRuleRegistry } from \"./registry.js\";\n\nfunction resolveRuleIdentifier(params: unknown): string | undefined {\n if (!params || typeof params !== \"object\") return undefined;\n\n const raw = params as Record<string, unknown>;\n const candidates = [raw.name, raw.id, raw.ruleId, raw.ruleName];\n for (const candidate of candidates) {\n if (typeof candidate !== \"string\") continue;\n const normalized = candidate.trim().replace(/\\.json$/i, \"\");\n if (normalized) return normalized;\n }\n\n return undefined;\n}\n\nexport function registerLightRulesGateway(\n api: OpenClawPluginApi,\n registry: LightRuleRegistry,\n logger: Pick<Logger, \"info\" | \"warn\">,\n rememberBroadcast?: (broadcast: BroadcastFn | undefined) => void,\n): void {\n type GatewayHandler = Parameters<OpenClawPluginApi[\"registerGatewayMethod\"]>[1];\n\n const registerGatewayMethodWithBroadcastCapture = (\n method: string,\n handler: GatewayHandler,\n ): void => {\n api.registerGatewayMethod(method, (opts) => {\n rememberBroadcast?.(opts.context?.broadcast);\n return handler(opts);\n });\n };\n\n // lightrules.list\n registerGatewayMethodWithBroadcastCapture(LIGHT_RULE_GATEWAY_METHODS.list, async ({ respond }) => {\n try {\n registry.reload();\n const rules = registry.list().map((rule) => ({\n ...rule,\n id: rule.name,\n }));\n respond(true, { ok: true, rules });\n } catch (err: any) {\n logger.warn(`${LIGHT_RULE_GATEWAY_METHODS.list} failed: ${err?.message}`);\n respond(false, null, {\n code: \"INTERNAL_ERROR\",\n message: err?.message ?? \"Unknown error\",\n });\n }\n });\n\n // lightrules.create\n registerGatewayMethodWithBroadcastCapture(\n LIGHT_RULE_GATEWAY_METHODS.create,\n async ({ params, respond }) => {\n const { name, title, description, segments, repeat, repeat_times } =\n params as unknown as LightRuleCreateParams;\n const resolvedTitle = typeof title === \"string\" && title.trim() ? title.trim() : name;\n\n if (!name || typeof name !== \"string\") {\n respond(false, null, { code: \"INVALID_PARAMS\", message: \"name is required\" });\n return;\n }\n if (!description || typeof description !== \"string\") {\n respond(false, null, { code: \"INVALID_PARAMS\", message: \"description is required\" });\n return;\n }\n\n const validation = validateSegments(segments);\n if (!validation.valid) {\n respond(false, null, {\n code: \"VALIDATION_FAILED\",\n message: JSON.stringify(validation.errors),\n });\n return;\n }\n\n let repeatTimes: number;\n try {\n repeatTimes = normalizeRepeatTimes({ repeat, repeat_times });\n assertAncsRepeatTimes(repeatTimes);\n } catch (err: any) {\n respond(false, null, {\n code: \"VALIDATION_FAILED\",\n message: err?.message ?? \"Unknown error\",\n });\n return;\n }\n\n try {\n const result = await registry.create({\n name,\n title: resolvedTitle,\n description,\n segments: validation.segments,\n repeat_times: repeatTimes,\n });\n logger.info(`Light rule created: ${name}`);\n respond(true, {\n ok: true,\n id: result.meta.name,\n name: result.meta.name,\n title: result.meta.title,\n rule: result.meta,\n });\n } catch (err: any) {\n if (err instanceof LightRuleError) {\n respond(false, null, { code: err.code, message: err.message });\n } else {\n logger.warn(`${LIGHT_RULE_GATEWAY_METHODS.create} failed: ${err?.message}`);\n respond(false, null, {\n code: \"INTERNAL_ERROR\",\n message: err?.message ?? \"Unknown error\",\n });\n }\n }\n },\n );\n\n // lightrules.update\n registerGatewayMethodWithBroadcastCapture(\n LIGHT_RULE_GATEWAY_METHODS.update,\n async ({ params, respond }) => {\n const { title, description, segments, repeat, repeat_times, enabled } =\n params as unknown as LightRuleUpdateParams;\n const name = resolveRuleIdentifier(params);\n const resolvedTitle = typeof title === \"string\" ? title.trim() : undefined;\n\n if (!name) {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"name is required (or provide id/ruleId/ruleName)\",\n });\n return;\n }\n if (title !== undefined && !resolvedTitle) {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"title must be a non-empty string\",\n });\n return;\n }\n if (description !== undefined && typeof description !== \"string\") {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"description must be a string\",\n });\n return;\n }\n\n let validatedSegments: LightSegment[] | undefined;\n if (segments !== undefined) {\n const validation = validateSegments(segments);\n if (!validation.valid) {\n respond(false, null, {\n code: \"VALIDATION_FAILED\",\n message: JSON.stringify(validation.errors),\n });\n return;\n }\n validatedSegments = validation.segments;\n }\n\n let repeatTimes: number | undefined;\n if (repeat !== undefined || repeat_times !== undefined) {\n try {\n repeatTimes = normalizeRepeatTimes({ repeat, repeat_times });\n assertAncsRepeatTimes(repeatTimes);\n } catch (err: any) {\n respond(false, null, {\n code: \"VALIDATION_FAILED\",\n message: err?.message ?? \"Unknown error\",\n });\n return;\n }\n }\n\n try {\n const result = await registry.update({\n name,\n title: resolvedTitle,\n description,\n segments: validatedSegments,\n repeat_times: repeatTimes,\n enabled,\n });\n logger.info(`Light rule updated: ${name}`);\n respond(true, {\n ok: true,\n id: result.meta.name,\n name: result.meta.name,\n title: result.meta.title,\n updated: true,\n rule: result.meta,\n });\n } catch (err: any) {\n if (err instanceof LightRuleError) {\n respond(false, null, { code: err.code, message: err.message });\n } else {\n logger.warn(`${LIGHT_RULE_GATEWAY_METHODS.update} failed: ${err?.message}`);\n respond(false, null, {\n code: \"INTERNAL_ERROR\",\n message: err?.message ?? \"Unknown error\",\n });\n }\n }\n },\n );\n\n // lightrules.delete\n registerGatewayMethodWithBroadcastCapture(\n LIGHT_RULE_GATEWAY_METHODS.delete,\n async ({ params, respond }) => {\n const name = resolveRuleIdentifier(params as unknown as LightRuleDeleteParams);\n\n if (!name) {\n respond(false, null, {\n code: \"INVALID_PARAMS\",\n message: \"name is required (or provide id/ruleId/ruleName)\",\n });\n return;\n }\n try {\n const result = await registry.delete(name);\n logger.info(`Light rule deleted: ${result.name}`);\n respond(true, {\n ok: true,\n id: result.name,\n name: result.name,\n deleted: true,\n });\n } catch (err: any) {\n if (err instanceof LightRuleError) {\n respond(false, null, { code: err.code, message: err.message });\n } else {\n logger.warn(`${LIGHT_RULE_GATEWAY_METHODS.delete} failed: ${err?.message}`);\n respond(false, null, {\n code: \"INTERNAL_ERROR\",\n message: err?.message ?? \"Unknown error\",\n });\n }\n }\n },\n );\n}\n",
38
+ "/**\n * notification service —— search / summary / stats / storage-path + shortcuts。\n * 全部纯读磁盘(🟢),不需要 daemon。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { buildQueryOptions, queryNotifications, type RawQueryOpts } from \"../notification/query.js\";\nimport type { NotificationQueryOptions } from \"../shared.js\";\nimport { daysAgo, today, formatDate } from \"../shared.js\";\nimport type { StoredNotification } from \"../shared.js\";\n\nconst MAX_LIMIT = Number.MAX_SAFE_INTEGER;\n\nexport async function notificationSearch(\n ctx: CliContext,\n _args: unknown[],\n opts: RawQueryOpts,\n): Promise<unknown> {\n const options = buildQueryOptions(opts);\n return queryNotifications(ctx.paths, options);\n}\n\ninterface SummaryOpts extends RawQueryOpts {\n sample?: string;\n top?: string;\n}\n\nfunction topCounts(\n items: StoredNotification[],\n pick: (n: StoredNotification) => string | undefined,\n topN: number,\n): Array<{ key: string; count: number }> {\n const counts = new Map<string, number>();\n for (const item of items) {\n const key = pick(item);\n if (!key) continue;\n counts.set(key, (counts.get(key) ?? 0) + 1);\n }\n return [...counts.entries()]\n .map(([key, count]) => ({ key, count }))\n .sort((a, b) => b.count - a.count || a.key.localeCompare(b.key))\n .slice(0, topN);\n}\n\nexport async function notificationSummary(\n ctx: CliContext,\n _args: unknown[],\n opts: SummaryOpts,\n): Promise<unknown> {\n const sample = opts.sample ? Number(opts.sample) : 30;\n const top = opts.top ? Number(opts.top) : 10;\n const options = buildQueryOptions({ ...opts, limit: String(MAX_LIMIT) }, MAX_LIMIT);\n const items = await queryNotifications(ctx.paths, options);\n return {\n ok: true,\n total: items.length,\n range: { from: opts.from ?? null, to: opts.to ?? null },\n topApps: topCounts(items, (n) => n.appDisplayName || n.appName, top),\n topSenders: topCounts(items, (n) => n.senderName || n.title, top),\n sample: items.slice(0, sample),\n };\n}\n\ninterface StatsOpts {\n from?: string;\n to?: string;\n app?: string;\n dim?: string;\n}\n\nconst HOUR_KEY = (n: StoredNotification): string =>\n String(new Date(n.timestamp).getHours()).padStart(2, \"0\");\n\nexport async function notificationStats(\n ctx: CliContext,\n _args: unknown[],\n opts: StatsOpts,\n): Promise<unknown> {\n const from = opts.from ?? daysAgo(7);\n const to = opts.to ?? today();\n const dim = opts.dim ?? \"all\";\n const allowed = [\"date\", \"app\", \"sender\", \"hour\", \"all\"];\n if (!allowed.includes(dim)) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", `--dim 只能是 ${allowed.join(\"|\")}`);\n }\n const options: NotificationQueryOptions = {\n app: opts.app,\n limit: MAX_LIMIT,\n fromTs: null,\n toTs: null,\n fromDateKey: from,\n toDateKey: to,\n };\n const items = await queryNotifications(ctx.paths, options);\n\n const byDate = topCounts(items, (n) => formatDate(new Date(n.timestamp)), MAX_LIMIT);\n const byApp = topCounts(items, (n) => n.appDisplayName || n.appName, MAX_LIMIT);\n const bySender = topCounts(items, (n) => n.senderName || n.title, MAX_LIMIT);\n const byHour = topCounts(items, HOUR_KEY, MAX_LIMIT);\n\n const dims = { date: byDate, app: byApp, sender: bySender, hour: byHour };\n return {\n ok: true,\n total: items.length,\n range: { from, to },\n dim,\n ...(dim === \"all\" ? dims : { [dim]: dims[dim as keyof typeof dims] }),\n };\n}\n\nexport function notificationStoragePath(ctx: CliContext): unknown {\n return { ok: true, path: ctx.paths.notifications };\n}\n\nexport async function notificationToday(ctx: CliContext): Promise<unknown> {\n const day = today();\n const options = buildQueryOptions({\n from: `${day}T00:00:00${tzOffset()}`,\n to: `${day}T23:59:59${tzOffset()}`,\n limit: String(MAX_LIMIT),\n }, MAX_LIMIT);\n return queryNotifications(ctx.paths, options);\n}\n\nexport async function notificationRecent(ctx: CliContext): Promise<unknown> {\n const fromTs = Date.now() - 60 * 60 * 1000;\n const options: NotificationQueryOptions = {\n limit: MAX_LIMIT,\n fromTs,\n toTs: null,\n fromDateKey: formatDate(new Date(fromTs)),\n toDateKey: null,\n };\n return queryNotifications(ctx.paths, options);\n}\n\nexport function notificationUnread(): unknown {\n throw new YoooclawError(\n \"YOOOCLAW_NOT_IMPLEMENTED\",\n \"+unread 预留:需要先落地通知的已读状态模型\",\n );\n}\n\n/** 本地时区偏移,如 +08:00。 */\nfunction tzOffset(): string {\n const min = -new Date().getTimezoneOffset();\n const sign = min >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(min);\n const hh = String(Math.floor(abs / 60)).padStart(2, \"0\");\n const mm = String(abs % 60).padStart(2, \"0\");\n return `${sign}${hh}:${mm}`;\n}\n",
39
+ "/**\n * 通知同步 checkpoint 协议(供外部记忆系统按批拉取)。\n * 与 phone-notifications 插件版 `ntf-sync` 行为一致,错误改走 YoooclawError。\n */\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { writeJsonFile } from \"../fs-utils.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport type { StoredNotification } from \"../shared.js\";\n\nexport const SYNC_FETCH_LIMIT = 300;\n\ninterface CheckpointData {\n [dateKey: string]: { lastIndex: number };\n}\n\nfunction checkpointPath(dir: string): string {\n return join(dir, \".checkpoint.json\");\n}\n\nfunction readCheckpoint(dir: string): CheckpointData {\n const p = checkpointPath(dir);\n if (!existsSync(p)) return {};\n try {\n return JSON.parse(readFileSync(p, \"utf-8\")) as CheckpointData;\n } catch {\n return {};\n }\n}\n\nfunction writeCheckpoint(dir: string, data: CheckpointData): void {\n writeJsonFile(checkpointPath(dir), data);\n}\n\nfunction listDateKeys(dir: string): string[] {\n if (!existsSync(dir)) return [];\n const pattern = /^(\\d{4}-\\d{2}-\\d{2})\\.json$/;\n const keys: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const m = pattern.exec(entry.name);\n if (m) keys.push(m[1]);\n }\n return keys.sort((a, b) => b.localeCompare(a));\n}\n\nfunction readDateFile(dir: string, dateKey: string): StoredNotification[] {\n const filePath = join(dir, `${dateKey}.json`);\n if (!existsSync(filePath)) return [];\n try {\n const parsed = JSON.parse(readFileSync(filePath, \"utf-8\"));\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nfunction parseIndexOption(raw: string, label: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isInteger(n) || String(n) !== raw || n < 0) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", `${label} 必须是非负整数`);\n }\n return n;\n}\n\nexport function scanSync(dir: string): unknown {\n const checkpoint = readCheckpoint(dir);\n const pending: { date: string; count: number; startIndex: number }[] = [];\n let totalPending = 0;\n for (const dateKey of listDateKeys(dir)) {\n const items = readDateFile(dir, dateKey);\n const lastIndex = checkpoint[dateKey]?.lastIndex ?? -1;\n const unprocessed = items.length - (lastIndex + 1);\n if (unprocessed > 0) {\n pending.push({ date: dateKey, count: unprocessed, startIndex: lastIndex + 1 });\n totalPending += unprocessed;\n }\n }\n return { ok: true, pending, totalPending };\n}\n\nexport function fetchSync(dir: string, date: string, maxEndIndexRaw?: string): unknown {\n const items = readDateFile(dir, date);\n if (items.length === 0) {\n throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `日期 ${date} 无通知数据`);\n }\n const checkpoint = readCheckpoint(dir);\n const lastIndex = checkpoint[date]?.lastIndex ?? -1;\n const startIndex = lastIndex + 1;\n let maxEndIndex = items.length - 1;\n if (maxEndIndexRaw) {\n maxEndIndex = Math.min(parseIndexOption(maxEndIndexRaw, \"--max-end-index\"), items.length - 1);\n }\n const snapshotEndExclusive = Math.max(startIndex, maxEndIndex + 1);\n const unprocessed = items.slice(startIndex, snapshotEndExclusive);\n const notifications = unprocessed.slice(0, SYNC_FETCH_LIMIT);\n const endIndex = notifications.length > 0 ? startIndex + notifications.length - 1 : lastIndex;\n const hasMore = unprocessed.length > notifications.length;\n return {\n ok: true,\n date,\n startIndex,\n endIndex,\n nextStartIndex: hasMore ? endIndex + 1 : null,\n limit: SYNC_FETCH_LIMIT,\n maxEndIndex,\n returned: notifications.length,\n totalUnprocessed: unprocessed.length,\n hasMore,\n notifications,\n };\n}\n\nexport function commitSync(dir: string, date: string, endIndexRaw?: string): unknown {\n const items = readDateFile(dir, date);\n if (items.length === 0) {\n throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `日期 ${date} 无通知数据`);\n }\n const checkpoint = readCheckpoint(dir);\n const lastIndex = checkpoint[date]?.lastIndex ?? -1;\n let committedIndex: number;\n let commitMode: string;\n if (endIndexRaw) {\n committedIndex = parseIndexOption(endIndexRaw, \"--end-index\");\n if (committedIndex >= items.length) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--end-index 超出当前日期通知文件范围\");\n }\n if (committedIndex < lastIndex) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--end-index 早于当前 checkpoint,不能回退消费进度\");\n }\n if (committedIndex > lastIndex + SYNC_FETCH_LIMIT) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--end-index 超出单批 fetch 上限,不能跳过未处理通知\");\n }\n commitMode = \"exact-end-index\";\n } else {\n committedIndex = Math.min(items.length - 1, lastIndex + SYNC_FETCH_LIMIT);\n commitMode = \"legacy-batch-limit\";\n }\n const hasMore = committedIndex < items.length - 1;\n checkpoint[date] = { lastIndex: committedIndex };\n writeCheckpoint(dir, checkpoint);\n return {\n ok: true,\n date,\n committedIndex,\n commitMode,\n limit: SYNC_FETCH_LIMIT,\n hasMore,\n nextStartIndex: hasMore ? committedIndex + 1 : null,\n };\n}\n",
40
+ "/**\n * sync service —— scan / fetch / commit(通知同步给记忆系统)。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { scanSync, fetchSync, commitSync } from \"../notification/sync.js\";\n\nexport function syncScan(ctx: CliContext): unknown {\n return scanSync(ctx.paths.notifications);\n}\n\nexport function syncFetch(\n ctx: CliContext,\n _args: unknown[],\n opts: { date?: string; maxEndIndex?: string },\n): unknown {\n if (!opts.date) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--date 必填(YYYY-MM-DD)\");\n }\n return fetchSync(ctx.paths.notifications, opts.date, opts.maxEndIndex);\n}\n\nexport function syncCommit(\n ctx: CliContext,\n _args: unknown[],\n opts: { date?: string; endIndex?: string },\n): unknown {\n if (!opts.date) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--date 必填(YYYY-MM-DD)\");\n }\n return commitSync(ctx.paths.notifications, opts.date, opts.endIndex);\n}\n",
41
+ "/**\n * recording service —— list / status / storage-path / setup-asr + +latest。\n * 查询纯读磁盘(🟢);setup-asr 写 asr-config.json(🟢)。\n */\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { ensureDir, writeJsonFile } from \"../fs-utils.js\";\nimport { ask, isInteractive } from \"../prompt.js\";\nimport { readRecordingIndex, type CliRecordingEntry } from \"../shared.js\";\n\nfunction readIndex(ctx: CliContext): CliRecordingEntry[] {\n if (!existsSync(ctx.paths.recordings)) return [];\n return readRecordingIndex(ctx.paths.recordings);\n}\n\nfunction toListItem(r: CliRecordingEntry) {\n return {\n id: r.id,\n name: r.metadata.name,\n duration_sec: r.metadata.duration_sec,\n status: r.status,\n file_size_bytes: r.metadata.file_size_bytes,\n has_audio: Boolean(r.audioFile),\n has_transcript: Boolean(r.transcriptFile),\n created_at: r.metadata.created_at,\n updated_at: r.updatedAt,\n error: r.lastError ?? null,\n };\n}\n\nexport function recordingList(\n ctx: CliContext,\n _args: unknown[],\n opts: { status?: string },\n): unknown {\n let recordings = readIndex(ctx);\n if (opts.status) recordings = recordings.filter((r) => r.status === opts.status);\n return { ok: true, total: recordings.length, recordings: recordings.map(toListItem) };\n}\n\nexport function recordingStatus(ctx: CliContext, args: unknown[]): unknown {\n const [id] = args as [string];\n const entry = readIndex(ctx).find((r) => r.id === id);\n if (!entry) {\n throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `录音不存在:${id}`);\n }\n return {\n ok: true,\n recording: {\n id: entry.id,\n name: entry.metadata.name,\n duration_sec: entry.metadata.duration_sec,\n file_size_bytes: entry.metadata.file_size_bytes,\n status: entry.status,\n created_at: entry.metadata.created_at,\n location: (entry.metadata as Record<string, unknown>).location ?? null,\n markers: (entry.metadata as Record<string, unknown>).markers ?? [],\n audioFile: entry.audioFile ?? null,\n srtFile: entry.srtFile ?? null,\n transcriptDataFile: entry.transcriptDataFile ?? null,\n transcriptFile: entry.transcriptFile ?? null,\n summaryFile: entry.summaryFile ?? null,\n title: entry.title ?? null,\n error: entry.lastError ?? null,\n ingestedAt: entry.ingestedAt,\n updatedAt: entry.updatedAt,\n },\n };\n}\n\nexport function recordingStoragePath(ctx: CliContext): unknown {\n return { ok: true, path: ctx.paths.recordings };\n}\n\nexport function recordingLatest(ctx: CliContext): unknown {\n const recordings = readIndex(ctx).sort(\n (a, b) => Date.parse(b.metadata.created_at) - Date.parse(a.metadata.created_at),\n );\n if (recordings.length === 0) {\n return { ok: true, recording: null };\n }\n return recordingStatus(ctx, [recordings[0].id]);\n}\n\ninterface SetupAsrOpts {\n provider?: string;\n apiKey?: string;\n nonInteractive?: boolean;\n}\n\nexport async function recordingSetupAsr(\n ctx: CliContext,\n _args: unknown[],\n opts: SetupAsrOpts,\n): Promise<unknown> {\n let provider = opts.provider;\n let apiKey = opts.apiKey;\n\n if (!opts.nonInteractive && isInteractive()) {\n provider = await ask(\"ASR provider(volcengine / whisper-local 等)\", provider ?? \"volcengine\");\n if (provider !== \"whisper-local\") {\n apiKey = await ask(\"ASR API key(留空跳过)\", apiKey ?? \"\");\n }\n }\n if (!provider) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"缺少 --provider(非交互模式必填)\");\n }\n\n const config: Record<string, unknown> = { provider };\n if (apiKey) config.apiKey = apiKey;\n\n ensureDir(ctx.paths.recordings);\n const path = join(ctx.paths.recordings, \"asr-config.json\");\n writeJsonFile(path, config);\n return { ok: true, path, provider, keyConfigured: Boolean(apiKey) };\n}\n",
42
+ "/**\n * 图片本地存储读取(images/index.json)。\n *\n * 元数据与同步状态机由 daemon 的图片通道写入(见 PRD「图片通道」);\n * CLI 的 image 查询命令纯读这里,不需要 daemon 在跑。\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { ProfilePaths } from \"../paths.js\";\n\nexport type ImageSyncStatus = \"syncing\" | \"synced\" | \"sync_failed\";\n\nexport interface ImageMetadata {\n oss_image_url: string;\n created_at: string;\n mime_type?: string;\n width?: number;\n height?: number;\n size_bytes?: number;\n source_app?: string;\n caption?: string;\n}\n\nexport interface ImageIndexEntry {\n imageId: string;\n metadata: ImageMetadata;\n /** 相对 images/ 的本地路径,如 files/img_xxx.jpg。 */\n localFile?: string | null;\n thumbnail?: string | null;\n status: ImageSyncStatus;\n lastError?: string | null;\n syncedAt?: string | null;\n}\n\nexport function imagesIndexPath(paths: ProfilePaths): string {\n return join(paths.images, \"index.json\");\n}\n\n/** 读取图片索引;目录/文件不存在返回空数组。 */\nexport function readImageIndex(paths: ProfilePaths): ImageIndexEntry[] {\n const indexPath = imagesIndexPath(paths);\n if (!existsSync(indexPath)) return [];\n try {\n const raw = JSON.parse(readFileSync(indexPath, \"utf-8\"));\n return Array.isArray(raw?.images) ? raw.images : [];\n } catch {\n return [];\n }\n}\n\n/** 把索引里的相对路径解析为绝对路径。 */\nexport function resolveImageFile(\n paths: ProfilePaths,\n relative: string,\n): string {\n return isAbsolute(relative) ? relative : join(paths.images, relative);\n}\n",
43
+ "/**\n * image service —— list / status / path / storage-path + +latest(🟢,纯读磁盘)。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport {\n readImageIndex,\n resolveImageFile,\n type ImageIndexEntry,\n} from \"../image/storage.js\";\nimport { matchesNotificationAppFilter } from \"../shared.js\";\n\ninterface ListOpts {\n status?: string;\n app?: string;\n from?: string;\n to?: string;\n limit?: string;\n}\n\nfunction byCreatedDesc(a: ImageIndexEntry, b: ImageIndexEntry): number {\n return Date.parse(b.metadata.created_at) - Date.parse(a.metadata.created_at);\n}\n\nexport function imageList(\n ctx: CliContext,\n _args: unknown[],\n opts: ListOpts,\n): unknown {\n let items = readImageIndex(ctx.paths);\n if (opts.status) items = items.filter((i) => i.status === opts.status);\n if (opts.app) {\n const app = opts.app;\n items = items.filter((i) =>\n matchesNotificationAppFilter(\n { appName: i.metadata.source_app ?? \"\", title: \"\", content: \"\", timestamp: \"\" },\n app,\n ),\n );\n }\n if (opts.from) {\n const fromTs = Date.parse(opts.from);\n items = items.filter((i) => Date.parse(i.metadata.created_at) >= fromTs);\n }\n if (opts.to) {\n const toTs = Date.parse(opts.to);\n items = items.filter((i) => Date.parse(i.metadata.created_at) <= toTs);\n }\n items = items.sort(byCreatedDesc);\n const limit = opts.limit ? Number(opts.limit) : 100;\n return { ok: true, total: items.length, images: items.slice(0, limit) };\n}\n\nexport function imageStatus(ctx: CliContext, args: unknown[]): unknown {\n const [id] = args as [string];\n const entry = readImageIndex(ctx.paths).find((i) => i.imageId === id);\n if (!entry) throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `图片不存在:${id}`);\n return { ok: true, image: entry };\n}\n\nexport function imagePath(\n ctx: CliContext,\n args: unknown[],\n opts: { thumbnail?: boolean },\n): unknown {\n const [id] = args as [string];\n const entry = readImageIndex(ctx.paths).find((i) => i.imageId === id);\n if (!entry) throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `图片不存在:${id}`);\n\n const relative = opts.thumbnail ? entry.thumbnail : entry.localFile;\n if (entry.status !== \"synced\" || !relative) {\n throw new YoooclawError(\n \"YOOOCLAW_IMAGE_NOT_READY\",\n `图片 ${id} 尚未下载完成`,\n { status: entry.status, lastError: entry.lastError ?? null },\n );\n }\n return { ok: true, path: resolveImageFile(ctx.paths, relative) };\n}\n\nexport function imageStoragePath(ctx: CliContext): unknown {\n return { ok: true, path: ctx.paths.images };\n}\n\nexport function imageLatest(ctx: CliContext): unknown {\n const items = readImageIndex(ctx.paths).sort(byCreatedDesc);\n return { ok: true, image: items[0] ?? null };\n}\n",
44
+ "/**\n * daemon 日志读取 —— 解析 `daemon.log` + 轮转文件 `daemon.log.YYYY-MM-DD`。\n *\n * 行格式(与 daemon logger 写入一致):`<ISO时间> [LEVEL] message`。\n */\nimport { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n\nexport interface LogLine {\n date: string;\n level: string;\n time: string;\n message: string;\n raw: string;\n}\n\nconst LINE_RE = /^(\\d{4}-\\d{2}-\\d{2})(T\\S+)?\\s+\\[(\\w+)\\]\\s+(.*)$/;\n\nexport interface LogQuery {\n keyword?: string;\n level?: string;\n from?: string;\n to?: string;\n limit: number;\n}\n\n/** 收集 daemon 当前日志 + 轮转日志文件路径(按日期倒序,current 在最前)。 */\nfunction logFiles(daemonLog: string): string[] {\n const dir = dirname(daemonLog);\n const base = basename(daemonLog);\n if (!existsSync(dir)) return [];\n const rotated = readdirSync(dir)\n .filter((f) => f.startsWith(`${base}.`) && /\\.\\d{4}-\\d{2}-\\d{2}$/.test(f))\n .sort((a, b) => b.localeCompare(a))\n .map((f) => join(dir, f));\n const files: string[] = [];\n if (existsSync(daemonLog)) files.push(daemonLog);\n files.push(...rotated);\n return files;\n}\n\nfunction parseLine(raw: string): LogLine | null {\n const m = LINE_RE.exec(raw);\n if (!m) return null;\n return {\n date: m[1],\n time: (m[1] + (m[2] ?? \"\")),\n level: m[3].toLowerCase(),\n message: m[4],\n raw,\n };\n}\n\nexport function searchLogs(daemonLog: string, query: LogQuery): LogLine[] {\n const keyword = query.keyword?.toLowerCase();\n const level = query.level?.toLowerCase();\n const results: LogLine[] = [];\n\n for (const file of logFiles(daemonLog)) {\n const content = readFileSync(file, \"utf-8\");\n // 单文件内按出现顺序,整体最新文件在前 → 反转每个文件使最新行靠前\n const lines = content.split(\"\\n\").filter(Boolean).reverse();\n for (const raw of lines) {\n if (results.length >= query.limit) return results;\n const parsed = parseLine(raw);\n const date = parsed?.date;\n if (query.from && date && date < query.from) continue;\n if (query.to && date && date > query.to) continue;\n if (level && parsed && parsed.level !== level) continue;\n if (keyword && !raw.toLowerCase().includes(keyword)) continue;\n results.push(parsed ?? { date: \"\", time: \"\", level: \"\", message: raw, raw });\n }\n }\n return results;\n}\n",
45
+ "/**\n * log service —— `log [keyword]` + `+errors`(🟢,纯读 daemon 日志文件)。\n */\nimport type { CliContext } from \"../context.js\";\nimport { searchLogs } from \"../log/reader.js\";\nimport { daysAgo, today } from \"../shared.js\";\n\ninterface LogOpts {\n from?: string;\n to?: string;\n limit?: string;\n level?: string;\n}\n\nexport function logSearch(\n ctx: CliContext,\n args: unknown[],\n opts: LogOpts,\n): unknown {\n const [keyword] = args as [string | undefined];\n const lines = searchLogs(ctx.paths.daemonLog, {\n keyword,\n level: opts.level,\n from: opts.from ?? daysAgo(7),\n to: opts.to ?? today(),\n limit: opts.limit ? Number(opts.limit) : 50,\n });\n return { ok: true, keyword: keyword ?? null, total: lines.length, lines };\n}\n\nexport function logErrors(ctx: CliContext): unknown {\n const lines = searchLogs(ctx.paths.daemonLog, {\n level: \"error\",\n from: daysAgo(1),\n to: today(),\n limit: 50,\n });\n return { ok: true, level: \"error\", total: lines.length, lines };\n}\n",
46
+ "/**\n * migrate from-openclaw —— 把 ~/.openclaw 插件数据接管到 ~/.yoooclaw/profiles/<profile>。\n */\nimport { cpSync, existsSync, readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { CliContext } from \"../context.js\";\nimport { ensureDir, readJsonFile, writeJsonFile, SECRET_FILE_MODE } from \"../fs-utils.js\";\nimport { sharedCredentialsPath } from \"../paths.js\";\nimport { API_KEY_FIELD } from \"../credentials/store.js\";\n\ninterface MigrateOpts {\n dryRun?: boolean;\n source?: string;\n}\n\ninterface SubdirPlan {\n name: string;\n source: string;\n target: string;\n exists: boolean;\n fileCount: number;\n}\n\nfunction countFiles(dir: string): number {\n if (!existsSync(dir)) return 0;\n try {\n return readdirSync(dir, { recursive: true } as never).length;\n } catch {\n return 0;\n }\n}\n\nexport function migrateFromOpenclaw(\n ctx: CliContext,\n _args: unknown[],\n opts: MigrateOpts,\n): unknown {\n const sourceRoot = opts.source ?? join(homedir(), \".openclaw\");\n const pluginRoot = join(sourceRoot, \"plugins\", \"phone-notifications\");\n\n const plans: SubdirPlan[] = [\n { name: \"notifications\", source: join(pluginRoot, \"notifications\"), target: ctx.paths.notifications },\n { name: \"recordings\", source: join(pluginRoot, \"recordings\"), target: ctx.paths.recordings },\n { name: \"light-rules\", source: join(pluginRoot, \"light-rules\"), target: ctx.paths.lightRules },\n { name: \"images\", source: join(pluginRoot, \"images\"), target: ctx.paths.images },\n ].map((p) => ({ ...p, exists: existsSync(p.source), fileCount: countFiles(p.source) }));\n\n // api-key 迁移计划\n const srcCreds = readJsonFile<Record<string, unknown>>(join(sourceRoot, \"credentials.json\"));\n const srcApiKey = typeof srcCreds?.[API_KEY_FIELD] === \"string\" ? (srcCreds[API_KEY_FIELD] as string) : undefined;\n const sharedPath = sharedCredentialsPath();\n const existingShared = readJsonFile<Record<string, unknown>>(sharedPath);\n const apiKeyAction = !srcApiKey\n ? \"none\"\n : existingShared?.[API_KEY_FIELD]\n ? \"skip-existing\"\n : \"copy\";\n\n const backupDir = `${ctx.paths.dir}.bak-${Date.now()}`;\n const willBackup = existsSync(ctx.paths.dir) && readdirSync(ctx.paths.dir).length > 0;\n\n if (opts.dryRun) {\n return {\n ok: true,\n dryRun: true,\n source: sourceRoot,\n profile: ctx.profile,\n backup: willBackup ? backupDir : null,\n subdirs: plans,\n apiKey: { action: apiKeyAction },\n hint: \"迁移前请先停止 openclaw 客户端,避免插件还在写 notifications 导致数据竞争\",\n };\n }\n\n if (willBackup) {\n cpSync(ctx.paths.dir, backupDir, { recursive: true });\n }\n ensureDir(ctx.paths.dir);\n\n const migrated: string[] = [];\n for (const plan of plans) {\n if (!plan.exists) continue;\n cpSync(plan.source, plan.target, { recursive: true });\n migrated.push(plan.name);\n }\n\n let apiKeyResult = apiKeyAction;\n if (apiKeyAction === \"copy\" && srcApiKey) {\n const data = existingShared ?? {};\n data[API_KEY_FIELD] = srcApiKey;\n writeJsonFile(sharedPath, data, SECRET_FILE_MODE);\n apiKeyResult = \"copied\";\n }\n\n return {\n ok: true,\n source: sourceRoot,\n profile: ctx.profile,\n backup: willBackup ? backupDir : null,\n migrated,\n apiKey: { action: apiKeyResult },\n };\n}\n",
47
+ "/**\n * update self —— 查 npm registry 比对版本并提示,不做自动更新(PRD 决策:走 npm)。\n */\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { CLI_VERSION } from \"../version.js\";\n\nconst PACKAGE = \"@yoooclaw/cli\";\nconst REGISTRY = \"https://registry.npmjs.org\";\n\ninterface UpdateOpts {\n beta?: boolean;\n json?: boolean;\n}\n\nfunction compareSemver(a: string, b: string): number {\n const pa = a.split(\"-\")[0].split(\".\").map(Number);\n const pb = b.split(\"-\")[0].split(\".\").map(Number);\n for (let i = 0; i < 3; i += 1) {\n const d = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (d !== 0) return d > 0 ? 1 : -1;\n }\n return 0;\n}\n\nexport async function updateSelf(\n _ctx: CliContext,\n _args: unknown[],\n opts: UpdateOpts,\n): Promise<unknown> {\n const tag = opts.beta ? \"beta\" : \"latest\";\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 8000);\n let latest: string;\n try {\n const res = await fetch(`${REGISTRY}/${encodeURIComponent(PACKAGE)}`, {\n signal: controller.signal,\n headers: { Accept: \"application/vnd.npm.install-v1+json\" },\n });\n if (!res.ok) {\n throw new YoooclawError(\"YOOOCLAW_NETWORK_ERROR\", `npm registry 返回 ${res.status}`);\n }\n const body = (await res.json()) as { \"dist-tags\"?: Record<string, string> };\n const resolved = body[\"dist-tags\"]?.[tag];\n if (!resolved) {\n throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `npm dist-tag \\`${tag}\\` 不存在`);\n }\n latest = resolved;\n } catch (err) {\n if (err instanceof YoooclawError) throw err;\n throw new YoooclawError(\"YOOOCLAW_NETWORK_ERROR\", `查询 npm registry 失败:${(err as Error).message}`);\n } finally {\n clearTimeout(timer);\n }\n\n const updateAvailable = compareSemver(latest, CLI_VERSION) > 0;\n return {\n ok: true,\n package: PACKAGE,\n channel: tag,\n current: CLI_VERSION,\n latest,\n updateAvailable,\n command: updateAvailable ? `npm update -g ${PACKAGE}` : null,\n hint: updateAvailable\n ? \"发现新版本;CLI 不做自动更新,请手动执行上面的命令\"\n : \"已是最新版本\",\n };\n}\n",
48
+ "/**\n * doctor —— 环境自检。默认仅做**无网络、无 keychain 也确定性**的本地检查(PRD 可测试性要求)。\n * 网络类自检(relay / OSS 出站可达性)交给 gateway test / tunnel +test。\n */\nimport { accessSync, constants, existsSync, statSync } from \"node:fs\";\nimport type { CliContext } from \"../context.js\";\nimport { ensureDir } from \"../fs-utils.js\";\nimport { rootDir } from \"../paths.js\";\nimport { configExists, loadConfig } from \"../config/store.js\";\nimport { resolveApiKey, resolveGatewayToken } from \"../credentials/store.js\";\nimport { keychainAvailable } from \"../credentials/keychain.js\";\nimport { daemonState } from \"../daemon/lock.js\";\n\ntype CheckStatus = \"ok\" | \"warn\" | \"fail\" | \"skip\";\ninterface Check {\n name: string;\n status: CheckStatus;\n detail: string;\n}\n\nconst MIN_NODE = [22, 12, 0];\n\nfunction checkNode(): Check {\n const parts = process.versions.node.split(\".\").map(Number);\n let ok = true;\n for (let i = 0; i < 3; i += 1) {\n if ((parts[i] ?? 0) > MIN_NODE[i]) break;\n if ((parts[i] ?? 0) < MIN_NODE[i]) { ok = false; break; }\n }\n return {\n name: \"node-version\",\n status: ok ? \"ok\" : \"fail\",\n detail: `Node ${process.versions.node}(要求 >= ${MIN_NODE.join(\".\")})`,\n };\n}\n\nfunction checkDir(name: string, dir: string, fix: boolean): Check {\n if (!existsSync(dir)) {\n if (fix) {\n ensureDir(dir);\n return { name, status: \"ok\", detail: `已创建 ${dir}` };\n }\n return { name, status: \"warn\", detail: `目录不存在:${dir}(--fix 可创建)` };\n }\n try {\n accessSync(dir, constants.R_OK | constants.W_OK);\n } catch {\n return { name, status: \"fail\", detail: `目录不可读写:${dir}` };\n }\n const mode = statSync(dir).mode & 0o777;\n const tooOpen = (mode & 0o077) !== 0;\n return {\n name,\n status: tooOpen ? \"warn\" : \"ok\",\n detail: `${dir}(mode ${mode.toString(8)}${tooOpen ? \",建议收紧到 700\" : \"\"})`,\n };\n}\n\nexport function doctor(\n ctx: CliContext,\n _args: unknown[],\n opts: { json?: boolean; fix?: boolean },\n): unknown {\n const fix = Boolean(opts.fix);\n const checks: Check[] = [checkNode(), checkDir(\"root-dir\", rootDir(), fix)];\n\n // profile 配置\n if (configExists(ctx.paths)) {\n try {\n loadConfig(ctx.paths);\n checks.push({ name: \"profile-config\", status: \"ok\", detail: `${ctx.paths.config} 可解析` });\n } catch (err) {\n checks.push({ name: \"profile-config\", status: \"fail\", detail: (err as Error).message });\n }\n } else {\n checks.push({\n name: \"profile-config\",\n status: \"warn\",\n detail: `profile \\`${ctx.profile}\\` 未初始化(yoooclaw config init)`,\n });\n }\n\n // api-key\n const apiKey = resolveApiKey();\n checks.push({\n name: \"api-key\",\n status: apiKey.value ? \"ok\" : \"warn\",\n detail: apiKey.value ? `来源 ${apiKey.source}` : \"未配置(yoooclaw auth set-api-key)\",\n });\n\n // gateway token\n if (configExists(ctx.paths)) {\n const token = resolveGatewayToken(loadConfig(ctx.paths));\n checks.push({\n name: \"gateway-token\",\n status: token.value ? \"ok\" : \"warn\",\n detail: token.value ? `来源 ${token.source}` : \"未设置(yoooclaw auth token-rotate)\",\n });\n }\n\n // keychain(可选加固,不可用只是 skip)\n checks.push({\n name: \"keychain\",\n status: keychainAvailable() ? \"ok\" : \"skip\",\n detail: keychainAvailable() ? \"可用\" : \"当前平台无可用 keychain,凭据将落文件\",\n });\n\n // daemon(不在跑只是 info/warn)\n const state = daemonState(ctx.paths);\n checks.push({\n name: \"daemon\",\n status: state.running ? \"ok\" : state.stale ? \"warn\" : \"skip\",\n detail: state.running\n ? `运行中(pid ${state.lock?.pid})`\n : state.stale\n ? \"锁文件存在但进程已死(陈旧锁)\"\n : \"未运行\",\n });\n\n const failed = checks.filter((c) => c.status === \"fail\").length;\n const warned = checks.filter((c) => c.status === \"warn\").length;\n return {\n ok: failed === 0,\n profile: ctx.profile,\n summary: { total: checks.length, failed, warned },\n checks,\n note: \"网络类自检(relay / OSS 可达性)请用 yoooclaw gateway test / tunnel +test\",\n };\n}\n",
49
+ "/**\n * daemon service —— start / stop / restart / status / logs / run-foreground(🔵)。\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, statSync, watchFile } from \"node:fs\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { requireConfig } from \"../config/store.js\";\nimport { daemonState, isProcessAlive, readLock, removeLock } from \"../daemon/lock.js\";\nimport { DaemonClient } from \"../daemon/client.js\";\nimport { runDaemonForeground, type DaemonStartOpts } from \"../daemon/main.js\";\n\ninterface StartOpts {\n bind?: string;\n port?: string;\n detach?: boolean; // commander:--no-detach → false\n logLevel?: string;\n}\n\nfunction startOpts(opts: StartOpts): DaemonStartOpts {\n return {\n bind: opts.bind,\n port: opts.port ? Number(opts.port) : undefined,\n logLevel: opts.logLevel,\n };\n}\n\n/** 内部命令:前台运行 daemon 主循环(detach 子进程入口)。 */\nexport async function daemonRunForeground(\n ctx: CliContext,\n _args: unknown[],\n opts: StartOpts,\n): Promise<unknown> {\n await runDaemonForeground(ctx, startOpts(opts));\n return { ok: true }; // 实际不会到这(runDaemonForeground 不 resolve)\n}\n\nexport async function daemonStart(\n ctx: CliContext,\n _args: unknown[],\n opts: StartOpts,\n): Promise<unknown> {\n requireConfig(ctx.paths);\n const state = daemonState(ctx.paths);\n if (state.running) {\n throw new YoooclawError(\n \"YOOOCLAW_DAEMON_ALREADY_RUNNING\",\n `daemon 已在运行(pid ${state.lock?.pid})`,\n { pid: state.lock?.pid },\n );\n }\n if (state.stale) removeLock(ctx.paths);\n\n // --no-detach:前台运行(systemd/launchd 包装)\n if (opts.detach === false) {\n await runDaemonForeground(ctx, startOpts(opts));\n return { ok: true };\n }\n\n // 默认:fork 子进程跑 run-foreground 并 detach\n const binEntry = process.argv[1];\n const args = [binEntry, \"daemon\", \"run-foreground\", \"--profile\", ctx.profile];\n if (opts.bind) args.push(\"--bind\", opts.bind);\n if (opts.port) args.push(\"--port\", opts.port);\n if (opts.logLevel) args.push(\"--log-level\", opts.logLevel);\n\n const child = spawn(process.execPath, args, {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n env: process.env,\n });\n child.unref();\n\n // 轮询 lock 确认起来(最多 ~3s)\n for (let i = 0; i < 30; i += 1) {\n await sleep(100);\n const s = daemonState(ctx.paths);\n if (s.running) {\n return { ok: true, pid: s.lock?.pid, bind: s.lock?.bind, port: s.lock?.port, detached: true };\n }\n }\n throw new YoooclawError(\n \"YOOOCLAW_UNKNOWN\",\n \"daemon 启动超时(3s 内未写出 lock)\",\n { hint: \"查看 yoooclaw daemon logs 排查\" },\n );\n}\n\nexport async function daemonStop(ctx: CliContext): Promise<unknown> {\n const lock = readLock(ctx.paths);\n if (!lock || !isProcessAlive(lock.pid)) {\n removeLock(ctx.paths);\n throw new YoooclawError(\"YOOOCLAW_DAEMON_NOT_RUNNING\", \"daemon 未运行\");\n }\n try {\n process.kill(lock.pid, \"SIGTERM\");\n } catch {\n /* 进程可能刚退出 */\n }\n // 等待优雅退出,最多 10s\n for (let i = 0; i < 100; i += 1) {\n await sleep(100);\n if (!isProcessAlive(lock.pid)) {\n removeLock(ctx.paths);\n return { ok: true, stopped: lock.pid, signal: \"SIGTERM\" };\n }\n }\n try {\n process.kill(lock.pid, \"SIGKILL\");\n } catch {\n /* ignore */\n }\n removeLock(ctx.paths);\n return { ok: true, stopped: lock.pid, signal: \"SIGKILL\" };\n}\n\nexport async function daemonRestart(\n ctx: CliContext,\n args: unknown[],\n opts: StartOpts,\n): Promise<unknown> {\n const lock = readLock(ctx.paths);\n const inheritedOpts: StartOpts = {\n ...opts,\n bind: opts.bind ?? lock?.bind,\n port: opts.port ?? (lock?.port ? String(lock.port) : undefined),\n logLevel: opts.logLevel ?? lock?.logLevel,\n };\n if (lock && isProcessAlive(lock.pid)) {\n await daemonStop(ctx);\n }\n return daemonStart(ctx, args, inheritedOpts);\n}\n\nexport async function daemonStatus(ctx: CliContext): Promise<unknown> {\n const state = daemonState(ctx.paths);\n if (!state.running) {\n throw new YoooclawError(\n \"YOOOCLAW_DAEMON_NOT_RUNNING\",\n \"daemon 未运行\",\n { stale: state.stale, hint: \"yoooclaw daemon start\" },\n );\n }\n const client = new DaemonClient(ctx.paths);\n const res = await client.get(\"/daemon/status\");\n return res.body;\n}\n\ninterface LogsOpts {\n follow?: boolean;\n lines?: string;\n level?: string;\n}\n\nfunction tailLines(file: string, n: number): string[] {\n if (!existsSync(file)) return [];\n const content = readFileSync(file, \"utf-8\").split(\"\\n\").filter(Boolean);\n return content.slice(-n);\n}\n\nexport async function daemonLogs(\n ctx: CliContext,\n _args: unknown[],\n opts: LogsOpts,\n): Promise<unknown> {\n const n = opts.lines ? Number(opts.lines) : 100;\n const file = ctx.paths.daemonLog;\n let lines = tailLines(file, n);\n if (opts.level) {\n const want = `[${opts.level.toUpperCase()}]`;\n lines = lines.filter((l) => l.includes(want));\n }\n\n if (!opts.follow) {\n return { ok: true, file, total: lines.length, lines };\n }\n\n // --follow:先打印 tail,再持续输出新增行(raw 到 stdout,不经 --format)\n for (const l of lines) process.stdout.write(l + \"\\n\");\n let size = existsSync(file) ? statSync(file).size : 0;\n await new Promise<void>(() => {\n watchFile(file, { interval: 500 }, () => {\n if (!existsSync(file)) return;\n const cur = statSync(file).size;\n if (cur > size) {\n const chunk = readFileSync(file, \"utf-8\").slice(-(cur - size));\n size = cur;\n process.stdout.write(chunk);\n } else if (cur < size) {\n size = cur; // 轮转\n }\n });\n });\n return { ok: true };\n}\n",
50
+ "/**\n * daemon 主循环(前台运行体)。`daemon start` 默认 fork 一个子进程跑 `daemon run-foreground`,\n * 该命令最终调用这里的 runDaemonForeground。\n *\n * 职责:单实例锁 → 装配 StandaloneRuntime + 存储 + 通知/图片/灯效规则注册 → 起 HTTP server →\n * 写 lock → 捕获信号优雅退出。\n *\n * 关于 Relay:本独立 daemon 当前以**直连 HTTP** 接收手机推送(POST /notifications,配合用户自建\n * cloudflared / tailscale serve 反代,见 PRD 内网穿透决策)。yoooclaw 托管 Relay 隧道为后续迭代,\n * tunnel status 如实反映「standalone HTTP 模式」。\n */\nimport { createServer, type IncomingMessage, type ServerResponse, type Server } from \"node:http\";\nimport type { CliContext } from \"../context.js\";\nimport { loadConfig } from \"../config/store.js\";\nimport { resolveGatewayToken } from \"../credentials/store.js\";\nimport { daemonState, writeLock, removeLock } from \"./lock.js\";\nimport { DaemonLogger } from \"./logger.js\";\nimport { StandaloneRuntime } from \"./runtime.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { ensureDir } from \"../fs-utils.js\";\nimport { ingestImage, type ImageSyncPayload } from \"../image/channel.js\";\nimport { listMonitors, createMonitor, deleteMonitor, setMonitorEnabled } from \"../monitor/store.js\";\nimport { CLI_VERSION } from \"../version.js\";\nimport {\n NotificationStorage,\n registerNotificationInterfaces,\n LightRuleRegistry,\n registerLightRulesGateway,\n validateSegments,\n type PluginConfig,\n} from \"../shared.js\";\n\nexport const PROTOCOL_VERSION = 1;\nexport const CAPABILITIES = [\"notifications\", \"recordings\", \"images\", \"lightrules\"];\n\nexport interface DaemonStartOpts {\n bind?: string;\n port?: number;\n logLevel?: string;\n}\n\ninterface DaemonState {\n startedAt: string;\n lastIngestAt: string | null;\n ingestCount: number;\n}\n\nasync function readBody(req: IncomingMessage): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(body));\n}\n\nexport async function runDaemonForeground(\n ctx: CliContext,\n opts: DaemonStartOpts,\n): Promise<void> {\n const state = daemonState(ctx.paths);\n if (state.running) {\n throw new YoooclawError(\n \"YOOOCLAW_DAEMON_ALREADY_RUNNING\",\n `daemon 已在运行(pid ${state.lock?.pid})`,\n );\n }\n\n const config = loadConfig(ctx.paths);\n const bind = opts.bind ?? config.daemon.bind;\n const port = opts.port ?? config.daemon.port;\n const logLevel = (opts.logLevel ?? config.daemon.logLevel) as never;\n const token = resolveGatewayToken(config).value;\n\n // 安全:绑公网必须有 token\n const loopback = bind === \"127.0.0.1\" || bind === \"::1\" || bind === \"localhost\";\n if (!loopback && !token) {\n throw new YoooclawError(\n \"YOOOCLAW_UNAUTHORIZED\",\n `绑定 ${bind} 需要先设置 gateway token`,\n { hint: \"运行 yoooclaw auth token-rotate 或改回 127.0.0.1\" },\n );\n }\n\n ensureDir(ctx.paths.dir);\n const logger = new DaemonLogger(ctx.paths.daemonLog, logLevel, false);\n const runtimeState: DaemonState = {\n startedAt: new Date().toISOString(),\n lastIngestAt: null,\n ingestCount: 0,\n };\n\n const pluginConfig: PluginConfig = {\n retentionDays: config.notification.retentionDays ?? undefined,\n ignoredApps: config.notification.ignoredApps,\n };\n\n const runtime = new StandaloneRuntime(logger, pluginConfig as Record<string, unknown>, ctx.paths.dir);\n\n // 通知存储\n const storage = new NotificationStorage(ctx.paths.notifications, pluginConfig, logger);\n await storage.init();\n\n // 灯效规则注册(rules 落 <profile>/tasks/)\n const lightRuleRegistry = new LightRuleRegistry({ workspaceDir: ctx.paths.dir });\n\n const ignored = new Set(config.notification.ignoredApps ?? []);\n registerNotificationInterfaces({\n // 结构兼容 OpenClawPluginApi 的子集\n api: runtime as never,\n logger,\n getStorage: () => storage,\n filterNotifications: (items) => items.filter((n) => !ignored.has(n.app)),\n registerGatewayMethod: (m, h) => runtime.registerGatewayMethod(m, h as never),\n onAfterIngest: (inserted) => {\n runtimeState.lastIngestAt = new Date().toISOString();\n runtimeState.ingestCount += inserted.length;\n },\n });\n registerLightRulesGateway(runtime as never, lightRuleRegistry, logger);\n\n const server = createServer((req, res) => {\n void handleRequest(req, res).catch((err) => {\n logger.error(`请求处理异常:${(err as Error).message}`);\n if (!res.headersSent) sendJson(res, 500, { ok: false, error: { code: \"INTERNAL_ERROR\", message: (err as Error).message } });\n });\n });\n\n function authorized(req: IncomingMessage): boolean {\n if (!token) return true; // 仅 loopback 且未设 token 时\n const header = req.headers[\"authorization\"];\n return header === `Bearer ${token}`;\n }\n\n async function handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const path = url.pathname;\n const method = req.method ?? \"GET\";\n\n // /health 公开(手机端协议协商)\n if (path === \"/health\" && method === \"GET\") {\n sendJson(res, 200, {\n server: \"yoooclaw\",\n version: CLI_VERSION,\n protocol: PROTOCOL_VERSION,\n capabilities: CAPABILITIES,\n });\n return;\n }\n\n if (!authorized(req)) {\n sendJson(res, 401, { ok: false, error: { code: \"YOOOCLAW_UNAUTHORIZED\", message: \"token 不一致或缺失\" } });\n return;\n }\n\n // ── 控制面 ──\n if (path === \"/daemon/status\" && method === \"GET\") {\n sendJson(res, 200, {\n ok: true,\n server: \"yoooclaw\",\n version: CLI_VERSION,\n pid: process.pid,\n profile: ctx.profile,\n bind,\n port,\n startedAt: runtimeState.startedAt,\n lastIngestAt: runtimeState.lastIngestAt,\n ingestCount: runtimeState.ingestCount,\n lightRules: lightRuleRegistry.list().length,\n relay: { mode: \"standalone-http\", connected: false, url: config.relay.url, enabled: config.relay.enabled },\n memoryRssBytes: process.memoryUsage().rss,\n });\n return;\n }\n if (path === \"/daemon/stop\" && method === \"POST\") {\n sendJson(res, 200, { ok: true, stopping: true });\n logger.info(\"收到 /daemon/stop,准备优雅退出\");\n setTimeout(() => void shutdown(\"stop-endpoint\"), 50);\n return;\n }\n if (path === \"/tunnel/status\" && method === \"GET\") {\n sendJson(res, 200, {\n ok: true,\n mode: \"standalone-http\",\n connected: false,\n relayUrl: config.relay.url,\n enabled: config.relay.enabled,\n note: \"独立 daemon 当前走直连 HTTP 接收推送;yoooclaw 托管 Relay 为后续迭代。可用 cloudflared / tailscale serve 反代\",\n });\n return;\n }\n if (path === \"/tunnel/reconnect\" && method === \"POST\") {\n sendJson(res, 200, { ok: true, mode: \"standalone-http\", reconnected: false, note: \"standalone HTTP 模式无 relay 连接可重连\" });\n return;\n }\n if (path === \"/tunnel/test\" && method === \"POST\") {\n // 回环自检:daemon 自己 POST 一条 echo 通知到本地 /notifications\n const echo = await selfEchoCheck(`http://127.0.0.1:${port}`, token);\n sendJson(res, 200, { ok: echo.ok, mode: \"standalone-http\", loopback: echo });\n return;\n }\n if (path === \"/light/send\" && method === \"POST\") {\n const body = await parseJson(req, res);\n if (body === undefined) return;\n await handleLightSend(body, res);\n return;\n }\n if (path === \"/images\" && method === \"POST\") {\n const body = await parseJson(req, res);\n if (body === undefined) return;\n try {\n const result = ingestImage(ctx.paths, body as ImageSyncPayload, {\n maxBytes: config.image.maxBytes,\n logger,\n });\n sendJson(res, 200, result);\n } catch (err) {\n sendJson(res, 400, { ok: false, error: { code: \"INVALID_PARAMS\", message: (err as Error).message } });\n }\n return;\n }\n // monitors CRUD(定义存储;本 build 不做 live cron 触发)\n if (path === \"/monitors\" && method === \"GET\") {\n sendJson(res, 200, { ok: true, monitors: listMonitors(ctx.paths) });\n return;\n }\n if (path === \"/monitors\" && method === \"POST\") {\n const body = await parseJson(req, res);\n if (body === undefined) return;\n try {\n sendJson(res, 200, { ok: true, monitor: createMonitor(ctx.paths, body as never) });\n } catch (err) {\n sendJson(res, 400, { ok: false, error: { code: \"INVALID_PARAMS\", message: (err as Error).message } });\n }\n return;\n }\n if (path.startsWith(\"/monitors/\") && method === \"DELETE\") {\n const name = decodeURIComponent(path.slice(\"/monitors/\".length));\n sendJson(res, 200, { ok: true, deleted: deleteMonitor(ctx.paths, name) });\n return;\n }\n if (path.startsWith(\"/monitors/\") && method === \"POST\") {\n const [, , name, action] = path.split(\"/\");\n const enabled = action === \"enable\";\n sendJson(res, 200, { ok: setMonitorEnabled(ctx.paths, decodeURIComponent(name), enabled), name, enabled });\n return;\n }\n\n // gateway 桥:POST /gateway/<method>\n if (path.startsWith(\"/gateway/\") && method === \"POST\") {\n const gwMethod = path.slice(\"/gateway/\".length);\n const body = await parseJson(req, res);\n if (body === undefined) return;\n const result = await runtime.callGateway(gwMethod, body);\n sendJson(res, result.ok ? 200 : 400, result);\n return;\n }\n\n // 注册的 HTTP 路由(如 POST /notifications)\n const route = runtime.httpRoutes.get(path);\n if (route) {\n await route.handler(req, res);\n return;\n }\n\n sendJson(res, 404, { ok: false, error: { code: \"YOOOCLAW_NOT_FOUND\", message: `未知路径:${path}` } });\n }\n\n async function parseJson(req: IncomingMessage, res: ServerResponse): Promise<unknown | undefined> {\n try {\n const raw = await readBody(req);\n return raw ? JSON.parse(raw) : {};\n } catch {\n sendJson(res, 400, { ok: false, error: { code: \"INVALID_PARAMS\", message: \"请求体不是合法 JSON\" } });\n return undefined;\n }\n }\n\n async function handleLightSend(body: unknown, res: ServerResponse): Promise<void> {\n const input = body as { segments?: unknown; preset?: string };\n if (!input.segments && !input.preset) {\n sendJson(res, 400, { ok: false, error: { code: \"INVALID_PARAMS\", message: \"需要 --segments 或 --preset\" } });\n return;\n }\n if (input.segments) {\n const validation = validateSegments(input.segments);\n if (!validation.valid) {\n sendJson(res, 400, { ok: false, error: { code: \"VALIDATION_FAILED\", message: JSON.stringify(validation.errors) } });\n return;\n }\n }\n // standalone 无已注册设备会话 → 接受但未投递(需 relay/手机在线)\n logger.info(`/light/send 已接收(preset=${input.preset ?? \"-\"});standalone 无连接设备,未实际投递`);\n sendJson(res, 200, {\n ok: true,\n accepted: true,\n delivered: false,\n reason: \"standalone daemon 暂无连接的灯效设备会话(需手机端在线 / relay)\",\n });\n }\n\n let serverRef: Server | null = null;\n let shuttingDown = false;\n async function shutdown(reason: string): Promise<void> {\n if (shuttingDown) return;\n shuttingDown = true;\n logger.info(`daemon 退出(${reason})`);\n try {\n await storage.close();\n } catch {\n /* ignore */\n }\n serverRef?.close();\n removeLock(ctx.paths);\n process.exit(0);\n }\n\n // listen,遇 EADDRINUSE(如 restart 端口尚未释放)退避重试\n const listenOnce = (): Promise<void> =>\n new Promise<void>((resolve, reject) => {\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener(\"listening\", onListening);\n reject(err);\n };\n const onListening = () => {\n server.removeListener(\"error\", onError);\n resolve();\n };\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen(port, bind);\n });\n\n for (let attempt = 0; ; attempt += 1) {\n try {\n await listenOnce();\n break;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EADDRINUSE\" && attempt < 10) {\n await new Promise((r) => setTimeout(r, 200));\n continue;\n }\n throw err;\n }\n }\n serverRef = server;\n writeLock(ctx.paths, {\n pid: process.pid,\n startedAt: runtimeState.startedAt,\n bind,\n port,\n logLevel: String(logLevel),\n });\n logger.info(`yoooclaw daemon 启动:${bind}:${port}(profile=${ctx.profile}, pid=${process.pid})`);\n\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"));\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"));\n\n // 前台保持运行(http server 维持 event loop);返回的 promise 永不 resolve\n await new Promise<void>(() => {});\n}\n\nasync function selfEchoCheck(baseUrl: string, token?: string): Promise<{ ok: boolean; status?: number; error?: string }> {\n try {\n const res = await fetch(`${baseUrl}/notifications`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n body: JSON.stringify({\n notifications: [\n { id: `echo_${Date.now()}`, app: \"yoooclaw.selftest\", title: \"tunnel +test\", body: \"echo\", timestamp: new Date().toISOString() },\n ],\n }),\n });\n return { ok: res.ok, status: res.status };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n",
51
+ "/**\n * daemon 文件 logger —— 写 `daemon.log`,按日期轮转为 `daemon.log.YYYY-MM-DD`。\n * 行格式:`<ISO本地时间> [LEVEL] message`(与 src/log/reader.ts 解析一致)。\n */\nimport { appendFileSync, existsSync, renameSync, statSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { ensureDir } from \"../fs-utils.js\";\nimport type { LogLevel } from \"../config/schema.js\";\n\nconst LEVEL_ORDER: Record<string, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n trace: 4,\n};\n\nfunction isoLocal(d: Date): string {\n const pad = (n: number, w = 2) => String(n).padStart(w, \"0\");\n const off = -d.getTimezoneOffset();\n const sign = off >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(off);\n return (\n `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` +\n `T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}` +\n `${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`\n );\n}\n\nfunction dateKey(d: Date): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\nexport class DaemonLogger {\n private currentDay: string;\n\n constructor(\n private readonly logFile: string,\n private readonly level: LogLevel = \"info\",\n private readonly alsoStderr = false,\n ) {\n ensureDir(dirname(logFile));\n this.currentDay = dateKey(new Date());\n this.rotateIfNeeded(new Date());\n }\n\n private enabled(level: string): boolean {\n return (LEVEL_ORDER[level] ?? 2) <= (LEVEL_ORDER[this.level] ?? 2);\n }\n\n private rotateIfNeeded(now: Date): void {\n if (!existsSync(this.logFile)) return;\n let fileDay: string | undefined;\n try {\n fileDay = dateKey(statSync(this.logFile).mtime);\n } catch {\n return;\n }\n const today = dateKey(now);\n if (fileDay !== today) {\n try {\n renameSync(this.logFile, `${this.logFile}.${fileDay}`);\n } catch {\n // 轮转失败不影响写入\n }\n }\n }\n\n private write(level: string, msg: string): void {\n if (!this.enabled(level)) return;\n const now = new Date();\n if (dateKey(now) !== this.currentDay) {\n this.rotateIfNeeded(now);\n this.currentDay = dateKey(now);\n }\n const line = `${isoLocal(now)} [${level.toUpperCase()}] ${msg}\\n`;\n try {\n appendFileSync(this.logFile, line);\n } catch {\n // 忽略写文件失败\n }\n if (this.alsoStderr) process.stderr.write(line);\n }\n\n debug(msg: string): void { this.write(\"debug\", msg); }\n info(msg: string): void { this.write(\"info\", msg); }\n warn(msg: string): void { this.write(\"warn\", msg); }\n error(msg: string): void { this.write(\"error\", msg); }\n}\n",
52
+ "/**\n * StandaloneRuntime —— 对外暴露**结构兼容** OpenClawPluginApi 的子集,\n * 让 phone-notifications 的注册模块(registerNotificationInterfaces /\n * registerLightRulesGateway 等)**不改代码**就能在 daemon 里跑。\n *\n * 实现侧:把注册进来的 HTTP 路由与 gateway 方法收集到 Map,由 daemon HTTP server 派发。\n * 不属于 CLI 形态的能力(registerTool / registerCli / on('before_prompt_build'))做 no-op。\n */\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport type HttpAuth = \"gateway\" | \"public\" | string;\nexport interface HttpRouteSpec {\n path: string;\n auth?: HttpAuth;\n handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;\n}\n\nexport type GatewayRespond = (\n ok: boolean,\n data?: unknown,\n error?: { code: string; message: string },\n) => void;\n\nexport interface GatewayOpts {\n params?: unknown;\n respond: GatewayRespond;\n context?: { broadcast?: (event: string, payload: unknown) => void };\n client?: unknown;\n}\nexport type GatewayHandler = (opts: GatewayOpts) => void | Promise<void>;\n\nexport interface GatewayResult {\n ok: boolean;\n data?: unknown;\n error?: { code: string; message: string };\n}\n\ninterface RuntimeLogger {\n debug: (m: string) => void;\n info: (m: string) => void;\n warn: (m: string) => void;\n error: (m: string) => void;\n}\n\nexport class StandaloneRuntime {\n readonly httpRoutes = new Map<string, HttpRouteSpec>();\n readonly gatewayMethods = new Map<string, GatewayHandler>();\n readonly services: string[] = [];\n\n constructor(\n readonly logger: RuntimeLogger,\n readonly pluginConfig: Record<string, unknown>,\n private readonly stateDir: string,\n ) {}\n\n /** runtime.state.resolveStateDir —— 兼容插件读 stateDir 的用法。 */\n readonly runtime = {\n state: {\n resolveStateDir: (): string => this.stateDir,\n },\n };\n\n registerHttpRoute(spec: HttpRouteSpec): void {\n this.httpRoutes.set(spec.path, spec);\n }\n\n registerGatewayMethod(method: string, handler: GatewayHandler): void {\n this.gatewayMethods.set(method, handler);\n }\n\n // ── CLI 形态下的 no-op(PRD「兼容性 shim」)──\n registerService(name: string): void {\n this.services.push(typeof name === \"string\" ? name : \"service\");\n }\n registerCli(): void {\n /* CLI 模式不复用插件 CLI 注册 */\n }\n registerTool(): void {\n /* CLI 不开 MCP,Agent 走 Skill + 直接调命令 */\n }\n on(): void {\n /* before_prompt_build 等宿主事件在 CLI 模式不参与 */\n }\n\n /** 调用一个 gateway 方法,把 respond 收敛成 Promise<GatewayResult>。 */\n callGateway(method: string, params: unknown): Promise<GatewayResult> {\n const handler = this.gatewayMethods.get(method);\n if (!handler) {\n return Promise.resolve({\n ok: false,\n error: { code: \"METHOD_NOT_FOUND\", message: `未注册的 gateway 方法:${method}` },\n });\n }\n return new Promise<GatewayResult>((resolve) => {\n let settled = false;\n const respond: GatewayRespond = (ok, data, error) => {\n if (settled) return;\n settled = true;\n resolve({ ok, data, error });\n };\n Promise.resolve(handler({ params, respond })).catch((err) => {\n if (!settled) {\n settled = true;\n resolve({\n ok: false,\n error: { code: \"INTERNAL_ERROR\", message: (err as Error).message },\n });\n }\n });\n });\n }\n}\n",
53
+ "/**\n * 图片下发通道 —— 与录音链路同构:先落元数据 + respond(true),再后台从 OSS 下载本体。\n *\n * 入口:daemon 的 HTTP `POST /images` 与 gateway `images.sync` 都调用 ingestImage。\n * 复刻录音的同步状态机:syncing → synced / sync_failed;imageId 幂等去重。\n */\nimport { createWriteStream, existsSync, readFileSync } from \"node:fs\";\nimport { Readable } from \"node:stream\";\nimport { join } from \"node:path\";\nimport { ensureDir, writeJsonFile } from \"../fs-utils.js\";\nimport type { ProfilePaths } from \"../paths.js\";\nimport {\n imagesIndexPath,\n type ImageIndexEntry,\n type ImageMetadata,\n} from \"./storage.js\";\n\nexport interface ImageSyncPayload {\n imageId: string;\n image: ImageMetadata;\n}\n\ninterface ChannelLogger {\n info: (m: string) => void;\n warn: (m: string) => void;\n}\n\nfunction readAll(paths: ProfilePaths): ImageIndexEntry[] {\n const p = imagesIndexPath(paths);\n if (!existsSync(p)) return [];\n try {\n const raw = JSON.parse(readFileSync(p, \"utf-8\"));\n return Array.isArray(raw?.images) ? raw.images : [];\n } catch {\n return [];\n }\n}\n\nfunction writeAll(paths: ProfilePaths, images: ImageIndexEntry[]): void {\n ensureDir(paths.images);\n writeJsonFile(imagesIndexPath(paths), { images });\n}\n\nfunction upsert(paths: ProfilePaths, entry: ImageIndexEntry): void {\n const images = readAll(paths);\n const idx = images.findIndex((i) => i.imageId === entry.imageId);\n if (idx >= 0) images[idx] = entry;\n else images.push(entry);\n writeAll(paths, images);\n}\n\nfunction extFromMime(mime?: string): string {\n if (!mime) return \"jpg\";\n if (mime.includes(\"png\")) return \"png\";\n if (mime.includes(\"webp\")) return \"webp\";\n if (mime.includes(\"gif\")) return \"gif\";\n return \"jpg\";\n}\n\nexport interface IngestImageResult {\n ok: boolean;\n imageId: string;\n status: ImageIndexEntry[\"status\"];\n deduped?: boolean;\n}\n\n/**\n * 接收图片下发:校验必填 → 落 syncing 元数据 → 后台下载(fire-and-forget)。\n * 幂等:imageId 已存在且 oss_image_url 未变化则跳过重复下载。\n */\nexport function ingestImage(\n paths: ProfilePaths,\n payload: ImageSyncPayload,\n opts: { maxBytes: number; logger: ChannelLogger },\n): IngestImageResult {\n const { imageId, image } = payload;\n if (!imageId || !image?.oss_image_url || !image?.created_at) {\n throw new Error(\"imageId / image.oss_image_url / image.created_at 必填\");\n }\n\n const existing = readAll(paths).find((i) => i.imageId === imageId);\n if (existing && existing.metadata.oss_image_url === image.oss_image_url && existing.status === \"synced\") {\n return { ok: true, imageId, status: \"synced\", deduped: true };\n }\n\n const entry: ImageIndexEntry = {\n imageId,\n metadata: image,\n localFile: null,\n thumbnail: null,\n status: \"syncing\",\n lastError: null,\n syncedAt: null,\n };\n upsert(paths, entry);\n\n void downloadInBackground(paths, entry, opts).catch((err) => {\n opts.logger.warn(`image[${imageId}] 后台下载异常:${(err as Error).message}`);\n });\n\n return { ok: true, imageId, status: \"syncing\" };\n}\n\nasync function downloadInBackground(\n paths: ProfilePaths,\n entry: ImageIndexEntry,\n opts: { maxBytes: number; logger: ChannelLogger },\n): Promise<void> {\n const filesDir = join(paths.images, \"files\");\n ensureDir(filesDir);\n const relative = `files/${entry.imageId}.${extFromMime(entry.metadata.mime_type)}`;\n const dest = join(paths.images, relative);\n\n try {\n const res = await fetch(entry.metadata.oss_image_url);\n if (!res.ok || !res.body) {\n throw new Error(`OSS 返回 ${res.status}`);\n }\n const declared = Number(res.headers.get(\"content-length\") ?? \"0\");\n if (declared && declared > opts.maxBytes) {\n throw new Error(`图片超过上限 ${opts.maxBytes} 字节`);\n }\n\n let written = 0;\n const fileStream = createWriteStream(dest);\n const reader = Readable.fromWeb(res.body as never);\n for await (const chunk of reader) {\n written += (chunk as Buffer).length;\n if (written > opts.maxBytes) {\n fileStream.destroy();\n throw new Error(`图片超过上限 ${opts.maxBytes} 字节`);\n }\n fileStream.write(chunk);\n }\n await new Promise<void>((resolve, reject) => {\n fileStream.end((err?: Error | null) => (err ? reject(err) : resolve()));\n });\n\n upsert(paths, {\n ...entry,\n localFile: relative,\n status: \"synced\",\n lastError: null,\n syncedAt: new Date().toISOString(),\n });\n opts.logger.info(`image[${entry.imageId}] 下载完成 (${written} bytes)`);\n } catch (err) {\n upsert(paths, {\n ...entry,\n status: \"sync_failed\",\n lastError: (err as Error).message,\n });\n opts.logger.warn(`image[${entry.imageId}] 下载失败:${(err as Error).message}`);\n }\n}\n",
54
+ "/**\n * 监控任务定义存储(state/monitors.json)。\n *\n * 本 build 负责定义的 CRUD 与启用状态;cron 实时触发为后续迭代(daemon 当前只持久化定义)。\n */\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { ProfilePaths } from \"../paths.js\";\nimport { ensureDir, writeJsonFile } from \"../fs-utils.js\";\n\nexport interface MonitorTask {\n name: string;\n description: string;\n matchRules: unknown;\n schedule: string;\n enabled: boolean;\n createdAt: string;\n updatedAt: string;\n lastRunAt: string | null;\n lastResult: unknown;\n}\n\nexport interface CreateMonitorInput {\n name: string;\n description: string;\n matchRules: unknown;\n schedule: string;\n}\n\nfunction storePath(paths: ProfilePaths): string {\n return join(paths.state, \"monitors.json\");\n}\n\nexport function listMonitors(paths: ProfilePaths): MonitorTask[] {\n const p = storePath(paths);\n if (!existsSync(p)) return [];\n try {\n const raw = JSON.parse(readFileSync(p, \"utf-8\"));\n return Array.isArray(raw?.monitors) ? raw.monitors : [];\n } catch {\n return [];\n }\n}\n\nfunction save(paths: ProfilePaths, monitors: MonitorTask[]): void {\n ensureDir(paths.state);\n writeJsonFile(storePath(paths), { monitors });\n}\n\nexport function createMonitor(paths: ProfilePaths, input: CreateMonitorInput): MonitorTask {\n if (!input.name || !input.description || !input.schedule || input.matchRules === undefined) {\n throw new Error(\"name / description / matchRules / schedule 均必填\");\n }\n const monitors = listMonitors(paths);\n if (monitors.some((m) => m.name === input.name)) {\n throw new Error(`监控任务已存在:${input.name}`);\n }\n const now = new Date().toISOString();\n const task: MonitorTask = {\n name: input.name,\n description: input.description,\n matchRules: input.matchRules,\n schedule: input.schedule,\n enabled: true,\n createdAt: now,\n updatedAt: now,\n lastRunAt: null,\n lastResult: null,\n };\n monitors.push(task);\n save(paths, monitors);\n return task;\n}\n\nexport function deleteMonitor(paths: ProfilePaths, name: string): boolean {\n const monitors = listMonitors(paths);\n const next = monitors.filter((m) => m.name !== name);\n if (next.length === monitors.length) return false;\n save(paths, next);\n return true;\n}\n\nexport function setMonitorEnabled(paths: ProfilePaths, name: string, enabled: boolean): boolean {\n const monitors = listMonitors(paths);\n const task = monitors.find((m) => m.name === name);\n if (!task) return false;\n task.enabled = enabled;\n task.updatedAt = new Date().toISOString();\n save(paths, monitors);\n return true;\n}\n\nexport function getMonitor(paths: ProfilePaths, name: string): MonitorTask | undefined {\n return listMonitors(paths).find((m) => m.name === name);\n}\n",
55
+ "/**\n * 依赖 daemon 的 service(🟡)—— 统一经 DaemonClient 走 localhost HTTP RPC。\n * light / lightrule / tunnel / monitor / gateway / api。\n */\nimport { readFileSync } from \"node:fs\";\nimport type { CliContext } from \"../context.js\";\nimport { YoooclawError } from \"../errors.js\";\nimport { DaemonClient, assertDaemonRunning } from \"../daemon/client.js\";\nimport { confirm, readStdin } from \"../prompt.js\";\n\nfunction client(ctx: CliContext): DaemonClient {\n assertDaemonRunning(ctx.paths);\n return new DaemonClient(ctx.paths);\n}\n\nfunction parseJsonArg(raw: string | undefined, label: string): unknown {\n if (raw === undefined) return undefined;\n try {\n return JSON.parse(raw);\n } catch {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", `${label} 不是合法 JSON`);\n }\n}\n\n// ── light ──\nexport async function lightSend(\n ctx: CliContext,\n _args: unknown[],\n opts: { segments?: string; preset?: string; repeat?: boolean; repeatTimes?: string },\n): Promise<unknown> {\n const body: Record<string, unknown> = {};\n if (opts.segments) body.segments = parseJsonArg(opts.segments, \"--segments\");\n if (opts.preset) body.preset = opts.preset;\n if (opts.repeat) body.repeat = true;\n if (opts.repeatTimes !== undefined) body.repeat_times = Number(opts.repeatTimes);\n const res = await client(ctx).post(\"/light/send\", body);\n return res.body;\n}\n\nexport async function lightBlink(ctx: CliContext): Promise<unknown> {\n const res = await client(ctx).post(\"/light/send\", { preset: \"blink\" });\n return res.body;\n}\n\n// ── lightrule ──\nasync function listRules(c: DaemonClient): Promise<Array<Record<string, unknown>>> {\n const res = await c.post<{ data?: { rules?: Array<Record<string, unknown>> } }>(\"/gateway/lightrules.list\", {});\n return res.body?.data?.rules ?? [];\n}\n\nexport async function lightruleList(ctx: CliContext): Promise<unknown> {\n return { ok: true, rules: await listRules(client(ctx)) };\n}\n\nexport async function lightruleShow(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [id] = args as [string];\n const rule = (await listRules(client(ctx))).find((r) => r.id === id || r.name === id);\n if (!rule) throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `规则不存在:${id}`);\n return { ok: true, rule };\n}\n\ninterface LightRuleOpts {\n fromFile?: string;\n name?: string;\n intent?: string;\n lightAction?: string;\n matchRules?: string;\n}\n\nasync function buildRuleParams(opts: LightRuleOpts, name?: string): Promise<Record<string, unknown>> {\n if (opts.fromFile) {\n const raw = opts.fromFile === \"-\" ? await readStdin() : readFileSync(opts.fromFile, \"utf-8\");\n return JSON.parse(raw) as Record<string, unknown>;\n }\n const params: Record<string, unknown> = {};\n if (name) params.name = name;\n if (opts.name) params.name = opts.name;\n if (opts.intent) params.description = opts.intent;\n const action = parseJsonArg(opts.lightAction, \"--light-action\");\n if (action !== undefined) {\n params.segments = Array.isArray(action) ? action : (action as { segments?: unknown }).segments ?? action;\n }\n const match = parseJsonArg(opts.matchRules, \"--match-rules\");\n if (match !== undefined) params.matchRules = match;\n return params;\n}\n\nexport async function lightruleCreate(\n ctx: CliContext,\n _args: unknown[],\n opts: LightRuleOpts,\n): Promise<unknown> {\n const c = client(ctx);\n const params = await buildRuleParams(opts);\n const res = await c.post(\"/gateway/lightrules.create\", params);\n if (!res.body || (res.body as { ok?: boolean }).ok === false) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", JSON.stringify((res.body as { error?: unknown })?.error ?? res.body));\n }\n return (res.body as { data?: unknown }).data ?? res.body;\n}\n\nexport async function lightruleUpdate(\n ctx: CliContext,\n args: unknown[],\n opts: LightRuleOpts,\n): Promise<unknown> {\n const [id] = args as [string];\n const c = client(ctx);\n const params = await buildRuleParams(opts, id);\n params.name = id;\n const res = await c.post(\"/gateway/lightrules.update\", params);\n return (res.body as { data?: unknown }).data ?? res.body;\n}\n\nexport async function lightruleDelete(\n ctx: CliContext,\n args: unknown[],\n opts: { yes?: boolean },\n): Promise<unknown> {\n const [id] = args as [string];\n if (!opts.yes && !(await confirm(`确认删除规则 \\`${id}\\`?`, false))) {\n throw new YoooclawError(\"YOOOCLAW_CONFIRMATION_REQUIRED\", \"已取消\");\n }\n const res = await client(ctx).post(\"/gateway/lightrules.delete\", { name: id });\n return (res.body as { data?: unknown }).data ?? res.body;\n}\n\nexport async function lightruleEnable(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [id] = args as [string];\n const res = await client(ctx).post(\"/gateway/lightrules.update\", { name: id, enabled: true });\n return (res.body as { data?: unknown }).data ?? res.body;\n}\n\nexport async function lightruleDisable(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [id] = args as [string];\n const res = await client(ctx).post(\"/gateway/lightrules.update\", { name: id, enabled: false });\n return (res.body as { data?: unknown }).data ?? res.body;\n}\n\nasync function toggleAll(ctx: CliContext, enabled: boolean): Promise<unknown> {\n const c = client(ctx);\n const rules = await listRules(c);\n const results: Array<{ name: unknown; ok: boolean }> = [];\n for (const rule of rules) {\n const res = await c.post(\"/gateway/lightrules.update\", { name: rule.name, enabled });\n results.push({ name: rule.name, ok: (res.body as { ok?: boolean })?.ok !== false });\n }\n return { ok: true, enabled, count: results.length, results };\n}\n\nexport const lightruleOn = (ctx: CliContext): Promise<unknown> => toggleAll(ctx, true);\nexport const lightruleOff = (ctx: CliContext): Promise<unknown> => toggleAll(ctx, false);\n\n// ── tunnel ──\nexport async function tunnelStatus(ctx: CliContext): Promise<unknown> {\n return (await client(ctx).get(\"/tunnel/status\")).body;\n}\nexport async function tunnelReconnect(ctx: CliContext): Promise<unknown> {\n return (await client(ctx).post(\"/tunnel/reconnect\")).body;\n}\nexport async function tunnelTest(ctx: CliContext): Promise<unknown> {\n return (await client(ctx).post(\"/tunnel/test\")).body;\n}\n\n// ── monitor ──\nexport async function monitorList(ctx: CliContext): Promise<unknown> {\n return (await client(ctx).get(\"/monitors\")).body;\n}\nexport async function monitorShow(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [name] = args as [string];\n const res = await client(ctx).get<{ monitors?: Array<{ name: string }> }>(\"/monitors\");\n const monitor = res.body?.monitors?.find((m) => m.name === name);\n if (!monitor) throw new YoooclawError(\"YOOOCLAW_NOT_FOUND\", `监控任务不存在:${name}`);\n return { ok: true, monitor };\n}\nexport async function monitorCreate(\n ctx: CliContext,\n args: unknown[],\n opts: { description?: string; matchRules?: string; schedule?: string },\n): Promise<unknown> {\n const [name] = args as [string];\n if (!opts.description || !opts.matchRules || !opts.schedule) {\n throw new YoooclawError(\"YOOOCLAW_INVALID_ARGUMENT\", \"--description / --match-rules / --schedule 均必填\");\n }\n const res = await client(ctx).post(\"/monitors\", {\n name,\n description: opts.description,\n matchRules: parseJsonArg(opts.matchRules, \"--match-rules\"),\n schedule: opts.schedule,\n });\n return res.body;\n}\nexport async function monitorDelete(\n ctx: CliContext,\n args: unknown[],\n opts: { yes?: boolean },\n): Promise<unknown> {\n const [name] = args as [string];\n if (!opts.yes && !(await confirm(`确认删除监控任务 \\`${name}\\`?`, false))) {\n throw new YoooclawError(\"YOOOCLAW_CONFIRMATION_REQUIRED\", \"已取消\");\n }\n return (await client(ctx).request(\"DELETE\", `/monitors/${encodeURIComponent(name)}`)).body;\n}\nexport async function monitorEnable(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [name] = args as [string];\n return (await client(ctx).post(`/monitors/${encodeURIComponent(name)}/enable`)).body;\n}\nexport async function monitorDisable(ctx: CliContext, args: unknown[]): Promise<unknown> {\n const [name] = args as [string];\n return (await client(ctx).post(`/monitors/${encodeURIComponent(name)}/disable`)).body;\n}\n\n// ── gateway test ──\nexport async function gatewayTest(\n ctx: CliContext,\n _args: unknown[],\n opts: { fromPhoneIp?: string; viaRelay?: boolean },\n): Promise<unknown> {\n const c = client(ctx);\n if (opts.viaRelay) {\n return { ok: true, viaRelay: true, result: (await c.post(\"/tunnel/test\")).body };\n }\n const probe = {\n notifications: [\n { id: `gwtest_${Date.now()}`, app: \"yoooclaw.gatewaytest\", title: \"gateway test\", body: \"probe\", timestamp: new Date().toISOString() },\n ],\n };\n const res = await c.post(\"/notifications\", probe);\n return {\n ok: res.status >= 200 && res.status < 300,\n fromPhoneIp: opts.fromPhoneIp ?? null,\n status: res.status,\n response: res.body,\n };\n}\n\n// ── raw api ──\nexport async function apiRaw(\n ctx: CliContext,\n args: unknown[],\n opts: { data?: string; header?: string[] | string },\n): Promise<unknown> {\n const [method, path] = args as [string, string];\n let data: unknown;\n if (opts.data) {\n let raw: string;\n if (opts.data === \"-\") raw = await readStdin();\n else if (opts.data.startsWith(\"@\")) raw = readFileSync(opts.data.slice(1), \"utf-8\");\n else raw = opts.data;\n try {\n data = JSON.parse(raw);\n } catch {\n data = raw;\n }\n }\n const headers: Record<string, string> = {};\n const headerList = Array.isArray(opts.header) ? opts.header : opts.header ? [opts.header] : [];\n for (const h of headerList) {\n const idx = h.indexOf(\":\");\n if (idx > 0) headers[h.slice(0, idx).trim()] = h.slice(idx + 1).trim();\n }\n const res = await client(ctx).request(method.toUpperCase(), path, data, headers);\n return { ok: res.status >= 200 && res.status < 300, status: res.status, body: res.body };\n}\n",
56
+ "/**\n * 命令实现注册表 —— path(`<service> <subcommand>`,去掉位置参数占位)→ handler。\n *\n * program.ts 按 path 查表;未注册的命令回落 notImplemented 占位。\n * 新增 service 实现时在此登记即可,命令树结构仍以 command-tree.ts 为准。\n */\nimport type { CommandHandler } from \"../program.js\";\nimport { configInit, configShow, configSet, configUnset } from \"./config.js\";\nimport { profileList, profileUse, profileCreate, profileDelete } from \"./profile.js\";\nimport { authSetApiKey, authStatus, authTokenRotate, authCheck } from \"./auth.js\";\nimport {\n notificationSearch,\n notificationSummary,\n notificationStats,\n notificationStoragePath,\n notificationToday,\n notificationRecent,\n notificationUnread,\n} from \"./notification.js\";\nimport { syncScan, syncFetch, syncCommit } from \"./sync.js\";\nimport {\n recordingList,\n recordingStatus,\n recordingStoragePath,\n recordingLatest,\n recordingSetupAsr,\n} from \"./recording.js\";\nimport {\n imageList,\n imageStatus,\n imagePath,\n imageStoragePath,\n imageLatest,\n} from \"./image.js\";\nimport { logSearch, logErrors } from \"./log.js\";\nimport { migrateFromOpenclaw } from \"./migrate.js\";\nimport { updateSelf } from \"./update.js\";\nimport { doctor } from \"./doctor.js\";\nimport {\n daemonStart,\n daemonStop,\n daemonRestart,\n daemonStatus,\n daemonLogs,\n daemonRunForeground,\n} from \"./daemon.js\";\nimport {\n lightSend,\n lightBlink,\n lightruleList,\n lightruleShow,\n lightruleCreate,\n lightruleUpdate,\n lightruleDelete,\n lightruleEnable,\n lightruleDisable,\n lightruleOn,\n lightruleOff,\n tunnelStatus,\n tunnelReconnect,\n tunnelTest,\n monitorList,\n monitorShow,\n monitorCreate,\n monitorDelete,\n monitorEnable,\n monitorDisable,\n gatewayTest,\n apiRaw,\n} from \"./daemon-services.js\";\n\nexport const HANDLERS: Record<string, CommandHandler> = {\n \"config init\": configInit,\n \"config show\": configShow,\n \"config set\": configSet,\n \"config unset\": configUnset,\n\n \"profile list\": profileList,\n \"profile use\": profileUse,\n \"profile create\": profileCreate,\n \"profile delete\": profileDelete,\n\n \"auth set-api-key\": authSetApiKey,\n \"auth status\": authStatus,\n \"auth token-rotate\": authTokenRotate,\n \"auth check\": authCheck,\n\n \"notification search\": notificationSearch,\n \"notification summary\": notificationSummary,\n \"notification stats\": notificationStats,\n \"notification storage-path\": notificationStoragePath,\n \"notification +today\": notificationToday,\n \"notification +recent\": notificationRecent,\n \"notification +unread\": notificationUnread,\n\n \"sync scan\": syncScan,\n \"sync fetch\": syncFetch,\n \"sync commit\": syncCommit,\n\n \"recording list\": recordingList,\n \"recording status\": recordingStatus,\n \"recording storage-path\": recordingStoragePath,\n \"recording setup-asr\": recordingSetupAsr,\n \"recording +latest\": recordingLatest,\n\n \"image list\": imageList,\n \"image status\": imageStatus,\n \"image path\": imagePath,\n \"image storage-path\": imageStoragePath,\n \"image +latest\": imageLatest,\n\n log: logSearch,\n \"log +errors\": logErrors,\n\n \"migrate from-openclaw\": migrateFromOpenclaw,\n \"update self\": updateSelf,\n doctor,\n\n \"daemon start\": daemonStart,\n \"daemon stop\": daemonStop,\n \"daemon restart\": daemonRestart,\n \"daemon status\": daemonStatus,\n \"daemon logs\": daemonLogs,\n \"daemon run-foreground\": daemonRunForeground,\n\n \"light send\": lightSend,\n \"light +blink\": lightBlink,\n\n \"lightrule list\": lightruleList,\n \"lightrule show\": lightruleShow,\n \"lightrule create\": lightruleCreate,\n \"lightrule update\": lightruleUpdate,\n \"lightrule delete\": lightruleDelete,\n \"lightrule enable\": lightruleEnable,\n \"lightrule disable\": lightruleDisable,\n \"lightrule +on\": lightruleOn,\n \"lightrule +off\": lightruleOff,\n\n \"tunnel status\": tunnelStatus,\n \"tunnel reconnect\": tunnelReconnect,\n \"tunnel +test\": tunnelTest,\n\n \"monitor list\": monitorList,\n \"monitor show\": monitorShow,\n \"monitor create\": monitorCreate,\n \"monitor delete\": monitorDelete,\n \"monitor enable\": monitorEnable,\n \"monitor disable\": monitorDisable,\n\n \"gateway test\": gatewayTest,\n api: apiRaw,\n};\n",
12
57
  "/**\n * `@yoooclaw/cli` 程序化入口。\n *\n * - `run(argv)` 解析并执行命令(bin.ts 调用)。\n * - 同时再导出核心模块,供测试与未来的程序化集成使用。\n */\nimport { buildProgram } from \"./program.js\";\n\nexport async function run(argv: string[] = process.argv): Promise<void> {\n const program = buildProgram();\n await program.parseAsync(argv);\n}\n\nexport { buildProgram } from \"./program.js\";\nexport { COMMAND_TREE } from \"./command-tree.js\";\nexport { CLI_VERSION } from \"./version.js\";\nexport { ErrorCode, YoooclawError } from \"./errors.js\";\nexport {\n renderResult,\n renderError,\n resolveFormat,\n type OutputFormat,\n} from \"./output/format.js\";\nexport {\n buildContext,\n resolveActiveProfile,\n type CliContext,\n type GlobalFlags,\n} from \"./context.js\";\nexport * as paths from \"./paths.js\";\n",
13
58
  "/**\n * yoooclaw CLI 可执行入口。\n * package.json#bin(yoooclaw / yc)指向构建产物 dist/bin.cjs。\n */\nimport { run } from \"./index.js\";\n\nvoid run(process.argv);\n"
14
59
  ],
15
- "mappings": "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",
16
- "debugId": "885B6E71DB5ADDF164756E2164756E21",
60
+ "mappings": "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",
61
+ "debugId": "9E8D45DFD5AB967964756E2164756E21",
17
62
  "names": []
18
63
  }