From e3ffe5b75f0098f521b4674b930c4c21880be095 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Mon, 13 Apr 2026 04:59:26 -0700 Subject: [PATCH] fix: remove legacy compression.summary_* config and env var fallbacks (#8992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the backward-compat code paths that read compression provider/model settings from legacy config keys and env vars, which caused silent failures when auto-detection resolved to incompatible backends. What changed: - Remove compression.summary_model, summary_provider, summary_base_url from DEFAULT_CONFIG and cli.py defaults - Remove backward-compat block in _resolve_task_provider_model() that read from the legacy compression section - Remove _get_auxiliary_provider() and _get_auxiliary_env_override() helper functions (AUXILIARY_*/CONTEXT_* env var readers) - Remove env var fallback chain for per-task overrides - Update hermes config show to read from auxiliary.compression - Add config migration (v16→17) that moves non-empty legacy values to auxiliary.compression and strips the old keys - Update example config and openclaw migration script - Remove/update tests for deleted code paths Compression model/provider is now configured exclusively via: auxiliary.compression.provider / auxiliary.compression.model Closes #8923 --- agent/auxiliary_client.py | 66 +--------- cli-config.yaml.example | 11 +- cli.py | 1 - hermes_cli/config.py | 50 ++++++-- .../scripts/openclaw_to_hermes.py | 4 +- run_agent.py | 3 +- tests/agent/test_auxiliary_client.py | 115 ------------------ tests/agent/test_auxiliary_config_bridge.py | 12 -- .../test_auxiliary_named_custom_providers.py | 11 -- tests/cli/test_cli_save_config_value.py | 4 +- tests/hermes_cli/test_tools_config.py | 3 +- tests/tools/test_vision_tools.py | 2 - 12 files changed, 58 insertions(+), 224 deletions(-) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index 6f2f64e9f..ede43781d 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -27,10 +27,6 @@ Per-task overrides are configured in config.yaml under the ``auxiliary:`` sectio (e.g. ``auxiliary.vision.provider``, ``auxiliary.compression.model``). Default "auto" follows the chains above. -Legacy env var overrides (AUXILIARY_{TASK}_PROVIDER, AUXILIARY_{TASK}_MODEL, -AUXILIARY_{TASK}_BASE_URL, etc.) are still read as a backward-compat fallback -but config.yaml takes priority. New configuration should always use config.yaml. - Payment / credit exhaustion fallback: When a resolved provider returns HTTP 402 or a credit-related error, call_llm() automatically retries with the next available provider in the @@ -753,30 +749,6 @@ def _resolve_api_key_provider() -> Tuple[Optional[OpenAI], Optional[str]]: # ── Provider resolution helpers ───────────────────────────────────────────── -def _get_auxiliary_provider(task: str = "") -> str: - """Read the provider override for a specific auxiliary task. - - Checks AUXILIARY_{TASK}_PROVIDER first (e.g. AUXILIARY_VISION_PROVIDER), - then CONTEXT_{TASK}_PROVIDER (for the compression section's summary_provider), - then falls back to "auto". Returns one of: "auto", "openrouter", "nous", "main". - """ - if task: - for prefix in ("AUXILIARY_", "CONTEXT_"): - val = os.getenv(f"{prefix}{task.upper()}_PROVIDER", "").strip().lower() - if val and val != "auto": - return val - return "auto" - - -def _get_auxiliary_env_override(task: str, suffix: str) -> Optional[str]: - """Read an auxiliary env override from AUXILIARY_* or CONTEXT_* prefixes.""" - if not task: - return None - for prefix in ("AUXILIARY_", "CONTEXT_"): - val = os.getenv(f"{prefix}{task.upper()}_{suffix}", "").strip() - if val: - return val - return None def _try_openrouter() -> Tuple[Optional[OpenAI], Optional[str]]: @@ -1591,8 +1563,8 @@ def get_text_auxiliary_client( task: Optional task name ("compression", "web_extract") to check for a task-specific provider override. - Callers may override the returned model with a per-task env var - (e.g. CONTEXT_COMPRESSION_MODEL, AUXILIARY_WEB_EXTRACT_MODEL). + Callers may override the returned model via config.yaml + (e.g. auxiliary.compression.model, auxiliary.web_extract.model). """ provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(task or None) return resolve_provider_client( @@ -2011,9 +1983,8 @@ def _resolve_task_provider_model( Priority: 1. Explicit provider/model/base_url/api_key args (always win) - 2. Config file (auxiliary.{task}.* or compression.*) - 3. Env var overrides (backward-compat: AUXILIARY_{TASK}_*, CONTEXT_{TASK}_*) - 4. "auto" (full auto-detection chain) + 2. Config file (auxiliary.{task}.provider/model/base_url) + 3. "auto" (full auto-detection chain) Returns (provider, model, base_url, api_key, api_mode) where model may be None (use provider default). When base_url is set, provider is forced @@ -2044,22 +2015,8 @@ def _resolve_task_provider_model( cfg_api_key = str(task_config.get("api_key", "")).strip() or None cfg_api_mode = str(task_config.get("api_mode", "")).strip() or None - # Backwards compat: compression section has its own keys. - # The auxiliary.compression defaults to provider="auto", so treat - # both None and "auto" as "not explicitly configured". - if task == "compression" and (not cfg_provider or cfg_provider == "auto"): - comp = config.get("compression", {}) if isinstance(config, dict) else {} - if isinstance(comp, dict): - cfg_provider = comp.get("summary_provider", "").strip() or None - cfg_model = cfg_model or comp.get("summary_model", "").strip() or None - _sbu = comp.get("summary_base_url") or "" - cfg_base_url = cfg_base_url or _sbu.strip() or None - - # Env vars are backward-compat fallback only — config.yaml is primary. - env_model = _get_auxiliary_env_override(task, "MODEL") if task else None - env_api_mode = _get_auxiliary_env_override(task, "API_MODE") if task else None - resolved_model = model or cfg_model or env_model - resolved_api_mode = cfg_api_mode or env_api_mode + resolved_model = model or cfg_model + resolved_api_mode = cfg_api_mode if base_url: return "custom", resolved_model, base_url, api_key, resolved_api_mode @@ -2073,17 +2030,6 @@ def _resolve_task_provider_model( if cfg_provider and cfg_provider != "auto": return cfg_provider, resolved_model, None, None, resolved_api_mode - # Env vars are backward-compat fallback for users who haven't - # migrated to config.yaml yet. - env_base_url = _get_auxiliary_env_override(task, "BASE_URL") - env_api_key = _get_auxiliary_env_override(task, "API_KEY") - if env_base_url: - return "custom", resolved_model, env_base_url, env_api_key, resolved_api_mode - - env_provider = _get_auxiliary_provider(task) - if env_provider != "auto": - return env_provider, resolved_model, None, None, resolved_api_mode - return "auto", resolved_model, None, None, resolved_api_mode return "auto", resolved_model, None, None, resolved_api_mode diff --git a/cli-config.yaml.example b/cli-config.yaml.example index c9e6645bb..637e45f13 100644 --- a/cli-config.yaml.example +++ b/cli-config.yaml.example @@ -309,15 +309,8 @@ compression: # compression of older turns. protect_last_n: 20 - # Model to use for generating summaries (fast/cheap recommended) - # This model compresses the middle turns into a concise summary. - # IMPORTANT: it receives the full middle section of the conversation, so it - # MUST support a context length at least as large as your main model's. - summary_model: "google/gemini-3-flash-preview" - - # Provider for the summary model (default: "auto") - # Options: "auto", "openrouter", "nous", "main" - # summary_provider: "auto" + # To pin a specific model/provider for compression summaries, use the + # auxiliary section below (auxiliary.compression.provider / model). # ============================================================================= # Auxiliary Models (Advanced — Experimental) diff --git a/cli.py b/cli.py index 5f30d63e6..a61bcd9d3 100644 --- a/cli.py +++ b/cli.py @@ -237,7 +237,6 @@ def load_cli_config() -> Dict[str, Any]: "compression": { "enabled": True, # Auto-compress when approaching context limit "threshold": 0.50, # Compress at 50% of model's context limit - "summary_model": "", # Model for summaries (empty = use main model) }, "smart_model_routing": { "enabled": False, diff --git a/hermes_cli/config.py b/hermes_cli/config.py index f30e663e5..ef4e04b71 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -414,9 +414,7 @@ DEFAULT_CONFIG = { "threshold": 0.50, # compress when context usage exceeds this ratio "target_ratio": 0.20, # fraction of threshold to preserve as recent tail "protect_last_n": 20, # minimum recent messages to keep uncompressed - "summary_model": "", # empty = use main configured model - "summary_provider": "auto", - "summary_base_url": None, + }, "smart_model_routing": { "enabled": False, @@ -702,7 +700,7 @@ DEFAULT_CONFIG = { }, # Config schema version - bump this when adding new required fields - "_config_version": 16, + "_config_version": 17, } # ============================================================================= @@ -1975,6 +1973,43 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A print(f" ✓ Migrated tool_progress_overrides → display.platforms: {migrated}") results["config_added"].append("display.platforms (migrated from tool_progress_overrides)") + # ── Version 16 → 17: remove legacy compression.summary_* keys ── + if current_ver < 17: + config = read_raw_config() + comp = config.get("compression", {}) + if isinstance(comp, dict): + s_model = comp.pop("summary_model", None) + s_provider = comp.pop("summary_provider", None) + s_base_url = comp.pop("summary_base_url", None) + migrated_keys = [] + # Migrate non-empty, non-default values to auxiliary.compression + if s_model and str(s_model).strip(): + aux = config.setdefault("auxiliary", {}) + aux_comp = aux.setdefault("compression", {}) + if not aux_comp.get("model"): + aux_comp["model"] = str(s_model).strip() + migrated_keys.append(f"model={s_model}") + if s_provider and str(s_provider).strip() not in ("", "auto"): + aux = config.setdefault("auxiliary", {}) + aux_comp = aux.setdefault("compression", {}) + if not aux_comp.get("provider") or aux_comp.get("provider") == "auto": + aux_comp["provider"] = str(s_provider).strip() + migrated_keys.append(f"provider={s_provider}") + if s_base_url and str(s_base_url).strip(): + aux = config.setdefault("auxiliary", {}) + aux_comp = aux.setdefault("compression", {}) + if not aux_comp.get("base_url"): + aux_comp["base_url"] = str(s_base_url).strip() + migrated_keys.append(f"base_url={s_base_url}") + if migrated_keys or s_model is not None or s_provider is not None or s_base_url is not None: + config["compression"] = comp + save_config(config) + if not quiet: + if migrated_keys: + print(f" ✓ Migrated compression.summary_* → auxiliary.compression: {', '.join(migrated_keys)}") + else: + print(" ✓ Removed unused compression.summary_* keys") + if current_ver < latest_ver and not quiet: print(f"Config version: {current_ver} → {latest_ver}") @@ -2790,10 +2825,11 @@ def show_config(): print(f" Threshold: {compression.get('threshold', 0.50) * 100:.0f}%") print(f" Target ratio: {compression.get('target_ratio', 0.20) * 100:.0f}% of threshold preserved") print(f" Protect last: {compression.get('protect_last_n', 20)} messages") - _sm = compression.get('summary_model', '') or '(main model)' + _aux_comp = config.get('auxiliary', {}).get('compression', {}) + _sm = _aux_comp.get('model', '') or '(auto)' print(f" Model: {_sm}") - comp_provider = compression.get('summary_provider', 'auto') - if comp_provider != 'auto': + comp_provider = _aux_comp.get('provider', 'auto') + if comp_provider and comp_provider != 'auto': print(f" Provider: {comp_provider}") # Auxiliary models diff --git a/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py b/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py index 9b58eab59..beb32aba2 100644 --- a/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py +++ b/optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py @@ -1995,7 +1995,9 @@ class Migrator: if compaction.get("timeout"): pass # No direct mapping if compaction.get("model"): - compression["summary_model"] = compaction["model"] + aux = hermes_cfg.setdefault("auxiliary", {}) + aux_comp = aux.setdefault("compression", {}) + aux_comp["model"] = compaction["model"] hermes_cfg["compression"] = compression changes = True diff --git a/run_agent.py b/run_agent.py index 6fa6bf8a0..a2dc801b1 100644 --- a/run_agent.py +++ b/run_agent.py @@ -1212,7 +1212,6 @@ class AIAgent: _compression_cfg = {} compression_threshold = float(_compression_cfg.get("threshold", 0.50)) compression_enabled = str(_compression_cfg.get("enabled", True)).lower() in ("true", "1", "yes") - compression_summary_model = _compression_cfg.get("summary_model") or None compression_target_ratio = float(_compression_cfg.get("target_ratio", 0.20)) compression_protect_last = int(_compression_cfg.get("protect_last_n", 20)) @@ -1301,7 +1300,7 @@ class AIAgent: protect_first_n=3, protect_last_n=compression_protect_last, summary_target_ratio=compression_target_ratio, - summary_model_override=compression_summary_model, + summary_model_override=None, quiet_mode=self.quiet_mode, base_url=self.base_url, api_key=getattr(self, "api_key", ""), diff --git a/tests/agent/test_auxiliary_client.py b/tests/agent/test_auxiliary_client.py index 77004c4e1..d1af6e7b9 100644 --- a/tests/agent/test_auxiliary_client.py +++ b/tests/agent/test_auxiliary_client.py @@ -17,7 +17,6 @@ from agent.auxiliary_client import ( call_llm, async_call_llm, _read_codex_access_token, - _get_auxiliary_provider, _get_provider_chain, _is_payment_error, _try_payment_fallback, @@ -32,12 +31,6 @@ def _clean_env(monkeypatch): "OPENROUTER_API_KEY", "OPENAI_BASE_URL", "OPENAI_API_KEY", "OPENAI_MODEL", "LLM_MODEL", "NOUS_INFERENCE_BASE_URL", "ANTHROPIC_API_KEY", "ANTHROPIC_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN", - # Per-task provider/model/direct-endpoint overrides - "AUXILIARY_VISION_PROVIDER", "AUXILIARY_VISION_MODEL", - "AUXILIARY_VISION_BASE_URL", "AUXILIARY_VISION_API_KEY", - "AUXILIARY_WEB_EXTRACT_PROVIDER", "AUXILIARY_WEB_EXTRACT_MODEL", - "AUXILIARY_WEB_EXTRACT_BASE_URL", "AUXILIARY_WEB_EXTRACT_API_KEY", - "CONTEXT_COMPRESSION_PROVIDER", "CONTEXT_COMPRESSION_MODEL", ): monkeypatch.delenv(key, raising=False) @@ -568,29 +561,6 @@ class TestGetTextAuxiliaryClient: call_kwargs = mock_openai.call_args assert call_kwargs.kwargs["base_url"] == "http://localhost:1234/v1" - def test_task_direct_endpoint_override(self, monkeypatch): - monkeypatch.setenv("OPENROUTER_API_KEY", "or-key") - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_BASE_URL", "http://localhost:2345/v1") - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_API_KEY", "task-key") - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_MODEL", "task-model") - with patch("agent.auxiliary_client.OpenAI") as mock_openai: - client, model = get_text_auxiliary_client("web_extract") - assert model == "task-model" - assert mock_openai.call_args.kwargs["base_url"] == "http://localhost:2345/v1" - assert mock_openai.call_args.kwargs["api_key"] == "task-key" - - def test_task_direct_endpoint_without_openai_key_uses_placeholder(self, monkeypatch): - """Local endpoints without an API key should use 'no-key-required' placeholder.""" - monkeypatch.setenv("OPENROUTER_API_KEY", "or-key") - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_BASE_URL", "http://localhost:2345/v1") - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_MODEL", "task-model") - with patch("agent.auxiliary_client.OpenAI") as mock_openai: - client, model = get_text_auxiliary_client("web_extract") - assert client is not None - assert model == "task-model" - assert mock_openai.call_args.kwargs["api_key"] == "no-key-required" - assert mock_openai.call_args.kwargs["base_url"] == "http://localhost:2345/v1" - def test_custom_endpoint_uses_config_saved_base_url(self, monkeypatch): config = { "model": { @@ -879,73 +849,9 @@ class TestAuxiliaryPoolAwareness: -class TestGetAuxiliaryProvider: - """Tests for _get_auxiliary_provider env var resolution.""" - - def test_no_task_returns_auto(self): - assert _get_auxiliary_provider() == "auto" - assert _get_auxiliary_provider("") == "auto" - - def test_auxiliary_prefix_takes_priority(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_VISION_PROVIDER", "openrouter") - assert _get_auxiliary_provider("vision") == "openrouter" - - def test_context_prefix_fallback(self, monkeypatch): - monkeypatch.setenv("CONTEXT_COMPRESSION_PROVIDER", "nous") - assert _get_auxiliary_provider("compression") == "nous" - - def test_auxiliary_prefix_over_context_prefix(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_COMPRESSION_PROVIDER", "openrouter") - monkeypatch.setenv("CONTEXT_COMPRESSION_PROVIDER", "nous") - assert _get_auxiliary_provider("compression") == "openrouter" - - def test_auto_value_treated_as_auto(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_VISION_PROVIDER", "auto") - assert _get_auxiliary_provider("vision") == "auto" - - def test_whitespace_stripped(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_VISION_PROVIDER", " openrouter ") - assert _get_auxiliary_provider("vision") == "openrouter" - - def test_case_insensitive(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_VISION_PROVIDER", "OpenRouter") - assert _get_auxiliary_provider("vision") == "openrouter" - - def test_main_provider(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_PROVIDER", "main") - assert _get_auxiliary_provider("web_extract") == "main" - - class TestTaskSpecificOverrides: """Integration tests for per-task provider routing via get_text_auxiliary_client(task=...).""" - def test_text_with_vision_provider_override(self, monkeypatch): - """AUXILIARY_VISION_PROVIDER should not affect text tasks.""" - monkeypatch.setenv("AUXILIARY_VISION_PROVIDER", "nous") - monkeypatch.setenv("OPENROUTER_API_KEY", "or-key") - with patch("agent.auxiliary_client.OpenAI"): - client, model = get_text_auxiliary_client() # no task → auto - assert model == "google/gemini-3-flash-preview" # OpenRouter, not Nous - - def test_compression_task_reads_context_prefix(self, monkeypatch): - """Compression task should check CONTEXT_COMPRESSION_PROVIDER env var.""" - monkeypatch.setenv("CONTEXT_COMPRESSION_PROVIDER", "nous") - monkeypatch.setenv("OPENROUTER_API_KEY", "or-key") # would win in auto - with patch("agent.auxiliary_client._read_nous_auth") as mock_nous, \ - patch("agent.auxiliary_client.OpenAI"): - mock_nous.return_value = {"access_token": "***"} - client, model = get_text_auxiliary_client("compression") - # Config-first: model comes from config.yaml summary_model default, - # but provider is forced to Nous via env var - assert client is not None - - def test_web_extract_task_override(self, monkeypatch): - monkeypatch.setenv("AUXILIARY_WEB_EXTRACT_PROVIDER", "openrouter") - monkeypatch.setenv("OPENROUTER_API_KEY", "or-key") - with patch("agent.auxiliary_client.OpenAI"): - client, model = get_text_auxiliary_client("web_extract") - assert model == "google/gemini-3-flash-preview" - def test_task_direct_endpoint_from_config(self, monkeypatch, tmp_path): hermes_home = tmp_path / "hermes" hermes_home.mkdir(parents=True, exist_ok=True) @@ -979,8 +885,6 @@ class TestTaskSpecificOverrides: """model: default: glm-5.1 provider: opencode-go -compression: - summary_provider: auto """ ) monkeypatch.setenv("HERMES_HOME", str(hermes_home)) @@ -1039,25 +943,6 @@ model: "model": "gpt-5.4", } - def test_compression_summary_base_url_from_config(self, monkeypatch, tmp_path): - """compression.summary_base_url should produce a custom-endpoint client.""" - hermes_home = tmp_path / "hermes" - hermes_home.mkdir(parents=True, exist_ok=True) - (hermes_home / "config.yaml").write_text( - """compression: - summary_provider: custom - summary_model: glm-4.7 - summary_base_url: https://api.z.ai/api/coding/paas/v4 -""" - ) - monkeypatch.setenv("HERMES_HOME", str(hermes_home)) - # Custom endpoints need an API key to build the client - monkeypatch.setenv("OPENAI_API_KEY", "test-key") - with patch("agent.auxiliary_client.OpenAI") as mock_openai: - client, model = get_text_auxiliary_client("compression") - assert model == "glm-4.7" - assert mock_openai.call_args.kwargs["base_url"] == "https://api.z.ai/api/coding/paas/v4" - class TestAuxiliaryMaxTokensParam: def test_codex_fallback_uses_max_tokens(self, monkeypatch): diff --git a/tests/agent/test_auxiliary_config_bridge.py b/tests/agent/test_auxiliary_config_bridge.py index 91dea15af..66350519b 100644 --- a/tests/agent/test_auxiliary_config_bridge.py +++ b/tests/agent/test_auxiliary_config_bridge.py @@ -273,18 +273,6 @@ class TestDefaultConfigShape: assert web["provider"] == "auto" assert web["model"] == "" - def test_compression_provider_default(self): - from hermes_cli.config import DEFAULT_CONFIG - compression = DEFAULT_CONFIG["compression"] - assert "summary_provider" in compression - assert compression["summary_provider"] == "auto" - - def test_compression_base_url_default(self): - from hermes_cli.config import DEFAULT_CONFIG - compression = DEFAULT_CONFIG["compression"] - assert "summary_base_url" in compression - assert compression["summary_base_url"] is None - # ── CLI defaults parity ───────────────────────────────────────────────────── diff --git a/tests/agent/test_auxiliary_named_custom_providers.py b/tests/agent/test_auxiliary_named_custom_providers.py index 4c16bcb01..a07833cc7 100644 --- a/tests/agent/test_auxiliary_named_custom_providers.py +++ b/tests/agent/test_auxiliary_named_custom_providers.py @@ -12,17 +12,6 @@ def _isolate(tmp_path, monkeypatch): hermes_home = tmp_path / ".hermes" hermes_home.mkdir() monkeypatch.setenv("HERMES_HOME", str(hermes_home)) - for env_var in ( - "AUXILIARY_VISION_PROVIDER", - "AUXILIARY_VISION_MODEL", - "AUXILIARY_VISION_BASE_URL", - "AUXILIARY_VISION_API_KEY", - "CONTEXT_VISION_PROVIDER", - "CONTEXT_VISION_MODEL", - "CONTEXT_VISION_BASE_URL", - "CONTEXT_VISION_API_KEY", - ): - monkeypatch.delenv(env_var, raising=False) # Write a minimal config so load_config doesn't fail (hermes_home / "config.yaml").write_text("model:\n default: test-model\n") diff --git a/tests/cli/test_cli_save_config_value.py b/tests/cli/test_cli_save_config_value.py index 7d030c03c..e48119414 100644 --- a/tests/cli/test_cli_save_config_value.py +++ b/tests/cli/test_cli_save_config_value.py @@ -51,10 +51,10 @@ class TestSaveConfigValueAtomic: def test_creates_nested_keys(self, config_env): """Dot-separated paths create intermediate dicts as needed.""" from cli import save_config_value - save_config_value("compression.summary_model", "google/gemini-3-flash-preview") + save_config_value("auxiliary.compression.model", "google/gemini-3-flash-preview") result = yaml.safe_load(config_env.read_text()) - assert result["compression"]["summary_model"] == "google/gemini-3-flash-preview" + assert result["auxiliary"]["compression"]["model"] == "google/gemini-3-flash-preview" def test_overwrites_existing_value(self, config_env): """Updating an existing key replaces the value.""" diff --git a/tests/hermes_cli/test_tools_config.py b/tests/hermes_cli/test_tools_config.py index 2c2bb3919..ed79559d2 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -119,8 +119,7 @@ def test_toolset_has_keys_for_vision_accepts_codex_auth(tmp_path, monkeypatch): monkeypatch.delenv("OPENROUTER_API_KEY", raising=False) monkeypatch.delenv("OPENAI_BASE_URL", raising=False) monkeypatch.delenv("OPENAI_API_KEY", raising=False) - monkeypatch.delenv("AUXILIARY_VISION_PROVIDER", raising=False) - monkeypatch.delenv("CONTEXT_VISION_PROVIDER", raising=False) + monkeypatch.setattr( "agent.auxiliary_client.resolve_vision_provider_client", lambda: ("openai-codex", object(), "gpt-4.1"), diff --git a/tests/tools/test_vision_tools.py b/tests/tools/test_vision_tools.py index 55949144a..e8fe8b417 100644 --- a/tests/tools/test_vision_tools.py +++ b/tests/tools/test_vision_tools.py @@ -463,8 +463,6 @@ class TestVisionRequirements: monkeypatch.delenv("OPENROUTER_API_KEY", raising=False) monkeypatch.delenv("OPENAI_BASE_URL", raising=False) monkeypatch.delenv("OPENAI_API_KEY", raising=False) - monkeypatch.delenv("AUXILIARY_VISION_PROVIDER", raising=False) - monkeypatch.delenv("CONTEXT_VISION_PROVIDER", raising=False) assert check_vision_requirements() is True