package tools import ( "context" "encoding/json" "fmt" "switchboard-core/tools/search" ) func init() { Register(&WebSearchTool{}) } // ═══════════════════════════════════════════ // web_search // ═══════════════════════════════════════════ type WebSearchTool struct{ BaseTool } func (t *WebSearchTool) Definition() ToolDef { return ToolDef{ Name: "web_search", DisplayName: "Search", Description: "Search the web for current information. Use this when you need up-to-date facts, news, or information you're not confident about. Returns titles, URLs, and text snippets from web pages.", Category: "search", Parameters: JSONSchema(map[string]interface{}{ "query": Prop("string", "Search query — be specific and concise"), "max_results": Prop("integer", "Maximum number of results to return (1-10, default 5)"), }, []string{"query"}), } } func (t *WebSearchTool) Execute(ctx context.Context, execCtx ExecutionContext, argsJSON string) (string, error) { var args struct { Query string `json:"query"` MaxResults int `json:"max_results"` } if err := json.Unmarshal([]byte(argsJSON), &args); err != nil { return "", fmt.Errorf("invalid arguments: %w", err) } if args.Query == "" { return "", fmt.Errorf("query is required") } if args.MaxResults <= 0 { args.MaxResults = 5 } if args.MaxResults > 10 { args.MaxResults = 10 } provider := search.Active() if provider == nil { return "", fmt.Errorf("no search provider configured") } results, err := provider.Search(ctx, args.Query, args.MaxResults) if err != nil { return "", fmt.Errorf("search failed: %w", err) } response := map[string]interface{}{ "provider": provider.Name(), "query": args.Query, "result_count": len(results), "results": results, } b, _ := json.Marshal(response) return string(b), nil }