feat: add ability to pin agents which will be visible everytime user …#1353
feat: add ability to pin agents which will be visible everytime user …#1353AniketR10 wants to merge 2 commits intogeneralaction:mainfrom
Conversation
…creates a new Task
|
@AniketR10 is attempting to deploy a commit to the General Action Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR adds the ability to pin agents in the Key issues found:
Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| src/renderer/components/MultiAgentDropdown.tsx | Adds pin/unpin UI to the agent dropdown with optimistic state updates, but the state is not rolled back when the settings save fails, and a comment incorrectly references localStorage instead of app settings. |
| src/main/settings.ts | Adds pinnedAgents field to AppSettings interface, default settings, and normalization — correctly typed and guarded, but missing deduplication that the adjacent hiddenOpenInApps block applies. |
Sequence Diagram
sequenceDiagram
participant U as User
participant D as MultiAgentDropdown
participant RPC as rpc.appSettings
participant S as settings.ts (main)
U->>D: Opens dropdown (component mounts)
D->>RPC: get()
RPC->>S: getAppSettings()
S-->>RPC: AppSettings { pinnedAgents: [...] }
RPC-->>D: settings
D-->>D: setPinnedAgents(settings.pinnedAgents)
U->>D: Clicks Pin button for an agent
D-->>D: setPinnedAgents(next) [optimistic]
D->>RPC: update({ pinnedAgents: next })
RPC->>S: updateAppSettings(partial)
S-->>S: normalizeSettings() → persists to disk
alt Save succeeds
RPC-->>D: updated settings
else Save fails
RPC-->>D: throws error
D-->>D: console.error (no state rollback ⚠️)
end
Last reviewed commit: 467935b
| setPinnedAgents(next); | ||
|
|
||
| try { | ||
| await rpc.appSettings.update({ pinnedAgents: next }); | ||
| } catch (error) { | ||
| console.error('Failed to save pinned agents', error); | ||
| } |
There was a problem hiding this comment.
No rollback on settings save failure
setPinnedAgents(next) is called optimistically before the async rpc.appSettings.update call. If the update fails, the UI reflects the pin as toggled but the setting is never persisted — on the next app launch (or the next time this component mounts) the pin will silently disappear, leaving the user confused. The state should be rolled back when the call fails.
| setPinnedAgents(next); | |
| try { | |
| await rpc.appSettings.update({ pinnedAgents: next }); | |
| } catch (error) { | |
| console.error('Failed to save pinned agents', error); | |
| } | |
| setPinnedAgents(next); | |
| try { | |
| await rpc.appSettings.update({ pinnedAgents: next }); | |
| } catch (error) { | |
| console.error('Failed to save pinned agents', error); | |
| setPinnedAgents(pinnedAgents); // rollback optimistic update | |
| } |
| // Setup state for pinned agents (using localStorage to remember preferences) | ||
| const [pinnedAgents, setPinnedAgents] = useState<string[]>([]); |
There was a problem hiding this comment.
Misleading comment references localStorage
The comment says "using localStorage to remember preferences" but the implementation reads from and writes to the Electron app settings via rpc.appSettings, not localStorage. This could mislead future contributors.
| // Setup state for pinned agents (using localStorage to remember preferences) | |
| const [pinnedAgents, setPinnedAgents] = useState<string[]>([]); | |
| // Setup state for pinned agents (persisted in app settings) | |
| const [pinnedAgents, setPinnedAgents] = useState<string[]>([]); |
| // Pinned Agents | ||
| const rawPinned = (input as any)?.pinnedAgents; | ||
| if (Array.isArray(rawPinned)) { | ||
| out.pinnedAgents = rawPinned.filter((item) => typeof item === 'string'); | ||
| } else { | ||
| out.pinnedAgents = []; | ||
| } |
There was a problem hiding this comment.
Missing deduplication for pinnedAgents
The hiddenOpenInApps normalization immediately above uses [...new Set(validated)] to deduplicate entries. pinnedAgents skips this step, so a corrupt or manually edited settings file could contain duplicate agent IDs. Duplicates won't break rendering but will cause an agent to appear pinned even after being "unpinned" (since filter only removes it once per call).
| // Pinned Agents | |
| const rawPinned = (input as any)?.pinnedAgents; | |
| if (Array.isArray(rawPinned)) { | |
| out.pinnedAgents = rawPinned.filter((item) => typeof item === 'string'); | |
| } else { | |
| out.pinnedAgents = []; | |
| } | |
| // Pinned Agents | |
| const rawPinned = (input as any)?.pinnedAgents; | |
| if (Array.isArray(rawPinned)) { | |
| out.pinnedAgents = [...new Set(rawPinned.filter((item) => typeof item === 'string'))]; | |
| } else { | |
| out.pinnedAgents = []; | |
| } |
…creates a new Task
Summary
Briefly describe what this PR does and why
Fixes
Fixes #1273
Snapshot
Type of change
Mandatory Tasks
Checklist
pnpm run format)pnpm run lint)