feat: Parallel sessions + multi-agent, with per-profile avatars#657
Conversation
Greptile SummaryThis PR introduces true parallel multi-session support and per-profile avatars. Conversations no longer abort when a new one starts; each run is tracked by a renderer-minted
Confidence Score: 5/5The change is safe to merge; the core multi-run routing is well-isolated and the tricky concurrency edges (double-click resume, renderer-gone abort, cross-run event bleed) all have explicit guards. The per-runId event filtering in useChatIPC and the activeRuns map in the main process are the heart of the change, and both are implemented correctly. The resumingRef deduplication prevents the double-mount race on session resume. handleClear properly resets hermesSessionId after clearing. The two observations flagged are about an avatar preview lag and a post-mount memory redundancy — neither affects correctness of the streaming or session-switching logic. src/renderer/src/screens/Agents/Agents.tsx for the avatar optimistic-update gap; src/renderer/src/screens/Layout/Layout.tsx for the retained seed array. Important Files Changed
|
…sume - Agents: handlePickColor / handleRemoveAvatar now surface IPC failures instead of silently leaving an optimistic, possibly-wrong UI. - Agents: avatar upload errors use a dedicated message (uploadImageFailed) rather than the profile-creation string. - Layout: guard handleResumeSession with an in-flight Set so a rapid double-click can't mount two tabs for the same session (the live-run check straddles an await). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Parallel sessions + multi-agent, with per-profile avatars
Adds true multi-session / multi-agent support to the desktop, plus profile
avatars & colors and a handful of related UX cleanups.
Highlights
Parallel / background sessions (multi-agent)
the in-flight one. Conversations keep running in the background, across
profiles, and you can jump back to watch them stream live.
(agent avatar + title, spinner while generating), with a close (×) button.
Click a tab to switch (and follow that agent); closing stops the run if it's
still working and never leaves the view empty.
runIdthreaded throughthe main process; every streaming IPC event is tagged with it so concurrent
runs never bleed into each other's transcript.
Profile avatars & colors
128px) and an accent color from a flat palette; unset profiles get a
stable, name-derived default color.
ProfileAvatarreplaces the generic icons in the nav switcher, theactive-sessions bar, and the Agents/Profiles page.
Danger zone (delete profile + clear warning). Active profile is shown with
an animated green outline instead of a badge.
UX cleanups
reclaim vertical space; new-chat/delete live in the sidebar / sessions page.
gateway) — a conversation starts only via the Chat button.
Implementation notes
Main / preload
src/main/index.ts— replaced the singlecurrentChatAbortwith aMap<runId, abort>;send-messagetakes arunIdand tags every event;abort-chattargets one run; shutdown aborts all.src/main/profile-meta.ts(new) —profile-meta.jsonper profile dir(
{ color, avatar }) + setters;profiles.tsreturns resolvedcolor/avatar.src/shared/profileColors.ts(new) — flat palette +defaultColorForName,shared by main and renderer.
src/preload/*— threadrunIdthrough send/abort/listeners; add profilecolor/avatar IPC.
Renderer
Chat.tsxis now per-run and self-contained (owns its messages);useChatIPCfilters events by
runId;useChatActionsthreadsrunId.Layout.tsxholds the globalruns[]+activeRunIdand all run lifecycle(new/switch/resume/close);
chatRuns.ts(new) holds the pure run helpers.ActiveSessionsBar.tsx,common/ProfileAvatar.tsx;utils/imageResize.tsfor avatar downscaling.ChatHeader.tsxremoved.Tests
tests/chat-runs.test.ts— run-registry helpers + therunIdevent filter.tests/profile-colors.test.ts— palette membership + deterministic defaults.Agents.test.tsxfor the new edit-modal delete flow.npm run typecheck(web + node) andnpm run lintpass; pre-existingunrelated test failures (ipc-handlers, reconcile-streamed-with-db,
tool-activity-group-title) are untouched by this branch.
Not yet verified
the live app has not been done here — logic is covered by typecheck/tests and
review. Worth a manual pass before merge.