8dbcb1147f
Add no-key web_search and web_fetch tools. Fetch pages with net/http and parse HTML content. Document built-in web capabilities.
97 lines
2.8 KiB
Go
97 lines
2.8 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestBuiltinSearchTool(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
t.Fatalf("method = %s", r.Method)
|
|
}
|
|
if got := r.URL.Query().Get("q"); got != "agentu" {
|
|
t.Fatalf("query = %q", got)
|
|
}
|
|
w.Header().Set("Content-Type", "text/html")
|
|
_, _ = w.Write([]byte(`
|
|
<html><body>
|
|
<div class="result">
|
|
<a class="result__a" href="/l/?uddg=https%3A%2F%2Fexample.com%2Fagentu">Agentu release</a>
|
|
<a class="result__snippet">Agentu adds built-in web tools.</a>
|
|
</div>
|
|
</body></html>`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
tool := NewBuiltinSearchToolWithBaseURL(server.URL, 5, server.Client())
|
|
out, err := tool.Execute(context.Background(), json.RawMessage(`{"query":"agentu"}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"Web search results", "Agentu release", "https://example.com/agentu", "Agentu adds built-in web tools"} {
|
|
if !strings.Contains(out, want) {
|
|
t.Fatalf("output missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuiltinFetchTool(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
t.Fatalf("method = %s", r.Method)
|
|
}
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
_, _ = w.Write([]byte(`
|
|
<html>
|
|
<head><title>Agentu</title><script>hidden()</script></head>
|
|
<body>
|
|
<h1>Agentu</h1>
|
|
<p>Built-in fetch reads HTML.</p>
|
|
<ul><li>Search</li><li>Fetch</li></ul>
|
|
</body>
|
|
</html>`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
tool := NewBuiltinFetchTool(server.Client())
|
|
out, err := tool.Execute(context.Background(), json.RawMessage(`{"url":"`+server.URL+`"}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, want := range []string{"Fetched web content", server.URL, "# Agentu", "Built-in fetch reads HTML", "- Search", "- Fetch"} {
|
|
if !strings.Contains(out, want) {
|
|
t.Fatalf("output missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
if strings.Contains(out, "hidden") {
|
|
t.Fatalf("script content should be ignored:\n%s", out)
|
|
}
|
|
}
|
|
|
|
func TestBuiltinFetchToolAcceptsURLsWithoutScheme(t *testing.T) {
|
|
args, err := parseWebFetchArgs(json.RawMessage(`{"url":"example.com/page"}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if args.URL != "https://example.com/page" {
|
|
t.Fatalf("url = %q", args.URL)
|
|
}
|
|
}
|
|
|
|
func TestBuiltinFetchToolFormatsFailedResults(t *testing.T) {
|
|
response := webFetchResponse{
|
|
FailedResults: []webFetchFailed{{URL: "https://example.com", Error: "blocked"}},
|
|
}
|
|
out := formatWebFetchResults("https://example.com", response)
|
|
for _, want := range []string{"No readable web content", "Fetch failed", "blocked"} {
|
|
if !strings.Contains(out, want) {
|
|
t.Fatalf("output missing %q:\n%s", want, out)
|
|
}
|
|
}
|
|
}
|