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:
+17
-1
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user