fix: ensure all tools work when behind a http proxy (#2065)

BitToby created

Replace custom `http.Transport` with cloned `DefaultTransport` to inherit
proxy configuration from environment variables (`HTTP_PROXY`, `HTTPS_PROXY`,
`NO_PROXY`). Affects `fetch`, `web_fetch`, `web_search`, `sourcegraph`, `download`,
and `agentic_fetch` tools.

Fixes enterprise environment compatibility where proxy configuration
is required for external HTTP requests.

Change summary

internal/agent/agentic_fetch_tool.go | 13 +++++++------
internal/agent/tools/download.go     | 13 +++++++------
internal/agent/tools/fetch.go        | 13 +++++++------
internal/agent/tools/sourcegraph.go  | 13 +++++++------
internal/agent/tools/web_fetch.go    | 13 +++++++------
internal/agent/tools/web_search.go   | 13 +++++++------
6 files changed, 42 insertions(+), 36 deletions(-)

Detailed changes

internal/agent/agentic_fetch_tool.go 🔗

@@ -52,13 +52,14 @@ var agenticFetchPromptTmpl []byte
 
 func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (fantasy.AgentTool, error) {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 30 * time.Second,
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   30 * time.Second,
+			Transport: transport,
 		}
 	}
 

internal/agent/tools/download.go 🔗

@@ -36,13 +36,14 @@ var downloadDescription []byte
 
 func NewDownloadTool(permissions permission.Service, workingDir string, client *http.Client) fantasy.AgentTool {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 5 * time.Minute, // Default 5 minute timeout for downloads
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   5 * time.Minute, // Default 5 minute timeout for downloads
+			Transport: transport,
 		}
 	}
 	return fantasy.NewParallelAgentTool(

internal/agent/tools/fetch.go 🔗

@@ -23,13 +23,14 @@ var fetchDescription []byte
 
 func NewFetchTool(permissions permission.Service, workingDir string, client *http.Client) fantasy.AgentTool {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 30 * time.Second,
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   30 * time.Second,
+			Transport: transport,
 		}
 	}
 

internal/agent/tools/sourcegraph.go 🔗

@@ -33,13 +33,14 @@ var sourcegraphDescription []byte
 
 func NewSourcegraphTool(client *http.Client) fantasy.AgentTool {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 30 * time.Second,
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   30 * time.Second,
+			Transport: transport,
 		}
 	}
 	return fantasy.NewParallelAgentTool(

internal/agent/tools/web_fetch.go 🔗

@@ -18,13 +18,14 @@ var webFetchToolDescription []byte
 // NewWebFetchTool creates a simple web fetch tool for sub-agents (no permissions needed).
 func NewWebFetchTool(workingDir string, client *http.Client) fantasy.AgentTool {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 30 * time.Second,
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   30 * time.Second,
+			Transport: transport,
 		}
 	}
 

internal/agent/tools/web_search.go 🔗

@@ -16,13 +16,14 @@ var webSearchToolDescription []byte
 // NewWebSearchTool creates a web search tool for sub-agents (no permissions needed).
 func NewWebSearchTool(client *http.Client) fantasy.AgentTool {
 	if client == nil {
+		transport := http.DefaultTransport.(*http.Transport).Clone()
+		transport.MaxIdleConns = 100
+		transport.MaxIdleConnsPerHost = 10
+		transport.IdleConnTimeout = 90 * time.Second
+
 		client = &http.Client{
-			Timeout: 30 * time.Second,
-			Transport: &http.Transport{
-				MaxIdleConns:        100,
-				MaxIdleConnsPerHost: 10,
-				IdleConnTimeout:     90 * time.Second,
-			},
+			Timeout:   30 * time.Second,
+			Transport: transport,
 		}
 	}