Merge branch 'main' of github.com:NousResearch/hermes-agent into feat/ink-refactor
This commit is contained in:
@@ -46,3 +46,59 @@ class TestFindDocker:
|
||||
with patch("tools.environments.docker.shutil.which", return_value=None):
|
||||
second = docker_mod.find_docker()
|
||||
assert first == second == "/usr/local/bin/docker"
|
||||
|
||||
def test_env_var_override_takes_precedence(self, tmp_path):
|
||||
"""HERMES_DOCKER_BINARY overrides PATH and known-location discovery."""
|
||||
fake_binary = tmp_path / "podman"
|
||||
fake_binary.write_text("#!/bin/sh\n")
|
||||
fake_binary.chmod(0o755)
|
||||
|
||||
with patch.dict(os.environ, {"HERMES_DOCKER_BINARY": str(fake_binary)}), \
|
||||
patch("tools.environments.docker.shutil.which", return_value="/usr/bin/docker"):
|
||||
result = docker_mod.find_docker()
|
||||
assert result == str(fake_binary)
|
||||
|
||||
def test_env_var_override_ignored_if_not_executable(self, tmp_path):
|
||||
"""Non-executable HERMES_DOCKER_BINARY falls through to normal discovery."""
|
||||
fake_binary = tmp_path / "podman"
|
||||
fake_binary.write_text("#!/bin/sh\n")
|
||||
fake_binary.chmod(0o644) # not executable
|
||||
|
||||
with patch.dict(os.environ, {"HERMES_DOCKER_BINARY": str(fake_binary)}), \
|
||||
patch("tools.environments.docker.shutil.which", return_value="/usr/bin/docker"):
|
||||
result = docker_mod.find_docker()
|
||||
assert result == "/usr/bin/docker"
|
||||
|
||||
def test_env_var_override_ignored_if_nonexistent(self):
|
||||
"""Non-existent HERMES_DOCKER_BINARY path falls through."""
|
||||
with patch.dict(os.environ, {"HERMES_DOCKER_BINARY": "/nonexistent/podman"}), \
|
||||
patch("tools.environments.docker.shutil.which", return_value="/usr/bin/docker"):
|
||||
result = docker_mod.find_docker()
|
||||
assert result == "/usr/bin/docker"
|
||||
|
||||
def test_podman_on_path_used_when_docker_missing(self):
|
||||
"""When docker is not on PATH, podman is tried next."""
|
||||
def which_side_effect(name):
|
||||
if name == "docker":
|
||||
return None
|
||||
if name == "podman":
|
||||
return "/usr/bin/podman"
|
||||
return None
|
||||
|
||||
with patch("tools.environments.docker.shutil.which", side_effect=which_side_effect), \
|
||||
patch("tools.environments.docker._DOCKER_SEARCH_PATHS", []):
|
||||
result = docker_mod.find_docker()
|
||||
assert result == "/usr/bin/podman"
|
||||
|
||||
def test_docker_preferred_over_podman(self):
|
||||
"""When both docker and podman are on PATH, docker wins."""
|
||||
def which_side_effect(name):
|
||||
if name == "docker":
|
||||
return "/usr/bin/docker"
|
||||
if name == "podman":
|
||||
return "/usr/bin/podman"
|
||||
return None
|
||||
|
||||
with patch("tools.environments.docker.shutil.which", side_effect=which_side_effect):
|
||||
result = docker_mod.find_docker()
|
||||
assert result == "/usr/bin/docker"
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
import json
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from tools.registry import ToolRegistry
|
||||
from tools.registry import ToolRegistry, discover_builtin_tools
|
||||
|
||||
|
||||
def _dummy_handler(args, **kwargs):
|
||||
@@ -286,6 +288,74 @@ class TestCheckFnExceptionHandling:
|
||||
assert any(u["name"] == "crashes" for u in unavailable)
|
||||
|
||||
|
||||
class TestBuiltinDiscovery:
|
||||
def test_matches_previous_manual_builtin_tool_set(self):
|
||||
expected = {
|
||||
"tools.browser_tool",
|
||||
"tools.clarify_tool",
|
||||
"tools.code_execution_tool",
|
||||
"tools.cronjob_tools",
|
||||
"tools.delegate_tool",
|
||||
"tools.file_tools",
|
||||
"tools.homeassistant_tool",
|
||||
"tools.image_generation_tool",
|
||||
"tools.memory_tool",
|
||||
"tools.mixture_of_agents_tool",
|
||||
"tools.process_registry",
|
||||
"tools.rl_training_tool",
|
||||
"tools.send_message_tool",
|
||||
"tools.session_search_tool",
|
||||
"tools.skill_manager_tool",
|
||||
"tools.skills_tool",
|
||||
"tools.terminal_tool",
|
||||
"tools.todo_tool",
|
||||
"tools.tts_tool",
|
||||
"tools.vision_tools",
|
||||
"tools.web_tools",
|
||||
}
|
||||
|
||||
with patch("tools.registry.importlib.import_module"):
|
||||
imported = discover_builtin_tools(Path(__file__).resolve().parents[2] / "tools")
|
||||
|
||||
assert set(imported) == expected
|
||||
|
||||
def test_imports_only_self_registering_modules(self, tmp_path):
|
||||
tools_dir = tmp_path / "tools"
|
||||
tools_dir.mkdir()
|
||||
(tools_dir / "__init__.py").write_text("", encoding="utf-8")
|
||||
(tools_dir / "registry.py").write_text("", encoding="utf-8")
|
||||
(tools_dir / "alpha.py").write_text(
|
||||
"from tools.registry import registry\nregistry.register(name='alpha', toolset='x', schema={}, handler=lambda *_a, **_k: '{}')\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(tools_dir / "beta.py").write_text("VALUE = 1\n", encoding="utf-8")
|
||||
|
||||
with patch("tools.registry.importlib.import_module") as mock_import:
|
||||
imported = discover_builtin_tools(tools_dir)
|
||||
|
||||
assert imported == ["tools.alpha"]
|
||||
mock_import.assert_called_once_with("tools.alpha")
|
||||
|
||||
def test_skips_mcp_tool_even_if_it_registers(self, tmp_path):
|
||||
tools_dir = tmp_path / "tools"
|
||||
tools_dir.mkdir()
|
||||
(tools_dir / "__init__.py").write_text("", encoding="utf-8")
|
||||
(tools_dir / "mcp_tool.py").write_text(
|
||||
"from tools.registry import registry\nregistry.register(name='mcp_alpha', toolset='mcp-test', schema={}, handler=lambda *_a, **_k: '{}')\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(tools_dir / "alpha.py").write_text(
|
||||
"from tools.registry import registry\nregistry.register(name='alpha', toolset='x', schema={}, handler=lambda *_a, **_k: '{}')\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with patch("tools.registry.importlib.import_module") as mock_import:
|
||||
imported = discover_builtin_tools(tools_dir)
|
||||
|
||||
assert imported == ["tools.alpha"]
|
||||
mock_import.assert_called_once_with("tools.alpha")
|
||||
|
||||
|
||||
class TestEmojiMetadata:
|
||||
"""Verify per-tool emoji registration and lookup."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user