Zum Hauptinhalt springen
S

dsh-ui-sound

soh4c4759/dsh-ui-sound

Akustisches Feedback für die DSH-Weboberfläche: Schaltflächen werden nach Bedeutung klassifiziert (normal, primary, toggle, send, close, danger, link); Aufgabenübergänge der aktuellen Sitzung (started, finished, failed) und ausstehende Interaktionen lösen einen Signalton aus. Für jedes Szenario gibt es eine eigene Signalauswahl und einen Schalter auf einer Einstellungsseite. Alle 78 Signale und 12 Sound-Pakete werden im Browser mit der Web Audio API erzeugt; das Paket enthält keine Audiodateien und sendet keine Netzwerkanfragen. Community-Port von dsh-plugin-uisfx auf DSH 0.2.0; die Änderungen stehen in PROVENANCE.md.

Installation

dsh plugin --profile web add github:soh4c4759/dsh-ui-sound

README

dsh-ui-sound

DeepSeek Harness Web GUI 的界面音效插件:把「界面交互」和「任务状态更新」都变成可听见的语义反馈,每一类反馈都能在设置页里单独挑音效、单独开关。

⚠️ 这是社区移植版,不是上游官方延续

本仓库是 dsh-plugin-uisfx(MIT,作者 XanthanL)在 DSH 0.2.0 上的移植适配版。 上游声明支持 dsh 0.1.0-rc.6;在 0.2.0 上它的宿主行无法激活、任务音静默失效。 请优先使用上游——只有当你确实运行在 0.2.0+ 且撞上那些问题时才需要本版。 改了什么、依据是什么,逐条记录在 PROVENANCE.md。

音效引擎来自开源项目 uisfx(MIT,Copyright © Yuki Capital), 共 78 个 cue × 12 个音色包,全部由 Web Audio 实时合成,不含任何音频文件、不发起网络请求。 见 NOTICE 与 vendor/uisfx-0.4.0.js。

安装

dsh plugin --profile <你的 profile> add github:SOH4C4759/dsh-ui-sound
# 然后重启 dsh

lib/ 是构建产物且已随仓库提交,没有构建步骤,git 源安装开箱可用。装完在 设置 → 音效 里配置。

它解决什么

DSH 默认几乎没有声音反馈:任务跑完了?失败了?按钮点中了没有?只能靠眼睛确认。 本插件补上两类语义音效:

  • 交互音效 —— 按钮按下时按语义分类发声(普通 / 主要 / 开关 / 发送 / 关闭 / 危险 / 链接),键盘 Enter、Space 激活同样发声。
  • 任务状态音效 —— 当前会话开始运行、运行成功结束、运行失败结束,以及出现需要你处理的交互(授权请求 / 提问 / 计划复核)时发声。

触发时机

情景 id默认 cue什么时候响
task.startstart当前会话的 agent 开始运行
task.successsuccess当前会话正常结束一轮
task.failureerror当前会话因错误结束一轮
task.pendingnotification任意会话出现待处理交互(授权 / 提问 / 计划复核)
click.normalpress普通按钮
click.primaryselect主要 / 强调按钮
click.toggletoggle-on开关、checkbox、aria-pressed
click.sendsend发送 / 提交
click.closeclose关闭 / 取消
click.dangerdelete删除 / 清空 / 危险操作
click.linkopen链接

三条刻意的取舍:

  1. 任务音只跟「你正在看的那个会话」。子代理和后台会话会不停地起停,全都发声等于噪声。 判据是会话列表里 retainedBy.mainView > 0 的那一行——和 DSH 自己判定「当前会话」的规则一致。 你切到设置页、文件页时,沿用最后一个主视图会话,不会突然静音。
  2. 待处理提醒对所有会话生效。它的价值就在于你没在看那个会话时提醒你,所以不按主视图过滤,用 提醒音 开关单独控制。
  3. 首帧只记基线。页面加载时已经在跑的会话不会补一声「开始」。

配置

设置 → 音效。可配置项:

设置默认值说明
启用音效开总开关
音量55%0–100%
音色包zen12 种整体音色,一键切换整套性格
任务音开task.start / success / failure 三类
按钮音开所有 click.*
提醒音开task.pending
每情景 cue见上表每个情景独立下拉选择 + 试听按钮

持久化落点(可直接手改,改完刷新页面生效):

%USERPROFILE%\.dsh\ui-sound\config.json
{
  "enabled": true,
  "volume": 0.55,
  "pack": "zen",
  "taskSounds": true,
  "clickSounds": true,
  "attentionSounds": true,
  "mapping": { "task.success": "complete", "click.send": "send" }
}

宿主半会校验并裁剪这个文件:音量夹到 0–1,未知音色包回落到 zen,未知 cue 回落到该情景的默认值—— 一个手滑写错的键不会让其它配置一起失效。设置页的改动也写回同一个文件,所以清浏览器数据不会丢配置。

12 个音色包

minimal(干练精确) / soft(圆润温暖) / glass(明亮清脆) / arcade(像素游戏) / mechanical(机械硬朗) / organic(木石水声) / dreamy(空灵慢速) / scifi(全息数字) / rubber(弹性俏皮) / cinematic(深沉大片) / studio(克制精准) / zen(纸、木、风铃,默认)

浏览器自动播放策略

