Skip to content
dsh.fish
Bundle

dsh-soundscape

DeepSeek Harness Web UI soundscape: turn-complete celebration (synthesized chime + confetti burst), blocked/approval alerts, error buzz, send clack and optional typing ambience. Zero audio assets, zero core changes, and a ctx.soundscape service other plugins can call.

Source
Blaczz
stars
2 stars
License
MIT
Updated
Updated 2 days ago

Readme

# dsh-soundscape 🔊

> A session soundscape for the DeepSeek Harness Web GUI: turn-complete celebration (synthesized fanfare + confetti), blocked-on-user alerts, error buzz, send clack, and optional typing ambience. Zero audio assets, zero core changes, plus a `ctx.soundscape` service for other plugins.

[English](./README.md) | [简体中文](./README.zh.md)

A **DeepSeek Harness (DSH)** web plugin that gives the agent's turns an audio identity: synthesized WebAudio feedback when a turn starts, succeeds, fails, or blocks on you — and a confetti burst when work completes. Every sound is generated live by oscillators and envelopes — **no audio files, no network requests, no core modifications**. Install, restart, and it works; tune it per-sound in the settings page.

## ✨ Features

| Event | Sound | Default |
|---|---|---|
| Turn started | send rebound clack `send` | ✅ |
| Turn completed successfully | **celebration fanfare + confetti** `celebrate` (or plain `ding`) | ✅ |
| Turn errored / interrupted | low buzz `buzz` | ✅ |
| Waiting on you (approval / question / plan review) | two-tone alert `alert` (1.5s throttle) | ✅ |
| Session opened | soft two-note greeting `greet` | ⛔ |
| Streaming output (optional) | typing ambience `click` (throttled + jittered) | ⛔ |

- **Zero audio assets**: pure WebAudio oscillator synthesis.
- **Zero core changes**: only official client-plugin seams (`conversation.input.dock` / `conversation.session.header.actions` / `settings.section`).
- **Durable settings**: the `soundscape` settings namespace, saved immediately.
- **Cross-plugin service**: `ctx.soundscape.play(name)` / `ctx.soundscape.celebrate()` for other client plugins.
- **HMR friendly**: every registration is a `ctx.effect`; hot reload cleans up automatically.

## 📦 Install

Prereqs: [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh web` works), Node ≥ 22.19, pnpm.

```bash
# From GitHub
dsh plugin --profile web add "github:Blaczz/dsh-soundscape#main"

# Local directory (development)
cd dsh-soundscape && npm install --legacy-peer-deps && npm run build
dsh plugin --profile web add ./dsh-soundscape

# Local link
dsh plugin --profile web add link:./dsh-soundscape
```

**Restart `dsh web` after install** (a new plugin row needs one restart; later source changes ride HMR).

> Git installs need `allowBuilds` authorization: if the first `add github:...` fails, put the package key
> under `allowBuilds` in `~/.dsh/profiles/web/pnpm-workspace.yaml` as dsh prints, then re-run; or publish a
> prebuilt npm package to skip build authorization entirely.

## 🎛️ Usage

1. Install, restart, open any session, send a message:
   - turn start → rebound clack;
   - successful completion → **fanfare + confetti** (switch to a plain ding in settings);
   - error/interrupt → buzz; waiting on your approval/answer → two-tone alert.
2. The session header has a **🔊/🔇** quick mute toggle (durable across restarts).
3. **Settings → 🔊 音效**: master switch, master volume, per-sound toggles with previews, and stream-cadence knobs.

## 🔌 For developers: the `ctx.soundscape` service

Other client plugins add `soundscape` to their `inject` and call:

```ts
export const inject = ['slots', 'soundscape']

export function apply(ctx: Context): void {
  ctx.soundscape.play('celebrate')       // one sound
  ctx.soundscape.celebrate()             // full celebration (sound + confetti)
  if (!ctx.soundscape.isEnabled()) ctx.soundscape.setEnabled(true)
}
```

Sound names: `click` `send` `ding` `celebrate` `buzz` `alert` `greet`. Each is gated by its user setting and the master volume.

## 🛠️ Development

```bash
npm install --legacy-peer-deps          # build deps
$env:DSH_NODE_MODULES = "$env:USERPROFILE\.dsh\profiles\node_modules"
npm run setup:dsh-workspace             # symlink the runtime @deepseek-ai/* packages
npm run verify                          # ★ one-shot local gate (clean + typecheck + test + build)
npm run typecheck                       # typecheck src + tests
npm test                                # vitest (37 tests: state machine / synth / engine / settings / manifest)
npm run build                           # tsc + tsdown → lib/
dsh web --patch ./cordis.patch.yml      # zero-install quick verification
```

`npm run verify` is the pre-push gate: the extracted pure state machine (`turn-feedback.ts`) plus mock AudioContext / fetch tests catch event-mapping, gating, and throttle bugs locally, no browser needed.

### Layout

```
dsh-soundscape/
├── package.json            # dual contract: dsh.bundle.patch + dsh.client
├── cordis.patch.yml        # bundle patch layer (inserts this package)
├── tsdown.config.ts        # client bundle (__ModuleLoader__.load + purity gate)
├── scripts/                # build / clean / setup-dsh-workspace
├── src/
│   ├── index.ts            # host half: settings namespace + loopback HTTP API
│   ├── soundscape-settings.ts  # shared settings model (schema + defaults)
│   ├── settings-api.ts     # GET/PATCH settings API (loopback-only)
│   └── client/             # browser half
│       ├── index.ts        # apply: ctx.soundscape service + slot injection
│       ├── SessionListener.tsx  # conversation-snapshot diff → event sounds
│       ├── SoundEngine.ts  # WebAudio engine (lazy AudioContext)
│       ├── synth.ts        # pure synthesis primitives (oscillators + envelopes)
│       ├── confetti.ts     # zero-dependency canvas confetti particles
│       ├── HeaderMute.tsx  # session-header mute toggle
│       ├── SettingsSection.tsx # settings page (with previews)
│       └── settings-client.ts  # settings API client
└── tests/                  # manifest contract + settings patch validation
```

## 🧩 Ecosystem positioning

- **Fills a gap**: before this, the DSH ecosystem had **no** turn-complete sound/celebration effect and no blocked-on-user alert sound (desktop notifications are silent; `dsh-fun-typewriter` covers only typing ambience).
- **Technical route**: dual-sided client plugin (`dsh.client` + bundle patch), mirroring `dsh-fun-typewriter`'s zero-asset WebAudio + plugin-owned settings API, extended with the `ctx.soundscape` cross-plugin service (the `ctx.provide` pattern from `dsh-client-shortcuts`).
- **Zero core changes**: everything registers through `ctx.effect` / `ctx.slots.inject`; HMR unload cleans up.

## ⚖️ License

MIT © 2026 Blaczz. An independent community plugin, not affiliated with [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).

Install

dsh plugin --profile web add github:Blaczz/dsh-soundscape

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source