Files
story/device-simulator-windows
Codex Local 0c2151ace9
ci / verify (push) Canceled after 0s
chore: checkpoint 第一版
2026-09-06 17:04:11 +08:00
..
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00
2026-09-06 17:04:11 +08:00

Windows 硬件对话智能体测试程序

这是方案 1 的 Windows 端到端验收工具。默认页面不再使用平台代管的 RTC/StartVoiceChat,而是按火山“硬件对话智能体低负载标准协议”直接连接 wss://ai-gateway.vei.volces.com/v1/realtime。传统 RTC 模拟器仍保留在页面右上角的“传统 RTC 测试页”。

实际覆盖的流程

  1. 使用平台设备 ID、时间戳、随机数、正文摘要和 HMAC-SHA256 调用设备 v2/v3 接口。
  2. 调用平台 /device/v3/hardware-agent-credentials:provision;平台自动应用产品级Instance ID、Product Key、默认Bot、传输和最低SDK配置,并使用KMS/Secret挂载的 Product Secret 代设备调用 DynamicRegister。
  3. 火山在动态注册时从产品额度中分配 License;平台只把本设备 Device Secret 下发给设备,Windows 使用 Safe Storage 加密保存后重新拉取配置版本并进入 ACTIVE。
  4. 创建 /device/v3/agent-sessions,从平台取得产品默认 Bot ID、low_load 传输方案、本次冻结的人设、背景、最近摘要、确认记忆和授权范围。
  5. 按火山规定的请求头签名建立 WebSocket,等待 session.created,提交本次 session.update,收到 session.updated 后才向平台回报 session_started并开放麦克风。
  6. Windows 麦克风被转换为 PCM16、16kHz、单声道、20ms 分片,通过 input_audio_buffer.append 实时上行;response.audio.delta 按火山 low-load WebSocket SDK 的 PCM16、16kHz、单声道格式实时播放。
  7. 消费服务端 VAD、用户最终识别、智能体最终字幕、Function Calling 和错误事件;双方最终话轮通过 v3 turns:batch 幂等上传。
  8. 智能体触发 memory_search、search_memory 或 retrieve_memory 时,程序使用平台签发的当前会话短期令牌调用同源记忆工具,再把结果作为 function_call_output 返回火山。
  9. 周期提交 session_updated。平台返回 stop_session 时立即关麦、补传字幕、关闭火山连接并回报 session_ended。
  10. 页面显示 13 项验收门禁,可导出不包含任何密钥的 JSON 报告。

使用前配置

平台维护中心只需把测试设备配置为:

  • voice_runtime = volc_hardware_agent

平台部署需配置并关联同一火山产品和 Bot:

  • Instance ID
  • Product Key
  • 默认 Bot ID
  • 传输方式 low_load
  • 最低 SDK 版本不高于 1.1.0-windows-standard-protocol
  • Product Secret(只进入平台密钥挂载,不进入Windows程序)
  • Device Name 由平台按设备ID稳定生成,或使用设备绑定中预先登记的名称
  • 可用的硬件对话智能体 License

Windows程序不提供 Product Secret、Device Secret 或 Bot ID 输入框。Bot ID、Instance ID、Product Key 和 Device Name 均来自平台;设备不能覆盖产品默认路由。

开始测试前还需按控制台中的 Bot 模型选择“智能体模型类型”:

  • 通用 LLM:使用官方 config.LLMConfig.SystemMessages 注入平台冻结的人设、背景与授权上下文;
  • 豆包端到端语音:使用官方 config.S2SConfig.ProviderParams.dialog 注入 system_role、speaking_style 和 dialog_id。

两种模式都使用官方 session.object/config/agent_config/input_audio_format/output_audio_format 报文结构。字段依据火山初始化会话配置与标准协议自定义接入文档。

构建

Set-Location .\device-simulator-windows
npm install
npm run build

输出文件:

release/hardware-agent-tester-0.3.5-windows-x64.exe

当前测试包未配置商业代码签名证书,Windows 可能显示“未知发布者”。交付前可用同目录 SHA-256 文件校验完整性;正式面向终端用户分发时应由甲方或发布主体使用其代码签名证书签名。

npm run build 会依次执行协议单测、TypeScript 检查、双页面构建和 Windows x64 便携包封装。

