当 DSH 需要你审批、向你提问、或一轮对话完成,而你正在浏览其他标签页时,弹出系统桌面通知提醒,点击即可跳回原会话。
- 语言
- TypeScript
- License
- BSD-3-Clause
- 分支
- main
安装
$ dsh plugin --profile web add dsh-web-ui-notify在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 bill9109/dsh-web-ui-notify:先查看仓库 https://github.com/bill9109/dsh-web-ui-notify 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
在 DSH Web UI 中为「工具需要审批」「Agent 提问」和「一轮对话完成」三类事件挂上系统桌面通知,当你切到别的标签页时,浏览器就会弹一条原生通知提醒你,点一下直接跳回出事的那个会话。
核心能力
- 当工具请求越权执行需要你审批时,弹出系统通知,标题带会话名,正文是越权原因或工具名
- 当 Agent 抛出问题时弹出系统通知,正文直接显示问题文本
- 当一轮对话完成时弹出系统通知,正文是该轮最终回答的前 80 个字;纯工具轮(没有最终文本)则改为显示「第 N 轮已完成」
- 会话列表里所有会话(含后台未打开的会话)出现上述事件时同样触发通知,标题点名会话,点击跳转到那个具体会话
- 后台会话整体跑完时弹「该会话已完成,可以切回查看」通知,按 sessionId 去重
- 点击通知自动聚焦浏览器窗口并打开对应会话;通知设置
requireInteraction,不会几秒后自动消失 - 当 DSH 标签页处于前台时不发通知(避免与 DSH 自己的提示重复)
- 在「设置 → 通用」新增一行「桌面通知」开关,可一键申请浏览器通知权限,状态显示「已开启 / 未授权 / 已被浏览器阻止 / 浏览器不支持」四档
技术实现
- 语言: TypeScript(同时编译出 Node 端 host bundle 和浏览器端 client bundle,已预编译提交到
lib/) - 关键依赖:
@deepseek-ai/dsh-client-runtime/client(ClientContext、ISessions、PendingInteraction类型);@deepseek-ai/dsh-client-ui-slots(settings.general.item槽位、PropsLocale、PropsRuntime);@deepseek-ai/cordis(host 端 Cordis 上下文);react(settings 行 UI) - 架构模式: DSH bundle 双端架构。host 半边(
src/index.ts)是空壳 Cordis 插件,不注入任何服务、不做任何动作,仅占位让包成为完整双端包;client 半边(src/client/index.ts)通过两条观察通路协同:① LIST 层订阅sessions.list的快照,遍历列表里所有会话,对状态为「pendingInteraction」的会话懒加载 binding 读pending等待负载,按${sid}:${wait.key}去重弹通知;② SNAPSHOT 层订阅当前会话的session快照,比对turnEnds的新轮次,弹「轮次完成」通知(首次打开时把已有轮次作为基线吸收,避免补弹历史)。所有通知均通过new Notification(...)构造,附带tag和requireInteraction: true,并挂onclick = focus + open。 - 入口文件:
src/index.ts(host,无逻辑)、src/client/index.ts(client 主体)、src/client/notify.ts(通知构造与去重门控)、src/client/NotificationSettingsRow.tsx(设置行 UI)、cordis.patch.yml(bundle 注入点)
适用场景
你日常用 DSH 跑长任务,比如让 Agent 改一摞文件、写一篇长文、跑一段数据清洗,过程中会频繁切到其他标签页(查文档、看聊天、刷新闻),而 DSH 自己只在那个被切走的标签页上画审批/提问/完成的提示;你盯着别的窗口时,DSH 和你互相等着,谁都不知道下一步该谁动。这个插件把提示搬到系统通知中心:审批弹一下、问题弹一下、一轮跑完弹一下,点回去就能直接处理。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | 未声明版本号 | package.json#dsh.client.platform 声明 web,需支持 dsh.bundle / dsh.client / profile 机制的 DSH(20260806 snapshot 起) |
| Node.js | ^20.0.0 或 >=22.0.0 | 来自 package.json#engines.node,仅 host 半边的编译/打包需要;运行时跑在浏览器里 |
| 平台 | macOS / Windows / Linux | 任意能跑现代浏览器的桌面系统;macOS 需在「系统设置 → 通知」额外放行浏览器 |
| 原生模块 | 无 | 客户端 bundle 走浏览器原生 Notification API,无 npm 依赖;host 半边只是占位 Cordis 插件 |
| 浏览器 | 现代浏览器 | 必须支持 Notification API;不支持的环境显示「浏览器不支持」状态,插件不提供降级方案 |
安装方式
dsh plugin --profile web add github:bill9109/dsh-web-ui-notify
安装后请重启 DSH Web 服务,并在浏览器硬刷新(Cmd/Ctrl+Shift+R),客户端 bundle 只在全新页面加载时挂载。
配置项
本插件无需配置文件、不读取 config.yaml / 环境变量。唯一的「设置项」是 DSH Web UI「设置 → 通用」里新增的「桌面通知」一行,用于一键申请浏览器通知权限(这是浏览器要求通知权限必须由用户手势触发)。该行的状态显示会随浏览器实际权限自动刷新为「已开启 / 未授权 / 已被浏览器阻止 / 浏览器不支持」四档之一。
常见问题
Q: 安装后通知一直没出现,怎么办?
A: 客户端 bundle 只在全新页面加载时挂载,安装或升级后必须先重启 DSH Web 服务,再在浏览器做硬刷新(Cmd/Ctrl+Shift+R)。然后打开 DSH 的「设置 → 通用 → 桌面通知」点击「开启」,并在浏览器弹出的权限框里选允许;macOS 还需要在「系统设置 → 通知」里允许浏览器。开关状态共有四档:已开启 / 未授权 / 已被浏览器阻止 / 浏览器不支持。
Q: DSH 在前台时为什么不响?
A: 这是有意为之:前台时 DSH 自己已经在对话界面里显示提示,再弹系统通知属于重复打扰。插件只在 document.visibilityState === 'hidden'(切到别的标签页或最小化)时才发通知;回到前台时通知会继续停留在系统通知中心等你点击。
Q: 会重复响吗?断线重连会不会再弹一次?
A: 不会。每个等待事件按稳定的 wait key 去重(key 形如 ${sessionId}:${wait.key}),在 mux 重放和重连后仍然命中同一 key;会话整体完成按 sessionId 去重;轮次完成按 ${sessionId}:${turn} 去重,且首次打开会话时会「吸收」历史已完成轮次作为基线,不会补弹旧轮次。
Q: 后台会话也会通知吗?
A: 会。会话列表里的每一个会话(不论是不是当前打开的那个)只要进入「待审批/待回答/已完成」状态,都会触发通知;标题里带上会话名,点击通知会跳到那个具体会话,而不是当前会话。
Q: 浏览器不支持 Notification API 还能用吗?
A: 不能。插件只走浏览器原生 Notification API;没有这个 API 的环境(很老或非主流浏览器)会显示「浏览器不支持」状态,插件不会发送任何通知,也不提供降级方案。
Q: 怎么升级、怎么卸载?
A: 升级用 dsh plugin --profile web update github:bill9109/dsh-web-ui-notify;卸载用 dsh plugin --profile web remove @bill9109/dsh-web-ui-notify。操作后都需重启 Web 服务并硬刷新浏览器,开关状态保存在 profile 的 Settings provider 里,升级和重启都会保留。
上手难度
入门 — 一条 dsh plugin 命令安装即用,无需配置文件;安装后只需重启 Web + 硬刷新浏览器,并在「设置 → 通用」点一下「开启」即可,没有别的开关或参数。
已知问题与限制
- 离开前台时通知门控在
document.visibilityState === 'hidden'上:浏览器最小化、系统级隐藏窗口、操作系统焦点不在浏览器都会让 visibilityState 为hidden;但部分浏览器在某些场景(如外接显示器熄屏、浏览器自身窗口被遮)可能仍判定为 visible,导致预期该响的场景没有响(src/client/notify.ts:33-35、src/client/index.ts:169-170) - 轮次完成通知的正文摘要上限 80 字,超长回答会被截断并加
…省略号;纯工具调用轮没有最终文本时显示「第 N 轮已完成」占位文案(src/client/index.ts:53-79) - 通知标题里会话名最长 40 字,超出会被截断;不同会话之间用
·分隔会话名与事件类型(src/client/index.ts:54-55、src/client/notify.ts:59-61) - 通知一旦发出不会自动消失(
requireInteraction: true),需要用户主动点击或关闭;系统通知中心堆积较多通知时仍依赖操作系统自身管理(src/client/notify.ts:64-66) - 浏览器 Notification API 在移动端 Safari / iOS WebView 上行为不一致,本插件未做针对性兼容(
README.md:67-94、package.json:54-64) - 源码中未发现
TODO/FIXME/HACK/XXX注释;2026-08-13 0.1.2 起适配 dsh 20260812 snapshot 的SlotRegistry/LocaleRuntime重命名与包作用域迁移@dsh-external→@bill9109,旧版本在新版 DSH 上不可用(CHANGELOG.md:16-21)
Install: dsh plugin --profile web add github:bill9109/dsh-web-ui-notify
A DeepSeek Harness Web UI client plugin: when a tool needs approval, DSH asks you a question, or a turn finishes while you are looking at another tab, it pops a system desktop notification — so neither DSH nor you end up waiting.
Why this exists
While you browse other pages, DSH needs human confirmation (tool approvals, questions) or finishes a round of work, and the Web UI in the foreground tab is the only place it asks. If you are looking anywhere else, the request waits silently. This plugin moves those moments onto your desktop: a native system notification appears, names the session, and clicks back into the conversation.
Features
- Notify on interaction with the current session: tool approvals and DSH questions carry context in the body (approvals show the over-permission reason, questions show the question text)
- Notify on background sessions too: sessions you are not looking at also notify when they need approval or a question (same contextual body as the current session); a finished background session notifies as well — click it to jump straight to that session
- Notify on turn completion: every finished turn of the current session notifies, with the first 80 characters of the final answer; tool-only turns without a final answer show the turn number. Completion, interruption, and error turns all notify
- Session name in the title: every notification title names its session, e.g. "Refactor database · needs approval"
- Click to jump to the session: clicking a notification not only returns to the DSH page but also opens that session
- Notifies only while you are away from the tab; when the page is in the foreground DSH already shows its own prompts, so it does not double-notify
- Each event notifies once — reconnects do not repeat it, and opening a session with history does not replay old turns
- Notifications do not auto-dismiss after a few seconds; they wait for you
- A toggle lives in Settings → General, following the DSH language (zh/en)
Install
The plugin is a DSH bundle (package.json declares dsh.bundle + dsh.client). Install it into the web profile with the standard dsh plugin mechanism — no DSH source changes and no hand-written patch:
dsh plugin --profile web add github:bill9109/dsh-web-ui-notify
Internally the command runs pnpm add <spec> in the profile directory and automatically appends packages that declare dsh.bundle to dsh.profile.bundles. You can also clone it and install from a local path (for development — rebuild and it takes effect):
dsh plugin --profile web add /path/to/dsh-web-ui-notify
The repository ships its build output (lib/), so the plugin works right after installing — no build step needed. It has zero runtime dependencies: the browser-side requires (react, react/jsx-runtime, ui-slots) resolve through DSH's own frontend module table, not npm.
Older DSH (before the profile system) installed via
pnpm --filter @deepseek-ai/dsh add+config.yaml; since the 20260806 snapshot the profile flow above is the way. If your DSH is still old, use the historical README (visible in git history).
After installing, restart the Web UI (the way you normally start DSH) and refresh the browser page — the plugin takes effect.
Upgrade
dsh plugin --profile web update github:bill9109/dsh-web-ui-notify
For a local-path installation, run add again against the replacement checkout. User settings (the Settings → General toggle) live in the profile's Settings provider and survive upgrades.
Uninstall
dsh plugin --profile web remove @bill9109/dsh-web-ui-notify
The command runs pnpm remove <pkg> in the profile directory and removes it from dsh.profile.bundles. After uninstalling, restart web and hard-refresh the browser.
Usage
After installation you must also grant browser notification permission, otherwise the plugin stays silent — without permission the browser simply blocks notifications.
- Open Settings → General → Desktop notifications and click Enable
- When the browser asks, choose Allow; the status becomes "Enabled"
- On macOS, also allow your browser under System Settings → Notifications
Then switch to another tab — approvals, questions, or finished turns produce system notifications, and clicking one brings you back to handle it.
The settings row has four states:
| Status | Meaning |
|---|---|
| Enabled | Working normally |
| Not granted | Click the button to grant |
| Blocked by browser | Previously denied — change the site setting back to Allow; the button alone will not help |
| Unsupported | The environment has no Notification API |
Troubleshooting
| Symptom | Resolution |
|---|---|
| No notifications appear | Confirm the toggle in Settings → General is Enabled, the browser permission for the DSH site is Allow, and on macOS the browser is allowed under System Settings → Notifications; then switch to another tab — the plugin only notifies while you are away |
| Notifications worked, then stopped after a restart | The browser may have reset site permissions; re-grant, or re-enable the toggle if the settings row shows a different state |
| "Blocked by browser" | The site permission was previously denied — change it back to Allow in the browser's site settings; clicking Enable alone will not help |
| "Unsupported" | The environment has no Notification API (e.g. an old or unusual browser); desktop notifications cannot work there |
| Plugin not in Settings → General after install | The plugin only appears after the Web UI is restarted and the page hard-refreshed; verify the bundle row is in the profile (`dsh --profile web --dump-config |
Development and verification
pnpm install
pnpm run build # tsc + tsdown -> lib/ (committed)
pnpm test # vitest: browser-plugin + settings-row suites
pnpm run build emits the host + client bundles into lib/, which is committed so consumers install without building. The test suite covers plugin wiring on a real cordis context and the settings row in jsdom. Changes that alter the plugin's visible surface (which events notify, the settings row, locales) should add or update coverage in tests/.
Community and About
- Use GitHub Issues for reproducible bugs, focused feature requests, and usage questions.
- Read CONTRIBUTING.md before proposing changes; report vulnerabilities privately via SECURITY.md.
- Follow releases and compatibility notes in CHANGELOG.md.
License
BSD-3-Clause
查看使用指南 →
该插件的安装步骤、关键要点、FAQ 与兼容性说明(基于已收录字段派生)。
收录徽章
[](https://deepseek-plugin.org/plugins/bill9109/dsh-web-ui-notify)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。