Bundle
dsh-sound-notify
DSH web plugin: play a chime when a turn completes or your input (approval / question / plan review) is needed — foreground or background.
- Source
- Vuitier
- License
- MIT
- Updated
- Updated 8 hours ago
Readme
# dsh-sound-notify 🔔
> [DeepSeek Harness (DSH)](https://www.npmjs.com/package/@deepseek-ai/dsh) Web 插件:**回合完成**与**需要人工介入**(审批 / 提问 / plan 审阅)时播放提示音。
挂机跑长任务、切去干别的时候,不用盯着屏幕等 —— 任务跑完「叮」一声,DSH 需要你拍板时「叮叮」两声。

-success)


## ✨ 功能
- **两种事件音**:回合完成(单声)、需要人工介入(审批 / 提问 / plan 审阅)
- **自选音频**:在设置页直接选本地 mp3 / wav,带「▶ 试听」;选完存进 `settings.yaml`,**随 DSH 配置快照同步到其他机器**
- **内置合成音回退**:没选文件也能响(Web Audio 合成的单叮 / 双叮)
- **标题闪烁提醒**:事件发生时标签页标题闪「🔔 任务完成 / 需要你的介入」,声音被浏览器拦时的视觉兜底
- **不分前台后台**:事件发生即播放
- **零构建**:手写双半插件(宿主半 + 浏览器半),没有打包步骤,`git clone` 即用
## 📦 安装
前置:已安装 DSH `>= 0.1.0-rc.7`(在 0.1.0-rc.7 上端到端验证通过)。
```powershell
# 方式一:直接从 GitHub 安装
dsh plugin --profile web add github:Vuitier/dsh-sound-notify
# 方式二:克隆后本地安装
git clone https://github.com/Vuitier/dsh-sound-notify.git
dsh plugin --profile web add .\dsh-sound-notify
```
`dsh plugin add` 底层转发给 pnpm,npm 包名 / git URL / `github:` 短写 / 本地路径都能用。装完后**重启一次正在跑的 dsh web 实例**(新开的页面才会装载本插件)。
验证是否装好:浏览器访问 `http://127.0.0.1:3080/plugins/dsh-sound-notify/client.js`,返回 JS 源码即已挂载。
## 🚀 使用
打开 DSH Web → **设置 → 提示音**:
| 设置项 | 默认 | 说明 |
| --- | --- | --- |
| 启用提示音 | 开 | 总开关 |
| 音量 | 0.6 | 0 – 1 |
| 回合完成时提示 | 开 | 关掉只保留介入提醒 |
| 完成提示音 | — | 选本地音频文件(建议 1MB 内),带试听 / 清除 |
| 需要人工介入时提示 | 开 | 审批 / 提问 / plan 审阅时提醒 |
| 介入提示音 | — | 同上,独立选文件 |
| 标签页标题闪烁提醒 | 开 | 视觉兜底 |
| 无音频文件时用内置合成音 | 关 | 没选文件时的 Web Audio 回退 |
也可以直接改 `$DSH_HOME/settings.yaml`(一般在 `~/.dsh/settings.yaml`):
```yaml
dsh-sound-notify:
enabled: true
volume: 0.8
useSynthFallback: true # 不选文件,用内置合成音
```
> 提示:浏览器的自动播放策略要求页面有过一次用户交互才允许出声。若首次没响,点一下页面任意处再试;标题闪烁不受此限制。
## 🔍 工作原理
**双半架构**(DSH 插件标准形态,本插件零构建、两个源文件):
- `lib/index.js` — 宿主半:只做一件事,向设置服务注册 `dsh-sound-notify` 命名空间的 schema(默认值 + 用户文档分节)。
- `lib/client.js` — 浏览器半:监听会话状态、检测边沿、播放音频、渲染设置页区块。
**信号判定**(边沿检测,同一快照内同类边沿合并、每事件至多一声,介入优先):
| 信号 | 触发条件 |
| --- | --- |
| 回合完成 | 会话 `running` 真→假,**或** `completed` 假→真(与侧边栏绿色「完成」提醒同源,双口径保险) |
| 需要介入 | `pendingInteraction` 空→非空 |
**双通道监控**:`ctx.sessions.list` 的 store 订阅 + 每 2s 轮询 `getSnapshot()`,避免个别环境下订阅事件不触发。
**音源优先级**:设置页自选文件(data URL,存 `settings.yaml`,随快照同步)→ 开启回退时的 Web Audio 合成音。
## 📁 目录结构
```
dsh-sound-notify/
├── lib/
│ ├── index.js # 宿主半:注册设置 schema
│ └── client.js # 浏览器半:监听 + 播放 + 设置页 UI
├── sounds/ # 示例提示音(占位,可自选文件替代)
│ ├── turn.wav # 单叮 880Hz
│ └── intervention.wav # 双叮 660→880Hz
├── scripts/
│ ├── test-client.mjs # vm 模拟浏览器装载,全链路自测(无需 DSH 实例)
│ ├── sound-e2e.mjs # Playwright 无头端到端(需测试实例,可选)
│ └── gen-default-sounds.mjs # 重新生成示例 wav
├── cordis.patch.yml # bundle 挂载声明(dsh plugin add 的官方通道)
└── package.json
```
## 🛠 开发与测试
零构建:改完 `lib/*.js` 保存即生效(需刷新页面)。常用验证:
```powershell
# 快速自测:vm 模拟装载 client.js,验证注册/apply/边沿检测/播放全链路
node scripts/test-client.mjs
# 重新生成示例音色
node scripts/gen-default-sounds.mjs
# 端到端(可选):需要一个跑在 3081 的 DSH web 测试实例 + playwright
# DSH_E2E_URL=http://127.0.0.1:3081/ node scripts/sound-e2e.mjs
```
### 插件开发备忘(踩坑记录)
写给后来的 DSH 插件作者,都是实测换来的:
- **会话快照的真实形状**:`ctx.sessions.list.getSnapshot()` 返回 `{ ids, byId, current, phase, ... }` —— **没有 `items` 字段**。entry 带 `running` / `pendingInteraction` / `completed`。按旧类型遍历 `items` 会导致永远监听不到任何变化(本项目最初「无声 bug」的根因)。
- **客户端 ctx 是白名单代理**:`inject` 必须声明全部要访问的服务,`typeof` 探测也算访问、会抛 `cannot get property ... without inject`。
- **slot 注册签名**:`ctx.slots.inject(key, () => ctx.slots.register({ name, id, order, label }, Component))` —— 第一个参数是对象(`name` 是 slot 名),组件是第二个参数;包一层 `slots.inject` 等宿主声明该 slot。
- **裸 `setTimeout` / `setInterval` 可能被遮蔽**:用 `window.setTimeout` / `window.setInterval`(或 try/catch 包裹)。
- 宿主半的 schema 库是 `@deepseek-ai/schemastery`(注意不是裸 `schemastery`)。
- 浏览器半经 `window.__ModuleLoader__.load({ id, factory })` 注册,id 必须与包名一致;`/plugins/<id>/client.js` 路由只服务 client.js,不能放任意静态文件。
## ⚠️ 已知限制
- 自选音频以 data URL 存 `settings.yaml`:文件越大配置越大(1MB mp3 ≈ 1.4MB 文本),建议选短音频。
- 首次安装后需重启一次 web 实例才会装载。
- 浏览器自动播放策略:页面从未交互过时首次播放可能被拦(有合成音与标题闪烁兜底)。
## 📄 License
[MIT](./LICENSE)
Install
dsh plugin --profile web add github:Vuitier/dsh-sound-notify
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-sound-notify from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.