本地完整自动回归

先启动仓库根目录的 Compose 开发环境,然后运行:

Set-Location .\device-simulator-windows
pwsh -NoProfile -File .\test\run-hardware-e2e.ps1
pwsh -NoProfile -File .\test\run-hardware-e2e.ps1 -ModelMode s2s
pwsh -NoProfile -File .\test\run-hardware-e2e.ps1 -ExecutablePath .\release\hardware-agent-tester-0.3.5-windows-x64.exe

第一条验证通用 LLM 报文,第二条验证端到端语音报文。回归会临时创建 low_load 设备绑定,启动一个校验真实火山签名和事件格式的本机 WebSocket 网关,再启动实际 Electron 窗口。测试只有在以下证据全部成立时才返回 PASS:

  • 动态上下文确认后才开放麦克风;
  • PCM 上行和音频下行均发生;
  • 用户与智能体各产生一条最终字幕并写入 PostgreSQL;
  • 平台下发停止状态,Windows 程序通过下一次 session_updated 收到 stop_session;
  • 会话、硬件会话均为 COMPLETED;
  • SaaS conversation.started 和 conversation.completed 事件均已产生;
  • 页面 13 项验收门禁全部通过。

测试结束会删除临时会话、事件和设备绑定,不污染日常开发数据。

安全边界

  • Product Secret 只存在于平台KMS/Secret挂载和注册调用内存,不到达设备,不写入数据库明文、日志或报告。
  • 平台返回的本设备Device Secret使用 Electron safeStorage 加密后保存在当前 Windows 用户目录,不进入源码和安装包;License由火山产品侧分配,不下发Windows程序。
  • 平台设备密钥只驻留 Electron 主进程,渲染页面不能读取已加载的明文。
  • 记忆工具地址必须与配置的平台 API 同源,防止短期令牌被发送给第三方地址。
  • 默认只允许连接火山官方硬件网关;本机 ws://127.0.0.1 仅供自动回归。
  • 平台确认 session.updated 前不会启动麦克风;收到 stop_session 后不会继续发送音频。
  • 导出的报告包含设备标识、Bot、配置摘要、事件和字幕,但不包含 Product Secret、Device Secret、平台签名密钥或记忆工具令牌。
  • 自动回归通过仅在SIMULATOR_AUTO_TEST=1时生效的进程环境注入mock一机一密,不写入正式Windows凭据缓存。

真实验收与本地模拟的区别

0.3.5 播放速度修复

  • 根据火山 low-load WebSocket SDK 示例,将智能体下行 PCM 的源采样率从错误的 24kHz 修正为 16kHz,避免 1.5 倍速和音调升高。
  • Windows 输出设备不是 16kHz 时,由 AudioWorklet 按实际系统输出采样率连续重采样,不改变语速和音高。

0.3.4 连续音频播放修复

  • 火山返回的 pcm_s16le/16kHz/mono 音频进入常驻 AudioWorklet 环形缓冲,不再按 WebSocket 分片创建独立播放器。
  • 默认预缓冲 120ms,网络瞬时抖动时自动重新缓冲,减少断音、金属音和语速漂移。
  • 连续处理跨分片的奇数字节,并在开始、结束和断流时做短淡入淡出以避免爆音。
  • 测试报告新增播放分片数、采样数和欠载次数。

0.3.3 失败会话修复

  • 火山 error 事件与连接 Promise 的异常共用一个失败清理任务,同一轮仅提交一次 session_failed,保留首次错误。
  • 失败清理期间禁止发送文字或重复结束;延迟到达的事件不再恢复“通话中”。失败后重新检测即可开始新一轮。
  • 新通话清空上一轮验收结果、错误和计时;失败清理的关闭不再标为正常关闭。
  • npm test 包含执行实际渲染器代码的并发失败回归测试,不会连接线上平台或消耗火山额度。
  • 此修复不代表火山 internal_error: StartVoiceChat failed 的上游原因已解决。

本地自动回归证明 Windows 程序、平台控制面、数据库、PCM 管道和协议状态机完整可执行。最终真实火山验收仍必须使用实际 Instance/Product/Device/Bot/License 凭据,确认火山返回真实 ASR、LLM、TTS 音频;程序不会把本机模拟网关的 PASS 冒充真实供应商验收。