mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
refactor(compression): scope Codex-native compaction to the app-server runtime
Drop the Responses-API native compaction path and its opt-in umbrella flag from the salvaged feature. On the Codex OAuth chat route Hermes owns the message list and the summary compressor works (and stays provider-portable — encrypted compaction items would lock the session history to chatgpt.com and break /model switches and provider fallback). On the app-server runtime (codex CLI/agent) the codex agent owns the real thread context, so thread/compact/start is the only mechanism that can actually shrink it (#36801) — that path is now the default behavior for codex_app_server sessions, controlled by compression.codex_app_server_auto (native|hermes|off), no umbrella flag. Removed: responses.compact() call path, codex_compaction_items replay/ persistence plumbing, codex_native_compaction + codex_responses_threshold config keys, desktop settings fields, and their tests. Kept: everything app-server (compact_thread(), compaction notifications, bookkeeping, docs, tests) plus cache-busting keys for the surviving knobs.
This commit is contained in:
parent
d1c8c03416
commit
87b65e24a7
5 changed files with 13 additions and 51 deletions
|
|
@ -415,17 +415,6 @@ compression:
|
|||
# for the ChatGPT Codex OAuth route. Set false to opt back down to threshold.
|
||||
codex_gpt55_autoraise: true
|
||||
|
||||
# Codex-native compaction paths are opt-in (default: false) to preserve
|
||||
# Hermes' existing auxiliary summarizer behavior for existing installs.
|
||||
# When true, Codex OAuth uses Responses API compact and Codex app-server
|
||||
# compaction uses the app-server thread compact API.
|
||||
codex_native_compaction: false
|
||||
|
||||
# Codex OAuth / Responses API compaction trigger (default: 0.85 = 85%).
|
||||
# Used only when codex_native_compaction is true. The recent tail still uses
|
||||
# protect_last_n below.
|
||||
codex_responses_threshold: 0.85
|
||||
|
||||
# Fraction of the threshold to preserve as recent tail (default: 0.20 = 20%)
|
||||
# e.g. 20% of 50% threshold = 10% of total context kept as recent messages.
|
||||
# Summary output is separately capped at 12K tokens (Gemini output limit).
|
||||
|
|
@ -437,8 +426,9 @@ compression:
|
|||
# compression of older turns.
|
||||
protect_last_n: 20
|
||||
|
||||
# Codex app-server auto-compaction mode:
|
||||
# Used only when codex_native_compaction is true.
|
||||
# Codex app-server (codex CLI runtime) thread-compaction mode. The codex
|
||||
# agent owns the real thread context on this runtime, so Hermes' summarizer
|
||||
# cannot shrink it — compaction goes through the app server instead.
|
||||
# native = let Codex decide when to compact its own thread (default)
|
||||
# hermes = let Hermes threshold trigger Codex thread/compact/start
|
||||
# off = Hermes will not auto-trigger compaction; Codex may still compact natively
|
||||
|
|
|
|||
|
|
@ -15321,6 +15321,8 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
|||
("model", "max_tokens"),
|
||||
("compression", "enabled"),
|
||||
("compression", "threshold"),
|
||||
("compression", "codex_gpt55_autoraise"),
|
||||
("compression", "codex_app_server_auto"),
|
||||
("compression", "target_ratio"),
|
||||
("compression", "protect_last_n"),
|
||||
("agent", "disabled_toolsets"),
|
||||
|
|
|
|||
|
|
@ -229,8 +229,6 @@ class TestExtractCacheBustingConfig:
|
|||
"enabled": False,
|
||||
"threshold": 0.6,
|
||||
"codex_gpt55_autoraise": False,
|
||||
"codex_native_compaction": True,
|
||||
"codex_responses_threshold": 0.85,
|
||||
"target_ratio": 0.3,
|
||||
"protect_last_n": 25,
|
||||
"codex_app_server_auto": "hermes",
|
||||
|
|
@ -241,8 +239,6 @@ class TestExtractCacheBustingConfig:
|
|||
assert out["compression.enabled"] is False
|
||||
assert out["compression.threshold"] == 0.6
|
||||
assert out["compression.codex_gpt55_autoraise"] is False
|
||||
assert out["compression.codex_native_compaction"] is True
|
||||
assert out["compression.codex_responses_threshold"] == 0.85
|
||||
assert out["compression.target_ratio"] == 0.3
|
||||
assert out["compression.protect_last_n"] == 25
|
||||
assert out["compression.codex_app_server_auto"] == "hermes"
|
||||
|
|
|
|||
|
|
@ -1782,52 +1782,28 @@ class TestConfigNormalizationDoesNotOverwriteUserValues:
|
|||
assert _explicit_config_paths({"memory": {}, "display": {}}) == set()
|
||||
|
||||
|
||||
class TestCodexNativeCompactionConfig:
|
||||
"""Codex-native compaction stays opt-in without mutating existing configs."""
|
||||
class TestCodexAppServerAutoConfig:
|
||||
"""codex_app_server_auto ships a default and survives migration untouched."""
|
||||
|
||||
def _write(self, tmp_path, body):
|
||||
(tmp_path / "config.yaml").write_text(body, encoding="utf-8")
|
||||
|
||||
def test_default_config_keeps_codex_native_compaction_opt_in(self):
|
||||
assert DEFAULT_CONFIG["compression"]["codex_native_compaction"] is False
|
||||
def test_default_config_has_native_mode(self):
|
||||
assert DEFAULT_CONFIG["compression"]["codex_app_server_auto"] == "native"
|
||||
assert DEFAULT_CONFIG["compression"]["codex_gpt55_autoraise"] is True
|
||||
|
||||
def test_migration_does_not_write_codex_native_compaction_default(self, tmp_path):
|
||||
def test_preserves_existing_codex_app_server_auto_value(self, tmp_path):
|
||||
with patch.dict(os.environ, {"HERMES_HOME": str(tmp_path)}):
|
||||
self._write(
|
||||
tmp_path,
|
||||
"_config_version: 31\n"
|
||||
"compression:\n"
|
||||
" threshold: 0.5\n"
|
||||
" codex_gpt55_autoraise: false\n",
|
||||
" codex_app_server_auto: hermes\n",
|
||||
)
|
||||
|
||||
result = migrate_config(interactive=False, quiet=True)
|
||||
migrate_config(interactive=False, quiet=True)
|
||||
|
||||
raw = yaml.safe_load((tmp_path / "config.yaml").read_text())
|
||||
assert raw["compression"]["codex_gpt55_autoraise"] is False
|
||||
assert "codex_native_compaction" not in raw["compression"]
|
||||
assert raw["compression"]["threshold"] == 0.5
|
||||
assert raw["_config_version"] == DEFAULT_CONFIG["_config_version"]
|
||||
assert (
|
||||
"compression.codex_native_compaction=false"
|
||||
not in result["config_added"]
|
||||
)
|
||||
assert raw["compression"]["codex_app_server_auto"] == "hermes"
|
||||
|
||||
def test_preserves_existing_codex_native_compaction_value(self, tmp_path):
|
||||
with patch.dict(os.environ, {"HERMES_HOME": str(tmp_path)}):
|
||||
self._write(
|
||||
tmp_path,
|
||||
"_config_version: 31\n"
|
||||
"compression:\n"
|
||||
" codex_native_compaction: true\n",
|
||||
)
|
||||
|
||||
result = migrate_config(interactive=False, quiet=True)
|
||||
|
||||
raw = yaml.safe_load((tmp_path / "config.yaml").read_text())
|
||||
assert raw["compression"]["codex_native_compaction"] is True
|
||||
assert (
|
||||
"compression.codex_native_compaction=false"
|
||||
not in result["config_added"]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@ class DummyAgent:
|
|||
result,
|
||||
*,
|
||||
auto_compaction="native",
|
||||
codex_native_compaction=True,
|
||||
):
|
||||
self.api_mode = "codex_app_server"
|
||||
self.codex_native_compaction_enabled = codex_native_compaction
|
||||
self.codex_app_server_auto_compaction = auto_compaction
|
||||
self.session_id = "hermes-session-1"
|
||||
self.platform = "cli"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue