Files
konstruct/tests/unit/test_tool_registry.py
Adolfo Delorenzo 420294b8fe test(02-02): add failing tool registry and executor unit tests
- Tests for BUILTIN_TOOLS (4 tools present, correct fields, confirmation flags)
- Tests for get_tools_for_agent filtering and to_litellm_format conversion
- Tests for execute_tool: valid args, invalid args, unknown tool, confirmation flow
- Tests for audit logger called on every invocation
2026-03-23 14:51:42 -06:00

150 lines
5.1 KiB
Python

"""
Unit tests for the tool registry.
Tests:
- BUILTIN_TOOLS contains all 4 expected tools
- get_tools_for_agent filters correctly based on agent.tool_assignments
- to_litellm_format produces valid OpenAI function-calling schema
- ToolDefinition model validation
"""
from __future__ import annotations
import uuid
from unittest.mock import MagicMock
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def make_agent(tool_list: list[str]) -> MagicMock:
"""Create a mock Agent with tool_assignments set."""
agent = MagicMock()
agent.id = uuid.uuid4()
agent.tool_assignments = tool_list
return agent
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
class TestBuiltinTools:
"""BUILTIN_TOOLS registry contains the correct tool definitions."""
def test_all_four_tools_present(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
assert "web_search" in BUILTIN_TOOLS
assert "kb_search" in BUILTIN_TOOLS
assert "http_request" in BUILTIN_TOOLS
assert "calendar_lookup" in BUILTIN_TOOLS
def test_tool_definitions_have_required_fields(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
for name, tool in BUILTIN_TOOLS.items():
assert tool.name == name, f"Tool name mismatch for {name}"
assert tool.description, f"Tool {name} missing description"
assert isinstance(tool.parameters, dict), f"Tool {name} parameters must be dict"
assert "type" in tool.parameters, f"Tool {name} parameters missing 'type' key"
assert tool.handler is not None, f"Tool {name} has no handler"
def test_http_request_requires_confirmation(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
assert BUILTIN_TOOLS["http_request"].requires_confirmation is True
def test_web_search_no_confirmation(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
assert BUILTIN_TOOLS["web_search"].requires_confirmation is False
def test_kb_search_no_confirmation(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
assert BUILTIN_TOOLS["kb_search"].requires_confirmation is False
def test_calendar_lookup_no_confirmation(self):
from orchestrator.tools.registry import BUILTIN_TOOLS
assert BUILTIN_TOOLS["calendar_lookup"].requires_confirmation is False
class TestGetToolsForAgent:
"""get_tools_for_agent filters BUILTIN_TOOLS by agent's tool_assignments list."""
def test_filters_to_assigned_tools(self):
from orchestrator.tools.registry import get_tools_for_agent
agent = make_agent(["web_search", "kb_search"])
result = get_tools_for_agent(agent)
assert set(result.keys()) == {"web_search", "kb_search"}
def test_empty_tool_list_returns_empty(self):
from orchestrator.tools.registry import get_tools_for_agent
agent = make_agent([])
result = get_tools_for_agent(agent)
assert result == {}
def test_unknown_tools_ignored_silently(self):
"""Tools in agent.tool_assignments that don't exist in BUILTIN_TOOLS are skipped."""
from orchestrator.tools.registry import get_tools_for_agent
agent = make_agent(["web_search", "nonexistent_tool"])
result = get_tools_for_agent(agent)
assert "web_search" in result
assert "nonexistent_tool" not in result
def test_all_tools_accessible(self):
from orchestrator.tools.registry import BUILTIN_TOOLS, get_tools_for_agent
agent = make_agent(list(BUILTIN_TOOLS.keys()))
result = get_tools_for_agent(agent)
assert set(result.keys()) == set(BUILTIN_TOOLS.keys())
class TestToLitellmFormat:
"""to_litellm_format converts tool definitions to OpenAI function-calling schema."""
def test_returns_list_of_dicts(self):
from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format
result = to_litellm_format({"web_search": BUILTIN_TOOLS["web_search"]})
assert isinstance(result, list)
assert len(result) == 1
def test_openai_schema_structure(self):
"""Each entry must have type='function' and a nested function object."""
from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format
result = to_litellm_format({"web_search": BUILTIN_TOOLS["web_search"]})
entry = result[0]
assert entry["type"] == "function"
assert "function" in entry
func = entry["function"]
assert func["name"] == "web_search"
assert "description" in func
assert "parameters" in func
def test_empty_tools_returns_empty_list(self):
from orchestrator.tools.registry import to_litellm_format
assert to_litellm_format({}) == []
def test_multiple_tools_converted(self):
from orchestrator.tools.registry import BUILTIN_TOOLS, to_litellm_format
result = to_litellm_format(BUILTIN_TOOLS)
assert len(result) == 4