| | import json |
| | from abc import ABC, abstractmethod |
| | from typing import Any, Dict, Optional, Union |
| |
|
| | from pydantic import BaseModel, Field |
| |
|
| | from app.utils.logger import logger |
| |
|
| |
|
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | class ToolResult(BaseModel): |
| | """Represents the result of a tool execution.""" |
| |
|
| | output: Any = Field(default=None) |
| | error: Optional[str] = Field(default=None) |
| | base64_image: Optional[str] = Field(default=None) |
| | system: Optional[str] = Field(default=None) |
| |
|
| | class Config: |
| | arbitrary_types_allowed = True |
| |
|
| | def __bool__(self): |
| | return any(getattr(self, field) for field in self.__fields__) |
| |
|
| | def __add__(self, other: "ToolResult"): |
| | def combine_fields( |
| | field: Optional[str], other_field: Optional[str], concatenate: bool = True |
| | ): |
| | if field and other_field: |
| | if concatenate: |
| | return field + other_field |
| | raise ValueError("Cannot combine tool results") |
| | return field or other_field |
| |
|
| | return ToolResult( |
| | output=combine_fields(self.output, other.output), |
| | error=combine_fields(self.error, other.error), |
| | base64_image=combine_fields(self.base64_image, other.base64_image, False), |
| | system=combine_fields(self.system, other.system), |
| | ) |
| |
|
| | def __str__(self): |
| | return f"Error: {self.error}" if self.error else self.output |
| |
|
| | def replace(self, **kwargs): |
| | """Returns a new ToolResult with the given fields replaced.""" |
| | |
| | return type(self)(**{**self.dict(), **kwargs}) |
| |
|
| |
|
| | class BaseTool(ABC, BaseModel): |
| | """Consolidated base class for all tools combining BaseModel and Tool functionality. |
| | |
| | Provides: |
| | - Pydantic model validation |
| | - Schema registration |
| | - Standardized result handling |
| | - Abstract execution interface |
| | |
| | Attributes: |
| | name (str): Tool name |
| | description (str): Tool description |
| | parameters (dict): Tool parameters schema |
| | _schemas (Dict[str, List[ToolSchema]]): Registered method schemas |
| | """ |
| |
|
| | name: str |
| | description: str |
| | parameters: Optional[dict] = None |
| | |
| |
|
| | class Config: |
| | arbitrary_types_allowed = True |
| | underscore_attrs_are_private = False |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | async def __call__(self, **kwargs) -> Any: |
| | """Execute the tool with given parameters.""" |
| | return await self.execute(**kwargs) |
| |
|
| | @abstractmethod |
| | async def execute(self, **kwargs) -> Any: |
| | """Execute the tool with given parameters.""" |
| |
|
| | def to_param(self) -> Dict: |
| | """Convert tool to function call format. |
| | |
| | Returns: |
| | Dictionary with tool metadata in OpenAI function calling format |
| | """ |
| | return { |
| | "type": "function", |
| | "function": { |
| | "name": self.name, |
| | "description": self.description, |
| | "parameters": self.parameters, |
| | }, |
| | } |
| |
|
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | def success_response(self, data: Union[Dict[str, Any], str]) -> ToolResult: |
| | """Create a successful tool result. |
| | |
| | Args: |
| | data: Result data (dictionary or string) |
| | |
| | Returns: |
| | ToolResult with success=True and formatted output |
| | """ |
| | if isinstance(data, str): |
| | text = data |
| | else: |
| | text = json.dumps(data, indent=2) |
| | logger.debug(f"Created success response for {self.__class__.__name__}") |
| | return ToolResult(output=text) |
| |
|
| | def fail_response(self, msg: str) -> ToolResult: |
| | """Create a failed tool result. |
| | |
| | Args: |
| | msg: Error message describing the failure |
| | |
| | Returns: |
| | ToolResult with success=False and error message |
| | """ |
| | logger.debug(f"Tool {self.__class__.__name__} returned failed result: {msg}") |
| | return ToolResult(error=msg) |
| |
|
| |
|
| | class CLIResult(ToolResult): |
| | """A ToolResult that can be rendered as a CLI output.""" |
| |
|
| |
|
| | class ToolFailure(ToolResult): |
| | """A ToolResult that represents a failure.""" |
| |
|