From 9de7dfe1cc3bd3a1b7ae96d9380fe65b1a01e412 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sat, 25 Jul 2026 12:49:29 -0700 Subject: [PATCH] feat(compression): stream the summary call on every compression path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The progress-hook streaming from #71508 only activated when a CompressionCommitFence was present (gateway session hygiene). CLI /compress and in-loop auto-compression still used the plain non-streaming summary call, where the SDK timeout is inactivity-based — a byte-trickling provider that keeps the connection alive could outlive auxiliary.compression.timeout indefinitely (the gap #69192/#41397 were built to close). Fenceless compression callers now install a no-op progress hook, which routes their summary call onto the same streamed path: the configured timeout acts on inactivity (slow models finish instead of being cut off mid-generation), and a degenerate trickle stream is bounded by the streamed total ceiling (max(600s, 4× the task timeout)) instead of running forever. No config knob needed — the ceiling machinery ships with the streaming layer and applies uniformly. Supersedes the opt-in wall-clock deadline approaches in PR #69192 (@JabberELF) and PR #41397: same guarantee (bounded total compression wall time even while bytes move) without a daemonized watchdog thread or a new config surface, and without punishing slow-but-healthy models. --- agent/conversation_compression.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/agent/conversation_compression.py b/agent/conversation_compression.py index 78d4a146e762..20be139c3b01 100644 --- a/agent/conversation_compression.py +++ b/agent/conversation_compression.py @@ -1767,8 +1767,20 @@ def compress_context( # when it is actually silent, not merely thorough. The hook is # thread-local and the compress call is synchronous on this thread, # so it cannot leak into unrelated auxiliary calls. + # + # Fenceless callers (CLI /compress, in-loop auto-compress) install a + # no-op hook: nobody polls their progress, but an ACTIVE hook is what + # switches the summary call onto the streamed path — giving every + # compression path the same two guarantees: the configured timeout + # acts on inactivity (slow models finish), and a byte-trickling + # provider that keeps the connection alive forever is cut off at the + # streamed total ceiling (see _aux_stream_total_ceiling) instead of + # outliving the SDK's inactivity timeout indefinitely. from agent.auxiliary_client import aux_progress_hook - _progress_hook = commit_fence.touch_progress if commit_fence is not None else None + _progress_hook = ( + commit_fence.touch_progress if commit_fence is not None + else (lambda: None) + ) with aux_progress_hook(_progress_hook): compressed = compress_fn(messages, **compress_kwargs) except BaseException as _compress_exc: