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

115 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 取消 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()` **立即返回“已取消”**
实施细节:
1. `cancelOne()` 里先:
- `session.status = "terminating"`
- 立即 `reject` 本地 prompt并清理 `activePromptRejects/activePromptSessions`
2. 再发送 `ACP cancel` 并等待 `Promise.race(..., timeout)`
3. 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. 推荐实施顺序
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” 保留为可选项,不强推