""" Tool Registry Manages all available tools and executes them. """ from typing import Dict, List, Any, Optional, Type from loguru import logger from tools.base import BaseTool, ToolResult from tools.web_search import WebSearchTool from tools.wikipedia import WikipediaTool from tools.rag import RAGTool from tools.gemini import GeminiTool from tools.openrouter import OpenRouterTool from tools.comfyui.image import ImageGenerationTool from tools.comfyui.video import VideoGenerationTool from tools.comfyui.audio import AudioGenerationTool class ToolRegistry: """ Registry for all tools. Handles: - Tool registration - Tool discovery (returns definitions for Ollama) - Tool execution """ def __init__(self, rag_store=None): self.tools: Dict[str, BaseTool] = {} self.rag_store = rag_store # Register all tools self._register_default_tools() def _register_default_tools(self) -> None: """Register all default tools.""" # Web search (DuckDuckGo - no API key needed) self.register(WebSearchTool()) # Wikipedia self.register(WikipediaTool()) # RAG (if store is available) if self.rag_store: self.register(RAGTool(self.rag_store)) # External LLM tools (these are hidden from user) self.register(GeminiTool()) self.register(OpenRouterTool()) # ComfyUI generation tools self.register(ImageGenerationTool()) self.register(VideoGenerationTool()) self.register(AudioGenerationTool()) logger.info(f"Registered {len(self.tools)} tools") def register(self, tool: BaseTool) -> None: """Register a tool.""" self.tools[tool.name] = tool logger.debug(f"Registered tool: {tool.name}") def unregister(self, tool_name: str) -> None: """Unregister a tool.""" if tool_name in self.tools: del self.tools[tool_name] logger.debug(f"Unregistered tool: {tool_name}") def get_tool(self, tool_name: str) -> Optional[BaseTool]: """Get a tool by name.""" return self.tools.get(tool_name) def get_tool_definitions(self) -> List[Dict[str, Any]]: """ Get tool definitions for Ollama. Returns definitions in the format expected by Ollama's tool calling. """ definitions = [] for tool in self.tools.values(): # Only include tools that have valid configurations definitions.append(tool.get_definition()) return definitions async def execute(self, tool_name: str, arguments: Dict[str, Any]) -> str: """ Execute a tool by name with given arguments. Returns the result as a string for LLM consumption. """ tool = self.get_tool(tool_name) if not tool: logger.error(f"Tool not found: {tool_name}") return f"Error: Tool '{tool_name}' not found" try: result = await tool.execute(**arguments) if result.success: return result.to_string() else: return f"Error: {result.error}" except Exception as e: logger.error(f"Tool execution failed: {tool_name} - {e}") return f"Error: {str(e)}" def list_tools(self) -> List[str]: """List all registered tool names.""" return list(self.tools.keys()) def has_tool(self, tool_name: str) -> bool: """Check if a tool is registered.""" return tool_name in self.tools