dsh-plugin-completion-notify
Verifieddsh-plugin-completion-notify · v0.7.1 · MIT · Web UI
Desktop notifications for dsh web: when a session finishes, or a popup is waiting for your approval, plan review, or answer, while you are not looking at it
Install
dsh plugin add dsh-plugin-completion-notify Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Creators
Readme
dsh-plugin-completion-notify
任务完成、或弹窗等待用户确认时弹出系统桌面通知的 dsh web 插件(dsh-plugin 社区插件)。
功能
- 非当前会话完成 → 弹出系统通知(无论页面在前台还是后台)
- 当前会话在你离开时完成 → 弹出系统通知。「离开」= 窗口隐藏(最小化/被遮挡/切标签)或窗口还在屏幕上但已失焦(切到别的应用);Electron 里失焦不会让
document.hidden变真,所以两者都要算 - 当前会话在你看着时完成 → 不打扰(你看得到)
- 弹窗等待用户处理时也通知,规则与完成时一致:
- 审批(工具/权限等执行确认)、计划审阅(计划批准)、提问(等待回答)都会触发;正文按类型区分(「等待审批 / 计划待审 / 等待回答」)
- 信号来自 ui-session 的
sessionStatus(会话弹窗注册的会话级等待);非当前会话出现等待弹窗 → 弹出系统通知(无论页面前后台) - 当前会话的弹窗在你离开时打开 → 弹出系统通知;你正看着时不打扰(弹窗已在你眼前)
- 同一等待只通知一次;等待被应答/清除后再次等待可再通知
- 「通用」设置页提供启用开关(默认开启,一个开关同时管完成与等待确认通知)
- 权限在用户首次交互或开启开关时请求(浏览器要求手势)
- 通知显示时长由系统设置控制(设置行内已写明入口),插件不做强制常驻,见已知限制
依赖
面向 DSH 0.2.x(在桌面应用运行时 0.2.0-rc.2 与 0.2.1-rc.2 上均验证过)。
DSH 0.2 的运行时会按插件声明的 @deepseek-ai/dsh-* peer 校验运行时版本,不一致的 bundle 会被静默跳过(列在 profile 的 skippedBundles 里,设置页不会出现)。所以 peer 用范围而不是精确版本:^0.2.0-rc.2 覆盖整个 0.2.x(含 0.2.x 的 rc),能过 0.2.0-rc.2 和 0.2.1-rc.2,并拒绝 0.3.x / 0.1.x。
0.7.0 曾把这些 peer 精确钉在
0.2.0-rc.2,运行时升到0.2.1-rc.2后整包被判定不兼容;0.7.1 起改为范围。(主机若仍在 0.1.x,请装 0.6.2。)
peer 依赖(npm 已发布):
@deepseek-ai/cordis(^4.0.4)@deepseek-ai/dsh-api-session-controller(sessions 列表服务)@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-renderer(ctx.slots服务声明方)@deepseek-ai/dsh-client-ui-session(ctx.uiSession.sessionStatus状态源)@deepseek-ai/dsh-client-ui-settings(ctx.configForms)@deepseek-ai/dsh-client-ui-settings-general(「通用」分区的settings.general.item座位)@deepseek-ai/dsh-client-ui-slots(0.2.1 起由 shell 以模块表 seed 形式提供,不再有独立运行包)@deepseek-ai/dsh-settings(host 半的 settings 配置投影)@deepseek-ai/schemastery(^3.18.4,host 半 Config 的.volatile())react
构建
npm install --legacy-peer-deps # 源码构建时跳过官方 @deepseek-ai/* 包的 peer 链
npm run build
产物:lib/index.js(host 半,导出 Config——其 volatile 字段就是设置页里的开关)、lib/client.js(浏览器半)。
测试
npm test
三套夹具,先 npm run build(它们跑的是 lib/ 里的真实产物):
test/behaviour.cjs(23 项)——加载真实lib/client.js,用桩 ctx / 假 Notification 驱动:非当前会话完成、三类等待、去重、当前会话「离开时通知 / 看着时静默(含失焦与最小化两种离开)」、开关关闭后静默,以及降级路径(运行时没有 ui-session 状态源时仍能通知完成)。test/host.mjs(11 项)——把真实lib/index.js挂进真实 Cordis 上下文(插件自己的 cordis 副本)+ 桩settings:校验Config默认值与 volatile 标记、apply经ctx.inject(['settings'])调到configure({auto:false}, fiber)。test/row.cjs(6 项)——按框架方式调用注册进settings.general.item的行组件:开关绑定存储值、切换经插件自己的注入面写回enabled。
这些用例是迁移期真实抓到 bug 的(去重释放语义、React 被内联),所以保留在仓库里作回归网。
安装
插件是 dsh.bundle 形态(声明配置层)。在 桌面应用里用自带的插件管理器最省事:
- 设置 → 插件 → 添加插件,填本地绝对路径(如
D:\dsh-plugins\completion-notify)或包名dsh-plugin-completion-notify
命令行(桌面应用需先完全退出,否则 profile 被占用):
dsh plugin --profile desktop add dsh-plugin-completion-notify
# 或本地开发:dsh plugin --profile desktop add /absolute/path/to/completion-notify
dsh plugin add 自动把包加入 dsh.profile.bundles 配置层并安装依赖。桌面 profile 的 patch 只在启动时应用,装完要重启应用;web profile 走 dsh web 重启即可。
手动挂载(不通过 dsh plugin add)时在 profile 的 cordis.patch.yml 加:
- insert:
- id: completion-notify
name: dsh-plugin-completion-notify
id 必须与插件内的设置命名空间一致(src/completion-notify-settings.ts 的 COMPLETION_NOTIFY_SETTINGS_NAMESPACE = 'completion-notify'):0.2 的 settings 服务按组合入口 id 提供每个插件的配置项,浏览器半用同一个 id 调 ctx.configForms.get(id)。改 id 时两处要一起改。
发布
npm publish
GitHub 仓库添加 dsh-plugin 话题。
已知限制
- 浏览器通知权限必须授予:首次交互时请求;被拒则静默
- 通知显示的时长由系统控制,插件不强制常驻:Notifications API 没有时长参数。Windows 默认仅约 5 秒,可在「设置 → 辅助功能 → 视觉效果 → 在以下时间后关闭通知」调长(等价注册表值
HKCU\Control Panel\Accessibility\MessageDuration,本机实测为 5);macOS 在「系统设置 → 通知 → 浏览器」把提醒样式设为「提醒」即可保持到手动处理。系统的"勿扰/专注助手"也可能抑制横幅 - 页面关闭后无通知(无 service worker push);页面级通知在页面关闭/刷新后即消失,无法跨页面常驻
- 去重是页面生命周期内的内存态:刷新后,仍处于「已完成」或「等待确认」状态的会话可能补弹一次
- 断线重连可能补弹一次:等待 feed 在重连/会话卸载时清空并由会话重建,无法区分「新等待」与「仍在等待的重现」
- 等待通知在出现时判定一次:当前会话的弹窗若在你看着时出现(未通知),之后离开也不会补发——与完成通知的规则一致
- 完成/等待信号都来自 ui-session 的
sessionStatus状态源(0.2 架构):非当前会话的完成用运行时自己打标的completionUnread,当前会话的完成与本插件自己检测 run→idle 边沿;等待确认读同一条目的pendingInteraction。「离开」判定为document.hidden || !document.hasFocus()。运行时没有该状态源时自动退化为只保留完成通知(用 sessions 列表自己检测边沿,仍然区分当前会话与离开)