dsh-desktop-alerts
任务需要你点头(审批 / 提权)时,或者某个对话的任务跑完了,让 Windows 直接在屏幕右下角弹一条系统通知 —— 穿透「请勿打扰」和全屏,DSH 在前台时不打扰。
DSH 的审批卡片只出现在窗口里。当你切去别的程序、全屏看视频或开着「请勿打扰」时,这张卡片可能几十分钟没人看见,任务就一直挂着。这个插件把审批请求转成 Windows 原生 toast:
- 穿透「请勿打扰」:Windows 11 走
scenario="urgent"(22H2+),Windows 10 走scenario="alarm"—— 这两类是系统里唯一允许越过勿扰与专注助手规则的提醒。 - 穿透全屏:专注助手的「全屏时」自动规则同样不拦 urgent / alarm(独占全屏的 DirectX 游戏除外,见已知限制)。
- 知道你在不在看:DSH 窗口在前台时不打扰(渲染进程焦点心跳 + Win32 前台窗口双重判断),切走后才弹。
- 点一下就回到 DSH:点通知(横幅或通知中心里的那一条)就把最小化的、被挡住的 DSH 窗口提到前台;DSH 已经退出时会重新启动它。走的是按用户注册的
dshalerts:协议,不需要管理员权限。 - 一直提醒到有人处理:审批没被点掉时按间隔追加提醒,被回答 / 取消后立刻停。
- 提示音可换、可定时:审批铃声从「闹钟声 / 系统提示音 / 自定义文件 / 静音」里选,响 1–60 秒自动停,不会像系统闹钟那样一直响到有人关。
- 任务完成也通知:每轮任务跑完再弹一条完成通知(带对话标题),左侧是绿色对勾,几秒后自动收起,不占屏幕。
- 通知中心可查:以
DeepSeek Harness的名义登记 AUMID,通知留在操作中心,不会「错过就没了」。
English: a DeepSeek Harness plugin that mirrors approval requests and finished turns to native Windows toasts (
scenario="urgent"on Win11 /"alarm"on Win10) so they break through Do-Not-Disturb and fullscreen, stays quiet while DSH is focused, and is fully configurable from DSH → Settings → 桌面通知.
环境要求
- Windows 10 1809+ 或 Windows 11(系统通知只有 Windows 有;其它平台插件静默禁用)
- DeepSeek Harness 桌面版(0.2.1+)
- 无额外依赖:宿主半边只用 Node 内置模块,发通知走系统自带的 PowerShell 5.1
安装
方式一:从 GitHub 安装(推荐)
在 DSH 里打开「插件」页,选择从 Git 安装,或直接用桌面端的 dsh plugin 命令:
# 换成你自己的 GitHub 用户名
dsh plugin add git+https://github.com/Gusheng-GS/dsh-desktop-alerts.git
方式二:本地源码(开发 / 调试)
# 1. 把仓库放到用户目录下
$src = '<本仓库路径>'
$dst = Join-Path $env:USERPROFILE '.dsh\plugins\dsh-desktop-alerts'
Copy-Item $src $dst -Recurse -Force
# 2. 链接进 desktop profile(Node 24 / pnpm 11)
cd $env:USERPROFILE\.dsh\profiles\desktop
pnpm add link:$env:USERPROFILE\.dsh\plugins\dsh-desktop-alerts
- 把
"dsh-desktop-alerts"追加到该 profilepackage.json的dsh.profile.bundles数组末尾。 - 重启 DeepSeek Harness。
第 3 步不能省:
pnpm add只装进node_modules,没写进bundles的包不会被加载(表现是设置页里没有这个分组、通知也不弹)。 仓库自带的node tools/deploy.mjs会一次性做完「复制 + 剥 BOM + 补 bundles」,改完源码直接跑它即可。
从旧名升级(0.4.x → 0.5.0)
0.4.2 及以前这个插件叫 dsh-approval-toast。0.5.0 起改名为 dsh-desktop-alerts(npm 上重名较多,换个不冲突的名字):
# 先卸掉旧包,否则新旧两份会同时加载、每条通知弹两遍
dsh plugin remove dsh-approval-toast
dsh plugin add dsh-desktop-alerts
- 旧配置文件
~/.dsh/dsh-approval-toast.json、旧日志会在首次启动时自动搬到新名字下(只搬一次,之后由~/.dsh/dsh-desktop-alerts.migrated标记)。设置不用重新配。 - 旧的
dshapproval:协议注册与DeepSeek.Harness.Approval应用 ID 会被顺手删掉,新的分别是dshalerts:和DeepSeek.Harness.DesktopAlerts。 - 通知中心里由旧版发出的那几条,点击已失效(它们的应用 ID 被删了),可以手动清掉。
设置
设置 → 桌面通知:
| 项 | 说明 |
|---|---|
| 启用审批通知 | 总开关 |
| DSH 在前台时不提醒 | 默认开;关掉后即使盯着 DSH 也会弹 |
| 点击通知切回 DSH 窗口 | 默认开;点横幅或通知中心那一条,最小化/被挡住的窗口会回到前台,DSH 已退出时重新启动它 |
| 通知强度 | 自动(紧急 → 闹钟回退)/ 紧急 / 闹钟 / 普通 |
| 提示音 | 闹钟声(循环)/ 系统提示音(响一次)/ 自定义音频文件 / 静音;审批的声音由插件自己播放,到点就停 |
| 自定义音频路径 | 选「自定义」时启用,填绝对路径;.wav 最稳,mp3 等走 MediaPlayer |
| 提示音响多久 | 1–60 秒;闹钟声与自定义文件按此时长播放后停止 |
| 追加提醒次数 / 间隔 | 审批未处理时的重复提醒,0 = 只弹一次 |
| 同一工具的冷却 | 连续审批不刷屏 |
| 通知标题 / 附上申请原因 | 审批通知文案 |
| 任务完成时也通知 | 单独开关;关掉则只有审批会弹 |
| 完成通知强度 | 紧急 / 闹钟通道 / 普通 |
| 完成时响系统提示音 | 一声系统提示音,不是闹钟循环 |
| 完成通知标题 | 正文自动带对话标题:「《重构登录》已完成」 |
- 「测试审批通知」「测试完成通知」两个按钮都会绕过焦点判断立刻弹一条,用来确认系统层面是否通畅(审批测试会按当前设置响一次铃声)。
- 图标是跟着类型走的:审批 = DSH 图标,任务完成 = 绿色对勾(toast 的
appLogoOverride,不占用lib/之外的资源)。
配置文件:%USERPROFILE%\.dsh\dsh-desktop-alerts.json(设置页读写同一份)。
诊断日志:%USERPROFILE%\.dsh\dsh-desktop-alerts.log —— 每行一个 JSON:load / capture / approval / task 结果,超过 256 KB 自动只保留最近 400 行。插件没弹、设置页没出现时先看它。
工作原理
approval/request (waterfall, prepend + global) ← 主路径
approval.request() 方法包装(透明透传) ← 兜底路径,两条去重
└─ announce(req) → 焦点/冷却判断 → payload JSON(audio=silent)
├─ powershell.exe -File lib/notify.ps1 -JsonPath <tmp>.json
│ ├─ 注册 HKCU\Software\Classes\AppUserModelId\DeepSeek.Harness.DesktopAlerts
│ ├─ Win32 GetForegroundWindow → DSH 在前台则跳过
│ └─ ToastNotificationManager.CreateToastNotifier(appId).Show(toast)
└─ powershell.exe -File lib/sound.ps1 -Path <file> -Seconds N ← 铃声,N 秒后自己退出
session/event → turn/end (reason.kind === 'completed') ← 完成通知
└─ 焦点判断 → payload(icon-task.png, audio=default|silent, duration=short)→ notify.ps1
- 监听必须带
{ prepend: true, global: true }:审批服务用waterfall(scopeTarget(agent, agent), 'approval/request', ...)派发,派发器会按作用域载体过滤监听者上下文 —— 不带global的监听在某些派发下会被直接丢掉。 - 宿主插件只监听、
next()透传,从不回答审批,不改变审批语义;通知失败只记日志,绝不影响审批链路。 - 完成通知不监听子代理会话(
session.header.origin === 'subagent'直接跳过),只报用户自己的对话;同一轮(sessionId:turn)只弹一次,aborted之类的结束原因也不算「完成」。 - 审批的铃声不放在 toast 里:toast 的循环音频无法按时停止,所以通知本体一律
audio=silent,声音交给lib/sound.ps1播 N 秒后退出;完成通知才用 toast 自带的一声系统提示音。 - 完成通知的「自动收起」不是靠
duration="short"(urgent / alarm 场景会忽略它),而是到点用ToastNotificationManager.History.Remove(tag, group, appId)把横幅收掉。 - 设置页「状态」里的「已捕获审批请求」会分别显示事件钩子与服务钩子各命中多少次,便于确认抓取链路活着。
- 点通知回到 DSH 由
lib/focus.ps1负责,按窗口状态分两条路:窗口在托盘里或最小化时再启动一次应用(第二个进程拿不到单实例锁,Electron 把它交给正在运行的实例,走应用自己的focusPrimaryWindow());窗口只是被压在别的窗口后面时,才直接SetForegroundWindow抢前台。抢完之后还有 2.6 秒看门狗:任务运行中窗口偶尔会在获得焦点后又被应用自己收起,看门狗会立刻把它放回来。 - 脚本是纯 ASCII 的 PowerShell 5.1 脚本(非 ASCII 文案一律走 UTF-8 JSON 载荷,避免 PS 5.1 无 BOM 解码乱码)。
已知限制
- 只有 Windows 有系统通知通道。
- 未打包桌面应用的 toast 需要用户级 AUMID 注册(脚本自动做,一次即可)。
- 点击通知回到 DSH 靠
dshalerts:协议处理器(注册在HKCU\Software\Classes\dshalerts,无需管理员)。DSH 被彻底退出后再点通知,会用注册时记录的 exe 路径把它重新拉起来;如果换过安装位置,重启一次 DSH 让插件重写注册表即可。 - 任务运行中点击通知,窗口偶尔会「闪一下」再回来:这是应用自身 close-to-tray 竞态,插件用看门狗兜住,不影响使用;
~/.dsh/dsh-desktop-alerts.log里kind:"activate"那行的method/reshows能看出走的是哪条路。 - 独占全屏的 DirectX 游戏里,Windows 可能压掉通知横幅;无边框全屏和普通全屏正常。
- 系统「专注助手 - 仅闹钟」下 urgent/alarm 能过;如果用户在系统里彻底关闭了本应用的通知,toast 会被静默丢弃(设置页会显示上次结果)。
- 前台判断依赖 Win32
GetForegroundWindow;在某些远程会话 / 锁屏状态下它可能返回空,此时按「没在前台」处理。
开发
npm test # 打包契约 + 客户端渲染(不弹通知,可在 CI 跑)
npm run test:smoke # 起一个假 ctx,跑审批瀑布 / 完成事件 / 路由
npm run icons # 重新生成 lib/icon-task.png(需要 Python + Pillow)
npm run deploy # 复制到 %USERPROFILE%\.dsh\plugins 并补 bundles(会剥 BOM)
单独调试通知脚本(不真的弹窗,只打印 XML):
powershell -NoProfile -ExecutionPolicy Bypass -File lib/notify.ps1 -JsonPath payload.json -DryRun
payload.json 的字段见 lib/notify.ps1 文件头的注释。
常见搜法(关键词)
在插件市场里,搜这些词都能找到它。中文:桌面通知、系统通知、通知横幅、审批通知、审批提醒、提权、任务完成通知、右下角弹窗、穿透请勿打扰、穿透全屏、提示音、闹钟铃声、点击切回窗口;English: Windows toast、notification、approval alert、task completed、Do Not Disturb、Focus Assist、fullscreen、ringtone、focus window。
要是没搜到,通常只是收录还没合并 —— 市场的插件列表来自精选列表,条目合并后才会出现;在那之前按上面的 dsh plugin add 直接装就行。
更新记录
见 CHANGELOG.md。
反馈与贡献
用着不对劲、想加个功能、或者只是想说声「这玩意救了我」——都欢迎开个 Issue。不用讲究格式,中文、English 都行,说清楚你在做什么、期望是什么就够了。
提之前顺手看一眼已有 Issue,避免重复。如果是「通知没弹」这类问题,带上这几样能省好几轮对话:
- DSH 版本(设置页最下方)和 Windows 版本(
winver); - 设置页「桌面通知」那张卡片的截图(上面有「上次结果」和两个钩子的命中计数);
%USERPROFILE%\.dsh\dsh-desktop-alerts.log的最后几行——日志只记通知动作,不记你和模型的对话内容。
想直接改代码也欢迎:Fork → 改 → npm test 和 npm run test:smoke 都绿了再发 PR。动手前在 Issue 里说一声,免得两个人做同一件事。
卸载
cd $env:USERPROFILE\.dsh\profiles\desktop
pnpm remove dsh-desktop-alerts
再从 dsh.profile.bundles 里删掉同名条目,重启即可。遗留的 DeepSeek.Harness.DesktopAlerts 注册表项(HKCU\Software\Classes\AppUserModelId)无害,可手动删除。
No comments yet. Be the first to write one.