""" tools/base.py — BaseTool abstract class. All tools inherit from this. The tool registry discovers them and builds the schema list sent to the AI provider on every agent call. """ from __future__ import annotations from abc import ABC, abstractmethod from dataclasses import dataclass @dataclass class ToolResult: """Normalised return value from every tool execution.""" success: bool data: dict | list | str | None = None error: str | None = None def to_dict(self) -> dict: if self.success: return {"success": True, "data": self.data} result: dict = {"success": False, "error": self.error} if self.data is not None: result["data"] = self.data return result class BaseTool(ABC): """ Abstract base for all aide tools. Subclasses must set class-level attributes: name — used in tool schema and audit log description — what the AI sees input_schema — JSON Schema for parameters (Anthropic-native format) Optional overrides: requires_confirmation — default False allowed_in_scheduled_tasks — default True """ name: str description: str input_schema: dict requires_confirmation: bool = False allowed_in_scheduled_tasks: bool = True @abstractmethod async def execute(self, **kwargs) -> ToolResult: """ Run the tool. Never raises — always returns a ToolResult. The dispatcher catches any unexpected exceptions as a safety net. """ def get_schema(self) -> dict: """Return the tool schema in aide-internal / Anthropic-native format.""" return { "name": self.name, "description": self.description, "input_schema": self.input_schema, } def confirmation_description(self, **kwargs) -> str: """ Human-readable description of the action shown to the user when confirmation is required. Override for better messages. """ args_str = ", ".join(f"{k}={v!r}" for k, v in kwargs.items()) return f"{self.name}({args_str})"