Skip to content

Commit c47c7a3

Browse files
zerob13yyhhyyyyyy
andauthored
release: 0.5.8 (#1305)
* Merge pull request #1302 from ThinkInAIXYZ/bugfix/question-end-error fix(agent): mark question tool messages sent * refactor: route openai to responses (#1303) * refactor: route openai to responses * fix(i18n): localize openaiResponsesNotice * feat: add hooks for notify (#1304) * docs(hooks): add hooks notifications spec/plan * docs(hooks): adjust settings UX and notifier triggers * docs(hooks): define webhook notifications and lifecycle hooks * feat(hooks): add confirmo notifications * feat(hooks): improve notifications cards * chore(i18n): add notifications hooks translations * fix(hooks): correct env var prefix * fix(hooks): align hook dispatch * fix(settings): improve hooks ui * fix(hooks): harden hook dispatch * chore: update 0.5.8 --------- Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
2 parents 43df5d3 + 347e95d commit c47c7a3

50 files changed

Lines changed: 57498 additions & 43797 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
# Changelog
2+
3+
## v0.5.8 (2026-02-09)
4+
- OpenAI 默认改为 Responses API
5+
- 支持了 Telegram/Discord/Confirmo 通知
6+
- 支持任务生命周期 hooks
7+
- 修复少量 Bug
8+
29
## v0.5.7 (2026-02-05)
310
- 完善 Skills 支持
411
- Agent 现在可以生成可交互的提问信息
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Plan: Hooks 与 Webhook 通知(DeepChat)
2+
3+
## 范围与原则
4+
5+
- **仅通知**:不会阻断/中止 DeepChat 的生成、工具与权限流程(hook 失败也不影响主链路)。
6+
- **仅 Settings 配置**:所有配置都由 Settings 管理,不读取/合并任何外部配置文件。
7+
- **Webhook-only**:Telegram/Discord 只做向外发送消息(HTTP 请求),不做双向交互/按钮/回调;Confirmo 走本地 hook。
8+
9+
## 交付拆分(建议)
10+
11+
为降低回归与 UI 复杂度,分两步交付:
12+
13+
- **Step 1(可用)**:Settings 页面 + 配置模型 + Test(Telegram/Discord/Confirmo/每个事件 command test)+ 基础日志
14+
- **Step 2(完整)**:生命周期事件注入 + 真实触发 + 队列/限流/截断/脱敏 + 单元/集成测试
15+
16+
## Step 1:Settings + Test 能力(不接入真实生命周期)
17+
18+
1. 定义数据模型与校验
19+
- 新增 shared types:`HookEventName`、settings config、event payload、执行/发送结果
20+
-`zod` 做 settings schema 校验(容错:未知字段忽略,但记录 warning)
21+
2. 配置存储与读取(main)
22+
- 在现有 config store 中新增 `hooksNotifications` 配置树(默认全关闭)
23+
- 提供 getter/setter + IPC 通道(renderer 仅通过 IPC 读写,避免在 renderer 暴露 secret)
24+
3. Settings UI(renderer)
25+
- 新增设置页面(或新增一个 section),布局要求:
26+
- 顶部:Telegram 卡片(Enable + 参数 + Test + 事件勾选)
27+
- 其次:Discord 卡片(Enable + 参数 + Test + 事件勾选)
28+
- 其次:Confirmo 卡片(Enable + Test;默认全部事件;需检测 hook 文件存在)
29+
- 下方:Hooks Commands 卡片(Enable + 每个生命周期:Switch + 单个 command 输入框 + 右侧 Test)
30+
- UI 风格参考知识库配置:卡片/折叠 + Switch 控制启用
31+
4. Test 逻辑(main)
32+
- `testTelegram()`:发送一条 `type="test"` 的通知文本到配置目标
33+
- `testDiscord()`:同上
34+
- `testConfirmo()`:执行本地 Confirmo hook(stdin JSON)
35+
- `testHookCommand(eventName)`:构造一个最小模拟 payload,通过 stdin JSON 执行对应 command
36+
- Test 结果返回 renderer:success/错误信息 + 状态码 + 用时 + stdout/stderr 摘要
37+
5. i18n
38+
- 新增 settings 文案 key(zh-CN/en-US),不硬编码中文
39+
40+
## Step 2:接入生命周期 + 可靠性
41+
42+
1. 生命周期事件注入(main)
43+
- `SessionStart`/`SessionEnd`:每次一次完整生成链路开始/结束
44+
- `UserPromptSubmit`:用户提交消息后、调用 LLM 前
45+
- `PreToolUse`:工具调用实际执行前(含 tool name/id/params)
46+
- `PostToolUse`:工具调用成功返回后
47+
- `PostToolUseFailure`:工具调用失败(error)
48+
- `PermissionRequest`:触发权限请求时(含 tool/permission meta)
49+
- `Stop`:生成停止(含 stop_reason、userStop)
50+
2. Dispatcher(非阻塞)
51+
- 根据配置把事件分发到:
52+
- command hook runner(按 event 的 switch+command)
53+
- Telegram notifier(按 channel enabled + event 勾选)
54+
- Discord notifier(同上)
55+
- Confirmo hook runner(同上)
56+
- 所有分发均异步执行、不可阻断主流程;失败仅记录日志与 diagnostics
57+
3. 队列/限流/截断/脱敏
58+
- per-channel 串行队列,保持顺序并降低触发限流概率
59+
- 自动截断:Telegram `sendMessage` 文本 4096;Discord webhook `content` 2000
60+
- 处理 429:按 `Retry-After`/`retry_after` 等信息退避重试(上限次数)
61+
- 脱敏:复用 main 侧 `redact.ts`(token、webhook URL、Authorization、apiKey 等)
62+
4. Tests
63+
- payload builder、截断、脱敏、队列顺序、429 退避、配置 schema
64+
- 可选:本地 mock server 验证 Telegram/Discord 200/429/500 行为
65+
66+
## 里程碑验收(Definition of Done)
67+
68+
- Settings 可配置 Telegram/Discord(启用/禁用 + 参数 + 事件勾选)并能 Test 成功/失败可见
69+
- Settings 可配置 Confirmo(检测 hook 可用性 + 事件勾选)并能 Test 成功/失败可见
70+
- 每个生命周期事件均可配置单个 command(启用/禁用)并能 Test 执行(展示 exit code/stdout/stderr 摘要)
71+
- 生命周期触发后可按配置向 Telegram/Discord/Confirmo 发送消息(失败不影响主流程,日志可追踪)
72+
- 不读取任何外部配置文件;默认关闭;不影响现有系统通知与聊天主流程
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
# Hooks 与 Webhook 通知(DeepChat)
2+
3+
## 背景
4+
5+
DeepChat 目前已有系统通知(OS Notification)与 UI 内提示,但缺少一套“可配置、可复用、可路由”的通知能力:
6+
7+
- 用户希望在关键生命周期点触发通知(例如:开始/结束、工具调用前后、权限请求等)。
8+
- 用户希望用 **一个命令输入框** 快速接入任意 webhook(例如 `curl`/`node` 脚本),并在 Settings 里一键测试。
9+
- 同时提供 **内置 Telegram / Discord / Confirmo** 常用通道,简单配置参数后勾选要推送的事件即可。
10+
11+
本功能只做“通知/观测”,不改变 DeepChat 的执行语义。
12+
13+
## 目标
14+
15+
- 在 Settings 中提供三类能力(均可启用/禁用,默认关闭):
16+
- **Telegram 通知**:全局配置(token/chatId/threadId)+ 事件勾选 + Test
17+
- **Discord 通知**:全局配置(webhookUrl)+ 事件勾选 + Test
18+
- **Confirmo 通知**:检测本地 hook 文件存在后可启用 + Test(默认全部事件)
19+
- **Hooks Commands**:每个生命周期事件一个 command 输入框(右侧 Test)+ 每事件启用/禁用
20+
- Hooks command 执行契约:
21+
- 每次触发将事件 payload 以 **stdin JSON** 传入命令
22+
- 捕获 stdout/stderr/exit code,仅用于诊断与日志(不阻断主流程)
23+
- Telegram/Discord 采用 outbound HTTP 请求(webhook/API),不做交互式组件、不接收回调。
24+
- Confirmo 采用本地 hook 执行(stdin payload),不做交互式组件。
25+
- 不读取/合并任何外部配置文件;所有配置仅由 DeepChat Settings 管理。
26+
27+
## 非目标(v1)
28+
29+
- 不提供双向 bot 交互(按钮、指令、回调、鉴权登录)。
30+
- 不提供复杂模板系统(仅提供固定内置消息格式;高级自定义由 command hooks 覆盖)。
31+
- 不提供“阻止/中止/改写”的 hooks 能力(exit code/输出不会影响工具与权限流程)。
32+
- 不提供按事件分别配置 Telegram/Discord 参数(仅全局配置 + 事件勾选)。
33+
34+
## 用户体验(Settings)
35+
36+
### 入口
37+
38+
在 Settings 增加一个页面或 section:`Notifications & Hooks`(建议独立页面,避免塞进现有 DisplaySettings)。
39+
40+
### 页面布局(从上到下)
41+
42+
1. Telegram 卡片(顶部)
43+
2. Discord 卡片
44+
3. Confirmo 卡片
45+
4. Hooks Commands 卡片(生命周期列表)
46+
47+
卡片交互参考知识库配置的模式:外层卡片 + Switch 启用/禁用 + 可折叠内容区域。
48+
49+
### Telegram 卡片
50+
51+
- Enable(Switch)
52+
- Bot Token(password input,可 reveal)
53+
- Chat ID(text input)
54+
- Thread ID(可选,text/number input,对应 `message_thread_id`
55+
- Events(多选勾选要推送的生命周期事件;默认建议勾选“重要事件”)
56+
- Test(按钮):发送一条测试消息,不依赖真实会话
57+
58+
### Discord 卡片
59+
60+
- Enable(Switch)
61+
- Webhook URL(password input,可 reveal)
62+
- Events(多选勾选要推送的生命周期事件)
63+
- Test(按钮):发送一条测试消息
64+
65+
### Confirmo 卡片
66+
67+
- Enable(Switch;仅在检测到 hook 文件后可用)
68+
- 默认发送全部事件,无需配置事件类型
69+
- Test(按钮):触发一次测试通知
70+
- 若未检测到 `~/.confirmo/hooks/confirmo-hook.js`,整卡片不可用并提示路径
71+
72+
### Hooks Commands 卡片
73+
74+
- Enable Hooks Commands(Switch)
75+
- 生命周期事件列表(每行):
76+
- 事件名(label)
77+
- Enable(Switch,便于保留 command 但临时停用)
78+
- Command(单行 input;留空视为未配置)
79+
- Test(按钮,位于输入框右侧):触发一次“模拟事件”,执行该 command
80+
81+
Test 结果展示(每行/每通道均需要):
82+
83+
- success/failed
84+
- 耗时(ms)
85+
- exit code(command)
86+
- stdout/stderr 摘要(最多 N 字符,避免 UI 卡顿)
87+
- 错误信息(HTTP status、429 退避信息、网络错误等)
88+
89+
## 生命周期事件(Hook Events)
90+
91+
> 事件名为 DeepChat 内部稳定 API(建议保持 PascalCase 以便脚本易读)。
92+
93+
| Event | 触发时机(主链路) | 关键字段(payload) |
94+
| --- | --- | --- |
95+
| `SessionStart` | 一次生成链路开始(准备调用 LLM 前) | `conversationId``workdir``providerId``modelId` |
96+
| `UserPromptSubmit` | 用户提交消息后、调用 LLM 前 | `promptPreview``messageId` |
97+
| `PreToolUse` | 工具调用执行前 | `tool.name``tool.callId``tool.paramsPreview` |
98+
| `PostToolUse` | 工具调用成功后 | `tool.name``tool.callId``tool.responsePreview` |
99+
| `PostToolUseFailure` | 工具调用失败后 | `tool.name``tool.callId``tool.error` |
100+
| `PermissionRequest` | 出现权限请求时 | `permission.*`(tool/permissionType/description/options) |
101+
| `Stop` | 生成停止(用户停止/完成/错误) | `stop.reason``stop.userStop` |
102+
| `SessionEnd` | 一次生成链路结束(finalize) | `usage?``error?``stop?` |
103+
104+
说明:
105+
106+
- 以上事件是 v1 必须落地的最小集合;后续可增量增加更多事件,但不能修改既有事件语义与字段含义。
107+
- Telegram/Discord 的 “Events 多选” 与 Hooks Commands 的事件列表保持同一集合,便于用户理解;Confirmo 默认全部事件。
108+
109+
## Hook Command 执行契约
110+
111+
### 输入(stdin)
112+
113+
触发时将 payload JSON 写入 stdin,一次性写入并关闭 stdin。
114+
115+
建议 payload 结构(v1):
116+
117+
```jsonc
118+
{
119+
"payloadVersion": 1,
120+
"event": "PreToolUse",
121+
"time": "2026-02-09T18:00:00.000Z",
122+
"isTest": false,
123+
"app": {
124+
"version": "0.5.7",
125+
"platform": "win32"
126+
},
127+
"session": {
128+
"conversationId": "conv_xxx",
129+
"agentId": "agent_xxx",
130+
"workdir": "C:\\repo\\project"
131+
},
132+
"user": {
133+
"messageId": "msg_xxx",
134+
"promptPreview": "Summarize the diff..."
135+
},
136+
"tool": {
137+
"callId": "toolcall_xxx",
138+
"name": "execute_command",
139+
"paramsPreview": "{\"command\":\"pnpm test\"}"
140+
},
141+
"permission": null,
142+
"stop": null,
143+
"error": null
144+
}
145+
```
146+
147+
字段策略:
148+
149+
- `*Preview` 字段默认应为“截断后的摘要”,避免把完整敏感内容外发;如需完整内容,推荐用户用 command hooks 自己读取上下文(或未来新增显式开关)。
150+
- Telegram/Discord 使用简洁卡片文本,不发送原始 payload;原始 payload 仅用于 Hooks Commands / Confirmo。
151+
- `isTest=true` 用于区分 Settings 的 Test 触发,脚本可据此避免产生副作用。
152+
153+
### 进程与环境
154+
155+
- 使用 `child_process.spawn` 执行 `command`(建议 `shell: true` 以支持用户常见的 `&&`/管道)。
156+
- `cwd`:优先使用当前会话的 `workdir`;若不可得,则回落到应用记录的最近 workdir;再回落到 `process.cwd()`
157+
- `timeout`:v1 可用固定默认(例如 30s),后续再支持可配置。
158+
- env:可附加少量只读变量,便于脚本快速取用(可选):
159+
- `DEEPCHAT_HOOK_EVENT`
160+
- `DEEPCHAT_CONVERSATION_ID`
161+
- `DEEPCHAT_WORKDIR`
162+
163+
### 输出(stdout/stderr/exit code)
164+
165+
- stdout/stderr:仅记录与展示摘要(Diagnostics),不做结构化解析要求。
166+
- exit code:仅用于标记成功/失败(Diagnostics),不影响 DeepChat 主链路。
167+
168+
## 内置通道:Telegram
169+
170+
### 配置
171+
172+
- `enabled: boolean`
173+
- `botToken: string`(secret)
174+
- `chatId: string`
175+
- `threadId?: string`(可选,映射到 `message_thread_id`
176+
- `events: HookEventName[]`
177+
178+
### 发送
179+
180+
- Endpoint:`POST https://api.telegram.org/bot{token}/sendMessage`
181+
- Body(JSON):`chat_id``text`、可选 `message_thread_id`
182+
- 文本长度限制:`text` 1-4096 字符(超出需截断)
183+
184+
### 建议默认消息格式
185+
186+
卡片式文本,字段简洁,突出事件与时间即可。
187+
188+
## 内置通道:Discord(Incoming Webhook)
189+
190+
### 配置
191+
192+
- `enabled: boolean`
193+
- `webhookUrl: string`(secret)
194+
- `events: HookEventName[]`
195+
196+
### 发送
197+
198+
- `POST webhookUrl`
199+
- Body(JSON):`embeds`(卡片)+ `allowed_mentions: { parse: [] }`(避免误 @),`content` 可选
200+
- 采用 embeds 形成卡片式消息(符合 Discord message object 结构)
201+
202+
## 内置通道:Confirmo(Local Hook)
203+
204+
### 配置
205+
206+
- `enabled: boolean`
207+
- `events: HookEventName[]`(固定为全部事件,Settings 不提供选择)
208+
- 可用性:仅当 `~/.confirmo/hooks/confirmo-hook.js` 存在时可启用
209+
210+
### 执行
211+
212+
- 使用内置 Node(如存在)执行 `confirmo-hook.js`,否则调用系统 `node`
213+
- 通过 stdin 写入 payload JSON(与 Hooks Commands 相同)
214+
215+
## 触发与分发策略(运行时)
216+
217+
当事件发生时,异步分发到以下目标(互不影响):
218+
219+
1. Hooks Commands:若该事件启用且 command 非空,则执行
220+
2. Telegram:若 enabled 且该事件在 events 列表中,则发送
221+
3. Discord:同上
222+
4. Confirmo:若 enabled 且该事件在 events 列表中,则执行
223+
224+
要求:所有分发均为 **best-effort**,不得阻塞 LLM/工具调用主流程。
225+
226+
## 可靠性与保护
227+
228+
- **串行队列**:Telegram/Discord 分别串行发送,保持顺序并降低限流概率。
229+
- **429 退避**:遇到限流按平台返回的等待时间进行重试(上限次数),最终失败写日志即可。
230+
- **截断**:按平台长度限制截断并在末尾加 `…(truncated)`
231+
- **脱敏**:对日志与 diagnostics 做脱敏(token、webhookUrl、Authorization 等)。
232+
233+
## 依赖与实现建议
234+
235+
尽量复用现有依赖,避免引入新包:
236+
237+
- Schema:`zod`(已在 dependencies)
238+
- HTTP:优先用 Node `fetch`(Node 20)或复用现有 `axios`
239+
- Command:`child_process`(必要时复用 `cross-spawn`
240+
- 日志:`electron-log`(已存在)
241+
242+
## 外部参考(实现用)
243+
244+
```text
245+
Telegram Bot API sendMessage:
246+
https://core.telegram.org/bots/api#sendmessage
247+
248+
Discord webhook rate limit note (Safety Center, for reference):
249+
https://discord.com/safety/using-webhooks-and-embeds
250+
```
251+
252+
## 已确认决策(来自需求)
253+
254+
1. 仅仅通知(不阻断流程)。
255+
2. 按 DeepChat 设计,不要求完全照抄任何外部实现。
256+
3. webhook 就够(Telegram/Discord 仅 outbound;无交互),Confirmo 走本地 hook。
257+
4. 所有配置都在 Settings 完成;Telegram/Discord/Confirmo 置顶且全局配置;生命周期事件每个只提供一个 command 输入框 + 右侧 Test。

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "DeepChat",
3-
"version": "0.5.7",
3+
"version": "0.5.8",
44
"description": "DeepChat,一个简单易用的 Agent 客户端",
55
"main": "./out/main/index.js",
66
"author": "ThinkInAIXYZ",

0 commit comments

Comments
 (0)