Skip to content

[Bug]: 会话在 AskUserQuestion 待回答状态下切走再切回后,UI 永久卡在 processing(假死) #2335

Description

@QZQ-go

Summary

本地会话的一个 turn 以 AskUserQuestion 工具调用结束、正在等待用户选择时,用户切换到其他会话(我这里切到了远程中继 remote workspace 的会话),之后再切回该会话,UI 永远显示 processing 状态、输入被锁死(假死)。而后端 runtime_state 实际是 Idle,没有任何任务在跑,也没有任何超时/恢复机制能解开。

期望行为:切回会话时应恢复"等待用户回答 AskUserQuestion"的交互状态(或至少将未完成 turn 标记为可继续),输入框保持可用。

根因分析(基于日志与落盘数据)

  1. 挂起状态未被持久化:turn 落盘时 status = "inprogress",最后一个 modelRound status = "streaming"。发出 AskUserQuestion 的那一轮 model response(19:26:59.768)没有写入 turn 文件(turn 文件最后写入时间 19:25,早于该响应)。
    • 证据:~/.bitfun/projects/<project>/sessions/452ffb66-b04d-4efc-b803-408c9f55c575/turns/turn-0001.json"status": "inprogress"modelRounds[last].status = "streaming"
  2. 后端空闲但 UI 恢复为 processing:切回会话触发 hydrate 后,前端 SessionStateMachine 把这个 20+ 分钟前的旧 turn 直接置为 processing,但没有任何后端任务与之对应:
    [2026-08-14T19:45:17.852][SessionStateMachine] State transition
    {"sessionId":"452ffb66-...","fromState":"idle","event":"start","toState":"processing",
     "payload":{"taskId":"452ffb66-...","dialogTurnId":"dialog_1786706585658_k00koobra"}}
    
    同时刻后端 session state.json"runtime_state": "Idle"
  3. 挂起的 AskUserQuestion 交互卡无法重新渲染,webview 同时反复报错:
    [FileOperationToolCard] Failed to load operation summary {...}, TauriCommandError: Failed to get operation summary: Operation not found: call_...
    

对话数据本身完好(turn-0000 / turn-0001 均完整落盘),重启后可以继续,所以这是状态恢复问题而不是数据丢失。

时间线(日志证据,2026-08-14)

时间 事件
19:23:05 用户发送第 2 条消息,Dialog turn started: dialog_1786706585658_k00koobra
19:23–19:26 agent 正常执行多轮工具调用(Grep/Read/Write/ExecCommand 均完成)
19:26:59.768 ai::model_response 收到完整响应:tool_calls=AskUserQuestion(stream 正常 done_marker_received)。turn 进入等待用户输入状态,此后该 turn 再无任何持久化,也永远没有 Dialog turn completed
19:38:08 / 19:45:17 / 19:48:09 三次切回该会话:switch_activated_after_hydrateidle → processing(恢复旧 turnId),后端无任务对应,UI 假死

复现步骤(推测,基于观察到的证据)

  1. 在本地会话让 agent 执行一个会以 AskUserQuestion 结束(等待选择)的任务;
  2. 不回答,切换到远程中继 workspace 会话或任意其他会话;
  3. 稍后切回原会话;
  4. 观察:UI 卡在 processing、输入不可用;后端无运行中任务。

修复建议

  • hydrate 时若后端 runtime 为 Idle 且 turn 为 inprogress:不要直接置 processing,可标记为 interrupted 并给用户一个"继续/重试"入口;
  • 或将 pending 的交互式工具调用(AskUserQuestion)状态持久化,切回时重新渲染交互卡,让用户可以补答;
  • 至少保证输入框不被永久锁死(现在没有任何出路,只能重启应用或放弃该会话)。

Environment

  • BitFun: 0.2.18(macOS,/Applications/BitFun.app)
  • 模型: glm-5.3(OpenAI 兼容 stream)
  • 场景:自建 relay + 远程 SSH workspace(mac mini),在本地会话与远程会话之间切换
  • 会话 ID: 452ffb66-b04d-4efc-b803-408c9f55c575(本地 workspace)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions