fix(consult): replay an unstarted consultation after refresh
Independent Staging Quality Gate / validate (push) Successful in 7m57s
Independent Staging Quality Gate / publish (push) Has been cancelled

Sending cleared the draft and stored a request id before the server reserved usage, so a refresh left a sent question with no agent run.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-18 17:33:23 +08:00
parent f4a2ba86ae
commit 188cff99ec
6 changed files with 269 additions and 101 deletions
+16
View File
@@ -4097,3 +4097,19 @@
- 相关记录:无
- 复发自:无
- 修复版本:已推入 staging,待部署
## BUG-276 | 发送后刷新草稿被正确清空,但咨询请求从未落地,Agent 无反应
- 状态:resolved(已推入 staging,待部署)
- 首次发现:2026-08-18
- 最近更新:2026-08-18
- 影响面:`/` 主对话发送、`POST /api/consult``GET /api/consult/status`、tab 内 `jyotisha.pending-consultation` 恢复。
- 用户现象:正常发出一条咨询后立刻刷新。输入框草稿已清空,不会把刚发出的问题填回来;对话里也看不到后台任务,Agent 没有后续反应。`GET /api/consult/status` 对这次 `requestId` 返回「咨询请求不存在」。
- 触发条件:点击发送后、服务端 `reserve_consultation_usage` 写入之前刷新页面。包括 2.5 秒撤回窗口内、问题持久化过程中,以及咨询 POST 已发出但还在选路/扣点、尚未插入 `consultation_requests` 时。
- 根因:发送在点击当下就清草稿、写入 pending `requestId` 并展示用户气泡,但真正的咨询占位发生在撤回窗口和 `persistSession` 之后的 `POST /api/consult` 里。刷新会中断这次 fetch。服务端只有在流开始之后才会 `continueAfterDisconnect`;占位之前断开则行不存在。刷新后恢复链路只轮询 status:把首次 404 当成「可能还在启动」假装 reserved,连打三次 404 后放弃,并且从未用同一 `requestId` 重放 POST。pending 存储也只留了 session/request id,撤回窗口内刷新时问题正文既不在会话里也不在草稿里。
- 修复:pending 存储同步写入问题原文、主题和入口;刷新恢复时用这份原文补回用户气泡。status 首次 404 仍等待一次确认,第二次 404 则跳过撤回窗口、不重复追加用户消息,用原 `requestId` 重放 `POST /api/consult`。若重放撞上 `request_conflict`(原请求稍后占位成功),改回 status 轮询而不是当成失败解锁。三次以上确认仍 404 才停止恢复。草稿仍在发送时清空,避免已发出的问题被填回输入框。
- 验证:`frontend/tests/consultation-recovery.test.ts` 覆盖 pending 带问题正文、404 后重放而非放弃、`request_conflict` 留在恢复态;既有草稿隔离合同继续要求发送清空存储键。
- 防复发:刷新恢复不得把「status 404」直接解释成用户已取消或请求已结束;在占位完成前断开必须能用同一 requestId 重放生成。pending 存储必须包含重放所需的问题原文。已发出的问题不得靠草稿复活,必须出现在会话里并由 Agent 继续。
- 相关记录:BUG-249(草稿持久化清空已发送问题,本条保留该行为)、咨询流恢复迁移 `20260808030000_consultation_stream_recovery.sql`(断线后续跑只覆盖已占位的 reserved 请求)
- 复发自:无
- 修复版本:已推入 staging,待部署