fix(moa): restore a valid preset after fallback model drift

build_moa_facade() reused agent.model as the preset name; a session
that had drifted to a fallback model crashed on restore with
MoAPresetNotFoundError. Validate the resolved preset against the
configured presets and fall back to the default preset.

Salvaged from PR #74903 by @liusencomic-cyber.
This commit is contained in:
knocksen
2026-07-31 21:51:17 -07:00
committed by Teknium
parent 716d274f58
commit 743c4906d9
2 changed files with 40 additions and 1 deletions
+17 -1
View File
@@ -2230,8 +2230,24 @@ def build_moa_facade(agent, preset_name: Any = None) -> MoAClient:
except Exception:
pass
resolved_preset = preset_name
if resolved_preset is None and getattr(agent, "provider", None) == "moa":
resolved_preset = getattr(agent, "model", None)
resolved_preset = str(resolved_preset or "default")
try:
from hermes_cli.config import load_config
from hermes_cli.moa_config import normalize_moa_config
moa_cfg = normalize_moa_config(load_config().get("moa") or {})
presets = moa_cfg.get("presets") or {}
if resolved_preset not in presets:
resolved_preset = moa_cfg.get("default_preset") or "default"
except Exception:
resolved_preset = "default"
return MoAClient(
str(preset_name or getattr(agent, "model", None) or "default"),
resolved_preset,
reference_callback=_moa_reference_relay,
# Thread the agent through so the reference fan-out wait can be
# aborted on a user interrupt (see _run_references_parallel).
+23
View File
@@ -90,6 +90,29 @@ def test_create_streams_aggregator_when_requested(monkeypatch, tmp_path):
assert agg["tools"] is not None
def test_build_moa_facade_ignores_fallback_model_name_when_restoring(monkeypatch, tmp_path):
"""A fallback restore must not turn the temporary fallback model name into
a MoA preset. Sessions that drifted to e.g. deepseek-v4-flash previously
crashed on restore with MoAPresetNotFoundError because build_moa_facade()
reused agent.model as the preset (#MoA restore path).
"""
home = tmp_path / ".hermes"
_write_cfg(home)
monkeypatch.setenv("HERMES_HOME", str(home))
from agent.moa_loop import build_moa_facade
agent = SimpleNamespace(
provider="moa",
model="deepseek-v4-flash",
tool_progress_callback=None,
)
client = build_moa_facade(agent, None)
assert client.chat.completions.preset_name == "review"
def test_create_wraps_completed_aggregator_response_as_delta_chunk(monkeypatch, tmp_path):
"""When an aggregator adapter returns a completed response despite
stream=True (Codex Responses compatibility shape), MoA must return a