浏览器不允许网页在没有用户手势前启动 AudioContext,因此页面加载后第一次点击之前不会有声音, 这是浏览器行为、不是插件故障。插件在第一次 pointerdown 时预热并恢复 AudioContext, 所以从第一次点击起就该有声;若仍无声,先点一下页面任意位置。

给其它插件用的 API

浏览器半通过 ctx.reflect.provide("uiSound", service) 暴露服务:

ctx.uiSound.play("task.success")   // 按情景触发(受对应开关与总开关约束)
ctx.uiSound.playCue("achievement") // 直接播一个 cue
ctx.uiSound.preview("success")     // 设置页那种无门控试听
ctx.uiSound.getPrefs()             // 当前偏好

调试入口:window.__dshUISound()(player)、window.__dshUISoundDebug()(当前 prefs)。

架构

  • 宿主半 lib/index.js:只注入 webServer,提供 /ui-sound/api/settings(GET/POST)与 /ui-sound/api/status, 仅接受回环地址 + 同源的请求;偏好走临时文件 + rename 原子写入。
  • 浏览器半 lib/client.js:内联 uisfx 0.4.0 引擎 + DSH 集成层。 任务状态来自 ctx.sessions.list 的行级 running 与 ctx.uiSession.sessionStatus 的 pendingInteraction; 交互音来自 document 捕获阶段的 pointerdown / 键盘合成 click。
  • 无 Host 设置命名空间依赖、无 webRuntime 依赖——前者外部 bundle 插件拿不稳,后者在 DSH 0.2.0 里不存在。

与 dsh-plugin-uisfx 的关系

本插件是 dsh-plugin-uisfx(MIT)在 DSH 0.2.0-rc.2 上的就地移植适配版, 音效引擎与其 78 cue / 12 音色包完整保留,只重写了 DSH 集成层。原版在本版本上失效的三处(都不报错、只静默失效):

原版读取0.2.0 实情后果
宿主 inject: ["webServer","webRuntime"]没有任何包提供 webRuntime宿主行无法激活
ctx.sessions.list.getSnapshot().current快照是 { ids, byId, phase, projectionsBySession }任务状态监听静默失效
snapshot.pendingSessionSnapshot 只有 pendingSubmissions,待处理交互在 uiSession.sessionStatus.pendingInteraction提醒音永远不会响

另有一处设计修正:attentionSounds 开关在上游被定义、在设置页可点,但没有任何代码读它;本版把 task.pending 接到该开关上。

逐文件的来源、改动幅度与许可归属见 PROVENANCE.md。

校验(改代码前后都该跑)

仓库里的 lib/ 是提交进版本库的产物,所以 CI 不构建,只守会被手改悄悄破坏的不变量。 三条命令本地与 CI 完全一致,不需要 pnpm install(不依赖任何 npm 包):

node scripts/verify-bundle.mjs           # 发布形态契约:manifest、exports/files 目标、入口语法
node scripts/verify-package.mjs          # 发布元数据、浏览器半契约、宿主半离线求值、文档里的条数
node scripts/verify-publish-guards.mjs   # 本机绝对路径 / 账号名 / 凭据 / 内网地址

三者分工不重叠:

  • verify-bundle.mjs 管「包装出来能不能被加载」——dsh.bundle.patch、每个 exports/files 目标是否真实存在、入口文件能否解析。它接受一个可选 root,所以既能查检出,也能查解包后的发布压缩包(release.yml 就是这么复核产物的)。
  • verify-package.mjs 管「发布出去是否安全、是否还在用当前 dsh 的 API」——真实 LICENSE 文件、非 private、repository/author/meta;浏览器半只有一个 ModuleLoader 工厂、只 require("react")、不再读 0.2.0 已移除的 list.current 与 snapshot.pending。它会真的 import lib/index.js(宿主半只依赖 node: 内置模块),读回 SCENARIO_IDS / PACK_IDS / CUE_IDS / DEFAULT_PREFS,核对 README 写的 11 情景 / 12 音色包 / 78 cue 是否就是代码真实值,并验一遍 normalizePrefs 的裁剪行为。文档漂移会让 CI 红,不会等读者踩坑才发现。
  • verify-publish-guards.mjs 扫全树文本文件,命中作者本机路径、账号名、token 字面量或内网网段即失败。

.github/workflows/ci.yml 在 push / PR 上跑全部三条,另加一次 npm pack 并核对压缩包里含全部运行期文件; release.yml 在 v* tag 上出发布包。发布流程见 RELEASING.md。

已知边界(未做)

  • 只做合成音效,不支持导入自定义音频文件(uisfx 引擎本身是参数化合成,没有采样播放通道)。
  • 不做 hover 音(78 个 cue 里有 hover,但悬停发声在长时间使用中会变成噪声)。
  • 不做工具调用级别的逐次音效(一轮里几十次工具调用,会淹没真正重要的状态变化)。

许可与归属

  • 本仓库新增与重写的代码:MIT,Copyright © 2026 林冠宇 (SOH4C4759),见 LICENSE。
  • 内联的 uisfx 0.4.0 运行时:MIT,Copyright © Yuki Capital,全文见 NOTICE。
  • 移植自 dsh-plugin-uisfx:MIT,Copyright © 2026 dsh-uisfx contributors,全文见 NOTICE。
  • 逐文件的来源与改动幅度见 PROVENANCE.md。

若你是上述任一权利人或维护者,对归属写法或移植本身有异议,开一条 issue 即可,我们会立即调整或下架。

Ähnliche Plugins