# 普通聊天模型切换确认与 Grok 4.7 验证 ## 问题与修复 普通聊天把 `config.set` 返回的本地模型确认写入 `ChatRouteState.pendingApproval`。随后普通聊天 transcript 快照中的 `pendingApproval: null` 会清除此卡片,但待切换模型仍在本地保留。下一次发送再次要求确认,表现为模型名称已经改变、消息却发送失败。 模型确认现在单独保存为响应式状态,按会话显示,不再被服务端工具审批快照覆盖。确认后正常提交模型设置;取消或重新选择会清理旧确认,过期确认不会误发为工具审批。等待确认期间重复发送不重复请求模型切换。 ## 验证 - 新增回归测试在修复前复现:模型确认经过 transcript 更新后变成 `undefined`。 - 修复后验证确认保留、确认后发送、无重复模型切换、重新选择清理旧确认,以及与工具审批互不覆盖。 - 65 项聊天、模型、同步和消息失败相关测试通过。 - `npm run typecheck` 与 `npm run build` 通过;构建仍有既有的大资源包提示。 ## 模型实际请求 2026-09-29 08:51 左右,通过瑶儿 Profile 使用的 Hermes xAI OAuth 凭据解析器,对同一供应商 Responses 接口发送独立的最小请求,未修改聊天内容或会话模型。 - 请求模型:`grok-4.7` - 提示:`Reply with exactly OK.` - HTTP 状态:200 - 返回模型:`grok-4.7` - 返回状态:`completed` - 输出:`OK` - 耗时:3.89 秒 本机运行日志也显示问题会话当天成功调用过 Grok 4.7,后续会话实际模型是 Grok 4.6。最小请求证明该账号通道当时可用,不代表已在用户另一台电脑上完成客户端验收。 ## 范围说明 Hermes 的长上下文切换确认默认阈值为 100,000 token,该会话最近一次实际输入约 181,833 token。确认是为了提示切换模型后的缓存失效,并非 Grok 4.7 不可用。费用及长上下文确认规则保持原样。 截图的 1015.9k 不能直接解释为当前上下文超限:当前 UI 在缺少上下文值时会回退到累计用量。此次未改动该显示逻辑。 首次排查完成源码修复与提交后,用户继续反馈卡片自动消失、点击允许无效,随后完成以下部署与验收。 ## 实际部署与浏览器验收 - 运行服务原来是提交 `6396efc`,尚未包含此次修复。 - 执行 `npm run desktop:build`,通过 `bin/desktop-service-sync.mjs` 更新现有 15300 服务。同版本构建先后关系无法自动判断,核对目标后使用更新器的 `force: true` 覆盖流程,保留更新前数据备份。 - 当前服务构建:`af061893a4e6471f06258af10d918b48dd92f722`,资源摘要 `d6bfeae0acc817a99917b09ab5b0845bf6733d969e5de0693a7fa9480687d3c1`。`/healthz`、`/readyz` 均成功。 - 在新服务的真实认证浏览器页面中打开原会话并重新加载,选择器与服务器均返回 `grok-4.7`。 - Hermes 日志确认:用户 08:53:26 发送的“测试”已使用 `grok-4.7`,08:53:47 完成回复;此次验收没有额外向该会话发送聊天消息。 - 新增 `tests/e2e/model-confirmation.spec.ts`:在隔离测试服务中渲染完整聊天页面,模拟供应商模型确认响应,经过两次真实 transcript SSE 重连后卡片仍可见;实际点击“允许”发送 `confirm_expensive_model: true`,随后聊天提交成功。该测试使用假 Gateway,不计入真实供应商调用证据。 - 同一浏览器测试分别加载旧部署 UI 和新 UI:旧 UI 在重连后丢失卡片、测试失败;新 UI 全流程通过。 - 远端已打开的页面需要重新加载才能取得新资源;没有直接操作或验收用户另一台电脑的桌面进程。没有重启 Hermes。