feat(plugins): implement web-search, web-fetch, http and file tools

- web-search: real SearXNG /search?format=json query, top-5 formatted
  results (was a 'not configured' stub)
- web-fetch: fetch page, strip scripts/styles/tags, truncate to 4000
  runes for the LLM context
- http: generic request tool (GET/POST/PUT/DELETE/PATCH) with scheme
  and method validation, status + truncated body
- file: sandboxed read/write/list inside the data directory with path
  escape rejection; split into file_read/file_write/file_list
- all tool schemas converted to proper JSON Schema; httptest/tempdir
  tests for each plugin
This commit is contained in:
Aska committed 2026-08-21 12:57:19 +08:00
1 parent d80710d85a
commit 9d040fde0b
8 files changed
+599 -44

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
package http_plugin
import (
"context"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestGet(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("method = %s", r.Method)
}
w.Write([]byte("hello"))
}))
defer srv.Close()
p := New()
out, err := p.Execute(context.Background(), "http_request", map[string]any{"url": srv.URL})
if err != nil {
t.Fatalf("Execute: %v", err)
}
if !strings.Contains(out, "HTTP 200") || !strings.Contains(out, "hello") {
t.Errorf("unexpected output: %q", out)
}
}
func TestPostWithBody(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
if r.Method != "POST" || string(body) != `{"a":1}` {
t.Errorf("method=%s body=%s", r.Method, body)
}
w.WriteHeader(201)
}))
defer srv.Close()
p := New()
out, err := p.Execute(context.Background(), "http_request", map[string]any{
"url": srv.URL, "method": "post", "body": `{"a":1}`,
})
if err != nil || !strings.Contains(out, "HTTP 201") {
t.Errorf("out=%q err=%v", out, err)
}
}
func TestRejectsBadInput(t *testing.T) {
p := New()
if _, err := p.Execute(context.Background(), "http_request", map[string]any{"url": "ftp://x"}); err == nil {
t.Error("bad scheme should fail")
}
if _, err := p.Execute(context.Background(), "http_request", map[string]any{"url": "http://x", "method": "TRACE"}); err == nil {
t.Error("bad method should fail")
}
}