From a017297cf140c58f5f4e2a4f8879506daf10f29e Mon Sep 17 00:00:00 2001 From: Baophan00 <109447498+Baophan00@users.noreply.github.com> Date: Fri, 31 Jul 2026 20:05:44 +0700 Subject: [PATCH] fix(config): respect --force for bare model key overwrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --force was silently ignored for 'model' keys — the guard always redirected to model.default even when the user explicitly asked to replace the entire section. Now --force triggers a warning and proceeds with the destructive overwrite for model too, matching the non-model mapping --force behaviour. --- hermes_cli/config.py | 23 +++++++++++++++-------- tests/hermes_cli/test_set_config_value.py | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/hermes_cli/config.py b/hermes_cli/config.py index a00d37643bb20..3128e63c204c0 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -4866,14 +4866,21 @@ def set_config_value(key: str, value: str, force: bool = False): _existing = user_config.get(key) if isinstance(_existing, dict): if key == "model": - # Redirect bare-model shorthand to model.default while - # keeping every sibling mapping key intact. - key = "model.default" - print( - f"✓ Redirecting bare 'model' to 'model.default' " - f"(preserving {len(_existing)} existing model sub-key(s))" - ) - # value was already coerced above; proceed to _set_nested + if force: + # --force: allow destructive section overwrite. + print( + f"⚠ Replacing entire 'model' section with a scalar " + f"(discarding {len(_existing)} existing sub-key(s))" + ) + else: + # Redirect bare-model shorthand to model.default while + # keeping every sibling mapping key intact. + key = "model.default" + print( + f"✓ Redirecting bare 'model' to 'model.default' " + f"(preserving {len(_existing)} existing model sub-key(s))" + ) + # value was already coerced above; proceed to _set_nested elif not force: _sub = [k for k in _existing if isinstance(k, str)] print( diff --git a/tests/hermes_cli/test_set_config_value.py b/tests/hermes_cli/test_set_config_value.py index ec588453b51ce..a70e8ebe7491c 100644 --- a/tests/hermes_cli/test_set_config_value.py +++ b/tests/hermes_cli/test_set_config_value.py @@ -643,3 +643,17 @@ class TestMappingGuard: parsed = _yaml.safe_load(_read_config(_isolated_hermes_home)) assert parsed["model"]["default"] == "claude-opus-4" assert parsed["model"]["provider"] == "openai-api" + + def test_model_force_overwrites_entire_section(self, _isolated_hermes_home): + """hermes config set --force model → overwrite entire section.""" + self._write_config(_isolated_hermes_home, { + "model": { + "default": "gpt-4o", + "provider": "openai-api", + "context_length": 128_000, + } + }) + set_config_value("model", "claude-opus-4", force=True) + import yaml as _yaml + parsed = _yaml.safe_load(_read_config(_isolated_hermes_home)) + assert parsed["model"] == "claude-opus-4"