mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-05 02:31:47 +00:00
Merge pull request #18029 from NousResearch/bb/tui-max-iterations-salvage
fix(tui): respect max turns config
This commit is contained in:
commit
29bcd2f6e9
2 changed files with 141 additions and 3 deletions
|
|
@ -3911,3 +3911,134 @@ def test_reload_env_rpc_surfaces_errors(monkeypatch):
|
|||
|
||||
assert "error" in resp
|
||||
assert "env path locked" in resp["error"]["message"]
|
||||
|
||||
|
||||
# ── max_iterations config reading ─────────────────────────────────────
|
||||
|
||||
|
||||
def _setup_make_agent_mocks(monkeypatch, cfg):
|
||||
monkeypatch.setattr(server, "_load_cfg", lambda: cfg)
|
||||
monkeypatch.setattr(server, "_resolve_startup_runtime", lambda: ("test-model", None))
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.runtime_provider.resolve_runtime_provider",
|
||||
lambda requested=None, target_model=None: {
|
||||
"provider": None,
|
||||
"base_url": None,
|
||||
"api_key": None,
|
||||
"api_mode": None,
|
||||
"command": None,
|
||||
"args": None,
|
||||
"credential_pool": None,
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(server, "_load_tool_progress_mode", lambda: "off")
|
||||
monkeypatch.setattr(server, "_load_reasoning_config", lambda: None)
|
||||
monkeypatch.setattr(server, "_load_service_tier", lambda: None)
|
||||
monkeypatch.setattr(server, "_load_enabled_toolsets", lambda: None)
|
||||
monkeypatch.setattr(server, "_get_db", lambda: None)
|
||||
monkeypatch.setattr(server, "_agent_cbs", lambda sid: {})
|
||||
|
||||
|
||||
def test_make_agent_reads_nested_max_turns(monkeypatch):
|
||||
_setup_make_agent_mocks(monkeypatch, {"agent": {"max_turns": 200}})
|
||||
|
||||
with patch("run_agent.AIAgent") as mock_agent:
|
||||
server._make_agent("sid1", "key1")
|
||||
|
||||
assert mock_agent.call_args.kwargs["max_iterations"] == 200
|
||||
|
||||
|
||||
def test_make_agent_nested_max_turns_takes_priority(monkeypatch):
|
||||
_setup_make_agent_mocks(monkeypatch, {"agent": {"max_turns": 500}, "max_turns": 100})
|
||||
|
||||
with patch("run_agent.AIAgent") as mock_agent:
|
||||
server._make_agent("sid1", "key1")
|
||||
|
||||
assert mock_agent.call_args.kwargs["max_iterations"] == 500
|
||||
|
||||
|
||||
def test_make_agent_defaults_to_90(monkeypatch):
|
||||
_setup_make_agent_mocks(monkeypatch, {})
|
||||
|
||||
with patch("run_agent.AIAgent") as mock_agent:
|
||||
server._make_agent("sid1", "key1")
|
||||
|
||||
assert mock_agent.call_args.kwargs["max_iterations"] == 90
|
||||
|
||||
|
||||
def test_make_agent_handles_null_agent_config(monkeypatch):
|
||||
_setup_make_agent_mocks(monkeypatch, {"agent": None, "max_turns": 80})
|
||||
|
||||
with patch("run_agent.AIAgent") as mock_agent:
|
||||
server._make_agent("sid1", "key1")
|
||||
|
||||
assert mock_agent.call_args.kwargs["max_iterations"] == 80
|
||||
|
||||
|
||||
class _FakeAgentForBackground:
|
||||
base_url = None
|
||||
api_key = None
|
||||
provider = None
|
||||
api_mode = None
|
||||
acp_command = None
|
||||
acp_args = None
|
||||
model = "test-model"
|
||||
enabled_toolsets = None
|
||||
ephemeral_system_prompt = None
|
||||
providers_allowed = None
|
||||
providers_ignored = None
|
||||
providers_order = None
|
||||
provider_sort = None
|
||||
provider_require_parameters = False
|
||||
provider_data_collection = None
|
||||
reasoning_config = None
|
||||
service_tier = None
|
||||
request_overrides = {}
|
||||
_fallback_model = None
|
||||
|
||||
|
||||
def test_background_agent_kwargs_reads_nested_max_turns(monkeypatch):
|
||||
monkeypatch.setattr(server, "_load_cfg", lambda: {"agent": {"max_turns": 300}})
|
||||
|
||||
kwargs = server._background_agent_kwargs(_FakeAgentForBackground(), "task_1")
|
||||
|
||||
assert kwargs["max_iterations"] == 300
|
||||
|
||||
|
||||
def test_background_agent_kwargs_falls_back_to_root_max_turns(monkeypatch):
|
||||
monkeypatch.setattr(server, "_load_cfg", lambda: {"max_turns": 50})
|
||||
|
||||
kwargs = server._background_agent_kwargs(_FakeAgentForBackground(), "task_1")
|
||||
|
||||
assert kwargs["max_iterations"] == 50
|
||||
|
||||
|
||||
def test_background_agent_kwargs_defaults_to_25(monkeypatch):
|
||||
monkeypatch.setattr(server, "_load_cfg", lambda: {})
|
||||
|
||||
kwargs = server._background_agent_kwargs(_FakeAgentForBackground(), "task_1")
|
||||
|
||||
assert kwargs["max_iterations"] == 25
|
||||
|
||||
|
||||
def test_background_agent_kwargs_handles_null_agent_config(monkeypatch):
|
||||
monkeypatch.setattr(server, "_load_cfg", lambda: {"agent": None, "max_turns": 40})
|
||||
|
||||
kwargs = server._background_agent_kwargs(_FakeAgentForBackground(), "task_1")
|
||||
|
||||
assert kwargs["max_iterations"] == 40
|
||||
|
||||
|
||||
def test_config_show_displays_nested_max_turns(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
server,
|
||||
"_load_cfg",
|
||||
lambda: {"agent": {"max_turns": 120}, "enabled_toolsets": [], "verbose": False},
|
||||
)
|
||||
monkeypatch.setattr(server, "_resolve_model", lambda: "test-model")
|
||||
|
||||
resp = server.handle_request({"id": "1", "method": "config.show", "params": {}})
|
||||
sections = resp["result"]["sections"]
|
||||
agent_rows = next(section["rows"] for section in sections if section["title"] == "Agent")
|
||||
|
||||
assert ["Max Turns", "120"] in agent_rows
|
||||
|
|
|
|||
|
|
@ -1670,6 +1670,11 @@ def _apply_personality_to_session(
|
|||
return False, None
|
||||
|
||||
|
||||
def _cfg_max_turns(cfg: dict, default: int) -> int:
|
||||
agent_cfg = cfg.get("agent") or {}
|
||||
return int(agent_cfg.get("max_turns") or cfg.get("max_turns") or default)
|
||||
|
||||
|
||||
def _background_agent_kwargs(agent, task_id: str) -> dict:
|
||||
cfg = _load_cfg()
|
||||
|
||||
|
|
@ -1681,7 +1686,7 @@ def _background_agent_kwargs(agent, task_id: str) -> dict:
|
|||
"acp_command": getattr(agent, "acp_command", None) or None,
|
||||
"acp_args": getattr(agent, "acp_args", None) or None,
|
||||
"model": getattr(agent, "model", None) or _resolve_model(),
|
||||
"max_iterations": int(cfg.get("max_turns", 25) or 25),
|
||||
"max_iterations": _cfg_max_turns(cfg, 25),
|
||||
"enabled_toolsets": getattr(agent, "enabled_toolsets", None)
|
||||
or _load_enabled_toolsets(),
|
||||
"quiet_mode": True,
|
||||
|
|
@ -1737,7 +1742,8 @@ def _make_agent(sid: str, key: str, session_id: str | None = None):
|
|||
from hermes_cli.runtime_provider import resolve_runtime_provider
|
||||
|
||||
cfg = _load_cfg()
|
||||
system_prompt = ((cfg.get("agent") or {}).get("system_prompt", "") or "").strip()
|
||||
agent_cfg = cfg.get("agent") or {}
|
||||
system_prompt = (agent_cfg.get("system_prompt", "") or "").strip()
|
||||
model, requested_provider = _resolve_startup_runtime()
|
||||
runtime = resolve_runtime_provider(
|
||||
requested=requested_provider,
|
||||
|
|
@ -1745,6 +1751,7 @@ def _make_agent(sid: str, key: str, session_id: str | None = None):
|
|||
)
|
||||
return AIAgent(
|
||||
model=model,
|
||||
max_iterations=_cfg_max_turns(cfg, 90),
|
||||
provider=runtime.get("provider"),
|
||||
base_url=runtime.get("base_url"),
|
||||
api_key=runtime.get("api_key"),
|
||||
|
|
@ -5394,7 +5401,7 @@ def _(rid, params: dict) -> dict:
|
|||
{
|
||||
"title": "Agent",
|
||||
"rows": [
|
||||
["Max Turns", str(cfg.get("max_turns", 25))],
|
||||
["Max Turns", str(_cfg_max_turns(cfg, 90))],
|
||||
["Toolsets", ", ".join(cfg.get("enabled_toolsets", [])) or "all"],
|
||||
["Verbose", str(cfg.get("verbose", False))],
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue