""" Web Search Tool - Search the web for information """ import logging from typing import Any, Dict from duckduckgo_search import DDGS logger = logging.getLogger(__name__) WEB_SEARCH_TOOL_SPEC = { "name": "web_search", "description": ( "Search the web for current information, news, facts, and research. " "Use this to find up-to-date information, verify facts, or gather research data. " "Returns search results with titles, snippets, and URLs." ), "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "The search query to execute", }, "max_results": { "type": "number", "description": "Maximum number of results to return (default: 5, max: 10)", }, }, "required": ["query"], }, } async def web_search_handler(arguments: Dict[str, Any]) -> tuple[str, bool]: """Handler for web search using DuckDuckGo.""" try: query = arguments.get("query", "") max_results = min(int(arguments.get("max_results", 5)), 10) if not query.strip(): return "Error: Search query is required", False logger.info(f"Searching web for: {query}") # Perform search with DDGS() as ddgs: results = list(ddgs.text(query, max_results=max_results)) if not results: return f"No results found for query: '{query}'", True # Format results output_lines = [f"🔍 Web Search Results for: '{query}'\n", f"Found {len(results)} results:\n"] for i, result in enumerate(results, 1): title = result.get("title", "No title") snippet = result.get("body", "No description") url = result.get("href", "") output_lines.append(f"\n{i}. {title}") output_lines.append(f" {snippet}") output_lines.append(f" 🔗 {url}\n") return "\n".join(output_lines), True except Exception as e: logger.error(f"Web search error: {e}") return f"❌ Error performing web search: {str(e)}", False