# 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) [![支持 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) [![平台](https://img.shields.io/badge/platform-Windows-0078D6)](https://github.com/sunligh91/dsh-helper) [![任务通知](https://img.shields.io/badge/-任务通知-4dc6fe)](https://github.com/sunligh91/dsh-helper) [![设置面板](https://img.shields.io/badge/-设置面板-4dc6fe)](https://github.com/sunligh91/dsh-helper) [![零构建](https://img.shields.io/badge/-零构建-4dc6fe)](https://github.com/sunligh91/dsh-helper) 🌏 [English](./README.md) · [**中文**](./README.zh.md) > 一个 [DSH](https://www.npmjs.com/package/@deepseek-ai/dsh) 插件:当 agent 会话**完成**、**异常**或**需要你确认**时弹出 Windows 原生通知,完成时还可附带提示音——长任务可以放手不管,出事的瞬间你会知道。 ## ✨ 功能一览 - **🔔 任务通知** — agent 进入空闲(任务完成)、出错、或即将向你提问时,弹出 Windows 原生 Toast。 - **🔊 完成音效** — 会话完成时播放提示音。随包内置一段合成的双音提示音;音量可调(0–100),也可指定任意本地音频文件(wav / mp3 / wma)。 - **⚙️ 设置面板** — DSH 设置页新增「任务通知 (dsh-helper)」分区:三个通知开关 + 音效控制。 - **🧪 测试按钮** — 一键发送测试通知并按当前设置试听音效,验证本机链路是否正常。 - **🪶 零原生依赖** — 通知走 PowerShell WinRT Toast,无需编译任何二进制。 - **🔁 热重载** — 配置写回 profile 的 `cordis.patch.yml`,由 DSH 的 patch watcher 自动生效,无需重启。 ## 🚀 安装 **前置条件**:DSH `0.1.2-rc.1+`,且 `web` profile 已初始化(至少跑过一次 `dsh web`),Node.js ≥ 20、pnpm ≥ 10。 ### 方式一 — npm registry(推荐) ```bash dsh plugin --profile web add dsh-helper@latest ``` 包内是**预构建产物**(`lib/` 已随包发布),**不含任何安装脚本**,因此 pnpm 不会要求你授权构建,装完即用。 ### 方式二 — 从 git 仓库安装 ```bash dsh plugin --profile web add github:sunligh91/dsh-helper ``` > git 源安装会拉源码并由 pnpm 运行 `prepare`;pnpm ≥10 在得到显式允许前会拒绝执行,需要把 pnpm 打印的包键写进该 profile 的 `pnpm-workspace.yaml`: > ```yaml > allowBuilds: > dsh-helper: true > ``` > 该授权等于「允许此包的代码在安装时于本机执行」。若只想装预构建代码,请用**方式一**。 ### 方式三 — 从源码安装 ```bash git clone https://github.com/sunligh91/dsh-helper.git cd dsh-helper # 链接到你的 web profile cd ~/.dsh/profiles/web pnpm add file:/绝对路径/dsh-helper ``` 然后把 `"dsh-helper"` 加进 `~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 数组,并**硬刷新**浏览器(Ctrl/Cmd + Shift + R)。 ## ⚙️ 配置 进入 **设置 → 任务通知 (dsh-helper)**。 | 配置项 | 默认值 | 说明 | | --- | --- | --- | | `notifyOnComplete` | `true` | 会话完成时通知(同一会话 60 秒内去重)。 | | `notifyOnError` | `true` | 会话出错时通知。 | | `notifyOnConfirm` | `true` | agent 即将提问时通知。 | | `soundOnComplete` | `true` | 完成通知后播放提示音。 | | `soundVolume` | `70` | 提示音音量,`0`–`100`。 | | `soundFile` | `""` | 本地音频文件路径(wav / mp3 / wma)。留空用内置提示音;自定义文件不存在时回退到内置提示音,再回退到 Windows 系统自带提示音。 | 默认值随包附在 `cordis.patch.yml`;你的改动会写入 `~/.dsh/profiles/web/cordis.patch.yml`。 ## 🔌 工作原理 | DSH 事件 | 行为 | | --- | --- | | `agent/status`(`idle`) | 弹出「任务完成」通知 + 播放提示音 | | `agent/request-error` | 弹出「任务异常」通知(纯放行,不做任何拦截或重试) | | `tools/pre-execute`(`ask_user_question`) | 弹出「需要确认」通知 | | `session/event` → `approval/asked` | 弹出「需要授权」通知 | > 审批通知监听的是会话审计事件 `approval/asked`,而不是瀑布事件 `approval/request`。原因是 cordis 的 waterfall 语义为「不调用 `next()` 即否决整条链」,任何排在前面并直接返回结果的监听器(例如自动审批门控)都会让后面的监听器永远收不到事件。`approval/asked` 是决策前写入日志的纯审计事件,不受此影响。 设置路由(`/_dsh/dsh-helper/settings`)仅监听本机,非 `127.0.0.1` / `::1` 的请求一律返回 `403`。 > 🔄 **还需要自动重试?** 本插件只做通知,这是有意为之。可搭配专门的重试插件,例如 [`dsh-task-reliability`](https://www.npmjs.com/package/dsh-task-reliability)(它在同一事件上返回 `{ kind: 'retry' }` 触发 DSH 原生重试)。 ## 🛠️ 开发与构建 ```bash git clone https://github.com/sunligh91/dsh-helper.git cd dsh-helper ``` | 文件 | 作用 | | --- | --- | | `lib/index.js` | 宿主侧 — cordis 插件:事件钩子 + 设置路由 | | `lib/client.js` | 客户端侧 — 通过 `window.__ModuleLoader__` 注册,无需构建 | | `cordis.patch.yml` | 注入 profile 的默认配置 | 两侧都是原生 ES module / UMD,没有打包器,改完刷新即可。 ## ⚠️ 已知限制 - 通知面向 Windows(PowerShell WinRT Toast)。在 macOS/Linux 上插件仍会加载,但通知和音效都是静默空操作。 - 音效走 PowerShell + WPF MediaPlayer;不可用时退回 `System.Media.SoundPlayer`(仅支持 wav,且音量设置不生效)。 - 若 Windows「专注助手 / 勿扰」开启,通知可能被拦截。 - **投递身份(0.5.0 起自动处理)**:Windows 要求桌面程序在开始菜单有一条携带 `System.AppUserModel.ID` 的快捷方式,否则 toast 会被**间歇性静默丢弃**(尤其当有前台窗口时),表现为「焦点不在本应用就收不到通知」。插件启动时会自动幂等补齐这条快捷方式(`%APPDATA%\Microsoft\Windows\Start Menu\Programs\dsh-helper.lnk`),无需手动操作、也无需管理员权限。 - 快捷方式若被清理软件删除,下次启动 DSH 会自动重建。 ## 📄 许可证 [MIT](./LICENSE) © sunligh91 ## 📝 更新日志 - **0.5.0** — 修复「焦点不在 DSH 就收不到通知」:Windows 要求桌面程序的开始菜单快捷方式携带 `System.AppUserModel.ID`,否则 toast 会被间歇性静默丢弃。插件启动时自动幂等补齐该快捷方式(运行时自建,包内不含任何安装脚本,npm 安装无需授权)。另:审批通知改挂 `session/event` → `approval/asked`,不再被自动审批门控的瀑布抢答吞掉。 - **0.4.4** — 移除 0.4.3 引入的全局节流(会吞掉并发主会话的完成通知),只保留**子 agent 不通知**这一条过滤规则。 - **0.4.3** — 修复通知轰炸:任务完成通知不再对**子 agent** 触发(dsh 并行跑多个子 agent,每个收尾都发一条,通知中心被刷爆——主会话 id 带 `session-` 前缀,子 agent 是裸 UUID,据此过滤);另加全局节流,60 秒内最多一条完成通知。 - **0.4.2** — 通知顶部改用自有应用标识:AUMID 从借用的 File Explorer GUID 换成 `dsh-helper`,并在每次发送前幂等写入 `HKCU\Software\Classes\AppUserModelId\dsh-helper` 的 `DisplayName`,通知顶部由一串十六进制 GUID 变为 **dsh-helper**。 - **0.4.1** — 修复通知回退成弹窗的根因:`GetTemplateContent` 被误调在 `ToastNotifier` 实例上(该方法属于 `ToastNotificationManager` 静态类),WinRT toast 从未真正成功过,一直走 WScript 弹窗兜底。现改回正确调用并实测弹出真通知。 - **0.4.0** — 新增「需要授权」通知(钩 `approval/request` 事件,工具权限审批时提醒);设置面板拆分为三个测试按钮:完成 / 多选一确认 / 权限审批。 - **0.3.2** — 修复确认通知不显示:Windows 会静默丢弃未注册自定义应用 id 的 Toast,现改用文件资源管理器的注册 AUMID 发送;新增 WScript.Shell 弹窗兜底。 - **0.3.1** — 加入临时诊断日志(确认问题解决后移除)。 - **0.3.0** — 新增完成音效(内置合成双音、音量可调、可指定本地文件)。 - **0.2.0** — 移除自动重试,专注通知。 - **0.1.0** — 首个版本:完成 / 异常 / 确认通知。