agentwake 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.cursor/hooks.json +2 -2
  2. package/README.md +210 -80
  3. package/dist/adapters/claude-hook-adapter.d.ts.map +1 -1
  4. package/dist/adapters/claude-hook-adapter.js +67 -0
  5. package/dist/adapters/claude-hook-adapter.js.map +1 -1
  6. package/dist/adapters/cursor-hook-adapter.d.ts.map +1 -1
  7. package/dist/adapters/cursor-hook-adapter.js +133 -47
  8. package/dist/adapters/cursor-hook-adapter.js.map +1 -1
  9. package/dist/adapters/cursor-terminal-hook.d.ts +12 -0
  10. package/dist/adapters/cursor-terminal-hook.d.ts.map +1 -1
  11. package/dist/adapters/cursor-terminal-hook.js +158 -4
  12. package/dist/adapters/cursor-terminal-hook.js.map +1 -1
  13. package/dist/adapters/qoder-log-adapter.d.ts +9 -0
  14. package/dist/adapters/qoder-log-adapter.d.ts.map +1 -1
  15. package/dist/adapters/qoder-log-adapter.js +188 -19
  16. package/dist/adapters/qoder-log-adapter.js.map +1 -1
  17. package/dist/bootstrap.d.ts.map +1 -1
  18. package/dist/bootstrap.js +25 -5
  19. package/dist/bootstrap.js.map +1 -1
  20. package/dist/cli.js +82 -19
  21. package/dist/cli.js.map +1 -1
  22. package/dist/config.d.ts +12 -0
  23. package/dist/config.d.ts.map +1 -1
  24. package/dist/config.js +45 -3
  25. package/dist/config.js.map +1 -1
  26. package/dist/installers/claude-code-installer.d.ts +15 -0
  27. package/dist/installers/claude-code-installer.d.ts.map +1 -0
  28. package/dist/installers/claude-code-installer.js +109 -0
  29. package/dist/installers/claude-code-installer.js.map +1 -0
  30. package/dist/notifiers/dingtalk-notifier.d.ts +15 -0
  31. package/dist/notifiers/dingtalk-notifier.d.ts.map +1 -0
  32. package/dist/notifiers/dingtalk-notifier.js +52 -0
  33. package/dist/notifiers/dingtalk-notifier.js.map +1 -0
  34. package/dist/notifiers/feishu-notifier.d.ts +14 -0
  35. package/dist/notifiers/feishu-notifier.d.ts.map +1 -0
  36. package/dist/notifiers/feishu-notifier.js +60 -0
  37. package/dist/notifiers/feishu-notifier.js.map +1 -0
  38. package/dist/notifiers/wecom-notifier.d.ts +13 -0
  39. package/dist/notifiers/wecom-notifier.d.ts.map +1 -0
  40. package/dist/notifiers/wecom-notifier.js +39 -0
  41. package/dist/notifiers/wecom-notifier.js.map +1 -0
  42. package/dist/paths.d.ts +9 -0
  43. package/dist/paths.d.ts.map +1 -0
  44. package/dist/paths.js +27 -0
  45. package/dist/paths.js.map +1 -0
  46. package/dist/run-gateway.d.ts +0 -1
  47. package/dist/run-gateway.d.ts.map +1 -1
  48. package/dist/run-gateway.js +11 -1
  49. package/dist/run-gateway.js.map +1 -1
  50. package/dist/setup.d.ts +2 -0
  51. package/dist/setup.d.ts.map +1 -0
  52. package/dist/setup.js +274 -0
  53. package/dist/setup.js.map +1 -0
  54. package/dist/utils/logger.d.ts.map +1 -1
  55. package/dist/utils/logger.js +20 -2
  56. package/dist/utils/logger.js.map +1 -1
  57. package/package.json +4 -2
  58. package/scripts/cursor-hook-forwarder.mjs +50 -4
