Skip to content

dsh-desktop-notifications

Verified

dsh-desktop-notifications · v1.0.0 · MIT

Windows desktop toast notifications for DeepSeek Harness (DSH): approval requests, user questions, run completion, errors and sign-in prompts — every toast led by the conversation name.

Install

dsh plugin add dsh-desktop-notifications

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

dsh-desktop-notifications

给 DeepSeek Harness(dsh)用的 Windows 桌面通知插件 —— DSH 需要你操作(申请权限、提问)或干完活(完成、出错、需要登录)时, 在 Windows 桌面右下角弹出原生 Toast,不用一直盯着浏览器标签页。

每条通知的第一行都是会话名称,多个对话同时跑时一眼分辨是谁在叫你; 授权 / 提问类通知零延时立即弹,并且正文会自动去掉 markdown 符号 (不会在通知里看到 **、`、~~)。

小明的课表整理                                  <- 第一行:会话名称(所有通知都是)
需要你确认权限 · pwsh · 删除 Downloads 下的文件    <- 第二行:具体事项

dsh-plugin · 仅 Windows 宿主插件 · 零依赖 · 无需构建 · MIT

特性

🔔 只发重要的事 申请权限、提问、任务完成、执行出错、需要登录
🗂️ 第一行永远是会话名 从会话日志折叠标题,不同对话的通知不会再混淆
⚡ "需要你"零延时 授权/提问一出现就弹(可分别配置延时,只在仍未被回答时才弹)
🧹 自动去 markdown 去掉 **、`、~~、[文字](链接);下划线与文件名保留
🪟 真正的系统通知 归属 DSH 自己的 AppUserModelID(com.deepseek.dsh),显示为 DeepSeek Harness,并进入通知中心
🧾 审计日志 每条通知记一行(~/.dsh/dsh-desktop-notifications.log),排查"为什么没弹"有据可查
🪶 无硬依赖 纯 ESM + 一个 PowerShell 脚本,无编译器、无打包器、无原生模块(@deepseek-ai/schemastery 是可选 peer,只用来生成设置表单)

触发时机

时机 事件 第二行 何时弹
需要你同意权限 approval/request 需要你确认权限 · <工具> · <原因> 立即
需要你选择 / 作答 user-questions/request 正在等待你的选择 · <问题> 立即
任务完成 agent/status → idle 任务完成 · 用时 …,可以回来查看结果了。 空闲满 4 秒
执行出错 agent/error 执行出错 · <错误摘要> 立即
需要登录 / 登录过期 deepseek-account/* 需要登录 · … 立即
子代理结束 subagent/end <子任务名> 已结束。 立即(默认关闭)
工作流结束 workflow/end 工作流运行已结束(…)。 立即(默认关闭)

两个防打扰设计:相同标题+正文 1.5 秒内只弹一次;"完成"要求 agent 空闲持续 4 秒才弹, 这期间又进入下一轮(例如 /goal 自动续跑)就取消这次通知。

安装

# 从 GitHub 安装
dsh plugin --profile desktop add github:FANLS05/dsh-desktop-notifications

# 或者从本地目录安装
dsh plugin --profile desktop add link:D:\path\to\dsh-desktop-notifications

然后在插件管理里确认 desktop-notifications 这一行是启用的即可(bundle patch 默认就是启用状态)。

环境要求:Windows 10/11 + DSH 桌面版(Node 20+ 由宿主提供)。

不想等真实事件时,可以直接自检:

node "$env:USERPROFILE\.dsh\plugins\dsh-desktop-notifications\scripts\notify-test.mjs"
node "$env:USERPROFILE\.dsh\plugins\dsh-desktop-notifications\scripts\notify-test.mjs" "**标题**" "正文 `code`"

配置

在 GUI 里改(推荐)

插件导出了 Config schema,DSH 会把它当作这一行的"设置文档": 打开 设置 → 插件,展开 dsh-desktop-notifications bundle,点 desktop-notifications 这一行的配置按钮, 下面所有开关都会以表单形式呈现,保存后立即生效(不用重启)。

在 profile patch 里改

在 %USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml 里给这一行加 config:

- id: desktop-notifications
  config:
    notifySubagent: true     # 子代理结束也通知
    notifyWorkflow: true     # 工作流结束也通知
    sound: false             # 静音(通知仍在)
    stripMarkdown: false     # 保留原始 markdown
    approvalDelayMs: 1500    # 只在仍未被回答时才弹
    questionDelayMs: 1500
    notifyOnMount: true      # 每次加载弹一条,便于确认通道正常
字段 默认值 说明
enabled true 总开关
appId com.deepseek.dsh 通知归属的 AppUserModelID
sound true 是否播放提示音
useElectron true 宿主是 Electron 主进程时优先用其原生通知
powershellPath "" 指定 PowerShell,空则自动找 powershell.exe → pwsh.exe
notifyApproval / notifyQuestion / notifyComplete / notifyError / notifyAccount true 各类事件开关
notifySubagent / notifyWorkflow false 可选事件(默认关)
notifyOnMount false 加载时自检通知
onlyRootSessions true 完成类通知只针对根会话
useSessionTitle true 用会话名当第一行
stripMarkdown true 去掉标题/正文里的 markdown
titleMaxChars 60 第一行截断长度
titleCacheTtlMs 30000 会话名缓存时长
approvalDelayMs / questionDelayMs 0 0 = 立即;调大则只在未被回答时弹
idleGraceMs 4000 空闲多久才算"完成"
dedupeWindowMs 1500 相同通知去重窗口
bodyMaxChars 180 第二行截断长度
logEnabled / logPath / logMaxBytes true / "" / 262144 审计日志(默认 ~/.dsh/dsh-desktop-notifications.log)

审计日志记的是清洗之后的最终文本:

Get-Content "$env:USERPROFILE\.dsh\dsh-desktop-notifications.log" -Encoding UTF8 -Tail 20

实现要点

  • 两条投递通道:优先用 Electron 的 Notification(宿主真是 Electron 主进程时); 否则起一个 PowerShell 子进程跑 lib/toast.ps1,脚本内部再三级降级: DSH 的 AppUserModelID → Windows PowerShell 内置 AppUserModelID → 通知区域气泡。
  • 为什么要起子进程:这里的 DSH 宿主其实是 Electron 的 utility 进程,没有 Notification API。
  • detached: true 是坑:在 Windows 上 detached 启动 powershell.exe 会让它 ~130ms 就以 退出码 0 结束、脚本根本没执行;同样的命令行只要不 detached 就正常。这一个参数决定了"能不能收到通知"。
  • prepend 再委托:approval/request / user-questions/request 是瀑布事件,谁先应答谁"认领"。 通知监听器用 { prepend: true } 抢在最前面发通知,然后照常 next(),不影响原有应答方。
  • 会话名的取值链:sessionQuery.readTitle() 折叠日志里的标题;事件不带会话时(登录提醒、 自检)依次退到"最近活动的对话" → "日志里最新的对话" → DSH。

开发

lib/index.js 是刻意做薄的入口:DSH 的 loader 按包名缓存已加载的模块且不会重新 import, 所以入口用 import('./impl.js?v=' + Date.now()) 绕开缓存 —— 改 lib/impl.js 只需要在插件管理里把该行禁用再启用一次,不用重启宿主、也不用改包名; 只有改 lib/index.js 本身才需要重启。

没有构建步骤:仓库里的 JavaScript 就是最终产物。

已知限制

  • 仅在 Windows 生效;其它平台加载后不做任何事。
  • Windows 的「专注助手 / 勿扰模式」会压制 Toast —— 系统行为,插件绕不过去(通知仍会进通知中心)。
  • 刚创建的会话可能还没有标题(DSH 异步生成),此时第一行会退到上一级。
  • 去 markdown 是"宁可多去":正文里单独出现的 *(例如 *.txt)也会被去掉, 需要原文就设 stripMarkdown: false。

同类插件

DSH 生态里的通知类插件已经不少,见 awesome-dsh-plugin › Notifications & Integrations (收录了 35 个)。比较有代表性的: hotpot-labs/dsh-notifier-plugin(跨平台,带设置卡片)、 lsq-dsh-plugins/dsh-windows-notifications(Windows 通知 + 应用内卡片)、 masknull/dsh-webhook-notifier(HTTP Webhook)、 zhangDSK-Xu/dsh-sound-alert(提示音 + 提醒卡片)。

本插件的差异点:零依赖、无需构建、第一行是会话名、授权/提问零延时、自动去 markdown、带审计日志。

许可

MIT