Protocol tests (16): - AgentRequest/AgentResponse serialization - DelegationIntent and DelegationReason validation - CoordinationResult aggregation - Error type tests Coordination tests (14): - Engine initialization and agent availability - Delegation execution (success, error, timeout) - Multi-intent coordination - Streaming delegation Librarian tests (42): - Library-desk client (all endpoints) - Wiki operations (search, get, create, update) - Smart-create with HybridRAG - Capability registration - Response model validation Total: 72 new tests, all passing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
257 lines
7.6 KiB
Python
257 lines
7.6 KiB
Python
"""
|
|
Tests for agent communication protocol.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from src.agents.protocol import (
|
|
AgentError,
|
|
AgentRequest,
|
|
AgentResponse,
|
|
AgentTimeoutError,
|
|
AgentUnavailableError,
|
|
CoordinationResult,
|
|
DelegationIntent,
|
|
DelegationReason,
|
|
ToolCallRecord,
|
|
)
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestAgentRequest:
|
|
"""Tests for AgentRequest model."""
|
|
|
|
def test_basic_request(self):
|
|
"""Test creating a basic agent request."""
|
|
request = AgentRequest(task="Find information about Docker")
|
|
|
|
assert request.task == "Find information about Docker"
|
|
assert request.context == ""
|
|
assert request.timeout_seconds == 60
|
|
|
|
def test_request_with_context(self):
|
|
"""Test request with additional context."""
|
|
request = AgentRequest(
|
|
task="Find Docker networking docs",
|
|
context="User is setting up a homelab",
|
|
delegation_reason=DelegationReason.DOMAIN_EXPERTISE,
|
|
)
|
|
|
|
assert request.task == "Find Docker networking docs"
|
|
assert request.context == "User is setting up a homelab"
|
|
assert request.delegation_reason == DelegationReason.DOMAIN_EXPERTISE
|
|
|
|
def test_request_serialization(self):
|
|
"""Test request can be serialized to dict."""
|
|
request = AgentRequest(
|
|
task="Research task",
|
|
context="Some context",
|
|
)
|
|
|
|
data = request.model_dump()
|
|
|
|
assert data["task"] == "Research task"
|
|
assert data["context"] == "Some context"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestAgentResponse:
|
|
"""Tests for AgentResponse model."""
|
|
|
|
def test_successful_response(self):
|
|
"""Test creating a successful response."""
|
|
response = AgentResponse(
|
|
success=True,
|
|
result="Here are the findings...",
|
|
reasoning="Searched wiki and found relevant docs",
|
|
duration_ms=1500,
|
|
)
|
|
|
|
assert response.success is True
|
|
assert response.result == "Here are the findings..."
|
|
assert response.reasoning == "Searched wiki and found relevant docs"
|
|
assert response.duration_ms == 1500
|
|
assert response.error_message is None
|
|
|
|
def test_failed_response(self):
|
|
"""Test creating a failed response."""
|
|
response = AgentResponse(
|
|
success=False,
|
|
result="",
|
|
error_message="Connection timeout",
|
|
duration_ms=30000,
|
|
)
|
|
|
|
assert response.success is False
|
|
assert response.result == ""
|
|
assert response.error_message == "Connection timeout"
|
|
|
|
def test_response_with_tool_calls(self):
|
|
"""Test response tracking tool calls."""
|
|
tool_call = ToolCallRecord(
|
|
tool_name="hybrid_search",
|
|
arguments={"query": "Docker networking"},
|
|
result="Found 5 results",
|
|
duration_ms=500,
|
|
)
|
|
|
|
response = AgentResponse(
|
|
success=True,
|
|
result="Based on search...",
|
|
tool_calls=[tool_call],
|
|
)
|
|
|
|
assert len(response.tool_calls) == 1
|
|
assert response.tool_calls[0].tool_name == "hybrid_search"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestDelegationIntent:
|
|
"""Tests for DelegationIntent model."""
|
|
|
|
def test_basic_intent(self):
|
|
"""Test creating a basic delegation intent."""
|
|
intent = DelegationIntent(
|
|
target_agent="librarian",
|
|
task="Research Docker networking",
|
|
reason=DelegationReason.DOMAIN_EXPERTISE,
|
|
expected_outcome="Documentation and examples",
|
|
)
|
|
|
|
assert intent.target_agent == "librarian"
|
|
assert intent.task == "Research Docker networking"
|
|
assert intent.reason == DelegationReason.DOMAIN_EXPERTISE
|
|
assert intent.priority == 1 # Default
|
|
|
|
def test_intent_with_priority(self):
|
|
"""Test intent with custom priority."""
|
|
intent = DelegationIntent(
|
|
target_agent="librarian",
|
|
task="Urgent research",
|
|
reason=DelegationReason.RESOURCE_EFFICIENCY,
|
|
expected_outcome="Quick answer",
|
|
priority=1,
|
|
)
|
|
|
|
assert intent.priority == 1
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestDelegationReason:
|
|
"""Tests for DelegationReason enum."""
|
|
|
|
def test_all_reasons_have_values(self):
|
|
"""Test all delegation reasons are defined."""
|
|
reasons = list(DelegationReason)
|
|
|
|
assert DelegationReason.DOMAIN_EXPERTISE in reasons
|
|
assert DelegationReason.TOOL_ACCESS in reasons
|
|
assert DelegationReason.RESOURCE_EFFICIENCY in reasons
|
|
assert DelegationReason.USER_PREFERENCE in reasons
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestCoordinationResult:
|
|
"""Tests for CoordinationResult model."""
|
|
|
|
def test_single_agent_result(self):
|
|
"""Test coordination with single agent."""
|
|
agent_response = AgentResponse(
|
|
success=True,
|
|
result="Research findings",
|
|
duration_ms=1000,
|
|
)
|
|
|
|
intent = DelegationIntent(
|
|
target_agent="librarian",
|
|
task="Research task",
|
|
reason=DelegationReason.DOMAIN_EXPERTISE,
|
|
expected_outcome="Findings",
|
|
)
|
|
|
|
result = CoordinationResult(
|
|
final_response="Research findings",
|
|
agent_responses={"librarian": agent_response},
|
|
delegation_intents=[intent],
|
|
total_duration_ms=1200,
|
|
agents_consulted=["librarian"],
|
|
)
|
|
|
|
assert result.final_response == "Research findings"
|
|
assert len(result.agent_responses) == 1
|
|
assert result.agents_consulted == ["librarian"]
|
|
|
|
def test_empty_result(self):
|
|
"""Test coordination with no delegations."""
|
|
result = CoordinationResult(
|
|
final_response="",
|
|
agent_responses={},
|
|
delegation_intents=[],
|
|
total_duration_ms=0,
|
|
agents_consulted=[],
|
|
)
|
|
|
|
assert result.final_response == ""
|
|
assert len(result.agents_consulted) == 0
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestAgentErrors:
|
|
"""Tests for agent error types."""
|
|
|
|
def test_agent_error(self):
|
|
"""Test base AgentError."""
|
|
error = AgentError("Something went wrong")
|
|
|
|
assert "Something went wrong" in str(error)
|
|
assert error.agent_name == "unknown"
|
|
|
|
def test_agent_timeout_error(self):
|
|
"""Test AgentTimeoutError."""
|
|
error = AgentTimeoutError(
|
|
"Timed out after 60s",
|
|
agent_name="librarian",
|
|
)
|
|
|
|
assert "Timed out" in str(error)
|
|
assert error.agent_name == "librarian"
|
|
|
|
def test_agent_unavailable_error(self):
|
|
"""Test AgentUnavailableError."""
|
|
error = AgentUnavailableError(
|
|
"Agent not registered",
|
|
agent_name="unknown_agent",
|
|
)
|
|
|
|
assert "not registered" in str(error)
|
|
assert error.agent_name == "unknown_agent"
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestToolCallRecord:
|
|
"""Tests for ToolCallRecord model."""
|
|
|
|
def test_tool_call_record(self):
|
|
"""Test creating a tool call record."""
|
|
record = ToolCallRecord(
|
|
tool_name="semantic_search",
|
|
arguments={"query": "networking concepts", "limit": 10},
|
|
result="Found 10 relevant documents",
|
|
duration_ms=250,
|
|
)
|
|
|
|
assert record.tool_name == "semantic_search"
|
|
assert record.arguments["query"] == "networking concepts"
|
|
assert record.duration_ms == 250
|
|
|
|
def test_tool_call_with_empty_result(self):
|
|
"""Test tool call with empty result."""
|
|
record = ToolCallRecord(
|
|
tool_name="query_graph",
|
|
arguments={"cypher": "MATCH (n) RETURN n"},
|
|
result="",
|
|
duration_ms=100,
|
|
)
|
|
|
|
assert record.result == ""
|