From 2ac582ecfd976a464c3536a96d96bf73b1782518 Mon Sep 17 00:00:00 2001 From: wonder Date: Sun, 21 Jun 2026 22:46:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20PreToolUse=20?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=EF=BC=8CAskUserQuestion=20=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - handler.go 添加 PreToolUse 事件处理,提取 AskUserQuestion 的 question 字段作为通知内容 - README.md 更新 hooks 配置示例、支持事件文档和测试命令 --- README.md | 27 +++++++++++++++++++++++++-- handler.go | 20 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 782e1ec..2d0ecb5 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## 功能特性 - **实时通知**:当 Claude Code 需要关注时,立即收到手机推送 -- **多事件支持**:Notification(权限请求、等待输入等)和 Stop(任务完成) +- **多事件支持**:Notification(权限请求、等待输入等)、Stop(任务完成)、PreToolUse(提问通知) - **轻量部署**:单个 Docker 容器,资源占用极低 - **灵活配置**:通过环境变量自定义 Gotify 服务器和 Token @@ -73,6 +73,17 @@ docker-compose up -d "type": "command", "command": "curl -s -X POST http://47.121.181.112:8082/hooks -H 'Content-Type: application/json' -d @-" } + ], + "PreToolUse": [ + { + "matcher": "AskUserQuestion", + "hooks": [ + { + "type": "command", + "command": "curl -s -X POST http://47.121.181.112:8082/hooks -H 'Content-Type: application/json' -d @-" + } + ] + } ] } } @@ -96,6 +107,13 @@ docker-compose up -d | 正常完成 | 任务完成 | 5 | Claude 完成了本轮回复 | | 循环检测 | 循环停止 | 8 | Stop hook 连续触发多次,已自动停止 | +### PreToolUse 事件 + +| 工具名称 | 标题 | 优先级 | 说明 | +|----------|------|--------|------| +| `AskUserQuestion` | 等待回答 | 6 | Claude 向你提问,等待回答 | +| 其他工具 | 工具调用 | 4 | Claude 正在使用工具 | + ## 配置说明 | 环境变量 | 必填 | 说明 | @@ -164,6 +182,11 @@ curl -X POST http://47.121.181.112:8082/hooks \ curl -X POST http://47.121.181.112:8082/hooks \ -H 'Content-Type: application/json' \ -d '{"session_id":"test","cwd":"/tmp","hook_event_name":"Stop"}' + +# 模拟 AskUserQuestion 事件 +curl -X POST http://47.121.181.112:8082/hooks \ + -H 'Content-Type: application/json' \ + -d '{"session_id":"test","cwd":"/tmp","hook_event_name":"PreToolUse","tool_name":"AskUserQuestion","tool_input":{"question":"你想使用哪种数据库?"}}' ``` ## 项目结构 @@ -184,7 +207,7 @@ cc-hook/ ## 扩展计划 - [ ] 数据库记录:将 Hook 事件写入数据库,便于复盘和分析 -- [ ] 更多事件支持:Tool Use、Error 等事件类型 +- [x] 更多事件支持:PreToolUse(AskUserQuestion 提问通知) - [ ] 消息模板:自定义通知消息格式 - [ ] 多 Gotify 支持:同时推送到多个 Gotify 服务器 diff --git a/handler.go b/handler.go index 715114d..042a1ef 100644 --- a/handler.go +++ b/handler.go @@ -49,6 +49,8 @@ func (h *HookHandler) HandleHook(w http.ResponseWriter, r *http.Request) { title, message, priority = h.handleNotification(event) case "Stop": title, message, priority = h.handleStop(event) + case "PreToolUse": + title, message, priority = h.handlePreToolUse(event) default: log.Printf("ignored event: %s", event.HookEventName) w.WriteHeader(http.StatusOK) @@ -90,6 +92,24 @@ func (h *HookHandler) handleNotification(event ClaudeCodeHookEvent) (title, mess return title, message, priority } +func (h *HookHandler) handlePreToolUse(event ClaudeCodeHookEvent) (title, message string, priority int) { + switch event.ToolName { + case "AskUserQuestion": + title = "Claude Code - 等待回答" + if question, ok := event.ToolInput["question"].(string); ok && question != "" { + message = "Claude 向你提问: " + question + } else { + message = "Claude 向你提出了一个问题,等待你的回答" + } + priority = 6 + default: + title = "Claude Code - 工具调用" + message = fmt.Sprintf("Claude 正在使用 %s", event.ToolName) + priority = 4 + } + return title, message, priority +} + func (h *HookHandler) handleStop(event ClaudeCodeHookEvent) (title, message string, priority int) { if event.StopHookActive { // Avoid infinite loop: Stop hook triggered too many times