From d98b69dedbb08a576bf8f217c99f3606a16a431b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:25:23 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Fix=20missing=20HTTP=20client=20timeout=20in=20jules=20API=20cl?= =?UTF-8?q?ient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a 15-second timeout to the http.Client in cmd/picoclaw/internal/jules/jules.go to prevent potential resource exhaustion or indefinite hangs if the external service is slow or unresponsive. Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com> --- cmd/picoclaw/internal/jules/jules.go | 5 ++++- pkg/agent/loop_test.go | 18 +++++++++--------- pkg/config/channels.go | 24 ++++++++++++------------ pkg/health/resource_tracker.go | 12 ++++++------ pkg/logger/logger.go | 6 +++--- pkg/migrate/sources/openclaw/common.go | 20 ++++++++++---------- pkg/tools/alpaca/alpaca.go | 4 ++-- pkg/tools/mcp2cli.go | 2 +- pkg/tools/mcp2cli_test.go | 2 +- pkg/tools/web/fetch.go | 2 +- pkg/tools/web/search.go | 2 +- 11 files changed, 50 insertions(+), 47 deletions(-) diff --git a/cmd/picoclaw/internal/jules/jules.go b/cmd/picoclaw/internal/jules/jules.go index db66516b1..49d0facc9 100644 --- a/cmd/picoclaw/internal/jules/jules.go +++ b/cmd/picoclaw/internal/jules/jules.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "os" + "time" "github.com/spf13/cobra" @@ -43,7 +44,9 @@ func doRequest(method, url string, body []byte) error { req.Header.Set("x-goog-api-key", apiKey) req.Header.Set("Content-Type", "application/json") - client := &http.Client{} + client := &http.Client{ + Timeout: 15 * time.Second, + } resp, err := client.Do(req) if err != nil { return fmt.Errorf("error making request: %w", err) diff --git a/pkg/agent/loop_test.go b/pkg/agent/loop_test.go index d3b5f304f..d41728103 100644 --- a/pkg/agent/loop_test.go +++ b/pkg/agent/loop_test.go @@ -844,15 +844,15 @@ func TestTargetReasoningChannelID_AllChannels(t *testing.T) { t.Fatalf("Failed to create channel manager: %v", err) } for name, id := range map[string]string{ - "whatsapp": "rid-whatsapp", - "telegram": "rid-telegram", - "discord": "rid-discord", - "maixcam": "rid-maixcam", - "qq": "rid-qq", - "dingtalk": "rid-dingtalk", - "slack": "rid-slack", - "line": "rid-line", - "onebot": "rid-onebot", + "whatsapp": "rid-whatsapp", + "telegram": "rid-telegram", + "discord": "rid-discord", + "maixcam": "rid-maixcam", + "qq": "rid-qq", + "dingtalk": "rid-dingtalk", + "slack": "rid-slack", + "line": "rid-line", + "onebot": "rid-onebot", } { chManager.RegisterChannel(name, &fakeChannel{id: id}) } diff --git a/pkg/config/channels.go b/pkg/config/channels.go index b3c46a93f..cbc7d7db1 100644 --- a/pkg/config/channels.go +++ b/pkg/config/channels.go @@ -1,18 +1,18 @@ package config type ChannelsConfig struct { - WhatsApp WhatsAppConfig `json:"whatsapp"` - Telegram TelegramConfig `json:"telegram"` - Discord DiscordConfig `json:"discord"` - MaixCam MaixCamConfig `json:"maixcam"` - QQ QQConfig `json:"qq"` - DingTalk DingTalkConfig `json:"dingtalk"` - Slack SlackConfig `json:"slack"` - Matrix MatrixConfig `json:"matrix"` - LINE LINEConfig `json:"line"` - OneBot OneBotConfig `json:"onebot"` - Pico PicoConfig `json:"pico"` - IRC IRCConfig `json:"irc"` + WhatsApp WhatsAppConfig `json:"whatsapp"` + Telegram TelegramConfig `json:"telegram"` + Discord DiscordConfig `json:"discord"` + MaixCam MaixCamConfig `json:"maixcam"` + QQ QQConfig `json:"qq"` + DingTalk DingTalkConfig `json:"dingtalk"` + Slack SlackConfig `json:"slack"` + Matrix MatrixConfig `json:"matrix"` + LINE LINEConfig `json:"line"` + OneBot OneBotConfig `json:"onebot"` + Pico PicoConfig `json:"pico"` + IRC IRCConfig `json:"irc"` } // GroupTriggerConfig controls when the bot responds in group chats. diff --git a/pkg/health/resource_tracker.go b/pkg/health/resource_tracker.go index 2ce4291a5..8ac247814 100644 --- a/pkg/health/resource_tracker.go +++ b/pkg/health/resource_tracker.go @@ -66,12 +66,12 @@ func (rt *ResourceTracker) logResources() { sysMB := float64(m.Sys) / 1024 / 1024 logger.InfoCF("SystemHealth", "Resource tracking telemetry", map[string]any{ - "goroutines": goroutines, - "memory_alloc_mb": allocMB, - "memory_total_mb": totalAllocMB, - "memory_sys_mb": sysMB, - "num_gc": m.NumGC, - "gc_pause_ns": m.PauseNs[(m.NumGC+255)%256], // Latest GC pause time + "goroutines": goroutines, + "memory_alloc_mb": allocMB, + "memory_total_mb": totalAllocMB, + "memory_sys_mb": sysMB, + "num_gc": m.NumGC, + "gc_pause_ns": m.PauseNs[(m.NumGC+255)%256], // Latest GC pause time "gc_pause_total_ns": m.PauseTotalNs, }) } diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index 1f2e82baf..df83ad263 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -34,9 +34,9 @@ var ( currentTimeFormat = "15:04:05" logger zerolog.Logger fileLogger zerolog.Logger - logFile *os.File - once sync.Once - mu sync.RWMutex + logFile *os.File + once sync.Once + mu sync.RWMutex ) func init() { diff --git a/pkg/migrate/sources/openclaw/common.go b/pkg/migrate/sources/openclaw/common.go index eb6cc0391..227dc159e 100644 --- a/pkg/migrate/sources/openclaw/common.go +++ b/pkg/migrate/sources/openclaw/common.go @@ -13,14 +13,14 @@ var migrateableDirs = []string{ } var supportedChannels = map[string]bool{ - "whatsapp": true, - "telegram": true, - "discord": true, - "maixcam": true, - "qq": true, - "dingtalk": true, - "slack": true, - "matrix": true, - "line": true, - "onebot": true, + "whatsapp": true, + "telegram": true, + "discord": true, + "maixcam": true, + "qq": true, + "dingtalk": true, + "slack": true, + "matrix": true, + "line": true, + "onebot": true, } diff --git a/pkg/tools/alpaca/alpaca.go b/pkg/tools/alpaca/alpaca.go index e7ddb1cdf..36cc30332 100644 --- a/pkg/tools/alpaca/alpaca.go +++ b/pkg/tools/alpaca/alpaca.go @@ -107,8 +107,8 @@ func (t *AlpacaTool) getPrice(symbol string) *tools.ToolResult { func (t *AlpacaTool) getSMA(symbol string) *tools.ToolResult { req := marketdata.GetBarsRequest{ - TimeFrame: marketdata.OneDay, - TotalLimit: 10, // 10-day simple moving average + TimeFrame: marketdata.OneDay, + TotalLimit: 10, // 10-day simple moving average } bars, err := t.marketData.GetBars(symbol, req) if err != nil { diff --git a/pkg/tools/mcp2cli.go b/pkg/tools/mcp2cli.go index a057630fb..58ac1f429 100644 --- a/pkg/tools/mcp2cli.go +++ b/pkg/tools/mcp2cli.go @@ -259,7 +259,7 @@ func splitQuoted(s string) []string { var quoteChar rune for _, r := range s { - if (r == '"' || r == '\'') { + if r == '"' || r == '\'' { if inQuotes && quoteChar == r { inQuotes = false } else if !inQuotes { diff --git a/pkg/tools/mcp2cli_test.go b/pkg/tools/mcp2cli_test.go index 7fc9fa438..177e42491 100644 --- a/pkg/tools/mcp2cli_test.go +++ b/pkg/tools/mcp2cli_test.go @@ -2,8 +2,8 @@ package tools import ( "context" - "testing" "github.com/stretchr/testify/assert" + "testing" ) func TestSplitQuoted(t *testing.T) { diff --git a/pkg/tools/web/fetch.go b/pkg/tools/web/fetch.go index 44d836f18..3bdb8966a 100644 --- a/pkg/tools/web/fetch.go +++ b/pkg/tools/web/fetch.go @@ -1,12 +1,12 @@ package web import ( - "jane/pkg/tools" "context" "encoding/json" "errors" "fmt" "io" + "jane/pkg/tools" "net" "net/http" "net/url" diff --git a/pkg/tools/web/search.go b/pkg/tools/web/search.go index d23b7d619..c40d29525 100644 --- a/pkg/tools/web/search.go +++ b/pkg/tools/web/search.go @@ -1,9 +1,9 @@ package web import ( - "jane/pkg/tools" "context" "fmt" + "jane/pkg/tools" ) type WebSearchTool struct {