Skip to content

fix: #94391 将 compaction aggregate timeout 从硬编码 60s 改为读取 compaction.timeoutSeconds 配置#94429

Closed
wings1029 wants to merge 1 commit into
openclaw:mainfrom
wings1029:fix/issue-94391-compaction-aggregate-timeout
Closed

fix: #94391 将 compaction aggregate timeout 从硬编码 60s 改为读取 compaction.timeoutSeconds 配置#94429
wings1029 wants to merge 1 commit into
openclaw:mainfrom
wings1029:fix/issue-94391-compaction-aggregate-timeout

Conversation

@wings1029

Copy link
Copy Markdown
Contributor

变更说明

COMPACTION_RETRY_AGGREGATE_TIMEOUT_MS 硬编码常量(60000ms)替换为从 agents.defaults.compaction.timeoutSeconds 配置读取的 compactionTimeoutMs(默认 180000ms)。

根因

在 ~200K token 的大 session 中,compaction 模型调用(anthropic/claude-sonnet-4-6)需要 143-187s 完成,但硬编码的 60s aggregate timeout 在模型调用完成前就丢弃了有效结果:

后果 详情
结果丢弃 compaction 完成(aborted=False)但被 60s 标记 incomplete
重试风暴 每轮失败触发新的 compaction 重试(观察到连续 6 次失败)
API 费用浪费 每次失败都白烧一次完整的 ~200K token provider 调用
静默失败 用户无任何错误提示,session 卡在 overflow 上限无法自动恢复

修复方案

将 aggregate timeout 关联到已有的 agents.defaults.compaction.timeoutSeconds 配置项:

  • 默认值:180s(原 60s),覆盖正常 compaction 调用的 143-187s 范围
  • 已调高配置的用户:自动获得修复,无需额外配置
  • 不改配置面:不加新配置项,复用已有字段

对比竞品 PR #94403

#94403 只是把硬编码从 60000 改成 300000,仍然硬编码。本 PR 将其接入已有配置体系,用户可以自行调整。

关联 Issue

Closes #94391

变更类型

  • Bug fix
  • New feature
  • Documentation
  • Code refactor
  • Test update
  • Dependency update

风险等级

low — 改动范围极小(删除 2 行、修改 2 行),复用已有的 compactionTimeoutMs 变量和 resolveCompactionTimeoutMs() 配置解析逻辑。

测试情况

  • compaction-retry-aggregate-timeout.test.ts:16/16 通过
  • 改动不涉及函数签名变更,mock 层无需适配

🤖 Generated with Claude Code

…action.timeoutSeconds 配置

将硬编码的 COMPACTION_RETRY_AGGREGATE_TIMEOUT_MS (60000ms) 替换为从
agents.defaults.compaction.timeoutSeconds 配置读取的 compactionTimeoutMs
(默认 180000ms)。

根因: 在 ~200K token 的大 session 中, compaction 模型调用需要 143-187s 完成,
但硬编码的 60s aggregate timeout 在调用完成前就丢弃了结果, 导致:
- 有效 compaction 结果被丢弃
- 每次失败都触发新的 compaction 重试 (重试风暴)
- 每次失败都白烧完整的 provider API 调用费用
- 用户无感知 (失败是静默的)

此修复将 aggregate timeout 关联到已有的
agents.defaults.compaction.timeoutSeconds 配置项 (默认 180s),
使已调高此配置的用户自动获得修复。

Co-Authored-By: Claude <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels Jun 18, 2026
@wings1029

Copy link
Copy Markdown
Contributor Author

🔍 Real behavior proof

1. 架构一致性证明

compactionTimeoutMsrunEmbeddedAttempt 中已被用于两个 compaction 相关路径,本 PR 将其复用到第三个路径(aggregate timeout),保持同一值的一致性:

行号 用途 值来源
attempt.ts:2095 const compactionTimeoutMs = resolveCompactionTimeoutMs(params.config) cfg.agents.defaults.compaction.timeoutSeconds → 默认 180s
attempt.ts:2098 resolveEmbeddedAttemptSessionWriteLockOptions({ compactionTimeoutMs }) — 锁持有时长上限 同一变量
attempt.ts:3758 scheduleAbortTimer(compactionTimeoutMs, "compaction-grace") — compaction 优雅超时 同一变量
attempt.ts:4938 (本 PR) aggregateTimeoutMs: compactionTimeoutMs — compaction 等待超时 同一变量

逻辑: 如果 180s 对 compaction 模型调用足够(内层 safety timeout),对外层等待也应该足够 — compaction 在同一时间段内要么完成、要么被内层超时杀死。

2. 配置解析链路已验证

resolveCompactionTimeoutMs() 的测试覆盖(compaction-safety-timeout.test.ts):

✓ returns default when timeoutSeconds is not set
✓ converts timeoutSeconds to milliseconds  
✓ preserves explicit timeoutSeconds above 600
✓ floors float timeoutSeconds (120.7 → 120)
✓ falls back for zero timeoutSeconds
✓ falls back for negative timeoutSeconds
✓ falls back for NaN timeoutSeconds
✓ falls back for Infinity timeoutSeconds

3. Aggregate timeout 函数本身已验证

compaction-retry-aggregate-timeout.test.ts — 16/16 通过:

✓ times out and fires callback when compaction retry never resolves
✓ keeps waiting while compaction remains in flight
✓ times out after an idle timeout window  
✓ does not time out when compaction retry resolves
✓ caps aggregate timeout before scheduling
✓ propagates immediate waitForCompactionRetry failures
✓ handles waitForCompactionRetry rejection after timeout wins
✓ propagates abort errors from abortable and clears timer

4. 行为变更分析

场景 修复前 (60s 硬编码) 修复后 (读配置, 默认 180s)
小 session (~50K token) ✅ compaction < 60s, 正常 ✅ 不变
大 session (~200K token) ❌ 60s 超时丢弃 143-187s 结果 → 重试风暴 ✅ 180s 覆盖 143-187s 调用
用户设 timeoutSeconds: 300 ❌ 仍然 60s 超时(硬编码忽略配置) ✅ 300s aggregate timeout
超短 compaction (< 60s) ✅ 无变化

5. Issue 证据关联

Issue #94391 包含完整 trajectory 证据(session 91f28c2c),证明:

  • compaction 模型调用完成时间:143s、174s、187s(均在 60s 后、180s 内)
  • 调用完成标志:aborted=False, externalAbort=False, timedOut=False
  • 60s 硬编码在每次调用完成前 ~83-127s 就标记 incomplete

本 PR 将 aggregate timeout 从 60s → 180s(默认),使这些已完成调用有机会被正常消费。

@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix: #94391 将 compaction aggregate timeout 从硬编码 60s 改为读取 compaction.timeoutSeconds 配置 This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 18, 2026
@wings1029

Copy link
Copy Markdown
Contributor Author

Superseded by #94421 which fixes the root cause (isCompactionStillInFlight signal during active retry streaming) rather than changing the timeout value. #94421's approach is superior: it preserves the 60s idle guard while correctly treating active model streaming as work-in-progress, so valid long-running retries are not abandoned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

1 participant