dsh-speak 1.0.0 → 1.3.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/LICENSE +21 -21
- package/README.md +289 -186
- package/README.zh-CN.md +274 -177
- package/adapters/dsh/install.ps1 +81 -81
- package/adapters/dsh/speech-hook.js +142 -133
- package/cordis.patch.yml +5 -0
- package/docs/DESIGN.md +270 -245
- package/docs/DESIGN.zh-CN.md +253 -232
- package/engine/speak.ps1 +76 -76
- package/engine/speak.sh +89 -0
- package/engine/speech-prompt.ps1 +22 -22
- package/engine/speech-summary.ps1 +27 -27
- package/package.json +52 -43
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Alan2Z
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alan2Z
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,186 +1,289 @@
|
|
|
1
|
-
# dsh-speak 🔊 — Voice announcements for AI coding harnesses
|
|
2
|
-
|
|
3
|
-
**English** · [中文](README.zh-CN.md)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
1
|
+
# dsh-speak 🔊 — Voice announcements for AI coding harnesses
|
|
2
|
+
|
|
3
|
+
**English** · [中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
Let your agent **tell you** when a long task is done — no more staring at the screen.
|
|
8
|
+
|
|
9
|
+
dsh-speak reads the final assistant reply aloud through system speech synthesis —
|
|
10
|
+
on Windows using natural voices (Windows 11 built-in, or
|
|
11
|
+
[NaturalVoiceSAPIAdapter] on Windows 10) with graceful fallback to stock voices;
|
|
12
|
+
on macOS using the built-in `say` (can follow a Siri natural voice). It was built
|
|
13
|
+
for [DeepSeek Harness](https://github.com/deepseek-ai/dsh)
|
|
14
|
+
and is structured so any harness can plug in.
|
|
15
|
+
|
|
16
|
+
> **Project status**: this project exists only to provide an **already-verified
|
|
17
|
+
> solution** for users who want their harness to speak. Barring unexpected
|
|
18
|
+
> circumstances, it will not be updated further.
|
|
19
|
+
|
|
20
|
+
## TL;DR — install for DSH
|
|
21
|
+
|
|
22
|
+
1. Install the package into your web profile (pick one):
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
dsh plugin --profile web add dsh-speak
|
|
26
|
+
# or, without pnpm:
|
|
27
|
+
npm install --prefix "$env:USERPROFILE\.dsh\profiles\web" dsh-speak
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
On macOS (bash):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install --prefix "$HOME/.dsh/profiles/web" dsh-speak
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
2. Append to `~/.dsh/profiles/web/cordis.patch.yml`:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- insert:
|
|
40
|
+
- id: speech-hook
|
|
41
|
+
name: 'dsh-speak'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
3. Restart the DSH web app — replies are now announced aloud.
|
|
45
|
+
|
|
46
|
+
> **Let your agent do it?** Paste this repo URL
|
|
47
|
+
> (`https://github.com/Alan2Z/dsh-speak`) into your DSH session and ask it to
|
|
48
|
+
> install the plugin — your agent follows this very README. Approving the
|
|
49
|
+
> out-of-workspace writes (`~/.dsh`) is all that's needed.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
harness event (DSH session event / Claude Code Stop hook / anything)
|
|
53
|
+
│
|
|
54
|
+
▼ adapters/… (harness-specific trigger: filter, throttle, cancel)
|
|
55
|
+
▼ engine/speak.ps1 / speak.sh (harness-agnostic: clean text → SAPI5 / say)
|
|
56
|
+
▼ 🔊 you hear the final reply
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
|
|
61
|
+
- **Automatic**: DSH web plugin watches the session event stream and announces the
|
|
62
|
+
final reply (skips reasoning/tool-call narration, merges multi-step messages).
|
|
63
|
+
- **Best-effort**: never throws, never blocks the harness, never breaks a session.
|
|
64
|
+
- **Natural voices**: Windows prefers natural voices — Windows 11 built-in packs,
|
|
65
|
+
or voices registered via NaturalVoiceSAPIAdapter on Windows 10 (e.g. Xiaoxiao);
|
|
66
|
+
macOS uses the system reading voice (Siri natural voices on recent macOS). Both
|
|
67
|
+
fall back to any installed voice.
|
|
68
|
+
- **Robust text cleaning**: strips markdown/URLs/emoji that make speech synthesis
|
|
69
|
+
fail silently, and guards the adapter's per-utterance character ceiling.
|
|
70
|
+
- **Portable engine**: any process can speak with one line:
|
|
71
|
+
Windows `powershell -File speak.ps1 -Text "你好"` / macOS `./speak.sh -t "你好"`.
|
|
72
|
+
|
|
73
|
+
## Prerequisites
|
|
74
|
+
|
|
75
|
+
Windows:
|
|
76
|
+
|
|
77
|
+
- Windows 10 or 11, PowerShell (any recent version).
|
|
78
|
+
- Natural voices:
|
|
79
|
+
- **Windows 11**: natural voice packs are built into the system — no extra
|
|
80
|
+
installation. Enable/switch them in *Settings → Accessibility → Narrator* or
|
|
81
|
+
*Settings → Time & Language → Speech*.
|
|
82
|
+
- **Windows 10**: install
|
|
83
|
+
[NaturalVoiceSAPIAdapter](https://github.com/gexgd0419/NaturalVoiceSAPIAdapter)
|
|
84
|
+
and use its VoiceDownloader to download the natural voice pack(s) you want
|
|
85
|
+
(Chinese or any other language).
|
|
86
|
+
- Without natural voices, the engine falls back to a stock voice (e.g. Huihui).
|
|
87
|
+
|
|
88
|
+
macOS:
|
|
89
|
+
|
|
90
|
+
- macOS (Apple Silicon or Intel), built-in `say` command — **no extra software**.
|
|
91
|
+
- Chinese voices: see the [macOS](#macos) section (incl. the Siri natural-voice
|
|
92
|
+
picker and its pitfalls).
|
|
93
|
+
|
|
94
|
+
## Quick start — DSH
|
|
95
|
+
|
|
96
|
+
### Option A — npm plugin (recommended)
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
# 1. install the plugin into your web profile (adds dsh-speak to
|
|
100
|
+
# ~/.dsh/profiles/web/package.json dependencies)
|
|
101
|
+
dsh plugin --profile web add dsh-speak
|
|
102
|
+
|
|
103
|
+
# 2. register it in ~/.dsh/profiles/web/cordis.patch.yml
|
|
104
|
+
# (for npm packages the bare package name is used — no file:/// URL needed):
|
|
105
|
+
# - insert:
|
|
106
|
+
# - id: speech-hook
|
|
107
|
+
# name: 'dsh-speak'
|
|
108
|
+
|
|
109
|
+
# 3. restart the DSH web app — replies are now announced automatically
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
> **No pnpm?** `dsh plugin` forwards to pnpm, which is not installed on every
|
|
113
|
+
> machine. The exact same install can be done with npm directly:
|
|
114
|
+
>
|
|
115
|
+
> ```powershell
|
|
116
|
+
> npm install --prefix "$env:USERPROFILE\.dsh\profiles\web" dsh-speak
|
|
117
|
+
> ```
|
|
118
|
+
|
|
119
|
+
The engine ships inside the package (`node_modules/dsh-speak/engine/`), so no extra
|
|
120
|
+
copying is needed.
|
|
121
|
+
|
|
122
|
+
### Option B — file install (no npm needed)
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
# 1. clone
|
|
126
|
+
git clone https://github.com/Alan2Z/dsh-speak.git
|
|
127
|
+
cd dsh-speak
|
|
128
|
+
|
|
129
|
+
# 2. one-command install: copies engine + plugin, registers in cordis.patch.yml
|
|
130
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File adapters\dsh\install.ps1
|
|
131
|
+
|
|
132
|
+
# 3. verify the engine speaks
|
|
133
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File "$env:USERPROFILE\.dsh\hooks\speak.ps1" -Text "你好,语音播报已就绪。"
|
|
134
|
+
|
|
135
|
+
# 4. restart the DSH web app — replies are now announced automatically
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
What the file installer did:
|
|
139
|
+
|
|
140
|
+
| file | destination |
|
|
141
|
+
| ---- | ----------- |
|
|
142
|
+
| `engine/*.ps1` | `%USERPROFILE%\.dsh\hooks\` |
|
|
143
|
+
| `adapters/dsh/speech-hook.js` | `%USERPROFILE%\.dsh\profiles\web\plugins\` |
|
|
144
|
+
| registration entry | appended to `%USERPROFILE%\.dsh\profiles\web\cordis.patch.yml` (backed up first) |
|
|
145
|
+
|
|
146
|
+
## macOS
|
|
147
|
+
|
|
148
|
+
The same adapter runs natively on macOS — the plugin auto-detects the platform and
|
|
149
|
+
calls `engine/speak.sh` (the built-in `say` command) instead of `speak.ps1`.
|
|
150
|
+
**Since 1.2.0 the macOS engine ships in the npm package** — no extra software.
|
|
151
|
+
|
|
152
|
+
### Install (npm — same as Windows)
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# 1. install into your web profile (no pnpm needed — only `dsh plugin` requires it)
|
|
156
|
+
npm install --prefix "$HOME/.dsh/profiles/web" dsh-speak
|
|
157
|
+
|
|
158
|
+
# 2. register in ~/.dsh/profiles/web/cordis.patch.yml (bare package name — no file:/// URL):
|
|
159
|
+
# - insert:
|
|
160
|
+
# - id: speech-hook
|
|
161
|
+
# name: 'dsh-speak'
|
|
162
|
+
|
|
163
|
+
# 3. no restart needed — the patch watcher hot-reloads; pure-text replies are
|
|
164
|
+
# announced after ~1.5 s (tool-calling replies are intentionally not announced)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
> With pnpm installed, `dsh plugin --profile web add dsh-speak` works identically.
|
|
168
|
+
|
|
169
|
+
### Voices (important — two pitfalls)
|
|
170
|
+
|
|
171
|
+
- By default the engine follows the **system reading voice** (*Settings →
|
|
172
|
+
Accessibility → Spoken Content → System Voice*). On **macOS 26** that picker has
|
|
173
|
+
an **ⓘ circle icon** next to it — click it for the full voice list; the plain
|
|
174
|
+
dropdown does **not** contain the Siri natural voices. Pick e.g. "普通话 Siri
|
|
175
|
+
声音1(男声)" there.
|
|
176
|
+
- **Siri voice** (*Settings → Siri → Voice*) and the system reading voice are
|
|
177
|
+
**two independent settings**; Siri voices are not exposed to `say -v '?'` and
|
|
178
|
+
cannot be selected by name — they only work as the system default.
|
|
179
|
+
- ⚠️ **Pitfall 1 (reproduced)**: opening the "Spoken Content / Siri Voice" settings
|
|
180
|
+
pane — **even without changing anything** — drifts/resets the system voice to the
|
|
181
|
+
classic "婷婷 (Tingting)". If the voice suddenly changes, re-pick it via the ⓘ
|
|
182
|
+
entry.
|
|
183
|
+
- ⚠️ **Pitfall 2**: the log lives at `$TMPDIR/dsh-speech-hook.log`
|
|
184
|
+
(`os.tmpdir()` — **not** `/tmp`).
|
|
185
|
+
- Use `-v Eddy|Flo|Tingting` to force a specific voice (`say -v '?'` lists them).
|
|
186
|
+
- `say` has no volume flag — volume follows the system output volume.
|
|
187
|
+
|
|
188
|
+
### Test the engine alone (no DSH needed)
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
curl -sfL -o ~/speak.sh "https://cdn.jsdelivr.net/gh/Alan2Z/dsh-speak@main/engine/speak.sh"
|
|
192
|
+
chmod +x ~/speak.sh
|
|
193
|
+
~/speak.sh -t "你好,Mac 版语音播报测试"
|
|
194
|
+
~/speak.sh -t "测试" -v Eddy -r 200 # explicit voice + rate
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Quick start — Claude Code
|
|
198
|
+
|
|
199
|
+
Register the Stop hook in `~/.claude/settings.json`:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"hooks": {
|
|
204
|
+
"Stop": [
|
|
205
|
+
{
|
|
206
|
+
"hooks": [
|
|
207
|
+
{
|
|
208
|
+
"type": "command",
|
|
209
|
+
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\\path\\to\\dsh-speak\\adapters\\claude-code\\stop-hook.ps1"
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Quick start — any other harness
|
|
219
|
+
|
|
220
|
+
Call the engine directly from your agent / wrapper / script:
|
|
221
|
+
|
|
222
|
+
```powershell
|
|
223
|
+
# announce a one-liner
|
|
224
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File engine\speak.ps1 -Text "构建完成"
|
|
225
|
+
|
|
226
|
+
# announce a long summary (from a file)
|
|
227
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File engine\speech-summary.ps1 -Text "…"
|
|
228
|
+
|
|
229
|
+
# ask for user attention (blocking, for prompts/approvals)
|
|
230
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File engine\speech-prompt.ps1 -Text "请做出选择"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Configuration
|
|
234
|
+
|
|
235
|
+
Engine parameters (see [docs/DESIGN.md](docs/DESIGN.md#5-configuration-reference)):
|
|
236
|
+
|
|
237
|
+
```powershell
|
|
238
|
+
speak.ps1 -Text "…" -Volume 50 -Rate 1 -MaxChars 300 -LongTextMessage "本次播报内容较长,请自行阅读。"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
DSH plugin environment variables:
|
|
242
|
+
|
|
243
|
+
| var | default | meaning |
|
|
244
|
+
| --- | ------- | ------- |
|
|
245
|
+
| `DSH_SPEAK_ENGINE` | empty (auto-resolved) | engine path override; otherwise resolved as `<package>/engine/<platform script>` → `~/.dsh/hooks/<platform script>` (Windows `speak.ps1` / macOS `speak.sh`) |
|
|
246
|
+
| `DSH_SPEAK_THROTTLE_MS` | `1500` | merge delay before announcing |
|
|
247
|
+
|
|
248
|
+
## Troubleshooting
|
|
249
|
+
|
|
250
|
+
| symptom | cause | fix |
|
|
251
|
+
| ------- | ----- | --- |
|
|
252
|
+
| No sound at all, no error | no natural voice enabled/installed | Win11: enable a natural voice in *Settings → Narrator / Speech*; Win10: install NaturalVoiceSAPIAdapter + a voice pack. Test `speak.ps1` directly |
|
|
253
|
+
| Long replies never spoken | adapter per-`Speak` character ceiling | already guarded at 300 chars — lower `-MaxChars` if needed |
|
|
254
|
+
| Emoji-heavy text silent | SAPI fails silently on emoji | already stripped by the engine |
|
|
255
|
+
| Plugin not loading | raw Windows path as plugin name | use the `file:///C:/…` URL form (installer does this) |
|
|
256
|
+
| macOS: voice suddenly became "婷婷" | opening the "Spoken Content / Siri Voice" pane drifted the system voice | re-pick via Settings → Accessibility → Spoken Content → System Voice → ⓘ entry |
|
|
257
|
+
| macOS: no log at `/tmp` | `os.tmpdir()` is `/var/folders/.../T`, not `/tmp` | log is at `$TMPDIR/dsh-speech-hook.log` |
|
|
258
|
+
|
|
259
|
+
Plugin diagnostics: Windows `%TEMP%\dsh-speech-hook.log`; macOS `$TMPDIR/dsh-speech-hook.log`
|
|
260
|
+
|
|
261
|
+
## Repository layout
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
engine/ harness-agnostic speech engine (PowerShell + SAPI5 / bash + say)
|
|
265
|
+
speak.ps1 / speak.sh clean + speak (the only seam any adapter needs)
|
|
266
|
+
speech-prompt.ps1 blocking short announcement
|
|
267
|
+
speech-summary.ps1 blocking reply-summary announcement
|
|
268
|
+
adapters/
|
|
269
|
+
dsh/ DSH web plugin + one-command installer
|
|
270
|
+
speech-hook.js session-event trigger (throttle + tool-call cancel)
|
|
271
|
+
install.ps1 copies + registers + backs up
|
|
272
|
+
claude-code/
|
|
273
|
+
stop-hook.ps1 Claude Code Stop hook trigger
|
|
274
|
+
docs/
|
|
275
|
+
DESIGN.md full design rationale, pitfalls, extension guide
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Writing a new adapter
|
|
279
|
+
|
|
280
|
+
Three reference patterns exist: **event-stream** (DSH), **stop-hook** (Claude Code),
|
|
281
|
+
**agent-called** (`speech-summary.ps1` from a shell). In every case the adapter only
|
|
282
|
+
needs to: capture the *final reply text* → invoke the engine. See
|
|
283
|
+
[docs/DESIGN.md §7](docs/DESIGN.md#7-extending).
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
MIT — see [LICENSE](LICENSE).
|
|
288
|
+
|
|
289
|
+
[NaturalVoiceSAPIAdapter]: https://github.com/gexgd0419/NaturalVoiceSAPIAdapter
|