# dsh-voice-notify [**简体中文**](README.md) | [English](README.en.md) [![check](https://github.com/TangAu-relife/dsh-voice-notify/actions/workflows/check.yml/badge.svg)](https://github.com/TangAu-relife/dsh-voice-notify/actions/workflows/check.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![platform: Windows](https://img.shields.io/badge/platform-Windows-0078d4.svg)](#安装) **一轮对话真正结束时,用中文语音播报一句提醒。** 给 DSH 用的宿主侧(Host half)插件:挂宿主原生的「轮次收尾」扩展点,随机播一条 随包内置的中文语音(晓晓 · 温暖,20 条叠词短句),不引任何第三方音频依赖。 ``` 主人主人,任务完成啦~ 都弄好啦,快来看看嘛~ 事情办得妥妥的,夸夸我嘛~ 报告报告,全部搞定啦~ 主人主人,我棒不棒呀~ 好啦好啦,全都做完啦~ 快夸夸我呀,我可厉害啦~ 叮咚,任务完成,撒花撒花~ 主人主人,辛苦你啦,也夸夸我嘛~ 收工收工,要不要歇一歇呀~ 办完啦办完啦,快来看看嘛~ 才不是特意为你做的呢,快收下~ 别太感动哦,我只是顺手做的~ 搞定啦搞定啦,主人要不要抱抱~ 忙完啦,主人记得喝水水哦~ 叮铃铃,任务交卷啦~ 夸夸我夸夸我,不然我要闹啦~ 圆满完成,给我一点掌声嘛~ 主人主人,累不累呀,歇一会儿嘛~ 做完啦,主人快摸摸我的头~ ``` --- ## 它做什么 | 行为 | 说明 | |---|---| | 挂接缝 | `agent/turn-stopping`(宿主 **serial** 扩展点,一轮真正收尾时派发) | | 放音 | 随机播一条内置 WAV;可选追加自己的语音目录 | | 不吵 | 子代理轮次默认**不响**;`minIntervalMs` 内不重复 | | 不阻塞 | `spawn` 后 `unref()`,立刻返回,绝不等它放完 | | 不致命 | 任何异常都吞掉只记日志 —— 提醒插件绝不能影响任务收尾 | | 可自证 | 从 apply / 收到事件 / 跳过原因 / spawn,到 PowerShell 的真实播放秒数,逐行落盘 | --- ## 安装 先拿到文件(方式 A 或 B),再跑 `install.ps1`(挂载方式一 或 方式二)。 ### 方式 A · 下载 Release 的 zip(不用装 git) 1. 去 [Releases](https://github.com/TangAu-relife/dsh-voice-notify/releases) 下载 `dsh-voice-notify-<版本>.zip` 2. 解压 —— 里面是一个 `dsh-plugin-voice-notify\` 文件夹,**已经是可直接安装的成品包** 3. 进这个文件夹跑一行: ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 ``` 如果 Windows 给下载来的脚本打了「来自 Internet」标记,先 `Get-ChildItem -Recurse -File | Unblock-File` 再跑(或者就用上面的 `-ExecutionPolicy Bypass`)。 装完**刷新一次设置页**,「设置 → 语音提醒」那一栏就出现了;之后**每轮对话真正收尾时自动播报**,不需要再做任何手工操作。 > zip 里是运行所需的全部内容:代码 + 20 条内置语音 + `install.ps1` + MIT 许可证。 > CI 配置、英文 README、界面截图只放在仓库里,不影响使用。 ### 方式 B · 从源码安装(git clone) ```powershell git clone https://github.com/TangAu-relife/dsh-voice-notify.git cd dsh-voice-notify ``` **要求**:Windows + PowerShell 5.1+、已装 DSH。放音走 .NET `SoundPlayer`(winmm), 目前只支持 Windows —— 非 Windows 平台上插件会打印一条警告并静默停用。 要自己重新合成语音,工作区里配套的 `speak.ps1`(在线 edge-tts,失败回退离线 piper) 不是本仓库的一部分,见下面「换成你自己的语音」。 ### 挂载方式一 · 守护热挂载(推荐,立即生效) ```powershell powershell -ExecutionPolicy Bypass -File .\install.ps1 # 首次安装:立即生效 powershell -ExecutionPolicy Bypass -File .\install.ps1 -Hot # 改了代码:不重启也生效 ``` 脚本做四件事,**全程不跑 pnpm**(因此不会扰动正在运行的 profile 依赖树): 1. 把插件**落地成一份带时间戳的真实副本**:`$DSH_HOME\plugins\voice-notify\deploy-\`; 2. 在 `\node_modules\` 建一个指向该副本的 **junction**,并清理本插件家族的旧 junction; 3. 把副本的包名改成实际使用的**说明符**(`-Hot` 时带时间戳,见下文「坑 3」); 4. 通过守护自己的接口 `POST /guardian/api/staged` **热挂载**,成功即转正 (写进 `$DSH_HOME/guardian/state.json` 的 `promoted`,以后每次启动自动恢复)。 ### 挂载方式二 · 正式名册(需要重启 DSH) ```powershell powershell -ExecutionPolicy Bypass -File .\install.ps1 -Mode roster ``` 等价于手工两步:把包名加进 profile `package.json` 的 `dependencies`(`link:` 指向落地副本) 与 `dsh.profile.bundles`。本包自带的 `cordis.patch.yml`(由 `package.json` 的 `dsh.bundle.patch` 声明)会在该 profile 里插入 `voice-notify` 行。**此方式需要重启 DSH**。 ### 卸载 ```powershell powershell -ExecutionPolicy Bypass -File .\install.ps1 -Uninstall # 移除条目 + junction powershell -ExecutionPolicy Bypass -File .\install.ps1 -Uninstall -Purge # 连落地副本一起删 ``` --- ## 配置 配置写在挂载条目的 `config` 里(守护接口的 POST 体,或名册 profile 的 patch 行): ```yaml - id: voice-notify name: dsh-voice-notify config: enabled: true # 总开关 includeSubagents: false # 子代理轮次是否也响 minIntervalMs: 4000 # 两条提醒的最小间隔(吸收同时收尾的多个轮次) clip: '' # 固定一条,如 'done-3';留空=随机 clipDir: '' # 额外语音目录,*.wav 一起进随机池 voiceScript: '' # 覆盖放音脚本(默认包内 lib/play.ps1) ``` --- ## 设置页(图形界面) ![设置页:固定语音的句子胶囊列表](docs/settings.png) 插件带**浏览器半侧**:在 **设置页里单开一栏**(`settings.section` 插槽,导航名「语音提醒」)。 - 总开关、子代理轮次是否也提醒、最小间隔(毫秒) - 固定语音(下拉框 + **可点选的句子胶囊列表**:点一下固定、双击试听,20 句一眼全看见)、额外语音目录、高级里的放音脚本 - 下拉框弹出层是**原生白底**,所以 `