test/moxie/tools/web_search.py
2026-03-24 04:07:54 +00:00

72 lines
2.3 KiB
Python
Executable File

"""
Web Search Tool
Uses DuckDuckGo for free web search (no API key needed).
"""
from typing import Dict, Any, Optional
from duckduckgo_search import DDGS
from loguru import logger
from tools.base import BaseTool, ToolResult
class WebSearchTool(BaseTool):
"""Web search using DuckDuckGo."""
@property
def name(self) -> str:
return "web_search"
@property
def description(self) -> str:
return "Search the web for current information. Use this for recent events, news, or topics not in your training data."
@property
def parameters(self) -> Dict[str, Any]:
return {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
},
"max_results": {
"type": "integer",
"description": "Maximum number of results to return (default: 5)",
"default": 5
}
},
"required": ["query"]
}
async def execute(self, query: str, max_results: int = 5, **kwargs) -> ToolResult:
"""Execute web search."""
self._log_execution({"query": query, "max_results": max_results})
try:
with DDGS() as ddgs:
results = list(ddgs.text(query, max_results=max_results))
if not results:
return ToolResult(
success=True,
data="No search results found."
)
# Format results
formatted_results = []
for i, result in enumerate(results, 1):
formatted_results.append(
f"{i}. {result.get('title', 'No title')}\n"
f" {result.get('body', 'No description')}\n"
f" Source: {result.get('href', 'No URL')}"
)
output = f"Web search results for '{query}':\n\n" + "\n\n".join(formatted_results)
self._log_success(output[:100])
return ToolResult(success=True, data=output)
except Exception as e:
self._log_error(str(e))
return ToolResult(success=False, error=str(e))