@@ -3,12 +3,12 @@
3
3
  "hooks": {
4
4
  "beforeShellExecution": [
5
5
  {
6
- "command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
6
+ "command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" CURSOR_AGENT=\"${CURSOR_AGENT:-1}\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
7
7
  }
8
8
  ],
9
9
  "afterShellExecution": [
10
10
  {
11
- "command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
11
+ "command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" CURSOR_AGENT=\"${CURSOR_AGENT:-1}\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
12
12
  }
13
13
  ]
14
14
  }
package/README.md CHANGED
@@ -1,137 +1,267 @@
1
- # AgentWake 🚀
1
+ # AgentWake
2
2
 
3
- **AgentWake** 是一个跨编辑器(Cursor / Claude Code / Qoder)的终端授权提醒网关。
4
- 当你在使用 AI 辅助编程工具时,终端任务经常会进入“等待用户同意(Approval)”状态。AgentWake 会在桌面和移动端为你提供实时通知,让你无需时刻盯着屏幕,告别阻塞等待!
3
+ 跨编辑器的 AI 编程通知网关。支持 Cursor / Claude Code / Qoder,当 AI 任务完成、异常终止或等待授权时,实时推送通知到桌面、手机和 IM 群。
4
+
5
+ ## 效果预览
6
+
7
+ <p align="center">
8
+ <img src="docs/screenshots/web.jpg" width="48%" alt="Web 界面" />
9
+ <img src="docs/screenshots/mobile_notify.jpg" width="48%" alt="手机通知" />
10
+ </p>
11
+
12
+ <p align="center">
13
+ <img src="docs/screenshots/cursor.png" width="48%" alt="Cursor 通知" />
14
+ <img src="docs/screenshots/qoder.png" width="48%" alt="Qoder 通知" />
15
+ </p>
5
16
 
6
17
  ---
7
18
 
8
- ## 🌟 核心特性
19
+ ## 核心特性
9
20
 
10
- - **多编辑器支持**:原生支持监听 Cursor Hook、Claude Hook 以及 Qoder 日志中的授权等待信号。
11
- - **全平台桌面通知**:支持 macOS、Windows、Linux 的系统级弹窗提醒。
12
- - **移动端实时提醒**:内置移动端 Web 应用,支持 PWA 安装,通过 HTTPS + WebSocket 实现手机端毫秒级推送。
13
- - **智能防打扰**:内置去重和限流机制,避免消息重复轰炸。
14
- - **开箱即用**:提供极简的 CLI 命令行工具,一键初始化与启动。
21
+ - **多编辑器支持** Cursor Hook、Claude Code HookQoder 日志监听
22
+ - **多通知渠道** 桌面系统通知、PWA 网页推送、钉钉、飞书、企业微信
23
+ - **Claude Code 深度集成** 支持 Stop / Notification / StopFailure / SessionEnd 等全部 Hook 事件,可自定义每个事件的通知标题
24
+ - **移动端实时推送** — 内置 PWA Web App,HTTPS + WebSocket 毫秒级推送,支持扫码连接
25
+ - **智能防打扰** 事件去重 + 速率限流,避免消息轰炸
26
+ - **交互式配置** — `agentwake setup` 一步步引导完成全部配置
15
27
 
16
28
  ---
17
29
 
18
- ## 🚀 快速开始
30
+ ## 快速开始
19
31
 
20
32
  ### 环境要求
21
33
 
