"""Tool system types."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Protocol, runtime_checkable


class ToolValidationError(Exception):
    """Raised when tool input validation fails."""

    def __init__(self, message: str, tool_name: str, cause: Exception | None = None) -> None:
        self.tool_name = tool_name
        self.cause = cause
        super().__init__(message)


class ToolExecutionError(Exception):
    """Raised when a tool function raises during execution."""

    def __init__(self, message: str, tool_name: str, cause: Exception | None = None) -> None:
        self.tool_name = tool_name
        self.cause = cause
        super().__init__(message)


@dataclass
class ToolDefinition:
    """Schema and metadata for a registered tool."""

    name: str
    description: str
    parameters: dict[str, Any]
    is_async: bool = False


@dataclass
class ToolResult:
    """Result from executing a tool."""

    tool_name: str
    output: Any = None
    error: str | None = None

    @property
    def is_error(self) -> bool:
        return self.error is not None


@runtime_checkable
class ToolProvider(Protocol):
    """Protocol for objects that can list and execute tools.

    Both ``ToolRegistry`` and ``MCPToolSource`` satisfy this protocol,
    allowing agents to accept either as a tool source.
    """

    def definitions(self) -> list[ToolDefinition]: ...

    async def execute(
        self,
        name: str,
        arguments: dict[str, Any] | str,
        *,
        context: Any | None = None,
    ) -> ToolResult: ...
