mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
Second, deeper pass over tools/gateway/hermes_cli plus first pass over the trees wave 1 missed (acp, acp_adapter, skills, computer_use, docker, dashboard, conformance, monitoring, secret_sources, hermes_state, providers). Same rubric as wave 1 (AGENTS.md test policy); security, alternation/caching invariants, issue-number regressions, and E2E kept. Real test-quality fixes found and rooted out along the way: - tests/tools/test_command_guards.py made real auxiliary-LLM HTTPS calls (DEFAULT_CONFIG smart-approval leaked in) — pinned approval mode=manual via autouse fixture: 17.4s → 0.4s. - test_model_switch_custom_providers.py / test_user_providers_model_switch.py silently probed live provider catalogs (~2s/test) — stubbed cached_provider_model_ids/provider_model_ids/fetch_api_models. - test_telegram_noise_filter.py: 15-platform copy-paste matrix over shared gateway.run logic → 3 representative platforms (55s → 3.9s). - test_gateway_shutdown.py: stop()'s 5s interrupt-deadline loop spun on MagicMock agents — interrupt.side_effect now clears _running_agents (22s → 1.0s). - test_gateway_inactivity_timeout.py poll-harness timings shrunk 3-5x (24s → 1.1s); test_mcp_stability.py backoff/SIGTERM-grace sleeps patched (15.4s → 2.5s); test_async_delegation.py negative-drain wait 5s → 0.5s. - test_telegram_init_deadline.py: loop-block margin restored to 1.0s with rationale comment — the watchdog-dump assertion needs the loop blocked well past deadline+grace under parallel load (flaked once in the 40-worker verification run at a 0.2s margin). Verification: full hermetic suite via scripts/run_tests.sh — 2,438 files, 21,718 tests passed, 0 failed, 293.9s wall. Suite totals vs original baseline: 46,820 → 19,757 test functions (−57.8%), wall 583.5s → 293.9s (−50%), subprocess CPU 13,564s → 11,623s.
82 lines
3.5 KiB
Python
82 lines
3.5 KiB
Python
"""Tests for hermes-api-server toolset and API server tool availability."""
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
|
|
from toolsets import resolve_toolset, get_toolset, validate_toolset
|
|
|
|
|
|
class TestHermesApiServerToolset:
|
|
"""Tests for the hermes-api-server toolset definition."""
|
|
|
|
|
|
def test_toolset_includes_web_tools(self):
|
|
tools = resolve_toolset("hermes-api-server")
|
|
assert "web_search" in tools
|
|
assert "web_extract" in tools
|
|
|
|
def test_toolset_includes_core_tools(self):
|
|
tools = resolve_toolset("hermes-api-server")
|
|
expected = [
|
|
"terminal", "process",
|
|
"read_file", "write_file", "patch", "search_files",
|
|
"vision_analyze", "image_generate",
|
|
"execute_code", "delegate_task",
|
|
"todo", "memory", "session_search", "cronjob",
|
|
]
|
|
for tool in expected:
|
|
assert tool in tools, f"Missing expected tool: {tool}"
|
|
|
|
def test_toolset_includes_browser_tools(self):
|
|
tools = resolve_toolset("hermes-api-server")
|
|
for tool in ["browser_navigate", "browser_snapshot", "browser_click",
|
|
"browser_type", "browser_scroll", "browser_back",
|
|
"browser_press"]:
|
|
assert tool in tools, f"Missing browser tool: {tool}"
|
|
|
|
|
|
class TestApiServerPlatformConfig:
|
|
|
|
def test_default_api_server_includes_terminal_toolset(self):
|
|
"""Regression #49622: desktop-only read_terminal is registered into the
|
|
'terminal' toolset (ships in-repo), so resolve_toolset('terminal') grows
|
|
to include it after discovery. read_terminal is NOT in the
|
|
hermes-api-server composite, so the old all-tools subset test dropped
|
|
'terminal' entirely. Its static membership (terminal, process) IS in the
|
|
composite, so it must stay enabled."""
|
|
from tools.registry import discover_builtin_tools
|
|
from hermes_cli.tools_config import _get_platform_tools
|
|
discover_builtin_tools()
|
|
assert "terminal" in _get_platform_tools({}, "api_server")
|
|
|
|
|
|
class TestApiServerAdapterToolset:
|
|
@patch("gateway.platforms.api_server.AIOHTTP_AVAILABLE", True)
|
|
def test_create_agent_reads_config_toolsets(self):
|
|
"""API server resolves toolsets from config like all other platforms."""
|
|
from gateway.platforms.api_server import APIServerAdapter
|
|
from gateway.config import PlatformConfig
|
|
|
|
adapter = APIServerAdapter(PlatformConfig())
|
|
|
|
with patch("gateway.run._resolve_runtime_agent_kwargs") as mock_kwargs, \
|
|
patch("gateway.run._resolve_gateway_model") as mock_model, \
|
|
patch("gateway.run._load_gateway_config") as mock_config, \
|
|
patch("run_agent.AIAgent") as mock_agent_cls:
|
|
|
|
mock_kwargs.return_value = {"api_key": "test-key", "base_url": None,
|
|
"provider": None, "api_mode": None,
|
|
"command": None, "args": []}
|
|
mock_model.return_value = "test/model"
|
|
# No platform_toolsets override — should fall back to hermes-api-server default
|
|
mock_config.return_value = {}
|
|
mock_agent_cls.return_value = MagicMock()
|
|
|
|
adapter._create_agent()
|
|
|
|
mock_agent_cls.assert_called_once()
|
|
call_kwargs = mock_agent_cls.call_args
|
|
toolsets = call_kwargs.kwargs.get("enabled_toolsets")
|
|
assert isinstance(toolsets, list)
|
|
assert len(toolsets) > 0
|
|
assert call_kwargs.kwargs.get("platform") == "api_server"
|
|
|