# DSH Realtime Voice DeepSeek Harness 官方插件形态的实时语音 Agent:安装后在 WebUI 输入框旁出现拨打按钮,用户可持续对话、打断播报、询问进度,并用语音启动、追加、纠正或停止当前 DSH Agent 工作。 当前版本:`0.1.0-alpha.9`,目标 DSH:`0.1.0-rc.7`。 本包同时声明 DSH bundle、Host 插件和“原生 WebUI 浏览器侧”插件。这里不是另做一个网站:UI 直接注入 DSH 自带的 `http://127.0.0.1:3080`,不新增页面或 UI 端口。它不修改 DSH 源码,不另起后台进程;卸载或禁用时会移除 UI/路由并关闭麦克风、音频、浏览器 WebSocket 和百炼连接,已经交给 DSH 的任务继续运行。 ## 当前能力 - DSH 原生 3080 WebUI:拨号按钮位于发送按钮右侧,使用同尺寸、同色系的通话图标 - 独立可拖动语音浮窗;可在任意位置展开使用,也可收起为带动态波形和计时的悬浮球 - “设置 → 插件 → DSH 实时语音”内一键切换 Qwen Audio Realtime Flash/Plus;下一通生效,不中断当前通话 - “快速声学打断 / 智能语义轮次”可切换;快速模式采用浏览器本地起音检测、立即停播、Host 显式取消和百炼 VAD 三层打断 - 自动识别 `DASHSCOPE_API_KEY`,也可在插件设置中通过 DSH 官方 credentials 安全写入或替换;浏览器不可回读明文 - 默认低延迟 `server_vad`(阈值 0.35、静音 500ms),可选 `smart_turn`;实时转写、流式 PCM 播放、用户全双工打断 - 实时优先的语义交接:Qwen Audio Realtime 立即处理自然对话;只有文件、应用、设备、项目、联网、打印等真实工作才通过官方 Function Calling 交给 DSH,不靠关键词或正则脚本触发 - DSH 是唯一执行面:任务直接进入拨号时绑定的原会话;空闲时 `queue`,工作中补充或纠正自动 `steer`,不创建影子语音 Agent 或后台 worker - 进度与终态闭环:DSH 的阶段消息、`turn/end` 结果、错误和取消状态回灌实时会话;只有权威终态才会被播报为“已完成” - 审批与追问闭环:订阅 DSH 原生 `approval/requested`、`question/requested`,用户可直接口头回答,也可在悬浮窗审批卡/选项卡确认,结果通过原始 RPC 回到同一任务 - 长通话恢复:异常断线为 owner 保留 30 秒原子恢复租约,控制序号、音频 stream/sequence/PTS 跨 transport 单调延续;WebUI 定时心跳并针对百炼 `1007` 限流延长退避,DSH 中已开始的任务始终继续运行 - DSH credentials 解析 `DASHSCOPE_API_KEY`,密钥不进入浏览器包 - `dsh.voice.v1` 客户端无关协议:WebUI 与微信小程序共用 hello/ready、播放排空 ACK、24 字节二进制帧、16/24 kHz PCM、打断和恢复契约 - 客户端无关的回声控制协商:旧 V1 客户端继续由 Host 有界门控;声明“本地相关性滤波 + 有序 pre-roll”的客户端不会再被 Host 重复封麦,打断首音可无损送达百炼 - 下行 PCM 按响应重组为 24 kHz/mono/s16le 的 40ms(1920 字节)有序帧,短尾帧先送达再 finalize;普通网络抖动排队,真正失控时显式可恢复重连而不静默丢音 - DSH Host 权威单通话租约:status 只提供非秘密元数据,恢复 token 仅由 owning socket 获得;WebUI/微信同时拨号时只有 Host 原子仲裁的客户端成功 - WebUI 本地所有权优先:已 ready、正在重连或仍持有本地恢复上下文时,不会被公开 `status.active` 误画成“另一端占用”;新拨号才由 status 预检,最终始终以 Host 的 ready/busy 裁决为准 - 新增独立 `dsh.voice.direct.v1` 控制协议:微信/原生客户端可在 Host 原子占用和 DSH Agent 权威控制下,携短期百炼凭证直连媒体面;Host 控制通道严格零 PCM,Function Call、审批、追问、进度和终态通过有界、幂等的语义桥传递 - Direct offer 的输入节奏固定声明为 32ms(16kHz/mono/s16le 约 1KB),仅描述客户端直传百炼的 append 节奏;输出仍按百炼可变 delta 由客户端连续播放 - Direct 新媒体会话可通过 `dsh.voice.transcript.v1` 恢复最近 8 轮有界 final 文本:历史按百炼 `conversation.item.create` 正式注入且绝不提升为 Host 指令;断线期间挂断可用原子 `intent: release` 立即清租约,不签 Key、不建媒体会话、不取消 DSH Agent - Direct 临时 Key 产品默认 60 秒、上限 120 秒,只允许官方签发端点且禁止重定向;临时 Key 不可提前撤销并继承父 Key 权限,生产必须使用仅授权目标 Realtime 模型的专用最小权限百炼 Key 运行时为双平面:Qwen Audio Realtime 是低延迟会话面,负责听、说、自然问答、VAD 打断和判断是否需要真实执行;DSH 当前会话选择的 DeepSeek/千问等 Agent 模型是执行面,负责工具、项目上下文和持续 Agent 工作。两者通过 4 个窄语义 Function Call(交接、取消、审批、追问回答)及 DSH 权威事件合成一个助手体验。 ## 上下文模型 实时语音保留一份通话所需的短期上下文,DSH 会话保留项目与执行的长期上下文。普通聊天不会污染 DSH 任务记录;一旦用户要求真实工作,Qwen 通过 `handoff_to_dsh_agent` 把完整意图写入拨号时绑定的 DSH 会话。插件订阅同一会话的进度、审批、追问和终态,再以带类型的 `[BACKEND]` 事件注入 Qwen,使通话继续保持低延迟,而执行结果始终以 DSH 为准。 一通电话与拨号瞬间的 DSH `sessionId` 一对一绑定,而且全局同时只允许一通。页面切换不会迁移通话,悬浮窗始终显示绑定线程并可返回。DSH 的“新建会话”页面在选定工作区后已经持有一个空白 session:从这里拨号会先进行自然通话,第一项需要真实执行的要求才成为该 DSH 会话的第一轮。尚未选工作区、因此尚无 session 时,插件不会猜目录或偷偷创建无归属会话,选择工作区后拨号入口自动出现。 ## 本地开发安装 ```powershell pnpm install pnpm build pnpm test pnpm verify dsh plugin --profile web add . ``` 随后由用户选择安全时机重启 `dsh web` 并刷新浏览器。官方 `dsh plugin add/remove` 会改变 profile bundle 集合,当前 DSH 不会在已运行进程里热安装一个全新的 bundle;本插件所承诺的热插拔是:不修改本体、Fiber 生命周期完整、配置重载和卸载可彻底释放插件资源。 ## 配置密钥 插件配置只保存凭据引用,默认是 `DASHSCOPE_API_KEY`。安装后会自动识别启动 DSH 的系统环境或已有 DSH credentials;也可以打开“设置 → 插件 → DSH 实时语音”直接输入。输入值走官方 write-only credentials API,设置页面只能看到“已配置/未配置”,不能回读明文。不要把 Key 写入 `cordis.patch.yml`、浏览器代码或 Git。 ## 一键安装 从 GitHub 安装当前版本: ```powershell dsh plugin --profile web add github:martinbear1/dsh-realtime-voice#v0.1.0-alpha.9 ``` 发布包会提交预构建 `lib/`,不使用会触发 pnpm `allowBuilds` 的 `prepare`,以保持一条命令安装。 卸载: ```powershell dsh plugin --profile web remove @harness-remote/dsh-realtime-voice ``` ## 微信小程序 Host 中转协议详见 [docs/PROTOCOL.md](docs/PROTOCOL.md),客户端直连百炼媒体面的控制协议详见 [docs/DIRECT_PROTOCOL.md](docs/DIRECT_PROTOCOL.md)。Direct 模式下永久 Key 仍只由插件保管;租约成功后插件即时签发最短可用的临时凭证,小程序的 PCM 直接发送百炼,只有 DSH 控制、语义 Function Call 与 Agent 事件经过认证网关。 百炼 WSS 的鉴权位于 WebSocket `Authorization` 握手头。微信和原生客户端可使用 Direct 模式;标准浏览器 WebSocket 无法设置该头,因此 3080 WebUI 保持使用隔离且兼容的 `dsh.voice.v1` Host 中转,不会把临时 bearer 降级放进 URL。微信合法 socket 域名、恢复/刷新和消息示例见 Direct 协议文档。 小程序 V1 的产品边界是前台实时通话。微信没有承诺所有设备的 RecorderManager PCM 都具有一致的位深和字节序,所以小程序必须先通过真机探针确认 `pcm_s16le`,才能在 `voice.hello` 中声明 `pcmS16leVerified: true`。后台/锁屏连续录音、所有机型可靠全双工和裸 PCM 的统一回声消除不在 V1 承诺内;进入后台时语音链路可停,但 DSH Agent 继续运行,回到前台后重新连线并读取权威任务状态。 ## 已验证 - DSH `0.1.0-rc.7` 官方 CLI 本地安装、卸载、重新安装 - 原生 3080 WebUI 插槽:安装后按钮 1 个,卸载后 0 个,重装后恢复 - 真实 WebUI 插件配置卡:Flash/Plus 即时持久化切换;系统 Key 状态检测和 write-only 输入框正常挂载 - 真实 WebUI 布局测量:拨号按钮与发送按钮均为 34px 蓝色圆形,拨号按钮位于发送按钮右侧 - 现有 Agent 会话与所选工作区空白新会话均出现拨号入口;无工作区时不创建隐式任务会话 - `qwen-audio-3.0-realtime-plus` 真实建连、`voice.ready` 和 ping/pong - Qwen Function Calling → 绑定 DSH 会话 `queue/steer` → DSH 权威事件 → Qwen 主动播报的语义执行回环 - 真实 `ws` 成功回调兼容:首个下行音频包不会被误判为发送失败;助手流式字幕按增量完整拼接 - 本地起音约 80ms 后先清空播放,Host 对同一响应只取消一次;VAD 云端事件继续作为权威兜底 - WebUI 与微信同能力下采用相同播放仲裁:本地播放队列排空后 ACK;旧客户端或 ACK 丢失按已发送 PCM 时长有界兜底,不会永久封麦 - 任意 DashScope delta 分片按字节无损重组,sequence/PTS 按实际发出的 PCM 包递增;取消、清播和连续响应不会串入旧 remainder - 新协商的本地回声滤波客户端按同一 WebSocket 顺序发送 `voice.cancel-response` 与 pre-roll PCM,Host 保证首帧上送;未上传的纯播放回声不会触发供应端自我打断 - 悬浮窗口拖拽坐标自动限制在视口内,窗口缩放与展开/收起时不会丢出屏幕 - 插件增删前后 28 个现有会话及最新会话 ID 保持一致 - 协议能力协商、DSH 会话绑定、语义 Function Calling、审批/追问校验、播放排空、打断竞态、断线续接、占用仲裁与 Host 生命周期自动化测试 真实麦克风环境音与听感仍需人工验收;自动测试不会擅自采集或上传环境音。