Skip to content

feat: 统一 Agent 失败收尾与文件回滚流程#47

Merged
ztygod merged 1 commit into
mainfrom
feat/common-error
Jul 18, 2026
Merged

feat: 统一 Agent 失败收尾与文件回滚流程#47
ztygod merged 1 commit into
mainfrom
feat/common-error

Conversation

@ztygod

@ztygod ztygod commented Jul 18, 2026

Copy link
Copy Markdown
Owner

背景

此前 Agent 的正常结束和异常结束分别走不同的处理路径。

达到最大迭代次数、验证不通过等非异常失败可以触发文件回滚,但模型、工具链或验证器抛出异常时会直接进入 catch 并返回,可能跳过文件回滚、Memory 保存和部分终止处理。

此外,原有回滚逻辑依赖已经创建的 checkpoint,存在以下问题:

  • 文件写入后、checkpoint 创建前发生异常时,修改无法回滚。
  • 同一文件经过多次累计 checkpoint 后,倒序回滚可能产生 Hash 冲突。
  • 回滚状态会覆盖任务本身的失败状态。
  • Memory、Observer 等非关键收尾逻辑异常可能影响主任务结果。
  • Abort 场景缺少明确且一致的最终状态。

本次改动

1. 统一 Agent 收尾流程

将原有运行逻辑拆分为:

  • executeRun:负责工作区准备、模型调用、工具执行和结果验证。
  • finalizeRun:负责文件回滚、最终状态计算、Memory 保存、结束中间件、终止事件和资源清理。

模型、工具、验证和 Abort 等所有退出路径现在都会进入统一的 finalizeRun,避免异常路径绕过必要的收尾逻辑。

2. 改为任务级文件回滚

ChangeTracker 现在以整个 Agent Run 为单位维护文件基线:

  • 第一次写入文件时记录任务开始前的内容。
  • 后续修改只更新文件的最新内容。
  • 任务失败时直接从最新内容恢复到任务开始前的内容。

新增 rollbackAll,不再通过倒序执行多个累计 checkpoint 完成回滚。

Checkpoint 继续用于记录修改过程、生成 Trace 和向 UI 展示 Diff,但不再作为实际回滚指令。

3. 支持未创建 checkpoint 的修改回滚

回滚逻辑现在直接读取当前 ChangeTracker 中的累计变化,不再依赖 run.changes

因此以下场景也能够正确恢复文件:

