mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
fix(auxiliary): treat explicit model:auto sentinel, not just cfg_model
'auto' is a sentinel meaning "inherit from main runtime / auto-detect", not a literal model id -- already handled for cfg_model (config-derived) in _resolve_task_provider_model, but not for the explicit `model` kwarg. MoA reference/aggregator slots (agent/moa_loop.py's _slot_runtime) forward a preset's `model:` field as this explicit argument rather than through auxiliary.<task> config, so a MoA preset configured with `model: auto` (a natural thing to try given the existing auxiliary.*.model: auto convention) reached this function as the explicit `model` arg and took the `model or cfg_model` branch, bypassing the cfg_model-only sentinel check entirely -- sending the literal string "auto" to the wire as a model id. Normalize both the explicit `model` and `cfg_model` the same way, fixing this at the single chokepoint every caller (MoA included) already goes through, rather than patching moa_loop.py separately.
This commit is contained in:
parent
0dbf639bc8
commit
2962ba2b7b
2 changed files with 58 additions and 0 deletions
|
|
@ -6369,6 +6369,15 @@ def _resolve_task_provider_model(
|
|||
# which downstream consumers like ContextCompressor accept as the task output.
|
||||
# The provider-side 'auto' is handled in _resolve_auto() via main_runtime
|
||||
# fallback, so dropping cfg_model to None here lets that path do its job.
|
||||
#
|
||||
# The explicit `model` kwarg needs the identical normalization: MoA slots
|
||||
# (agent/moa_loop.py's _slot_runtime) forward a preset's `model:` field as
|
||||
# this explicit argument rather than through auxiliary.<task> config, so a
|
||||
# user-configured `model: auto` on a MoA reference/aggregator slot reaches
|
||||
# this function here, not as cfg_model. Only normalizing cfg_model let that
|
||||
# literal "auto" slip through via `model or cfg_model` below.
|
||||
if model and model.lower() == "auto":
|
||||
model = None
|
||||
if cfg_model and cfg_model.lower() == "auto":
|
||||
cfg_model = None
|
||||
|
||||
|
|
|
|||
|
|
@ -394,6 +394,55 @@ class TestResolveTaskProviderModel:
|
|||
assert resolved_provider == "anthropic"
|
||||
assert model == "claude-haiku-4-5-20251001"
|
||||
|
||||
def test_explicit_model_auto_sentinel_is_normalized(self):
|
||||
"""MoA slots (agent/moa_loop.py's _slot_runtime) forward a preset's
|
||||
`model:` field as the explicit `model` kwarg here, not through
|
||||
auxiliary.<task> config. Only cfg_model was normalized before, so a
|
||||
MoA reference/aggregator slot configured with `model: auto` sent the
|
||||
literal string "auto" to the wire as a model id."""
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
provider="anthropic",
|
||||
model="auto",
|
||||
)
|
||||
|
||||
assert resolved_provider == "anthropic"
|
||||
assert model is None
|
||||
|
||||
def test_explicit_model_auto_sentinel_case_insensitive(self):
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
provider="anthropic",
|
||||
model="AUTO",
|
||||
)
|
||||
|
||||
assert model is None
|
||||
|
||||
def test_explicit_model_auto_falls_back_to_cfg_model(self, monkeypatch):
|
||||
"""When the explicit model is the "auto" sentinel, it must not shadow
|
||||
a real configured task model — the `model or cfg_model` fallback
|
||||
chain should still reach cfg_model exactly as if model had been
|
||||
omitted entirely."""
|
||||
monkeypatch.setattr(
|
||||
"agent.auxiliary_client._get_auxiliary_task_config",
|
||||
lambda _task: {"provider": "openai", "model": "gpt-real-model"},
|
||||
)
|
||||
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
task="moa_reference",
|
||||
model="auto",
|
||||
)
|
||||
|
||||
assert model == "gpt-real-model"
|
||||
|
||||
def test_non_auto_model_is_unaffected(self):
|
||||
"""Regression guard: a real model name must not be touched by the
|
||||
sentinel normalization."""
|
||||
resolved_provider, model, base_url, api_key, api_mode = _resolve_task_provider_model(
|
||||
provider="openai",
|
||||
model="gpt-4o-mini",
|
||||
)
|
||||
|
||||
assert model == "gpt-4o-mini"
|
||||
|
||||
|
||||
class TestMoaAggregatorSharedResolution:
|
||||
"""The shared MoA→aggregator helper and the layers that consume it.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue