dsh-messager 0.3.1 → 0.3.3

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/README.en.md CHANGED
@@ -178,13 +178,16 @@ pnpm typecheck # host side
178
178
  pnpm build # host tsc + client declarations + client bundle (lib/)
179
179
  ``
180
180
 
181
- ## Version compatibility (dsh-messager 0.3.1 / DSH 0.1.2-rc.1)
181
+ ## Version compatibility (dsh-messager 0.3.3 / DSH 0.1.7-alpha.1)
182
182
 
183
- - **v0.3.1 supports only DSH `0.1.2-rc.1`**; all `@deepseek-ai/dsh-*` peerDependencies are pinned to that version.
184
- - This release only updates the DSH peer dependency versions; notification logic, configuration format, and existing channel behavior are unchanged.
183
+ - **v0.3.3 supports only DSH `0.1.7-alpha.1`**; all `@deepseek-ai/dsh-*` peerDependencies are pinned to that version.
184
+ - **This is a breaking update.** DSH 0.1.7 changed its settings configuration model and client APIs, so older DSH versions are incompatible. If you still use an older DSH version, do not upgrade to dsh-messager v0.3.3. Stay on dsh-messager v0.3.1 / DSH 0.1.2-rc.1, or upgrade DSH to 0.1.7-alpha.1 first.
185
185
  - Compatibility notes:
186
186
  - The removed `dsh-client-runtime` is no longer used. Client session lists use `dsh-api-session-controller`, interaction state uses `dsh-client-ui-session`, and slot services use `dsh-client-ui-renderer`.
187
- - The `messager` settings namespace is registered from the Loader config and can also be read/written through the plugin's own `/dsh-messager/config` route, which is not subject to DSH's settings namespace allowlist.
187
+ - The settings namespace is the profile entry ID (`messager` by default). Configuration remains available through the plugin's own `/dsh-messager/config` route. DSH 0.1.7 loads the schema from the entry module's exported `Config`, requires editable fields to be `.volatile()`, and broadcasts changes through `settings/document-updated`.
188
+ - DSH 0.1.7 imports an existing legacy `settings.yaml` into the profile at startup and renames it to `settings.yaml.imported`.
189
+ - v0.3.3 reads the live volatile configuration when each notification is delivered, keeps browser notifications disabled until the host configuration loads, honors trigger filters in the browser, and refreshes configuration when a background tab becomes visible.
190
+ - The settings form keeps its save controls visible and shows the number of unsaved changes.
188
191
 
189
192
  ## Known limitations
190
193
 
package/README.md CHANGED
@@ -13,12 +13,12 @@ DeepSeek Harness(DSH)**任务状态通知插件**:会话需要交互、任
13
13
 
14
14
  | 需求 | 实现 |
15
15
  | --- | --- |
16
- | 触发时机 | 需要交互(审批 `approval/asked`、提问/计划待审 `ask_user_question`、客户端 `uiSession.pendingInteractions`)、任务完成(`agent/status` running→idle 且仅根会话 + `turn/end` 原因)、任务出错(`agent/error`) |
16
+ | 触发时机 | 需要交互(审批 `approval/asked`、提问/计划待审 `ask_user_question`、客户端 `uiSession.sessionStatus`)、任务完成(`agent/status` running→idle 且仅根会话 + `turn/end` 原因)、任务出错(`agent/error`) |
17
17
  | 推送路径 | 系统通知(node-notifier toast)、浏览器通知(Notification API)、飞书(interactive 卡片 + HMAC-SHA256 签名)、企业微信(markdown + 可选加签)、Discord(embed 卡片)、钉钉(actionCard + 可选加签)、Telegram(Bot API HTML 消息);`NotifyChannel` 接口可扩展 |
