fix(model-switch): preserve per-model metadata dict in _save_discovered_models_to_config (#67841)

When custom_providers[].models uses the mapping form to store
per-model metadata (e.g. context_length), _save_discovered_models_to_config
must not replace it with a flat list of strings.  Add a guard that skips
entries whose models value is a dict, preserving the user's curated
metadata.

The regression was introduced by PR #65652, which added the auto-save
helper without considering the dict form.
This commit is contained in:
kyssta-exe 25470058+kyssta-exe@users.noreply.github.com 2026-07-20 05:21:41 +00:00 committed by kshitij
parent cd0219da86
commit 311bacb572
2 changed files with 42 additions and 0 deletions

View File

@ -133,6 +133,11 @@ def _save_discovered_models_to_config(
if entry_url.rstrip("/").lower() != norm_url:
continue
existing = entry.get("models")
# Preserve per-model metadata: when ``models`` is a mapping
# (e.g. ``{"model-a": {"context_length": 8192}}``), the user
# has curated metadata per model — do not replace it.
if isinstance(existing, dict):
continue
# Only update when models are stale — avoids unnecessary
# config writes on every picker open.
if isinstance(existing, list) and existing == model_ids:

View File

@ -1479,3 +1479,40 @@ def test_save_discovered_models_noop_on_empty_args(monkeypatch):
_save_discovered_models_to_config("", [])
assert load_calls == 0, "load_config must not be called for empty args"
def test_save_discovered_models_preserves_dict_form(monkeypatch):
"""``_save_discovered_models_to_config`` must not replace a dict-form
``models`` mapping (per-model metadata like ``context_length``) with
a flat list of strings (#67841)."""
from hermes_cli.model_switch import _save_discovered_models_to_config
save_calls = []
def fake_save(config):
save_calls.append(dict(config))
monkeypatch.setattr("hermes_cli.config.save_config", fake_save)
monkeypatch.setattr(
"hermes_cli.config.load_config",
lambda: {
"custom_providers": [
{
"name": "my-gateway",
"base_url": "https://gateway.example.com/v1",
"models": {
"configured-model": {"context_length": 8192},
},
}
]
},
)
# Dict-form models must NOT be overwritten by discovered models
_save_discovered_models_to_config(
"https://gateway.example.com/v1",
["configured-model", "discovered-model"],
)
assert save_calls == [], (
"Dict-form models must not be replaced with a flat list"
)