suna/backend/agentpress/tool.py

132 lines
4.3 KiB
Python
Raw Normal View History

2024-10-23 09:28:12 +08:00
"""
2024-11-18 13:54:26 +08:00
Core tool system providing the foundation for creating and managing tools.
This module defines the base classes and decorators for creating tools in AgentPress:
- Tool base class for implementing tool functionality
2025-07-28 17:53:10 +08:00
- Schema decorators for OpenAPI tool definitions
2024-11-18 13:54:26 +08:00
- Result containers for standardized tool outputs
2024-10-23 09:28:12 +08:00
"""
2025-05-07 21:24:00 +08:00
from typing import Dict, Any, Union, Optional, List
2024-11-18 08:38:31 +08:00
from dataclasses import dataclass, field
2024-10-23 09:28:12 +08:00
from abc import ABC
2024-10-06 01:04:15 +08:00
import json
2024-10-23 09:28:12 +08:00
import inspect
2024-11-18 08:38:31 +08:00
from enum import Enum
2025-04-02 02:49:35 +08:00
from utils.logger import logger
2024-11-18 08:38:31 +08:00
class SchemaType(Enum):
2024-11-18 13:54:26 +08:00
"""Enumeration of supported schema types for tool definitions."""
2024-11-18 08:38:31 +08:00
OPENAPI = "openapi"
@dataclass
class ToolSchema:
2024-11-18 13:54:26 +08:00
"""Container for tool schemas with type information.
Attributes:
2025-07-28 19:13:42 +08:00
schema_type (SchemaType): Type of schema (OpenAPI)
2024-11-18 13:54:26 +08:00
schema (Dict[str, Any]): The actual schema definition
"""
2024-11-18 08:38:31 +08:00
schema_type: SchemaType
schema: Dict[str, Any]
2024-10-06 01:04:15 +08:00
@dataclass
class ToolResult:
2024-11-18 13:54:26 +08:00
"""Container for tool execution results.
Attributes:
success (bool): Whether the tool execution succeeded
output (str): Output message or error description
"""
2024-10-06 01:04:15 +08:00
success: bool
output: str
class Tool(ABC):
2024-11-18 13:54:26 +08:00
"""Abstract base class for all tools.
Provides the foundation for implementing tools with schema registration
and result handling capabilities.
Attributes:
_schemas (Dict[str, List[ToolSchema]]): Registered schemas for tool methods
Methods:
get_schemas: Get all registered tool schemas
success_response: Create a successful result
fail_response: Create a failed result
"""
2024-10-06 01:04:15 +08:00
def __init__(self):
2024-11-18 13:54:26 +08:00
"""Initialize tool with empty schema registry."""
2024-11-18 08:38:31 +08:00
self._schemas: Dict[str, List[ToolSchema]] = {}
2025-04-01 10:36:26 +08:00
logger.debug(f"Initializing tool class: {self.__class__.__name__}")
2024-10-23 09:28:12 +08:00
self._register_schemas()
def _register_schemas(self):
"""Register schemas from all decorated methods."""
2024-10-23 09:28:12 +08:00
for name, method in inspect.getmembers(self, predicate=inspect.ismethod):
2024-11-18 08:38:31 +08:00
if hasattr(method, 'tool_schemas'):
self._schemas[name] = method.tool_schemas
2025-04-01 10:36:26 +08:00
logger.debug(f"Registered schemas for method '{name}' in {self.__class__.__name__}")
2024-10-06 01:04:15 +08:00
2024-11-18 08:38:31 +08:00
def get_schemas(self) -> Dict[str, List[ToolSchema]]:
2024-11-18 13:54:26 +08:00
"""Get all registered tool schemas.
Returns:
Dict mapping method names to their schema definitions
"""
2024-10-23 09:28:12 +08:00
return self._schemas
2024-10-06 01:04:15 +08:00
2024-11-02 08:01:26 +08:00
def success_response(self, data: Union[Dict[str, Any], str]) -> ToolResult:
2024-11-18 13:54:26 +08:00
"""Create a successful tool result.
Args:
data: Result data (dictionary or string)
Returns:
ToolResult with success=True and formatted output
"""
2024-10-06 01:04:15 +08:00
if isinstance(data, str):
text = data
else:
text = json.dumps(data, indent=2)
2025-04-01 10:36:26 +08:00
logger.debug(f"Created success response for {self.__class__.__name__}")
2024-10-06 01:04:15 +08:00
return ToolResult(success=True, output=text)
def fail_response(self, msg: str) -> ToolResult:
2024-11-18 13:54:26 +08:00
"""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}")
2024-10-06 01:04:15 +08:00
return ToolResult(success=False, output=msg)
2024-11-18 08:38:31 +08:00
def _add_schema(func, schema: ToolSchema):
"""Helper to add schema to a function."""
if not hasattr(func, 'tool_schemas'):
func.tool_schemas = []
func.tool_schemas.append(schema)
2025-04-01 10:36:26 +08:00
logger.debug(f"Added {schema.schema_type.value} schema to function {func.__name__}")
2024-11-18 08:38:31 +08:00
return func
def openapi_schema(schema: Dict[str, Any]):
"""Decorator for OpenAPI schema tools."""
def decorator(func):
2025-04-01 10:36:26 +08:00
logger.debug(f"Applying OpenAPI schema to function {func.__name__}")
2024-11-18 08:38:31 +08:00
return _add_schema(func, ToolSchema(
schema_type=SchemaType.OPENAPI,
schema=schema
))
return decorator
2025-07-28 19:13:42 +08:00
def xml_schema(schema: Dict[str, Any]):
"""Deprecated decorator - does nothing, kept for compatibility."""
2024-11-18 08:38:31 +08:00
def decorator(func):
2025-07-28 19:13:42 +08:00
logger.debug(f"xml_schema decorator called on {func.__name__} - ignoring (deprecated)")
return func
2024-10-23 09:28:12 +08:00
return decorator