前言¶
DeepSeek Harness(DSH)是「一切皆插件」的智能体开发框架,插件可以扩展会话生命周期、工具调用、UI 交互等。在开发或使用智能体时,常常需要明确的「当前任务结束」「需要用户决策」「新会话开始」等信号。dsh-completion-voice 插件通过微软 Edge 神经语音(晓伊声线)在三个关键时机播报语音提示,并附带左下角悬浮泡可一键静音/恢复。它依赖 Windows 自带环境,离线可用,不依赖第三方 TTS 服务。
插件定位¶
- 名称:dsh-completion-voice(GitHub 仓库名为 dsh-voice)
- 维护者:zhangjie-2007
- 分类:客户端
- 许可证:MIT
- 核心能力:在 DSH 会话的三个时机播报语音,支持自定义文本与声线,支持一键静音/恢复。
播报时机与默认行为¶
插件监听 DSH 的会话事件流与 cordis 生命周期事件,在以下三个时机触发播报:
1. 一轮任务真正结束 →「已完成当前任务」¶
- 触发条件:
turn/end事件,且event.data.reason.kind === 'completed',且非子代理会话,且不在静默窗口内(settleMs),且会话无 active goal。 - 播报文本:默认为「已完成当前任务」。
- 声线:默认使用微软 Edge 神经语音
zh-CN-XiaoyiNeural。 - 说明:
aborted、error、max-tokens、blocked等情况不会触发播报。
2. 需要你做选择 →「老大老大,等你做选择呢」¶
- 触发条件:
tool/call事件,且data.name匹配ask_user_question或exit_plan_mode;或approval/asked事件。 - 播报文本:默认为「老大老大,等你做选择呢」(第二个「老大」尾音拖长)。
- 声线:默认与任务完成一致,可通过
choiceVoice单独配置。 - 间隔限制:
choiceMinIntervalMs默认 3000 ms,防止同一问题被多次事件重复播报。 - 说明:该时机不做子代理 / goal /
settleMs过滤,越早提醒越好。
3. 开始一个新对话 → 按时间问候¶
- 触发条件:cordis 的
session/created事件。 - 播报内容:根据本机时间在四个时段中选择一句问候语(默认):
- 早段(5:00–10:59):早上好!有什么工作需要做吗?
- 中段(11:00–12:59):中午好!有什么工作需要做吗?
- 午段(13:00–17:59):下午好!有什么工作需要做吗?
- 晚段(18:00–次日 4:59):晚上好!有什么工作需要做吗?
- 声线:默认与任务完成一致,可通过
greetingVoice单独配置。 - 间隔限制:
greetingMinIntervalMs默认 15000 ms,避免同时恢复多个会话时连珠炮。 - 延时:
greetingDelayMs默认 500 ms,在会话创建到播报之间留一点时间。 - 过滤条件:默认跳过子代理会话;
header.isSeeded === true的恢复/分叉会话默认跳过(greetingSkipSeeded)。 - 预合成:插件加载时默认把四段问候语依次预合成到本地缓存,之后纯本地播放,无需联网。
4. 悬浮泡:一键静音 / 恢复¶
- 位置:页面左下角 40 px 小圆泡,与输入框发送按钮大小相当。
- 状态:粉色渐变 = 正在发声,灰色 = 已静音。
- 操作:点击切换,浮出小字「语音已开 🔔 / 语音已关 🔕」。
- 静音范围:三条提示音全部静音,不影响预合成缓存。
- 状态保存:写入
<cacheDir>\bubble-state.json,重启后保持。 - 拖拽:按住可拖到任意位置,位置记在浏览器
localStorage里。 - 开关音效:开启时为上行三连音 C6-E6-G6 + 高频闪光;关闭时为下行两音 G5-D5,均由浏览器 Web Audio 实时合成,无需联网。
- 配置:
showBubble: false可关闭气泡;此时路由仍注册,但页面不再注入。
接口(仅限回环地址、同源页面)¶
GET /dsh-completion-voice/api -> { ok: true, enabled: true, sound: true }
POST /dsh-completion-voice/api {"toggle":true} 或 {"enabled":false}
发声引擎与限制¶
- 支持引擎:
edge(默认):微软 Edge 神经语音,在线合成一次文本为 mp3,存本地缓存,之后本地播放,瞬时、离线可用。sapi:Windows 自带 SAPI(如 Microsoft Huihui),机械感强;当 Edge 合成失败时自动降级使用。- 播放方式:
- Edge:宿主进程
spawn一个隐藏的powershell.exe,用 WPFMediaPlayer播放 mp3。 - SAPI:通过
-EncodedCommand(UTF-16LE + base64)调用SAPI.SpVoice.Speak()。 - 系统要求:Windows。在 Linux/macOS 上插件正常加载,但只写日志、不出声。
- 网络依赖:Edge 合成只在第一次合成时需要(调用
api.msedgeservices.com),之后走本地缓存。 - 不使用浏览器
speechSynthesis:Electron 桌面端没有可用的 Web Speech 合成,中文语音基本读不出来。
文件结构¶
lib/plugin.mjs 插件入口(薄壳):每次带时间戳动态 import impl.mjs
lib/impl.mjs 真正的实现:事件过滤、缓存管理、播报调度
lib/edge-tts.mjs 无依赖 Edge 神经语音客户端(含 Sec-MS-GEC 计算)
lib/ws-client.mjs 极简 WebSocket 客户端(手动握手,自定义 Origin/UA)
lib/player.mjs Windows 播放:WPF MediaPlayer 放 mp3;SAPI 兜底朗读
lib/bubble.mjs 悬浮泡宿主侧:注入行 + /dsh-completion-voice/{bubble.js,api} 路由
lib/bubble-client.js 悬浮泡的浏览器脚本(原生 JS,无构建、无依赖)
安装与启用¶
本仓库根目录就是插件包本身(package.json 在根上),可直接从 GitHub 安装:
# HTTPS
dsh plugin --profile desktop add git+https://github.com/zhangjie-2007/dsh-voice.git
# 或者 SSH
dsh plugin --profile desktop add git+ssh://git@github.com/zhangjie-2007/dsh-voice.git
国内网络下 git+https:// 常被重置,推荐使用 SSH 方式(需已配置 GitHub SSH key)。
安装后,插件会在 apply 时往 <DSH_HOME>\logs\dsh-completion-voice.log 写一行 apply: enabled=… engine=…,看到这行即说明加载成功。
卸载¶
dsh plugin --profile desktop remove dsh-completion-voice
配置¶
默认值写在 lib/impl.mjs 的 DEFAULTS 里,实际生效的覆盖写在 profile 的 <DSH_HOME>\profiles\<profile>\cordis.patch.yml(按 id 匹配):
- id: dsh-completion-voice
name: dsh-completion-voice
config:
text: '已完成当前任务'
choiceText: '老大<prosody rate="-45%">老大</prosody>,等你做选择呢'
engine: edge
voice: zh-CN-XiaoyiNeural
主要配置项:
| 键 | 默认 | 含义 |
|---|---|---|
enabled |
true |
总开关 |
text |
'已完成当前任务' |
任务完成时的播报文本 |
announceOnChoice |
true |
是否播报「需要你做选择」 |
choiceText |
'老大<prosody rate="-45%">老大</prosody>,等你做选择呢' |
选择提示音的文本;留空则完全不播。支持内联 SSML |
choiceToolMatch |
'ask_user_question\|exit_plan_mode' |
哪些工具调用算「要做选择」(正则匹配,忽略大小写) |
announceOnApproval |
true |
权限确认(approval/asked)是否也算「要做选择」 |
choiceVoice |
'' |
选择提示音的声线;留空 = 沿用 voice |
choiceMinIntervalMs |
3000 |
两次「要做选择」播报的最小间隔(ms) |
announceOnSessionStart |
true |
开始新对话时是否按时间播报问候语 |
greetingMorning |
'早上好!有什么工作需要做吗?' |
早段(默认 5:00–10:59)文本;留空则不播 |
greetingNoon |
'中午好!有什么工作需要做吗?' |
中段(11:00–12:59)文本 |
greetingAfternoon |
'下午好!有什么工作需要做吗?' |
午段(13:00–17:59)文本 |
greetingEvening |
'晚上好!有什么工作需要做吗?' |
晚段(18:00–次日 4:59)文本 |
greetingHours |
'5,11,13,18' |
四段起始小时,格式 "早,中,午,晚",必须是 4 个 0–23 的整数(可跨零点) |
greetingVoice |
'' |
问候语的声线;留空 = 沿用 voice |
greetingDelayMs |
500 |
会话创建到播报之间的延时(ms) |
greetingMinIntervalMs |
15000 |
两次问候之间的最小间隔(ms) |
greetingSkipSeeded |
true |
恢复 / 分叉出来的会话(header.isSeeded)不问候 |
greetingPrefetchAll |
true |
后台把四段问候语都预合成好(串行,1.8 s 间隔) |
engine |
'edge' |
'edge' = Edge 神经语音(在线合成 + 本地缓存);'sapi' = 系统本地语音 |
voice |
'zh-CN-XiaoyiNeural' |
Edge 声线名 |
rate |
0 |
语速:Edge 用百分比(-20 = 慢 20%);engine: sapi 时按 /10 映射到 SAPI 的 -10..10 |
pitch |
0 |
音调偏移(Hz),仅 Edge |
典型用法¶
- 在 Windows 上安装后,插件默认启用 Edge 神经语音,在任务完成、需要选择、新会话开始时分别播报对应语音,并显示悬浮泡。
- 如需关闭某条提示音,可留空对应文本(
text、choiceText、greetingMorning/Noon/Afternoon/Evening)或设enabled: false。 - 如需修改声线,可配置
voice(Edge 声线名)或engine: sapi使用系统语音。 - 如需自定义文本(如将「已完成当前任务」改为「任务结束」),可在
cordis.patch.yml中修改text。 - 如需完全静音,可关闭
showBubble或通过接口POST /dsh-completion-voice/api {"enabled":false}一次性关闭所有播报。
适用场景与注意¶
- 适用场景:需要在 DSH 会话中明确「任务结束」「需要决策」「新会话开始」等信号的开发者或使用者;希望获得类似真人感语音反馈的场景。
- 系统要求:当前仅支持 Windows。在 Linux/macOS 上插件正常加载,但只写日志、不出声。
- 权限说明:插件以当前 DSH 进程权限运行,安装前建议检查源码与许可证(MIT)。
- 配置覆盖:实际生效的配置覆盖写在 profile 的
cordis.patch.yml中,按id: dsh-completion-voice匹配。
总结¶
dsh-completion-voice 在 DSH 的三个关键时机用微软 Edge 神经语音播报提示,支持自定义文本与声线,提供悬浮泡一键静音/恢复。它依赖 Windows 环境,离线可用,不依赖第三方 TTS 服务,适合需要在智能体会话中获得明确语音反馈的场景。
- 目录页:https://www.skillhub.cn/plugins/zhangjie-2007/dsh-voice
- GitHub:https://github.com/zhangjie-2007/dsh-voice