fix(cli): reuse canonical root model key normalization in load_cli_config

This commit is contained in:
novax635 2026-05-23 21:31:18 +03:00 committed by Teknium
parent 2442a0c281
commit 421ab81052
2 changed files with 28 additions and 20 deletions

19
cli.py
View file

@ -468,7 +468,9 @@ def load_cli_config() -> Dict[str, Any]:
if config_path.exists():
try:
with open(config_path, "r", encoding="utf-8") as f:
file_config = yaml.safe_load(f) or {}
from hermes_cli.config import _normalize_root_model_keys
file_config = _normalize_root_model_keys(yaml.safe_load(f) or {})
_file_has_terminal_config = "terminal" in file_config
@ -489,21 +491,6 @@ def load_cli_config() -> Dict[str, Any]:
if "model" in file_config["model"] and "default" not in file_config["model"]:
defaults["model"]["default"] = file_config["model"]["model"]
# Legacy root-level provider/base_url fallback.
# Some users (or old code) put provider: / base_url: at the
# config root instead of inside the model: section. These are
# only used as a FALLBACK when model.provider / model.base_url
# is not already set — never as an override. The canonical
# location is model.provider (written by `hermes model`).
if not defaults["model"].get("provider"):
root_provider = file_config.get("provider")
if root_provider:
defaults["model"]["provider"] = root_provider
if not defaults["model"].get("base_url"):
root_base_url = file_config.get("base_url")
if root_base_url:
defaults["model"]["base_url"] = root_base_url
# Deep merge file_config into defaults.
# First: merge keys that exist in both (deep-merge dicts, overwrite scalars)
for key in defaults:

View file

@ -470,8 +470,8 @@ class TestRootLevelProviderOverride:
assert cfg["model"]["provider"] == "openrouter"
def test_root_provider_ignored_when_default_model_provider_exists(self, tmp_path, monkeypatch):
"""Even when model.provider is the default 'auto', root-level provider is ignored."""
def test_root_provider_used_as_fallback_when_model_provider_missing(self, tmp_path, monkeypatch):
"""Legacy root-level provider still populates model.provider in the CLI loader."""
import yaml
hermes_home = tmp_path / ".hermes"
@ -491,8 +491,29 @@ class TestRootLevelProviderOverride:
monkeypatch.setattr(cli, "_hermes_home", hermes_home)
cfg = cli.load_cli_config()
# Root-level "opencode-go" must NOT leak through
assert cfg["model"]["provider"] != "opencode-go"
assert cfg["model"]["provider"] == "opencode-go"
def test_root_base_url_used_as_fallback_when_model_base_url_missing(self, tmp_path, monkeypatch):
"""Legacy root-level base_url still populates model.base_url in the CLI loader."""
import yaml
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
config_path = hermes_home / "config.yaml"
config_path.write_text(yaml.safe_dump({
"base_url": "https://example.com/v1",
"model": {
"default": "google/gemini-3-flash-preview",
},
}))
import cli
monkeypatch.setattr(cli, "_hermes_home", hermes_home)
cfg = cli.load_cli_config()
assert cfg["model"]["base_url"] == "https://example.com/v1"
def test_terminal_vercel_runtime_bridged_to_env(self, tmp_path, monkeypatch):
"""Classic CLI must expose terminal.vercel_runtime to terminal_tool.py."""