-
Notifications
You must be signed in to change notification settings - Fork 53.2k
fix(agent): make the compression retry cap config-driven (compression.max_attempts) #64010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Kenmege
wants to merge
2
commits into
NousResearch:main
from
Kenmege:fix/config-driven-compression-attempts
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| """compression.max_attempts — config-driven compression retry cap. | ||
|
|
||
| The conversation loop's compression retry cap was hardcoded to 3, stranding | ||
| sessions that legitimately need more rounds — e.g. a restart history reload | ||
| whose incompressible tool schemas keep the request estimate above the | ||
| threshold while the messages themselves compress fine (the #62605 failure | ||
| class). The cap is now parsed from ``compression.max_attempts`` in | ||
| ``agent_init`` and read by the loop via | ||
| ``getattr(agent, "max_compression_attempts", 3)``. | ||
|
|
||
| These tests pin the parse/validate/attach seam: default preserved, custom | ||
| value honored, floor and ceiling enforced, garbage tolerated. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import contextlib | ||
| import io | ||
| from pathlib import Path | ||
|
|
||
| from hermes_state import SessionDB | ||
| from run_agent import AIAgent | ||
|
|
||
|
|
||
| def _config(max_attempts=None) -> dict: | ||
| compression = { | ||
| "enabled": True, | ||
| "threshold": 0.50, | ||
| "target_ratio": 0.20, | ||
| "protect_first_n": 3, | ||
| "protect_last_n": 20, | ||
| } | ||
| if max_attempts is not None: | ||
| compression["max_attempts"] = max_attempts | ||
| return { | ||
| "compression": compression, | ||
| "prompt_caching": {"cache_ttl": "5m"}, | ||
| "sessions": {}, | ||
| "bedrock": {}, | ||
| } | ||
|
|
||
|
|
||
| def _make_agent(monkeypatch, tmp_path: Path, *, max_attempts=None): | ||
| from hermes_cli import config as config_mod | ||
|
|
||
| monkeypatch.setattr( | ||
| config_mod, "load_config", lambda: _config(max_attempts=max_attempts) | ||
| ) | ||
| db = SessionDB(db_path=tmp_path / "state.db") | ||
| with contextlib.redirect_stdout(io.StringIO()): | ||
| agent = AIAgent( | ||
| base_url="https://chatgpt.com/backend-api/codex", | ||
| api_key="test-key", | ||
| provider="openai-codex", | ||
| model="gpt-5.5", | ||
| enabled_toolsets=[], | ||
| disabled_toolsets=[], | ||
| quiet_mode=True, | ||
| skip_memory=True, | ||
| session_db=db, | ||
| session_id="max-attempts-test", | ||
| ) | ||
| return agent | ||
|
|
||
|
|
||
| class TestCompressionMaxAttemptsConfig: | ||
| def test_default_is_three_when_unset(self, monkeypatch, tmp_path): | ||
| agent = _make_agent(monkeypatch, tmp_path) | ||
| assert agent.max_compression_attempts == 3 | ||
|
|
||
| def test_custom_value_is_honored(self, monkeypatch, tmp_path): | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts=6) | ||
| assert agent.max_compression_attempts == 6 | ||
|
|
||
| def test_hard_capped_at_ten(self, monkeypatch, tmp_path): | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts=25) | ||
| assert agent.max_compression_attempts == 10 | ||
|
|
||
| def test_zero_and_negative_fall_back_to_default(self, monkeypatch, tmp_path): | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts=0) | ||
| assert agent.max_compression_attempts == 3 | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts=-2) | ||
| assert agent.max_compression_attempts == 3 | ||
|
|
||
| def test_non_integer_falls_back_to_default(self, monkeypatch, tmp_path): | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts="lots") | ||
| assert agent.max_compression_attempts == 3 | ||
|
|
||
| def test_loop_pickup_degrades_to_default_when_attribute_missing( | ||
| self, monkeypatch, tmp_path | ||
| ): | ||
| # The loop reads getattr(agent, "max_compression_attempts", 3): a | ||
| # configured agent exposes its value, and an object without the | ||
| # attribute (older pickle / minimal stub) degrades to the prior | ||
| # hardcoded behavior. | ||
| agent = _make_agent(monkeypatch, tmp_path, max_attempts=7) | ||
| assert getattr(agent, "max_compression_attempts", 3) == 7 | ||
| assert getattr(object(), "max_compression_attempts", 3) == 3 |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This local is initialized after the pre-API compaction branch, which still uses
compression_attempts < 3and logs/3on current main (agent/conversation_loop.py:1046-1054). Please resolve the configured cap before that branch and use it there too; otherwisecompression.max_attempts: 6still allows only three preflight compressions on the #62605 path.