22
- - Node.js (推荐 v18+)
23
- - [mkcert](https://github.com/FiloSottile/mkcert) (用于生成本地 HTTPS 证书,移动端访问必备)
34
+ - Node.js >= 18
35
+ - [mkcert](https://github.com/FiloSottile/mkcert)(生成本地 HTTPS 证书,移动端推送必需)
36
+
37
+ ### 安装
38
+
39
+ ```bash
40
+ npm i -g agentwake
41
+ ```
42
+
43
+ ### 方式一:交互式引导(推荐)
44
+
45
+ ```bash
46
+ agentwake init # 生成 HTTPS 证书到 ~/.agentwake/certs/
47
+ agentwake setup # 交互式配置向导
48
+ ```
49
+
50
+ `setup` 会引导你完成:
51
+ 1. 选择 AI 工具(Claude Code / Cursor / 全部)
52
+ 2. 选择监听的事件类型
53
+ 3. 自定义每个事件的通知标题(可选)
54
+ 4. 选择通知渠道(钉钉 / 飞书 / 企业微信)
55
+ 5. 输入 Webhook 地址和密钥
56
+ 6. 自动安装 Claude Code Hooks 到 `~/.claude/settings.json`
57
+ 7. 启动服务
58
+
59
+ ### 方式二:手动配置
60
+
61
+ ```bash
62
+ agentwake init # 生成 ~/.agentwake/.env 和 HTTPS 证书
63
+ # 编辑 ~/.agentwake/.env 填入配置
64
+ agentwake start
65
+ ```
66
+
67
+ 所有数据存放在 `~/.agentwake/` 目录下,无需手动创建工作目录。
68
+
69
+ ### 方式三:从源码启动
70
+
71
+ ```bash
72
+ git clone https://github.com/tjdxwwj/agentwake.git
73
+ cd agentwake
74
+ npm install
75
+
76
+ # 初始化(生成 HTTPS 证书和 .env)
77
+ npm run init
78
+
79
+ # 交互式配置
80
+ npm run setup
81
+
82
+ # 启动开发服务器
83
+ npm run dev
84
+ ```
85
+
86
+ 启动后服务运行在 `https://localhost:3199`。
87
+
88
+ ---
89
+
90
+ ## 通知渠道
91
+
92
+ | 渠道 | 配置方式 | 说明 |
93
+ |------|---------|------|
94
+ | 桌面系统通知 | 内置,无需配置 | macOS / Windows / Linux |
95
+ | PWA 网页推送 | 内置,手机浏览器打开服务地址 | 需 HTTPS,支持 Service Worker 系统通知 |
96
+ | 钉钉 | `AGENTWAKE_DINGTALK_WEBHOOK` | 群机器人 Webhook,支持签名校验 |
97
+ | 飞书 | `AGENTWAKE_FEISHU_WEBHOOK` | 群机器人 Webhook,支持签名校验 |
98
+ | 企业微信 | `AGENTWAKE_WECOM_WEBHOOK` | 群机器人 Webhook,安全性由 URL Key 保证 |
99
+
100
+ ### 钉钉配置
101
+
102
+ 在钉钉群 -> 群设置 -> 智能群助手 -> 添加机器人 -> 自定义 Webhook,复制 Webhook 地址。
24
103
 
25
- ### 安装与启动
104
+ ```env
105
+ AGENTWAKE_DINGTALK_WEBHOOK=https://oapi.dingtalk.com/robot/send?access_token=xxx
106
+ AGENTWAKE_DINGTALK_SECRET=SECxxx # 可选,签名密钥
107
+ ```
108
+
109
+ ### 飞书配置
26
110
 
27
- 1. **全局安装 CLI**
28
- ```bash
29
- npm i -g agentwake
30
- ```
111
+ 在飞书群 -> 设置 -> 群机器人 -> 添加自定义机器人,复制 Webhook 地址。
112
+
113
+ ```env
114
+ AGENTWAKE_FEISHU_WEBHOOK=https://open.feishu.cn/open-apis/bot/v2/hook/xxx
115
+ AGENTWAKE_FEISHU_SECRET=xxx # 可选,签名校验密钥
116
+ ```
31
117
 
32
- 2. **初始化项目与证书**
33
- ```bash
34
- mkdir my-agentwake && cd my-agentwake
35
- agentwake init
36
- ```
37
- *注意:初始化过程中会自动使用 mkcert 生成本地 HTTPS 证书。*
118
+ ### 企业微信配置
38
119
 
39
- 3. **启动网关服务**
40
- ```bash
41
- agentwake start
42
- ```
120
+ 在企业微信群 -> 群机器人 -> 添加群机器人,复制 Webhook 地址。
43
121
 
44
- 启动后,网关默认运行在 `https://localhost:3199` (或者局域网 IP)。
122
+ ```env
123
+ AGENTWAKE_WECOM_WEBHOOK=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
124
+ ```
45
125
 
46
126
  ---
47
127
 
48
- ## 🔌 编辑器接入指南
128
+ ## 编辑器接入
129
+
130
+ ### Claude Code
131
+
132
+ 运行 `agentwake setup` 会自动完成以下操作:
133
+ - 生成 Hook 转发脚本到 `~/.agentwake/hooks/claude-hook-relay.sh`
134
+ - 写入 Hook 配置到 `~/.claude/settings.json`
135
+
136
+ 支持的 Hook 事件:
49
137
 
50
- ### Cursor 接入
138
+ | 事件 | 说明 | 默认启用 |
139
+ |------|------|---------|
140
+ | Notification | 需要用户注意 | 是 |
141
+ | Stop | 任务完成 | 是 |
142
+ | StopFailure | 任务异常终止 | 是 |
143
+ | SessionEnd | 会话结束 | 是 |
144
+ | SessionStart | 会话开始 | 否 |
145
+ | PreToolUse | 工具调用前 | 否 |
146
+ | PostToolUse | 工具调用后 | 否 |
51
147
 
52
- AgentWake 已经内置了对 Cursor 工作流的支持:
53
- 1. 确保在目标项目中执行过 `agentwake init`。
54
- 2. 保持 `agentwake start` 运行。
55
- 3. 当 Cursor 终端触发需要用户授权的命令时,你将立刻收到通知。
148
+ ### Cursor
56
149
 
57
- ### Qoder 接入
150
+ 1. 在项目中执行 `agentwake init`
151
+ 2. 保持 `agentwake start` 运行
152
+ 3. Cursor 终端触发授权等待时自动通知
58
153
 
59
- AgentWake 会尝试自动发现 Qoder 的日志目录(如 macOS 下的 `~/Library/Application Support/Qoder/logs/.../agent.log`)。
154
+ ### Qoder
155
+
156
+ 自动发现日志目录,或手动指定:
60
157
 
61
- 如果自动发现失败,你可以通过环境变量手动指定日志路径:
62
158
  ```bash
63
- AGENTWAKE_QODER_LOG_PATH="/ABSOLUTE/PATH/TO/agent.log" agentwake start
159
+ AGENTWAKE_QODER_LOG_PATH=”/path/to/agent.log agentwake start
64
160
  ```
65
161
 
66
162
  ---
67
163
 
68
- ## 📱 移动端访问与证书信任(必读)
164
+ ## 自定义通知标题
69
165
 
70
- 为了在手机上接收实时通知,你必须让手机信任电脑上由 `mkcert` 生成的根证书。
166
+ 通过 `agentwake setup` 交互式设置,或直接在 `.env` 中配置:
71
167
 
72
- 1. 找到根证书位置:
73
- 在电脑终端运行 `mkcert -CAROOT`,找到目录下的 `rootCA.pem` 文件。
74
- 2. 安装到手机:
75
- - **iOS**:将文件发送到手机,在“设置”中安装描述文件,并在“通用 -> 关于本机 -> 证书信任设置”中开启“完全信任”。
76
- - **Android**:将文件发送到手机,在安全设置中“从存储设备安装” CA 证书(部分安卓系统可能需要将后缀改为 `.crt`)。
77
- 3. Node.js TLS 兼容(如果遇到本地转发报错):
78
- ```bash
79
- export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
80
- ```
168
+ ```env
169
+ AGENTWAKE_CLAUDE_TITLE_STOP=AI搞定了
170
+ AGENTWAKE_CLAUDE_TITLE_STOP_FAILURE=AI挂了
171
+ AGENTWAKE_CLAUDE_TITLE_NOTIFICATION=AI喊你看一眼
172
+ AGENTWAKE_CLAUDE_TITLE_SESSION_END=会话结束了
173
+ ```
174
+
175
+ 未配置的事件使用默认标题。
81
176
 
82
177
  ---
83
178
 
84
- ## 🛠️ 面向开发者
179
+ ## 移动端 PWA 设置
85
180
 
86
- 如果你想参与 AgentWake 的开发,请参考以下指南:
181
+ 手机需要信任本地 HTTPS 证书才能接收 Service Worker 系统通知。
87
182
 
88
- ### 技术栈
89
- - **后端**:Node.js + TypeScript + Express + WebSocket (`ws`) + Zod
90
- - **前端**:HTML/CSS/JS (PWA 支持)
91
- - **系统交互**:`node-notifier` (桌面通知)
183
+ 1. 获取根证书路径:`mkcert -CAROOT`,找到 `rootCA.pem`
184
+ 2. 安装到手机:
185
+ - **iOS** 发送到手机安装描述文件,然后在 设置 > 通用 > 关于本机 > 证书信任设置 中启用完全信任
186
+ - **Android** — 在安全设置中安装 CA 证书(可能需要改后缀为 `.crt`)
187
+ 3. 手机浏览器打开 `https://<局域网IP>:3199`,确认 HTTPS 连接安全后允许通知权限
188
+
189
+ ---
92
190
 
93
- ### 本地开发
191
+ ## 全部环境变量
192
+
193
+ | 变量 | 默认值 | 说明 |
194
+ |------|--------|------|
195
+ | `AGENTWAKE_HOST` | `0.0.0.0` | 监听地址 |
196
+ | `AGENTWAKE_PORT` | `3199` | 监听端口 |
197
+ | `AGENTWAKE_HTTPS_ENABLED` | `1` | 是否启用 HTTPS |
198
+ | `AGENTWAKE_HTTPS_CERT_PATH` | `certs/dev-cert.pem` | HTTPS 证书路径 |
199
+ | `AGENTWAKE_HTTPS_KEY_PATH` | `certs/dev-key.pem` | HTTPS 私钥路径 |
200
+ | `AGENTWAKE_DESKTOP_ENABLED` | `1` | 是否启用桌面系统通知(`0` 关闭) |
201
+ | `AGENTWAKE_PWA_ENABLED` | `1` | 是否启用 PWA/WebSocket 推送(`0` 关闭) |
202
+ | `AGENTWAKE_DINGTALK_ENABLED` | `1` | 是否启用钉钉通知(`0` 关闭) |
203
+ | `AGENTWAKE_DINGTALK_WEBHOOK` | — | 钉钉 Webhook URL |
204
+ | `AGENTWAKE_DINGTALK_SECRET` | — | 钉钉签名密钥 |
205
+ | `AGENTWAKE_FEISHU_ENABLED` | `1` | 是否启用飞书通知(`0` 关闭) |
206
+ | `AGENTWAKE_FEISHU_WEBHOOK` | — | 飞书 Webhook URL |
207
+ | `AGENTWAKE_FEISHU_SECRET` | — | 飞书签名密钥 |
208
+ | `AGENTWAKE_WECOM_ENABLED` | `1` | 是否启用企业微信通知(`0` 关闭) |
209
+ | `AGENTWAKE_WECOM_WEBHOOK` | — | 企业微信 Webhook URL |
210
+ | `AGENTWAKE_CLAUDE_TITLE_*` | — | Claude 事件自定义标题 |
211
+ | `AGENTWAKE_DEDUPE_WINDOW_MS` | `10000` | 去重窗口(毫秒) |
212
+ | `AGENTWAKE_RATE_LIMIT_WINDOW_MS` | `10000` | 限流窗口(毫秒) |
213
+ | `AGENTWAKE_RATE_LIMIT_MAX_EVENTS` | `40` | 窗口内最大事件数 |
214
+ | `AGENTWAKE_WS_PATH` | `/ws` | WebSocket 路径 |
215
+ | `AGENTWAKE_QODER_LOG_PATH` | — | Qoder 日志路径(自动发现) |
216
+ | `AGENTWAKE_ALLOWED_HOOK_IPS` | — | 限制 Hook 来源 IP(逗号分隔) |
217
+
218
+ ---
219
+
220
+ ## 开发
94
221
 
95
222
  ```bash
96
- # 1. 克隆代码并安装依赖
97
- git clone https://github.com/your-username/agentwake.git
223
+ git clone https://github.com/tjdxwwj/agentwake.git
98
224
  cd agentwake
99
225
  npm install
100
-
101
- # 2. 准备环境变量
102
226
  cp .env.example .env
227
+ npm run init # 生成本地证书
228
+ npm run dev # 启动开发服务器
229
+ npm test # 运行测试
230
+ ```
103
231
 
104
- # 3. 初始化(生成本地证书等)
105
- npm run init
232
+ ### 目录结构
106
233
 
107
- # 4. 启动开发服务器
108
- npm run dev
234
+ ```
235
+ src/
236
+ adapters/ # 输入适配器(Cursor / Claude / Qoder)
237
+ gateway/ # 核心网关(Adapter 注册、事件路由)
238
+ notifiers/ # 通知分发(桌面 / WebSocket / 钉钉 / 飞书 / 企业微信)
239
+ installers/ # Hook 自动安装器
240
+ web/ # PWA 前端
109
241
  ```
110
242
 
111
- ### 核心目录结构
112
- - `src/adapters/`:各类编辑器(Cursor/Claude/Qoder)的输入信号适配器。
113
- - `src/gateway/`:核心网关,负责 Adapter 注册与事件路由。
114
- - `src/notifiers/`:通知分发器(桌面系统通知、移动端 WebSocket、PWA Push)。
115
- - `web/`:移动端 Web App 源码。
243
+ ### 技术栈
244
+
245
+ Node.js + TypeScript + Express + WebSocket (ws) + Zod
116
246
 
117
247
  ---
118
248
 
119
- ## ❓ 常见问题 (FAQ)
249
+ ## FAQ
120
250
 
121
- **Q: 为什么手机端收不到通知?**
122
- A: 请按顺序检查:
123
- 1. 手机是否和电脑在同一局域网下。
124
- 2. 手机浏览器是否显示“安全/受信任”的 HTTPS 连接(若显示不安全,请重新检查证书安装步骤)。
125
- 3. 检查 Web 页面上的 WebSocket 连接状态是否显示为“已连接”。
251
+ **手机收不到通知?**
252
+ 1. 确认手机和电脑在同一局域网
253
+ 2. 确认浏览器显示安全的 HTTPS 连接(非”不安全”)
254
+ 3. 确认已授予通知权限
255
+ 4. 检查 Web 页面 WebSocket 状态是否为”已连接”
126
256
 
127
- **Q: 能否自定义运行端口?**
128
- A: 可以,通过 CLI 参数或环境变量修改:
257
+ **如何修改端口?**
129
258
  ```bash
130
- agentwake start --port 4000
131
- # 或者使用环境变量
132
259
  AGENTWAKE_PORT=4000 agentwake start
133
260
  ```
134
261
 
262
+ **个人微信能收通知吗?**
263
+ 微信不支持 Webhook 消息推送 API。可以使用企业微信群机器人作为替代。
264
+
135
265
  ---
136
266
 
137
- *AgentWake - 让 AI 编程更省心。*
267
+ MIT License
@@ -1 +1 @@
1
- {"version":3,"file":"claude-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,wBAAgB,uBAAuB,IAAI,cAAc,CAoBxD"}
1
+ {"version":3,"file":"claude-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA+CzD,wBAAgB,uBAAuB,IAAI,cAAc,CAsDxD"}
@@ -1,16 +1,83 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createClaudeHookAdapter = createClaudeHookAdapter;
4
+ const zod_1 = require("zod");
5
+ const notify_event_1 = require("../domain/notify-event");
4
6
  const hook_common_1 = require("./hook-common");
7
+ // Claude Code native hook payload schema
8
+ const claudeNativeSchema = zod_1.z.object({
9
+ hook_event_name: zod_1.z.string(),
10
+ session_id: zod_1.z.string().optional(),
11
+ last_assistant_message: zod_1.z.string().optional(),
12
+ transcript_path: zod_1.z.string().optional(),
13
+ cwd: zod_1.z.string().optional(),
14
+ }).passthrough();
15
+ const HOOK_LEVEL_MAP = {
16
+ StopFailure: "error",
17
+ Notification: "warn",
18
+ Stop: "info",
19
+ SessionEnd: "info",
20
+ SessionStart: "info",
21
+ };
22
+ const IGNORED_HOOKS = new Set(["PreToolUse", "PostToolUse"]);
23
+ /** Default titles when no custom title is configured. */
24
+ const DEFAULT_TITLES = {
25
+ Stop: "Claude Code: 任务完成",
26
+ StopFailure: "Claude Code: 任务异常终止",
27
+ Notification: "Claude Code: 需要你的注意",
28
+ SessionEnd: "Claude Code: 会话已结束",
29
+ SessionStart: "Claude Code: 会话已开始",
30
+ };
31
+ function buildClaudeDedupeKey(payload) {
32
+ const messageToken = payload.last_assistant_message?.slice(0, 120) ?? "";
33
+ return [
34
+ "claude",
35
+ payload.hook_event_name,
36
+ payload.session_id ?? "unknown-session",
37
+ payload.transcript_path ?? "",
38
+ messageToken,
39
+ ].join(":");
40
+ }
5
41
  function createClaudeHookAdapter() {
6
42
  return {
7
43
  id: "claude-hook-adapter",
8
44
  start(context) {
45
+ const customTitles = context.config.claudeEventTitles;
9
46
  context.app.post(context.config.claudeHookPath, async (req, res) => {
10
47
  if (!(0, hook_common_1.validateHookSourceIp)(req, context.config.allowedHookIps)) {
11
48
  (0, hook_common_1.forbidden)(res);
12
49
  return;
13
50
  }
51
+ // Try Claude Code native format first (has hook_event_name field)
52
+ const nativeParsed = claudeNativeSchema.safeParse(req.body);
53
+ if (nativeParsed.success && nativeParsed.data.hook_event_name) {
54
+ const data = nativeParsed.data;
55
+ const hookName = data.hook_event_name;
56
+ if (IGNORED_HOOKS.has(hookName)) {
57
+ res.status(202).json({ ok: true, accepted: false, reason: "ignored-event" });
58
+ return;
59
+ }
60
+ const level = HOOK_LEVEL_MAP[hookName] ?? "info";
61
+ const title = customTitles[hookName] || DEFAULT_TITLES[hookName] || `Claude Code: ${hookName}`;
62
+ const event = (0, notify_event_1.createNotifyEvent)({
63
+ source: "claude-hook",
64
+ editor: "claude-code",
65
+ level,
66
+ title,
67
+ body: data.last_assistant_message?.slice(0, 300) || "",
68
+ dedupeKey: buildClaudeDedupeKey(data),
69
+ meta: {
70
+ eventName: hookName,
71
+ sessionId: data.session_id,
72
+ transcriptPath: data.transcript_path,
73
+ cwd: data.cwd,
74
+ },
75
+ });
76
+ await context.emit(event);
77
+ res.status(200).json({ ok: true, accepted: true });
78
+ return;
79
+ }
80
+ // Fallback: generic hook event parsing (approval-waiting text matching)
14
81
  const event = (0, hook_common_1.parseHookEvent)("claude-code", "claude-hook", req.body);
15
82
  if (!event) {
16
83
  res.status(202).json({ ok: true, accepted: false, reason: "ignored" });
@@ -1 +1 @@
1
- {"version":3,"file":"claude-hook-adapter.js","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":";;AAOA,0DAoBC;AA1BD,+CAIuB;AAEvB,SAAgB,uBAAuB;IACrC,OAAO;QACL,EAAE,EAAE,qBAAqB;QACzB,KAAK,CAAC,OAAO;YACX,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;gBACjE,IAAI,CAAC,IAAA,kCAAoB,EAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC9D,IAAA,uBAAS,EAAC,GAAG,CAAC,CAAC;oBACf,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,IAAA,4BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrE,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBACvE,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"claude-hook-adapter.js","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":";;AAgDA,0DAsDC;AAtGD,6BAAwB;AAExB,yDAA6E;AAC7E,+CAIuB;AAEvB,yCAAyC;AACzC,MAAM,kBAAkB,GAAG,OAAC,CAAC,MAAM,CAAC;IAClC,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE;IAC3B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,sBAAsB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7C,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,GAAG,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3B,CAAC,CAAC,WAAW,EAAE,CAAC;AAEjB,MAAM,cAAc,GAAgC;IAClD,WAAW,EAAE,OAAO;IACpB,YAAY,EAAE,MAAM;IACpB,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,MAAM;CACrB,CAAC;AAEF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;AAE7D,yDAAyD;AACzD,MAAM,cAAc,GAA2B;IAC7C,IAAI,EAAE,mBAAmB;IACzB,WAAW,EAAE,qBAAqB;IAClC,YAAY,EAAE,qBAAqB;IACnC,UAAU,EAAE,oBAAoB;IAChC,YAAY,EAAE,oBAAoB;CACnC,CAAC;AAEF,SAAS,oBAAoB,CAAC,OAA2C;IACvE,MAAM,YAAY,GAAG,OAAO,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IACzE,OAAO;QACL,QAAQ;QACR,OAAO,CAAC,eAAe;QACvB,OAAO,CAAC,UAAU,IAAI,iBAAiB;QACvC,OAAO,CAAC,eAAe,IAAI,EAAE;QAC7B,YAAY;KACb,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,SAAgB,uBAAuB;IACrC,OAAO;QACL,EAAE,EAAE,qBAAqB;QACzB,KAAK,CAAC,OAAO;YACX,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAEtD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;gBACjE,IAAI,CAAC,IAAA,kCAAoB,EAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC9D,IAAA,uBAAS,EAAC,GAAG,CAAC,CAAC;oBACf,OAAO;gBACT,CAAC;gBAED,kEAAkE;gBAClE,MAAM,YAAY,GAAG,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC5D,IAAI,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC9D,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;oBAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC;oBACtC,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAChC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;wBAC7E,OAAO;oBACT,CAAC;oBACD,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC;oBACjD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,gBAAgB,QAAQ,EAAE,CAAC;oBAE/F,MAAM,KAAK,GAAG,IAAA,gCAAiB,EAAC;wBAC9B,MAAM,EAAE,aAAa;wBACrB,MAAM,EAAE,aAAa;wBACrB,KAAK;wBACL,KAAK;wBACL,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE;wBACtD,SAAS,EAAE,oBAAoB,CAAC,IAAI,CAAC;wBACrC,IAAI,EAAE;4BACJ,SAAS,EAAE,QAAQ;4BACnB,SAAS,EAAE,IAAI,CAAC,UAAU;4BAC1B,cAAc,EAAE,IAAI,CAAC,eAAe;4BACpC,GAAG,EAAE,IAAI,CAAC,GAAG;yBACd;qBACF,CAAC,CAAC;oBACH,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC1B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;oBACnD,OAAO;gBACT,CAAC;gBAED,wEAAwE;gBACxE,MAAM,KAAK,GAAG,IAAA,4BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrE,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBACvE,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor-hook-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAezD,wBAAgB,uBAAuB,IAAI,cAAc,CA0JxD"}
1
+ {"version":3,"file":"cursor-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor-hook-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAmBzD,wBAAgB,uBAAuB,IAAI,cAAc,CAoPxD"}