# dsh-helper [![npm version](https://img.shields.io/npm/v/dsh-helper)](https://www.npmjs.com/package/dsh-helper) [![npm downloads](https://img.shields.io/npm/dm/dsh-helper)](https://www.npmjs.com/package/dsh-helper) [![GitHub stars](https://img.shields.io/github/stars/sunligh91/dsh-helper)](https://github.com/sunligh91/dsh-helper/stargazers) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Supported DSH: 0.1.2-rc.1+](https://img.shields.io/badge/DSH-0.1.2--rc.1%2B-blue)](https://www.npmjs.com/package/@deepseek-ai/dsh) [![platform](https://img.shields.io/badge/platform-Windows-0078D6)](https://github.com/sunligh91/dsh-helper) [![task notifications](https://img.shields.io/badge/-task%20notifications-4dc6fe)](https://github.com/sunligh91/dsh-helper) [![settings panel](https://img.shields.io/badge/-settings%20panel-4dc6fe)](https://github.com/sunligh91/dsh-helper) [![zero build](https://img.shields.io/badge/-zero%20build-4dc6fe)](https://github.com/sunligh91/dsh-helper) 🌏 [**English**](./README.md) Β· [δΈ­ζ–‡](./README.zh.md) > A [DSH](https://www.npmjs.com/package/@deepseek-ai/dsh) plugin that pops native Windows notifications when an agent session **finishes**, **fails**, or **needs your confirmation** β€” with an optional completion chime β€” so you can walk away from long runs and still know the moment something needs you. ## ✨ Features - **πŸ”” Task notifications** β€” a native Windows toast when the agent goes idle (task complete), hits an error, is about to ask you a question, or a tool needs permission approval. - **πŸ”Š Completion chime** β€” plays a sound when a session finishes. Ships with a built-in synthesized two-note chime; volume is adjustable (0–100) and you can point it at any local audio file (wav / mp3 / wma). - **βš™οΈ Settings panel** β€” a **Task Notifications (dsh-helper)** section in DSH Settings with four notification toggles plus the sound controls. - **πŸ§ͺ Three test buttons** β€” preview each real notification type (complete / multi-choice confirm / permission approval) with one click. - **πŸͺΆ Zero native dependencies** β€” notifications go through PowerShell WinRT Toast, so there is nothing to compile. - **πŸ” Hot reload** β€” configuration is written back to the profile's `cordis.patch.yml` and picked up by DSH's patch watcher, no restart needed. ## πŸš€ Installation **Prerequisites**: DSH `0.1.2-rc.1+` with the `web` profile already initialized (run `dsh web` at least once), Node.js β‰₯ 20, pnpm β‰₯ 10. ### Option 1 β€” npm registry (recommended) ```bash dsh plugin --profile web add dsh-helper@latest ``` The package ships **prebuilt artifacts** (`lib/` is published) and contains **no install scripts**, so pnpm never asks you to authorize a build. ### Option 2 β€” from the git repo ```bash dsh plugin --profile web add github:sunligh91/dsh-helper ``` > A git install pulls source and has pnpm run `prepare`; pnpm β‰₯10 refuses until you explicitly allow it. Copy the exact package key pnpm prints into that profile's `pnpm-workspace.yaml`: > ```yaml > allowBuilds: > dsh-helper: true > ``` > That authorization means "allow this package's code to run on your machine at install time". If you only want prebuilt code, use **Option 1**. ### Option 3 β€” from source ```bash git clone https://github.com/sunligh91/dsh-helper.git cd dsh-helper # link it into your web profile cd ~/.dsh/profiles/web pnpm add file:/absolute/path/to/dsh-helper ``` Then add `"dsh-helper"` to the `dsh.profile.bundles` array in `~/.dsh/profiles/web/package.json`, and **hard-refresh** your browser (Ctrl/Cmd + Shift + R). ## βš™οΈ Configuration Go to **Settings β†’ Task Notifications (dsh-helper)**. | Key | Default | Description | | --- | --- | --- | | `notifyOnComplete` | `true` | Notify when a session finishes (deduped to once per 60 s per session). | | `notifyOnError` | `true` | Notify when a session hits an error. | | `notifyOnConfirm` | `true` | Notify when the agent is about to ask you a question (multi-choice). | | `notifyOnPermission` | `true` | Notify when a tool triggers a permission approval dialog. | | `soundOnComplete` | `true` | Play the completion chime after the completion toast. | | `soundVolume` | `70` | Chime volume, `0`–`100`. | | `soundFile` | `""` | Path to a local audio file (wav / mp3 / wma). Empty = the bundled chime; if the custom file is missing it falls back to the bundled chime, then to Windows built-in notify sounds. | Defaults ship in `cordis.patch.yml`; your overrides are written to `~/.dsh/profiles/web/cordis.patch.yml`. ## πŸ”Œ How it works | DSH event | Behaviour | | --- | --- | | `agent/status` (`idle`) | Completion toast + chime | | `agent/request-error` | Error toast (passthrough β€” this plugin never blocks or retries) | | `tools/pre-execute` (`ask_user_question`) | Confirmation toast (multi-choice question) | | `session/event` β†’ `approval/asked` | Permission toast (tool approval) | > Approval notifications listen on the session audit event `approval/asked` rather than the `approval/request` waterfall. Cordis waterfall semantics are "not calling `next()` vetoes the rest of the chain", so any earlier listener that returns a result directly (e.g. an auto-approval gate) would permanently starve later listeners. `approval/asked` is a log-only audit event written before the decision, so it cannot be pre-empted. The settings HTTP route (`/_dsh/dsh-helper/settings`) is bound to localhost only β€” anything other than `127.0.0.1` / `::1` gets a `403`. > πŸ”„ **Need auto-retry too?** This plugin intentionally does notifications only. Pair it with a retry plugin such as [`dsh-task-reliability`](https://www.npmjs.com/package/dsh-task-reliability), which returns `{ kind: 'retry' }` on the same event. ## πŸ› οΈ Development ```bash git clone https://github.com/sunligh91/dsh-helper.git cd dsh-helper ``` | File | Role | | --- | --- | | `lib/index.js` | Host half β€” cordis plugin: event hooks + settings route | | `lib/client.js` | Client half β€” registered via `window.__ModuleLoader__`, no build step | | `cordis.patch.yml` | Default configuration inserted into the profile | Both halves are plain ES modules / UMD β€” there is no bundler, so edit and reload. ## ⚠️ Known limitations - Notifications target Windows (PowerShell WinRT Toast). On macOS/Linux the plugin still loads, but toasts and sounds are silent no-ops. - Sound playback uses WPF MediaPlayer via PowerShell. If that's unavailable it falls back to `System.Media.SoundPlayer`, which only plays wav and ignores the volume setting. - If Windows Focus Assist / Do Not Disturb is on, toasts may be suppressed. - **Delivery identity (handled automatically since 0.5.0)**: Windows requires a desktop app to have a Start-Menu shortcut carrying `System.AppUserModel.ID`, otherwise toasts are **intermittently and silently dropped** (especially while a foreground window exists) β€” the symptom users report as "I only get notifications while the app is focused". The plugin idempotently creates that shortcut on startup (`%APPDATA%\Microsoft\Windows\Start Menu\Programs\dsh-helper.lnk`) β€” no manual step, no admin rights. - If a cleanup tool removes the shortcut, it is recreated on the next DSH start. ## πŸ“„ License [MIT](./LICENSE) Β© sunligh91 ## πŸ“ Changelog - **0.5.0** β€” Fixed "no notifications unless the app is focused": Windows requires a desktop app's Start-Menu shortcut to carry `System.AppUserModel.ID`, otherwise toasts are intermittently dropped silently. The plugin now idempotently creates that shortcut at startup (runtime-created, so the package ships **no install scripts** and npm installation needs no build authorization). Also: approval notifications now listen on `session/event` β†’ `approval/asked` instead of the `approval/request` waterfall, so an auto-approval gate can no longer starve them. - **0.4.4** β€” Removed the global throttle introduced in 0.4.3 (it swallowed completion notifications from concurrent main sessions). Only the **sub-agent filter** remains. - **0.4.3** β€” Fixed notification flooding: completion notifications no longer fire for **sub-agents** (dsh runs several sub-agents in parallel and each one finishing posted a "task complete" toast, flooding the notification center β€” main session ids carry a `session-` prefix while sub-agent ids are bare UUIDs, used for filtering); added a global 60s throttle so multiple main sessions finishing together still post at most one toast. - **0.4.2** β€” The toast header now shows a real app name: the AUMID switched from the borrowed File Explorer GUID to `dsh-helper`, with its `DisplayName` idempotently written to `HKCU\Software\Classes\AppUserModelId\dsh-helper` before every send β€” the header changes from a hex GUID to **dsh-helper**. - **0.4.1** β€” Fixed notifications falling back to a popup dialog: `GetTemplateContent` was mistakenly called on the `ToastNotifier` instance (the method belongs to the static `ToastNotificationManager` class), so the WinRT toast never actually succeeded and every notification took the WScript dialog fallback. Now calls the correct target β€” real toasts verified. - **0.4.0** β€” Added a "needs permission" notification (hooks the `approval/request` event for tool approval dialogs); the settings panel now has three test buttons: complete / multi-choice confirm / permission. - **0.3.2** β€” Fixed confirmation toasts not appearing. Windows silently drops WinRT toasts sent under an unregistered custom app id, so notifications are now sent under File Explorer's always-registered AUMID. Added a `WScript.Shell` popup fallback for environments where WinRT is unavailable. - **0.3.1** β€” Added temporary diagnostic logging (to be removed once the confirm-notification issue is verified resolved). - **0.3.0** β€” Added an optional completion chime (built-in synthesized two-note sound, adjustable volume, custom local file). - **0.2.0** β€” Removed auto-retry; notifications only. - **0.1.0** β€” Initial release: completion / error / confirm notifications.