| """ToolDiscoveryTool - Dynamic tool discovery for Stack 2.9""" |
|
|
| import json |
| from datetime import datetime |
| from typing import Any, Dict, List |
|
|
| from .base import BaseTool, ToolResult |
| from .registry import tool_registry |
|
|
|
|
| class ToolSearchTool(BaseTool): |
| """Search for tools by capability or keyword.""" |
|
|
| name = "tool_search" |
| description = "Search available tools by keyword or capability" |
|
|
| input_schema = { |
| "type": "object", |
| "properties": { |
| "query": { |
| "type": "string", |
| "description": "Search query (tool name, capability, or keyword)" |
| }, |
| "capability": { |
| "type": "string", |
| "description": "Filter by capability (web, task, agent, data, etc.)" |
| } |
| }, |
| "required": ["query"] |
| } |
|
|
| async def execute(self, query: str, capability: Optional[str] = None) -> ToolResult: |
| """Search tools.""" |
| all_tools = tool_registry.list_tools() |
| query_lower = query.lower() |
|
|
| matches = [] |
| for name, tool_info in all_tools.items(): |
| desc = tool_info.get("description", "").lower() |
| if query_lower in name.lower() or query_lower in desc: |
| matches.append({"name": name, **tool_info}) |
|
|
| if capability: |
| cap_lower = capability.lower() |
| matches = [m for m in matches if cap_lower in m.get("description", "").lower()] |
|
|
| return ToolResult(success=True, data={ |
| "query": query, |
| "capability": capability, |
| "matches": matches, |
| "count": len(matches) |
| }) |
|
|
|
|
| class ToolListAllTool(BaseTool): |
| """List all registered tools.""" |
|
|
| name = "tool_list_all" |
| description = "List all available tools in the registry" |
|
|
| input_schema = { |
| "type": "object", |
| "properties": { |
| "category": { |
| "type": "string", |
| "description": "Filter by category (web, task, agent, team, skill, etc.)" |
| } |
| }, |
| "required": [] |
| } |
|
|
| async def execute(self, category: Optional[str] = None) -> ToolResult: |
| """List all tools.""" |
| all_tools = tool_registry.list_tools() |
|
|
| if category: |
| cat_lower = category.lower() |
| filtered = {k: v for k, v in all_tools.items() if cat_lower in v.get("description", "").lower()} |
| return ToolResult(success=True, data={ |
| "category": category, |
| "tools": filtered, |
| "count": len(filtered) |
| }) |
|
|
| return ToolResult(success=True, data={ |
| "tools": all_tools, |
| "count": len(all_tools) |
| }) |
|
|
|
|
| class ToolInfoTool(BaseTool): |
| """Get detailed information about a specific tool.""" |
|
|
| name = "tool_info" |
| description = "Get detailed information about a specific tool" |
|
|
| input_schema = { |
| "type": "object", |
| "properties": { |
| "name": { |
| "type": "string", |
| "description": "Tool name" |
| } |
| }, |
| "required": ["name"] |
| } |
|
|
| async def execute(self, name: str) -> ToolResult: |
| """Get tool info.""" |
| tool = tool_registry.get_tool(name) |
|
|
| if not tool: |
| return ToolResult(success=False, error=f"Tool '{name}' not found") |
|
|
| return ToolResult(success=True, data={ |
| "name": tool.name, |
| "description": tool.description, |
| "input_schema": tool.input_schema |
| }) |
|
|
|
|
| class ToolCapabilitiesTool(BaseTool): |
| """List all available capabilities/functionalities.""" |
|
|
| name = "tool_capabilities" |
| description = "List all tool capabilities grouped by category" |
|
|
| input_schema = { |
| "type": "object", |
| "properties": {}, |
| "required": [] |
| } |
|
|
| async def execute(self) -> ToolResult: |
| """List capabilities.""" |
| all_tools = tool_registry.list_tools() |
|
|
| categories = { |
| "web": ["web_search", "web_fetch", "web_fetch_meta"], |
| "task": ["task_create", "task_list", "task_update", "task_delete"], |
| "agent": ["agent_spawn", "agent_status", "agent_list"], |
| "team": ["team_create", "team_disband", "team_list", "team_status", "team_assign"], |
| "skill": ["skill_list", "skill_execute", "skill_info", "skill_chain", "skill_search"], |
| "scheduling": ["cron_create", "cron_list", "cron_delete"], |
| "messaging": ["message_send", "message_list", "message_channel", "message_template"], |
| "remote": ["remote_add", "remote_list", "remote_trigger", "remote_remove"], |
| "discovery": ["tool_search", "tool_list_all", "tool_info", "tool_capabilities"] |
| } |
|
|
| capabilities = {} |
| for cat, tools in categories.items(): |
| available = [t for t in tools if t in all_tools] |
| if available: |
| capabilities[cat] = available |
|
|
| return ToolResult(success=True, data={ |
| "capabilities": capabilities, |
| "total_categories": len(capabilities) |
| }) |
|
|
|
|
| from typing import Optional |
| from .base import BaseTool |
|
|
| |
| tool_registry.register(ToolSearchTool()) |
| tool_registry.register(ToolListAllTool()) |
| tool_registry.register(ToolInfoTool()) |
| tool_registry.register(ToolCapabilitiesTool()) |
|
|