dsh-plugin-notify-sounds 1.8.6 → 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 +209 -205
- package/README.zh.md +208 -204
- package/lib/client.js +3285 -2794
- package/lib/index.js +275 -6
- package/package.json +1 -1
package/README.zh.md
CHANGED
|
@@ -1,206 +1,210 @@
|
|
|
1
|
-
# dsh-plugin-notify-sounds
|
|
2
|
-
|
|
3
|
-
[](https://awesome-dsh-plugin.com)
|
|
4
|
-
[](https://dsh-plugin.org/plugins/billcx330/dsh-plugin-notify-sounds)
|
|
5
|
-
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
6
|
-
[](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
|
|
7
|
-
[](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
|
|
10
|
-
[English](README.md) | 中文
|
|
11
|
-
|
|
12
|
-
**智能体在等你、或干完活时,轻轻响一声。**
|
|
13
|
-
|
|
14
|
-
人不在窗口前也不怕:后台弹系统通知(**点击即回到窗口**),任务栏标题亮出「待处理 / 已完成」;你回来看过一眼之后,它就闭嘴——不会像闹钟一样反复催你。
|
|
15
|
-
|
|
16
|
-
**安装**:DSH → 左侧栏「插件」→ 添加插件,粘贴下面这行(**带上版本号**,否则发布不满 24 小时的版本会被 pnpm 的 `minimumReleaseAge` 解析回上一版),点「安装」:
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
dsh-plugin-notify-sounds@1.
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 🎨 与 DSH 界面风格统一
|
|
25
|
-
|
|
26
|
-
设置面板中的每一处视觉细节都取自 DSH 自身的设计体系:行几何、分隔线、字号与间距沿用官方设计令牌,音效选择器使用官方 `Menu` 组件,图标来自官方图标族,排布沿用「文字左 / 控件右」的原生行式。安装后不会在设置中出现风格割裂的第三方区块。
|
|
27
|
-
|
|
28
|
-
## ✨ 它能做什么
|
|
29
|
-
|
|
30
|
-
| 提醒什么 | 效果 |
|
|
31
|
-
|---|---|
|
|
32
|
-
| **需要你决策** | 智能体发起审批、计划确认、提问时提示音;审批与提问可分别设音效 |
|
|
33
|
-
| **任务完成** | 会话由运行转为空闲时提示音 |
|
|
34
|
-
| **人不在窗口前也能感知** | 后台弹系统通知(正文就是审批理由或提问原文,点击回到窗口);任务栏标题显示「待处理 / 已完成」 |
|
|
35
|
-
| **没看到会再提醒** | 未处理决策按 1/5/15/30 分钟重复提醒 |
|
|
36
|
-
| **只提醒你关心的** | 子智能体(后台任务)默认完全静默,只提醒主对话,可开关 |
|
|
37
|
-
| **该安静时安静** | 静音时段(如 22:00–08:00,可跨午夜)、仅页面不可见时提示、总开关一键全静音 |
|
|
38
|
-
| **声音随你** |
|
|
39
|
-
| **检测更新** | 设置里检查 npm 新版本,并指向真正负责安装的入口——**左侧栏「插件」**(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`;若当前安装未被 lockfile 记录,会在行内提示 |
|
|
40
|
-
|
|
41
|
-
## 💡 为什么需要它
|
|
42
|
-
|
|
43
|
-
DSH 的状态提示只有视觉——状态点、侧栏标记。你一切到别的窗口,就既看不到也听不到,智能体却可能正卡在那里等你一句话。
|
|
44
|
-
|
|
45
|
-
这个插件把「在等你」和「干完了」变成声音。配合系统通知与标题标记,人走开也知道发生了什么;而你回来处理过之后它就安静——重复提醒也只针对你**从没看过**的决策。
|
|
46
|
-
|
|
47
|
-
## 🔔 声音
|
|
48
|
-
|
|
49
|
-
双音铃 · 风铃 · 单音叮 · 水滴 · 脉冲 · 上行琶音 · 金币 · 达成 · 敲门 —— 九种内置音效全部由 Web Audio 现场合成,不含任何音频文件、不发一次网络请求。
|
|
50
|
-
|
|
51
|
-
也可以换上你自己的铃声(mp3/wav/ogg,≤512KB,自动校验并做音量归一化),或者干脆选「无声」只留通知。三种触发(审批 / 提问 / 完成)各选各的音效,设置里随时试听。
|
|
52
|
-
|
|
53
|
-
## ⚙️ 设置
|
|
54
|
-
|
|
55
|
-
设置 → **提示音**(位于「通用设置」与「模型」之间),每项功能都有独立开关,界面与 DSH 原生设置完全一致:
|
|
56
|
-
|
|
57
|
-
总开关与音量 · 三种触发各自的音效(含试听)· 子智能体提醒 · 系统通知 · 窗口标题提醒 · 重复提醒间隔 · 静音时段 · 仅后台提示 ·
|
|
58
|
-
|
|
59
|
-
改动即时生效,无需重启。
|
|
60
|
-
|
|
61
|
-
## 📦 安装
|
|
62
|
-
|
|
63
|
-
### 🖱️ 最简单:在 DSH 里点两下(推荐)
|
|
64
|
-
|
|
65
|
-
1. 打开 DSH → **左侧栏「插件」**,点**添加插件**;
|
|
66
|
-
2. 在输入框粘贴包名**和版本号**(本插件已发布在 [npm](https://www.npmjs.com/package/dsh-plugin-notify-sounds)):
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
dsh-plugin-notify-sounds@1.
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
版本号不要省:pnpm 的 `minimumReleaseAge` 策略会把刚发布不到 24 小时的版本挡在外面,只写包名会解析回上一个版本。想看最新版本号可到 [npm](https://www.npmjs.com/package/dsh-plugin-notify-sounds?activeTab=versions) 或 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 查。
|
|
73
|
-
(填 GitHub 仓库地址 `https://github.com/BillCx330/dsh-plugin-notify-sounds` 或本地目录路径也可以,但那样不带版本锁定)
|
|
74
|
-
3. 点**安装**,装完**重启 DSH** 一次。
|
|
75
|
-
|
|
76
|
-
输入框上方的「安装源」是下载源,默认中国大陆镜像源,国内一般不用改。DSH 会提示「插件以你的权限运行」——本插件只读会话状态、在本地发声;唯一的请求是点击系统通知时发给**本机 DSH** 的唤窗请求,不向外部发送任何数据。
|
|
77
|
-
|
|
78
|
-
### ⬆️ 升级
|
|
79
|
-
|
|
80
|
-
**升级由包管理器安装**,这样 profile 的 lockfile 会跟着一起更新——DSH 插件无法自己持久地更新自己(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码)。所以插件只负责**检查**,并告诉你从哪里装:
|
|
81
|
-
|
|
1
|
+
# dsh-plugin-notify-sounds
|
|
2
|
+
|
|
3
|
+
[](https://awesome-dsh-plugin.com)
|
|
4
|
+
[](https://dsh-plugin.org/plugins/billcx330/dsh-plugin-notify-sounds)
|
|
5
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
6
|
+
[](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
|
|
7
|
+
[](https://www.npmjs.com/package/dsh-plugin-notify-sounds)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
|
|
10
|
+
[English](README.md) | 中文
|
|
11
|
+
|
|
12
|
+
**智能体在等你、或干完活时,轻轻响一声。**
|
|
13
|
+
|
|
14
|
+
人不在窗口前也不怕:后台弹系统通知(**点击即回到窗口**),任务栏标题亮出「待处理 / 已完成」;你回来看过一眼之后,它就闭嘴——不会像闹钟一样反复催你。
|
|
15
|
+
|
|
16
|
+
**安装**:DSH → 左侧栏「插件」→ 添加插件,粘贴下面这行(**带上版本号**,否则发布不满 24 小时的版本会被 pnpm 的 `minimumReleaseAge` 解析回上一版),点「安装」:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
dsh-plugin-notify-sounds@1.9.0
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🎨 与 DSH 界面风格统一
|
|
25
|
+
|
|
26
|
+
设置面板中的每一处视觉细节都取自 DSH 自身的设计体系:行几何、分隔线、字号与间距沿用官方设计令牌,音效选择器使用官方 `Menu` 组件,图标来自官方图标族,排布沿用「文字左 / 控件右」的原生行式。安装后不会在设置中出现风格割裂的第三方区块。
|
|
27
|
+
|
|
28
|
+
## ✨ 它能做什么
|
|
29
|
+
|
|
30
|
+
| 提醒什么 | 效果 |
|
|
31
|
+
|---|---|
|
|
32
|
+
| **需要你决策** | 智能体发起审批、计划确认、提问时提示音;审批与提问可分别设音效 |
|
|
33
|
+
| **任务完成** | 会话由运行转为空闲时提示音 |
|
|
34
|
+
| **人不在窗口前也能感知** | 后台弹系统通知(正文就是审批理由或提问原文,点击回到窗口);任务栏标题显示「待处理 / 已完成」 |
|
|
35
|
+
| **没看到会再提醒** | 未处理决策按 1/5/15/30 分钟重复提醒 |
|
|
36
|
+
| **只提醒你关心的** | 子智能体(后台任务)默认完全静默,只提醒主对话,可开关 |
|
|
37
|
+
| **该安静时安静** | 静音时段(如 22:00–08:00,可跨午夜)、仅页面不可见时提示、总开关一键全静音 |
|
|
38
|
+
| **声音随你** | 九种内置音效;**最多 3 个自己的音频**,可以改名、指派给任意提醒(mp3 / wav / ogg / m4a,每个 ≤15 秒);音量调节;每项独立开关 |
|
|
39
|
+
| **检测更新** | 设置里检查 npm 新版本,并指向真正负责安装的入口——**左侧栏「插件」**(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`;若当前安装未被 lockfile 记录,会在行内提示 |
|
|
40
|
+
|
|
41
|
+
## 💡 为什么需要它
|
|
42
|
+
|
|
43
|
+
DSH 的状态提示只有视觉——状态点、侧栏标记。你一切到别的窗口,就既看不到也听不到,智能体却可能正卡在那里等你一句话。
|
|
44
|
+
|
|
45
|
+
这个插件把「在等你」和「干完了」变成声音。配合系统通知与标题标记,人走开也知道发生了什么;而你回来处理过之后它就安静——重复提醒也只针对你**从没看过**的决策。
|
|
46
|
+
|
|
47
|
+
## 🔔 声音
|
|
48
|
+
|
|
49
|
+
双音铃 · 风铃 · 单音叮 · 水滴 · 脉冲 · 上行琶音 · 金币 · 达成 · 敲门 —— 九种内置音效全部由 Web Audio 现场合成,不含任何音频文件、不发一次网络请求。
|
|
50
|
+
|
|
51
|
+
也可以换上你自己的铃声(mp3/wav/ogg,≤512KB,自动校验并做音量归一化),或者干脆选「无声」只留通知。三种触发(审批 / 提问 / 完成)各选各的音效,设置里随时试听。
|
|
52
|
+
|
|
53
|
+
## ⚙️ 设置
|
|
54
|
+
|
|
55
|
+
设置 → **提示音**(位于「通用设置」与「模型」之间),每项功能都有独立开关,界面与 DSH 原生设置完全一致:
|
|
56
|
+
|
|
57
|
+
总开关与音量 · 三种触发各自的音效(含试听)· 子智能体提醒 · 系统通知 · 窗口标题提醒 · 重复提醒间隔 · 静音时段 · 仅后台提示 · 最多 3 个可改名的自定义音频 · 自动检查更新(安装走包管理器)
|
|
58
|
+
|
|
59
|
+
改动即时生效,无需重启。
|
|
60
|
+
|
|
61
|
+
## 📦 安装
|
|
62
|
+
|
|
63
|
+
### 🖱️ 最简单:在 DSH 里点两下(推荐)
|
|
64
|
+
|
|
65
|
+
1. 打开 DSH → **左侧栏「插件」**,点**添加插件**;
|
|
66
|
+
2. 在输入框粘贴包名**和版本号**(本插件已发布在 [npm](https://www.npmjs.com/package/dsh-plugin-notify-sounds)):
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
dsh-plugin-notify-sounds@1.9.0
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
版本号不要省:pnpm 的 `minimumReleaseAge` 策略会把刚发布不到 24 小时的版本挡在外面,只写包名会解析回上一个版本。想看最新版本号可到 [npm](https://www.npmjs.com/package/dsh-plugin-notify-sounds?activeTab=versions) 或 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 查。
|
|
73
|
+
(填 GitHub 仓库地址 `https://github.com/BillCx330/dsh-plugin-notify-sounds` 或本地目录路径也可以,但那样不带版本锁定)
|
|
74
|
+
3. 点**安装**,装完**重启 DSH** 一次。
|
|
75
|
+
|
|
76
|
+
输入框上方的「安装源」是下载源,默认中国大陆镜像源,国内一般不用改。DSH 会提示「插件以你的权限运行」——本插件只读会话状态、在本地发声;唯一的请求是点击系统通知时发给**本机 DSH** 的唤窗请求,不向外部发送任何数据。
|
|
77
|
+
|
|
78
|
+
### ⬆️ 升级
|
|
79
|
+
|
|
80
|
+
**升级由包管理器安装**,这样 profile 的 lockfile 会跟着一起更新——DSH 插件无法自己持久地更新自己(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码)。所以插件只负责**检查**,并告诉你从哪里装:
|
|
81
|
+
|
|
82
82
|
- **在 DSH 里(推荐,也是唯一实测过的路径)**:**左侧栏「插件」** → 在「已安装插件」里卸载本插件 → **添加插件** → 粘贴 `dsh-plugin-notify-sounds@<版本>` → 安装 → 重启 DSH。(务必带版本号:pnpm 的 `minimumReleaseAge` 会让刚发布不到 24 小时的版本不参与自动解析,只写包名会装回上一个版本。)
|
|
83
|
-
- **装了市场插件**([dshmarket](https://www.npmjs.com/package/dshmarket)):在市场里一键更新。
|
|
84
|
-
- **`web` profile**:`dsh plugin --profile <你的 profile> add dsh-plugin-notify-sounds@<版本>`。
|
|
85
|
-
|
|
86
|
-
更新行还会提示「当前版本与 lockfile 记录不一致」——那是 1.8.0 之前的自更新留下的状态,按上面方式重装一次即可永久修好。
|
|
87
|
-
|
|
88
|
-
### 🛠️ 其他安装方式
|
|
89
|
-
|
|
90
|
-
**命令行** —— 对你实际使用的 profile 一条命令:
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
dsh plugin --profile <你的 profile> add github:BillCx330/dsh-plugin-notify-sounds
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
(Git 安装跟仓库默认分支走,不带版本锁定;要可复现的安装请用上面的 `包名@版本号`。)
|
|
97
|
-
|
|
98
|
-
**Release 压缩包** —— 从 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 下载 `.tgz`,用它**在磁盘上的路径**安装:
|
|
99
|
-
|
|
100
|
-
```sh
|
|
101
|
-
dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds-1.8.6.tgz
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
(`dsh plugin add` 把参数原样交给包管理器,所以要给本地文件路径,不能填下载地址。)
|
|
105
|
-
|
|
106
|
-
**本地目录** —— 开发或试用未发布的改动:
|
|
107
|
-
|
|
108
|
-
```sh
|
|
109
|
-
dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**手工编辑** —— 在 profile 的 `package.json` 的 `dependencies` 加 `"dsh-plugin-notify-sounds": "github:BillCx330/dsh-plugin-notify-sounds"`,在 `dsh.profile.bundles` 追加 `"dsh-plugin-notify-sounds"`,然后在 profile 目录跑一次包安装(如 `pnpm install`)把依赖装进 `node_modules`。
|
|
113
|
-
|
|
114
|
-
命令行方式会自动写入 `dsh.profile.bundles` 并装好依赖,无需手工编辑。包内直接带预构建产物、不声明任何生命周期脚本,安装过程不执行构建脚本。安装后**重启 DSH**(日常升级仅客户端改动时,可热更生效)。
|
|
115
|
-
|
|
116
|
-
## ⚠️ 已知边界
|
|
117
|
-
|
|
118
|
-
- **手改配置**:偏好写在 profile 的 `cordis.patch.yml`,值必须符合 schema(音量 0–100、音效为预设之一、时间 `HH:MM`);写错会让插件不加载,改回即可。设置界面只会写入合法值。
|
|
119
|
-
- **升级由包管理器安装,不再由插件自己完成**:1.8.0 移除了自安装器(原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装会静默把旧版本装回来)。更新行仍会检查 npm、报告新版,然后指向真正负责安装的入口——**左侧栏「插件」**(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。
|
|
120
|
-
- **1.7.0 及更早版本**可以通过它们自带的自更新到达 1.8.0(1.8.0 保持同样的七个文件名),但这次到达不会被 pnpm 登记:按上面的方式用包管理器重装一次,此后所有升级都会留下。1.6.9 及更早无法安装「新增了文件」的版本——固定白名单会安全拒绝;同样的一次性重装即可解决。
|
|
121
|
-
- **多窗口**:提示音、系统通知和重复提醒由同一个 GUI 的所有页面选出一个「发声页」来发(1.7.0 起),所以同一个事件只响一次;窗口标题标记仍是每个窗口各自一份,因为它们各自有标题。发声页关闭或崩溃后几秒内由其他页面接管。
|
|
122
|
-
- **点击通知回到窗口**:Windows 完整实现并实测;macOS / Linux 走系统深链,未验证。
|
|
123
|
-
- **唤窗按窗口标题定位主窗口**:刻意不读取其他进程信息(那会触发杀软主动防御)。若将来 DSH 改变标题格式,唤窗会静默失效——提示音与通知本身不受影响。
|
|
124
|
-
- **导航小图标**:依赖设置面板的 DOM 结构,若DSH 改版后自动回落为官方齿轮,仅影响外观。
|
|
125
|
-
- **通知权限**:桌面端放行;受限环境(某些浏览器策略)下被拒时,行内会引导手动允许,其余功能不受影响。
|
|
126
|
-
- **macOS 的系统通知**:桌面外壳对权限请求一律放行,所以设置里恒显示「已授权」;**实际是否弹横幅由 macOS 决定**(系统设置 → 通知 → DeepSeek Harness),未签名的开发版可能静默失败——「显示已授权却没通知」多半不是插件的问题。
|
|
127
|
-
|
|
128
|
-
## 🧩 设计与实现
|
|
129
|
-
|
|
130
|
-
给想改代码的人看的要点(实现细节以源码注释为准):
|
|
131
|
-
|
|
132
|
-
- **触发不碰事件瀑布**:审批/提问的请求是 waterfall 事件,UI 应答后晚注册的监听器收不到。本插件改读 `uiSession.sessionStatus`(DSH 自己聚合的 pending/running 事实,与侧栏状态点同源),纯观察、零侵入。
|
|
133
|
-
- **重复提醒的节拍**:15 秒粒度检查未处理决策;**看过即除名**(决策出现时你正在窗口、或之后回到窗口,都算看过),切走不重新武装;新问题替换旧问题会重置计时。免打扰期间的提醒直接作废,不会顺延到时段结束补发。
|
|
134
|
-
- **通知点击回到窗口**:渲染进程唤不起 OS 窗口,点击时 POST 到宿主半边的 `/notify-sounds/focus`(带 connection 围栏),由宿主唤起。Windows 用 DSH 自带的 `koffi` 直接调 `user32.dll`(不引新依赖、只操作窗口、不启动 PowerShell——那会触发杀软主动防御并归因到 DSH);桌面端/浏览器端按 `Origin` 头自动区分,浏览器端不误唤桌面窗口。
|
|
135
|
-
- **通知折叠**:不把 `tag` 交给平台(平台替换旧通知时会吞掉指向它的点击),由插件自己关旧发新,并持有每一代通知对象的引用,避免点击回调被回收成死按钮。
|
|
136
|
-
- **标题标记**:只做前缀加/删,与 DSH 自身的标题管理互不干扰;前缀按实际写入的文字记录,语言切换不叠加、不残留。「已完成」是未读消息——离开期间发生的完成才标记,回到页面即清除——不是常驻的「空闲」状态,看过的完成不会在每次切走时重新出现。
|
|
137
|
-
- **免打扰即遗忘**:静音时段内发生的决策与完成不记账——不响、不通知、不打标题标记,时段结束也不补发;本该在时段内发出的重复提醒直接作废。
|
|
138
|
-
- **冷却与健壮性**:同一会话的同类触发 2 秒内不重复响(另一个会话的决策照常响);音量经 `Number.isFinite` 防护(手改 YAML 的非法值回落默认);写入被拒时控件回弹到已接受值并显示错误行;开关写入中禁用,防双击竞写。
|
|
139
|
-
- **音量滑杆**:非受控输入,拖动只写 CSS 自定义属性,松手才提交一次,不卡顿、不回弹。
|
|
140
|
-
- **主题与排版**:全部使用 `--dsw-alias-*` 令牌,分区与行几何复刻官方设置页;音效选择用官方 `Menu` 下拉,不会撑出横向滚动。
|
|
141
|
-
|
|
142
|
-
## 📜 更新记录
|
|
143
|
-
|
|
144
|
-
- **v1.8.6**(2026-10-23)**把一次全量审计翻出来的问题收干净,没有新功能。** 修复:目标模式下,若用户在等到目标结束之前关掉「只在最终轮提醒」,目标结束后仍会补响一次——等待器现在会复查这个开关;更新检查把「失败」也缓存满 24 小时,一次网络抖动就让整行显示一整天「检查失败」,现在失败只缓存 1 分钟,并且不再断言原因是网络,而是如实说两个源都没给出可用答复;`pnpm-lock.yaml` 里带 peer 后缀的键(`pkg@1.8.4(@scope/peer@3.18.4)`)会被当成版本号,让正常的安装被误报「未被包管理器登记」并劝用户重装;当前版本读不出来时,界面会显示「当前版本 ? · 已是最新」,现在单独说明无法读取;「重复提醒间隔」把手改的 7 分钟显示成 5 分钟、实际按 7 分钟响,现在显示与计时共用同一次吸附;静音时段起止相同被当作「不静音」,描述已写明;客户端的时间解析接受 `9:05` 而宿主 schema 拒绝,现在两边一样严;自定义音效读取文件失败时误报「无法解码」,现在分开说;系统通知构造失败一次后整页永久显示「不支持」,现在成功一次即恢复。**更新指引**:桌面端的插件管理器是**左侧栏「插件」**(不是「设置 → 插件」),1.8.5 写错了,已改正;安装命令一律带版本号(此前渲染成 `@v1.8.5`,多了一个 `v`,复制进包管理器未必能解析),并说明发布不满 24 小时的版本会被 pnpm 的 `minimumReleaseAge` 挡掉。**清理**:移除 1.8.0 留下的 527 行不可达自安装器(宿主文件从 1553 行降到 1023 行,连同 10 个只服务于它的导入)、永远返回 null 的更新通知组件、8 个死字典键,以及只测死代码的测试;三条路由的拼写现在都在跨半契约测试里对齐(`/notify-sounds/goal` 此前漏了,而它正是漂移过一次的那条)。README 里「多窗口各自响一次」的说法与 1.7.0 起的发声页选举矛盾,已改正。
|
|
145
|
-
- **v1.8.5**(2026-10-20)**文案跟上机制。** 更新行此前仍写着「发现新版可一键安装」——从 1.8.0 起已不支持:这一行只负责检查,并指向包管理器。现在行内如实说明,且引导里带上版本号(`dsh-plugin-notify-sounds@{version}`),避免刚发布的版本被 pnpm 的 `minimumReleaseAge` 策略静默解析成上一个版本。README 的功能表、设置摘要与安装步骤不再承诺一键安装;历史更新记录保持原样。
|
|
146
|
-
- **v1.8.4**(2026-10-20)**点击通知一定能找到窗口。** 真实点击的日志显示:窗口明明存在,原生唤窗却报 "no window found"——隐藏或正在重绘的窗口可能瞬时返回空标题,而当时的搜索只认标题。现在窗口搜索同时按「拥有窗口的进程」匹配(桌面壳是本宿主进程的父进程),前台请求连续重试三次之后才走深链兜底。
|
|
147
|
-
- **v1.8.3**(2026-10-20)**窗口关到托盘时,点击通知也能回到 DSH 了。** 原先的 Win32 唤窗只搜**可见**窗口,关到托盘的 DSH 窗口永远找不到,只能退到很慢的深链兜底——表现就是「点了通知没反应」。现在会记住标题匹配的不可见窗口,并在置前之前先 `SW_SHOW` 让它显示出来;深链仍作为最后兜底。
|
|
148
|
-
- **v1.8.2**(2026-10-20)**真正修好目标模式的提醒。** 1.8.1 的宿主路由读了 `stateOf(session, "goal")`,却取 `current.phase`,而投影值把 goal 嵌在里面:`current.goal.phase`。于是每次读取都为空、每轮照响。现在改为读嵌套字段(并保留扁平形状的兜底),宿主侧调试记录已确认:中间轮 `current.goal.phase` 是 `active`,最后一轮是 `complete`。
|
|
149
|
-
- **v1.8.1**(2026-10-20)**修复目标模式的提醒。** 1.8.0 的开关从浏览器自己的会话投影读 phase,而那份投影只包含这个页面打开过的会话——目标所在的会话没被打开过时读到空值,代码把它当成「没有目标」,于是每轮又照响。浏览器半现在改问宿主新增的只读路由 `/notify-sounds/goal`(宿主的投影存储才是权威的),并在目标仍为 `active` 时持续复查:目标完成、暂停或受阻时响唯一一次;会话重新开始运行则保持安静。宿主不回答该路由时退回旧行为。
|
|
150
|
-
- **v1.8.0**(2026-10-20)**插件不再自己安装更新,改由包管理器负责。** 原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装(或市场升级)会静默把 pnpm 记录的版本装回来:1.7.0 的安装可能一声不响退回 1.6.9。DSH 0.2.1 让插件无法从内部持久地自安装(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码),所以自安装器被移除:更新行只检查 npm、报告新版,并指向真正负责安装的入口——设置 → 插件(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。它还会把「运行版本」与「lockfile 会恢复的版本」做比较,**不一致时明确提示**,把静默回退变成用户可自助修复的状态。**新增:目标模式下等目标结束再提醒**(issue #2)——目标模式会自动进行多轮,原先每轮结束都会响;新开关「目标模式下只在最终轮提醒」让中间轮保持安静,只在目标完成、暂停或受阻时响一次(普通对话不受影响;默认关闭)。本版保持同样的七个文件名,1.6.9 / 1.7.0 的安装仍可通过它们自带的自更新到达 1.8.0——之后用包管理器重装一次,升级即永久生效。
|
|
151
|
-
- **v1.7.0**(2026-10-16)**更新机制的转折点**:一键更新不再受「固定七个文件名」的白名单约束,改为按规则接受包目录下的任何普通文件——路径穿越、绝对路径、符号链接、非普通文件、保留名字(更新器自己的备份/临时名与记录文件、`.git`、`node_modules`、`.npmrc`)、含 `:` 的路径段,以及只有大小写不同的重名或**与 `package.json` 声明的入口只差大小写**的文件,依然一律拒绝,文件数与解压体积也都有上限(解压时即受 `gunzip` 上限约束)。**1.7.0 及以后可以正常更新到任意增减文件的新版**:某个版本去掉的文件现在会真的被删掉(依据更新器自己留下的 `.update-manifest.json` 记录,**只删它自己装过的文件**,用户放进目录里的东西一律不动;第一条记录之前的安装不做任何猜测)。**1.6.9 及更早**遇到「新增了文件」的新版会更新失败(安全失败:一个字节都不写,已装版本继续正常工作),README 里说明了重装一次的办法。修复:关掉「自动检查更新」会让每日轮询永久停摆(重新打开也不恢复);窗口标题在两次 Win32 读取之间变短时,点通知唤窗会静默失效;预发布版本号按字符串比较(`rc.10` 被误判为比 `rc.9` 旧);**同一个 GUI 开多个标签页或多个窗口时提示音、系统通知、重复提醒全部翻倍**(现在由 BroadcastChannel + 本地记录选出一个「发声页」,其余页保持安静,只在发声页消失后接管;窗口标题标记各窗口独立,不受影响);自定义音效的峰值归一化改为**逐样本**扫描(原先每 8 帧抽样会与接近 fs/8 的高频混叠、系统性低估峰值)。更新失败时给出**按阶段区分的建议**(网络类提示重试;解包/替换类给出手动重装步骤与仓库地址,并列出失败的两个版本号),写入顺序改为**最后写 `package.json`**(中途崩溃时检查仍会提示更新,用户再点一次即可自愈),并会校验归档里的清单确实是本包、确实是 registry 报的那个版本。设置里「自定义音效」移到**三种提示音之后**(它们才是会用到它的三处);`settings` 相关的小修:冷却表改为真正的 LRU(原先是 FIFO,最常触发的会话反而最先被淘汰)、会话列表每轮只取一次快照、macOS 桌面版的「窗口标题提醒」开关改为**禁用**(原先能打开但标记无处显示)、英文界面更新提示里残留的全角标点修掉、README 的 Release 安装说明改为可照做的本地路径写法。
|
|
152
|
-
- **v1.6.9**(2026-10-12)修正 v1.6.8 的 README 文件名兼容性:改回 `README.md`(英文默认)+ `README.zh.md`(中文),确保旧版本更新白名单能识别。新文件名会让旧用户的更新被拒——白名单是单向兼容的,更新时跑的是旧代码。
|
|
153
|
-
- **v1.6.8**(2026-10-12)修复复核细节 + 优化:`autoCheck` 首帧时序补上(`undefined` 不再被当成允许联网);删孤立 JSDoc;teardown 断言改为真正验证监听器移除;`normalizedGain` 抽样(每 8 帧,260 万→33 万次);`master` gain 播完自动断连(不再泄漏音频节点);`swapNavIcon` try/catch + 保留原节点、dispose 时还原(React 重排不再炸);冷却表 LRU 淘汰(不再全清);`sessionRows` 同步块级快照缓存。
|
|
154
|
-
- **v1.6.7**(2026-10-12)修复复核发现的 3 处细节:macOS 浏览器标签页不再被误标「暂不支持标题提醒」(`isDesktopShell` 才是判据);「自动检查=关」的首帧时序缺口补上(`undefined` 不再被当成允许);三处注释与实现不符已更正。补 BUG-1 回归测试(挂起 AudioContext 三断言)。
|
|
155
|
-
- **v1.6.6**(2026-10-12)按审计报告修复 9 处:浏览器自动播放策略下不再丢失提示音、也不再「攒到某次点击时一起补放」(首次手势解锁 + 只在真正可播时排程);macOS 唤窗改为按 bundle id 激活、深链兜底,失败会写进日志;更新回滚补全——新增文件一并撤回、不留临时文件、成功后清理备份;检查与更新加单飞,两个页面同时点不再互踩或重复请求;「自动检查更新=关」真正生效;移动端通知构造失败会如实显示不支持;导航图标回到官方 17×17 坐标系。跨平台标注:macOS 的「窗口标题提醒」标为暂不支持,浏览器下的重复提醒标注后台可能节流。
|
|
156
|
-
- **v1.6.5**(2026-10-11)免打扰改为**真的忘记**:静音时段里发生的决策与完成不再记账——不响、不通知、不打标题标记,时段结束后也不会把夜里漏掉的一起发回来;本该在时段内发出的重复提醒直接作废而非顺延。更新提示移到分区顶部(页面回顶也能第一眼看到,不再需要滚动);更新行文案简化。
|
|
157
|
-
- **v1.6.4**(2026-10-11)更新完成后不用再手动往下翻:更新会替换插件自身的客户端文件、触发页面重载并回到顶部,现在「更新完成」提示出现时,「更新」行会**平滑滚动回视野**。
|
|
158
|
-
- **v1.6.3**(2026-10-11)更新成功的提示不再一闪而过:更新结果改由**宿主**记住、随每次检查下发——即便更新替换掉了客户端自身文件、页面热重载丢掉本地状态,「更新完成:vX → vY,重启 DSH 后生效」也会一直显示到你重启;同时更新后**作废检查缓存**,不会再出现「明明刚升完却仍显示有新版」。
|
|
159
|
-
- **v1.6.2**(2026-10-11)修复一键更新在**镜像源**下必然失败:npmmirror 的 tarball 会跳转到它的 CDN,而下载器此前拒绝一切重定向,于是「只要检查由镜像应答,下载就永远到不了」(真机演练实测发现)。现在重定向改为逐跳跟随、每一跳都必须仍落在受信主机上(镜像 CDN 是唯一合法跳转),sha512 校验不变;失败提示会带上失败阶段(下载 / 校验 / 解包 / 替换),便于定位。
|
|
160
|
-
- **v1.6.1**(2026-10-11)README 重排为发布页风格:补「**与 DSH 界面保持一致**」一节讲清界面取自 DSH 自身设计体系;通篇表达润色,并修正升级说明(本插件自带更新,无需卸载重装)。本版同时是「一键更新」的发布演练。
|
|
161
|
-
- **v1.6.0**(2026-10-11)新增**检查更新与一键更新**:设置里可查 npm 新版本并一键安装——下载后按 registry 公布的 sha512 校验、只解包白名单文件(拒绝符号链接与路径穿越)、先备份再替换、失败自动还原;下载内容从不执行,新代码在 DSH 重启时生效。自动检查每天最多一次、可关;npm 官方源不通时自动改用国内镜像。
|
|
162
|
-
- **v1.5.0**(2026-10-08)「已完成」标题标记改为未读语义——离开期间发生的完成才标记,回到页面即清除,不再每次切走都重新出现;触发冷却按会话独立,2 秒内两个会话先后需要决策时都会响。补齐宿主半测试(配置 schema、唤窗路由、标题匹配)并交叉校验两半共享常量;`dsh.client.inject` 显式声明 sessions 提供包;静音时段结束后的补发行为写入文档。
|
|
163
|
-
|
|
164
|
-
- **v1.4.4**(2026-10-08)静音时段现在也会屏蔽任务栏标题提醒;进入或离开静音时段时,标题标记会自动刷新。自定义音效上传/移除按顺序写入配置,写入被拒时回滚;配置写入同步抛错也会按保存失败处理。
|
|
165
|
-
- **v1.4.3**(2026-10-08)三处修复:环境不支持音频解码时,上传自定义铃声不再被误判为有效(反正也播不出来);通知权限请求**同步抛错**也走拒绝处理,不留未处理异常;静音时段只接受合法 `HH:MM`(`99:99` 之类会被拒),Windows 原生唤窗抛错时继续走深链兜底。另补两条回归测试,并把解码失败的提示改准确(文件损坏与环境不支持解码两种情况都说清)。
|
|
166
|
-
- **v1.4.2**(2026-10-07)干净发布点:`v1.4.1` 的标签发布时被重钉过一次,本版重新发布,让下游拿到确定的标签;无行为变更。
|
|
167
|
-
- **v1.4.1**(2026-10-07)移除「没能唤回窗口」提示——判据会误报(窗口明明回来了还弹),而成功本身就是反馈;点通知现在全程静默,不再有任何跟点击弹出的通知。另:README 改版为发布页风格。
|
|
168
|
-
- **v1.4.0**(2026-10-07)看过就不再重复提醒;修复通知点击没反应(根因:平台 `tag` 替换吞掉点击);新增「子智能体的提醒」开关;另修标题前缀叠加等 5 项。
|
|
169
|
-
- **v1.3.3**(2026-10-07)重复提醒不再打扰正在看窗口的你;标题提醒改用文字(待处理 / 已完成)。
|
|
170
|
-
- **v1.3.2**(2026-10-05)两轮代码审查修复:非法 base64 中断跟踪器、通知对象回收、重复提醒吃冷却、时钟回拨静音、titleFlash 即时生效。
|
|
171
|
-
- **v1.3.1**(2026-10-05)修复唤窗时好时坏(Windows 前台锁)。
|
|
172
|
-
- **v1.3.0**(2026-10-05)唤窗改为进程内 FFI;桌面端/浏览器端自动区分。
|
|
173
|
-
- **v1.2.1**(2026-10-05)修复点击无反应。
|
|
174
|
-
- **v1.2.0**(2026-10-05)新增宿主 focus 路由(该版本点击无效,v1.3.x 修正)。
|
|
175
|
-
- **v1.1.2**(2026-10-05)修复下拉列表空白。
|
|
176
|
-
- **v1.1.1**(2026-10-05)排版与文案修复。
|
|
177
|
-
- **v1.1.0**(2026-10-05)自定义铃声、系统通知、分轨音效、重复提醒、静音时段、三种新音效。
|
|
178
|
-
- **v1.0.0**(2026-10-04)首个版本。
|
|
179
|
-
|
|
180
|
-
## 💻 开发
|
|
181
|
-
|
|
182
|
-
```powershell
|
|
183
|
-
npm install # 一次性:宿主测试需要 schemastery 开发依赖
|
|
184
|
-
node test/smoke.mjs # 客户端半:装配、触发、冷却、静音、重复提醒、通知点击、子智能体过滤
|
|
185
|
-
node test/host.mjs # 宿主半:配置 schema、唤窗路由、标题匹配、两半契约交叉校验
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
发布到 npm:升好版本号后 `npm publish`(首次发布先 `npm login` 并按提示开启 2FA)。**npm 的版本号不可覆盖**——有任何改动都请升版本再发。
|
|
189
|
-
|
|
190
|
-
```
|
|
191
|
-
dsh-plugin-notify-sounds/
|
|
192
|
-
├── package.json # dsh.bundle.patch + dsh.client
|
|
193
|
-
├── cordis.patch.yml # Loader 行:id: notify-sounds
|
|
194
|
-
├── lib/
|
|
195
|
-
│ ├── index.js # Host 半:配置模式 + 点通知唤窗路由
|
|
196
|
-
│ └── client.js # Client 半:音效引擎、状态监听、设置分区
|
|
197
|
-
└── test/
|
|
198
|
-
├── smoke.mjs # 客户端半
|
|
199
|
-
└── host.mjs # 宿主半
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
`package.json` 已按可发布形态声明(`files` 只带运行时产物,`@deepseek-ai/schemastery` 为 peerDependency、另有一份 devDependency 供宿主测试,纯 ESM、无构建步骤),日后发 npm 直接 `npm publish` 即可。
|
|
203
|
-
|
|
204
|
-
## 📄 License
|
|
205
83
|
|
|
206
|
-
|
|
84
|
+
卸载不会丢东西:偏好和自定义音频都存在 profile 里(`cordis.patch.yml` 与 `notify-sounds/sounds/`),重装后自动恢复——包括升级到 1.9.0 时由旧版内嵌音频自动迁移过来的那份。
|
|
85
|
+
- **装了市场插件**([dshmarket](https://www.npmjs.com/package/dshmarket)):在市场里一键更新。
|
|
86
|
+
- **`web` profile**:`dsh plugin --profile <你的 profile> add dsh-plugin-notify-sounds@<版本>`。
|
|
87
|
+
|
|
88
|
+
更新行还会提示「当前版本与 lockfile 记录不一致」——那是 1.8.0 之前的自更新留下的状态,按上面方式重装一次即可永久修好。
|
|
89
|
+
|
|
90
|
+
### 🛠️ 其他安装方式
|
|
91
|
+
|
|
92
|
+
**命令行** —— 对你实际使用的 profile 一条命令:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
dsh plugin --profile <你的 profile> add github:BillCx330/dsh-plugin-notify-sounds
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
(Git 安装跟仓库默认分支走,不带版本锁定;要可复现的安装请用上面的 `包名@版本号`。)
|
|
99
|
+
|
|
100
|
+
**Release 压缩包** —— 从 [Releases](https://github.com/BillCx330/dsh-plugin-notify-sounds/releases) 下载 `.tgz`,用它**在磁盘上的路径**安装:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds-1.9.0.tgz
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
(`dsh plugin add` 把参数原样交给包管理器,所以要给本地文件路径,不能填下载地址。)
|
|
107
|
+
|
|
108
|
+
**本地目录** —— 开发或试用未发布的改动:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
dsh plugin --profile <你的 profile> add ./dsh-plugin-notify-sounds
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**手工编辑** —— 在 profile 的 `package.json` 的 `dependencies` 加 `"dsh-plugin-notify-sounds": "github:BillCx330/dsh-plugin-notify-sounds"`,在 `dsh.profile.bundles` 追加 `"dsh-plugin-notify-sounds"`,然后在 profile 目录跑一次包安装(如 `pnpm install`)把依赖装进 `node_modules`。
|
|
115
|
+
|
|
116
|
+
命令行方式会自动写入 `dsh.profile.bundles` 并装好依赖,无需手工编辑。包内直接带预构建产物、不声明任何生命周期脚本,安装过程不执行构建脚本。安装后**重启 DSH**(日常升级仅客户端改动时,可热更生效)。
|
|
117
|
+
|
|
118
|
+
## ⚠️ 已知边界
|
|
119
|
+
|
|
120
|
+
- **自定义音频存在哪**:音频按内容哈希存成 `profiles/<profile>/notify-sounds/sounds/<sha256>.<ext>`,配置里只留文件名。**备份或换机要拷整个 profile 目录**——只拷 `cordis.patch.yml` 不会带上音频。卸载插件后最多留下最后一个文件(几百 KB)。
|
|
121
|
+
- **手改配置**:偏好写在 profile 的 `cordis.patch.yml`,值必须符合 schema(音量 0–100、音效为预设之一、时间 `HH:MM`);写错会让插件不加载,改回即可。设置界面只会写入合法值。
|
|
122
|
+
- **升级由包管理器安装,不再由插件自己完成**:1.8.0 移除了自安装器(原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装会静默把旧版本装回来)。更新行仍会检查 npm、报告新版,然后指向真正负责安装的入口——**左侧栏「插件」**(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。
|
|
123
|
+
- **1.7.0 及更早版本**可以通过它们自带的自更新到达 1.8.0(1.8.0 保持同样的七个文件名),但这次到达不会被 pnpm 登记:按上面的方式用包管理器重装一次,此后所有升级都会留下。1.6.9 及更早无法安装「新增了文件」的版本——固定白名单会安全拒绝;同样的一次性重装即可解决。
|
|
124
|
+
- **多窗口**:提示音、系统通知和重复提醒由同一个 GUI 的所有页面选出一个「发声页」来发(1.7.0 起),所以同一个事件只响一次;窗口标题标记仍是每个窗口各自一份,因为它们各自有标题。发声页关闭或崩溃后几秒内由其他页面接管。
|
|
125
|
+
- **点击通知回到窗口**:Windows 完整实现并实测;macOS / Linux 走系统深链,未验证。
|
|
126
|
+
- **唤窗按窗口标题定位主窗口**:刻意不读取其他进程信息(那会触发杀软主动防御)。若将来 DSH 改变标题格式,唤窗会静默失效——提示音与通知本身不受影响。
|
|
127
|
+
- **导航小图标**:依赖设置面板的 DOM 结构,若DSH 改版后自动回落为官方齿轮,仅影响外观。
|
|
128
|
+
- **通知权限**:桌面端放行;受限环境(某些浏览器策略)下被拒时,行内会引导手动允许,其余功能不受影响。
|
|
129
|
+
- **macOS 的系统通知**:桌面外壳对权限请求一律放行,所以设置里恒显示「已授权」;**实际是否弹横幅由 macOS 决定**(系统设置 → 通知 → DeepSeek Harness),未签名的开发版可能静默失败——「显示已授权却没通知」多半不是插件的问题。
|
|
130
|
+
|
|
131
|
+
## 🧩 设计与实现
|
|
132
|
+
|
|
133
|
+
给想改代码的人看的要点(实现细节以源码注释为准):
|
|
134
|
+
|
|
135
|
+
- **触发不碰事件瀑布**:审批/提问的请求是 waterfall 事件,UI 应答后晚注册的监听器收不到。本插件改读 `uiSession.sessionStatus`(DSH 自己聚合的 pending/running 事实,与侧栏状态点同源),纯观察、零侵入。
|
|
136
|
+
- **重复提醒的节拍**:15 秒粒度检查未处理决策;**看过即除名**(决策出现时你正在窗口、或之后回到窗口,都算看过),切走不重新武装;新问题替换旧问题会重置计时。免打扰期间的提醒直接作废,不会顺延到时段结束补发。
|
|
137
|
+
- **通知点击回到窗口**:渲染进程唤不起 OS 窗口,点击时 POST 到宿主半边的 `/notify-sounds/focus`(带 connection 围栏),由宿主唤起。Windows 用 DSH 自带的 `koffi` 直接调 `user32.dll`(不引新依赖、只操作窗口、不启动 PowerShell——那会触发杀软主动防御并归因到 DSH);桌面端/浏览器端按 `Origin` 头自动区分,浏览器端不误唤桌面窗口。
|
|
138
|
+
- **通知折叠**:不把 `tag` 交给平台(平台替换旧通知时会吞掉指向它的点击),由插件自己关旧发新,并持有每一代通知对象的引用,避免点击回调被回收成死按钮。
|
|
139
|
+
- **标题标记**:只做前缀加/删,与 DSH 自身的标题管理互不干扰;前缀按实际写入的文字记录,语言切换不叠加、不残留。「已完成」是未读消息——离开期间发生的完成才标记,回到页面即清除——不是常驻的「空闲」状态,看过的完成不会在每次切走时重新出现。
|
|
140
|
+
- **免打扰即遗忘**:静音时段内发生的决策与完成不记账——不响、不通知、不打标题标记,时段结束也不补发;本该在时段内发出的重复提醒直接作废。
|
|
141
|
+
- **冷却与健壮性**:同一会话的同类触发 2 秒内不重复响(另一个会话的决策照常响);音量经 `Number.isFinite` 防护(手改 YAML 的非法值回落默认);写入被拒时控件回弹到已接受值并显示错误行;开关写入中禁用,防双击竞写。
|
|
142
|
+
- **音量滑杆**:非受控输入,拖动只写 CSS 自定义属性,松手才提交一次,不卡顿、不回弹。
|
|
143
|
+
- **主题与排版**:全部使用 `--dsw-alias-*` 令牌,分区与行几何复刻官方设置页;音效选择用官方 `Menu` 下拉,不会撑出横向滚动。
|
|
144
|
+
|
|
145
|
+
## 📜 更新记录
|
|
146
|
+
|
|
147
|
+
- **v1.9.0**(2026-10-27)**自定义音频变成一个小库:最多 3 个,可以改名、指派。** 此前三个提醒共用同一个「自定义」上传——想给「完成」配一个、同时让「决策」用内置音,做不到。现在「自定义音效」只有一行:点「添加音频」选文件,加进去的会列在它下面(最多 3 个),每个都能改名、试听、移除;三个提醒的音效下拉里会直接列出这些音频的名字,挑哪个就响哪个。**存放位置也换了**:音频不再以 base64 塞进 `cordis.patch.yml`(一个 512KB 的音频就是 699,052 个字符,是整份配置的 277 倍,而且每次改设置都要整份重新广播),改为存到 `profiles/<profile>/notify-sounds/sounds/<哈希>.<后缀>`,配置里只留名字。顺带补了三件一直缺的:**上限 3MB、每个 15 秒**(太长的音频会变成背景音,解码后还可能占几十 MB 内存);**没有声音、或短到听不见的文件,在上传时就被拒绝**;**读不到音频时改用该项的默认音**——此前配置里的音频一旦损坏,三个提醒会全部静默,界面上还什么都不说。列表里也会标出「文件找不到了」和「还没有提醒使用它」。老用户升级时,原来的音频会自动搬进这个库;搬不进去就原样留着,照旧能响。
|
|
148
|
+
- **v1.8.6**(2026-10-23)**把一次全量审计翻出来的问题收干净,没有新功能。** 修复:目标模式下,若用户在等到目标结束之前关掉「只在最终轮提醒」,目标结束后仍会补响一次——等待器现在会复查这个开关;更新检查把「失败」也缓存满 24 小时,一次网络抖动就让整行显示一整天「检查失败」,现在失败只缓存 1 分钟,并且不再断言原因是网络,而是如实说两个源都没给出可用答复;`pnpm-lock.yaml` 里带 peer 后缀的键(`pkg@1.8.4(@scope/peer@3.18.4)`)会被当成版本号,让正常的安装被误报「未被包管理器登记」并劝用户重装;当前版本读不出来时,界面会显示「当前版本 ? · 已是最新」,现在单独说明无法读取;「重复提醒间隔」把手改的 7 分钟显示成 5 分钟、实际按 7 分钟响,现在显示与计时共用同一次吸附;静音时段起止相同被当作「不静音」,描述已写明;客户端的时间解析接受 `9:05` 而宿主 schema 拒绝,现在两边一样严;自定义音效读取文件失败时误报「无法解码」,现在分开说;系统通知构造失败一次后整页永久显示「不支持」,现在成功一次即恢复。**更新指引**:桌面端的插件管理器是**左侧栏「插件」**(不是「设置 → 插件」),1.8.5 写错了,已改正;安装命令一律带版本号(此前渲染成 `@v1.8.5`,多了一个 `v`,复制进包管理器未必能解析),并说明发布不满 24 小时的版本会被 pnpm 的 `minimumReleaseAge` 挡掉。**清理**:移除 1.8.0 留下的 527 行不可达自安装器(宿主文件从 1553 行降到 1023 行,连同 10 个只服务于它的导入)、永远返回 null 的更新通知组件、8 个死字典键,以及只测死代码的测试;三条路由的拼写现在都在跨半契约测试里对齐(`/notify-sounds/goal` 此前漏了,而它正是漂移过一次的那条)。README 里「多窗口各自响一次」的说法与 1.7.0 起的发声页选举矛盾,已改正。
|
|
149
|
+
- **v1.8.5**(2026-10-20)**文案跟上机制。** 更新行此前仍写着「发现新版可一键安装」——从 1.8.0 起已不支持:这一行只负责检查,并指向包管理器。现在行内如实说明,且引导里带上版本号(`dsh-plugin-notify-sounds@{version}`),避免刚发布的版本被 pnpm 的 `minimumReleaseAge` 策略静默解析成上一个版本。README 的功能表、设置摘要与安装步骤不再承诺一键安装;历史更新记录保持原样。
|
|
150
|
+
- **v1.8.4**(2026-10-20)**点击通知一定能找到窗口。** 真实点击的日志显示:窗口明明存在,原生唤窗却报 "no window found"——隐藏或正在重绘的窗口可能瞬时返回空标题,而当时的搜索只认标题。现在窗口搜索同时按「拥有窗口的进程」匹配(桌面壳是本宿主进程的父进程),前台请求连续重试三次之后才走深链兜底。
|
|
151
|
+
- **v1.8.3**(2026-10-20)**窗口关到托盘时,点击通知也能回到 DSH 了。** 原先的 Win32 唤窗只搜**可见**窗口,关到托盘的 DSH 窗口永远找不到,只能退到很慢的深链兜底——表现就是「点了通知没反应」。现在会记住标题匹配的不可见窗口,并在置前之前先 `SW_SHOW` 让它显示出来;深链仍作为最后兜底。
|
|
152
|
+
- **v1.8.2**(2026-10-20)**真正修好目标模式的提醒。** 1.8.1 的宿主路由读了 `stateOf(session, "goal")`,却取 `current.phase`,而投影值把 goal 嵌在里面:`current.goal.phase`。于是每次读取都为空、每轮照响。现在改为读嵌套字段(并保留扁平形状的兜底),宿主侧调试记录已确认:中间轮 `current.goal.phase` 是 `active`,最后一轮是 `complete`。
|
|
153
|
+
- **v1.8.1**(2026-10-20)**修复目标模式的提醒。** 1.8.0 的开关从浏览器自己的会话投影读 phase,而那份投影只包含这个页面打开过的会话——目标所在的会话没被打开过时读到空值,代码把它当成「没有目标」,于是每轮又照响。浏览器半现在改问宿主新增的只读路由 `/notify-sounds/goal`(宿主的投影存储才是权威的),并在目标仍为 `active` 时持续复查:目标完成、暂停或受阻时响唯一一次;会话重新开始运行则保持安静。宿主不回答该路由时退回旧行为。
|
|
154
|
+
- **v1.8.0**(2026-10-20)**插件不再自己安装更新,改由包管理器负责。** 原地写文件从不会更新 profile 的 lockfile,于是下一次插件安装(或市场升级)会静默把 pnpm 记录的版本装回来:1.7.0 的安装可能一声不响退回 1.6.9。DSH 0.2.1 让插件无法从内部持久地自安装(管理器拒绝已声明的包,而它的「先移除再安装」会先卸载掉正要完成安装的代码),所以自安装器被移除:更新行只检查 npm、报告新版,并指向真正负责安装的入口——设置 → 插件(卸载后再装)、市场,或 web profile 上的 `dsh plugin add`。它还会把「运行版本」与「lockfile 会恢复的版本」做比较,**不一致时明确提示**,把静默回退变成用户可自助修复的状态。**新增:目标模式下等目标结束再提醒**(issue #2)——目标模式会自动进行多轮,原先每轮结束都会响;新开关「目标模式下只在最终轮提醒」让中间轮保持安静,只在目标完成、暂停或受阻时响一次(普通对话不受影响;默认关闭)。本版保持同样的七个文件名,1.6.9 / 1.7.0 的安装仍可通过它们自带的自更新到达 1.8.0——之后用包管理器重装一次,升级即永久生效。
|
|
155
|
+
- **v1.7.0**(2026-10-16)**更新机制的转折点**:一键更新不再受「固定七个文件名」的白名单约束,改为按规则接受包目录下的任何普通文件——路径穿越、绝对路径、符号链接、非普通文件、保留名字(更新器自己的备份/临时名与记录文件、`.git`、`node_modules`、`.npmrc`)、含 `:` 的路径段,以及只有大小写不同的重名或**与 `package.json` 声明的入口只差大小写**的文件,依然一律拒绝,文件数与解压体积也都有上限(解压时即受 `gunzip` 上限约束)。**1.7.0 及以后可以正常更新到任意增减文件的新版**:某个版本去掉的文件现在会真的被删掉(依据更新器自己留下的 `.update-manifest.json` 记录,**只删它自己装过的文件**,用户放进目录里的东西一律不动;第一条记录之前的安装不做任何猜测)。**1.6.9 及更早**遇到「新增了文件」的新版会更新失败(安全失败:一个字节都不写,已装版本继续正常工作),README 里说明了重装一次的办法。修复:关掉「自动检查更新」会让每日轮询永久停摆(重新打开也不恢复);窗口标题在两次 Win32 读取之间变短时,点通知唤窗会静默失效;预发布版本号按字符串比较(`rc.10` 被误判为比 `rc.9` 旧);**同一个 GUI 开多个标签页或多个窗口时提示音、系统通知、重复提醒全部翻倍**(现在由 BroadcastChannel + 本地记录选出一个「发声页」,其余页保持安静,只在发声页消失后接管;窗口标题标记各窗口独立,不受影响);自定义音效的峰值归一化改为**逐样本**扫描(原先每 8 帧抽样会与接近 fs/8 的高频混叠、系统性低估峰值)。更新失败时给出**按阶段区分的建议**(网络类提示重试;解包/替换类给出手动重装步骤与仓库地址,并列出失败的两个版本号),写入顺序改为**最后写 `package.json`**(中途崩溃时检查仍会提示更新,用户再点一次即可自愈),并会校验归档里的清单确实是本包、确实是 registry 报的那个版本。设置里「自定义音效」移到**三种提示音之后**(它们才是会用到它的三处);`settings` 相关的小修:冷却表改为真正的 LRU(原先是 FIFO,最常触发的会话反而最先被淘汰)、会话列表每轮只取一次快照、macOS 桌面版的「窗口标题提醒」开关改为**禁用**(原先能打开但标记无处显示)、英文界面更新提示里残留的全角标点修掉、README 的 Release 安装说明改为可照做的本地路径写法。
|
|
156
|
+
- **v1.6.9**(2026-10-12)修正 v1.6.8 的 README 文件名兼容性:改回 `README.md`(英文默认)+ `README.zh.md`(中文),确保旧版本更新白名单能识别。新文件名会让旧用户的更新被拒——白名单是单向兼容的,更新时跑的是旧代码。
|
|
157
|
+
- **v1.6.8**(2026-10-12)修复复核细节 + 优化:`autoCheck` 首帧时序补上(`undefined` 不再被当成允许联网);删孤立 JSDoc;teardown 断言改为真正验证监听器移除;`normalizedGain` 抽样(每 8 帧,260 万→33 万次);`master` gain 播完自动断连(不再泄漏音频节点);`swapNavIcon` try/catch + 保留原节点、dispose 时还原(React 重排不再炸);冷却表 LRU 淘汰(不再全清);`sessionRows` 同步块级快照缓存。
|
|
158
|
+
- **v1.6.7**(2026-10-12)修复复核发现的 3 处细节:macOS 浏览器标签页不再被误标「暂不支持标题提醒」(`isDesktopShell` 才是判据);「自动检查=关」的首帧时序缺口补上(`undefined` 不再被当成允许);三处注释与实现不符已更正。补 BUG-1 回归测试(挂起 AudioContext 三断言)。
|
|
159
|
+
- **v1.6.6**(2026-10-12)按审计报告修复 9 处:浏览器自动播放策略下不再丢失提示音、也不再「攒到某次点击时一起补放」(首次手势解锁 + 只在真正可播时排程);macOS 唤窗改为按 bundle id 激活、深链兜底,失败会写进日志;更新回滚补全——新增文件一并撤回、不留临时文件、成功后清理备份;检查与更新加单飞,两个页面同时点不再互踩或重复请求;「自动检查更新=关」真正生效;移动端通知构造失败会如实显示不支持;导航图标回到官方 17×17 坐标系。跨平台标注:macOS 的「窗口标题提醒」标为暂不支持,浏览器下的重复提醒标注后台可能节流。
|
|
160
|
+
- **v1.6.5**(2026-10-11)免打扰改为**真的忘记**:静音时段里发生的决策与完成不再记账——不响、不通知、不打标题标记,时段结束后也不会把夜里漏掉的一起发回来;本该在时段内发出的重复提醒直接作废而非顺延。更新提示移到分区顶部(页面回顶也能第一眼看到,不再需要滚动);更新行文案简化。
|
|
161
|
+
- **v1.6.4**(2026-10-11)更新完成后不用再手动往下翻:更新会替换插件自身的客户端文件、触发页面重载并回到顶部,现在「更新完成」提示出现时,「更新」行会**平滑滚动回视野**。
|
|
162
|
+
- **v1.6.3**(2026-10-11)更新成功的提示不再一闪而过:更新结果改由**宿主**记住、随每次检查下发——即便更新替换掉了客户端自身文件、页面热重载丢掉本地状态,「更新完成:vX → vY,重启 DSH 后生效」也会一直显示到你重启;同时更新后**作废检查缓存**,不会再出现「明明刚升完却仍显示有新版」。
|
|
163
|
+
- **v1.6.2**(2026-10-11)修复一键更新在**镜像源**下必然失败:npmmirror 的 tarball 会跳转到它的 CDN,而下载器此前拒绝一切重定向,于是「只要检查由镜像应答,下载就永远到不了」(真机演练实测发现)。现在重定向改为逐跳跟随、每一跳都必须仍落在受信主机上(镜像 CDN 是唯一合法跳转),sha512 校验不变;失败提示会带上失败阶段(下载 / 校验 / 解包 / 替换),便于定位。
|
|
164
|
+
- **v1.6.1**(2026-10-11)README 重排为发布页风格:补「**与 DSH 界面保持一致**」一节讲清界面取自 DSH 自身设计体系;通篇表达润色,并修正升级说明(本插件自带更新,无需卸载重装)。本版同时是「一键更新」的发布演练。
|
|
165
|
+
- **v1.6.0**(2026-10-11)新增**检查更新与一键更新**:设置里可查 npm 新版本并一键安装——下载后按 registry 公布的 sha512 校验、只解包白名单文件(拒绝符号链接与路径穿越)、先备份再替换、失败自动还原;下载内容从不执行,新代码在 DSH 重启时生效。自动检查每天最多一次、可关;npm 官方源不通时自动改用国内镜像。
|
|
166
|
+
- **v1.5.0**(2026-10-08)「已完成」标题标记改为未读语义——离开期间发生的完成才标记,回到页面即清除,不再每次切走都重新出现;触发冷却按会话独立,2 秒内两个会话先后需要决策时都会响。补齐宿主半测试(配置 schema、唤窗路由、标题匹配)并交叉校验两半共享常量;`dsh.client.inject` 显式声明 sessions 提供包;静音时段结束后的补发行为写入文档。
|
|
167
|
+
|
|
168
|
+
- **v1.4.4**(2026-10-08)静音时段现在也会屏蔽任务栏标题提醒;进入或离开静音时段时,标题标记会自动刷新。自定义音效上传/移除按顺序写入配置,写入被拒时回滚;配置写入同步抛错也会按保存失败处理。
|
|
169
|
+
- **v1.4.3**(2026-10-08)三处修复:环境不支持音频解码时,上传自定义铃声不再被误判为有效(反正也播不出来);通知权限请求**同步抛错**也走拒绝处理,不留未处理异常;静音时段只接受合法 `HH:MM`(`99:99` 之类会被拒),Windows 原生唤窗抛错时继续走深链兜底。另补两条回归测试,并把解码失败的提示改准确(文件损坏与环境不支持解码两种情况都说清)。
|
|
170
|
+
- **v1.4.2**(2026-10-07)干净发布点:`v1.4.1` 的标签发布时被重钉过一次,本版重新发布,让下游拿到确定的标签;无行为变更。
|
|
171
|
+
- **v1.4.1**(2026-10-07)移除「没能唤回窗口」提示——判据会误报(窗口明明回来了还弹),而成功本身就是反馈;点通知现在全程静默,不再有任何跟点击弹出的通知。另:README 改版为发布页风格。
|
|
172
|
+
- **v1.4.0**(2026-10-07)看过就不再重复提醒;修复通知点击没反应(根因:平台 `tag` 替换吞掉点击);新增「子智能体的提醒」开关;另修标题前缀叠加等 5 项。
|
|
173
|
+
- **v1.3.3**(2026-10-07)重复提醒不再打扰正在看窗口的你;标题提醒改用文字(待处理 / 已完成)。
|
|
174
|
+
- **v1.3.2**(2026-10-05)两轮代码审查修复:非法 base64 中断跟踪器、通知对象回收、重复提醒吃冷却、时钟回拨静音、titleFlash 即时生效。
|
|
175
|
+
- **v1.3.1**(2026-10-05)修复唤窗时好时坏(Windows 前台锁)。
|
|
176
|
+
- **v1.3.0**(2026-10-05)唤窗改为进程内 FFI;桌面端/浏览器端自动区分。
|
|
177
|
+
- **v1.2.1**(2026-10-05)修复点击无反应。
|
|
178
|
+
- **v1.2.0**(2026-10-05)新增宿主 focus 路由(该版本点击无效,v1.3.x 修正)。
|
|
179
|
+
- **v1.1.2**(2026-10-05)修复下拉列表空白。
|
|
180
|
+
- **v1.1.1**(2026-10-05)排版与文案修复。
|
|
181
|
+
- **v1.1.0**(2026-10-05)自定义铃声、系统通知、分轨音效、重复提醒、静音时段、三种新音效。
|
|
182
|
+
- **v1.0.0**(2026-10-04)首个版本。
|
|
183
|
+
|
|
184
|
+
## 💻 开发
|
|
185
|
+
|
|
186
|
+
```powershell
|
|
187
|
+
npm install # 一次性:宿主测试需要 schemastery 开发依赖
|
|
188
|
+
node test/smoke.mjs # 客户端半:装配、触发、冷却、静音、重复提醒、通知点击、子智能体过滤
|
|
189
|
+
node test/host.mjs # 宿主半:配置 schema、唤窗路由、标题匹配、两半契约交叉校验
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
发布到 npm:升好版本号后 `npm publish`(首次发布先 `npm login` 并按提示开启 2FA)。**npm 的版本号不可覆盖**——有任何改动都请升版本再发。
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
dsh-plugin-notify-sounds/
|
|
196
|
+
├── package.json # dsh.bundle.patch + dsh.client
|
|
197
|
+
├── cordis.patch.yml # Loader 行:id: notify-sounds
|
|
198
|
+
├── lib/
|
|
199
|
+
│ ├── index.js # Host 半:配置模式 + 点通知唤窗路由
|
|
200
|
+
│ └── client.js # Client 半:音效引擎、状态监听、设置分区
|
|
201
|
+
└── test/
|
|
202
|
+
├── smoke.mjs # 客户端半
|
|
203
|
+
└── host.mjs # 宿主半
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`package.json` 已按可发布形态声明(`files` 只带运行时产物,`@deepseek-ai/schemastery` 为 peerDependency、另有一份 devDependency 供宿主测试,纯 ESM、无构建步骤),日后发 npm 直接 `npm publish` 即可。
|
|
207
|
+
|
|
208
|
+
## 📄 License
|
|
209
|
+
|
|
210
|
+
[MIT](LICENSE) © BillCx330
|