""" Base Tool Class All tools inherit from this class. """ from abc import ABC, abstractmethod from typing import Dict, Any, Optional from pydantic import BaseModel from loguru import logger class ToolResult: """Result from a tool execution.""" def __init__( self, success: bool, data: Any = None, error: Optional[str] = None ): self.success = success self.data = data self.error = error def to_string(self) -> str: """Convert result to string for LLM consumption.""" if self.success: if isinstance(self.data, str): return self.data elif isinstance(self.data, dict): return str(self.data) else: return str(self.data) else: return f"Error: {self.error}" class BaseTool(ABC): """ Abstract base class for all tools. Each tool must implement: - name: The tool's identifier - description: What the tool does - parameters: JSON schema for parameters - execute: The actual tool logic """ def __init__(self, config: Optional[Dict] = None): self.config = config or {} self._validate_config() @property @abstractmethod def name(self) -> str: """Tool name used in function calls.""" pass @property @abstractmethod def description(self) -> str: """Tool description shown to the LLM.""" pass @property @abstractmethod def parameters(self) -> Dict[str, Any]: """JSON schema for tool parameters.""" pass def get_definition(self) -> Dict[str, Any]: """Get the OpenAI-style tool definition.""" return { "type": "function", "function": { "name": self.name, "description": self.description, "parameters": self.parameters, } } @abstractmethod async def execute(self, **kwargs) -> ToolResult: """Execute the tool with given parameters.""" pass def _validate_config(self) -> None: """Validate tool configuration. Override in subclasses.""" pass def _log_execution(self, kwargs: Dict) -> None: """Log tool execution.""" logger.info(f"Executing tool: {self.name} with args: {kwargs}") def _log_success(self, result: Any) -> None: """Log successful execution.""" logger.debug(f"Tool {self.name} completed successfully") def _log_error(self, error: str) -> None: """Log execution error.""" logger.error(f"Tool {self.name} failed: {error}")