Bundle
@ai-galaxy/dsh-sound
DeepSeek Harness plugin: per-event task-completion and attention sounds for turn-end / approval / question / plan-review / goal-blocked / task-failure, each with its own sound (built-in synth, local audio file) and volume, with a separate subagent channel (Web UI)
- Source
- AI-Galaxy-GPU
- stars
- 9 stars
- License
- MIT
- Updated
- Updated yesterday
Readme
# dsh-sound English | [δΈζ](README.zh.md) A DeepSeek Harness (DSH) plugin for the **Web UI**: play a customizable sound when a task finishes, and an attention sound whenever something needs a human. > π¬ **Submitted to [Awesome DSH Plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin)** β [PR #752](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/752) (pending maintainer approval) ## Screenshots  ## Features ### Six independent events Each event type has its **own sound and its own volume** (0β100%): | Event | Detection | Default sound | |---|---|---| | Turn end / background task completed | `turn/end` with `reason.kind === 'completed'`; job β `completed` | Chime | | Approval request | `approval/requested` frame | Ding | | User question | `question/requested` frame (not plan-review shaped) | Ding | | Plan review | `question/requested` frame classified as plan-review | Ding | | Goal blocked | goal projection enters `blocked` | Ding | | Background / loop failure | job β `failed`; `turn/end` `error`; `host/agent-error` | Bell | - **Completion** respects the βquiet current sessionβ option; **attention** events (approval / question / plan-review / goal-blocked / failure) always ring. - User abort, killed jobs, and `max-tokens` / `blocked` / `interrupted` turns stay silent. - Events come from `events.mux` plus `events.host`. Mux-open replay of still-pending approval/question frames (refresh recovery) does not ring; each `rpcId` rings at most once. - When the event stream is unavailable or frames fail to unwrap, the plugin falls back to snapshot diffing. - **Multiple tabs**: the same event rings only once (BroadcastChannel tie-break). A single tab plays immediately, with no 40 ms handshake. ### Separate subagent channel Subagent-originated events are detected and routed independently from the main agent: - **One-shot subagent jobs** β a `session/jobs` entry with `kind === 'subagent'` (each parallel delegation completing used to ring the main completion sound; now it does not). - **Subagent sessions** β events whose session row is marked `origin: 'subagent'` / `parentId` (continuable subagents), including child-session turn ends, approvals, questions, goal projections, and failures. The settings panel adds a **ε代ηδΊδ»Ά / Subagent Events** section with six rows (same sound sources and per-row volume as the main events) plus an **ignore all subagent events** master switch. All six subagent sounds default to **mute**; main-agent events are unchanged. ### Sound sources Each event picks one sound from a **Radio.Button group** in the settings panel: - **Built-in synthesized sounds** β Ding / Chime / Bell / Complete / Success, generated live with Web Audio, no audio files required. - **Mute** β silence that event. - **Local file** β choose any MP3/WAV/etc. file; a **file picker appears below the event row** once selected. Uploaded files are stored in IndexedDB (`dsh-sound-audio`), immune to the localStorage quota. ### Settings panel (Settings β ε£°ι³ιη₯ / Sound Notification) The master switch and config export/import stay visible; a **δΈ» Agent / ε代η** tab bar switches the panel between the six main event rows and the subagent panel (its own six rows plus the γεΏ½η₯ε代ηδΊδ»Άγ/ ignore-all-subagent-events switch). Each event row has a volume slider on the title row and a Radio.Group of Radio.Button options below β click to select and play; a local-file row with a choose/replace button appears when ζ¬ε°ζδ»Ά is selected. ## Install Requires a DSH version with bundle-plugin support (`dsh.profile.bundles` + `dsh.bundle.patch`) and `pnpm` on PATH (`corepack enable` or `npm i -g pnpm`). ```sh # One command: pnpm installs the package and adds it to the profile's bundle layer dsh plugin --profile web add @ai-galaxy/dsh-sound # Restart the server (or refresh the page), then open Settings β ε£°ι³ιη₯ ``` Other profiles work the same way: `dsh plugin --profile <name> add @ai-galaxy/dsh-sound`. To track unreleased `main`, install from the GitHub source instead: ```sh dsh plugin --profile web add github:AI-Galaxy-GPU/dsh-sound ``` ### Manual install (without pnpm) 1. Copy this package and its runtime deps (`@deepseek-ai/schemastery`, `@deepseek-ai/cosmokit`, `@standard-schema/spec`) into `$DSH_HOME/profiles/web/node_modules/`. 2. Append `"@ai-galaxy/dsh-sound"` to `dsh.profile.bundles` in `$DSH_HOME/profiles/web/package.json`. 3. Restart `dsh web`. ## Configuration storage - The browser half persists its configuration in **localStorage** (key `dsh-sound:config`), sanitizing every read and filling defaults. Uploaded local music files are stored in **IndexedDB** (`dsh-sound-audio`) instead β no localStorage quota limits. - Config keys: `enabled`, `quietCurrent`, `ignoreSubagent`, and six main sound + six main volume fields β `completionSound` / `approvalSound` / `questionSound` / `planReviewSound` / `goalBlockedSound` / `failureSound` (builtin key, `none`, `local`, `data:` URL, or `audio:<id>`) and `completionVolume` β¦ `failureVolume` (0β1) β plus the matching `subagentCompletionSound` β¦ `subagentFailureSound` / `subagentCompletionVolume` β¦ `subagentFailureVolume` pairs for the subagent channel (all sounds default to `none`). `localFiles` keeps the last chosen local file per event (`completion`, β¦ and `subagent-completion`, β¦) so switching to a built-in sound and back does not drop it. - **0.2.0 migration**: older configs are upgraded automatically β `defaultSound` becomes `completionSound`, voice/TTS values degrade to the per-event default, and `workspaces` / `debounceMs` / global `volume` / voice settings are dropped. - **Export / import**: the settings panel downloads the full config as JSON (IndexedDB audio references are inlined as data URLs) and restores it from a JSON file β moving browsers or machines does not require reconfiguration. - The host half also registers the `dsh-sound` settings namespace: on rc.6 the settings API allowlist (`WEB_SETTINGS_NAMESPACES` in `dsh-host-apiproxy`) does not expose third-party namespaces to browsers, so the client does not depend on `settingsScope` today; the registration keeps the migration path open for future releases. ## Compatibility & capability disclosure **Compatibility** - Node.js: `>=20` (`engines.node`). - DSH: verified on `0.1.5-alpha.1`, `0.1.5-alpha.2`, `0.1.5-rc.1`, `0.1.5-rc.2` β declared as `compatible` in `dsh.compatibility.dshReleases`; the plugin was also smoke-tested end-to-end (settings panel + live event sounds) on a source build of `0.1.3-alpha.1`. - Verification (2026-09-13): each declared version passed a disposable-profile cycle β `dsh plugin --profile web add <tarball>` β `dsh web --no-open` boots and serves the plugin bundle (`@ai-galaxy/dsh-sound/client.js` present in the boot page, no plugin load errors) β `dsh plugin --profile web remove @ai-galaxy/dsh-sound` leaves the profile clean. Each run used a temporary `DSH_HOME`, deleted afterwards. **Dependencies** - Host half: `@deepseek-ai/schemastery` (settings schema) plus the peer `@deepseek-ai/cordis`. No other runtime dependencies. - Client half: React, `@deepseek-ai/dsh-client-runtime`, and `@deepseek-ai/dsh-client-ui-settings` are provided by the host application through the client module table; the package ships no copies of them. **Capabilities and permissions** - Local files: the settings panel opens the browser's own file picker for an audio file the user selects; the audio is stored in IndexedDB (`dsh-sound-audio`). There is no filesystem access outside the browser sandbox and no automatic file scanning. - Storage: configuration lives in `localStorage` (`dsh-sound:config`), audio files in IndexedDB. - No network requests, no external services, no shell or command execution, no credentials, no native artifacts, and no install lifecycle scripts (`preinstall` / `install` / `postinstall` / `prepare` are absent). **Failure bounds** - Playback failures (browser autoplay policy, unsupported audio) stay silent; the UI keeps working. - Unavailable IndexedDB/localStorage degrades to in-memory configuration; unreadable audio references are ignored. - Unavailable or unparseable event streams degrade to session-snapshot diffing; malformed frames are ignored without crashing. - Every configuration read is sanitized against the known field set and defaults. ## Development ```sh npm test # 100+ assertions across host and client halves (Node only, no browser needed) npm run check # syntax check ``` Layout: > **Profile development note**: the profile's pnpm uses `nodeLinker: hoisted`, > which COPIES `file:` dependencies into `node_modules` at install time β > edits to this checkout do not reach the running app until you either > re-run `pnpm --dir ~/.dsh/profiles/web update @ai-galaxy/dsh-sound` or replace the > copied directory with a symlink to this checkout. The web server reads > bundle content per request (only the boot-page rev hash is cached at > startup), so after refreshing the copy a browser hard-refresh (Cmd+Shift+R) > is enough β no server restart needed. - `lib/index.js` β host half: registers the settings namespace (schema + defaults) - `lib/client.js` β browser bundle: event detection, sound engine (Web Audio / IndexedDB audio), settings panel - `lib/types/index.d.ts` β host-side type declarations - `cordis.patch.yml` β bundle patch layer (inserts the `dsh-sound` row) - `tools/` β tests and verification scripts (not shipped in the npm package) ## Publish Published as `@ai-galaxy/dsh-sound` (requires membership of the `ai-galaxy` npm org; `publishConfig.access` is already `public`). ```sh npm login # npm account (2FA recommended) npm publish --access public ``` ## License [MIT](LICENSE)
Install
dsh plugin --profile web add github:AI-Galaxy-GPU/dsh-sound
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 ai-galaxy-dsh-sound from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.