🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

系统通知 linanbuan/dsh-system-notify

DeepSeek 客户端
linanbuan1 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

在授权、操控电脑、任务完成或终止时弹出系统通知

30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/6 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/linanbuan/dsh-system-notify.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/06·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 1 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 15 处,展示前 13 条)
  • 执行外部命令固定命令
    lib/native.js:44
    const probe = spawnSync('pwsh', ['-NoProfile', '-NonInteractive', '-Command', 'exit 0'], {
  • 读取本地文件
    lib/native.js:62
    if (!existsSync(binDir)) return []
  • 读取本地文件
    lib/native.js:68
    entries = readdirSync(dir, { withFileTypes: true })
  • 执行外部命令来自配置/变量
    lib/native.js:127
    child = spawn(exe, [], { stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true })
  • 读取本地文件
    lib/native.js:227
    if (this.resolved !== null && existsSync(this.resolved)) return this.resolved
  • 读取本地文件
    lib/native.js:232
    if (existsSync(candidate) && statSync(candidate).isFile()) {
  • 读取本地文件
    lib/native.js:232
    if (existsSync(candidate) && statSync(candidate).isFile()) {
  • 读取本地文件
    lib/native.js:281
    if (existsSync(script)) {
  • 执行外部命令来自配置/变量
    lib/native.js:312
    child = spawn(plan.file, plan.args, {
  • 读取本地文件
    native/samples/invoke-from-node.cjs:10
    if (!fs.existsSync(exe)) {
  • 执行外部命令来自配置/变量
    native/samples/invoke-from-node.cjs:29
    const byStdin = spawnSync(exe, [], {
  • 写入本地文件
    native/samples/invoke-from-node.cjs:38
    fs.writeFileSync(requestFile, JSON.stringify({ ...request, tag: 'dsh-node-sample-file' }, null, 2), 'utf8');
  • 执行外部命令来自配置/变量
    native/samples/invoke-from-node.cjs:39
    const byFile = spawnSync(exe, [requestFile], { encoding: 'utf8', windowsHide: true, timeout: 3000 });
扫描于 2026/11/6(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(140 字)↓

用 Windows App SDK 给 DeepSeek Harness 弹系统通知:授权请求 / 电脑操控 / 任务完成 / 会话终止。检测点在 agent 运行时(cordis 事件),不进 function calling、不改 system prompt、不依赖模型输出。

README

由 DeepSeek 最新模型翻译生成
系统弹窗 · dsh-system-notify DSH 现在不会提醒你任何事:会话要授权、要操控你的电脑、任务跑完了、任务挂掉了、会话被终止了——统统没有声音、没有弹窗,全靠你盯着那个窗口。 这个插件补上这一环:在 agent 运行时盯着这些状态变化,用 Windows App SDK 弹出系统通知。它不是工具、不进 function calling、不改 system prompt——模型什么都不输出,通知照样会来。 - 包名:@local/dsh-system-notify - 类型:宿主插件(没有客户端半边) - 运行环境:Windows 10 1809+ / Windows 11,DSH 桌面端 - 第三方依赖:无(宿主侧零依赖,原生侧只用 Windows App SDK 与 .NET) 目录 - 它解决什么问题 - 检测点 - 为什么不是 tool - 通知长什么样 - 安装 - 配置 - 规则与开关 - 节流 - 诊断接口 - 排障 - 隐私 - 已知限制 - 测试 - 结构 - License 它解决什么问题 | 你在等的事 | 之前 | 装上之后 | | agent 要求授权(提权、写文件、跑命令) | 界面里静静躺着,你不看就永远卡着 | 「会话请求授权」弹窗,带工具名与原因 |
展开完整文档(README 剩余 1 节)
系统弹窗 · dsh-system-notify

DSH 现在不会提醒你任何事:会话要授权、要操控你的电脑、任务跑完了、任务挂掉了、会话被终止了——统统没有声音、没有弹窗,全靠你盯着那个窗口。

这个插件补上这一环:在 agent 运行时盯着这些状态变化,用 Windows App SDK 弹出系统通知。它不是工具、不进 function calling、不改 system prompt——模型什么都不输出,通知照样会来。

- 包名:@local/dsh-system-notify
- 类型:宿主插件(没有客户端半边)
- 运行环境:Windows 10 1809+ / Windows 11,DSH 桌面端
- 第三方依赖:无(宿主侧零依赖,原生侧只用 Windows App SDK 与 .NET)

目录

- 它解决什么问题
- 检测点
- 为什么不是 tool
- 通知长什么样
- 安装
- 配置
- 规则与开关
- 节流
- 诊断接口
- 排障
- 隐私
- 已知限制
- 测试
- 结构
- License

它解决什么问题

| 你在等的事 | 之前 | 装上之后 |
| agent 要求授权(提权、写文件、跑命令) | 界面里静静躺着,你不看就永远卡着 | 「会话请求授权」弹窗,带工具名与原因 |
| agent 要操控电脑(OpenCU 之类) | 同上 | 「电脑操控请求」弹窗,单独一条规则 |
| 一轮任务跑完 | 只能盯着看它停没停 | 「任务完成」,带会话名与轮次 |
| 一轮任务失败/被阻塞/爆上下文 | 同上 | 「任务未完成」,带错误码与消息 |
| 会话被终止 | 同上 | 「会话已终止」(只在终止时还有一轮在跑时才弹) |

检测点

全部挂在 DSH 已经存在的运行时事件上,不新增任何"让模型做决定"的环节:

| 检测点 | 来源 | 覆盖场景 | 默认 |
| approval/asked / approval/decided | session/event(审批服务写的会话事件) | 要求授权、提权、电脑操控请求 | 开 |
| turn/end | session/event(agent-loop 在每轮收尾时追加) | 任务结束 / 失败 / 被阻塞 / 被中断 | 开 |
| session/disposed | cordis 事件 | 会话终止 | 开 |
| agent/error | cordis 事件 | 运行错误(turn/end 的 error 已覆盖大多数情况) | 关 |
| tool/call | session/event(每调用一个工具前追加) | 电脑操控:操控类工具一被调用就提醒 | 开 |

电脑操控为什么挂在 tool/call 上而不是审批事件上:本地运行时调研(docs/research/runtime-hooks.md)确认,OpenCU 那套电脑操控不经过 DSH 的审批服务——它自带一套 app-approvals,源码对 ctx.approval 零引用。所以"只看审批"就等于永远抓不到电脑操控。computer_use / opencu 这类工具被调用时,tool/call 是唯一纯事件级的挂点(tools/pre-execute 载荷更好,但要 return next() 才不打断调用,一个只读观察者没有理由插进那条链)。

同一会话里连续几十次 computer_use 不会刷屏:这条规则带 5 分钟冷却(cooldownMs),节流桶按会话合并。

两条与"贴心"有关的细节:

1. 授权先等一小会儿再弹(scope.approvalGraceMs,默认 1500 ms)。approval/asked 之后往往几十毫秒就 approval/decided——你本来就在界面前点了,或者会话策略是 never 直接自动拒绝。真正值得打扰的是"弹出来之后一秒半还没人决定",那时候 agent 是真卡住了。
2. 子会话默认静默(scope.includeChildSessions,默认 false)。一个 agent 拉起一堆 subagent 时,你不该被十条通知淹没。

为什么不是 tool

需求里写得很清楚:通知不能由 AI 发起。这个插件在结构上就做不到"被模型调用":

- 它没有注册任何工具,ctx.tool、function calling 的 tools 列表里都没有它;
- 它不读也不写 system prompt,模型不知道它存在;
- 它的触发源是 cordis 事件(session/event、session/disposed、agent/error)——这些事件由 DSH 自己的审批服务、agent 循环、会话存储产生,模型输出什么、输不输出,都影响不了它们;
- 监听器只读:不 append 事件、不改审批结果、不碰 agent 循环。cordis 的 emit 是"遇抛即停",所以每个监听器都被 contain() 包住——这里出错只会变成一条警告,绝不饿死其他订阅者。

测试里有一条 test/plugin-contract.test.mjs 用 Proxy 卡死了这个边界:插件只要访问 ctx.tool 或 ctx.systemPrompt,测试就直接失败。

通知长什么样

标题由规则决定,正文由模板渲染({session} 是会话标题,没有标题时用 cwd 最后一段):

┌─────────────────────────────────────────┐
│ DeepSeek Harness │
│ 会话请求授权 │ │ pwsh 需要授权:danger-full-access · 迁移脚本 │ └─────────────────────────────────────────┘

紧急程度映射到 Windows 的通知场景与提示音:授权/失败类用 urgent(Scenario.Urgent),完成类用 default。

安装

插件是标准 DSH bundle 包:package.json 里的 dsh.bundle.patch 指向 cordis.patch.yml,patch 里一条 insert 就把宿主半边挂进 profile。

方式一 · 在 DSH 桌面端里装(推荐)

用桌面端的插件管理器安装本目录。它会把包写进当前 profile 的 dsh.profile.bundles,不需要命令行。

方式二 · 手工写进 profile

在 profile 的 package.json 里加一条依赖和一个 bundle 条目(路径换成你本机的插件目录):

{
"dependencies": {
"@local/dsh-system-notify": "link:<本插件目录的绝对路径>" },
"dsh": {
"profile": {
"bundles": ["...", "@local/dsh-system-notify"]
}
}
}

然后在 profile 目录里装一次依赖并重启 DSH。

首次使用:编译原生助手

通知真正的发送端是 native/ 下的 Windows App SDK 小助手(Node 自己弹不出系统通知)。有两种情况:

- 自动:sink.autoBuild 默认开启。第一次要发通知时,插件会自己跑 native/build.ps1(没有这个脚本就退到 dotnet build native/.csproj -c Release),构建期间的通知会排队等它;
- 手动:自己先编一次,之后启动零延迟:

需要 .NET SDK 10(原生侧目标 net10.0-windows10.0.19041.0)

pwsh -NoProfile -File native/build.ps1

构建产物落在 native/bin/Release/(已被 .gitignore 排除)。想确认发送端是否通,用诊断接口的 /test(见下),或直接跑助手自检:

nativeinReleaseDshNotificationSink.exe --selftest

配置

写在 profile 的 cordis.patch.yml 里,按 id 覆盖:

- id: system-notify
config:
enabled: true

sink:
provider: windows # windows | log | none
helperPath: '' # 留空=自动在 native/bin 下找 appName: DeepSeek Harness appIconPath: '' # 留空=用 native/assets 里的图标 timeoutMs: 5000 autoBuild: true fallbackProvider: log # windows 发送失败后降级到哪

throttle:
dedupeWindowMs: 8000 # 同一件事的重复通知窗口 minIntervalMs: 1000 # 同一类事件的最小间隔 maxPerMinute: 15 # 全局每分钟上限 quietHours: start: '' # 'HH:mm',留空=不启用 end: '' allowHighSeverity: false # 静音时段内高优先级是否仍放行

scope:
includeChildSessions: false # 子 agent 会话要不要弹 approvalGraceMs: 1500 # 授权通知的等待时间,0 = 立刻弹

limits:
maxTitleChars: 72
maxBodyChars: 220
queueLimit: 32

所有字段都有默认值,写错的值会被夹回合法范围,并在日志里留一条 系统弹窗配置:… 说明——配置写错不会让插件挂不上,但也不会悄悄生效。

规则与开关

规则是一张有序分派表,第一条 match 命中的规则决定这条通知的归属与文案:

- 命中但 enabled: false=吞掉这条通知,不再往下找更宽的规则。于是「关掉电脑操控弹窗」就真的不会再收到电脑操控弹窗,而不是悄悄降级成一条泛泛的「会话请求授权」;
- match 里没写的约束等于通配;
- toolName 是不区分大小写的正则。

内置七条:

| id | 检测点 | 默认 | 说明 |
| computer-control | approval | 开 | 走审批链路的操控类工具(工具名匹配 computer|cua|opencu|screen|mouse|keyboard) |
| approval | approval | 开 | 兜住其余所有授权请求 |
| computer-control-call | tool-call | 开 | 操控类工具被调用就提醒,5 分钟冷却 |
| turn-completed | turn-end | 开 | reason.kind = completed |
| turn-failed | turn-end | 开 | error / blocked / max-tokens |
| turn-aborted | turn-end | 关 | 你亲手按的停止,通常不需要再弹一次 |
| session-end | session-end | 开 | 会话销毁时那一轮还在跑 |
| session-end-idle | session-end | 关 | 会话销毁时本来就空闲(几乎每次退出程序都会命中,默认不打扰) |
| agent-error | agent-error | 关 | 与 turn-failed 重复,按需打开 |
内置一共九条。写自定义 rules 时 signal 可取值:approval、tool-call、turn-end、session-end、agent-error;cooldownMs(0–3600000)是该规则的冷却时间,0 表示沿用全局 throttle.minIntervalMs。

自定义规则(rules 一旦写了就整体替换内置表,想保留内置的请一并抄过去):

- id: system-notify
config:
rules:
- id: approval
enabled: true
signal: approval # approval | tool-call | turn-end | session-end | agent-error
match:
toolName: 'bash|pwsh' # 可选,正则 title: '要你点头' body: '{tool} 在等授权{reasonText} · {session}' tag: approval # tag 最长 16 字符(Windows 限制) urgency: high # low | normal | high scenario: urgent # default | urgent | reminder | alarm

可用占位符:{session} {project} {sessionId} {cwd} {tool} {reason} {reasonText} {turn} {reasonKind} {outcomeText} {error} {time}。写错的占位符会原样留在通知里,方便你一眼看出配置错了。

节流

规则通过之后还有四道闸门,命中即拒绝,拒绝原因都进统计(能在诊断接口里看到):

| 闸门 | 作用 | 默认 |
| duplicate | 同一个 dedupeKey(同一次审批、同一轮结束)在窗口内重复 | 8000 ms |
| interval | 同一个 throttleKey 距上次发送太近 | 1000 ms |
| rate | 全局每分钟上限(滑动窗口) | 15 条 |
| quiet | 落在静音时段内 | 不启用 |

被拒绝的信号不占名额:只有真正发出去的那一次才记账。想彻底静音一段时间,比 maxPerMinute: 1 更直接的办法是 quietHours:

throttle:
quietHours:
start: '23:00'
end: '07:00'
allowHighSeverity: true # 半夜的授权请求还是弹,完成通知不弹

发送是串行的:通知按事件顺序一条条发,队列满了(默认 32 条)就丢最旧的并警告一次。

诊断接口

挂了 connection 服务时(正常桌面端都有),插件注册三个 POST 路由:

配置摘要、规则表、节流统计、发送端状态、最近一次发送结果

curl -X POST http://127.0.0.1:<端口>/api/system-notify/status

立刻发一条测试通知(绕过节流,用来验证 Windows App SDK 链路)

curl -X POST http://127.0.0.1:<端口>/api/system-notify/test -d "{}"

清空节流状态

curl -X POST http://127.0.0.1:<端口>/api/system-notify/throttle/reset

/status 里最该先看的两处:sink.detail.helper.located(有没有找到原生助手)与 counters.skipped(到底是被关掉了、被节流压掉了,还是没有规则命中)。

排障

一条通知都没有

1. 看 /api/system-notify/status 的 sink.detail.helper:located: null 说明原生助手没构建成功,lastError 里会写原因;
2. 看 counters.skipped:child-session 表示全是子会话(打开 scope.includeChildSessions),rule-disabled 表示规则被你关掉了;
3. 看 Windows 设置 → 通知:DeepSeek Harness 这一项是不是被关掉了。

弹是弹了,但显示的是 PowerShell 的图标/名字

助手在启动早期还没有设置 AppUserModelID。--selftest 里的 aumidRegistration 与 processAumid 能确认注册情况;注册在 HKCU 下,普通用户权限即可,不需要管理员。

构建失败

dotnet --list-sdks 要有 .NET SDK 10(原生侧目标是 net10.0-windows10.0.19041.0)或更新版本,nuget.org 要可达。失败信息会以一条 系统弹窗:构建失败(退出码 …) 出现在 DSH 日志里,修好之后重启 DSH,或先手动跑一次 native/build.ps1。

插件调用 native/build.ps1 时优先用 pwsh(PowerShell 7)。原因:Windows PowerShell 5.1 会按系统 ANSI 代码页解码无 BOM 的 UTF-8 脚本,脚本里的中文注释会让它误报"缺少结束符 }"——这条错看起来像语法错,其实是编码错。没有 pwsh 时插件会退回 5.1 并在日志里提示。

我不想要通知了

- 暂时:enabled: false(检测照跑,一条都不发);
- 只关某类:把对应规则的 enabled 设为 false;
- 彻底:从 profile 的 bundles 里删掉这个包。

隐私

通知内容只在本机生成、只交给本机的原生助手,任何字段都不出网。默认只带:会话标题(或 cwd 最后一段)、工具名、授权原因、轮次与结束原因。不读取对话正文、不读取工具输出、不写数据库。

已知限制

- 只有 Windows 有发送端。其他平台 sink.provider 会退到 log(只写日志),检测与节流照常工作;
- 通知里的按钮点了不会有任何回调:原生助手是「一次调用一个进程」,Show() 之后进程即退出,没人监听 NotificationInvoked。插件因此不发按钮(发了会让人误以为点了有用);
- 原生助手是 framework-dependent 的,运行需要 .NET 10 运行时(装了 SDK 10 的构建机自带);另一台只部署不构建的机器上,要么装运行时,要么改成 self-contained 发布;
- 同 tag 的通知不会互相替换,每条都是通知中心里的独立条目(Windows App SDK 不自动替换);
- 单次发送约 0.5 秒(每次都要重新 Register()),所以通知走串行队列,不是并发;队列上限 32 条,超了丢最旧的;
- Windows App SDK 路径失败时,原生助手会按设计降级到旧版 ToastNotificationManager(按钮、urgency 等特性可能不完全生效),降级信息写在 stderr 与 /status 里;
- session/disposed 的真实语义:关会话标签、归档会话、子会话结束都不触发它;它只在关主窗口(≈退出程序)与插件重载时成批到达。所以 session-end 的文案是「第 N 轮没有跑完(会话已销毁)」,而不是「你关掉了会话」;空闲销毁由默认关闭的 session-end-idle 负责,否则每次退出都会抖一串。
- 硬杀/崩溃没有 turn/end:进程被 SIGKILL 或崩溃时,那一轮不会写 turn/end,也就不会通知。要兜住只能在下次启动做补偿自检(遍历会话找末尾未闭合的 turn/start),当前版本没做。
- 退出路径上的通知是尽力而为:宿主关停预算约 5 秒,桌面主进程最多再等 10 秒就 SIGTERM→SIGKILL,插件在插件卸载时会放弃还没发出的队列(并留一条警告)。

测试

node --test "test/.test.mjs"

72 条用例,覆盖配置归一化、信号翻译、规则优先级、节流(含跨零点静音)、文案渲染、判定顺序、发送端降级、插件契约(含「不许碰 ctx.tool / ctx.systemPrompt」的 Proxy 断言),以及一组真 cordis 上下文的冒烟测试(装得上、收得到事件、卸载后不再发)。

那组真 cordis 测试在裸仓库里会跳过(解析不到 @deepseek-ai/cordis)。想强制运行,把 DSH_CORDIS_PATH 指到一个能解析依赖的 cordis 目录即可。

除了单测,这几条是真的跑过的:

- 真 cordis 上下文 + windows 发送端:触发一次授权事件,Windows 通知中心里出现 tag=approval、scenario=urgent、正文为渲染结果的条目(--history 可查);
- 冷构建:删掉 native/bin 后由插件自己 autoBuild(走 native/build.ps1)→ 找到 exe → 真实发出通知,全程约 4 秒(NuGet 缓存已热);
- 突发压力:一轮里 20 次工具调用(含 6 次 computer_use)+ 5 次并发授权请求,最终只弹 2 条(冷却与节流按预期生效)。

结构

index.js 插件入口:订阅事件、串行发送、诊断路由 lib/config.js 配置归一化与默认值(手写校验,零依赖) lib/signals.js 运行时事件 → 信号(会话标题/轮次的记忆) lib/rules.js 有序规则表与匹配 lib/throttle.js 去重 / 间隔 / 每分钟上限 / 静音时段 lib/engine.js 判定顺序:信号 + 规则 + 节流 → 通知或拒绝理由 lib/format.js 占位符渲染、单行化、截断 lib/sinks.js windows / log / none 发送端与降级 lib/native.js 原生助手定位、构建、调用 native/ Windows App SDK 通知助手(C#) test/ 72 条用例 docs/native-sink.md 原生端协议:stdin/stdout JSON、错误码、AUMID、降级路径 docs/research/ 运行时检测点调研(每条结论带 文件:行号) docs/log/project-log.md 项目日志(按轮次追加)

License

MIT
预览分享卡片长什么样 ↓linanbuan/dsh-system-notify
分享 · DeepSeek Harness Hub
linanbuan/dsh-system-notify

在授权、操控电脑、任务完成或终止时弹出系统通知

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部