mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-20 16:19:37 +00:00
Pure file reorganization — no logic changes, no renames, no refactoring. Functions moved to new files in the same package for maintainability. Split 13 files across 6 packages into 25 new files: - store/pg: teams.go → teams_tasks/delegation/messaging.go; mcp_servers.go → mcp_servers_access.go - tools: delegate.go → delegate_state/policy/events.go; subagent.go → subagent_exec/config.go; web_search.go → web_search_brave/ddg.go; web_fetch.go → web_fetch_convert.go; sessions.go → sessions_history/send.go - providers: anthropic.go → anthropic_stream/request.go - mcp: manager.go → manager_connect/tools/util.go - channels/feishu: bot.go → bot_parse/policy.go; larkclient.go → larkclient_messaging.go - cmd: gateway_consumer.go → gateway_cron.go; agent_chat.go → agent_chat_client/standalone.go Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
94 lines
2.2 KiB
Go
94 lines
2.2 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
)
|
|
|
|
// --- Brave Search Provider ---
|
|
|
|
type braveSearchProvider struct {
|
|
apiKey string
|
|
client *http.Client
|
|
}
|
|
|
|
func newBraveSearchProvider(apiKey string) *braveSearchProvider {
|
|
return &braveSearchProvider{
|
|
apiKey: apiKey,
|
|
client: &http.Client{Timeout: time.Duration(searchTimeoutSeconds) * time.Second},
|
|
}
|
|
}
|
|
|
|
func (p *braveSearchProvider) Name() string { return "brave" }
|
|
|
|
func (p *braveSearchProvider) Search(ctx context.Context, params searchParams) ([]searchResult, error) {
|
|
q := url.Values{}
|
|
q.Set("q", params.Query)
|
|
q.Set("count", fmt.Sprintf("%d", params.Count))
|
|
|
|
if params.Country != "" {
|
|
q.Set("country", params.Country)
|
|
}
|
|
if params.SearchLang != "" {
|
|
q.Set("search_lang", params.SearchLang)
|
|
}
|
|
if params.UILang != "" {
|
|
q.Set("ui_lang", params.UILang)
|
|
}
|
|
if f := normalizeFreshness(params.Freshness); f != "" {
|
|
q.Set("freshness", f)
|
|
}
|
|
|
|
reqURL := braveSearchEndpoint + "?" + q.Encode()
|
|
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create request: %w", err)
|
|
}
|
|
req.Header.Set("Accept", "application/json")
|
|
req.Header.Set("X-Subscription-Token", p.apiKey)
|
|
|
|
resp, err := p.client.Do(req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read response: %w", err)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("brave API returned %d: %s", resp.StatusCode, truncateStr(string(body), 200))
|
|
}
|
|
|
|
var braveResp struct {
|
|
Web struct {
|
|
Results []struct {
|
|
Title string `json:"title"`
|
|
URL string `json:"url"`
|
|
Description string `json:"description"`
|
|
} `json:"results"`
|
|
} `json:"web"`
|
|
}
|
|
|
|
if err := json.Unmarshal(body, &braveResp); err != nil {
|
|
return nil, fmt.Errorf("parse response: %w", err)
|
|
}
|
|
|
|
results := make([]searchResult, 0, len(braveResp.Web.Results))
|
|
for _, r := range braveResp.Web.Results {
|
|
results = append(results, searchResult{
|
|
Title: r.Title,
|
|
URL: r.URL,
|
|
Description: r.Description,
|
|
})
|
|
}
|
|
return results, nil
|
|
}
|