mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
fix(moa): disabled presets no longer hijack a plain model switch (#55598)
exact_moa_preset_name matched any bare model name equal to a preset key, regardless of the preset's enabled flag. On the no-explicit-provider switch path (PATH B in model_switch.py), a plain /model switch whose name collided with a preset key (e.g. "default") silently pivoted the session onto the MoA virtual provider — even when the user had set enabled: false to opt out (issue #55187). The LLM driving a routine model switch could land on a broken moa provider with empty default_preset / unconfigured aggregator credentials. Gate the implicit bare-name match on the per-preset enabled flag. Explicit selection via --provider moa / the model picker uses PATH A and does not go through exact_moa_preset_name, so a disabled preset stays reachable when the user explicitly asks for it.
This commit is contained in:
parent
bff61f558f
commit
e7ca53e6b8
2 changed files with 48 additions and 1 deletions
|
|
@ -158,11 +158,26 @@ def resolve_moa_preset(config: Any, name: str | None = None) -> dict[str, Any]:
|
|||
|
||||
|
||||
def exact_moa_preset_name(config: Any, text: str) -> str | None:
|
||||
"""Return the preset name iff ``text`` exactly matches an *enabled* preset.
|
||||
|
||||
Used by the no-explicit-provider switch path (PATH B in
|
||||
``hermes_cli/model_switch.py``) to recognize a bare ``/model <preset>``
|
||||
that the user typed without the ``moa:`` prefix. This is an *implicit*
|
||||
match, so it must honor the per-preset ``enabled`` opt-out: a user who set
|
||||
``enabled: false`` to disable a preset must not have a plain model switch
|
||||
whose name happens to collide with that preset key silently pivot the
|
||||
session onto the MoA virtual provider (issue #55187). Explicit selection
|
||||
via ``--provider moa`` / the model picker does not go through here, so a
|
||||
disabled preset is still reachable when the user explicitly asks for it.
|
||||
"""
|
||||
wanted = str(text or "").strip()
|
||||
if not wanted:
|
||||
return None
|
||||
cfg = normalize_moa_config(config)
|
||||
return wanted if wanted in cfg["presets"] else None
|
||||
preset = cfg["presets"].get(wanted)
|
||||
if preset is None or not preset.get("enabled", True):
|
||||
return None
|
||||
return wanted
|
||||
|
||||
|
||||
def set_active_moa_preset(config: Any, name: str | None) -> dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,38 @@ def test_exact_preset_matching_is_not_fuzzy():
|
|||
assert exact_moa_preset_name(config, "coding please fix this") is None
|
||||
|
||||
|
||||
def test_exact_preset_matching_skips_disabled_presets():
|
||||
"""A disabled preset must not match the implicit bare-name switch path.
|
||||
|
||||
Regression for #55187: with ``enabled: false`` presets, a plain model
|
||||
switch whose name collides with a preset key (e.g. ``default``) silently
|
||||
pivoted the session onto the MoA virtual provider. The per-preset
|
||||
``enabled`` opt-out must gate this implicit match.
|
||||
"""
|
||||
config = {
|
||||
"presets": {
|
||||
"default": {"enabled": False},
|
||||
"klo": {"enabled": False},
|
||||
},
|
||||
}
|
||||
assert exact_moa_preset_name(config, "default") is None
|
||||
assert exact_moa_preset_name(config, "klo") is None
|
||||
|
||||
|
||||
def test_exact_preset_matching_allows_enabled_presets():
|
||||
"""An explicitly enabled preset still matches the bare-name switch path."""
|
||||
config = {
|
||||
"presets": {
|
||||
"fast": {"enabled": True},
|
||||
"slow": {"enabled": False},
|
||||
},
|
||||
}
|
||||
assert exact_moa_preset_name(config, "fast") == "fast"
|
||||
assert exact_moa_preset_name(config, "slow") is None
|
||||
# Default (no explicit enabled key) is enabled and still matches.
|
||||
assert exact_moa_preset_name({"presets": {"x": {}}}, "x") == "x"
|
||||
|
||||
|
||||
def test_active_preset_toggle_validation():
|
||||
config = {"default_preset": "coding", "presets": {"coding": {}, "review": {}}}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue