fix(compression): warn the user when compression is blocked but context keeps growing - #69857
Merged
Conversation
Contributor
૮ >ﻌ< ა ci reviewran on 7bf9005 ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job1 visual diff. inline evidence upload failed. Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso) |
Collaborator
Related: #62625 already proposes blocked-compression warning plumbing for #62708. This patch has additional current-head follow-ups; both solve the same user-visible warning goal, so maintainers should choose or consolidate rather than treat either as a duplicate. |
teknium1
force-pushed
the
salvage/62625-warn-blocked
branch
from
July 23, 2026 14:59
7a73af2 to
b941729
Compare
…ssion is blocked Previously, when a session crossed the compression threshold but compression was skipped (summary-LLM cooldown, #11529, or anti-thrashing, #40803), the model kept accumulating context until it hit the hard provider token limit and silently stopped answering — with no signal to the user about why. Changes: - context_compressor.should_compress_info() returns a (should_compress, reason) tuple. reason is 'cooldown:<seconds>' or 'ineffective' when compression is needed but blocked. should_compress() keeps its bool contract so existing callers (conversation_loop.py) and regression #29335 are unaffected. - turn_context.build_turn_context() emits a deduped _emit_warning when the context is over threshold but compression is blocked, advising /new or /compress. Dedup keys on the block *kind* (cooldown/ineffective), not the ticking countdown, so a cooldown doesn't re-fire the warning every turn. - Adds tests/agent/test_turn_context_overflow_warning.py covering the tuple shape, both block kinds, dedup, and re-fire-after-clear.
- ContextEngine.should_compress_info() default impl so plugin engines (e.g. _StubEngine) don't raise AttributeError at the call site. - Centralise warning/reset in AIAgent._warn_context_overflow_blocked / _clear_context_overflow_warn so turn-context and conversation-loop guards share identical dedup logic and reset on the real compression boundary. - Cover conversation_loop.py pre-API (~L1007) and loop-compaction (~L4774) guards, not just the turn-context preflight. - _FakeAgent mirrors the two helpers; test suite green (219 passed). Fixes #62708
…ath + noise-filter survival pins Follow-up fixes for the #62625 salvage: - Dedup-reset gap (sweeper review): when the block clears while the context is STILL over threshold, execution enters the compression branch — the PR's 'else' reset never ran, so the warning stayed suppressed forever after the first block. _clear_context_overflow_warn() now fires on every automatic compression path: turn-context preflight, conversation_loop pre-API gate, and the post-tool loop-compaction gate. - should_compress_info on current main: main refactored should_compress into _automatic_compression_blocked()/_locally(); the tuple variant now derives its reason from the same in-memory state via _compression_block_reason(), keeping cooldown:<s>/ineffective shapes. - ContextEngine.should_compress_info ABC default now actually returns (should_compress(tokens), None) — the PR's default had a docstring but no return (returned None, would crash tuple-unpacking call sites). - Below-threshold guard: the turn-context persisted-cooldown branch and the conversation_loop pre-API cooldown branch no longer warn when the estimate is under threshold (should_compress_info returns a None reason; the preflight pre-check is not a threshold guarantee). The pre-API guard also honors compression.max_attempts instead of a hardcoded 3, and no longer fabricates a cooldown reason. - Noise-filter survival (#69550 composition): warning text is now a template constant (CONTEXT_OVERFLOW_BLOCKED_WARNING_TEMPLATE) marked FAILURE-CLASS, pinned un-swallowed in VISIBLE_COMPRESSION_MESSAGES and in new tests that execute the real _TELEGRAM_NOISY_STATUS_RE + _prepare_gateway_status_message. - Contributor mapping for stanislav@local -> sl4m3.
…t doubles The dedup-reset calls assumed a full AIAgent; gateway/loop test doubles built via object.__new__ lack _clear_context_overflow_warn and crashed in build_turn_context (caught by test_api_content_sidecar on CI slice 3). getattr-guard all four call sites per the established test-double pitfall pattern (AGENTS.md #17).
…ight Two composition fixes vs the merged #69865 engine-preflight arm: 1. should_compress_info probe getattr-guarded — minimal compressor doubles (SimpleNamespace) and plugin engines lack it; absence means no block reason, no warning. 2. Engine maintenance hook stays un-consulted when any skip-branch fired (failure cooldown / deferred estimate / codex-native) — restoring the #20316 contract the warn-chain restructure broke.
teknium1
force-pushed
the
salvage/62625-warn-blocked
branch
from
July 23, 2026 15:34
f6317d6 to
7bf9005
Compare
This was referenced Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a session's context crosses the compression threshold but automatic compression is blocked (summary-LLM cooldown or the anti-thrash breaker), the user now gets a visible, deduped warning telling them to run
/newor/compress— instead of the session silently growing until it dies at the hard provider token limit. Root cause:should_compress()returns a bareFalseon the veto paths and every guard onlylogger.info'd the skip, so the failure mode was invisible from chat (the warning half of #62708).Changes
agent/context_compressor.py:should_compress_info()returns(bool, reason)(cooldown:<s>/ineffective); on current main's refactored gate it derives the reason from the same in-memory state via a new_compression_block_reason()helper.should_compress()keeps its bool contract.agent/context_engine.py: backward-compatible ABC defaultshould_compress_info()→(should_compress(tokens), None)so plugin engines never raiseAttributeError(follow-up: the PR's default had no return statement — it returnedNoneand would have crashed tuple-unpacking call sites).run_agent.py: centralizedAIAgent._warn_context_overflow_blocked()/_clear_context_overflow_warn()— dedup keys on the block kind so a ticking cooldown doesn't re-fire every turn.agent/turn_context.py+agent/conversation_loop.py: all three automatic-compression guards (preflight, pre-API, post-tool loop compaction) warn when blocked-over-threshold, and every compression path resets the dedup — closing the sweeper-review gap where the block clearing while still over threshold entered the compression branch and skipped theelsereset, suppressing the warning forever after.compression.max_attemptsinstead of a hardcoded 3.agent/conversation_compression.py: warning text is a template constant (CONTEXT_OVERFLOW_BLOCKED_WARNING_TEMPLATE) marked FAILURE-CLASS — deliberately not inROUTINE_COMPRESSION_STATUS_SAMPLESor the noise regex; wording composes with fix(compression): floor the threshold recommendation at the effective small-context minimum #69332's recomputed-trigger notice (no contradictory threshold advice, just/new//compress).tests/: PR's suite (tuple shape, both block kinds, dedup, re-fire) + follow-up tests: dedup-reset-while-still-over-threshold, below-threshold cooldown no-warn, plugin-engine ABC default, and noise-filter survival tests that execute the real_TELEGRAM_NOISY_STATUS_RE(fix(gateway): suppress routine pre-API compression chatter on chat platforms #69550-widened) and_prepare_gateway_status_messageend-to-end; both reason shapes pinned un-swallowed inVISIBLE_COMPRESSION_MESSAGES.Validation
False,logger.infoonly — user sees nothing until token-limit death/new//compressguidanceAttributeError(contract only requiredshould_compress)(should_compress(tokens), None)Targeted tests: 630 passed (overflow-warning suite ×19, turn-context ×18, telegram noise filter ×587, plugin engine init ×6);
-k 'blocked or overflow_warn or should_compress_info'sweep: 532 passed, 0 failed; sibling compressor suites (rotation state, idle compaction, context compressor, feasibility): 246 passed.Credit
Salvaged from #62625 by @sl4m3. Addresses the warning half of #62708.
Infographic