From 0add906e71a3ed119f0d193e3829aaa11ad0abc4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Mar 2026 06:29:08 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20refactor:=20organize=20web=20too?= =?UTF-8?q?l=20into=20sub-package=20pkg/tools/web?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 What: - Moved modularized web tool files into `pkg/tools/web/` directory. - Updated package name to `web`. - Simplified filenames (e.g., `web_fetch_tool.go` -> `fetch.go`). - Updated `pkg/agent/loop_init.go` to import and use the new `web` package. 💡 Why: - Better organization of the `pkg/tools` directory. - Consistent with other complex tools like `alpaca`. - Addresses reviewer feedback. ✅ Verification: - All tests in `pkg/tools/web` pass. - `pkg/agent/loop_init.go` compiles correctly with the new package structure. - Sandbox-specific test in `ssrf_test.go` correctly skips. ✨ Result: - Granular, well-organized web tool sub-package. - Improved codebase structure and maintainability. Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com> --- pkg/agent/loop_init.go | 5 ++-- pkg/tools/{web_common.go => web/common.go} | 2 +- .../common_test.go} | 2 +- pkg/tools/{web_fetch_tool.go => web/fetch.go} | 25 ++++++++++--------- .../fetch_test.go} | 4 +-- pkg/tools/{web_keys.go => web/keys.go} | 2 +- .../{web_keys_test.go => web/keys_test.go} | 2 +- .../providers.go} | 2 +- .../{web_search_tool.go => web/search.go} | 11 ++++---- .../search_test.go} | 2 +- pkg/tools/{web_ssrf.go => web/ssrf.go} | 2 +- .../{web_ssrf_test.go => web/ssrf_test.go} | 2 +- 12 files changed, 32 insertions(+), 29 deletions(-) rename pkg/tools/{web_common.go => web/common.go} (99%) rename pkg/tools/{web_common_test.go => web/common_test.go} (99%) rename pkg/tools/{web_fetch_tool.go => web/fetch.go} (87%) rename pkg/tools/{web_fetch_tool_test.go => web/fetch_test.go} (99%) rename pkg/tools/{web_keys.go => web/keys.go} (98%) rename pkg/tools/{web_keys_test.go => web/keys_test.go} (99%) rename pkg/tools/{web_search_providers.go => web/providers.go} (99%) rename pkg/tools/{web_search_tool.go => web/search.go} (95%) rename pkg/tools/{web_search_tool_test.go => web/search_test.go} (99%) rename pkg/tools/{web_ssrf.go => web/ssrf.go} (99%) rename pkg/tools/{web_ssrf_test.go => web/ssrf_test.go} (99%) diff --git a/pkg/agent/loop_init.go b/pkg/agent/loop_init.go index 283ead868..a1fd3f873 100644 --- a/pkg/agent/loop_init.go +++ b/pkg/agent/loop_init.go @@ -22,6 +22,7 @@ import ( "jane/pkg/skills" "jane/pkg/state" "jane/pkg/tools" + "jane/pkg/tools/web" "jane/pkg/voice" ) @@ -74,7 +75,7 @@ func registerSharedTools( } if cfg.Tools.IsToolEnabled("web") { - searchTool, err := tools.NewWebSearchTool(tools.WebSearchToolOptions{ + searchTool, err := web.NewWebSearchTool(web.WebSearchToolOptions{ BraveAPIKeys: config.MergeAPIKeys(cfg.Tools.Web.Brave.APIKey, cfg.Tools.Web.Brave.APIKeys), BraveMaxResults: cfg.Tools.Web.Brave.MaxResults, BraveEnabled: cfg.Tools.Web.Brave.Enabled, @@ -107,7 +108,7 @@ func registerSharedTools( } } if cfg.Tools.IsToolEnabled("web_fetch") { - fetchTool, err := tools.NewWebFetchToolWithProxy(50000, cfg.Tools.Web.Proxy, cfg.Tools.Web.FetchLimitBytes) + fetchTool, err := web.NewWebFetchToolWithProxy(50000, cfg.Tools.Web.Proxy, cfg.Tools.Web.FetchLimitBytes) if err != nil { logger.ErrorCF("agent", "Failed to create web fetch tool", map[string]any{"error": err.Error()}) } else { diff --git a/pkg/tools/web_common.go b/pkg/tools/web/common.go similarity index 99% rename from pkg/tools/web_common.go rename to pkg/tools/web/common.go index 2c2fb007a..7a769bcc8 100644 --- a/pkg/tools/web_common.go +++ b/pkg/tools/web/common.go @@ -1,4 +1,4 @@ -package tools +package web import ( "fmt" diff --git a/pkg/tools/web_common_test.go b/pkg/tools/web/common_test.go similarity index 99% rename from pkg/tools/web_common_test.go rename to pkg/tools/web/common_test.go index 11db8624f..efad6ae3b 100644 --- a/pkg/tools/web_common_test.go +++ b/pkg/tools/web/common_test.go @@ -1,4 +1,4 @@ -package tools +package web import ( "net/http" diff --git a/pkg/tools/web_fetch_tool.go b/pkg/tools/web/fetch.go similarity index 87% rename from pkg/tools/web_fetch_tool.go rename to pkg/tools/web/fetch.go index 8a3a6b974..44d836f18 100644 --- a/pkg/tools/web_fetch_tool.go +++ b/pkg/tools/web/fetch.go @@ -1,6 +1,7 @@ -package tools +package web import ( + "jane/pkg/tools" "context" "encoding/json" "errors" @@ -86,30 +87,30 @@ func (t *WebFetchTool) Parameters() map[string]any { } } -func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolResult { +func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *tools.ToolResult { urlStr, ok := args["url"].(string) if !ok { - return ErrorResult("url is required") + return tools.ErrorResult("url is required") } parsedURL, err := url.Parse(urlStr) if err != nil { - return ErrorResult(fmt.Sprintf("invalid URL: %v", err)) + return tools.ErrorResult(fmt.Sprintf("invalid URL: %v", err)) } if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" { - return ErrorResult("only http/https URLs are allowed") + return tools.ErrorResult("only http/https URLs are allowed") } if parsedURL.Host == "" { - return ErrorResult("missing domain in URL") + return tools.ErrorResult("missing domain in URL") } // Lightweight pre-flight: block obvious localhost/literal-IP without DNS resolution. // The real SSRF guard is newSafeDialContext at connect time. hostname := parsedURL.Hostname() if isObviousPrivateHost(hostname) { - return ErrorResult("fetching private or local network hosts is not allowed") + return tools.ErrorResult("fetching private or local network hosts is not allowed") } maxChars := t.maxChars @@ -121,13 +122,13 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil) if err != nil { - return ErrorResult(fmt.Sprintf("failed to create request: %v", err)) + return tools.ErrorResult(fmt.Sprintf("failed to create request: %v", err)) } req.Header.Set("User-Agent", userAgent) resp, err := t.client.Do(req) if err != nil { - return ErrorResult(fmt.Sprintf("request failed: %v", err)) + return tools.ErrorResult(fmt.Sprintf("request failed: %v", err)) } resp.Body = http.MaxBytesReader(nil, resp.Body, t.fetchLimitBytes) @@ -138,9 +139,9 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe if err != nil { var maxBytesErr *http.MaxBytesError if errors.As(err, &maxBytesErr) { - return ErrorResult(fmt.Sprintf("failed to read response: size exceeded %d bytes limit", t.fetchLimitBytes)) + return tools.ErrorResult(fmt.Sprintf("failed to read response: size exceeded %d bytes limit", t.fetchLimitBytes)) } - return ErrorResult(fmt.Sprintf("failed to read response: %v", err)) + return tools.ErrorResult(fmt.Sprintf("failed to read response: %v", err)) } contentType := resp.Header.Get("Content-Type") @@ -182,7 +183,7 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe resultJSON, _ := json.MarshalIndent(result, "", " ") - return &ToolResult{ + return &tools.ToolResult{ ForLLM: string(resultJSON), ForUser: fmt.Sprintf( "Fetched %d bytes from %s (extractor: %s, truncated: %v)", diff --git a/pkg/tools/web_fetch_tool_test.go b/pkg/tools/web/fetch_test.go similarity index 99% rename from pkg/tools/web_fetch_tool_test.go rename to pkg/tools/web/fetch_test.go index 9e8ae3a6b..db993e512 100644 --- a/pkg/tools/web_fetch_tool_test.go +++ b/pkg/tools/web/fetch_test.go @@ -1,4 +1,4 @@ -package tools +package web import ( "bytes" @@ -213,7 +213,7 @@ func TestWebFetchTool_PayloadTooLarge(t *testing.T) { result := tool.Execute(ctx, args) if result == nil { - t.Fatal("expected a ToolResult, got nil") + t.Fatal("expected a tools.ToolResult, got nil") } expectedErrorMsg := fmt.Sprintf("size exceeded %d bytes limit", testFetchLimit) diff --git a/pkg/tools/web_keys.go b/pkg/tools/web/keys.go similarity index 98% rename from pkg/tools/web_keys.go rename to pkg/tools/web/keys.go index 248333d20..28066eab7 100644 --- a/pkg/tools/web_keys.go +++ b/pkg/tools/web/keys.go @@ -1,4 +1,4 @@ -package tools +package web import ( "sync/atomic" diff --git a/pkg/tools/web_keys_test.go b/pkg/tools/web/keys_test.go similarity index 99% rename from pkg/tools/web_keys_test.go rename to pkg/tools/web/keys_test.go index 2609b8fa4..39a3e852d 100644 --- a/pkg/tools/web_keys_test.go +++ b/pkg/tools/web/keys_test.go @@ -1,4 +1,4 @@ -package tools +package web import ( "testing" diff --git a/pkg/tools/web_search_providers.go b/pkg/tools/web/providers.go similarity index 99% rename from pkg/tools/web_search_providers.go rename to pkg/tools/web/providers.go index 02c64ea32..c08282579 100644 --- a/pkg/tools/web_search_providers.go +++ b/pkg/tools/web/providers.go @@ -1,4 +1,4 @@ -package tools +package web import ( "bytes" diff --git a/pkg/tools/web_search_tool.go b/pkg/tools/web/search.go similarity index 95% rename from pkg/tools/web_search_tool.go rename to pkg/tools/web/search.go index 53e29da72..d23b7d619 100644 --- a/pkg/tools/web_search_tool.go +++ b/pkg/tools/web/search.go @@ -1,6 +1,7 @@ -package tools +package web import ( + "jane/pkg/tools" "context" "fmt" ) @@ -144,10 +145,10 @@ func (t *WebSearchTool) Parameters() map[string]any { } } -func (t *WebSearchTool) Execute(ctx context.Context, args map[string]any) *ToolResult { +func (t *WebSearchTool) Execute(ctx context.Context, args map[string]any) *tools.ToolResult { query, ok := args["query"].(string) if !ok { - return ErrorResult("query is required") + return tools.ErrorResult("query is required") } count := t.maxResults @@ -159,10 +160,10 @@ func (t *WebSearchTool) Execute(ctx context.Context, args map[string]any) *ToolR result, err := t.provider.Search(ctx, query, count) if err != nil { - return ErrorResult(fmt.Sprintf("search failed: %v", err)) + return tools.ErrorResult(fmt.Sprintf("search failed: %v", err)) } - return &ToolResult{ + return &tools.ToolResult{ ForLLM: result, ForUser: result, } diff --git a/pkg/tools/web_search_tool_test.go b/pkg/tools/web/search_test.go similarity index 99% rename from pkg/tools/web_search_tool_test.go rename to pkg/tools/web/search_test.go index b622121d9..9f9224c15 100644 --- a/pkg/tools/web_search_tool_test.go +++ b/pkg/tools/web/search_test.go @@ -1,4 +1,4 @@ -package tools +package web import ( "context" diff --git a/pkg/tools/web_ssrf.go b/pkg/tools/web/ssrf.go similarity index 99% rename from pkg/tools/web_ssrf.go rename to pkg/tools/web/ssrf.go index c0fbb079b..865e6d98a 100644 --- a/pkg/tools/web_ssrf.go +++ b/pkg/tools/web/ssrf.go @@ -1,4 +1,4 @@ -package tools +package web import ( "context" diff --git a/pkg/tools/web_ssrf_test.go b/pkg/tools/web/ssrf_test.go similarity index 99% rename from pkg/tools/web_ssrf_test.go rename to pkg/tools/web/ssrf_test.go index 12ec84af8..56f2d8a00 100644 --- a/pkg/tools/web_ssrf_test.go +++ b/pkg/tools/web/ssrf_test.go @@ -1,4 +1,4 @@ -package tools +package web import ( "context"