18
18
  | 可配置 | 触发开关、各通道启停/verbosity/icon、去重冷却、标题前缀等,见[配置](#配置) |
19
19
 
20
- 触发语义与 Web UI 状态圆点完全对齐:**橙点 = 需要交互**(`uiSession.pendingInteractions`),**绿点 = 任务完成**
21
- (`running→idle` 且非当前会话),**蓝点 = 运行中**(不通知)。
20
+ 触发语义与 Web UI 状态圆点完全对齐:**橙点 = 需要交互**(`uiSession.sessionStatus`),**绿点 = 任务完成**
21
+ (`running→idle` 且不在主视图),**蓝点 = 运行中**(不通知)。
22
22
 
23
23
  ## 安装
24
24
 
@@ -42,7 +42,10 @@ dsh web # 或 dsh --profile web
42
42
 
43
43
  > - `--patch` 不是安装步骤,而是可选的**开发调试**手段(见下节「本地开发」):
44
44
  > 它只加载 host 端、不写 profile、仅对本次启动生效。装了 bundle 之后**请勿再同时
45
- > 带 `--patch` 启动同一插件**(host 端会加载两份,settings 命名空间重复注册报错)。
45
+ > 带 `--patch` 启动同一插件**(host 端会加载两份,同一事件重复通知)。
46
+ > ⚠️ 另外,经 `--patch` 装入的条目 id 会带 `include:` 前缀、且**不会进入
47
+ > `settings.describe()`**,因此 `--patch` 模式下设置页分区必然显示「不可用」——
48
+ > 这是该调试路径的固有限制,验证设置页请走 `dsh plugin add` 安装。
46
49
  > - 以**源码方式运行 DSH**(从 deepseek-harness 仓库根目录)时,把上述 `dsh` 换成
47
50
  > `pnpm dsh` 即可,命令与行为完全一致:`pnpm dsh plugin --profile web add …`、
48
51
  > `pnpm dsh web`。profile 目录仍为 `$DSH_HOME/profiles/web`(`dsh web` 即
@@ -58,7 +61,7 @@ webServer 路由(`/dsh-messager/config`,同源校验 + 脱敏视图)直达
58
61
  `settings` 服务 —— **不依赖 DSH 的设置白名单,发行版(npx 安装)开箱即用**,
59
62
  无需任何补丁。
60
63
 
61
- > 配置与 `settings.yaml` 同源(同一命名空间):任一处变更均实时生效。
64
+ > 配置与 host 端**同源**(同一 settings 命名空间):任一处变更均实时生效。
62
65
 
63
66
  ## 本地开发
64
67
 
@@ -82,21 +85,34 @@ webServer 路由(`/dsh-messager/config`,同源校验 + 脱敏视图)直达
82
85
  ## 配置
83
86
 
84
87
  配置优先级:**schema 默认值 → base(该插件行的 `config:`)→ 用户层(Web 设置页)**。
85
- host 端把 Loader config 注册为 settings 命名空间 `messager` 的 base 层,因此:
88
+
89
+ > ⚠️ **DSH 0.1.7 的配置模型**(与旧版不同,务必知悉):
90
+ > - settings 命名空间 = 插件在 profile 中的**条目 id**(本包 `cordis.patch.yml`
91
+ > 声明为 `messager`),**不是**插件自己注册的字符串;
92
+ > - schema 由 Loader 直接读取**插件入口模块导出的 `Config`**,因此 `src/index.ts`
93
+ > 必须 `export { Config }`——不导出则该条目被 `describe()` 静默跳过,设置页与
94
+ > 配置路由一律显示「不可用」且**不报错**;
95
+ > - 所有可编辑字段必须标记 `.volatile()`:DSH 用 volatile 门控写入,非 volatile
96
+ > 路径会被 `settings.mutate` 拒绝,且无 volatile 字段时整个命名空间判为不可配置;
97
+ > - 已**没有** `ctx.settings.register(...)` 这种 API;配置热更新改由
98
+ > `settings/document-updated` 事件驱动。
99
+
86
100
  - base 的写法按使用方式不同:dev 调试写在 `cordis.yml`(patch 覆盖层)里该行的
87
101
  `config:`;正式安装写在 **profile 的 `cordis.patch.yml`** 里按 `id: messager`
88
102
  覆盖该行,或直接改 bundle 包内的 `cordis.patch.yml`;
89
- - 用户层三处入口,**同源不冲突、任一处变更均实时生效**(host 端 `watch` 重建通道;
90
- client 端经 `settings/document-updated` 失效重拉):
103
+ - 用户层两处入口,**同源不冲突、任一处变更均实时生效**(host 端订阅
104
+ `settings/document-updated` 重建通道;client 端同样据此失效重拉):
91
105
  1. **设置页分区**:设置 →「通知&信使」分区(完整字段表单,所有环境可用);
92
- 2. **设置文档**:直接编辑 `$DSH_HOME/settings.yaml` 的 `messager:` 段(完整字段,
93
- 含 dedup 节流等表单未展示的项);
94
- 3. **RPC**:settings.describe / settings.mutate(host 侧可用;Web 端白名单不影响本插件
95
- 的分区,因为分区走插件自己的配置路由)。
106
+ 2. **RPC**:settings.describe / settings.mutate(host 侧可用;Web 端白名单不影响
107
+ 本插件的分区,因为分区走插件自己的配置路由)。
96
108
 
97
109
  > 配置读写链路:设置分区 → `GET/POST /dsh-messager/config`(webServer 路由,同源校验)
98
- > → host 端 `settings` 服务(describe 脱敏视图 / mutate 逐字段 ops)→ settings.yaml。
99
- > 写后 `settings/document-updated` 事件(DSH 内置转发)驱动前端刷新。
110
+ > → host 端 `settings` 服务(describe 脱敏视图 / mutate 逐字段 ops)→ profile 的
111
+ > `cordis.patch.yml`。写后 `settings/document-updated` 事件(DSH 内置转发)驱动前端刷新。
112
+ >
113
+ > 📌 DSH 0.1.7 已废弃 `$DSH_HOME/settings.yaml` 作为配置源:启动时若存在会被自动
114
+ > 导入 profile 并**重命名为 `settings.yaml.imported`**。请改编辑 profile 的
115
+ > `cordis.patch.yml`(或用设置页)。
100
116
  >
101
117
  > 🌐 **国际化**:分区菜单与表单文案随 DSH 设置的语言切换(中文 / English),
102
118
  > 字典注册在 `ctx.locale`(zh/en 键集一致,缺失键 fail loud 显示键名)。
@@ -151,9 +167,9 @@ host 端把 Loader config 注册为 settings 命名空间 `messager` 的 base
151
167
 
152
168
  | 触发 | host 端(system/feishu/wecom/discord/dingtalk/telegram) | client 端(browser) |
153
169
  | --- | --- | --- |
154
- | 审批 | `session/event` `approval/asked` | `ctx.uiSession.pendingInteractions` 中 `kind==='approval'` 从无到有 |
155
- | 提问/计划待审 | `session/event` `tool/call`(`ask_user_question`) | `ctx.uiSession.pendingInteractions` 中 `kind==='question'/'plan-review'` 从无到有 |
156
- | 任务完成 | `agent/status` running→idle(仅根会话)+`turn/end` 原因 | 摘要 `running:true→false` 且非当前会话 |
170
+ | 审批 | `session/event` `approval/asked` | `ctx.uiSession.sessionStatus` 中 `pendingInteraction.kind==='approval'` 从无到有 |
171
+ | 提问/计划待审 | `session/event` `tool/call`(`ask_user_question`) | `ctx.uiSession.sessionStatus` 中 `pendingInteraction.kind==='question'/'plan-review'` 从无到有 |
172
+ | 任务完成 | `agent/status` running→idle(仅根会话)+`turn/end` 原因 | 摘要 `running:true→false` 且 `retainedBy.mainView` 为空 |
157
173
  | 任务出错 | `agent/error` | -(host 端覆盖) |
158
174
 
159
175
  ## 通道扩展
@@ -181,14 +197,14 @@ dsh-messager/
181
197
  ├── assets/icon.png # 默认通知图标
182
198
  ├── doc/plan/ # 规划存档(01 起编号)
183
199
  ├── src/
184
- │ ├── index.ts # host apply:事件接线 + settings 注册 + 通道构建 + 路由挂载
185
- │ ├── config.ts # Config schema(Loader config 与 settings 共用)
200
+ │ ├── index.ts # host apply:事件接线 + 通道构建 + 路由挂载(并导出 Config schema)
201
+ │ ├── config.ts # Config schema(全字段 .volatile();Loader config 与 settings 共用)
186
202
  │ ├── config-shared.ts # 配置路由的跨端共享类型(host/client 共用)
187
203
  │ ├── config-route.ts # webServer 配置路由(GET 视图 / POST ops,同源校验)
188
204
  │ ├── signals.ts # 事件 → Signal 提取(纯函数)
189
205
  │ ├── notify.ts # 调度:过滤/冷却/防抖/限流 + NotifyChannel 接口
190
206
  │ ├── templates.ts # verbosity 模板渲染(纯函数)
191
- │ ├── settings.ts # settings 命名空间注册(base = Loader config)
207
+ │ ├── settings.ts # 条目 id(settings 命名空间)解析,供配置路由使用
192
208
  │ ├── channels/ # system(node-notifier)、feishu/wecom/discord/dingtalk/telegram(webhook/Bot API+签名)
193
209
  │ └── client/ # 浏览器端:sessions diff、Notification、设置分区、配置同步
194
210
  │ ├── index.ts # 分区注册(动态 order)+ 浏览器通知 + 配置路由访问器
@@ -199,29 +215,39 @@ dsh-messager/
199
215
  │ ├── locales.ts # zh/en 字典(ctx.locale 注册)
200
216
  │ ├── config.ts # 浏览器通知的配置句柄(走配置路由)
201
217
  │ └── diff.ts # 完成摘要 / 待交互状态 diff(纯函数)
202
- └── tests/ # vitest 单元测试(129 个)
218
+ └── tests/ # vitest 单元测试(147 个)
203
219
  ```
204
220
 
205
221
  ## 测试
206
222
 
207
223
  ```sh
208
- pnpm test # 129 个单元测试:信号提取/模板/调度/各通道签名与载荷/配置解析/client diff/配置路由/fetch scope/字典一致性/表单门控
224
+ pnpm test # 147 个单元测试:信号提取/模板/调度/各通道签名与载荷/配置解析与 volatile 契约/client diff/配置路由/fetch scope/字典一致性/表单门控
209
225
  pnpm typecheck # host 端
210
226
  pnpm build # host tsc + client 声明 + client bundle(lib/)
211
227
  ```
212
228
 
213
- ## 版本兼容(dsh-messager 0.3.1 / DSH 0.1.2-rc.1)
229
+ > ⚠️ 测试**不会**投递真实系统通知:`vitest.config.ts` 用 `resolve.alias` 把
230
+ > `node-notifier` 换成 no-op 桩(`tests/stubs/node-notifier.ts`)。系统通道的 schema
231
+ > 默认值就是 `enabled: true`,不换桩的话 `pnpm test` 会真的弹 Windows toast。
232
+
233
+ ## 版本兼容(dsh-messager 0.3.3 / DSH 0.1.7-alpha.1)
214
234
 
215
- - **v0.3.1 仅支持 DSH `0.1.2-rc.1`**;所有 `@deepseek-ai/dsh-*` peerDependencies
235
+ - **v0.3.3 仅支持 DSH `0.1.7-alpha.1`**;所有 `@deepseek-ai/dsh-*` peerDependencies
216
236
  统一锁定该版本,不再兼容旧 RC 接口。
217
- - 本版本仅更新 DSH peer 依赖版本;通知逻辑、配置格式和现有通道行为不变。
218
237
  - client 端适配新版拆分:会话列表来自 `dsh-api-session-controller`,交互状态来自
219
- `dsh-client-ui-session` 的 `ctx.uiSession.pendingInteractions`,`ctx.slots` 由
238
+ `dsh-client-ui-session` 的 `ctx.uiSession.sessionStatus`,`ctx.slots` 由
220
239
  `dsh-client-ui-renderer` 提供;不再依赖已移除的 `dsh-client-runtime`。
221
- - 完成通知仍按会话摘要 `running: true → false` 且非当前会话触发;交互通知仅在
240
+ - 完成通知仍按会话摘要 `running: true → false` 且不在主视图触发;交互通知仅在
222
241
  `approval` / `question` / `plan-review` 从无到有时触发,首次订阅只建立基线。
223
- - host 设置使用字符串命名空间 `messager`;配置读写继续走插件自有 webServer 路由
224
- `/dsh-messager/config`,现有 schema、settings 数据和第三方通道配置无需迁移或重置。
242
+ - host 设置使用 profile 条目 id 作为命名空间(本包为 `messager`);配置读写继续走插件
243
+ 自有 webServer 路由 `/dsh-messager/config`,现有 schema 与第三方通道配置无需迁移或重置。
244
+ - **0.1.7 配置模型迁移**(v0.3.2):移除已不存在的 `ctx.settings.register`;schema 改由
245
+ Loader 读取入口导出的 `Config`;全部可编辑字段标记 `.volatile()`;命名空间由
246
+ `ctx.fiber.entry.options.id` 动态解析(不再硬编码)。`@deepseek-ai/cordis` 升至
247
+ `^4.0.3`(4.0.2 不导出 `Volatile`),`schemastery` 对齐 `^3.18.3`(避免双实例)。
248
+ - **v0.3.3**:host 调度器改为**投递时读取 volatile 引用**(不再缓存配置快照,也不再依赖
249
+ `settings/document-updated` 的时序),配置一改立即生效;client 端修掉「拉取失败静默开启
250
+ 浏览器通知」与「浏览器通道忽略 `triggers.*`」两个缺陷,并在标签页恢复可见时补拉配置。
225
251
 
226
252
  ## 已知边界
227
253