diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index b01038a8d..e4f6abc64 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -1469,6 +1469,9 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage) // Set its ID to match the routed agent so prompts and logs match agent.ID = route.AgentID + // Inject media store so tools (like send_file) can function + agent.Tools.SetMediaStore(al.mediaStore) + // Re-register shared tools (web, message, spawn) to this transient agent // We pass a mini-registry containing only this agent registerSharedTools(al, al.cfg, al.bus, &AgentRegistry{agents: map[string]*AgentInstance{agent.ID: agent}}, baseAgent.Provider) diff --git a/pkg/config/config.go b/pkg/config/config.go index f84c949ee..26b15de9e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1259,6 +1259,29 @@ func (c *Config) SecurityCopyFrom(path string) error { return loadSecurityConfig(c, securityPath(path)) } +func MergeAPIKeys(apiKey string, apiKeys []string) []string { + seen := make(map[string]struct{}) + var all []string + + if k := strings.TrimSpace(apiKey); k != "" { + if _, exists := seen[k]; !exists { + seen[k] = struct{}{} + all = append(all, k) + } + } + + for _, k := range apiKeys { + if trimmed := strings.TrimSpace(k); trimmed != "" && trimmed != "[NOT_HERE]" { + if _, exists := seen[trimmed]; !exists { + seen[trimmed] = struct{}{} + all = append(all, trimmed) + } + } + } + + return all +} + // expandMultiKeyModels expands ModelConfig entries with multiple API keys into // separate entries for key-level failover. Each key gets its own ModelConfig entry, // and the original entry's fallbacks are set up to chain through the expanded entries.