diff --git a/config/config.example.json b/config/config.example.json index aa75c8338..06fead4eb 100644 --- a/config/config.example.json +++ b/config/config.example.json @@ -6,7 +6,8 @@ "model": "glm-4.7", "max_tokens": 8192, "temperature": 0.7, - "max_tool_iterations": 20 + "max_tool_iterations": 20, + "timeout": 120 } }, "channels": { diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index f3dd94090..2979fb618 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -41,6 +41,7 @@ type AgentLoop struct { contextBuilder *ContextBuilder tools *tools.ToolRegistry running atomic.Bool + timeout int summarizing sync.Map // Tracks which sessions are currently being summarized } @@ -143,6 +144,7 @@ func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers maxIterations: cfg.Agents.Defaults.MaxToolIterations, sessions: sessionsManager, state: stateManager, + timeout: cfg.Agents.Defaults.Timeout, contextBuilder: contextBuilder, tools: toolsRegistry, summarizing: sync.Map{}, @@ -674,7 +676,11 @@ func formatToolsForLog(tools []providers.ToolDefinition) string { // summarizeSession summarizes the conversation history for a session. func (al *AgentLoop) summarizeSession(sessionKey string) { - ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) + summarizeTimeout := al.timeout + if summarizeTimeout <= 0 { + summarizeTimeout = 120 + } + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(summarizeTimeout)*time.Second) defer cancel() history := al.sessions.GetHistory(sessionKey) diff --git a/pkg/config/config.go b/pkg/config/config.go index d76ec8095..12f304cf3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -66,6 +66,7 @@ type AgentDefaults struct { MaxTokens int `json:"max_tokens" env:"PICOCLAW_AGENTS_DEFAULTS_MAX_TOKENS"` Temperature float64 `json:"temperature" env:"PICOCLAW_AGENTS_DEFAULTS_TEMPERATURE"` MaxToolIterations int `json:"max_tool_iterations" env:"PICOCLAW_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"` + Timeout int `json:"timeout" env:"PICOCLAW_AGENTS_DEFAULTS_TIMEOUT"` } type ChannelsConfig struct { @@ -225,6 +226,7 @@ func DefaultConfig() *Config { MaxTokens: 8192, Temperature: 0.7, MaxToolIterations: 20, + Timeout: 120, }, }, Channels: ChannelsConfig{ diff --git a/pkg/providers/http_provider.go b/pkg/providers/http_provider.go index 17eb6214c..a4361d6eb 100644 --- a/pkg/providers/http_provider.go +++ b/pkg/providers/http_provider.go @@ -27,9 +27,12 @@ type HTTPProvider struct { httpClient *http.Client } -func NewHTTPProvider(apiKey, apiBase, proxy string) *HTTPProvider { +func NewHTTPProvider(apiKey, apiBase, proxy string, timeout int) *HTTPProvider { + if timeout <= 0 { + timeout = 120 + } client := &http.Client{ - Timeout: 120 * time.Second, + Timeout: time.Duration(timeout) * time.Second, } if proxy != "" { @@ -429,5 +432,5 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) { return nil, fmt.Errorf("no API base configured for provider (model: %s)", model) } - return NewHTTPProvider(apiKey, apiBase, proxy), nil + return NewHTTPProvider(apiKey, apiBase, proxy, cfg.Agents.Defaults.Timeout), nil }