# dsh-caps-beacon [English](README.md) | 简体中文 把 MacBook 的 **Caps Lock 指示灯**变成 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的状态灯——[Mac-Agent-Beacon](https://github.com/rynzh/Mac-Agent-Beacon) 的 DSH 原生版。 **常亮 = 工作中 · 快闪 = 需要你 · 熄灭 = 空闲** 让 DSH 在后台干活时,你不用再切回来盯屏幕:扫一眼键盘就知道状态。 ## 灯光含义 | 宿主状态 | LED | | --- | --- | | 根 agent 正在运行(工具调用、模型请求、重试) | **常亮** | | 有审批请求在等你 | **快闪** | | `ask_user_question` 提问或计划审批在等你回答 | **快闪** | | 根任务以 `error` / `blocked` 结束(锁存到下一个任务开始) | **快闪** | | 空闲 | **熄灭** | "需要注意"永远压过"工作中":审批一解决,灯立刻回到常亮。默认只盯根 agent(`rootsOnly`),子 agent 扇出不会让你的键盘狂闪。 插件是**纯观察者**:`approval/request` 和 `tools/execute` 监听器一律通过 `next()` 转发,绝不替你做任何决定。它只写 LED——不按键、不改键位映射、 不改审批策略。退出时助手会把物理灯恢复成当前逻辑大写状态。 ## 工作原理 ``` DSH 宿主事件 ──▶ 插件状态机 ──▶ beacon-led (C) ──▶ Caps Lock LED ``` - 插件监听 DSH 的**公开宿主事件**——`agent/status`、`approval/request`、 `tools/execute`、`session/event`。不逆向任何内部接口,agent 栈升级不会 悄悄弄坏它。 - 一个小 C 助手(`native/led.c`,经 Mac-Agent-Beacon 改编自 [CapsPulse](https://github.com/ssk090/capspulse),均为 MIT)通过 macOS IOKit/IOHID 输出元素驱动内置键盘的 Caps Lock LED。插件保活一个 `beacon-led serve` 子进程,往它的 stdin 写 `1`/`0` 字节;快闪由插件内 定时器驱动。 - 助手绝不注入按键。写 LED 期间若逻辑大写状态发生变化,立即停止。 - 助手仍可能因环境原因死亡——系统睡眠重置 HID 设备、信号波及它的进程 组等。插件会自动重启它(指数退避,1 秒到 30 秒)并重新应用当前灯态, 信标自愈,而不是黑到下次重启 dsh。 ## 环境要求 - 带内置 Apple 键盘的 MacBook(外接键盘和 Magic Keyboard 不支持)。 - macOS + Xcode Command Line Tools(`xcode-select --install`,用于一步 `make` 编译)。 - 装好 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`)并有一个 profile——以 `web` 为例测试。 ## 安装 ```sh # 1. 把插件加入 profile(任意 profile 均可,此处以 web 为例)。 dsh plugin --profile web add github:xinyang920/dsh-caps-beacon # 2. 在 pnpm 放置包的位置编译 LED 助手。 cd ~/.dsh/profiles/web/node_modules/dsh-caps-beacon && make # 3. 重启 dsh web——bundle 成员在启动时读取。 ``` 第 1 步会自动把 bundle 注册进 `dsh.profile.bundles`。第 2 步编译 `build/beacon-led`(约一秒;安装器刻意不替你执行编译产物)。第 3 步必需, 因为插件在启动时加载。 ### 如被系统拦截,授予 LED 访问权限 多数机器上助手无需额外授权即可写 LED。如果你的机器拦了: 1. 运行 `./build/beacon-led inspect`——访问被拒时它会说明原因。 2. 打开 **系统设置 → 隐私与安全性 → 输入监控**,点 **+**,按 `Cmd-Shift-G` 输入 profile `node_modules` 里 `dsh-caps-beacon/build/beacon-led` 的绝对路径。 3. 重启 `dsh web`。 ## 验证 ```sh # 助手能找到键盘和 LED 元素: ./build/beacon-led inspect # {"keyboard":"Apple Internal Keyboard / Trackpad","led_output":true,...} # dsh 运行期间助手进程存活: pgrep -fl beacon-led ``` 然后给任意会话派个任务:运行期间 LED 常亮。最简单的快闪测试:让 agent 调用 `ask_user_question` 向你提问——提示等待期间 LED 快闪。 助手失败和异常退出会以 `[dsh-caps-beacon]` 前缀记录在 dsh 日志里。 ## 配置 在 profile 的 `cordis.patch.yml` 里按 id `dsh-caps-beacon` 覆盖(patch 会 替换整行 `config`,需要什么就重述什么): ```yaml - id: dsh-caps-beacon config: enabled: true ledPath: "" # beacon-led 绝对路径;默认:包内 build/beacon-led blinkIntervalMs: 250 rootsOnly: true # 忽略子 agent 和后台子进程 verbose: false # 记录每次模式切换 triggers: approval: true # approval/request 等待中 question: true # ask_user_question / exit_plan_mode 等待中 error: true # 任务以 error/blocked 结束 ``` ## 排查 - **灯从不亮**——dsh 运行时查 `pgrep -fl beacon-led`。没有进程说明插件 没加载:确认 `~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 里有 `dsh-caps-beacon`,然后重启。有进程但灯不亮,通常是外接键盘或 Karabiner 的问题:Karabiner-Elements 独占抓取内置键盘时会挡住 LED。 - **灯在会话中途变黑**——助手死了(系统睡眠、终端 Ctrl+C 是常见诱因)。 v0.1.1 起插件会在几秒内自动复活它;dsh 日志里可见 `[dsh-caps-beacon] helper restarted after failure`。若超过一分钟仍是黑的, 重启 `dsh web`。 - **`make` 失败**——安装 Xcode Command Line Tools (`xcode-select --install`)后重试。 - **升级了插件**——重跑安装第 2 步(包目录里 `make`)让二进制跟上,然后 重启。 ## 卸载 ```sh dsh plugin --profile web remove dsh-caps-beacon ``` 如果你的 dsh 版本没有自动移除,把 `~/.dsh/profiles/web/package.json` 里 `dsh.profile.bundles` 中的 `dsh-caps-beacon` 删掉,然后重启。 ## 致谢 - [Mac-Agent-Beacon](https://github.com/rynzh/Mac-Agent-Beacon)(MIT)—— 原版 Codex 状态灯,LED 助手的 stdin 协议与安全检查直接源自它。本项目 用 DSH 公开宿主事件替换了它最难的部分(逆向 Codex Desktop IPC 流)。 - [CapsPulse](https://github.com/ssk090/capspulse)(MIT)——IOKit/IOHID 控制 Caps Lock LED 的原始技术来源。 见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 ## 许可 [MIT](LICENSE)