dsh-notify-me 1.7.0 → 1.9.0

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.md CHANGED
@@ -1,117 +1,242 @@
1
+ <div align="center">
2
+
3
+ <img src="https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/brand/icon-app-128.png" width="76" height="76" alt="dsh-notify-me">
4
+
1
5
  # dsh-notify-me
2
6
 
7
+ **离开 DSH 页面,也能及时知道何时需要回来。**
8
+
3
9
  简体中文 | [English](README.en.md)
4
10
 
5
11
  [![npm version](https://img.shields.io/npm/v/dsh-notify-me?style=flat-square&label=npm&color=cb3837)](https://www.npmjs.com/package/dsh-notify-me)
6
- [![npm downloads](https://img.shields.io/npm/dm/dsh-notify-me?style=flat-square&label=downloads&color=1F883D)](https://www.npmjs.com/package/dsh-notify-me)
7
- ![License](https://img.shields.io/badge/license-MIT-blue)
8
- ![Platform](https://img.shields.io/badge/platform-browser-blue)
9
- ![Size](https://img.shields.io/badge/bundle-%7E79KB-green)
12
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-notify-me?style=flat-square&label=downloads%2Fmonth&color=1F883D)](https://www.npmjs.com/package/dsh-notify-me)
13
+ [![npm total downloads](https://img.shields.io/npm/dt/dsh-notify-me?style=flat-square&label=total%20downloads&color=1F883D)](https://www.npmjs.com/package/dsh-notify-me)
14
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)
15
+ [![DSH Web and Desktop](https://img.shields.io/badge/DSH-Web%20%7C%20Desktop-blue?style=flat-square)](#安装)
16
+ [![Client bundle size](https://img.shields.io/badge/client-%7E156%20KiB-green?style=flat-square)](lib/client.js)
17
+ [![DSH Compatibility](https://img.shields.io/badge/DSH-%E5%B7%B2%E9%80%82%E9%85%8D%200.2.1--rc.2-6366f1.svg?style=flat-square)](#兼容性)
10
18
  [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
11
19
 
12
- ---
20
+ </div>
13
21
 
14
- **离开 DSH 页面也不错过任何动静。** 当模型停下来需要你操作(审批 / 方案待确认 / 提问)、或你在别的软件时回复正好在后台完成,dsh-notify-me 会用系统通知 + 提示音 + 标签页标题标记提醒你——权限审批的通知还带「同意 / 拒绝」按钮,点一下就完成裁决,不用切回页面。开关和通知语言都直接在 **DSH 设置 → 通知提醒** 里改。
22
+ [安装](#安装) · [效果预览](#效果预览) · [配置](#在-dsh-设置里改配置) · [兼容性](#兼容性) · [更新日志](CHANGELOG.md)
15
23
 
16
- ---
24
+ DSH Web / Desktop 的通知插件,让你敢不开完整访问,也不必一直守着页面。
17
25
 
18
- ## 为什么需要它
26
+ - **需要你操作时**:审批、方案确认、提问,用通知、提示音和标题标记提醒。
27
+ - **后台回复完成时**:及时回来查看结果,点击通知可回到对应对话。
28
+ - **离开电脑时**:可选转发到 Discord、Bark、Gotify 或自己的 Webhook。
29
+ - **不看主屏时**:可选页面内浮层提醒,跟着 DSH 窗口出现在你正看着的那块屏(系统通知只会出现在主屏)。
19
30
 
20
- DSH 的两种权限模式各有代价:
31
+ > 页面或桌面应用需保持运行,后台 / 最小化可以。系统通知需要通知权限;审批按钮在支持 Service Worker 的 Web 环境(如 `http://127.0.0.1` 或 `https`)由通知提供,桌面端的通知没有按钮——打开「页面浮层提醒」后可在浮层上直接裁决(见[副屏与浮层提醒](#副屏与浮层提醒))。
21
32
 
22
- | 模式 | 你付出的代价 | 代价形态 |
23
- | --- | --- | --- |
24
- | 不开完整访问(`workspace-write` + ask) | **等待**——agent 卡在审批上,不盯着页面就是干等 | 时间成本,随会话数增长 |
25
- | 开完整访问(full access) | **不可逆风险**——放弃的是事前拦截能力 | 风险成本,与你盯不盯无关 |
33
+ > 🔎 想找这个插件?可以搜:`dsh-notify-me`、**消息提醒**、**可操作提醒**、**桌面通知**、**需要你操作**、**回复完成提醒**、**后台完成提醒**、**外部通知**、**Discord / Bark / Gotify 推送**(npm 关键词已含以上中英文词)。
26
34
 
27
- dsh-notify-me 把「监督」和「守在屏幕前」解耦:只在真的出现决策点(审批 / 方案确认 / 提问)或回复跑完时,才用系统通知把你叫回来——**让你敢不开完整访问**,不必靠放弃拦截能力来换效率。它不降低 full access 本身的权限风险(它不是沙箱),只是把 ask 模式的等待成本压到接近零。
35
+ ## 效果预览
28
36
 
29
- ---
37
+ ![Windows 上经 Edge 显示的 DSH 普通通知,未包含审批按钮](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/notify-toast.png)
30
38
 
31
- > 🔎 想找这个插件?可以搜:`dsh-notify-me`、**消息提醒**、**可操作提醒**、**桌面通知**、**需要你操作**、**回复完成提醒**、**后台完成提醒**、**外部通知**、**Discord / Bark / Gotify 推送**(npm 关键词已含以上中英文词)。
39
+ *普通通知示例 · Windows / Edge · 不含审批按钮。* [查看原图](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/notify-toast.png)
32
40
 
33
- ## 效果预览
41
+ ![DSH 页面右下角的三张浮层提醒:提问、审批请求(带「同意 / 拒绝」按钮)、回复完成](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/overlay-zh.png)
42
+
43
+ *页面浮层提醒(1.8.0)· 真实插件在独立演示页里渲染 · 系统通知画不到副屏时用它,卡片落在 DSH 窗口所在的那块屏。* [查看原图](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/overlay-zh.png)
44
+
45
+ <details>
46
+ <summary>展开设置界面预览</summary>
47
+
48
+ ![通知提醒设置页:页眉、提醒方式、什么时候提醒、试一试与折叠的高级设置](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/settings-zh.png)
49
+
50
+ 真实插件设置组件(v1.9.0 默认配置)在独立演示环境里整页渲染;只保留左侧导航作参照,不是 DSH 宿主外壳。
51
+ </details>
52
+
53
+ ## 安装
54
+
55
+ ### DSH Web
56
+
57
+ 已安装 DSH CLI 的用户,在终端执行:
58
+
59
+ ```powershell
60
+ # 安装并自动挂载进 web profile
61
+ dsh plugin --profile web add dsh-notify-me
62
+ ```
63
+
64
+ 重启 `dsh web`,然后硬刷新页面(Ctrl+Shift+R)。如果你使用其他 Web profile,请把命令中的 `web` 换成实际名称。
65
+
66
+ ### DSH Desktop
34
67
 
35
- | 系统通知效果(截图来自 Windows) |
36
- | --- |
37
- | ![DSH 通知效果](https://raw.githubusercontent.com/chromoany/dsh-notify-me/main/docs/screenshots/notify-toast.png) |
68
+ 1. 在桌面应用打开 **插件 → 添加插件**。
69
+ 2. 输入 npm 包名 `dsh-notify-me`,按应用提示完成安装,并确认插件已启用。
70
+ 3. 完全退出并重新启动 DSH Desktop,使插件加载。
38
71
 
39
- [更新日志](CHANGELOG.md)
72
+ 桌面端的 `desktop` profile 由 Electron 应用管理;不要把上面的 Web 命令改成 `--profile desktop`,CLI 会拒绝此操作。安装到 Web profile 也不会自动安装到桌面端。
73
+
74
+ ## 首次验证
75
+
76
+ 1. 在 DSH 页面上点击一次,按提示允许通知;若此前拒绝过,在浏览器站点设置中允许通知。操作系统也需要允许对应浏览器 / DSH Desktop 显示通知。
77
+ 2. 打开 **设置 → 通知提醒**,确认出现该分区及底部插件版本号,保持「启用提醒」「系统通知」「提示音」开启。
78
+ 3. 点击设置页的「测试『回复完成』」按钮:应出现一条测试通知,并按当前音效设置播放声音。这个本地测试不会转发到外部通知端点,也不受「页面打开时也提醒」开关限制。
79
+
80
+ Web 用户可再测试审批按钮;桌面端该测试只发普通通知,**没有「同意 / 拒绝」按钮属于预期行为**。
81
+
82
+ **控制台验证(可选)** — 支持 DevTools 的环境也可执行:
83
+
84
+ ```js
85
+ window.__dshNotifyMe.test("done") // 「完成」示例
86
+ window.__dshNotifyMe.test("attention") // 「需要你」示例
87
+ window.__dshNotifyMe.test("approval") // Web 桥可用时带「同意 / 拒绝」按钮;桌面端为无按钮通知
88
+ window.__dshNotifyMe.debug() // 桥接状态看 bridge 字段,active = 按钮可用
89
+ ```
90
+
91
+ 没有测试通知时,先检查:通知权限是否被拒绝(在页面上点一下 → 选「允许」;或地址栏锁 → 站点设置 → 通知 → 允许 → 刷新)、装完没重启 DSH、系统设置里浏览器通知被关。
92
+
93
+ ## 为什么需要它
94
+
95
+ - **不开完整访问(`workspace-write` + ask)**:保留事前审批,但错过请求会让 agent 等待。
96
+ - **开完整访问(full access)**:减少审批打断,同时放弃事前拦截能力。
97
+
98
+ dsh-notify-me 把「监督」和「守在屏幕前」解耦:只在真的出现决策点(审批 / 方案确认 / 提问)或回复跑完时,才用系统通知把你叫回来——**让你敢不开完整访问**,不必靠放弃拦截能力来换效率。它不降低 full access 本身的权限风险(它不是沙箱),只是减少 ask 模式下因错过审批而产生的等待。
40
99
 
41
100
  ## 提醒时机
42
101
 
43
- | 时机 | 提醒内容 | 默认 |
44
- | --- | --- | --- |
45
- | 🔔 **模型需要你操作** — 审批请求 / 方案待确认(plan review)/ 提问(`ask_user_question`) | 通知 + 提示音 + `🔔 需要你 ·` 标题标记;审批的通知上直接带「同意 / 拒绝」按钮 | 页面可见也提醒(当前对话除外:默认只留标题标记) |
46
- | ✅ **回复完成** — 一轮回复跑完;后台会话完成也会报 | 通知 + 提示音;后台会话**完成但还没看**的期间标题带 `✅ 回复完成 ·` 标记,打开该会话即撤 | 仅页面隐藏/后台时提醒(标题标记不受此限) |
102
+ | 事件 | 默认行为 |
103
+ | --- | --- |
104
+ | 🔔 需要你操作 | 页面可见也提醒;当前对话只留标题标记 |
105
+ | ✅ 回复完成 | 页面隐藏 / 后台时提醒 |
106
+
107
+ **需要你操作**包括审批请求、方案待确认(plan review)和提问(`ask_user_question`)。支持快捷裁决的 Web 环境会显示「同意 / 拒绝」按钮,桌面端无按钮。
108
+
109
+ **回复完成**也覆盖后台会话;完成但还没看时,标题带 `✅ 回复完成 ·` 标记,打开对应会话即撤。标题标记不受「页面打开时也提醒」开关限制。
47
110
 
48
111
  > **后台**子代理(subagent)子会话的等待与完成默认**不提醒**:DSH 把每个子代理子会话列成独立会话,但它们是所属主对话那一轮里的步骤,提醒只会是噪音。你当前打开的那个子代理会话不算在内,照常提醒。设置页「子代理会话不提醒」可关掉这个静音。
49
112
 
50
113
  ## 在 DSH 设置里改配置
51
114
 
52
- 打开 **设置 → 通知提醒**(首次安装后刷新一次页面即可看到),页面提供:
115
+ 打开 **设置 → 通知提醒**。页面按「提醒方式 → 什么时候提醒 → 试一试」三段排开,不常改的收进底部「高级设置」,点一下展开。
116
+
117
+ ### 提醒方式
118
+
119
+ - **启用提醒** 总开关:关闭后不弹通知、不响提示音,也不改标签页标题;
120
+ - **系统通知**(默认开):经浏览器弹系统通知,进 Windows / macOS 通知中心;
121
+ - **页面浮层提醒**(默认关):在 DSH 页面角落画提醒卡片,窗口在哪块屏它就在哪块屏——系统通知只会画在主屏,主屏不看时用它;不需要通知权限,桌面端也能在卡片上直接「同意 / 拒绝」,可与系统通知同开。展开后可选四个角落的位置,见[副屏与浮层提醒](#副屏与浮层提醒);
122
+ - **提示音 / 音量**:提示音开关与音量滑块;具体播什么由「高级设置 → 音效来源」决定;
123
+ - **审批通知上直接裁决**(默认开):审批通知带「同意 / 拒绝」,点一下即完成裁决,不用切回页面。**桌面端的通知没有按钮**(`dsh-app://` 页面无法注册 Service Worker),需要按钮就打开「页面浮层提醒」,改在浮层上裁决;设置页会如实说明当前哪种渠道能给按钮。
124
+
125
+ ### 副屏与浮层提醒
126
+
127
+ Windows 的系统通知横幅固定画在主屏上,系统没有设置项、浏览器也没有 API 能把它挪到别的显示器。主屏不看、DSH 停在副屏时,通知就等于没发。
128
+
129
+ 「页面浮层提醒」绕开系统通知中心,直接在 DSH 页面里画一张卡片:窗口在哪块屏,卡片就出现在哪块屏。
130
+
131
+ - **位置**:设置里选右上 / 右下 / 左上 / 左下,默认右下;改完立刻生效;
132
+ - **不需要通知权限**:通知权限没给、或桌面端弹不出带按钮的通知时,浮层照常工作;
133
+ - **审批卡片带「同意 / 拒绝」**:与审批卡片的「允许一次 / 拒绝」等价,桌面端也能用(不依赖 Service Worker);点卡片正文则切回对应对话;
134
+ - **停留时间**:「需要你」20 秒后自动收起,「回复完成」8 秒;带按钮的审批卡片不自动收,直到裁决或手动关掉。最多同时叠 4 张;
135
+ - **与系统通知的关系**:两个开关互不替代。都开着时主屏看系统通知、副屏看浮层,也可以只留浮层。
136
+
137
+ 浮层只知道窗口在哪块屏,不知道你人在看哪块屏。窗口留在主屏、人却盯着副屏时,它同样看不见。
138
+
139
+ ### 什么时候提醒
140
+
141
+ - **页面打开时也提醒「需要你」**(默认开):页面在最前也提醒;关掉后只有切到后台才提醒;
142
+ - **当前对话不弹通知**(默认开):等待就发生在你正看着的对话里时只留标签页标记,免得挡住审批卡片;切到后台后照常提醒,若你已处理掉就作废;
143
+ - **页面打开时也提醒「回复完成」**(默认关):默认只在切到后台时提醒,避免打扰;
144
+ - **子代理会话不提醒**(默认开):跳过后台子代理(subagent)会话——它们是主对话那一轮的步骤,完成由主对话自己的提醒覆盖;你当前打开的那个子代理会话照常提醒;
145
+ - **点击通知回到对应对话**(默认开):点通知把 DSH 带到前台并切到提醒所属的对话;多个标签页同时开着时只调起一个(优先当前可见的那个);关掉后点通知不做任何事。桌面端的抬窗细节见[运行环境与诊断](#运行环境与诊断)。
146
+
147
+ ### 试一试
148
+
149
+ 三个按钮分别发一条「需要你」「回复完成」「审批按钮」测试提醒,用当前设置立即发,**不受**「什么时候提醒」里的开关限制;下方一行如实说明当前哪种渠道能给审批按钮。
150
+
151
+ 设置页底部常显插件版本号(`dsh-notify-me v…`)——报障、核对是否装上新版本时直接照抄这一行。
152
+
153
+ ### 高级设置
154
+
155
+ 默认收起,点一下展开。里面收着三块不常改的东西:音效来源、外部推送、运行环境与诊断——分别见下面三节。
156
+
157
+ ### 音效
158
+
159
+ 「需要你」与「回复完成」可独立选择内置合成音、自定义音频或系统通知音。
160
+
161
+ <details>
162
+ <summary>自定义音频、试听与回落规则</summary>
53
163
 
54
- - **启用提醒** 主开关:关闭后不再弹系统通知、不播放提示音、也不改标签页标题;
55
- - **运行环境**(默认自动识别):按页面协议识别 Web 端 / 桌面端(DSH Desktop,`dsh-app://`),识别不准时可手动指定——桌面端点通知走 `dsh://` 深链抬窗、快捷裁决按钮不可用;Web 端走 `window.focus()` 与 Service Worker 桥。手动覆盖与自动识别不一致时,设置页会明示检测结果;
56
- - **系统通知 / 提示音 / 音量**:Toast、提示音开关与音量滑块;
57
164
  - **音效来源**(「需要你」与「回复完成」各自独立选):内置合成音(默认)/ 自定义音频文件 / 系统通知音。选「自定义音频文件」可在设置页挑一个本地音频(上限 1 MiB,存在浏览器本地,可试听与移除);选「系统通知音」则完全不播插件音效,通知照发,声音交给操作系统(音色跟着系统通知设置走),此时「试听」会改发一条测试通知——该模式没有插件可播的音,你听到的就是它。任一来源缺文件、读不出来或存不下时自动回落到内置合成音,提醒不会因此变成哑的;
165
+
166
+ </details>
167
+
168
+ ### 外部推送
169
+
170
+ 默认关闭。支持 Discord Webhook / Bark / Gotify / 自定义 Webhook;提醒正文会发往你填写的地址,只使用可信端点。
171
+
172
+ <details>
173
+ <summary>目标地址、转发开关与发送测试</summary>
174
+
58
175
  - **外部通知**(默认关):把提醒同时转发到你自己的推送端点,人不在电脑前也能收到——支持 **Discord Webhook** / **Bark** / **Gotify** / **自定义 Webhook**,可加多个目标,每个选类型填地址(Discord 填 Webhook 地址;Bark 填 `https://api.day.app/<设备密钥>`;Gotify 填 `https://<服务器>/message?token=<应用令牌>`;自定义端点收一条 POST JSON:`{source, event, title, body, sessionId, time}`);「转发「需要你」」「转发「回复完成」」各自独立开关;**发送测试通知**往所有目标发一条测试消息(不受这两类开关限制,也不会冒充真提醒)。转发跟本地提醒走同一套触发规则(「当前对话不弹通知」等开关同样管它);提醒正文会原样发往你填的地址,**只填你自己信任的端点**;
59
- - **页面打开时也提醒「需要你」**(默认开)与 **页面打开时也提醒「回复完成」**(默认关);
60
- - **当前对话不弹通知**(默认开):等待就发生在你正看着的对话里时只留标题标记,不弹通知也不响音(免得盖住审批卡片);页面切到后台立刻补发,若你已经处理掉就作废。其它后台会话不受影响;
61
- - **子代理会话不提醒**(默认开):后台子代理(subagent)子会话的「需要你」与「回复完成」都不提醒——它们是主对话那一轮的步骤,完成由主对话自己的提醒覆盖;你当前打开的那个子代理会话照常提醒;关掉后恢复逐会话提醒;
62
- - **点击通知回到对应对话**(默认开):点通知把 DSH 带到前台并切到提醒所属的对话;多个 DSH 标签页同时开着时,一次点击只调起一个窗口(优先当前可见的那个)并只切它的对话,其余标签页不动;关掉后点通知不做任何事。桌面端(DSH Desktop)同样会把窗口带到前台并切对话:页面侧的 `window.focus()` 在 Electron 里抬不动原生窗口,1.5.2 起改走应用自己的 `dsh://open` 深链调窗(窗口隐藏在托盘里也能被抬回来);
63
- - **审批通知上直接裁决**(默认开):权限审批的通知上带「同意 / 拒绝」按钮,点一下就按审批卡片的「允许一次 / 拒绝」直接裁决,不用切回页面;点通知正文仍是原来的「切回对应对话」。**桌面端暂不支持按钮**(`dsh-app://` 页面无法注册 Service Worker),审批通知自动退回无按钮样式,设置页会明示这一限制;
176
+
177
+ </details>
178
+
179
+ ### 运行环境与诊断
180
+
181
+ 在「高级设置」最后一块。默认自动识别当前是 Web 端还是桌面端(DSH Desktop,`dsh-app://`);识别不准时可手动指定——桌面端点通知走 `dsh://` 深链抬窗、通知上不带快捷裁决按钮;Web 端走 `window.focus()` 与 Service Worker 桥。手动覆盖与自动识别不一致时,设置页会明示检测结果。
182
+
183
+ <details>
184
+ <summary>通知语言、桌面端抬窗与恢复默认</summary>
185
+
64
186
  - **通知语言**:跟随界面 / 简体中文 / English——决定通知文字与 `🔔 …` 标题标记使用的语言;
65
- - **测试按钮**:用当前设置立即发一条「需要你」「回复完成」或「审批按钮」测试提醒(**不受**上面「页面打开时也提醒」开关限制;「需要你」测试的标题标记约 6 秒后自动消失);
66
- - **版本信息**:设置页底部常显当前插件版本号(`dsh-notify-me v…`)——报障、核对是否装上新版本时直接照抄这一行。
187
+ - **桌面端怎么抬窗**:页面侧的 `window.focus()` 在 Electron 里抬不动原生窗口,1.5.2 起改走应用自己的 `dsh://open` 深链调窗(窗口隐藏在托盘里也能被抬回来);
188
+ - **恢复默认设置**:把所有开关与音效设置还原成出厂值(不动外部推送目标和已选的自定义音频文件)。
189
+
190
+ </details>
191
+
192
+ > 左侧导航行的图标由 DSH 设置外壳统一渲染:外壳按分区 id 硬编码(只认 account / models / agent-presets / plugins / archived-sessions),其他分区一律给默认齿轮,`settings.section` 也没有图标字段——插件的铃铛标志只能出现在自己的页面里,换不了导航行。
67
193
 
68
194
  > 需要浏览器通知权限:页面上点一下 → 允许;或地址栏锁 → 站点设置 → 通知 → 允许 → 刷新。macOS 还要在 系统设置 → 通知 里允许该浏览器。
69
195
 
70
- ## 提醒方式
196
+ ## 五种提醒渠道
71
197
 
72
- - **系统通知**:经浏览器弹出的系统通知,进 Windows 通知中心或 macOS 通知中心(点击回到提醒所属的对话;审批的通知点按钮直接裁决)
198
+ - **系统通知**:经浏览器弹出的系统通知,进 Windows 通知中心或 macOS 通知中心(点击回到提醒所属的对话;支持快捷裁决的 Web 环境可点审批按钮直接裁决,桌面端无按钮)
199
+ - **页面浮层**(可选,默认关):画在 DSH 页面角落的提醒卡片,落在窗口所在的那块屏,可带「同意 / 拒绝」按钮;见[副屏与浮层提醒](#副屏与浮层提醒)
73
200
  - **提示音**:默认是 WebAudio 合成音(「需要你」与「完成」使用不同音型);可在设置里为两类提醒分别换成自定义音频文件,或改成让操作系统播放它自己的通知音
74
201
  - **标签页标题标记**:有待处理事项时,标题前出现 `🔔 需要你 · …` / `🔔 Action needed · …`;后台会话**完成但还没看**时出现 `✅ 回复完成 · …` / `✅ Reply finished · …`,打开对应会话(或它再次开跑)即消失。两种标记可同时出现,「需要你」在前;宿主改写标题后标记基于新标题重建
75
202
  - **外部通知**(可选,默认关):按设置里配的推送目标,把同一条提醒转发到 Discord Webhook / Bark / Gotify / 自定义 Webhook——临时离开电脑时,手机上的推送渠道照样收到
76
203
 
77
204
  本插件是**浏览器层**实现:DSH 页面需保持打开(最小化/后台即可——那正是它监听的「离开」状态)。
78
205
 
79
- ## 安装
206
+ ## 兼容性
80
207
 
81
- ```powershell
82
- # DSH 官方插件命令:安装并自动挂载进 web profile
83
- dsh plugin --profile web add dsh-notify-me
84
- ```
208
+ 逐版本适配记录见 [package.json](package.json) 的 `dsh.compatibility.dshReleases`。当前宿主(`0.2.1-rc.2`)的安装门控只读 `peerDependencies` 与 `engines`,**不再读取这个字段**,所以它现在只是一份给人看的记录,不构成门禁。
85
209
 
86
- 重启 `dsh web` 后硬刷新页面(Ctrl+Shift+R)。
210
+ 实测**真正激活**(各自独立 profile 启动:插件条目进启动页 `__DSH_BOOT__` 且注入依赖解析通过、`/plugins/??dsh-notify-me/client.js&rev=…` 返回含新代码的构建,设置里出现「通知提醒」分区,即插件的 `apply` 确实执行)于 `0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2` 与 `0.2.0-rc.2`;更早的 `0.1.1-rc.2` 亦验证过。
87
211
 
88
- **兼容性** — 插件按宿主代际自动选源,逐版本声明见 `package.json` 的 `dsh.compatibility.dshReleases`:
212
+ `0.2.1-rc.2`(当前 latest)另跑了一轮隔离验证:隔离 `DSH_HOME` 起 `dsh web`(70 个启动条目),插件条目排在第 59、`application` 批,三个注入目标都在且都排在它前面;`/plugins/??dsh-notify-me/client.js&rev=…` 返回 1.7.0 源码构建(140,153 B);无头 Chromium 载入页面后 `apply` 正常执行,`window.__dshNotifyMe.debug()` 报 `uiSession: bound`、`uiSessionSource: sessionStatus`、`bridge: active`。宿主侧的形状与 `0.2.0-rc.2` 一致,没有需要改代码的地方。
213
+
214
+ <details>
215
+ <summary>宿主代际与适配排查细节</summary>
216
+
217
+ 插件按宿主代际自动选源;下表是各形状的边界,不是门禁:
89
218
 
90
219
  | 宿主代际 | 「需要你」交互来源 | 判断当前会话 | 点通知切会话 |
91
220
  | --- | --- | --- | --- |
92
221
  | `≤ 0.1.2-alpha.1` | 控制器快照的 `pending[]` | 快照 `current` | `sessions.open()` |
93
222
  | `0.1.2-alpha.2 .. 0.1.6-alpha.1` | `uiSession.pendingInteractions` | 快照 `current` | `sessions.open()` |
94
- | `≥ 0.1.6-alpha.2`(含 `0.2.0-rc.2`) | `uiSession.sessionStatus` | `retainedBy.mainView` | `uiWorkspace.openSession()` |
223
+ | `≥ 0.1.6-alpha.2`(含 `0.2.0-rc.2`、`0.2.1-rc.2`) | `uiSession.sessionStatus` | `retainedBy.mainView` | `uiWorkspace.openSession()` |
95
224
 
96
- 区间仅作示意:插件按 store 形状自动选源(`sessionStatus` 存在即走新路),版本号只是各形状的出现边界。`package.json` 的 `peerDependencies` 范围同理只影响 npm install 的提示文案——兼容与否以 `dshReleases` 的逐版实测声明为准,未实测的新版本由形状驱动兜底。
225
+ 区间仅作示意:插件按 store 形状自动选源(`sessionStatus` 存在即走新路),版本号只是各形状的出现边界。`package.json` 的 `peerDependencies` 范围决定 npm 的 peer 提示——`0.2.1-rc.2` 已落在 `>=0.2.0-rc.1 <0.3.0-0` 里,不需要豁免;`dshReleases` 只是存档,真实兼容性以逐版实测为准,未实测的新版本由形状驱动兜底。
97
226
 
98
- 实测**真正激活**(各自独立 profile 启动:设置里出现「通知提醒」分区,即插件的 `apply` 确实执行)于 `0.1.2-rc.1`、`0.1.5-rc.2` 与 `0.2.0-rc.2`;更早的 `0.1.1-rc.2` 亦验证过。两个坑值得记住:一是 `dsh.client.inject` 里列了新版运行时已不再提供的包,客户端条目会停在 `pending (waiting for services: …)` 而永不执行——1.1.3 在 `0.1.2-rc.1` 及以后正是这样失效的;二是宿主换存储/字段名时**不会报错**,提醒只会静默失效——`0.2.0-rc.2` 上 `pendingInteractions`→`sessionStatus`、`list.current`→`retainedBy.mainView`、`sessions.open()`→`uiWorkspace.openSession()` 都是这一类,所以每次适配都要用 `window.__dshNotifyMe.debug()` 确认真的是 `bound`、以及用的是哪个来源。
227
+ 两个坑值得记住:一是 `dsh.client.inject` 里列了新版运行时已不再提供的包,客户端条目会停在 `pending (waiting for services: …)` 而永不执行——1.1.3 在 `0.1.2-rc.1` 及以后正是这样失效的;二是宿主换存储/字段名时**不会报错**,提醒只会静默失效——`0.2.0-rc.2` 上 `pendingInteractions`→`sessionStatus`、`list.current`→`retainedBy.mainView`、`sessions.open()`→`uiWorkspace.openSession()` 都是这一类,所以每次适配都要用 `window.__dshNotifyMe.debug()` 确认真的是 `bound`、以及用的是哪个来源。`0.2.1-rc.2` 这两处都没有再变:`sessionStatus` 仍是 `{running, pendingInteraction, completionUnread}` 的 Map,`uiWorkspace.openSession(id)` 照旧,会话列表里仍然没有 `current`。
99
228
 
100
- **验证** — F12 控制台执行:
229
+ </details>
101
230
 
102
- ```js
103
- window.__dshNotifyMe.test("done") // 「完成」示例
104
- window.__dshNotifyMe.test("attention") // 「需要你」示例
105
- window.__dshNotifyMe.test("approval") // 「审批按钮」示例:通知上有「同意 / 拒绝」,点着试试
106
- window.__dshNotifyMe.debug() // 桥接状态看 bridge 字段,active = 按钮可用
107
- ```
108
-
109
- 没反应?九成是:通知权限被拒绝(在页面上点一下 → 选「允许」;或地址栏锁 → 站点设置 → 通知 → 允许 → 刷新)、装完没重启 DSH、系统设置里浏览器通知被关。
231
+ `1.9.0` 的界面重排没有放宽也没有收紧这个范围:设置页是纯 React 渲染 + 既有 CSS 变量(每个色值都带 fallback),没有引入任何新的宿主 API;浮层、标题标记、抬窗仍走 1.7 / 1.8 那几条路径。**0.1.1-rc.2 到 0.2.1-rc.2 的插件条目照旧兼容**,换回旧宿主也不需要改配置。新增的只有界面元素——设置页页眉的铃铛是插件自己画的 SVG(`docs/brand/`),与宿主无关。
110
232
 
111
233
  ## 控制台高级配置
112
234
 
113
235
  设置页是第一入口;想脚本化/批量改或恢复默认时,偏好存 `localStorage`(`dshNotifyMe.config`),可用控制台实时调整:
114
236
 
237
+ <details>
238
+ <summary>展开控制台 API 与存储说明</summary>
239
+
115
240
  ```js
116
241
  window.__dshNotifyMe.config // 查看
117
242
  window.__dshNotifyMe.setConfig({
@@ -128,6 +253,8 @@ window.__dshNotifyMe.setConfig({
128
253
  volume: 0.5, // 音量 0~1
129
254
  autoFocus: true, // 点通知回到提醒所属的对话
130
255
  quickActions: true, // 审批通知上的「同意 / 拒绝」按钮
256
+ overlay: false, // 页面浮层提醒(跟着 DSH 窗口落在哪块屏;不需要通知权限)
257
+ overlayCorner: "bottom-right", // 浮层位置:'top-right' | 'bottom-right' | 'top-left' | 'bottom-left'
131
258
  externalEnabled: false, // 外部通知转发主开关(默认关:不填端点就什么都不发)
132
259
  externalAttention: true, // 转发「需要你」(触发规则跟本地提醒完全一致)
133
260
  externalDone: true, // 转发「回复完成」
@@ -135,15 +262,24 @@ window.__dshNotifyMe.setConfig({
135
262
  })
136
263
  window.__dshNotifyMe.resetConfig() // 恢复默认(同时清掉已选的自定义音效文件)
137
264
  window.__dshNotifyMe.decide("approval:3", "allowed-once") // 程序化裁决:"allowed-once" | "rejected"
138
- window.__dshNotifyMe.testExternal() // 向所有推送目标发一条测试通知,返回 {sent, unverified, failed, statuses}
265
+ window.__dshNotifyMe.testExternal() // 显式外发测试:向有效目标发送,返回 {sent, unverified, failed, statuses}
139
266
  ```
140
267
 
268
+ > **外部通知测试的开关边界**:设置页「发送测试通知」要求「启用提醒」与「外部通知」主开关开启,但忽略两类提醒的转发开关。控制台 `testExternal()` 是显式测试调用:只要配置了有效目标,即使上述主开关关闭,也会向这些目标发送测试消息;没有有效目标则不发送。普通的 `test("done")` / `test("attention")` / `test("approval")` 只测试本地提醒,不外发。
269
+
141
270
  > 自定义音效文件不在 `dshNotifyMe.config` 里,而是按类别各存一个键(`dshNotifyMe.sound.done` / `dshNotifyMe.sound.attention`,内容是 `{name, size, data}` 的 data URL)——一个文件转成 data URL 会膨胀约 1.37 倍,塞进配置会拖慢每次读取。`resetConfig()` 会连这两个键一起清掉。
142
271
  >
143
272
  > 想确认当前生效的来源,看 `window.__dshNotifyMe.debug()` 的 `soundDone` / `soundAttention` 与 `customSoundDone` / `customSoundAttention`。
144
273
 
274
+ </details>
275
+
145
276
  ## 工作原理
146
277
 
278
+ 提醒核心监听会话状态与待处理交互;审批裁决由页面侧完成,桌面抬窗使用应用深链。
279
+
280
+ <details>
281
+ <summary>展开事件来源、审批桥接与桌面抬窗实现</summary>
282
+
147
283
  提醒核心按宿主代际取源(见上表),当前会话一律来自客户端 `sessions` 服务:
148
284
 
149
285
  - **当前会话** `SessionSnapshot`:`running` true→false = 回复完成;
@@ -165,26 +301,31 @@ DSH Desktop 是一层 Electron 壳,页面跑在 `dsh-app://app` 下:DOM 的
165
301
 
166
302
  真实壳已实测(DSH Desktop 0.2.0-rc.2,issue #9 三轮复测):点通知 = 抬窗 + 切会话一步到位,跨会话、窗口在后台时同样稳定。触发时机是这条链路的关键:深链必须在**带用户手势的处理器**里发——通知的 `onclick` 自带手势,所以产品路径通;而无手势的脚本化注入(如 CDP evaluate 手工塞 iframe)会被 Chromium 静默丢弃、外部协议根本不回流,复现时看起来就像「通道被拦死」。
167
303
 
304
+ </details>
305
+
168
306
  ## 已知限制
169
307
 
170
308
  - 页面必须开着才会提醒(后台标签/最小化可以;关标签页即失效——浏览器层方案固有限制)。
171
309
  - 通知经由浏览器弹出,需允许浏览器通知权限,且勿扰模式不能屏蔽它。
310
+ - 系统通知横幅只画在主屏:Windows 没有设置项、Chromium 没有 API 能把它指到别的显示器(多屏时副屏收不到系统通知)。要用副屏提醒,开「页面浮层提醒」,它会跟着 DSH 窗口走。
172
311
  - 每次页面加载后第一次出声/弹通知前,需在页面上点击过一次(浏览器自动播放与权限策略)。
173
312
  - 未授权通知权限时只有提示音与标题标记。
174
313
  - 快捷裁决按钮要 Service Worker:`http://127.0.0.1`、`https` 可用,`http://192.168.x.x` 这类局域网地址不行;**桌面端(`dsh-app://`)已实测无法注册 Service Worker**,按钮渲染不了,审批通知退回无按钮样式。浏览器或桌面宿主不渲染通知按钮时,`window.__dshNotifyMe.debug()` 的 `bridge` 字段会说明原因,其余功能不受影响。
175
314
  - macOS:浏览器里提醒、提示音、标题标记、点通知跳转都没有平台假设,照常工作;但 DSH Desktop(Electron)的系统通知要求应用已签名,未签名的通知直接发不出去,官方 macOS 版是否满足这一前提未实测;审批按钮在 macOS 桌面宿主上的渲染同样未实测(Windows 桌面端已实测不渲染,见上条),不渲染时自动退回无按钮通知。
176
315
  - 配置存在浏览器 `localStorage`:换浏览器/设备或清除站点数据后会回到默认值(设置页可一键恢复默认)。
177
- - `≥ 0.1.6`(含 `0.2.0-rc.2`)的「回复完成」提醒正文只有会话名,不再附带回复摘要——宿主快照已不再提供 `nodes`;提醒本身照常触发。
316
+ - `≥ 0.1.6`(含 `0.2.0-rc.2`、`0.2.1-rc.2`)的「回复完成」提醒正文只有会话名,不再附带回复摘要——宿主快照已不再提供 `nodes`;提醒本身照常触发。
178
317
  - 标题标记由宿主与插件共同写 `document.title`:宿主重算标题时标记可能被覆盖,直到下一次提醒事件重新写成。
179
318
  - 「当前对话不弹通知」按 `document.hidden` 判定:窗口被别的应用完全盖住时仍算「页面可见」,此时当前对话的等待照样静默。
180
319
  - 外部通知转发受浏览器跨域(CORS)限制:端点不放行时自动降级为「送出但不可确认」(no-cors),如实标为「已送出不可确认」;Discord Webhook 官方放行跨域,可直接确认送达。HTTP 错误如实记失败、不重试。转发在本地提醒决定要发之后才触发,所以被「当前对话不弹通知」等规则静音的提醒也不会外发。
181
320
 
321
+ - **设置左侧导航行是宿主的默认齿轮图标**:设置外壳按分区 id 硬编码图标,其它分区一律给默认齿轮,`settings.section` 没有图标字段,插件改不了;插件自己的铃铛标志只出现在设置页页眉与 README。
322
+
182
323
  ## 开发自检
183
324
 
184
325
  ```powershell
185
326
  node --check lib\client.js
186
327
  node --check lib\index.js
187
- node smoke\smoke-test.cjs # 离线状态机冒烟测试:三代宿主 + 主开关 + 中英语言用例 + 快捷裁决桥(Service Worker 半侧一并跑)
328
+ node smoke\smoke-test.cjs # 离线状态机冒烟测试:三代宿主 + 主开关 + 中英语言用例 + 快捷裁决桥(Service Worker 半侧一并跑)+ 页面浮层
188
329
  node smoke\cordis-host-test.mjs # 真 cordis 端到端(找不到本机 DSH 时自动跳过)
189
330
  npm pack --dry-run # 预览发布包
190
331
  ```