Notifications & Integrations
dsh-turn-notify
Ruiming-cn/dsh-turn-notify · ★ 0
DSH (DeepSeek Harness) plugin — Windows toast + chime the moment the agent needs you: turn done, blocked, error, approval, question, plan review.
Manifest details
安装
dsh plugin --profile web add github:Ruiming-cn/dsh-turn-notifyGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
For install and environment setup, plus plugin development tutorials, see DSH community docs ↗
README
Table of contents
- Features
- When it fires (every moment the agent needs you)
- Notification style
- Chime
- Multi-session isolation & anti-storm
- Notifier
- Layout
- Requirements
- Installation
- 1. One-command install (PowerShell notifier fallback)
- 2. Install with the native notifier (recommended on Windows)
- 3. Configure the patch
- 4. Restart the DSH GUI
- 5. One-time: register the AUMID shortcut
- Configuration
- Building dsh-notify.exe (required after clone)
- Tests
- Troubleshooting
- Migration & Release
English | 简体中文
A notification plugin for DSH (DeepSeek Harness): whenever the agent needs your input, it sends a Windows system notification — a toast in the corner + a chime + a preview of the question/answer — so you know the moment the agent is waiting for you, even when you're away from the screen.
Features
When it fires (every moment the agent needs you)
| Moment | Event | Notes |
|---|---|---|
| Turn completed | turn/end: completed |
User-initiated turns only; 10s cooldown |
| Goal blocked / paused / completed | goal/change |
Only on phase transitions (create→active etc. stay silent) |
| Conversation interrupted / aborted | turn/end: aborted |
Distinguishes user stop vs parent/hook cancel |
| Turn error | turn/end: error |
Includes error code + truncated message |
| Output limit reached | turn/end: max-tokens |
Output was truncated |
| Session interrupted (crash recovery) | turn/end: interrupted |
Check the session |
| Approval needed | approval/asked |
Includes tool name and reason |
| Waiting for your answer | ask_user_question tool call |
Agent asks and blocks on you; includes question text and count |
| Plan awaiting review | exit_plan_mode tool call |
Plan is ready — review it or keep planning |
| Runtime error | agent/error |
Step-level failure, notified mid-turn without waiting for turn end |
Subagent sessions stay silent; only root sessions notify.
Notification style
- WinRT Toast:
duration='long',ToastText02template,hint-style='title'headline - Icon: DSH black whale (set via the Start-menu shortcut's
IconLocation; not embedded in the exe) - Three-line body: session tag (
Session xxxxxx) /Q: …/A: …, each truncated topreviewChars(default 15) - Bilingual:
language: 'zh' | 'en'(default Chinese) — titles, bodies, Q/A prefixes and session tags all follow the language
Chime
- Defaults to
C:\Windows\Media\Windows Background.wav(falls back to chimes / Ding / Notify) - Played directly via
SoundPlayer, in sync with the toast (no delay; independent of the system notification-sound setting)
Multi-session isolation & anti-storm
- Per-session state keyed by
session.id; sessions never interfere completednotifications run through a serial queue; critical events are dispatched immediately, never blocked by the queue- Anti-storm: same-session same-kind critical events merge into one within 1.5s (
error/agent-errorandblocked/goal-blockedare unified, preventing double toasts) - Session state is released on
session/disposedand capped (default 128 sessions, oldest evicted) — no unbounded memory growth
Notifier
- Prefers
dsh-notify.exe(standalone C# binary, AUMIDdsh-turn-notifyregistered — bypasses security software that blocks script hosts) - Falls back to
notify.ps1(PowerShell + WinRT Toast) when the exe is missing - Three-level degradation on failure: Toast → tray balloon → log
Layout
dsh-turn-notify/
├── plugin/ # Plugin body (pure ESM, no build step)
│ ├── index.mjs # Cordis entry: event listeners + dispatch
│ ├── decide.mjs # Decider: event→notice mapping, bilingual copy, filtering, cooldown, anti-storm, preview
│ ├── scheduler.mjs # Scheduling: serial queue + critical fast-path + timeout
│ ├── dsh-notify.cs # Notifier C# source (Toast + chime + tray balloon)
│ ├── dsh-notify.exe # Build artifact (AUMID dsh-turn-notify; NOT committed, see "Build")
│ ├── notify.ps1 # PowerShell fallback script
│ ├── smoke.ps1 # Manual smoke-test script
│ └── test.mjs # node:test unit tests
├── docs/ # Design docs & implementation plan
└── test/harness/ # DSH event simulator for tests
Requirements
- Windows 10/11
- DSH (DeepSeek Harness), using its cordis patch mechanism (
cordis.patch.yml) - Node.js ≥ 18.13 (tests only)
Installation
1. One-command install (PowerShell notifier fallback)
dsh plugin --profile web add github:Ruiming-cn/dsh-turn-notify
This installs the bundle and registers the turn-notify entry through
cordis.patch.yml; restart dsh web afterwards. Without a locally built
dsh-notify.exe the plugin automatically falls back to notify.ps1 (which
security software may block).
2. Install with the native notifier (recommended on Windows)
Build dsh-notify.exe into plugin/ first (see "Build"), then install from
the local checkout so the built exe ships with the plugin:
dsh plugin --profile web add /path/to/dsh-turn-notify
3. Configure the patch
The bundle declares the plugin entry; to change options, attach config to
the same entry in ~/.dsh/profiles/web/cordis.patch.yml (keep id: turn-notify):
- id: turn-notify
config:
language: zh # zh | en (notification copy; default zh)
sound: true
notify:
completed: true
blocked: true
aborted: true
error: true
maxTokens: true
interrupted: true
goals: true
approvals: true
questions: true
planReview: true
agentError: true
cooldownMs: 10000
mergeWindowMs: 1500
previewChars: 15
titlePrefix: DSH
showSessionTag: true
timeoutMs: 10000
dryRun: false
Defaults live in the plugin code; the keys are the same as the legacy manual
name: "./turn-notify/index.mjs"entry, minus the relative path.
4. Restart the DSH GUI
Restarting is required after any plugin code change (Node module cache + DSH's HMR is watch-only — it listens to cordis.patch.yml only, it does not hot-reload plugin JS). After restart, the startup log should show:
[turn-notify] loaded (build <date>: questions/planReview/agentError/mergeWindow active)
5. One-time: register the AUMID shortcut
For the toast to show the app icon and belong to "DSH 通知" instead of "PowerShell", a Start-menu shortcut with an AUMID must exist:
- Location:
%APPDATA%\Microsoft\Windows\Start Menu\Programs\DSH 通知.lnk - Target:
...\turn-notify\dsh-notify.exe - AppUserModelID:
dsh-turn-notify - IconLocation: DSH black whale icon
C:\Users\20668\.dsh\dsh-whale.ico,0
Do this once; re-register after reinstalling or switching machines.
Configuration
| Key | Default | Description |
|---|---|---|
notify |
all on | Per-kind toggles (completed/blocked/aborted/error/maxTokens/interrupted/goals/approvals/questions/planReview/agentError) |
language |
'zh' |
Notification copy language: zh (Chinese) or en (English) |
cooldownMs |
10000 |
Completed-notification cooldown (ms per session) |
mergeWindowMs |
1500 |
Anti-storm merge window for critical events (ms, per session per kind) |
maxSessions |
128 |
Session-state cap (oldest evicted when exceeded) |
previewChars |
15 |
Q/A preview truncation length |
titlePrefix |
'DSH' |
Notification title prefix |
showSessionTag |
true |
Show the session-tag line |
sound |
true |
Play the chime |
timeoutMs |
10000 |
Notifier subprocess timeout |
dryRun |
false |
Log only, don't actually send (testing) |
rootSessionsOnly |
true |
Notify root sessions only (subagents stay silent) |
Building dsh-notify.exe (required after clone)
dsh-notify.exe is a build artifact and is not committed (see .gitignore). Build it after cloning so the plugin uses the exe path; when missing, the plugin falls back to notify.ps1 (which security software may block). Dependencies:
- .NET Framework 4.8
csc.exe(C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe) - Windows SDK
Windows.winmd(UnionMetadata, e.g. 10.0.26100.0) - GAC
System.Runtime.dllandSystem.Runtime.WindowsRuntime.dll
$winmd = "C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0\Windows.winmd"
$sysruntime = "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll"
& "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /nologo /nostdlib /target:exe /out:"dsh-notify.exe" /r:mscorlib.dll /r:System.dll /r:System.Core.dll /r:"$sysruntime" /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.Runtime.WindowsRuntime.dll /r:"$winmd" "dsh-notify.cs"
Run it inside plugin/ (/out writes to the current directory), then copy the whole plugin/ folder to the global profile.
Tests
node --test plugin/test.mjs
51 unit tests covering: every notification kind, waiting-answer / plan-review / runtime-error, Chinese & English copy, subagent silence, per-session cooldown, anti-storm merging, serial queue & critical fast-path, timeout & error handling, synchronous spawn-failure recovery, dryRun, exePath mode, Q/A preview with code-point-safe truncation, state cleanup & capacity cap.
Troubleshooting
| Symptom | Check |
|---|---|
| Changes don't take effect | Restart the GUI (plugin JS is not hot-reloaded); confirm [turn-notify] loaded (build ...) in the startup log |
| No chime | Check sound: true in the patch; verify manually with dsh-notify.exe -Title t -Body b -Sound; confirm C:\Windows\Media\Windows Background.wav exists |
| No toast | Confirm the DSH 通知.lnk shortcut exists (AUMID registered); add dsh-notify.exe to security-software trust; check Focus Assist (Do Not Disturb) |
| Banner content clipped | Windows banners hold ~3 lines; keep previewChars=15 for a full three-line body |
| No toast while DSH is focused | Notifications are OS-level UI, unrelated to focus; usually Focus Assist or system volume |
Migration & Release
- Published: https://github.com/Ruiming-cn/dsh-turn-notify (MIT License)
- Deployed globally: runs at
~/.dsh/profiles/web/turn-notify/, patch uses a relative path - Updating: pull the latest code → build the exe in
plugin/(see "Build") → copyplugin/to the global profile → restart the GUI - History: see CHANGELOG.md