Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions tests/tools/test_code_execution_modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def _force_local_terminal(monkeypatch):
EXECUTION_MODES,
_get_execution_mode,
_is_usable_python,
_load_config,
_resolve_child_cwd,
_resolve_child_python,
build_execute_code_schema,
Expand Down Expand Up @@ -110,6 +111,41 @@ def test_execution_modes_tuple(self):
self.assertEqual(set(EXECUTION_MODES), {"project", "strict"})


def test_load_config_honors_managed_resource_cap(tmp_path, monkeypatch):
"""Managed code_execution values must override a lower profile value."""
home = tmp_path / "home"
managed = tmp_path / "managed"
home.mkdir()
managed.mkdir()
(home / "config.yaml").write_text(
"code_execution:\n"
" mode: strict\n"
" timeout: 111\n"
" max_tool_calls: 3\n",
encoding="utf-8",
)
(managed / "config.yaml").write_text(
"code_execution:\n"
" max_tool_calls: 2147483647\n",
encoding="utf-8",
)
monkeypatch.setenv("HERMES_HOME", str(home))
monkeypatch.setenv("HERMES_MANAGED_DIR", str(managed))

import hermes_cli.config as config
from hermes_cli import managed_scope

config._LOAD_CONFIG_CACHE.clear()
config._RAW_CONFIG_CACHE.clear()
managed_scope.invalidate_managed_cache()

cfg = _load_config()

assert cfg["max_tool_calls"] == 2147483647
assert cfg["mode"] == "strict"
assert cfg["timeout"] == 111


# ---------------------------------------------------------------------------
# Interpreter resolver
# ---------------------------------------------------------------------------
Expand Down
19 changes: 19 additions & 0 deletions tests/tui_gateway/test_make_agent_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,25 @@ def test_make_agent_honors_tui_launch_env_flags():
assert kwargs["skip_memory"] is True


def test_cfg_max_turns_managed_value_wins_launch_env(tmp_path, monkeypatch):
"""Administrator policy must outrank a stale desktop launch override."""
managed = tmp_path / "managed"
managed.mkdir()
(managed / "config.yaml").write_text(
"agent:\n max_turns: 2147483647\n",
encoding="utf-8",
)
monkeypatch.setenv("HERMES_MANAGED_DIR", str(managed))
monkeypatch.setenv("HERMES_TUI_MAX_TURNS", "7")

from hermes_cli.managed_scope import invalidate_managed_cache
from tui_gateway.server import _cfg_max_turns

invalidate_managed_cache()

assert _cfg_max_turns({"agent": {"max_turns": 2147483647}}, default=90) == 2147483647


def test_probe_config_health_flags_null_sections():
"""Bare YAML keys (`agent:` with no value) parse as None and silently
drop nested settings; probe must surface them so users can fix."""
Expand Down
7 changes: 4 additions & 3 deletions tools/code_execution_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1679,13 +1679,14 @@ def _load_config() -> dict:
during tool discovery. Importing ``cli`` here pulls prompt_toolkit/Rich and
a large chunk of the classic REPL onto every agent startup path, including
``hermes --tui`` where it is never used. Read the lightweight raw config
instead; the config layer already caches by (mtime, size), and an absent
key cleanly falls back to DEFAULT_EXECUTION_MODE.
and apply the managed overlay explicitly so profile values stay sparse but
administrator-pinned resource limits still win.
"""
try:
from hermes_cli.config import read_raw_config
from hermes_cli.managed_scope import apply_managed_overlay

cfg = read_raw_config().get("code_execution", {})
cfg = apply_managed_overlay(read_raw_config()).get("code_execution", {})
return cfg if isinstance(cfg, dict) else {}
except Exception:
return {}
Expand Down
9 changes: 8 additions & 1 deletion tui_gateway/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4147,13 +4147,20 @@ def _apply_personality_to_session(


def _cfg_max_turns(cfg: dict, default: int) -> int:
agent_cfg = cfg.get("agent") or {}
try:
from hermes_cli.managed_scope import is_key_managed

if is_key_managed("agent.max_turns"):
return int(agent_cfg.get("max_turns") or default)
except Exception:
pass
try:
env_max = int(os.environ.get("HERMES_TUI_MAX_TURNS", "") or 0)
if env_max > 0:
return env_max
except (TypeError, ValueError):
pass
agent_cfg = cfg.get("agent") or {}
return int(agent_cfg.get("max_turns") or cfg.get("max_turns") or default)


Expand Down