fix(core,docs): window-derived output caps and compaction threshold, slower retry ladder, retry-all-but-auth (#235)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,7 @@ Task 运行期间,宿主可通过 `session.steer(input)` 排队一条用户消
|
||||
|
||||
## 自动重连
|
||||
|
||||
除 `auth` 外,LLM 侧的所有失败都会触发引擎内自动重连——`timeout`(网络超时、传输层断连、限流、5xx、瞬时的供应商额度错误)、`malformed`(流截断、JSON 解析失败),**以及 `failed`**。`failed` 也重试,尽管分类器判定它不是瞬时错误:那个判定本质是一张允许清单(已知错误码、状态码与消息措辞),所以用自己说法描述瞬时故障的网关(例如 `Upstream HTTP/2 stream failed`)会落到这一档,此前会直接终止本轮。重试一个真正的永久错误,代价是走完退避梯度后以同样的方式收场;而把瞬时错误直接中断,则毁掉这一轮。注意改的是**策略**而非**分类**:`failed` 请求在 `request_end` 与成本中心里仍然记为 `failed`,不会被改标成超时。重连时同一次 `run` 内重发原始输入,并附加 `[turn_retried]` 块携带上一次的部分输出,避免工具重复执行。默认最多重连 5 次,指数退避并设上限(基数 250ms、上限 30s:250ms、500ms、1s、2s、4s,总耐心约 7.75s——所有可重试类别共用一张时间表,向较慢的类别递增,头几步仍与传输层抖动所需的一样快);超限后该轮以 `failed` 收场。每次失败的 `request_end` 会以 `retry_in_ms` 宣告计划中的等待(与实际休眠同一公式)、以 `attempt` 标注这是本轮第几次尝试(权威序号,CLI 与 Web 的重试行直接显示它),Web App 据此实时倒计时,并提供「立即重试」(经 `Session.skipReconnectWait` 跳过剩余等待——重试计数不变)与「放弃」(普通中断;引擎的退避中中断路径结束本轮)两个内联按钮,CLI 则打印自己的 `[重试]` 行。三种可重试终态的渲染完全一致——用户看不见的重试,等于一次没有任何解释、也无从退出的卡顿。压缩请求是一次普通的 LLM 请求,默认沿用同一重连上限与退避阶梯(无效摘要也计入同一预算,见「上下文压缩」一节);压缩放弃后保留原上下文、等下一次触发再试。鉴权错误在任何重试启发式之前判定、从不重试:请求以专属终态 `auth` 收场(Session 锁定的只是模型引用,凭据在会话装载时取自当前 Project 配置),Web App 据此禁用该 Session 的输入框,直到该模型的凭据被更新(更新后自动解锁)或用户点击「重试」。工具错误从不重试——它们作为 `tool_call_output` 反馈给模型,由模型决定下一步。
|
||||
除 `auth` 外,LLM 侧的所有失败都会触发引擎内自动重连——`timeout`(传输形态的错误:网络超时、传输层断连、限流、5xx)、`malformed`(流截断、JSON 解析失败),**以及 `failed`**——凡不是明确凭据错误的供应商拒绝都在此列,普通 403 与配额/订阅错误也一样重试。终态只是分类而非策略:分类器只挑标签,用自己说法描述瞬时故障的网关(例如 `Upstream HTTP/2 stream failed`)或阶梯中途恢复的配额,都与断网一样走满同一阶梯。重试一个真正的永久错误,代价是走完退避梯度后以同样的方式收场;而把瞬时错误直接中断,则毁掉这一轮。注意改的是**策略**而非**分类**:`failed` 请求在 `request_end` 与成本中心里仍然记为 `failed`,不会被改标成超时。重连时同一次 `run` 内重发原始输入,并附加 `[turn_retried]` 块携带上一次的部分输出,避免工具重复执行。默认最多重连 5 次,指数退避并设上限(基数 2s、上限 30s:2s、4s、8s、16s、30s,总耐心约 60s——所有可重试类别共用一张时间表,按较慢的类别定基数:供应商重启、限流这类瞬时故障需要以秒计的恢复时间,旧的 250ms 基数约 7.75s 就烧完整个阶梯;每次计划等待也都达到 Web App 2s 的倒计时下限,重试始终可见);超限后该轮以 `failed` 收场。每次失败的 `request_end` 会以 `retry_in_ms` 宣告计划中的等待(与实际休眠同一公式)、以 `attempt` 标注这是本轮第几次尝试(权威序号,CLI 与 Web 的重试行直接显示它),Web App 据此实时倒计时,并提供「立即重试」(经 `Session.skipReconnectWait` 跳过剩余等待——重试计数不变)与「放弃」(普通中断;引擎的退避中中断路径结束本轮)两个内联按钮,CLI 则打印自己的 `[重试]` 行。三种可重试终态的渲染完全一致——用户看不见的重试,等于一次没有任何解释、也无从退出的卡顿。压缩请求是一次普通的 LLM 请求,默认沿用同一重连上限与退避阶梯(无效摘要也计入同一预算,见「上下文压缩」一节);压缩放弃后保留原上下文、等下一次触发再试。鉴权错误在任何重试启发式之前判定、从不重试:请求以专属终态 `auth` 收场(Session 锁定的只是模型引用,凭据在会话装载时取自当前 Project 配置),Web App 据此禁用该 Session 的输入框,直到该模型的凭据被更新(更新后自动解锁)或用户点击「重试」。工具错误从不重试——它们作为 `tool_call_output` 反馈给模型,由模型决定下一步。
|
||||
|
||||
## 上下文压缩(Compaction)
|
||||
|
||||
@@ -119,7 +119,7 @@ interface CompactionSettings {
|
||||
|
||||
| reason | 触发条件 |
|
||||
| --- | --- |
|
||||
| `context` | 上一轮 `token_usage.request.total` ≥ `maxContextLength`(默认 128000) |
|
||||
| `context` | 上一轮 `token_usage.request.total` ≥ `maxContextLength`(默认 128000;生效阈值不超过模型 `context_window` − 2048,小窗口模型——如 32k 的本地 vLLM——约在 30.7k 处压缩,而不是先撞上窗口硬限制;条目未配置 `context_window` 时按 128000 的假定默认值推导) |
|
||||
| `turns` | Session 轮数 ≥ `maxSessionTurns`(默认 -1,即不限) |
|
||||
| `manual` | 用户执行 `/compact` 或调用 `session.compact()` |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user