yao/tools/websearch/serper.go
Max 7da06a4ae1 feat(search): refactor builtinSearch to utilize websearch tool and enhance context handling
- Updated the builtinSearch function to delegate search operations to the websearch tool, improving modularity and maintainability.
- Enhanced context handling by passing the agent context to builtinSearch, allowing for user and team identification during searches.
- Added a new DecryptValue function in cloud.go to streamline value decryption, delegating to the existing config.DecryptValue method.
- Updated .gitignore to include tools/README.md for better project organization.
2026-05-02 19:58:03 +08:00

65 lines
1.7 KiB
Go

package websearch
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
func serperSearch(apiKey, query string, limit int) []SearchResult {
if apiKey == "" {
return nil
}
payload, _ := json.Marshal(map[string]interface{}{
"q": query,
"num": limit,
})
req, err := http.NewRequest("POST", "https://google.serper.dev/search", bytes.NewReader(payload))
if err != nil {
return []SearchResult{{Title: "Error", Content: fmt.Sprintf("serper request build failed: %s", err.Error())}}
}
req.Header.Set("X-API-KEY", apiKey)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
return []SearchResult{{Title: "Error", Content: fmt.Sprintf("serper request failed: %s", err.Error())}}
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return []SearchResult{{Title: "Error", Content: fmt.Sprintf("serper read body failed: %s", err.Error())}}
}
if resp.StatusCode != http.StatusOK {
return []SearchResult{{Title: "Error", Content: fmt.Sprintf("serper HTTP %d: %s", resp.StatusCode, string(body))}}
}
var result struct {
Organic []struct {
Title string `json:"title"`
Link string `json:"link"`
Snippet string `json:"snippet"`
} `json:"organic"`
}
if err := json.Unmarshal(body, &result); err != nil {
return []SearchResult{{Title: "Error", Content: fmt.Sprintf("serper parse failed: %s", err.Error())}}
}
out := make([]SearchResult, 0, len(result.Organic))
for _, r := range result.Organic {
out = append(out, SearchResult{
Title: r.Title,
URL: r.Link,
Content: r.Snippet,
})
}
return out
}