Bundle
dsh-sound-notifier
DSH bundle: plays distinct chimes in the Web UI on message received, thinking start, tool call, and turn end.
- Source
- Zhengshuji
- License
- MIT
- Updated
- Updated 7 days ago
Readme
# dsh-sound-notifier
Sound alerts for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH): the Web UI plays a distinct chime when the agent receives a message, starts thinking, calls a tool, or finishes a turn.
Installed as an official DSH **bundle** (`dsh.bundle` + `dsh.client`), so it loads automatically on every DSH start — no per-session activation required.
## Features
| Moment | Event | Sound |
|---|---|---|
| Message received | `agent/inbox/inserted` | two short pops (660 Hz → 990 Hz) |
| Thinking starts | first `reasoning-delta` in `llm/stream` | rising sweep (392 → 784 Hz, triangle) |
| Tool invoked | `tools/pre-execute` | crisp double tick (233 Hz → 311 Hz, triangle) |
| Turn ended | `agent/turn-stopping` | major-triad arpeggio (C5–E5–G5) |
- Sounds are synthesized with the Web Audio API — no audio assets.
- Only top-level sessions chime; subagent/workflow activity stays silent.
- Already-played events are not replayed after a page refresh (`sessionStorage`).
## How it works
The plugin has two halves:
- **Host half** (`index.js`) listens to DSH events, appends them to a bounded queue (256 entries), and serves them over a `GET /sound-alerts/events?after=N` endpoint registered through the official `webServer` service.
- **Browser half** (`client.js`) is a standard `dsh.client` plugin: the client-modules table injects it into `window.__DSH_BOOT__`, it polls the endpoint every 400 ms, and plays the matching chime.
## Requirements
- DeepSeek Harness with the Web UI (`dsh web` / `dsh --profile web`)
- pnpm (the `dsh plugin` command forwards to pnpm)
## Installation
From the root of your `deepseek-harness` checkout:
```sh
pnpm dsh plugin --profile web add /path/to/dsh-sound-notifier
```
This links the directory into `~/.dsh/profiles/web`, and because `package.json` declares `dsh.bundle`, it is appended to the profile's `dsh.profile.bundles` automatically.
**Restart DSH** (stop the running `pnpm dsh web` and start it again) for the plugin to load.
Verify the composed config without restarting:
```sh
pnpm dsh --profile web --dump-config # shows a "# == dsh-sound-notifier" layer
```
Install directly from GitHub (add the printed package key to the profile's `pnpm-workspace.yaml` `allowBuilds` on first try, see the [official publishing guide](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md)):
```sh
pnpm dsh plugin --profile web add github:your-name/dsh-sound-notifier
```
## Uninstall
```sh
pnpm dsh plugin --profile web remove dsh-sound-notifier
```
## Customizing sounds
Edit the `SOUNDS` table in `client.js`:
| Option | Meaning |
|---|---|
| `freq` | start frequency (Hz) |
| `endFreq` | sweep target frequency (Hz); omit for no sweep |
| `dur` | duration (seconds) |
| `type` | waveform: `sine` / `triangle` / `square` / `sawtooth` |
| `gain` | volume (0–1) |
| `delay` | relative delay (seconds), for sequencing multiple notes |
The local `link:` install reads the file directly — save and restart DSH.
## Project structure
```
dsh-sound-notifier/
├── package.json # dsh.bundle + dsh.client manifest; exports ./client
├── cordis.patch.yml # plugin row: { id: sound-alerts, name: dsh-sound-notifier }
├── index.js # host half: event listeners, queue, polling endpoint
└── client.js # browser half: dsh.client bundle, polls and plays
```
## Known limitations
- **Polling latency**: up to ~400 ms between an event and its chime.
- **Fixed endpoint**: `/sound-alerts/events` is served by the host half's `webServer` route; without a webserver the events are still recorded but never polled.
- **Top-level sessions only**: `agent.owner === undefined` filtering means a subagent page opened on its own stays silent.
- **Internal LLM calls are skipped**: `compaction` and `session-title` purposes never trigger the "thinking" chime.
- **Browser autoplay policy**: the audio context is created lazily and `resume()`d on each play.
## Contributing
Bug reports and pull requests are welcome. Keep changes focused; update this README when behavior changes.
## License
[MIT](LICENSE)
Install
dsh plugin --profile web add github:Zhengshuji/dsh-sound-notifier
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-notifier from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.