# dsh-taskbar-alert ยท taskbar flash on attention When the agent needs you โ€” an approval, a question, a plan review โ€” or when a turn finishes, the **DeepSeek Harness window and its Windows taskbar button flash**. If you switched to another app, minimised DSH, or another window covers it, you still won't miss the moment that needs your decision. | Trigger | When | | --- | --- | | ๐Ÿ”” Approval | A tool call needs your permission and the approval card is waiting | | ๐Ÿ”” Question / plan review | `ask_user_question` or a plan review is waiting for an answer | | โœ… Turn finished | The root conversation finished its turn | ## Behaviour - Uses the native Win32 `FlashWindowEx`: it flashes the **taskbar button** and the **window frame**. - Window in the background: `FLASHW_ALL | FLASHW_TIMERNOFG`, so it keeps flashing until you bring DSH back to the foreground (or until `flashSeconds` expires). - Window already in the foreground: a fixed burst of 3 `FLASHW_ALL` flashes. Windows' `TIMERNOFG` means "an active window does not flash", which would leave you with no feedback at all while you stare at the screen waiting for an approval. ## How it works The host half (`index.js`) listens to three host events and needs no page: - `approval/request` โ€” approval requests; - `user-questions/request` โ€” questions and plan review; - `agent/status` โ€” the root agent going from `running` to `idle`, i.e. a finished turn. > โš ๏ธ **Approval and question listeners must be registered with `{ prepend: true }`.** Both are cordis `waterfall` events: listeners run outermost-first, and any listener that does not call `next()` ends the entire chain. DSH's session controller registers an `approval/request` listener at boot that forwards the request to the page and waits for your click โ€” **it never calls `next()`**. A plugin is a bundle mounted later, so a plain listener sits at the tail of the chain and is never invoked. That is exactly why "only the completion flash works, approval does not". `prepend: true` puts the observer at the front; it flashes and then calls `next()` so the answerer still makes the decision. The flash itself is performed by **one long-lived PowerShell helper**. At start it compiles the `user32.dll` interop once with `Add-Type`, then serves `flash` / `stop` / `quit` commands on stdin. It locates windows by a visible top-level window whose title contains `DeepSeek Harness`, so window recreation and multiple windows still match. The helper is warmed up 2.5 s after the plugin loads so the first alert is instant; turn the warm-up off to start it lazily on the first alert instead (about 1โ€“2 s of compilation latency). ## Settings The plugin declares its own Config (`@deepseek-ai/schemastery`), so **Settings โ†’ Plugins โ†’ Taskbar Flash Alert** shows these fields: | Field | Default | Meaning | | --- | --- | --- | | `approval` | `true` | Flash on approval requests | | `question` | `true` | Flash on questions / plan review | | `complete` | `true` | Flash when a turn finishes | | `flashSeconds` | `0` | Auto-stop after N seconds; `0` = flash until the window is activated | | `warmup` | `true` | Warm the PowerShell helper in the background so the first alert is instant | You can also edit the `config` of the entry in the profile's `cordis.patch.yml`. ## Limits - **Windows only.** The flash is a Win32 call; on other platforms the plugin stays silent. - **Flash only, no icon colour change.** Turning the taskbar icon red or adding a red badge requires the app's main process to call `BrowserWindow.setOverlayIcon`; the DSH Desktop Electron shell does not expose that to plugins (its own `flashFrame` is only used for its update prompt). This plugin implements the flashing half. - **Targets the DSH Desktop window.** It only works inside DSH Desktop (an Electron window whose title contains `DeepSeek Harness`). A browser tab will not flash โ€” use a notification plugin such as `dsh-notify-me` there. - Each alert spawns or reuses one hidden `powershell.exe` (about 30โ€“60 MB resident). Set `warmup` to `false` if that matters; the helper then starts on demand and is reaped when the plugin unloads. - It is only an attention cue: it never approves anything for you. ## Install ```sh dsh plugin --profile add dsh-taskbar-alert ``` Or install the bundle directory directly with `plugin_manager install_bundle `. ## Development self-check ```powershell node --check index.js node probe.mjs ``` `probe.mjs` loads the plugin into a fake context that reproduces cordis' dispatch rules: it first registers an answerer that never calls `next()` (mimicking the real session controller), then loads the plugin, then dispatches one `approval/request`, one `user-questions/request` and one `agent/status`. The output should contain: ```text [probe] approval outcome: allowed-once | bridge claims: 1 [probe] question outcome: {"answers":[]} | bridge claims: 1 [dsh-taskbar-alert] OK flash 1 [dsh-taskbar-alert] OK flash 1 [dsh-taskbar-alert] OK flash 1 [dsh-taskbar-alert] OK stop 1 ``` `bridge claims: 1` proves the decision is still made by the answerer (the plugin does not steal it); the three `OK flash 1` lines prove all three triggers reached `FlashWindowEx` and matched one harness window. Run `probe.mjs` in a **non-sandboxed** terminal: the sandbox forbids child-process pipes (`spawn EPERM`) and the helper cannot start. ## License MIT