工具写入文件
→ 工具中间件发生异常
→ checkpoint 尚未创建
→ 任务进入统一收尾
→ 文件恢复到任务开始前状态</span></code></pre><h3><span>4. 增加结构化回滚结果</span></h3><p><span>回滚结果现在包含:</span></p><ul data-spread="false"><li><p><code><span>not_required</span></code><span>:没有需要回滚的文件。</span></p></li><li><p><code><span>completed</span></code><span>:所有文件恢复成功。</span></p></li><li><p><code><span>partial</span></code><span>:部分文件恢复成功。</span></p></li><li><p><code><span>failed</span></code><span>:所有文件恢复失败。</span></p></li></ul><p><span>同时返回:</span></p><ul data-spread="false"><li><p><span>已恢复文件列表。</span></p></li><li><p><span>回滚冲突及对应文件。</span></p></li><li><p><span>冲突原因。</span></p></li></ul><p><span>回滚前仍会检查文件 Hash。如果文件在 Agent 写入后被用户或其他程序修改,将拒绝强制覆盖,并记录为回滚冲突。</span></p><h3><span>5. 分离任务结果与收尾结果</span></h3><p><span>任务结果和回滚结果现在分别记录。</span></p><p><span>例如模型异常但文件成功恢复时:</span></p><pre><code><span>{
  stopReason: "error",
  task: {
    status: "failed"
  },
  finalization: {
    rollback: {
      status: "completed"
    }
  }
}</span></code></pre><p><span>这能够同时表达:</span></p><ul data-spread="false"><li><p><span>用户任务执行失败。</span></p></li><li><p><span>Agent 产生的文件修改已经成功恢复。</span></p></li></ul><p><span>回滚不再将任务状态覆盖为 </span><code><span>rolled_back</span></code><span>。</span></p><h3><span>6. 明确 Abort 行为</span></h3><p><span>用户取消任务时:</span></p><ul data-spread="false"><li><p><span>停止后续模型和工具循环。</span></p></li><li><p><span>跳过验证及自动修复。</span></p></li><li><p><span>根据 </span><code><span>rollbackOnFailure</span></code><span> 决定是否回滚修改。</span></p></li><li><p><code><span>stopReason</span></code><span> 设置为 </span><code><span>aborted</span></code><span>。</span></p></li><li><p><code><span>task.status</span></code><span> 设置为 </span><code><span>cancelled</span></code><span>。</span></p></li><li><p><span>不将用户取消视为系统运行异常。</span></p></li></ul><h3><span>7. 隔离非关键收尾错误</span></h3><p><span>Memory 保存、结束中间件和 Observer 属于非关键收尾操作。</span></p><p><span>这些操作失败时:</span></p><ul data-spread="false"><li><p><span>不覆盖模型、工具或验证产生的主错误。</span></p></li><li><p><span>不改变已经确定的任务结果。</span></p></li><li><p><span>不触发对成功任务的回滚。</span></p></li><li><p><span>错误统一记录在 </span><code><span>finalization.issues</span></code><span> 中。</span></p></li></ul><p><span>例如代码修改和验证已经成功,但 Memory 保存失败时,任务仍然返回 </span><code><span>completed</span></code><span>。</span></p><h3><span>8. 统一终止事件入口</span></h3><p><span>新增统一的 </span><code><span>runTerminated</span></code><span> 入口,根据最终 </span><code><span>stopReason</span></code><span> 发送对应的完成或失败事件。</span></p><p><span>Observer 和 EventBus listener 异常会被记录为收尾问题,不再中断 Agent 主流程。</span></p><p><span>运行注册的释放仍放在 </span><code><span>finally</span></code><span> 中,确保所有退出路径都能完成资源清理。</span></p><h2><span>测试覆盖</span></h2><p><span>新增和补充了以下测试:</span></p><ul data-spread="false"><li><p><span>模型异常后回滚已经 checkpoint 的修改。</span></p></li><li><p><span>工具写入后、checkpoint 前发生异常时回滚修改。</span></p></li><li><p><span>验证器抛出基础设施异常后回滚修改。</span></p></li><li><p><span>Abort 后返回 </span><code><span>cancelled</span></code><span> 并回滚修改。</span></p></li><li><p><span>Memory 保存失败不影响成功任务结果。</span></p></li><li><p><span>同一文件经过多次 checkpoint 后恢复到任务开始前内容。</span></p></li><li><p><span>文件被外部修改时拒绝强制覆盖并返回回滚冲突。</span></p></li></ul><h2><span>验证结果</span></h2><p><span>已通过:</span></p><ul data-spread="false"><li><p><span>TypeScript 类型检查</span></p></li><li><p><span>ESLint</span></p></li><li><p><span>完整测试</span></p></li><li><p><span>项目构建</span></p></li><li><p><span>Git Diff 格式检查</span></p></li></ul><h2><span>行为变化</span></h2>
场景 | stopReason | task.status | 默认回滚
-- | -- | -- | --
正常完成 | completed | completed | 否
模型异常 | error | failed | 是
工具链异常 | error | failed | 是
验证器异常 | error | failed | 是
达到最大迭代次数 | max_iterations | failed | 是
用户取消 | aborted | cancelled | 是
Memory 保存失败 | 保持原结果 | 保持原状态 | 不改变原决策

<p><span>默认回滚行为仍受 </span><code><span>rollbackOnFailure</span></code><span> 配置控制。</span></p><pre><code></code></pre>

@ztygod
ztygod merged commit cc917b2 into main Jul 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant