Skip to content

fix(compression): protect the summary call from mid-flight interrupts (#23975) - #49928

Merged
teknium1 merged 1 commit into
mainfrom
fix/compression-interrupt-protection
Jun 21, 2026
Merged

fix(compression): protect the summary call from mid-flight interrupts (#23975)#49928
teknium1 merged 1 commit into
mainfrom
fix/compression-interrupt-protection

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Context compression's summary call is now protected from a mid-flight gateway interrupt (#23975). Previously, an incoming user message while the agent was busy could abort the in-flight summary, causing compression to fall back to a degraded static "summary unavailable" marker — losing the real handoff.

Root cause: the Codex Responses auxiliary stream's cancellation check polls the thread interrupt flag and raised InterruptedError unconditionally (agent/auxiliary_client.py). Compression is atomic — it must either complete the summary or cleanly defer — but the interrupt reached the in-flight call and triggered the fallback path.

Changes

  • agent/auxiliary_client.py: add a thread-local aux_interrupt_protection() context manager + _aux_interrupt_protected() helper. The Codex stream's cancellation check now skips the interrupt poll when protection is active (is_interrupted() and not _aux_interrupt_protected()). Timeouts still fire (a hung call must die) and all other aux tasks (vision, web_extract, title_generation, …) stay interruptible.
  • agent/context_compressor.py: wrap the summary call_llm in aux_interrupt_protection(). Re-entrant, so the main-model retry recursion is safe.

Behavior

Aux call Before After
Compression summary + interrupt aborted → fallback marker completes atomically
Compression summary + timeout times out times out (unchanged)
vision / web_extract / title_gen + interrupt interruptible interruptible (unchanged)

Verified the compressor wiring test fails without the with wrap and passes with it. 107 passing across the compressor + interrupt-protection suites; 375 passing on the auxiliary-client surface.

Credit

Salvaged the thread-local interrupt-protection approach from @konsisumer's PR #24001. Authorship preserved via co-author trailer; that PR closes pointing here.

Infographic

protect-compression-from-interrupts

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: fix/compression-interrupt-protection vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11282 on HEAD, 11280 on base (🆕 +2)

🆕 New issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:2984: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

✅ Fixed issues (1):

Rule Count
invalid-assignment 1
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

Unchanged: 5914 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround labels Jun 21, 2026
Context compression is atomic, but a gateway interrupt (an incoming user
message while the agent is busy) could abort the in-flight summary call.
The Codex Responses aux stream polls the thread interrupt flag and raised
InterruptedError unconditionally — so compression fell back to a degraded
static 'summary unavailable' marker, losing the real handoff (#23975).

Add a thread-local interrupt-protection flag (aux_interrupt_protection
context manager) in auxiliary_client; the Codex stream's cancellation
check honors it. The compressor wraps its summary call_llm in the context
manager. Timeouts still fire (a hung call must die) and all other aux
tasks (vision, web_extract, title_generation, …) stay interruptible.
Re-entrant, so the main-model retry recursion is safe.

Co-authored-by: konsisumer <der@konsi.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants