- 首页
- Documentation
- 会话
- 非压缩自动重试策略
非压缩自动重试策略
本文档描述了 AgentSession 中标准的 API 错误重试路径。
本文明确排除了通过自动压缩进行的上下文溢出恢复。溢出由压缩逻辑处理,相关文档见 compaction.md。
../src/session/agent-session.ts../src/config/settings-schema.ts../src/modes/controllers/event-controller.ts../src/modes/rpc/rpc-mode.ts../src/modes/rpc/rpc-client.ts../src/modes/rpc/rpc-types.ts
重试与压缩的边界划分
Section titled “重试与压缩的边界划分”重试和压缩从相同的 agent_end 路径进行检查,但它们被有意分开处理:
agent_end检查最后一条助手消息。#isRetryableError(...)首先执行。- 如果发起了重试,则该轮跳过压缩检查。
- 上下文溢出错误被硬性排除在重试分类之外(
isContextOverflow(...)会短路重试判断)。 - 因此溢出会落入
#checkCompaction(...)而非标准重试。
总结:过载/限流/服务端/网络类故障使用本重试策略;上下文窗口溢出使用压缩恢复。
#isRetryableError(...) 需要满足以下所有条件:
- 助手
stopReason === "error" errorMessage存在- 消息不是上下文溢出
errorMessage匹配#isRetryableErrorMessage(...)
当前可重试的模式集(基于正则表达式):
- overloaded
- rate limit / usage limit / too many requests
- HTTP 类服务端状态码:429、500、502、503、504
- service unavailable / server error / internal error
- connection error / fetch failed
retry delay相关措辞
这是基于字符串模式的分类,而非类型化的提供商错误代码。
重试生命周期和状态转换
Section titled “重试生命周期和状态转换”重试使用的会话状态:
#retryAttempt: number(0表示空闲)#retryPromise: Promise<void> | undefined(跟踪进行中的重试生命周期)#retryResolve: (() => void) | undefined(解析#retryPromise)#retryAbortController: AbortController | undefined(取消退避等待)
流程(#handleRetryableError):
- 读取
retry设置组。 - 如果
retry.enabled === false,立即停止(返回false,不启动重试)。 - 递增
#retryAttempt。 - 首次尝试时创建
#retryPromise(链中的第一次尝试)。 - 如果尝试次数超过
retry.maxRetries,发出最终失败事件并停止。 - 计算延迟:
retry.baseDelayMs * 2^(attempt-1)。 - 对于使用量限制错误,解析重试提示并调用认证存储(
markUsageLimitReached(...));如果提供商/模型切换成功,则强制延迟为0。 - 发出
auto_retry_start。 - 从代理运行时状态中移除尾部的助手错误消息(在持久化的会话历史中保留)。
- 支持中止的等待。
- 唤醒后,通过
setTimeout(..., 0)调度agent.continue()。
重试计数器的重置条件
Section titled “重试计数器的重置条件”#retryAttempt 在以下情况下重置为 0:
- 重试开始后首次成功的非错误、非中止助手消息(发出
auto_retry_end { success: true }) - 退避等待期间重试被取消
- 超过最大重试次数路径
#retryPromise 在重试链结束时(成功、取消或超过最大次数)通过 #resolveRetry() 解析/清除。
退避和最大尝试次数语义
Section titled “退避和最大尝试次数语义”设置:
retry.enabled(默认true)retry.maxRetries(默认3)retry.baseDelayMs(默认2000)
尝试次数编号:
- 尝试计数器在最大值检查之前递增
- 开始事件使用当前尝试次数(从 1 开始)
- 超过最大次数的结束事件报告
attempt: this.#retryAttempt - 1(最后尝试的重试次数)
使用默认设置的退避序列:
- 第 1 次尝试:2000 毫秒
- 第 2 次尝试:4000 毫秒
- 第 3 次尝试:8000 毫秒
延迟覆盖输入仅在使用量限制处理路径中使用,且仅用于影响认证存储的模型/账户切换决策。在主要的非压缩重试路径中,退避保持本地指数延迟,除非切换成功(delayMs = 0)。
显式重试中止
Section titled “显式重试中止”abortRetry():
- 中止
#retryAbortController(如果存在) - 解析重试 promise(
#resolveRetry())以解除等待者的阻塞
如果中止发生在等待期间,捕获路径会发出:
auto_retry_end { success: false, finalError: "Retry cancelled" }- 重置尝试次数/控制器
全局操作中止交互
Section titled “全局操作中止交互”abort() 在中止活动的代理流之前调用 abortRetry()。这保证了当用户发出通用中止时,重试退避会被取消。
TUI 交互
Section titled “TUI 交互”收到 auto_retry_start 时,EventController:
- 将
Esc处理器切换为session.abortRetry() - 渲染加载文本:
Retrying (attempt/maxAttempts) in Ns… (esc to cancel)
收到 auto_retry_end 时,恢复之前的 Esc 处理器并清除加载状态。
流式处理和提示完成行为
Section titled “流式处理和提示完成行为”prompt() 最终在 agent.prompt(...) 返回后等待 #waitForRetry()。
效果:
- 一个 prompt 调用在任何已启动的重试链完成(成功/失败/取消)之前不会完全解析
- 重试生命周期是一个逻辑提示执行边界的一部分
这防止了调用者过早地将正在重试的轮次视为已完成。
控制:设置和 RPC
Section titled “控制:设置和 RPC”在设置模式的 retry 组中定义:
retry.enabledretry.maxRetriesretry.baseDelayMs
会话中的编程式切换:
setAutoRetryEnabled(enabled)写入retry.enabledautoRetryEnabled读取retry.enabledisRetrying报告重试生命周期 promise 是否处于活动状态
RPC 控制
Section titled “RPC 控制”RPC 命令接口:
set_auto_retry→session.setAutoRetryEnabled(command.enabled)abort_retry→session.abortRetry()
客户端辅助方法:
RpcClient.setAutoRetry(enabled)RpcClient.abortRetry()
两个命令都返回成功响应;重试进度/失败详情通过流式会话事件传递,而非命令响应负载。
事件发送和失败呈现
Section titled “事件发送和失败呈现”会话级重试事件:
auto_retry_start { attempt, maxAttempts, delayMs, errorMessage }auto_retry_end { success, attempt, finalError? }
传播:
- 通过
AgentSession.subscribe(...)发出 - 作为扩展事件转发到扩展运行器
- 在 RPC 模式下,直接作为 JSON 事件对象转发(
session.subscribe(event => output(event))) - 在 TUI 中,由
EventController消费用于加载/错误 UI
最终失败呈现:
- 超过最大次数或取消时,
auto_retry_end.success === false - TUI 显示:
Retry failed after N attempts: <finalError> - 扩展/钩子接收具有相同字段的
auto_retry_end - RPC 消费者在 stdout 流上接收相同的事件对象
永久停止条件
Section titled “永久停止条件”当发生以下任一情况时,重试停止且不会自动继续:
retry.enabled为 false- 错误未被分类为可重试
- 错误为上下文溢出(委托给压缩路径)
- 超过最大重试次数
- 用户取消重试(在重试加载期间按
abort_retry或Esc) - 全局中止(
abort)先取消重试
在计数器重置后,未来的可重试错误仍可启动新的重试链。
操作注意事项
Section titled “操作注意事项”- 分类基于正则文本匹配;此处不使用提供商特定的结构化错误。
- 重试会从运行时上下文中剥离失败的助手错误,然后再继续,但会话历史仍保留该错误条目。
RpcSessionState目前暴露了autoCompactionEnabled但没有autoRetryEnabled字段;RPC 调用者必须自行跟踪切换状态或通过其他 API 查询设置。