3.9 KiB
3.9 KiB
取消 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_000(30s)- 先
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() 立即返回“已取消”。
实施细节:
cancelOne()里先:session.status = "terminating"- 立即
reject本地 prompt,并清理activePromptRejects/activePromptSessions
- 再发送
ACP cancel并等待Promise.race(..., timeout)。 - ACP cancel 返回或超时后,再设置
session.status = "idle"。
护栏(必须落地):
prompt()开头添加 guard:若session.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. 推荐实施顺序
- 必做:
ABORT_TIMEOUT30s → 10s - 推荐:先 reject + terminating guard + SSE 抑制
- 可选:并行 cancel
- 可选:HTTP/IPC 先 200
5. 测试覆盖建议
新增单测覆盖:
abortSession()会在 ACP cancel 之前先触发本地 reject。abortSession()超时后仍完成清理并返回。prompt()在terminating状态被拒绝(防止重入)。handleAcpSessionUpdate()在terminating状态下抑制输出(避免 ghost SSE)。
6. 小结
本次落地以 “体验明显提速 + 语义不破坏” 为原则。
核心点:
- 缩短 cancel 等待时间
- 本地快速 reject + terminating 护栏
- 可并行化提升批量取消效率
- “先 200” 保留为可选项,不强推