Files
qiming/qimingclaw/docs/agent-cancel-time-optimization.md

3.9 KiB
Raw Permalink Blame History

取消 Agent 任务 — 时间优化(重构版)

分析范围Electron 客户端侧「取消 agent 任务」整条链路 + 可落地优化方案。 最后更新2026-03-17


1. 当前链路与实际实现

1.1 入口与路径(已核对代码)

入口 路径 最终调用
渲染进程 / 外部 HTTP computer:cancelSession IPC 或 POST /computer/agent/session/cancel AcpEngine.abortSession(sessionId)
应用内 agent 停止 agent:abort IPC agentService.abortSession(id)engine.abortSession(id)

1.2 关键实现acpEngine.abortSession

当前核心逻辑:

  • ABORT_TIMEOUT = 30_00030s
  • await ACP cancel(最多 30s
  • reject 本地 prompt
  • 多 session 取消为串行

对应文件:

  • /Users/apple/workspace/qiming-agent/crates/agent-electron-client/src/main/services/engines/acp/acpEngine.ts
  • /Users/apple/workspace/qiming-agent/crates/agent-electron-client/src/main/services/computerServer.ts
  • /Users/apple/workspace/qiming-agent/crates/agent-electron-client/src/main/ipc/computerHandlers.ts

2. 现存问题与体验风险

问题 表现 用户影响
cancel 等待过长 固定 30s 取消最坏 30s 才返回,体验迟滞
本地 reject 延后 必须等 ACP cancel prompt() 与 UI 状态更新偏慢
多 session 串行 总时长累加 批量取消耗时线性增长

新增风险(如果改成“先 reject 再 ACP”

  • 会话在 ACP 端仍运行,但 UI 可能允许新 prompt 进入,造成重入/交叉输出风险。
  • ACP 仍持续吐 SSE 更新,可能出现“取消后还继续输出”的错觉。

3. 落地方案(带安全护栏)

3.1 缩短 ACP cancel 等待时间(必做)

  • ABORT_TIMEOUT 从 30s 缩短至 10s(与 rcoder 默认一致)。
  • 超时后仍按现有 catch/清理逻辑执行。

3.2 先 reject 本地,再等待 ACP推荐但必须加护栏

目标:让 UI 和 prompt() 立即返回“已取消”

实施细节:

  1. cancelOne() 里先:
    • session.status = "terminating"
    • 立即 reject 本地 prompt并清理 activePromptRejects/activePromptSessions
  2. 再发送 ACP cancel 并等待 Promise.race(..., timeout)
  3. ACP cancel 返回或超时后,再设置 session.status = "idle"

护栏(必须落地):

  • prompt() 开头添加 guardsession.status === "terminating",直接拒绝新 prompt避免 ACP 端仍在运行时重入。
  • handleAcpSessionUpdate() 在 session 处于 terminating 时,忽略 message/tool 类 SSE 更新(避免“取消后仍继续输出”)。

3.3 多 session 取消并行化(可做)

  • for ... await cancelOne() 改为 Promise.all(...)
  • cancelOne() 内部已捕获错误,因此并行不会导致整体 reject。

3.4 “先 200 再后台 cancel”暂不默认

  • HTTP/IPC 可以不 await abortSession(),先返回 200 再后台收尾。
  • 这是强 UX 优化,但语义变化较大(“已取消”并不代表 ACP 已停止)。
  • 建议保留为可选策略,需产品确认语义。

4. 推荐实施顺序

  1. 必做ABORT_TIMEOUT 30s → 10s
  2. 推荐:先 reject + terminating guard + SSE 抑制
  3. 可选:并行 cancel
  4. 可选HTTP/IPC 先 200

5. 测试覆盖建议

新增单测覆盖:

  • abortSession() 会在 ACP cancel 之前先触发本地 reject。
  • abortSession() 超时后仍完成清理并返回。
  • prompt()terminating 状态被拒绝(防止重入)。
  • handleAcpSessionUpdate()terminating 状态下抑制输出(避免 ghost SSE

6. 小结

本次落地以 “体验明显提速 + 语义不破坏” 为原则。

核心点:

  • 缩短 cancel 等待时间
  • 本地快速 reject + terminating 护栏
  • 可并行化提升批量取消效率
  • “先 200” 保留为可选项,不强推