dsh-client-ui-notify
Ringtone notifications for DeepSeek Harness: alerts are triggered when the conversation ends and when authorization is required (either with a built-in tone, TTS voice, or custom audio). **DeepSeek Harness 网页端铃声提醒插件:回答完成或需要授权时响铃提醒,支持内置铃声 / 文字转语音 / 自定义音频。
- Stars
- 2
- Language
- TypeScript
- Created
- Aug 18, 2026
- Updated
- Aug 18, 2026
Introduction
@deepseek-ai/dsh-client-ui-notify
English | 中文
Sound-alert plugin for the web client: rings when a session's answer completes and when a session needs authorization, so a background conversation cannot finish unnoticed.
The browser half provides ctx.notify (a NotifyRuntime) and registers a preference row into the settings General section; the Host half exposes the durable ui-notify settings namespace the row reads and writes through ctx.settingsScope, stored in the user-settings document ($DSH_HOME/settings.yaml by default).
Alert events
The runtime observes ctx.sessions.list and rings in two situations, both gated by the master switch and their own toggle:
- Answer complete — a session's
runningbit flips true → false (the sidebar's green "done" reminder, current session included). - Authorization needed — a session's
pendingInteractionappears (approval, plan review, or ask-user question).
The first list snapshot only records observed state (a session already idle at load rings nothing), and connection/reset re-baselines so reconnect status replay cannot ring.
Alert methods
- Built-in ringtone — a two-tone chime synthesized at build time, embedded as a base64 data URI in the client bundle (
src/client/builtin-ringtone.ts), so no extra asset route exists. - Text to speech —
speechSynthesis.speakreads the configured text aloud (skipped when the text is empty). - Custom audio — plays an http(s) URL or a data URL, or a local file the row uploads to the host (≤ 1MB).
The uploaded file lands under
$DSH_HOME/storages/ui-notify/audio/, read and written through the trust-fenced/_dsh-ui-notify/audio/<id>.<ext>webServer route (the same browser-trust fence as/api, loopback-only); the durable setting stores just the served URL — file bytes never enter the settings document. Common audio formats are supported (wav, mp3, ogg, mp4, m4a, webm, aac, flac, aiff, wma, mid).
Playback degrades to a no-op when the platform capability is absent, so a misconfigured alert never throws from an event handler. The row's Preview button plays the current method immediately.
Settings surface

The General settings row adds the Enable sound alerts master switch, the two event switches (alert when an answer completes / alert when authorization is needed), the Alert method selector, the method-specific input fields, and the Preview button. Every control writes exactly one field through the injected setField face; the row never touches the settings transport itself. The Host half registers the namespace only when the settings provider is composed, so a deployment without one shows no row and no namespace.
Installation
Quick start: download the installer (zip), extract it, and run install.ps1 on Windows or bash install.sh on macOS/Linux; restart dsh web and you are done.
Manual installation:
-
Copy the plugin directory (
package.json+lib/) to$DSH_HOME/profiles/node_modules/@deepseek-ai/dsh-client-ui-notify/($DSH_HOMEdefaults to~/.dsh). -
Append the loader row to
$DSH_HOME/profiles/web/cordis.patch.yml(or the profile that serves the web UI):- insert: - id: ui-notify name: '@deepseek-ai/dsh-client-ui-notify' -
Restart
dsh weband refresh the browser; the Sound alerts row appears under Settings → General.
To uninstall: delete the copied directory and the ui-notify rows from cordis.patch.yml.
The plugin is a plain npm package; its runtime dependencies (cordis, dsh-settings, …) come from dsh's built-in closure, so no extra install is needed.
Model Experience
None, as the plugin plays browser sounds; nothing here reaches a model request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
- User-audio route is loopback-only — a LAN deployment that serves the browser through
trustedHostsgets 403 on uploads/downloads (playback of http(s)/data URLs is unaffected); wiring the route into the trusted-host list is deferred. - Orphaned hosted files — replacing a file deletes the previous one from the row, but a setting edited by hand (or an upload that never reached the row) can leave a file under
$DSH_HOME/storages/ui-notify/audio/; no retention sweep exists yet. - TTS voices follow the browser — no voice/rate/pitch controls exist; the text field is the only TTS input.
- One text for both events — the TTS method speaks the same text whether an answer completed or authorization is needed.