← 返回列表
未验证
本插件由 DeepSeek Harness官方 cordis / @deepseek-ai/dsh- 插件栈驱动,结合…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/17 · 已提供中文文档
DSH Web GUI 的审批提醒插件:待处理审批/计划审查/问题提醒(提示音、标签页标题与 favicon 徽标、PWA 徽标、审批中心停靠栏、系统通知),以及完成、任务失败、断开连接和 429 运行时错误提醒。
综合分
27.6
GitHub 分
27.6
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add renpengfei1027/dsh-web-notify该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/17(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-api-remotes@deepseek-ai/dsh-settings用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-web-notify
npm version
License: MIT
English version · 默认中文
本插件由 DeepSeek Harness(官方 cordis / @deepseek-ai/dsh- 插件栈)驱动,结合 DeepSeek-V4-Flash-0731 模型参数的官方事件帧构建。
当前 DeepSeek Harness 处于开发预览快速迭代期,推荐以开发调试模式(link: 本地仓库)挂载本插件:改代码后 npm run build 即时生效,配合 window.__NOTIFICATIONS__ diagnostics 排查问题最顺手;当然也提供了 npm 一键挂载的备选方式。
DSH Web GUI 的审批注意力插件:当任意会话出现待处理的审批 / 计划审批 / 提问时,浏览器不再静默——提示音、标签页标题与 Favicon 徽标、OS 通知、右下角通知中心同步呈现;会话完成、任务失败、连接掉线、模型/工具异常(429 配额等)也有提醒。检测管道覆盖全部会话行(含子代理);受运行时委派策略约束,被委派的子代理实际上不会产生待审批/提问,其完成 / 失败 / 异常提醒照常生效(详见下文「子代理通知可达性」)。
纯插件形态:host 半(lib/index.js)+ client 半(lib/client.js,loader 格式),通过 profile patch 挂载。
快速上手(推荐路径)
① 克隆仓库 → 安装依赖 → 构建产物
↓
② link:仓库目录 挂入 web profile
↓
③ 放行设置命名空间(patch 脚本)
↓
④ 重启 dsh web → 设置页找到「通知」卡片 → 按自己需求开关通道/音量/免打扰
↓
⑤ DevTools 控制台观察 window.__NOTIFICATIONS__ :
applied / cardRegistered / monitors / lastHeartbeatAt
hostStatuses / hostStatusCounts ← 宿主投递的 job 状态词汇
feedCounters ← 每类事件计数
jobSamples / seenStatuses ← 浏览器侧采样环
demo() / demoSound() ← 一键 UI / 音频 demo
场景应用
1. 待处理审批 / 计划审批 / 提问到达
任意会话(包括未打开过的子代理)出现 pendingInteraction 即触发;同一 (会话, kind) 在冷却期(默认 5s)内不重复报警。
| 通道 | 表现 |
|---|---|
| 提示音 | WebAudio E5-G5-B5 三连音 |
| 标签页标题 | ⚠ N 待审批 — ,MutationObserver 对抗 shell 标题写入 |
| 标签页 Favicon | 32×32 红底白字徽章(≤9 显示数字,>9 显示红点) |
| OS 通知 | 按会话 tag 去重,点击跳转对应会话 + 聚焦窗口;approval 类型 requireInteraction: true 持久显示直到处理 |
| PWA 任务栏徽标 | 已安装的 PWA 窗口在任务栏/应用图标显示数字(navigator.setAppBadge) |
| 通知中心 Dock | 右下角 FAB(实时计数)+ 展开面板列出全部待处理;按会话标题 + kind 圆点着色「去处理」一键跳转;归零自动收起;新到达时 FAB 脉冲高亮 |
当前会话降级:页面可见且新审批属于当前打开的会话时,提示音与 OS 通知静默(用户眼睛就在这),仅保留视觉通道;切走或最小化后恢复全通道。
子代理通知可达性:会话列表是客户端 lineage 展开后的同一张表(子代理行 origin: 'subagent' 按 parentSessionId 嵌套),因此检测管道天然覆盖子代理行——一旦某个子代理行挂上 pendingInteraction,提示音 / 徽标 / OS 通知 / Dock 全通道照常触发。但按当前 DSH 委派语义,被委派的子代理实际上不会产生这三种待处理状态:
- 审批:dsh-subagent 在委派边界把子代理的审批策略固定为 'never'(无论父级策略如何),任何需审批操作(如 sandbox 升权)被确定性拒绝,不产生 approval/requested 帧,也就没有 pendingInteraction;
- 提问 / 计划审批:dsh-user-questions 对受父级持有的调用方抛 DELEGATED_CALLER,子代理只能把未决问题写进最终结果,由父级代为询问;计划审批只是 intent.kind === 'plan-review' 的提问分类,同样不会产生;
- 因此通知中心里只可能出现父会话的审批条目,子代理行永远不会亮起待处理点。
与之相对,子代理的完成、任务失败、模型/工具异常走 session/event 流与 jobs 归集,覆盖所有会话,提醒照常生效。
2. 会话 / 子代理完成
任意会话 turn/end 完成 → 完成 toast 卡片(右上角,done 变体)+ 完成单音 + 可选 OS 通知。
- 页面可见 + 当前会话完成:toast / OS 静默,仅兜底播一声软完成音(用户可能滚走)
- 页面隐藏:无 toast(看不到),改用 tab 标题脉冲 + PWA 角标 + 提示音 + OS 通知
3. 任务失败
jobsBySession 中 job 状态为 failed / killed、或 completed 但 detail 非空且非 exit code: 0(DSH 真机异常终态映射)→ error 变体 toast + 提示音 + 可选 OS 通知。按 job 注册号只报一次。
4. 模型 / 工具运行异常(429 配额等)
宿主订阅官方 session/event 流,捕获 llm/retry(429 配额 / 限流)、turn/end 的 error / max-tokens / interrupted、tool/result 的 error / isError → error 变体 toast(错误原文进 body,截 240 字符)+ 提示音 + 可选 OS 通知。同会话同 kind 在冷却期内不重复。
5. 掉线 / 重连
共享 connection 服务断线持续超过 connectionAlertAfterMs(默认 10s)→ warning toast + 提示音;恢复时轻 toast + 完成单音。快速闪断(未跨阈值)不报。启动期从未连上过不报。
配置参数
设置卡片注册进 DSH Web 设置页的「插件配置」→「通知」(官方 settings.plugin.item 槽位),改完即生效(120 ms debounce 热重配,无需重启)。
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
| sound | boolean | true | 提示音主开关 |
| volume | number 0–1 | 0.15 | 提示音音量 |
| badge | boolean | true | 标签页标题徽标 + Favicon 徽章 + PWA 任务栏徽标(同一开关) |
| toast | boolean | true | 一次性事件卡片(完成 / 失败 / 断线) |
| notify | boolean | true | OS 通知主开关(首次触发在下一个用户手势请求 Notification 权限) |
| dock | boolean | true | 通知中心 Dock(右下角 FAB + 展开面板) |
| completion | boolean | true | ① 会话 / 子代理完成提醒 |
| completionSound | boolean | true | 完成时播放轻单音 |
| completionNotify | boolean | true | 完成也走 OS 通知 |
| connection | boolean | true | ② 掉线 / 重连提醒 |
| connectionAlertAfterMs | number ≥1000 | 10000 | 断线持续超过该毫秒数才提醒 |
| jobFailure | boolean | true | ③ 后台任务失败提醒 |
| failureNotify | boolean | false | ③ 任务失败 + ④ 任务异常共用一个 OS 通知开关 |
| agentError | boolean | true | ④ 模型 / 工具运行异常(429 配额、输出上限、中断、工具失败) |
| cooldownMs | number ≥0 | 5000 | 同会话同 kind 去重冷却 |
| alertKinds | string[] | ["approval","plan-review","question"] | 触发待处理提醒的 kind 白名单 |
| quiet | object | {enabled:false, start:"23:00", end:"08:00"} | 免打扰时段(仅静音,视觉通道照常) |
| soundResolved | boolean | false | 审批解决时播放下行柔和音 |
| diagnostics | boolean | true | on-device 观测仪(采样最近 60 次会话快照,含 job 状态;状态集合始终自动收集) |
几个常用调法示例:
- 只要审批不要失败/断线:completion=false、connection=false、jobFailure=false、agentError=false
- 只想听响,不喜欢卡片弹:toast=false、notify=false,保留 sound + badge + dock
- 夜间开发免打扰:quiet.enabled=true、quiet.start=22:00、quiet.end=09:00,提示音全关、视觉照常
- 只接 PWA / 任务栏,系统通知弹了嫌吵:notify=false、badge=true、dock=true
安装
DSH 插件通过 dsh plugin 命令安装进 profile(dsh web 对应 web profile)。考虑到 DeepSeek Harness 当前处于开发预览快速迭代期,推荐开发调试模式挂载,便于即时迭代与 diagnostics 排查;当然也提供了 npm 一键挂载的备选方式。
前提条件
- Node.js >= 22
- pnpm — dsh plugin 内部使用 pnpm 安装依赖:npm install -g pnpm
- dsh CLI — 若未全局安装,所有 dsh 命令前缀 npx @deepseek-ai/dsh,如 npx @deepseek-ai/dsh plugin --profile web add dsh-web-notify
方式一:开发调试模式挂载(当前推荐)
1. 克隆仓库
git clone https://github.com/renpengfei1027/dsh-web-notify.git
cd dsh-web-notify
2. 安装依赖并构建(需要 Node.js >= 22)
npm install
npm run build
3. 把仓库挂进 web profile(link: 指向仓库根目录)
dsh plugin --profile web add link:$(pwd)
Windows PowerShell: dsh plugin --profile web add link:$PWD.Path
4. 重启 dsh web,设置页「插件配置」下即出现「通知」卡片
dsh web
方式二:npm 一键挂载
dsh plugin --profile web add dsh-web-notify
AI 编码工具 / 沙箱环境注意事项
在 TRAE、Cursor 等 AI 编码工具中安装本插件时,需注意:
1. 沙箱写限制:AI 工具的沙箱通常阻止写入 ~/.dsh/ 目录,而 dsh plugin 和 dsh web 都需要写 profile 文件。必须在 AI 工具外部的普通终端中执行这些命令。
2. 切勿手动 npm install:手动把包塞进 ~/.dsh/profiles/web/node_modules/ 会绕过 dsh plugin 的依赖链接逻辑,导致插件的 @deepseek-ai/ peer 依赖与 DSH host 的模块树脱节,settings 服务不可达,命名空间注册静默失败(卡片永远只读)。
3. 始终用 dsh plugin --profile web add:这是唯一正确的安装方式,它会通过 pnpm 正确链接依赖、更新 package.json 和 cordis.patch.yml。
安装后校验
安装完成并重启 dsh web 后,检查以下文件和指标:
| 校验项 | 位置 / 命令 | 预期 |
|---|---|---|
| profile dependencies | ~/.dsh/profiles/web/package.json | dependencies 含 dsh-web-notify |
| profile patch | ~/.dsh/profiles/web/cordis.patch.yml | 含 - id: notifications 插入行 |
| 包已安装 | ~/.dsh/profiles/web/node_modules/dsh-web-notify/ | 目录存在,含 lib/、cordis.patch.yml |
| 命名空间已注册 | DevTools Console: __NOTIFICATIONS__.scopeStatus | "ready"(非 "unavailable") |
| 卡片可编辑 | 设置页 → 插件配置 → 通知 | 字段可编辑(非只读) |
放行设置命名空间(可选,但推荐)
DSH 官方 apiproxy 的 WEB_SETTINGS_NAMESPACES 是硬编码白名单,第三方命名空间默认只读。运行一次本仓库的 patch 脚本把 notifications 注入白名单:
node scripts/patch-apiproxy.mjs
之后设置卡片可读可写;不放行则卡片只读,DEFAULTS 生效。dsh 升级后需重跑此脚本(脚本幂等,重跑安全)。
为什么必须 patch(官方暂无优雅注入方式)
DSH 官方把 settings 白名单(WEB_SETTINGS_NAMESPACES)与 host 事件转发白名单(API_REMOTE_FORWARDED_EVENTS)硬编码在包里,暂不开放插件注入(官方注释标记为 deferred work,见 deepseek-ai/deepseek-harness),所以只能 patch bundle。脚本在运行时用 os.homedir() 定位 npx 缓存并自动发现 _npx/ 目录,换机器无需改路径。
Diagnostics 观察调试
插件加载后,在 DSH Web 页面打开 DevTools Console:
// 插件是否完整挂载
__NOTIFICATIONS__.applied, __NOTIFICATIONS__.cardRegistered
true, true
// 绑定到了哪个 settings provider,sessions / connection 服务是否可用
__NOTIFICATIONS__.binder, __NOTIFICATIONS__.sessions, __NOTIFICATIONS__.connAvailable
"settingsScope", true, true
// 宿主事件通道健康度(~30s 一次心跳;lastHeartbeatAt 不变表示 host feed 断了)
__NOTIFICATIONS__.feedCounters, __NOTIFICATIONS__.lastHeartbeatAt
{ heartbeat: 4, "agent-error": 1, … }, 1756789012345
// 宿主投递的 job 状态全量词汇(可对照 sentinel / lifecycle 对哪些终态做判断)
__NOTIFICATIONS__.hostStatuses, __NOTIFICATIONS__.hostStatusCounts
["failed","killed","completed","running",…], { completed: 8, failed: 2, … }
// 浏览器侧采样(diagnostics=true 时开启,最近 60 帧)
__NOTIFICATIONS__.jobSamples[0]
{ ts, sessionId, sessionTitle, jobs: [{ jobId, status }], alerts: [] }
// 一键 demo 卡片 / demo 提示音(排查 UI 与音频是否能响)
__NOTIFICATIONS__.demo("error") // 弹 error 变体卡片
__NOTIFICATIONS__.demoSound(0.3) // 以指定音量播放完成单音
生效
插件集合变更必须重启 dsh web——仅刷新页面不会注册新包(官方 client-modules 文档明确:包元数据按名缓存且永不过期)。白名单 patch 之后也要重启。
验证
1. 设置页「插件配置」下出现独立的「通知」卡片,字段可编辑
2. 触发一个待审批:标签页标题出现 ⚠ 1 待审批 —,Favicon 显示红底数字 1,右下角 Dock 出现 FAB 与列表,播放三连音,OS 通知弹出(首次需授权)
3. 点击 OS 通知或 Dock 行的「去处理」→ 窗口聚焦并打开对应会话
4. 完成一个会话:右上角弹完成 toast + 完成单音
5. DevTools 控制台可见 [notifications] 前缀的日志;window.__NOTIFICATIONS__ 暴露 apply 分步记录与 jobSamples 采样环
卸载
dsh plugin --profile web remove dsh-web-notify
或删除本地 profile 的 cordis.patch.yml 插入行与 node_modules junction。
限制
- 提醒粒度是会话级(列表行只有 kind 状态);任务失败能到 job 级(含命令 label 与 exit detail),模型 / 工具异常走事件流原文(截 240 字符)
- 子代理可达性:子代理行位于检测管道内(与会话同一张 lineage 表),但被委派子代理的审批策略固定为 'never'、提问被拒,实际不会产生待审批/计划审批/提问条目——只可能出现父会话的审批;完成 / 失败 / 异常提醒照常覆盖子代理(见上文「子代理通知可达性」)
- 提示音需要页面有过用户手势(浏览器音频策略);无手势时静默降级为视觉通道
- OS 通知权限在首次提醒后的下一次点击时请求;若 Windows 不弹,检查浏览器站点设置(127.0.0.1 通知权限)与 Windows「专注助手」
- 设置卡片走 settings scope;若宿主 apiproxy 未放行第三方命名空间,卡片只读,DEFAULTS 生效
项目结构
dsh-web-notify/
├── package.json # dsh.client.platform=web + inject + dsh.bundle.patch
├── cordis.patch.yml # 插件行 insert
├── src/
│ ├── index.ts # host 半:settings 命名空间 + systemPrompt 通告 + 事件流转发
│ └── client/ # 浏览器半(零 @deepseek-ai 运行时依赖)
│ ├── index.ts # 入口:apply/inject/mount + settings scope 热重配 + 卡片注册
│ ├── types.ts # 本地结构类型 + DEFAULTS
│ ├── locales.ts # zh/en 词典 + t()
│ ├── channels.ts # WebAudio 提示音 / 免打扰 / OS 通知 / jumpToSession
│ ├── badge.ts # 标题徽标 + Favicon 徽章(canvas)+ PWA 徽标
│ ├── stores.ts # toast / dock 两个 uSES store
│ ├── toast-ui.tsx # toast 卡片 + 堆栈
│ ├── toast-mount.tsx
│ ├── sentinel.ts # 待处理边沿哨兵(Dock 承担视觉,仅打脉冲)
│ ├── lifecycle.ts # ① 完成 + ③ 任务失败 + ② 连接监视
│ ├── dock.ts # Dock FAB + 面板 + mount + startDock
│ └── settings-card.tsx # 设置卡片
└── scripts/
├── build.mjs # esbuild 构建 → lib/{index.js,client.js}(loader 包装)
├── smoke.mjs # 运行时冒烟(9 场景,对生成产物跑)
├── patch-apiproxy.mjs # 把 notifications 注入 apiproxy 白名单
└── release.mjs # 发布流水线:build → smoke → pack → publish
License
MIT
dsh-web-notify(英文)
中文版 · 默认中文
基于 DeepSeek Harness(官方 cordis / @deepseek-ai/dsh-* 插件栈)构建,针对 DeepSeek-V4-Flash-0731 模型参数产生的事件帧。
DeepSeek Harness 目前处于快速迭代的开发预览阶段。 推荐通过 dev / debug 模式(link: 本地仓库)挂载本插件:npm run build 后改动立即生效,且 window.__NOTIFICATIONS__ 诊断让排查最顺畅。也提供 npm 一次性安装作为替代方案。
DSH Web GUI 的审批提醒插件:只要任意会话存在待审批 / 计划审批 / 提问,浏览器就会回响——提示音、标签页标题 + favicon 徽标、OS 通知,以及角落 Dock 会同时呈现该事件。检测管道覆盖每一行会话(包括子代理);在当前运行时委派策略下,被委派的子代理实际无法产生审批/提问等待(见下文「子代理通知可达性」),而其完成 / 失败 / 运行时错误提醒照常工作。完成、任务失败、断连以及模型/工具运行时错误(429 配额等)也会提醒。
纯插件形式:一个宿主半部(lib/index.js)加一个浏览器半部(lib/client.js,loader 格式),通过 profile patch 挂载。
快速开始(推荐路径)
(1) Clone → install deps → build artefacts
↓
(2) Link repo root into the web profile
↓
(3) Whitelist the settings namespace (patch script)
↓
(4) Restart dsh web → find the "Notifications" card in Settings →
turn channels / volume / quiet-hours on and off as you like
↓
(5) In DevTools console, inspect window.__NOTIFICATIONS__:
applied / cardRegistered / monitors / lastHeartbeatAt
hostStatuses / hostStatusCounts ← job status vocab the host emits
feedCounters ← per-event counters
jobSamples / seenStatuses ← browser-side sample ring
demo() / demoSound() ← one-shot UI / audio demos
使用场景
1. 待审批 / 计划审查 / 问题到达
在任意会话(包括从未打开过的子代理)的 pendingInteraction 边沿触发。同一(会话,类型)在冷却窗口内(默认 5 秒)不会重复提醒。
| 渠道 | 行为 |
|---|---|
| 提示音 | WebAudio 三音:E5–G5–B5 |
| 标签页标题 | ⚠ N approval pending — ;一个 MutationObserver 对抗 shell 自身的标题写入 |
| 标签页 Favicon | 32×32 红色徽章配白色数字(计数 > 9 时为纯红点) |
| 操作系统通知 | 按会话通过 tag 去重;点击跳转到该会话并聚焦窗口;approval 通知设置 requireInteraction: true,因此会一直保留直到被处理 |
| PWA 任务栏徽章 | 作为 PWA 安装后,任务栏/应用图标显示计数(navigator.setAppBadge) |
| 通知停靠栏 | 角落 FAB 带实时计数,外加可展开面板列出每一个待处理项;按(标题,类型)显示彩色圆点;一键"处理"跳转到该会话;计数归零时自动折叠;有新项到达时 FAB 脉冲 |
当前会话降级:当页面可见且新待处理项属于当前打开的会话时,提示音 + 操作系统通知会被静默(你正看着它),只有视觉表面保持活跃。切换标签页或最小化会恢复完整表面。
子代理通知可达性:会话列表是一张扁平化的谱系表(origin: 'subagent' 的子代理行嵌套在其 parentSessionId 下),因此检测管道在构造上就覆盖子代理行——子代理行上的任何 pendingInteraction 都会触发所有渠道(提示音 / 徽章 / 操作系统通知 / 停靠栏)。然而在当前 DSH 委派语义下,被委派的子代理实际上永远无法产生这三种待处理状态中的任何一种:
- 审批:dsh-subagent 在委派边界将子级的审批策略固定为 'never'(无论父级策略如何),因此任何需要审批的操作(例如沙箱升级)都会被确定性地拒绝——永远不会发出 approval/requested 帧,因此也就没有 pendingInteraction;
- 问题 / 计划评审:dsh-user-questions 会为归属于另一个活跃 agent 的调用方抛出 DELEGATED_CALLER,因此子 agent 只能将未解决的问题并入其最终结果,交由父级来提问;计划评审仅仅是问题帧的 intent.kind === 'plan-review' 分类,同样无法发生;
- 因此,只有 父会话 的审批条目才会出现在通知停靠栏中——子 agent 行永远不会点亮待处理标记。
相比之下,子 agent 的 完成、作业失败以及模型/工具运行时错误 会经由 session/event 流和作业分组传递,覆盖每个会话,并正常发出警报。
2. 会话 / 子 agent 完成
会话在 turn/end 时结束 → 完成提示卡片(右上角,“done”变体)+ 单次完成提示音 + 可选的系统通知。
- 可见且当前会话完成:提示卡片 + 系统通知被静音,播放柔和的完成提示音作为安全网(你可能已经滚动到别处)
- 页面隐藏:不显示提示卡片(没人看得到)——改为标签页标题脉冲 + PWA 徽章 + 提示音 + 系统通知
3. 作业失败
jobsBySession 中任何状态为 failed / killed 的作业,或状态为 completed 但带有非空且非 exit code: 0 详情的作业(DSH 真机异常终端映射)→ 错误变体提示卡片 + 提示音 + 可选的系统通知。每个已注册的作业 id 仅报告一次。
4. 模型 / 工具运行时错误(429 配额等)
宿主订阅官方 session/event 流并捕获:llm/retry(429 / 速率限制)、turn/end 的 error / max-tokens / interrupted 变体,以及带有 error 或 isError 内容的 tool/result → 携带原始提供方消息(上限 240 字符)的错误变体提示卡片 + 提示音 + 可选的系统通知。在冷却期内按(会话,类型)去重。
5. 断开 / 重连
共享的 connection 服务持续断开超过 connectionAlertAfterMs(默认 10 秒)→ 警告提示卡片 + 提示音。重连时,显示轻量提示卡片 + 完成提示音。从未越过阈值的短暂波动保持静默。从未连接过的启动阶段永不发出警报。
配置
设置卡片注册在 DSH Web 设置页面的 插件设置 → 通知 下(官方 settings.plugin.item 插槽)。更改热生效(120 毫秒防抖,无需重启)。
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| sound | boolean | true | 提示音总开关 |
| volume | number 0–1 | 0.15 | 提示音音量 |
| badge | boolean | true | 标签页标题徽章 + Favicon 徽章 + PWA 任务栏徽章(一个共享开关) |
| toast | boolean | true | 一次性角落提示卡片(完成 / 失败 / 断开) |
| notify | boolean | true | 系统通知总开关;首次触发后的下一次用户手势会请求 Notification 权限 |
| dock | boolean | true | 通知停靠栏:角落 FAB + 可展开面板 |
| completion | boolean | true | ① 会话 / 子 agent 完成警报 |
| completionSound | boolean | true | 完成时播放轻柔提示音 |
| completionNotify | boolean | true | 完成时同时发送操作系统通知 |
| connection | boolean | true | ② 断开 / 重连提醒 |
| connectionAlertAfterMs | number ≥1000 | 10000 | 触发提醒前的断连毫秒数 |
| jobFailure | boolean | true | ③ 后台任务失败提醒 |
| failureNotify | boolean | false | ③ 失败 + ④ 运行时错误共用的操作系统通知开关 |
| agentError | boolean | true | ④ 模型 / 工具运行时错误:429 配额、输出上限、中断、工具失败 |
| cooldownMs | number ≥0 | 5000 | 每会话每类型的去重时间窗口 |
| alertKinds | string[] | ["approval","plan-review","question"] | 待处理提醒的类型白名单 |
| quiet | object | {enabled:false, start:"23:00", end:"08:00"} | 免打扰时段(仅静音;视觉提示仍保留) |
| soundResolved | boolean | false | 待处理审批解决时的下游轻柔提示音 |
| diagnostics | boolean | true | 设备端观察器(最近 60 条会话快照,含任务状态;状态集始终自动收集) |
几个常用配置方案:
- 仅审批提醒,不要失败 / 断连提醒:completion=false、connection=false、jobFailure=false、agentError=false
- 只要提示音,讨厌弹卡片:toast=false、notify=false,保留 sound + badge + dock
- 深夜静音:quiet.enabled=true、quiet.start=22:00、quiet.end=09:00 —— 提示音完全关闭,视觉提示保留
- 只用 PWA / 任务栏,操作系统通知太吵:notify=false、badge=true、dock=true
安装
DSH 插件通过 dsh plugin 命令安装到配置文件(profile)中(dsh web 使用 web 配置文件)。鉴于 DeepSeek Harness 目前处于快速迭代的开发预览阶段,推荐使用开发 / 调试模式挂载,以便即时迭代和诊断排障。同时也提供了 npm 一次性安装作为替代方案。
方式 1:开发 / 调试模式挂载(目前推荐)
1. clone the repo
git clone https://github.com/renpengfei1027/dsh-web-notify.git
cd dsh-web-notify
2. install dependencies and build (Node.js >= 22 required)
npm install
npm run build
3. link the repo root into the web profile
dsh plugin --profile web add link:$(pwd)
4. restart dsh web — a standalone Notifications card
appears under Settings → Plugin settings
dsh web
方式 2:npm 一次性安装
dsh plugin --profile web add dsh-web-notify
将设置命名空间加入白名单(可选,但推荐)
DSH 自身在 dsh-host-apiproxy 中的 WEB_SETTINGS_NAMESPACES 是一个硬编码的允许列表——第三方命名空间默认只读。运行一次补丁脚本,将 notifications 注入允许列表:
node scripts/patch-apiproxy.mjs
之后,设置卡片就是读+写的。如果没有这个补丁,卡片会回退为只读,并应用 DEFAULTS。每次 dsh 升级后都要重新运行;该脚本是幂等的,可以安全地重复运行。
用于调试的诊断信息
插件加载后,打开 DSH Web DevTools 控制台:
// 挂载健康状况
__NOTIFICATIONS__.applied, __NOTIFICATIONS__.cardRegistered
true, true
// 我们拿到的是哪个设置绑定器;sessions/connection 服务是否可用?
__NOTIFICATIONS__.binder, __NOTIFICATIONS__.sessions, __NOTIFICATIONS__.connAvailable
"settingsScope", true, true
// 宿主事件源健康状况(心跳约每 30 秒一次;lastHeartbeatAt 过期意味着宿主事件源已中断)
__NOTIFICATIONS__.feedCounters, __NOTIFICATIONS__.lastHeartbeatAt
{ heartbeat: 4, "agent-error": 1, … }, 1756789012345
// 宿主发出的完整任务状态词汇表——用它来复核
// 哨兵/生命周期守卫会对哪些终态做出反应。
__NOTIFICATIONS__.hostStatuses, __NOTIFICATIONS__.hostStatusCounts
["failed","killed","completed","running",…], { completed: 8, failed: 2, … }
// 浏览器端样本(在 diagnostics=true 时捕获;最近 60 帧)
__NOTIFICATIONS__.jobSamples[0]
{ ts, sessionId, sessionTitle, jobs: [{ jobId, status }], alerts: [] }
// 一次性 UI / 音频演示(确认界面已接好且音频可以播放)
__NOTIFICATIONS__.demo("error") // 推送一个 error 变体卡片
__NOTIFICATIONS__.demoSound(0.3) // 以指定音量播放完成提示音
生效
插件名单变更需要重启 dsh web——仅刷新页面永远不会注册新包(官方 client-modules 文档明确指出,包元数据按名称缓存且永不过期)。白名单补丁也需要重启。
验证
1. 在设置页面的 Plugin settings 下,会出现一个独立的 Notifications 卡片,带有可编辑字段
2. 触发一个待处理审批:标签页标题显示 ⚠ 1 approval pending — ,favicon 绘制一个红色的 1,角落停靠 FAB + 列表出现,三音提示音播放,并且弹出操作系统通知(首次使用时允许)
3. 点击操作系统通知或停靠行上的 “Handle” → 窗口获得焦点并打开该会话
4. 完成一个会话:右上角出现完成 toast + 单次完成提示音
5. DevTools 控制台显示 [notifications] 日志行;window.__NOTIFICATIONS__ 暴露 apply 明细 + jobSamples 环形缓冲区
卸载
dsh plugin --profile web remove dsh-web-notify
…或者从配置文件的 cordis.patch.yml 中移除插入行,并删除 node_modules 联接。
限制
- 对于待处理项,粒度是会话级的(列表行只携带一种 kind 状态);任务失败可达到任务级(命令标签 + 退出详情);模型/工具错误携带事件流原始消息,上限为 240 个字符
- 子代理可达性:子代理行位于检测管道内部(同一张扁平化谱系表),但被委派的子代理的审批策略被固定为 'never',且用户提问会被拒绝——子代理永远不会出现任何审批/计划审查/提问条目,只有父会话的才会出现;完成/失败/运行时错误提醒仍然覆盖子代理(见上文“子代理通知可达性”)
- 提示音需要页面上先有用户手势(浏览器自动播放策略);没有手势时,它会静默降级为仅视觉呈现
- OS 通知权限会在首次触发后的第一次点击时请求;如果 Windows 上始终没有任何提示,请检查浏览器站点设置(127.0.0.1 通知权限)和 Windows 专注助手
- 该卡片遵循设置作用域;如果宿主 apiproxy 尚未将该命名空间加入白名单,则卡片为只读,并应用 DEFAULTS
项目结构
dsh-web-notify/
├── package.json # dsh.client.platform=web + inject + dsh.bundle.patch
├── cordis.patch.yml # plugin-row insert
├── src/
│ ├── index.ts # host half: settings NS + systemPrompt notice + event forwarder
│ └── client/ # browser half (zero @deepseek-ai runtime deps)
│ ├── index.ts # entry: apply/inject/mount + settings-scope hot reconfig + card
│ ├── types.ts # local types + DEFAULTS
│ ├── locales.ts # zh/en dicts + minimal t()
│ ├── channels.ts # WebAudio chime / quiet-hours / OS notify / jumpToSession
│ ├── badge.ts # title badge + canvas favicon badge + PWA badge
│ ├── stores.ts # uSES stores for toast + dock
│ ├── toast-ui.tsx # toast cards + stack
│ ├── toast-mount.tsx
│ ├── sentinel.ts # pending-edge sentinel (dock owns visuals; just pulses)
│ ├── lifecycle.ts # ① completion + ③ job-failure + ② connection monitor
│ ├── dock.ts # dock FAB + panel + mount + startDock
│ └── settings-card.tsx # settings card
└── scripts/
├── build.mjs # esbuild → lib/{index.js,client.js} (loader-wrapped)
├── smoke.mjs # runtime smoke (9 scenarios, runs on built artefacts)
├── patch-apiproxy.mjs # inject notifications into apiproxy allowlists
└── release.mjs # release pipeline: build → smoke → pack → publish
许可证
MIT扫码进群