fix(agent): persist compression backoff across resume (#54465) - #54525
fix(agent): persist compression backoff across resume (#54465)#54525rodboev wants to merge 7 commits into
Conversation
(cherry picked from commit 667a08e35f94eae8c339b9d46e3ac715bebfee62)
|
Salvaged and merged via #55499 (merge commit 58d8e25 on main). Your six commits were cherry-picked unchanged, so your authorship is preserved per-commit in main's history. Thank you for the thorough fix and the excellent repro/evidence in #54465 — the cross-process restart wedge was exactly as you diagnosed. I added one follow-up commit on top hardening the lock-lease refresher: its loop previously treated any falsy refresh as a permanent stop, which conflated genuine lost-ownership with a one-off transient DB error — a single blip could silently reintroduce the TTL-expiry wedge. It now tolerates consecutive failures for at most one lease's worth of time (cap = int(ttl / refresh_interval), floor 1), so the give-up window is genuinely bounded by the TTL, plus debug logging on the two previously-silent cooldown except arms and 5 mutation-checked regression tests. Closing this in favor of the merged #55499. Thanks again! |
Summary
Resumed oversized sessions can currently re-enter automatic preflight compression immediately after a timeout because the cooldown lives only on the in-memory
ContextCompressor. A restart builds a fresh compressor, so the next turn can hit the same preflight compression path before any assistant response.This PR persists same-session compression failure state on the session row, hydrates that state into resumed compressors, rebinds reset-only session switches onto the active session row, suppresses only same-session automatic preflight while the cooldown is still live, and keeps the current compression lock lease valid while the owning compression is still in flight. Manual
/compresskeeps its existing bypass behavior, and unrelated session IDs stay unaffected.Related scope note: #53171, #49905, and #41397 already cover the timeout-retry and wall-clock slices from this issue, so this PR stays on the remaining durable session-state piece.
Changes
hermes_state.py: add session-scoped compression failure columns andSessionDBhelpers for record/read/clear plus owner-checked lock lease refresh.agent/context_compressor.py: bind resumed session state into the built-in compressor, write through same-session cooldown changes, and preserve manual force bypass while keeping restart-persistent cooldowns intact.agent/agent_init.py,run_agent.py: bind fresh or reset-only session switches onto the active session row so later cooldown reads and writes stay on the right session after/new,/resume, or/branch.agent/turn_context.py: check same-session persisted cooldown before emitting the preflight compression status and entering the automatic preflight loop.agent/conversation_compression.py: keep the current holder's lock lease alive until release, and release it on the remaining early exception exits after refresh starts.tests/test_hermes_state.py,tests/agent/test_context_compressor.py,tests/agent/test_context_engine_host_contract.py,tests/agent/test_turn_context.py,tests/agent/test_compression_concurrent_fork.py: add focused regression coverage for persisted cooldown behavior, session isolation, reset-only session rebinding, owner-only lease refresh, and negative-space cases.Validation
/compressduring an active cooldown/new,/resume, or/branchafter a session-specific cooldownTest plan
tests/agent/test_context_engine_host_contract.py tests/test_hermes_state.py tests/agent/test_context_compressor.py tests/agent/test_turn_context.py tests/agent/test_compression_concurrent_fork.py -v --timeout=0— 453 passedUpstream
This PR intentionally leaves #54465 open because the timeout-retry and wall-clock slices are tracked separately in #53171, #49905, and #41397.