Plays a chime and speaks a Chinese voice alert when an approval, question, or plan-review popup appears in the DSH web GUI, so you never miss a request.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-approval-voice
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:ZIye1208/dsh-approval-voice
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
This plugin publishes its README in Chinese only.
DSH Web GUI 插件:当需要你审批或回答的弹窗(沙箱权限升级审批、ask_user_question 提问、计划审批等)出现时,自动播放提示音并用语音播报,避免漏看。
工作原理
插件有两条检测路径,两条路径统一使用会话作用域的事件标识
(session:<sessionId>:<kind>:<key>),因此不会重复提醒:
- 全局待处理交互源(首选):订阅 DSH 客户端的全局待处理交互快照,按
Map<sessionId, {kind, key}>感知所有会话的 approval / question / plan-review —— 包括没有开在任何标签页里的会话。两种客户端核心形状都支持(resolveGlobalSource()自动适配):- 网页版 dsh 0.1.5-rc.3:
ctx.uiSession.pendingInteractions(即侧边栏「等待审批」所用的 root hooksessionPendingInteraction); - 桌面端 dsh-desktop 0.2.0-rc.2:没有
pendingInteractions,改用ctx.uiSession.sessionStatus(Map<sessionId, {running, pendingInteraction, completionUnread}>, 取其中的pendingInteraction),这正是桌面端侧边栏「等待审批」用的源。
- 网页版 dsh 0.1.5-rc.3:
- DOM 标记(兜底):仅在两个源都取不到时(更老的 DSH)才使用,监听当前视图渲染出来的卡片:
| 标记 | 对应界面 |
|---|---|
data-approval-key |
沙箱权限升级等审批(ApprovalPanel) |
data-question-key |
提问 / 选择题(QuestionComposer) |
data-plan-review-key |
计划审批(PlanReviewPanel) |
命中时按配置播放升调提示音(Web Audio,C5-E5-G5)和/或语音播报(SpeechSynthesis,中文语音)。每个请求只提醒一次。
安装
方式一:npm(推荐,已发布到 npmjs)
dsh plugin --profile web add dsh-approval-voice
方式二:GitHub(备选)
dsh plugin --profile web add github:ZIye1208/dsh-approval-voice
安装后重启 dsh web 服务,刷新页面即可生效。
本地开发安装(改代码即时生效):
dsh plugin --profile web add link:C:\path\to\dsh-approval-voice
使用
- 默认开启「提示音 + 语音播报」,且默认对所有会话提醒(多会话 / 单页签切换会话 / 多标签页都能听到任何会话的审批、提问、计划审批)。
- 设置入口:设置 → 常规 → 审批语音提示,可配置:
- 总开关;
- 提醒方式:仅提示音 / 仅语音播报 / 提示音 + 语音播报;
- 音量;
- 提醒范围:
所有会话(默认,覆盖所有会话,含没开在任何标签页里的会话)或仅当前会话(只在当前标签页响应本页显示的会话); - 提示音文件:选择本地音频文件(mp3/wav/ogg 等,≤2MB)替换内置提示音;点「恢复默认」回到内置提示音。超限或保存失败时面板会直接报错,不会"看着像存住了"。
- 试听按钮:按当前设置播放一次(含自定义提示音)。
- 控制台调试:
window.__approvalVoice.get()/set({...})/test()/pending()/global()/alertedCount()/soundBytes()/currentSessionId()/tabId。set({...})返回{ ok, error, config }:ok:false表示没存住(已回滚内存配置),别忽略它。 - 配置保存在浏览器 localStorage(键
dsh.approvalVoice.v1),同一浏览器所有标签页共享。
多会话提醒原理
DSH Web GUI 里每个会话可能是一个独立标签页,也可能只是同一页签侧边栏里的一条。插件按以下方式让任一会话的审批都能被听到:
- 每个页签订阅 DSH 客户端的全局待处理交互源(网页版
ctx.uiSession.pendingInteractions、 桌面端ctx.uiSession.sessionStatus),因此任何会话(哪怕没开在任何页签里、只在侧边栏显示 「等待审批」)出现审批 / 提问 / 计划审批时,每个页签都会感知到;两个源都取不到时才退回监听本页 DOM 里的卡片。 - 事件标识是会话作用域的(
session:<sessionId>:<kind>:<key>),配合BroadcastChannel(并写入 localStorage 作为兜底)在全浏览器内一次提醒只响一次:优先由当前聚焦的标签页 播放(声音最可靠),若没有任何聚焦标签页,则由最先到时的后台标签页兜底播放。 - 若抢到播放权的页签实际没能出声(浏览器拒绝自动播放且音频未解锁),它会释放 claim 并广播
bell-failed,请已解锁音频的其它页签补响一次。 仅当前会话模式不广播,只在本地为本页正在显示的那个会话出声。
注意事项
- 语音播报依赖系统安装的中文 TTS 语音;找不到中文语音时自动退化为仅提示音(避免用英文语音念中文)。
- 浏览器自动播放策略:首次点击/按键后音频才解锁;设置在自定义提示音且未起播时会自动回退内置提示音,
并把失败原因打到
console.warn(不再静默无声)。 - 自定义提示音以 data URL 存入 localStorage(≤2MB 二进制,编码成 base64 后约 1.33 倍), 请选择短促音频;跨标签页共享。提示音单独占一个 key,不跟开关/音量挤在一起 —— 这样拖动音量滑块不会每次都重写几 MB 的数据。老版本留下的提示音会在首次启动时自动搬过去。
- 保存失败不会静默:浏览器存储配额不足(数据 URL 太大、或同源其它插件把 localStorage 占满)时,
面板会显示红色错误行、失败原因写进
console.warn,并且配置回滚到上一个值 —— 绝不会出现"面板显示已自定义、刷新后提示音消失"。遇到这种提示就换更短的音频(建议 1MB 以内), 或清理浏览器数据后重试。 - 若所有 DSH 标签页都在后台且使用「仅语音播报」,浏览器可能限制后台标签页的语音合成(提示音不受影响)。
- 卸载:
dsh plugin --profile web remove dsh-approval-voice,重启服务即可。
文件结构
dsh-approval-voice/
├── package.json # dsh.bundle + dsh.client 声明(免构建)
├── cordis.patch.yml # 插件名册插入行
├── lib/index.js # 宿主侧空插件(浏览器专用插件无需宿主行为)
├── lib/client.js # 浏览器端实现(模块加载器格式,纯 JS)
├── test-global-scope.mjs # 回归测试:直接加载真实 lib/client.js 的假浏览器测试
└── test-cross-tab.mjs # 旧版跨标签页协调逻辑复刻测试
Links
More in this category
xmanrui/dsh-im★ 2147
Connect IM bots to DeepSeek Harness via QR codes or bot credentials (9 channels: Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp).
shaobeichen/dsh-pocket★ 1929
Remote phone access to the DSH Web UI: scan a QR code for LAN or public (cloudflared tunnel) access with real-time sync, a mobile-adaptive layout, and a settings tab.
OpenPetsHQ/openpets#dsh★ 1309
Bridges DeepSeek Harness lifecycle status, errors, and approval requests to a locally running OpenPets desktop companion.
inclusionAI/Avernet#deepseek-harness-channel-bcn★ 641
Connects DeepSeek Harness to Avernet's Bot Collaboration Network over WebSocket V2, with automatic onboarding, isolated agent sessions, tool-call events, and multi-bot routing tools.
c1overzz/dsh-bili-scroll★ 203
Let your DSH agent browse Bilibili on its own, read subtitles, write a daily digest, and @ you when it finds something worth your attention.
Oscar-Williams/dsh-deepcanary★ 91
Evidence-first attention supervision for DeepSeek Harness with C0–C3 policy, deduplicated Inbox alerts, quiet hours, and redacted outcome records.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.