dsh-notify-say 0.4.46 → 0.4.48

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/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  > 本文件由 `tools/release-build.ps1` 从开发提交自动生成,**请勿手工编辑**。
4
4
  > 只列面向使用者的变更(新增功能与修复),不含内部维护提交。
5
5
 
6
+ ## v0.4.48 — 2026-10-18
7
+
8
+ - feat(update): v0.4.48 —— 检查更新 + 引导升级(不做自动更新)
9
+
6
10
  ## v0.4.46 — 2026-10-18
7
11
 
8
12
  - fix(test): v0.4.46 —— 修「本地绿、CI 红」+ 发版流程补发布包内测试
package/README.md CHANGED
@@ -1,219 +1,388 @@
1
- # dsh-notify-say
2
-
3
- 给 [DeepSeek Harness](https://github.com/deepseek-ai) Desktop 用的通知插件:**任务跑完会说话**。
4
-
5
- > 别的通知插件"叮"一声;这个会喊你"主人、任务完成了"。
6
- > 而且**子代理还在跑的时候,它不会骗你说完成了**。
7
-
8
- ---
9
-
10
- ## 它解决什么问题
11
-
12
- 你让 AI 跑一个较长任务,然后切去干别的。常见两种通知插件的毛病:
13
-
14
- 1. **该响的时候不响** —— 主会话一轮结束就报"完成",但其实它派出的子代理还在跑,你回来发现没干完。
15
- 2. **不该响的时候一直响** —— 每个子代理结束都弹一次,连环轰炸。
16
-
17
- 本插件的做法:
18
-
19
- - **空闲门(idle gate)**:主会话这轮结束、但仍有子代理或后台任务在跑时,**先不播**;等全部结束再播**一次**。超时(默认 10 分钟)兜底,防子任务卡死导致永不播报。
20
- - **按会话去抖**:同一会话 60 秒内只响一次。
21
- - **失败单独提醒**:回合出错时播**日语道歉语音**(可选),比"任务完成"更该让你立刻知道。
22
-
23
- ---
24
-
25
- ## 特性
26
-
27
- | 特性 | 说明 |
28
- |---|---|
29
- | **语音播报** | 本地 wav,不联网、不调用云端 TTS。发布版附 1 个音色,其余可按需下载 |
30
- | **空闲门** | 有在飞工作时不误报"完成",全部结束才播一次 |
31
- | **五类事件** | 完成 / 出错 / 被拦截 / 待批准 / 要提问,各自独立开关 |
32
- | **设置页 GUI** | 走官方 `Config` schema,DSH 设置页自动生成表单 |
33
- | **命令行** | `tools/notify-config.ps1`,改完**立即生效、不用重启** |
34
- | **点通知跳会话** | 点击 Toast 可直接回到对应会话(拿不到导航服务时自动降级为"唤出窗口") |
35
- | **不装语音也能用** | 没有语音包 = Toast + 系统提示音,这是正常配置 |
36
- | **全离线** | 不联网、不发送任何会话内容 |
37
-
38
- ---
39
-
40
- ## 安装
41
-
42
- ### 前置
43
-
44
- - DSH Desktop **0.1.7-rc.2 或更高**
45
- - Windows(Toast 用 WinRT,播放用 MCI;暂不支持 macOS/Linux)
46
-
47
- ### 方式一:插件页(推荐)
48
-
49
- 在 DSH 的 **设置 → 插件** 里搜索 `dsh-notify-say` 安装。
50
-
51
- ### 方式二:手工 link(本地开发)
52
-
53
- 把本仓库目录链接进 profile:
54
-
55
- ```
56
- D:\Program Files (x86)\DSH\profiles\desktop\package.json
57
- dependencies 里加: "dsh-notify-say": "link:<本仓库路径>"
58
- dsh.profile.bundles 里加: "dsh-notify-say"
59
- ```
60
-
61
- 然后在该 profile 目录执行 `pnpm install`,重启 DSH。
62
-
63
- ---
64
-
65
- ## 配置
66
-
67
- 三种方式,优先级由低到高(后者覆盖前者):
68
-
69
- ```
70
- 1. schema 默认值
71
- 2. cordis.patch.yml 的 config
72
- 3. DSH 设置页里改的值
73
- 4. tools/notify-config.ps1 写的 storages/config.json
74
- ```
75
-
76
- > ⚠️ **注意语义**:一旦你在设置页改过某项,再改 `cordis.patch.yml` 里同一项**不再生效**。
77
- > 这是 DSH 官方设计(用户层优先级更高),不是本插件的 bug。
78
-
79
- ### 设置页
80
-
81
- DSH **设置 → 通知**(由官方 Loader 从本插件的 `Config` schema 自动生成),共 12 项:
82
-
83
- 语音开关、音色模式(固定/随机)、音色名、音量,
84
- 以及完成/出错/被拦截/已中止/待批准/要提问/子代理/空闲门 八个开关。
85
-
86
- ### 命令行
87
-
88
- ```powershell
89
- cd <插件目录>\tools
90
-
91
- .\notify-config.ps1 -Show # 看当前生效值
92
- .\notify-config.ps1 -Voice off # 静音(Toast 仍弹)
93
- .\notify-config.ps1 -Volume 40
94
- .\notify-config.ps1 -VoiceMode random
95
- .\notify-config.ps1 -VoiceName ankomon
96
- .\notify-config.ps1 -Disable aborted -Enable subagents
97
- .\notify-config.ps1 -Clear # 交还控制权给设置页
98
- ```
99
-
100
- 改完**立即生效**,不需要重启 DSH。
101
-
102
- ### 语音包管理
103
-
104
- 核心包只带**一个日语音色**(ずんだもん),体积约 2.8 MB。
105
- 完整多音色包体积较大(十余个音色约 40 MB),故不随包发布 —— 计划通过单独下载提供(尚未实现)。
106
-
107
- ```powershell
108
- .\notify-config.ps1 -ListPacks # 看已装哪些音色、各占多少
109
- .\notify-config.ps1 -PurgeVoice <key> # 删掉不用的音色
110
- .\notify-config.ps1 -InstallHint # 看怎么获取更多音色
111
- ```
112
-
113
- **不装任何语音包也完全可用**:通知会退回 Windows Toast + 系统提示音。
114
-
115
- 想要更多音色,两条路:
116
-
117
- 1. **自己合成**:装 [VOICEVOX](https://voicevox.hiroshiba.jp/)(本地免费 TTS),启动引擎(默认 `http://127.0.0.1:50021`),
118
- 然后按下面的命名规则把合成好的 wav 放进对应目录即可。
119
- (合成脚本不随本包发布——它依赖本地 VOICEVOX 引擎与特定音色表,放在发布包里只会误导。)
120
- 2. **手工放入**:把 wav 按下面的命名放进对应目录
121
-
122
- ```
123
- sounds/voice-lines/<key>~1.wav 完成
124
- sounds/voice-lines/question/<key>~1.wav 提问
125
- sounds/voice-lines/approval/<key>~1.wav 审批
126
- sounds/voice-lines/fail/<key>~1.wav 出错
127
- ```
128
-
129
- ---
130
-
131
- ## 兼容性与降级
132
-
133
- 本插件的首要目标是**稳定**,所以每个依赖外部能力的地方都有降级路径:
134
-
135
- | 能力 | 拿不到时怎么办 |
136
- |---|---|
137
- | `@deepseek-ai/schemastery`(生成设置页) | 不导出 `Config` → **设置页不出现,插件照常工作** |
138
- | `uiWorkspace.openSession`(点通知跳会话) | 不跳转,Toast 仍能唤出窗口(**退回旧行为**) |
139
- | 语音包 | 回退系统提示音 |
140
- | `$DSH_HOME` 未设置 | 配置走 patch 默认值;不写任何状态文件 |
141
-
142
- **不会出现"静默失效"**:每个降级都有明确行为,并有测试锁定。
143
-
144
- > 对比:某些插件写 `if (typeof sessions?.open === 'function') sessions.open(id)`,
145
- > 而 `sessions.open` 在 0.1.7+ 已被移除 —— 该功能**静默失效,用户点通知没反应却无从察觉**。
146
- > 详见 `CARD.md` 的 §零之二。
147
-
148
- ---
149
-
150
- ## 已知限制
151
-
152
- - **仅 Windows**(Toast = WinRT,播放 = MCI,调用 Windows PowerShell 5.1)
153
- - **设置页真实渲染尚未验证**(代码已就绪、schema 结构已测,但未在宿主里看过界面)
154
- - **点通知跳会话依赖未文档化 API**(`uiWorkspace`),官方随时可能改;坏了会自动降级
155
- - `blocked`(回合被拦截)只用系统蜂鸣,不播失败语音 —— 因为语义是"被拦下"而非"失败"
156
- - **`fail` 语音包只覆盖 16 个基础音色**(103 个音色里的其余 87 个只有完成语音)。选到未覆盖的音色时,失败会在同池内换一个音色,不会哑掉、也不会播错语义
157
-
158
- ---
159
-
160
- ## 开发
161
-
162
- ### 跑测试
163
-
164
- ```powershell
165
- npm test # 主套件(纯 Node,不需要 DSH 宿主)
166
- npm run test:all # 全部(含 route 注入的两组)
167
- npm run test:route # 需要 --import loader 的接线测试
168
- npm run test:audio-wire
169
- ```
170
-
171
- **274 条测试。** 绝大多数是纯逻辑测试,克隆仓库后 `npm test` 即可跑。
172
-
173
- 少数用例需要真实的 DSH 宿主(用于验证 Cordis 上下文行为)。
174
- 找不到宿主时它们会**自动 skip** —— 注意 skip 不等于通过。
175
- 指定宿主路径:
176
-
177
- ```powershell
178
- $env:DSH_CORDIS_ENTRY = "<DSH 安装目录>\.runtime\node_modules\@deepseek-ai\cordis\lib\index.js"
179
- npm test
180
- ```
181
-
182
- ### 测试分层
183
-
184
- | 层次 | 内容 |
185
- |---|---|
186
- | 单元 | 音源选择、空闲门、配置校验、TTS 文案、http-guard 判定 |
187
- | 集成 | 真实 HTTP 服务器 + 真实 handler,覆盖请求/响应全链路 |
188
- | 实机 | 真实 Cordis 上下文(需宿主,无则 skip) |
189
- | 发布 | 构建发布包并断言被禁音色/第三方素材未进包 |
190
-
191
- 集成测试(`test/http-integration.test.mjs`)是 2026-10-18 加的,起因是
192
- 一次真实回归:给 `/consume` 加了"写操作必须 JSON"的防护,但客户端还在用
193
- GET —— 单元测试全绿,功能却断了。集成测试会读取客户端源码里的真实调用形状,
194
- 所以两边一旦不同步就会变红。
195
-
196
- ### CI
197
-
198
- `.github/workflows/ci.yml` 在每次 push / PR 时跑:
199
-
200
- - 单元测试(Node 20 / 22 / 24)
201
- - PowerShell 语法与 UTF-8 BOM 检查
202
- - 关键文件齐全 + npm 打包内容检查(含"被禁音色不得进包")
203
- - 版本一致性
204
-
205
- ### 变异测试
206
-
207
- 关键断言都做过变异验证(故意改坏代码确认测试变红)。例如:
208
-
209
- - 把 `consume` 的客户端调用改回 GET → E0/E1 变红
210
- - 把 `head` 的前缀剥离去掉 → E3 变红
211
- - 把 `verifyReload` 改成永远放行 → S2/S6/R8/R8b 变红
212
-
213
- ---
214
-
215
- ## 许可
216
-
217
- 代码以 MIT 发布。
218
- **语音文件不适用 MIT**,由 VOICEVOX 生成,各音色有其自身使用条款,
219
- 详见 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md)。
1
+ # dsh-notify-say
2
+
3
+ 给 [DeepSeek Harness](https://github.com/deepseek-ai) Desktop 用的通知插件:**任务跑完会说话**。
4
+
5
+ > 别的通知插件"叮"一声;这个会喊你"任务完成了"。
6
+ > 而且**子代理还在跑的时候,它不会骗你说完成了**。
7
+
8
+ 只支持 **Windows**。
9
+
10
+ ---
11
+
12
+ ## 目录
13
+
14
+ - [它解决什么问题](#它解决什么问题)
15
+ - [特性](#特性)
16
+ - [安装](#安装)
17
+ - [快速开始](#快速开始)
18
+ - [配置](#配置)
19
+ - [语音包](#语音包)
20
+ - [关于"跳回会话"](#关于跳回会话)
21
+ - [兼容性与降级](#兼容性与降级)
22
+ - [已知限制](#已知限制)
23
+ - [常见问题](#常见问题)
24
+ - [开发](#开发)
25
+ - [许可](#许可)
26
+
27
+ ---
28
+
29
+ ## 它解决什么问题
30
+
31
+ 你让 AI 跑一个较长任务,然后切去干别的。常见两种通知插件的毛病:
32
+
33
+ 1. **该响的时候不响** —— 主会话一轮结束就报"完成",但其实它派出的子代理还在跑,你回来发现没干完。
34
+ 2. **不该响的时候一直响** —— 每个子代理结束都弹一次,连环轰炸。
35
+
36
+ 本插件的做法:
37
+
38
+ - **空闲门(idle gate)**:主会话这轮结束、但仍有子代理或后台任务在跑时,**先不播**;等全部结束再播**一次**。超时兜底(默认 10 分钟),防子任务卡死导致永不播报。
39
+ - **按会话去抖**:同一会话默认 60 秒内只响一次。
40
+ - **失败单独提醒**:回合出错时播**日语道歉语音**(可选)—— 比"任务完成"更该让你立刻知道。
41
+
42
+ ---
43
+
44
+ ## 特性
45
+
46
+ | 特性 | 说明 |
47
+ |---|---|
48
+ | **语音播报** | 播放本地 wav,**不调用云端 TTS**。发布版自带 1 个音色,另 13 个可在设置页按需下载 |
49
+ | **空闲门** | 有在飞工作时不误报"完成",全部结束才播一次 |
50
+ | **五类事件** | 完成 / 出错 / 被拦截 / 待批准 / 要提问,各自独立开关 |
51
+ | **设置页 GUI** | 走官方 `Config` schema,在 DSH 设置页里直接改,**改完立即生效** |
52
+ | **命令行** | `tools/notify-config.ps1`,适合脚本化与排查 |
53
+ | **切回窗口时跳会话** | 通知时你不在前台 → 你切回来时自动跳到那个会话(见[下文](#关于跳回会话)) |
54
+ | **不装语音也能用** | 没有语音包 = Toast + 系统提示音,这是正常配置 |
55
+ | **许可先告知** | 下载音色前弹出条款确认,写明署名要求与官方条款链接 |
56
+ | **诊断导出** | 一键导出脱敏日志(用户名/路径已替换),方便提 Issue |
57
+ | **日志隐私分级** | 默认只记元数据,**不记台词正文**;要详细日志需手动开 debug |
58
+ | **检查更新** | 显示当前/最新版本,有新版时给出升级命令(**不自动更新**,见[下文](#有新版本了怎么办)) |
59
+
60
+ > **联网说明**:播放、通知、TTS 全部离线。只有**下载语音包**时需要访问 GitHub。
61
+ > 不下载语音包的话,这个插件不会联网。
62
+
63
+ ---
64
+
65
+ ## 安装
66
+
67
+ ### 前置
68
+
69
+ - DSH Desktop **0.1.7-rc.2 或更高**
70
+ - Windows(Toast 用 WinRT,播放用 MCI,调用 Windows PowerShell 5.1)
71
+
72
+ ### 方式一:插件页(推荐)
73
+
74
+ 在 DSH 的 **设置 → 插件** 里搜索 `dsh-notify-say` 安装。
75
+
76
+ ### 方式二:npm
77
+
78
+ ```
79
+ npm install dsh-notify-say
80
+ ```
81
+
82
+ ### 方式三:手工 link(本地开发)
83
+
84
+ 把本仓库目录链接进 profile:
85
+
86
+ ```
87
+ D:\Program Files (x86)\DSH\profiles\desktop\package.json
88
+ dependencies 里加: "dsh-notify-say": "link:<本仓库路径>"
89
+ dsh.profile.bundles 里加: "dsh-notify-say"
90
+ ```
91
+
92
+ 然后在该 profile 目录执行 `pnpm install`,重启 DSH。
93
+
94
+ ---
95
+
96
+ ## 快速开始
97
+
98
+ 装好之后**什么都不用配就能用**:任务完成时会弹 Toast + 播自带音色。
99
+
100
+ 想做更多,进 **DSH 设置 → 通知**:
101
+
102
+ | 想做的事 | 去哪 |
103
+ |---|---|
104
+ | 换音色 / 调音量 | 设置页「音色」「音量」 |
105
+ | 下载更多音色(13 个可选) | 设置页「语音包」→ 点「加载列表」→ 选一个点「下载」 |
106
+ | 只保留提示音、不要语音 | 音源改成「系统提示音」 |
107
+ | 出错时也要语音提醒 | 「出错」开关(默认已开) |
108
+ | 让子代理结束也提醒 | 「子代理」开关(默认关) |
109
+ | 少响一点 | 「同会话去抖」调大 |
110
+ | 看看有没有新版 | 高级区「版本与更新」→ 检查更新 |
111
+
112
+ ---
113
+
114
+ ## 配置
115
+
116
+ 四种来源,**优先级由低到高**(后者覆盖前者):
117
+
118
+ ```
119
+ 1. schema 默认值
120
+ 2. cordis.patch.yml 的 config
121
+ 3. DSH 设置页里改的值
122
+ 4. tools/notify-config.ps1 写的 storages/config.json
123
+ ```
124
+
125
+ > ⚠️ **注意语义**:一旦你在设置页改过某项,再改 `cordis.patch.yml` 里同一项**不再生效**。
126
+ > 这是 DSH 官方设计(用户层优先级更高),不是本插件的 bug。
127
+
128
+ ### 设置页
129
+
130
+ **DSH 设置 → 通知**。包含音源选择、音色、音量、增益、TTS 参数、五个事件开关、
131
+ 去抖与冷却、音源按事件覆盖、自定义音频、语音包管理、日志级别、诊断导出等。
132
+
133
+ 分常规区与「高级」折叠区:日常只用常规区,排查时才展开高级区。
134
+
135
+ ### 命令行
136
+
137
+ ```powershell
138
+ cd <插件目录>\tools
139
+
140
+ .\notify-config.ps1 -Show # 看当前生效值
141
+ .\notify-config.ps1 -Voice off # 静音(Toast 仍弹)
142
+ .\notify-config.ps1 -Volume 40
143
+ .\notify-config.ps1 -VoiceMode random
144
+ .\notify-config.ps1 -VoiceName ankomon
145
+ .\notify-config.ps1 -Disable aborted -Enable subagents
146
+ .\notify-config.ps1 -Clear # 交还控制权给设置页
147
+ ```
148
+
149
+ 改完**立即生效**,不需要重启 DSH。
150
+
151
+ ---
152
+
153
+ ## 语音包
154
+
155
+ 核心包只带**一个日语音色**(ずんだもん),安装包约 3.2 MB。
156
+
157
+ 另有 **13 个音色**可单独下载(每个约 1.7–3.0 MB,合计约 27 MB),
158
+ **在设置页里点几下就能装**,不需要命令行。
159
+
160
+ ### 怎么装
161
+
162
+ 1. **DSH 设置 → 通知 → 语音包** → 点「加载列表」
163
+ 2. 列表里会显示每个音色的名称、体积、署名要求
164
+ 3. 点「下载」→ **先弹出条款确认弹窗**(见下)→ 确认后开始下载
165
+ 4. 装好后在「音色」下拉里就能选到
166
+
167
+ ### 下载前会告知什么
168
+
169
+ 点下载会弹一个居中弹窗,写明:
170
+
171
+ - **署名要求**(例如 `VOICEVOX:ずんだもん`)—— 你用这些语音做的内容需要保留这个署名
172
+ - **官方条款链接**(可点开原文)
173
+ - 提示"下载后 zip 内也带 TERMS.md;你用它做的内容(视频、直播等)仍需守上述条款"
174
+
175
+ 这不是走形式:13 个音色里有 2 个因为条款**禁止再分发**被我们排除在外,
176
+ 1 个因为身份存疑(同名角色有多个)暂不收录。审核依据是官方条款原文,
177
+ 留档在 [`docs/audio-audit/`](docs/audio-audit/)。
178
+
179
+ > 需要说清楚:我们的审核结论是**依据官方通用条款**得出的,
180
+ > 不等于各权利人针对"独立 WAV 素材 ZIP 再分发"出具过专项授权。
181
+
182
+ ### 卸载
183
+
184
+ 设置页里点「卸载」即可,会删掉该音色整个目录。
185
+ **卸载不依赖网络** —— 离线时也能卸。
186
+
187
+ ### 已装的音色放哪
188
+
189
+ ```
190
+ %LOCALAPPDATA%\dsh-notify-say\voice-lines\<音色key>\
191
+ ```
192
+
193
+ 每个音色一个目录,卸载 = 删这一个目录。
194
+
195
+ ### 不装语音包也完全可用
196
+
197
+ 通知会退回 Windows Toast + 系统提示音。
198
+
199
+ ### 想自己做音色
200
+
201
+ 装 [VOICEVOX](https://voicevox.hiroshiba.jp/)(本地免费 TTS),启动引擎(默认 `http://127.0.0.1:50021`),
202
+ 然后按命名规则把合成好的 wav 放进对应目录:
203
+
204
+ ```
205
+ sounds/voice-lines/<key>~1.wav 完成
206
+ sounds/voice-lines/question/<key>~1.wav 提问
207
+ sounds/voice-lines/approval/<key>~1.wav 审批
208
+ sounds/voice-lines/fail/<key>~1.wav 出错
209
+ ```
210
+
211
+ (合成脚本不随本包发布 —— 它依赖本地 VOICEVOX 引擎与特定音色表,放进发布包只会误导。)
212
+
213
+ ---
214
+
215
+ ## 关于"跳回会话"
216
+
217
+ 这里有个容易误解的地方,说清楚:
218
+
219
+ **点击 Toast 本体只能把 DSH 窗口唤到前面,带不了会话 id。**
220
+ Windows 的 Toast 协议激活是一个固定串(`dsh://open`),没有地方塞会话 id。
221
+
222
+ **真正会"跳回会话"的是这个机制**:
223
+
224
+ ```
225
+ 通知发出时你不在前台 → 插件记下那个会话
226
+ 你切回 DSH 窗口 → 插件自动跳到那个会话
227
+ ```
228
+
229
+ 所以体验是:你在别处干活 → 听到"任务完成了" → 切回 DSH → **它已经帮你跳过去了**。
230
+
231
+ 相关开关(默认值偏保守):
232
+
233
+ | 开关 | 默认 | 说明 |
234
+ |---|---|---|
235
+ | 后台完成时跳转 | 开 | 通知时你不在前台 → 切回来时跳 |
236
+ | 前台完成时也跳 | 关 | 你本来就在看着,别乱动界面 |
237
+
238
+ 配置读不到时**两个都当作关**(宁可少跳一次,也不擅自动你的界面)。
239
+
240
+ ---
241
+
242
+ ## 兼容性与降级
243
+
244
+ 本插件的首要目标是**稳定**,所以每个依赖外部能力的地方都有降级路径:
245
+
246
+ | 能力 | 拿不到时怎么办 |
247
+ |---|---|
248
+ | `@deepseek-ai/schemastery`(生成设置页) | 不导出 `Config` → **设置页不出现,插件照常工作** |
249
+ | `uiWorkspace.openSession`(跳会话) | 不跳转,Toast 仍能唤出窗口(**退回旧行为**) |
250
+ | 语音包目录 | 回退系统提示音 |
251
+ | 网络(下载语音包时) | 显示失败原因并可重试;**已装音色不受影响** |
252
+ | `$DSH_HOME` 未设置 | 配置走 patch 默认值;不写任何状态文件 |
253
+
254
+ **不会出现"静默失效"**:每个降级都有明确行为,并有测试锁定。
255
+
256
+ ---
257
+
258
+ ## 已知限制
259
+
260
+ - **仅 Windows**(Toast = WinRT,播放 = MCI,调用 Windows PowerShell 5.1)
261
+ - **跳会话依赖未文档化 API**(`uiWorkspace`),官方随时可能改;坏了会自动降级为"只唤起窗口"
262
+ - `blocked`(回合被拦截)只用系统蜂鸣,不播失败语音 —— 语义是"被拦下"而非"失败"
263
+ - **失败语音只覆盖部分音色**:选到未覆盖的音色时,会在同池内换一个音色播,不会哑掉、也不会播错语义
264
+ - **开发期热重载是实验性功能**(`devReload`,默认关):它依赖 DSH/Cordis 内部结构与 Node 模块加载机制,
265
+ 能工作但不算稳定能力。用户不需要它 —— 那是给改插件源码的人用的
266
+ - **13 个音色的许可结论是条件性判断**(依据官方通用条款),不代表各权利人出具过专项授权
267
+
268
+ ---
269
+
270
+ ## 常见问题
271
+
272
+ **装了没声音?**
273
+ 按顺序查:① 设置页「音源」是不是「不发声」;② 「语音」开关是否关着;
274
+ ③ 「音量」是否拉到 0;④ 播放依赖 Windows PowerShell 5.1,被安全软件拦了会静音。
275
+ 设置页「诊断」区可以**导出脱敏诊断文件**,里面能看出每次播报的决策路径。
276
+
277
+ **会不会打扰我?**
278
+ 默认同会话 60 秒只响一次;「子代理」默认关(子代理结束不单独提醒)。
279
+ 觉得吵可以把「同会话去抖」调大,或直接关掉某类事件。
280
+
281
+ **会上传我的会话内容吗?**
282
+ 不会。通知文案是插件内置的固定句子(可自定义),播放也全在本地。
283
+ 默认日志只记"播了什么、成功与否",**不记台词正文**。
284
+ 唯一联网的地方是下载语音包(访问 GitHub)。
285
+
286
+ **提示"未能获取可下载列表"?**
287
+ 那是 GitHub 访问不通。**已装的音色照常能用**,卸载也能用(卸载不依赖网络)。
288
+ 网络恢复后点「重试」即可。
289
+
290
+ **为什么只有 13 个音色?**
291
+ VOICEVOX 有几十个角色,但每个的条款都要单独读原文核对。
292
+ 我们只收录**条款明确允许本插件这样分发**的,宁可少也不冒险。
293
+ 被排除的例子:有 2 个明确禁止再分发,1 个身份存疑。
294
+
295
+ **有新版本了怎么办?**
296
+
297
+ 设置页 → 高级 → **版本与更新** → 点「检查更新」。有新版时那里会显示版本号、
298
+ `CHANGELOG.md` 链接,以及一条升级命令(可一键复制)。
299
+
300
+ **插件不会自己更新自己。** 原因很实在:
301
+
302
+ - 装上你的机器后,插件不知道自己是通过 npm、GitHub 还是 `link:` 装的
303
+ - 正在运行的程序替换自己的文件,失败后很难恢复
304
+ - DSH 官方 CLI 已经能升级插件(`dsh plugin --profile <名字> update dsh-notify-say`)—— 重复实现没意义
305
+
306
+ 所以分工是:**插件负责告诉你有新版;你执行命令;DSH 完成升级。**
307
+ 更新后需要重启对应的 DSH profile。
308
+
309
+ > 如果你是从源码 `link:` 安装的(开发模式),插件会认出来并**不给命令** ——
310
+ > 那种情况请直接更新源码目录,用插件命令会覆盖你的源码。
311
+
312
+ **能加我喜欢的音色吗?**
313
+ 可以提 Issue。但要走审核流程(读官方条款原文、留档),不是加个下载链接的事。
314
+
315
+ ---
316
+
317
+ ## 开发
318
+
319
+ ### 跑测试
320
+
321
+ ```powershell
322
+ npm test # 主套件(纯 Node,不需要 DSH 宿主)
323
+ npm run test:all # 全部(含 route 注入的两组)
324
+ npm run test:route # 需要 --import loader 的接线测试
325
+ npm run test:audio-wire
326
+ ```
327
+
328
+ **374 条测试通过。** 绝大多数是纯逻辑测试,克隆仓库后 `npm test` 即可跑。
329
+
330
+ 少数用例需要真实的 DSH 宿主(用于验证 Cordis 上下文行为)。
331
+ 找不到宿主时它们会**自动 skip** —— 注意 skip 不等于通过。
332
+
333
+ ```powershell
334
+ $env:DSH_CORDIS_ENTRY = "<DSH 安装目录>\.runtime\node_modules\@deepseek-ai\cordis\lib\index.js"
335
+ npm test
336
+ ```
337
+
338
+ ### 测试分层
339
+
340
+ | 层次 | 内容 |
341
+ |---|---|
342
+ | 单元 | 音源选择、空闲门、配置校验、TTS 文案、http-guard 判定 |
343
+ | 集成 | 真实 HTTP 服务器 + 真实 handler,覆盖请求/响应全链路 |
344
+ | 行为 | 构造真实输入验证行为(如真实 ZIP 字节、真实目录) |
345
+ | 实机 | 真实 Cordis 上下文(需宿主,无则 skip) |
346
+ | 发布 | 构建发布包并断言被禁音色/第三方素材未进包 |
347
+
348
+ ### 为什么有这么多"防复发"测试
349
+
350
+ 这个项目踩过的坑多数是同一类:**代码看着对、测试也绿,但两者一起错**。所以后来改成:
351
+
352
+ - **构造真实输入**而不是检查源码里有没有某个字符串
353
+ (典型:ZIP 解压防护查了不存在的字段 `entry.size`,测试也在断言同一个错字段 → 一起绿)
354
+ - **状态更新全量扫描**而不是逐个手查
355
+ (典型:组件状态漏字段已发生 4 次,现在有 C43 静态扫描锁住)
356
+ - **变异验证**:故意改坏代码,确认测试真的会红
357
+
358
+ ### CI
359
+
360
+ `.github/workflows/ci.yml` 在每次 push / PR 时跑:
361
+
362
+ - 单元测试(Node 20 / 22 / 24)
363
+ - PowerShell 语法与 UTF-8 BOM 检查
364
+ - 关键文件齐全 + npm 打包内容检查(含"被禁音色不得进包")
365
+ - 版本一致性
366
+
367
+ ### 发版
368
+
369
+ ```powershell
370
+ .\tools\release.ps1 -Bump patch -PublishNpm
371
+ ```
372
+
373
+ 流程:升版本 → 跑测试 → 重建发布包 → **在发布包里再跑一次测试**
374
+ (这一步是必要的:开发目录与发布包的文件集不同,只在开发目录跑会"本地绿、线上红")
375
+ → 提交推送 → 可选发 npm。
376
+
377
+ `CHANGELOG.md` 由 `release-build.ps1` **自动生成**(从开发提交提取标题,
378
+ 过滤掉内部资料与 hash),随包发布。**请勿手工编辑**。
379
+
380
+ ---
381
+
382
+ ## 许可
383
+
384
+ 代码以 MIT 发布。
385
+
386
+ **语音文件不适用 MIT**,由 VOICEVOX 生成,各音色有其自身使用条款,
387
+ 详见 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md)。
388
+ 每个音色包内另有该音色的 `TERMS.md`。