Skip to content

feat(code): system tray with running-agent badge#2384

Draft
fercgomes wants to merge 8 commits into
mainfrom
posthog-code/tray-running-agent-badge
Draft

feat(code): system tray with running-agent badge#2384
fercgomes wants to merge 8 commits into
mainfrom
posthog-code/tray-running-agent-badge

Conversation

@fercgomes
Copy link
Copy Markdown
Contributor

Summary

  • Adds a system tray icon visible while the app is open (menu bar on macOS, system tray on Windows/Linux) with a live badge showing the number of currently running agent sessions.
  • Click the tray icon to restore and focus the main window.
  • macOS shows the count via Tray.setTitle(). Windows/Linux swap between pre-rendered overlay PNGs in apps/code/build/tray/ (badge-0.png ships now; badge-1..9.png and badge-9plus.png are picked up automatically when design adds them — adapter falls back to badge-0.png until then). Tooltip always shows "N running agent(s)" so the count is at minimum hover-discoverable.

Architecture

  • New ITray platform interface in @posthog/platform/tray, fulfilled by ElectronTray adapter — services never import from electron directly.
  • New TrayService (apps/code/src/main/services/tray/service.ts) depends on ITray, AgentService, IMainWindow via constructor injection.
  • New AgentService.getRunningSessionCount() matches existing hasActiveSessions() semantics (promptPending || inFlightMcpToolCalls.size > 0).
  • New AgentServiceEvent.RunningCountChanged event emitted at the three transition points: prompt() enter, prompt() finally, and cleanupSession() when a running session is removed. TrayService is the only subscriber today.
  • TrayService.initialize() runs in initializeServices() in main; TrayService.dispose() runs in AppLifecycleService.doShutdown().
  • forge.config.ts extraResource now includes build/tray and build/app-icon.png so the assets ship with packaged builds.

Test plan

  • pnpm dev:code — tray icon appears on boot in menu bar (macOS) / system tray (Win/Linux); tooltip reads 0 running agents.
  • Start one agent → macOS shows 1 next to the icon, tooltip becomes 1 running agent.
  • Start three concurrent agents → badge reads 3. Finish one → 2. Finish all → badge clears.
  • Spin up 10+ sessions → Win/Linux shows badge-9plus.png (or falls back to badge-0.png until overlays designed), macOS shows the literal count, tooltip reads 10 running agents.
  • Minimize or background the main window → click tray icon → window restores and focuses.
  • Quit the app → tray icon disappears.
  • pnpm --filter code make → install the packaged build → repeat the above with packaged paths (process.resourcesPath/tray/...).
  • pnpm --filter code typecheck
  • pnpm --filter code test — AgentService tests pass (1505 passing locally; archive integration failures are pre-existing sandbox-only artifacts).

Follow-ups

  • Design badge-1.pngbadge-9.png, badge-9plus.png for Windows/Linux. No code change needed — adapter picks them up automatically.
  • Optional macOS template image (badge-0.template.png) for proper dark/light menu-bar adaptation.

fercgomes added 8 commits May 26, 2026 20:05
Adds a system tray icon (menu bar on macOS, tray on Windows/Linux) that
displays the count of currently running agent sessions. On macOS the
count is shown via `Tray.setTitle()` next to the icon; on Windows and
Linux the icon is swapped between pre-rendered overlays in
`apps/code/build/tray/`. Tooltip is always set to `"N running agent(s)"`,
so the count is at least hover-discoverable on every platform until the
designed overlay PNGs land.

- New `ITray` platform port + `ElectronTray` adapter
- New `TrayService` listens to a new `AgentService.RunningCountChanged`
  event and refreshes the badge live
- Click on the tray icon restores and focuses the main window
- Tray is initialized after services come up and disposed in graceful exit

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
The 1024×1024 source PNG was being handed to `Tray` unmodified, so it
overflowed the menu bar. Resize every loaded image to 22px tall on macOS
and 16px elsewhere, and set the template flag on macOS so the icon
adapts to light/dark menu bars.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
`setTemplateImage(true)` on a fully-opaque colored PNG renders the
silhouette as a solid block that's nearly invisible against the dark
menu bar. Drop the template flag and resize to 16px (Electron's
documented tray target) with the best quality filter.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
Adds a proper macOS template image (hedgehog silhouette extracted from
the brand icon by alpha-thresholding the white background) at 22/44/66
px so Electron auto-picks the right scale. Template mode lets the icon
adapt to light/dark menu bar like other system icons. Windows/Linux
still use the colored `badge-N.png` set at 16 px.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
The previous template kept the brand icon's internal white highlights
as transparent cutouts, which read as a "bezelled" or carved hedgehog
in the menu bar. Fill internal holes and slightly dilate the mask so
the silhouette renders as one flat solid shape.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
`promptPending` is only true while the agent is actively generating — a
quick prompt flickered the badge for under a second and a longer one
hid it again the moment generation finished. Switch the running count
to `sessions.size`, which stays stable from session creation through
idle/cancellation. Emit `RunningCountChanged` when a session is added
in `getOrCreateSession` (was previously only emitted around prompt())
and unconditionally on `cleanupSession`.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
The 2-iteration binary_dilation I added to smooth anti-aliased edges
also expanded the silhouette by ~2px on every side, which read as a
visible border around the hedgehog. Generate the template from just
the filled-holes mask with no dilation.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
Render the rounded-square area as the solid template and cut the
hedgehog out of it instead of the other way around — the negative
space reads cleaner at menu-bar size than a small lumpy hedgehog
shape on its own.

Generated-By: PostHog Code
Task-Id: 01d444b5-b5d4-426a-9ae3-57ba28e54e09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant