"""Base classes for all capability modules.""" from __future__ import annotations from abc import abstractmethod from typing import Any from pydantic import BaseModel from pydantic_ai.capabilities import AbstractCapability from pydantic_ai.toolsets import FunctionToolset __all__ = ["AbstractCapability", "CapabilityWithTools", "DownloadedFile"] class DownloadedFile(BaseModel): """Return value for tools that download content to a local file.""" path: str size_bytes: int class CapabilityWithTools(AbstractCapability[Any]): """Base for capabilities that want their tool list auto-appended to instructions. Subclasses implement `_instructions_header()` with static context text. `get_instructions()` appends a formatted list of tools from `get_toolset()` automatically, so the instructions stay in sync with the actual toolset. """ @abstractmethod def _instructions_header(self) -> str: """Return the static preamble for this capability's instructions.""" def get_instructions(self) -> str: header = self._instructions_header() toolset = self.get_toolset() if not isinstance(toolset, FunctionToolset) or not toolset.tools: return header lines = [f"- `{name}`" for name in toolset.tools] return header + "\n\n" + "\n".join(lines)