diff --git a/src/main/settings.ts b/src/main/settings.ts index 37546504f..7c2a5621a 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -107,6 +107,7 @@ export interface AppSettings { }; defaultOpenInApp?: OpenInAppId; hiddenOpenInApps?: OpenInAppId[]; + pinnedAgents?: string[]; } function getPlatformTaskSwitchDefaults(): { next: ShortcutBinding; prev: ShortcutBinding } { @@ -179,6 +180,7 @@ const DEFAULT_SETTINGS: AppSettings = { }, defaultOpenInApp: 'terminal', hiddenOpenInApps: [], + pinnedAgents: [], }; function getSettingsPath(): string { @@ -530,6 +532,15 @@ export function normalizeSettings(input: AppSettings): AppSettings { out.hiddenOpenInApps = []; } + // Pinned Agents + const rawPinned = (input as any)?.pinnedAgents; + if (Array.isArray(rawPinned)) { + const validated = rawPinned.filter((item) => typeof item === 'string'); + out.pinnedAgents = [...new Set(validated)]; + } else { + out.pinnedAgents = []; + } + return out; } diff --git a/src/renderer/components/MultiAgentDropdown.tsx b/src/renderer/components/MultiAgentDropdown.tsx index 6755562eb..be556542f 100644 --- a/src/renderer/components/MultiAgentDropdown.tsx +++ b/src/renderer/components/MultiAgentDropdown.tsx @@ -1,7 +1,8 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; +import { rpc } from '@/lib/rpc'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from './ui/tooltip'; -import { Info, ExternalLink } from 'lucide-react'; +import { Info, ExternalLink, Pin } from 'lucide-react'; import { type Agent } from '../types'; import { type AgentRun } from '../types/chat'; import { agentConfig } from '../lib/agentConfig'; @@ -24,8 +25,51 @@ export const MultiAgentDropdown: React.FC = ({ className = '', disabledAgents = [], }) => { - // Use agentConfig order directly (already properly ordered) - const sortedAgents = Object.entries(agentConfig); + // Setup state for pinned agents (persisted via rpc.appSettings) + const [pinnedAgents, setPinnedAgents] = useState([]); + + useEffect(() => { + let cancel = false; + rpc.appSettings.get().then((settings) => { + if (!cancel && settings?.pinnedAgents) { + setPinnedAgents(settings.pinnedAgents); + } + }); + return () => { + cancel = true; + }; + }, []); + + // handle pinning/unpinning + const togglePin = async (agentId: string, e: React.MouseEvent) => { + e.stopPropagation(); + + const previousState = [...pinnedAgents]; + + const next = pinnedAgents.includes(agentId) + ? pinnedAgents.filter((a) => a !== agentId) + : [...pinnedAgents, agentId]; + setPinnedAgents(next); + + try { + await rpc.appSettings.update({ pinnedAgents: next }); + } catch (error) { + console.error('Failed to save pinned agents', error); + // If the save fails, roll the UI back + setPinnedAgents(previousState); + } + }; + + // Dynamically sort agents + const sortedAgents = React.useMemo(() => { + return Object.entries(agentConfig).sort(([keyA], [keyB]) => { + const aPinned = pinnedAgents.includes(keyA); + const bPinned = pinnedAgents.includes(keyB); + if (aPinned && !bPinned) return -1; + if (!aPinned && bPinned) return 1; + return 0; + }); + }, [pinnedAgents]); const [open, setOpen] = useState(false); const [hoveredAgent, setHoveredAgent] = useState(null); const [runsSelectOpenFor, setRunsSelectOpenFor] = useState(null); @@ -130,7 +174,7 @@ export const MultiAgentDropdown: React.FC = ({ }} >
handleRowClick(agent)} >
@@ -154,56 +198,72 @@ export const MultiAgentDropdown: React.FC = ({ /> {config.name}
- {isSelected && ( -
- - - - - - + {isSelected && ( +
+ + + + + + +

+ Run up to {MAX_RUNS} instances of this agent to compare different + solutions.{' '} + e.stopPropagation()} + > + Docs + + +

+
+
+
+ )} + +
) : (