diff --git a/cmd/picoclaw/main.go b/cmd/picoclaw/main.go index 2129662d7..c9e029ee4 100644 --- a/cmd/picoclaw/main.go +++ b/cmd/picoclaw/main.go @@ -404,7 +404,7 @@ func agentCmd() { } msgBus := bus.NewMessageBus() - agentLoop := agent.NewAgentLoop(cfg, msgBus, provider) + agentLoop := agent.NewAgentLoop(cfg, msgBus, provider, getConfigPath()) // Print agent startup info (only for interactive mode) startupInfo := agentLoop.GetStartupInfo() @@ -539,7 +539,7 @@ func gatewayCmd() { } msgBus := bus.NewMessageBus() - agentLoop := agent.NewAgentLoop(cfg, msgBus, provider) + agentLoop := agent.NewAgentLoop(cfg, msgBus, provider, getConfigPath()) // Print agent startup info fmt.Println("\nšŸ“¦ Agent Status:") diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index a1e90f66f..6934724ca 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -44,6 +44,7 @@ type AgentLoop struct { tools *tools.ToolRegistry running atomic.Bool summarizing sync.Map // Tracks which sessions are currently being summarized + configPath string // Path to config.json for persistence } // processOptions configures how a message is processed @@ -104,7 +105,7 @@ func createToolRegistry(workspace string, restrict bool, cfg *config.Config, msg return registry } -func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers.LLMProvider) *AgentLoop { +func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers.LLMProvider, configPath string) *AgentLoop { workspace := cfg.WorkspacePath() os.MkdirAll(workspace, 0755) @@ -149,6 +150,7 @@ func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers contextBuilder: contextBuilder, tools: toolsRegistry, summarizing: sync.Map{}, + configPath: configPath, } } @@ -204,6 +206,16 @@ func (al *AgentLoop) GetModel() string { func (al *AgentLoop) SetModel(model string) { al.model = model + al.cfg.Agents.Defaults.Model = model + al.saveConfig() +} + +func (al *AgentLoop) saveConfig() { + if al.configPath != "" { + if err := config.SaveConfig(al.configPath, al.cfg); err != nil { + logger.ErrorCF("agent", "Failed to save config", map[string]interface{}{"error": err.Error(), "path": al.configPath}) + } + } } // listModelsResponse builds a dynamic /models response from the current config. @@ -350,7 +362,7 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage) return fmt.Sprintf("āŒ Failed to switch to `%s`: %v", newProvider, err), nil } al.provider = newLLM - al.SetModel(newModel) + al.SetModel(newModel) // This also calls saveConfig() return fmt.Sprintf("āœ… Switched: `%s/%s` → `%s/%s`", oldProvider, oldModel, newProvider, newModel), nil }