fix(desktop): keep configured MoA presets in model picker

This commit is contained in:
giggling-ginger 2026-07-08 07:34:00 +00:00
parent f64e4f4f57
commit 8eac52054b
2 changed files with 87 additions and 1 deletions

View file

@ -340,13 +340,61 @@ def _filter_explicit_provider_rows(rows: list[dict], ctx: ConfigContext) -> list
if slug == "moa":
# MoA is a virtual routing mode, not an independently configured
# provider. Hide it from explicit-only pickers unless it is the
# current provider (handled above).
# current provider (handled above) or the user explicitly wrote an
# enabled MoA preset into config.yaml. Use raw config so the
# DEFAULT_CONFIG preset does not make every desktop picker show MoA.
if _raw_config_has_enabled_moa_preset():
kept.append(row)
continue
if is_provider_explicitly_configured(slug):
kept.append(row)
return kept
def _raw_config_has_enabled_moa_preset() -> bool:
"""Return True when the user's raw config explicitly enables MoA.
``load_config()`` includes ``DEFAULT_CONFIG["moa"].presets.default`` for
everyone. Explicit-only model pickers must not treat that default as a user
choice, but they should keep MoA visible once the user has saved at least
one enabled preset (or an older flat MoA config) in their own config.yaml.
"""
try:
from hermes_cli.config import read_raw_config
raw = read_raw_config()
except Exception:
return False
if not isinstance(raw, dict):
return False
moa = raw.get("moa")
if not isinstance(moa, dict):
return False
presets = moa.get("presets")
if isinstance(presets, dict):
for name, preset in presets.items():
if not str(name or "").strip():
continue
if not isinstance(preset, dict):
return True
if preset.get("enabled", True):
return True
return False
legacy_keys = {
"reference_models",
"aggregator",
"reference_temperature",
"aggregator_temperature",
"max_tokens",
"reference_max_tokens",
"fanout",
}
return any(key in moa for key in legacy_keys) and bool(moa.get("enabled", True))
def _apply_picker_hints(rows: list[dict]) -> None:
"""Add ``authenticated``/``auth_type``/``key_env``/``warning`` per row.

View file

@ -402,6 +402,7 @@ def test_explicit_only_filters_ambient_credentials_but_keeps_current_and_custom_
ctx = _empty_ctx(provider="openai-codex", model="gpt-5.4")
with (
_list_auth_returning(rows),
patch("hermes_cli.config.read_raw_config", return_value={}),
patch(
"hermes_cli.auth.is_provider_explicitly_configured",
side_effect=lambda slug: slug == "gemini",
@ -416,6 +417,43 @@ def test_explicit_only_filters_ambient_credentials_but_keeps_current_and_custom_
]
def test_explicit_only_keeps_moa_when_raw_config_has_enabled_preset():
rows = [
{"slug": "moa", "name": "MoA", "models": ["review"],
"total_models": 1, "is_current": False, "is_user_defined": False,
"source": "virtual"},
]
ctx = _empty_ctx(provider="openrouter", model="anthropic/claude-opus-4.8")
raw_config = {
"moa": {
"active_preset": "review",
"presets": {
"review": {
"enabled": True,
"reference_models": [
{"provider": "openai-codex", "model": "gpt-5.5"},
],
"aggregator": {
"provider": "openrouter",
"model": "anthropic/claude-opus-4.8",
},
},
},
},
}
with (
_list_auth_returning(rows),
patch("hermes_cli.config.load_config", return_value=raw_config),
patch("hermes_cli.config.read_raw_config", return_value=raw_config),
patch("hermes_cli.auth.is_provider_explicitly_configured", return_value=False),
):
payload = build_models_payload(ctx, explicit_only=True)
assert [row["slug"] for row in payload["providers"]] == ["moa"]
assert payload["providers"][0]["models"] == ["review"]
# ─── picker_hints ──────────────────────────────────────────────────────