fix(agent): protect context compression from session interrupts - #24001
fix(agent): protect context compression from session interrupts#24001konsisumer wants to merge 1 commit into
Conversation
Compression is infrastructure that preserves conversation continuity. The Codex auxiliary Responses adapter polled `tools.interrupt.is_interrupted()` during streaming, so a new Telegram message or watch-pattern notification arriving while a summary was running would raise InterruptedError and force Hermes to insert a fallback context marker — silently dropping the middle of the session from model context. Add a thread-local protection flag (`_AuxInterruptProtection`) that masks the interrupt check inside `_CodexCompletionsAdapter._check_cancelled`, and enable it for `task="compression"` calls in `call_llm`. Timeouts and the explicit close-on-timeout closer are unchanged, so a hung Codex stream still cancels via the configured `auxiliary.compression.timeout`. The pending gateway message stays queued in `_pending_messages` and is served as soon as compression returns, preserving the existing UX without losing the summary. Fixes NousResearch#23975
af4443c to
ac26e04
Compare
|
Thanks for the additional reproductions. I re-ran the scoped regression checks on this branch: The new Telegram follow-up repro and the Windows Desktop confirmation hit the same interrupt path this PR is targeting: compression is already in flight, a session interrupt lands, and Hermes falls back to the marker. This branch keeps compression runs alive for The Azure |
Context compression should not abort when a new gateway message arrives mid-stream.
What changed and why
_AuxInterruptProtection) inagent/auxiliary_client.pythat masks_CodexCompletionsAdapter._check_cancelled'sis_interrupted()poll while it is active.call_llm(task="compression", ...)now wraps the inner implementation with that protection, so a new Telegram message or watch-pattern notification arriving while the summary is streaming no longer raisesInterruptedErrorand forces Hermes to insert a fallback context marker.auxiliary.compression.timeout. The protection is scoped to the auxiliary call site only; other auxiliary tasks (vision,web_extract, etc.) continue to honor interrupts so users can still cancel long-running web extractions or vision lookups._pending_messagesand is served as soon as compression returns, so the user-facing UX is unchanged except that the next turn now sees a real summary instead of the fallback marker.How to test
pytest tests/agent/test_auxiliary_client.py::TestCodexAuxiliaryCompressionInterruptProtection -qcovers: baseline interrupt aborts the non-compression call, protection masks the interrupt during streaming, timeouts still fire under protection, the flag is thread-local and nests correctly, andcall_llmenables protection only fortask="compression".pytest tests/agent/test_context_compressor.py tests/agent/test_compress_focus.py tests/agent/test_context_compressor_summary_continuity.py tests/agent/test_auxiliary_main_first.py -qto confirm no regressions in the compression flow.What platforms tested on
Fixes #23975