/ tests / gateway / test_api_server_toolset.py
test_api_server_toolset.py
  1  """Tests for hermes-api-server toolset and API server tool availability."""
  2  import os
  3  import json
  4  from unittest.mock import patch, MagicMock
  5  
  6  import pytest
  7  
  8  from toolsets import resolve_toolset, get_toolset, validate_toolset
  9  
 10  
 11  class TestHermesApiServerToolset:
 12      """Tests for the hermes-api-server toolset definition."""
 13  
 14      def test_toolset_exists(self):
 15          ts = get_toolset("hermes-api-server")
 16          assert ts is not None
 17  
 18      def test_toolset_validates(self):
 19          assert validate_toolset("hermes-api-server")
 20  
 21      def test_toolset_includes_web_tools(self):
 22          tools = resolve_toolset("hermes-api-server")
 23          assert "web_search" in tools
 24          assert "web_extract" in tools
 25  
 26      def test_toolset_includes_core_tools(self):
 27          tools = resolve_toolset("hermes-api-server")
 28          expected = [
 29              "terminal", "process",
 30              "read_file", "write_file", "patch", "search_files",
 31              "vision_analyze", "image_generate",
 32              "execute_code", "delegate_task",
 33              "todo", "memory", "session_search", "cronjob",
 34          ]
 35          for tool in expected:
 36              assert tool in tools, f"Missing expected tool: {tool}"
 37  
 38      def test_toolset_includes_browser_tools(self):
 39          tools = resolve_toolset("hermes-api-server")
 40          for tool in ["browser_navigate", "browser_snapshot", "browser_click",
 41                        "browser_type", "browser_scroll", "browser_back",
 42                        "browser_press"]:
 43              assert tool in tools, f"Missing browser tool: {tool}"
 44  
 45      def test_toolset_includes_homeassistant_tools(self):
 46          tools = resolve_toolset("hermes-api-server")
 47          for tool in ["ha_list_entities", "ha_get_state", "ha_list_services", "ha_call_service"]:
 48              assert tool in tools, f"Missing HA tool: {tool}"
 49  
 50      def test_toolset_excludes_clarify(self):
 51          tools = resolve_toolset("hermes-api-server")
 52          assert "clarify" not in tools
 53  
 54      def test_toolset_excludes_send_message(self):
 55          tools = resolve_toolset("hermes-api-server")
 56          assert "send_message" not in tools
 57  
 58      def test_toolset_excludes_text_to_speech(self):
 59          tools = resolve_toolset("hermes-api-server")
 60          assert "text_to_speech" not in tools
 61  
 62  
 63  class TestApiServerPlatformConfig:
 64      def test_platforms_dict_includes_api_server(self):
 65          from hermes_cli.tools_config import PLATFORMS
 66          assert "api_server" in PLATFORMS
 67          assert PLATFORMS["api_server"]["default_toolset"] == "hermes-api-server"
 68  
 69  
 70  class TestApiServerAdapterToolset:
 71      @patch("gateway.platforms.api_server.AIOHTTP_AVAILABLE", True)
 72      def test_create_agent_reads_config_toolsets(self):
 73          """API server resolves toolsets from config like all other platforms."""
 74          from gateway.platforms.api_server import APIServerAdapter
 75          from gateway.config import PlatformConfig
 76  
 77          adapter = APIServerAdapter(PlatformConfig())
 78  
 79          with patch("gateway.run._resolve_runtime_agent_kwargs") as mock_kwargs, \
 80               patch("gateway.run._resolve_gateway_model") as mock_model, \
 81               patch("gateway.run._load_gateway_config") as mock_config, \
 82               patch("run_agent.AIAgent") as mock_agent_cls:
 83  
 84              mock_kwargs.return_value = {"api_key": "test-key", "base_url": None,
 85                                          "provider": None, "api_mode": None,
 86                                          "command": None, "args": []}
 87              mock_model.return_value = "test/model"
 88              # No platform_toolsets override — should fall back to hermes-api-server default
 89              mock_config.return_value = {}
 90              mock_agent_cls.return_value = MagicMock()
 91  
 92              adapter._create_agent()
 93  
 94              mock_agent_cls.assert_called_once()
 95              call_kwargs = mock_agent_cls.call_args
 96              toolsets = call_kwargs.kwargs.get("enabled_toolsets")
 97              assert isinstance(toolsets, list)
 98              assert len(toolsets) > 0
 99              assert call_kwargs.kwargs.get("platform") == "api_server"
100  
101      @patch("gateway.platforms.api_server.AIOHTTP_AVAILABLE", True)
102      def test_create_agent_respects_config_override(self):
103          """User can override API server toolsets via platform_toolsets in config.yaml."""
104          from gateway.platforms.api_server import APIServerAdapter
105          from gateway.config import PlatformConfig
106  
107          adapter = APIServerAdapter(PlatformConfig())
108  
109          with patch("gateway.run._resolve_runtime_agent_kwargs") as mock_kwargs, \
110               patch("gateway.run._resolve_gateway_model") as mock_model, \
111               patch("gateway.run._load_gateway_config") as mock_config, \
112               patch("run_agent.AIAgent") as mock_agent_cls:
113  
114              mock_kwargs.return_value = {"api_key": "test-key", "base_url": None,
115                                          "provider": None, "api_mode": None,
116                                          "command": None, "args": []}
117              mock_model.return_value = "test/model"
118              # User overrides with just web and terminal
119              mock_config.return_value = {
120                  "platform_toolsets": {"api_server": ["web", "terminal"]}
121              }
122              mock_agent_cls.return_value = MagicMock()
123  
124              adapter._create_agent()
125  
126              mock_agent_cls.assert_called_once()
127              call_kwargs = mock_agent_cls.call_args
128              toolsets = call_kwargs.kwargs.get("enabled_toolsets")
129              assert sorted(toolsets) == ["terminal", "web"]