| """ |
| Agent Helper Utilities for Testing |
| |
| This module provides utility functions for testing AI agent behavior and tool invocations. |
| """ |
|
|
| from typing import Dict, Any, Optional, List |
| import asyncio |
|
|
| from src.services.agent_service import AgentService |
| from src.tools.mcp_server import MCPContext |
|
|
|
|
| async def invoke_agent_with_message( |
| user_id: int, |
| message: str, |
| conversation_history: Optional[List[Dict[str, str]]] = None |
| ) -> Dict[str, Any]: |
| """ |
| Invoke the AI agent with a message and return the response. |
| |
| Args: |
| user_id: User ID for context |
| message: User message to process |
| conversation_history: Optional conversation history |
| |
| Returns: |
| Agent response dict with content, tool_calls, etc. |
| """ |
| agent_service = AgentService(user_id=user_id) |
|
|
| if conversation_history is None: |
| conversation_history = [] |
|
|
| response = await agent_service.process_message( |
| message=message, |
| conversation_history=conversation_history |
| ) |
|
|
| return response |
|
|
|
|
| async def invoke_tool_directly( |
| context: MCPContext, |
| tool_name: str, |
| **kwargs |
| ) -> Dict[str, Any]: |
| """ |
| Invoke an MCP tool directly with given parameters. |
| |
| Args: |
| context: MCPContext with user_id pre-bound |
| tool_name: Name of tool to invoke |
| **kwargs: Tool parameters |
| |
| Returns: |
| Tool execution result |
| """ |
| from src.tools import mcp_server |
|
|
| tool_func = mcp_server.get_tool(tool_name) |
|
|
| if not tool_func: |
| raise ValueError(f"Tool '{tool_name}' not found") |
|
|
| result = await tool_func(context, **kwargs) |
| return result |
|
|
|
|
| def extract_tool_calls(agent_response: Dict[str, Any]) -> List[Dict[str, Any]]: |
| """ |
| Extract tool calls from agent response. |
| |
| Args: |
| agent_response: Agent response dict |
| |
| Returns: |
| List of tool call dicts |
| """ |
| return agent_response.get("tool_calls", []) |
|
|
|
|
| def assert_tool_called(agent_response: Dict[str, Any], tool_name: str): |
| """ |
| Assert that a specific tool was called in the agent response. |
| |
| Args: |
| agent_response: Agent response dict |
| tool_name: Expected tool name |
| |
| Raises: |
| AssertionError: If tool was not called |
| """ |
| tool_calls = extract_tool_calls(agent_response) |
|
|
| tool_names = [tc.get("tool") for tc in tool_calls] |
|
|
| assert tool_name in tool_names, f"Expected tool '{tool_name}' to be called, but got: {tool_names}" |
|
|
|
|
| def assert_tool_succeeded(tool_result: Dict[str, Any]): |
| """ |
| Assert that a tool execution succeeded. |
| |
| Args: |
| tool_result: Tool execution result |
| |
| Raises: |
| AssertionError: If tool execution failed |
| """ |
| status = tool_result.get("status") |
|
|
| if status == "error": |
| error_msg = tool_result.get("error", "Unknown error") |
| raise AssertionError(f"Tool execution failed: {error_msg}") |
|
|
| assert status == "success", f"Expected status 'success', got '{status}'" |
|
|
|
|
| def assert_tool_failed(tool_result: Dict[str, Any], expected_error: Optional[str] = None): |
| """ |
| Assert that a tool execution failed with expected error. |
| |
| Args: |
| tool_result: Tool execution result |
| expected_error: Optional expected error message substring |
| |
| Raises: |
| AssertionError: If tool execution succeeded or error doesn't match |
| """ |
| status = tool_result.get("status") |
|
|
| assert status == "error", f"Expected status 'error', got '{status}'" |
|
|
| if expected_error: |
| error_msg = tool_result.get("error", "") |
| assert expected_error in error_msg, f"Expected error containing '{expected_error}', got '{error_msg}'" |
|
|
|
|
| def create_mock_conversation_history(messages: List[tuple]) -> List[Dict[str, str]]: |
| """ |
| Create mock conversation history for testing. |
| |
| Args: |
| messages: List of (role, content) tuples |
| |
| Returns: |
| Formatted conversation history |
| |
| Example: |
| history = create_mock_conversation_history([ |
| ("user", "Add a task to buy groceries"), |
| ("assistant", "I've added the task.") |
| ]) |
| """ |
| history = [] |
|
|
| for role, content in messages: |
| history.append({ |
| "role": role, |
| "content": content |
| }) |
|
|
| return history |
|
|
|
|
| async def test_agent_intent_recognition( |
| user_id: int, |
| message: str, |
| expected_tool: str |
| ) -> bool: |
| """ |
| Test that agent correctly recognizes user intent and selects appropriate tool. |
| |
| Args: |
| user_id: User ID for context |
| message: User message |
| expected_tool: Expected tool name to be called |
| |
| Returns: |
| True if agent selected correct tool, False otherwise |
| """ |
| response = await invoke_agent_with_message(user_id, message) |
|
|
| tool_calls = extract_tool_calls(response) |
|
|
| if not tool_calls: |
| return False |
|
|
| tool_names = [tc.get("tool") for tc in tool_calls] |
|
|
| return expected_tool in tool_names |
|
|