fix(compression): separate provider-exact vs projected token state - #23934
Closed
heathley wants to merge 1 commit into
Closed
fix(compression): separate provider-exact vs projected token state#23934heathley wants to merge 1 commit into
heathley wants to merge 1 commit into
Conversation
heathley
force-pushed
the
fix/context-token-state-23902
branch
from
May 18, 2026 08:18
2c41b43 to
78399e9
Compare
1 task
Contributor
|
Automated hermes-sweeper review: this compression-token-state bug is already fixed on current
The cross-referenced competing fix discussion on #28057 identified the same post-compression rough-estimate failure mode; current main now addresses it without reusing the rough estimate as provider usage. |
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
Fixes premature context compression caused by conflating two different token states in
last_prompt_tokens.Today Hermes writes two semantically different values into the same field:
prompt_tokensafterupdate_from_response()_compress_context()The compression decision later reads
last_prompt_tokensas if it were provider-exact in both cases, which can trigger compression early when the post-compression estimate is higher than the last API-reported value.Resolves #23902.
Root cause
last_prompt_tokenswas carrying both:That worked poorly after compression, because
_compress_context()overwrote the exact value with an estimate, and the next compression check treated that estimate as authoritative.What changed
ContextCompressor state split
Separated token tracking into:
last_provider_prompt_tokensprojected_prompt_tokensprojected_prompt_tokens_source_transcript_mutated_since_apiFor backward compatibility,
last_prompt_tokensnow mirrorsprojected_prompt_tokens, so existing gateway/CLI consumers still read a current projected context value.Exact vs projected request pressure
Added
get_current_request_pressure(messages, system_prompt, tools).Behavior:
This preserves the post-#14695 requirement that tool schema tokens remain part of request pressure estimation.
Dirty-state invalidation
Added coarse invalidation when local transcript state changes, including:
This avoids per-message delta accounting while still preventing stale provider-exact values from being reused after local mutations.
Post-compression behavior
_compress_context()no longer overwrites provider-exact token state.Instead it updates projected pressure as an estimate with source
estimated_post_compression, leaving the last provider-exact value intact for diagnostics while ensuring the next compression check doesnot mistake stale exact usage for current request pressure.
Why this shape
This intentionally does not revert #14695 / #18265 behavior.
Tool schemas are still included in estimates, and the fix avoids reintroducing the “compression triggers too late because tools were excluded” bug.
It also does not add per-message delta accounting or low-level append hooks. The implementation uses coarse invalidation plus fresh full-request estimation when the transcript is dirty.
Tests
Added/updated regression coverage for:
update_from_response()setting provider-exact + projected state consistentlylast_prompt_tokens_compress_context()Validation
Passed:
pytest tests/agent/test_context_compressor.py tests/agent/test_context_engine.py tests/run_agent/test_projected_token_state.py -qpython3 -m py_compile agent/context_compressor.py run_agent.py tests/run_agent/test_projected_token_state.pyRelated