""" 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 == ""