fix lint + error check

This commit is contained in:
afjcjsbx 2026-03-17 17:14:23 +01:00
parent 3791f06faf
commit 8f460726cc
4 changed files with 42 additions and 15 deletions

View file

@ -16,6 +16,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/sipeed/picoclaw/pkg/logger"
"github.com/sipeed/picoclaw/pkg/utils" "github.com/sipeed/picoclaw/pkg/utils"
) )
@ -29,7 +30,6 @@ const (
defaultMaxChars = 50000 defaultMaxChars = 50000
maxRedirects = 5 maxRedirects = 5
format = "plaintext"
) )
// Pre-compiled regexes for HTML text extraction // Pre-compiled regexes for HTML text extraction
@ -790,20 +790,27 @@ type privateHostWhitelist struct {
func NewWebFetchTool(maxChars int, format string, fetchLimitBytes int64) (*WebFetchTool, error) { func NewWebFetchTool(maxChars int, format string, fetchLimitBytes int64) (*WebFetchTool, error) {
// createHTTPClient cannot fail with an empty proxy string. // createHTTPClient cannot fail with an empty proxy string.
return NewWebFetchToolWithProxy(maxChars, "", format, fetchLimitBytes, nil) return NewWebFetchToolWithConfig(maxChars, "", format, fetchLimitBytes, nil)
} }
// allowPrivateWebFetchHosts controls whether loopback/private hosts are allowed. // allowPrivateWebFetchHosts controls whether loopback/private hosts are allowed.
// This is false in normal runtime to reduce SSRF exposure, and tests can override it temporarily. // This is false in normal runtime to reduce SSRF exposure, and tests can override it temporarily.
var allowPrivateWebFetchHosts atomic.Bool var allowPrivateWebFetchHosts atomic.Bool
func NewWebFetchToolWithProxy(maxChars int, proxy string, format string, fetchLimitBytes int64) (*WebFetchTool, error) { func NewWebFetchToolWithProxy(
return NewWebFetchToolWithConfig(maxChars, proxy, fetchLimitBytes, nil) maxChars int,
proxy string,
format string,
fetchLimitBytes int64,
privateHostWhitelist []string,
) (*WebFetchTool, error) {
return NewWebFetchToolWithConfig(maxChars, proxy, format, fetchLimitBytes, privateHostWhitelist)
} }
func NewWebFetchToolWithConfig( func NewWebFetchToolWithConfig(
maxChars int, maxChars int,
proxy string, proxy string,
format string,
fetchLimitBytes int64, fetchLimitBytes int64,
privateHostWhitelist []string, privateHostWhitelist []string,
) (*WebFetchTool, error) { ) (*WebFetchTool, error) {
@ -933,7 +940,26 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe
bodyStr := string(body) bodyStr := string(body)
contentType := resp.Header.Get("Content-Type") contentType := resp.Header.Get("Content-Type")
mediaType, _, _ := mime.ParseMediaType(contentType) mediaType, params, err := mime.ParseMediaType(contentType)
if err != nil {
// The most common error here is "mime: no media type" if the header is empty.
logger.WarnCF("tool", "Failed to parse Content-Type", map[string]any{
"raw_header": contentType,
"error": err.Error(),
})
// security fallback
mediaType = "application/octet-stream"
}
charset, hasCharset := params["charset"]
if hasCharset {
// If the charset is not utf-8, we might have to convert the bodyStr
// before passing it to the HTML/Markdown parser
if strings.ToLower(charset) != "utf-8" {
logger.WarnCF("tool", "Note: the content is not in UTF-8", map[string]any{"charset": charset})
}
}
var text, extractor string var text, extractor string

View file

@ -17,6 +17,7 @@ import (
const ( const (
testFetchLimit = int64(10 * 1024 * 1024) testFetchLimit = int64(10 * 1024 * 1024)
format = "plaintext"
) )
// TestWebTool_WebFetch_Success verifies successful URL fetching // TestWebTool_WebFetch_Success verifies successful URL fetching
@ -476,7 +477,7 @@ func TestWebTool_WebFetch_PrivateHostAllowedByExactWhitelist(t *testing.T) {
defer server.Close() defer server.Close()
host, _ := serverHostAndPort(t, server.URL) host, _ := serverHostAndPort(t, server.URL)
tool, err := NewWebFetchToolWithConfig(50000, "", testFetchLimit, []string{host}) tool, err := NewWebFetchToolWithConfig(50000, "", format, testFetchLimit, []string{host})
if err != nil { if err != nil {
t.Fatalf("Failed to create web fetch tool: %v", err) t.Fatalf("Failed to create web fetch tool: %v", err)
} }
@ -501,7 +502,7 @@ func TestWebTool_WebFetch_PrivateHostAllowedByCIDRWhitelist(t *testing.T) {
defer server.Close() defer server.Close()
host, _ := serverHostAndPort(t, server.URL) host, _ := serverHostAndPort(t, server.URL)
tool, err := NewWebFetchToolWithConfig(50000, "", testFetchLimit, []string{singleHostCIDR(t, host)}) tool, err := NewWebFetchToolWithConfig(50000, "", format, testFetchLimit, []string{singleHostCIDR(t, host)})
if err != nil { if err != nil {
t.Fatalf("Failed to create web fetch tool: %v", err) t.Fatalf("Failed to create web fetch tool: %v", err)
} }
@ -778,7 +779,7 @@ func TestWebTool_WebFetch_MissingDomain(t *testing.T) {
} }
func TestNewWebFetchToolWithProxy(t *testing.T) { func TestNewWebFetchToolWithProxy(t *testing.T) {
tool, err := NewWebFetchToolWithProxy(1024, "http://127.0.0.1:7890", format, testFetchLimit) tool, err := NewWebFetchToolWithProxy(1024, "http://127.0.0.1:7890", format, testFetchLimit, nil)
if err != nil { if err != nil {
logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()}) logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()})
} else if tool.maxChars != 1024 { } else if tool.maxChars != 1024 {
@ -789,7 +790,7 @@ func TestNewWebFetchToolWithProxy(t *testing.T) {
t.Fatalf("proxy = %q, want %q", tool.proxy, "http://127.0.0.1:7890") t.Fatalf("proxy = %q, want %q", tool.proxy, "http://127.0.0.1:7890")
} }
tool, err = NewWebFetchToolWithProxy(0, "http://127.0.0.1:7890", format, testFetchLimit) tool, err = NewWebFetchToolWithProxy(0, "http://127.0.0.1:7890", format, testFetchLimit, nil)
if err != nil { if err != nil {
logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()}) logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()})
} }
@ -800,7 +801,7 @@ func TestNewWebFetchToolWithProxy(t *testing.T) {
} }
func TestNewWebFetchToolWithConfig_InvalidPrivateHostWhitelist(t *testing.T) { func TestNewWebFetchToolWithConfig_InvalidPrivateHostWhitelist(t *testing.T) {
_, err := NewWebFetchToolWithConfig(1024, "", testFetchLimit, []string{"not-an-ip-or-cidr"}) _, err := NewWebFetchToolWithConfig(1024, "", format, testFetchLimit, []string{"not-an-ip-or-cidr"})
if err == nil { if err == nil {
t.Fatal("expected invalid whitelist entry to fail") t.Fatal("expected invalid whitelist entry to fail")
} }