From 60391d0eef1fb96b6c3ea94531576874d67b09b1 Mon Sep 17 00:00:00 2001 From: AIalliAI <285906080+AIalliAI@users.noreply.github.com> Date: Thu, 11 Jun 2026 19:50:06 +0000 Subject: [PATCH] fix(agent): don't apply Codex gpt-5.5 autoraise notice when an external context engine is active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When context.engine selects a plugin engine (e.g. LCM), the host compression threshold — including the Codex gpt-5.5 50% -> 85% autoraise — only configures the built-in ContextCompressor and never reaches the plugin. The autoraise notice still fired, telling the user auto-compaction was raised when nothing actually changed, and the startup context-limit line printed the host percent next to the engine's own threshold_tokens, contradicting itself. - Clear _compression_threshold_autoraised when a plugin engine is selected, suppressing both the CLI startup notice and the gateway turn-1 replay via _compression_warning. - Print the active engine's own threshold_percent in the startup context-limit line so percent and token count agree. - Built-in behavior is preserved, including the fallback path where a configured engine fails to load and the built-in compressor takes over. Fixes #44439 --- agent/agent_init.py | 14 ++- .../test_plugin_context_engine_init.py | 98 +++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/agent/agent_init.py b/agent/agent_init.py index 36bea43f44b..32a06259441 100644 --- a/agent/agent_init.py +++ b/agent/agent_init.py @@ -1773,6 +1773,12 @@ def init_agent( if _selected_engine is not None: agent.context_compressor = _selected_engine + # External engines own compaction policy: the host compression + # threshold (including the Codex gpt-5.5 autoraise above) only + # configures the built-in ContextCompressor and never reaches the + # plugin, so the autoraise notice would announce a change that does + # not apply. Drop it. (#44439) + agent._compression_threshold_autoraised = None # Resolve context_length for plugin engines — mirrors switch_model() path from agent.model_metadata import get_model_context_length _plugin_ctx_len = get_model_context_length( @@ -2012,7 +2018,13 @@ def init_agent( if not agent.quiet_mode: if compression_enabled: - print(f"📊 Context limit: {agent.context_compressor.context_length:,} tokens (compress at {int(compression_threshold*100)}% = {agent.context_compressor.threshold_tokens:,})") + # Report the active engine's own threshold — for a plugin engine + # the host compression_threshold is not in effect, and mixing the + # two printed a percent that contradicted the token count. (#44439) + _active_threshold_pct = getattr( + agent.context_compressor, "threshold_percent", compression_threshold + ) + print(f"📊 Context limit: {agent.context_compressor.context_length:,} tokens (compress at {int(_active_threshold_pct*100)}% = {agent.context_compressor.threshold_tokens:,})") else: print(f"📊 Context limit: {agent.context_compressor.context_length:,} tokens (auto-compression disabled)") # Notice with the exact opt-back-out command. Printed inline at startup diff --git a/tests/run_agent/test_plugin_context_engine_init.py b/tests/run_agent/test_plugin_context_engine_init.py index 7285cb1f625..f4b29ef0093 100644 --- a/tests/run_agent/test_plugin_context_engine_init.py +++ b/tests/run_agent/test_plugin_context_engine_init.py @@ -139,3 +139,101 @@ def test_plugin_engine_update_model_args(): assert "model" in kw assert "provider" in kw assert "api_mode" in kw + + +def _codex_agent_kwargs(): + return dict( + model="gpt-5.5", + provider="openai-codex", + api_key="test-key-1234567890", + base_url="https://chatgpt.com/backend-api/codex", + quiet_mode=True, + skip_context_files=True, + skip_memory=True, + ) + + +def test_codex_gpt55_autoraise_suppressed_for_plugin_engine(): + """Codex gpt-5.5 autoraise must not fire when an external engine is active. + + Regression test for #44439 — the host compression threshold (including + the 0.85 autoraise) never reaches a plugin context engine, so the notice + announced a change that did not apply. + """ + engine = _StubEngine() + cfg = { + "context": {"engine": "stub"}, + "compression": {"enabled": True, "threshold": 0.75}, + "agent": {}, + } + + with ( + patch("hermes_cli.config.load_config", return_value=cfg), + patch("plugins.context_engine.load_context_engine", return_value=engine), + patch("agent.model_metadata.get_model_context_length", return_value=272_000), + patch("run_agent.get_tool_definitions", return_value=[]), + patch("run_agent.check_toolset_requirements", return_value={}), + patch("run_agent.OpenAI"), + ): + from run_agent import AIAgent + + agent = AIAgent(**_codex_agent_kwargs()) + + assert agent.context_compressor is engine + assert agent._compression_threshold_autoraised is None + assert agent._compression_warning is None + # The engine's own policy is untouched by the host threshold. + assert engine.threshold_percent == 0.75 + + +def test_codex_gpt55_autoraise_still_applies_to_builtin_compressor(): + """Stock built-in compressor keeps the 50% → 85% Codex gpt-5.5 autoraise.""" + cfg = { + "compression": {"enabled": True, "threshold": 0.50}, + "agent": {}, + } + + with ( + patch("hermes_cli.config.load_config", return_value=cfg), + patch("agent.context_compressor.get_model_context_length", return_value=272_000), + patch("run_agent.get_tool_definitions", return_value=[]), + patch("run_agent.check_toolset_requirements", return_value={}), + patch("run_agent.OpenAI"), + ): + from run_agent import AIAgent + + agent = AIAgent(**_codex_agent_kwargs()) + + assert agent._compression_threshold_autoraised == {"from": 0.50, "to": 0.85} + assert agent.context_compressor.threshold_percent == 0.85 + # Gateway parity: the notice is stashed for replay on turn 1. + assert agent._compression_warning and "85%" in agent._compression_warning + + +def test_codex_gpt55_autoraise_applies_when_plugin_engine_missing(): + """If the configured engine fails to load, the built-in compressor is + active and the autoraise (plus its notice) must still apply.""" + cfg = { + "context": {"engine": "no-such-engine"}, + "compression": {"enabled": True, "threshold": 0.50}, + "agent": {}, + } + + with ( + patch("hermes_cli.config.load_config", return_value=cfg), + patch( + "plugins.context_engine.load_context_engine", + side_effect=ValueError("not found"), + ), + patch("hermes_cli.plugins.get_plugin_context_engine", return_value=None), + patch("agent.context_compressor.get_model_context_length", return_value=272_000), + patch("run_agent.get_tool_definitions", return_value=[]), + patch("run_agent.check_toolset_requirements", return_value={}), + patch("run_agent.OpenAI"), + ): + from run_agent import AIAgent + + agent = AIAgent(**_codex_agent_kwargs()) + + assert agent._compression_threshold_autoraised == {"from": 0.50, "to": 0.85} + assert agent.context_compressor.threshold_percent == 0.85