# AI 参数重名优先级调整(2026-10-09) ## 使用者确认的规则与范围 此前契约和绑定检查拒绝 params 中的协议重名字段,真实 SaaS 任务 4 同时给出 `agent.tts.voice` 与 `agent.tts.params.voice`,导致 Dispatcher 退出。 使用者明确确认变更:**任务/会话生成字段优先,忽略 params 中重名键,其他参数按原值传递**。同值、不同值或 null 均使用该优先级;不修改获批任务原始快照,不要求 SaaS 删除原有重复字段。参数仍是必填、可空的平坦对象,本轮不改变其他结构和业务规则。 同步共享契约、实现、测试和说明,验证后提交并推送、重新部署 `server.sip`。保留固定配置、数据和既有 SaaS 任务授权,不清理或迁移数据、不操作真实 MQ 拓扑、不重启 Asterisk、不独立试拨或主动投递任务。 ## 共享契约及 SaaS 通知 共享仓库 `sip-contracts` 提交 `f490afab764a702dda919c718dca1a05e5bceb0a` 已推送,本项目同步固定该提交。规范位置为 `contracts/schema/saas-dispatcher.md` 的 AI 参数段落。Schema 已接受这类平坦对象,无需改变数据结构。 提供给 SaaS 开发人员的变更通知:重名参数不再导致任务拒绝,任务/session 的 model、voice、消息及事务身份具有优先权。现有任务中重复 voice 不需要删除或更改任务内容,其他参数继续原值传递;其余现行契约不变。 ## 实际改动 - 删除绑定阶段 ASR/LLM/TTS 重名参数拒绝和废弃的 `reservedParams` 路径,不保留旧拒绝兼容层。 - LLM 和百炼 TTS 已有“复制 params,再写入任务/会话字段”的组装逻辑,分别保证 model/messages、voice 优先;补完整任务绑定到实际请求的回归,不只是手工构造绑定对象。 - 火山 ASR 在对接 SDK 前复制 params,并移除与 SDK 生成字段重名的 `reqid`、`sequence`、`model_name`。请求使用任务 model 和真实 session 身份,其他参数保持原值,原快照及绑定中的 params 不改。 - SDK 自身保护生成身份的规则不变,本次是业务优先级调整,不是 SDK 缺陷,不改依赖版本或引入本地 replace。 - 更新现行 `AGENTS.md`,旧部署证据标明当时拒绝规则及要求 SaaS 删除 voice 的建议已被取代,历史事实仍保留。 ## 验证 - 测试先加入重名键,旧代码在 ASR、LLM、TTS 绑定阶段明确失败;修复后通过。 - 同值、不同值、null 三组重名值均接受,任务字段不被改写,原始任务快照不变。 - ASR WebSocket 实际请求:model_name 采用任务值,reqid/sequence 由 session 生成,原绑定中重名值仍保留;其他字段以及 false、null、大整数保持原值。 - LLM HTTP 实际请求:model/messages 采用任务/会话值,其他字段原值传递。 - 百炼 TTS WebSocket 实际请求:voice 采用任务值,其他字段原值传递。 - Agent 正式快照与重放保护测试接受重名键、不改冻结绑定;缺失/null/非对象/嵌套参数等原先无效结构仍明确拒绝,拒绝不得持久接纳或拨号。更新旧的“重名即无效”测试为真正的结构错误测试,不削弱基础校验。 - `make proto-check acceptance-local`、`make release-check-local`、`go vet ./...`、`go test -race ./...`、构建及隔离 RabbitMQ/HTTPS/双向 TLS 端到端全部通过。 - 业务单元覆盖率 **70.8%**。 - 本地 mock 请求不代表供应商实际可用、真实通话、AI/录音/OSS 或生产验收。 ## 部署验证与保留的验收边界 2026-10-09 17:16 安装,17:20–17:24(Asia/Shanghai)只读复核: | 项目 | 现场事实 | | --- | --- | | 已推送、已安装源码 | `ddd4de20fac1d224ad5afb8d710bcc52e7fcd821` | | 制品 SHA-256 | `3356f12e89927835d82e2a7c08f63d281ce5b48084bdb94949ea1c8095dcbf02` | | 制品一致性 | 两角色固定 `current` 解析至该提交,运行制品与发布清单 hash 相同 | | Agent | enabled、active/running;PID `2872989`,重启次数 `0` | | Dispatcher | enabled、active/running;PID `2873001`,17:16:23 至 17:24:55 未变,重启次数 `0`、退出状态 `0` | | Asterisk | enabled、active/running;PID `777461`、10 月 5 日启动时间未变,未重启 | | SaaS 原任务 | 17:24:55 HTTP 200、归属正确;任务 4 revision `1`,原 voice 与 params.voice 均仍存在且同值,无需平台修改 | | 任务与发现 | 四个真实任务的快照已接纳,均为 `paused`;持久 discovery_ready=true | | 实际 SIP | 原启动代次 16 加载核对成功;随后处理真实 SaaS 队列中的既有 SIP 通知,完整读取并确认新本地加载代次 `17`,pending=0 | | 数据保留 | 未 reset;SQLite inode `416829`、user_version `3` 不变;inbox 无占用 | | 主配置保留 | `pjsip.conf` SHA-256 仍为 `29619dcad31c31adde63ae1fc74b95feb10943a601f120f34d54ec332f7b708c` | | 活动通道 | 安装前后只读核对为 0,未独立拨号或主动投递任务 | 原参数冲突不再阻止启动,真实 SaaS 保留重复 voice 的任务已被接受,Dispatcher 已持续运行,没有用清数据、改 SaaS 任务或删除其他有效参数解决。 ### 独立部署探测仍需区分 安装返回 `ok=true`,三服务 enabled/active、制品检查和监听通过;但状态工具仍显示 `dependency_state=saas_pending`、`business_ready=false`。其计算只引用启动前保存的 `dependency-status.json`:该独立 probe 的 tasks 阶段失败,只保存 `*fmt.wrapError`、http_status=0、transport_failure=unavailable,未提供具体原因。本次没有重写该文件、把失败改成成功或更改探测程序。 上述标签不能替代真实程序的持久发现就绪、四个任务快照已接纳、SIP 17 已核对和连续零重启事实;同时真实程序运行正常也不能代签这项独立探测。探测失败的具体原因尚未定位,完整外部依赖/部署验收仍保留未完成项,不把这轮参数修复扩大成所有检测都通过。 四个任务均处于暂停状态,本轮没有实际外呼、供应商 ASR/LLM/TTS、录音/OSS 或重启自启动验收;未提交或输出凭据、prompt、完整配置、通话内容或音频。