Skip to content

feat: unify local + external agents in Running agents sidebar tree - #283

Open
NovakPAai wants to merge 3 commits into
mainfrom
claude/novak-running-agents-unified-tree
Open

feat: unify local + external agents in Running agents sidebar tree#283
NovakPAai wants to merge 3 commits into
mainfrom
claude/novak-running-agents-unified-tree

Conversation

@NovakPAai

Copy link
Copy Markdown
Collaborator

Summary

The "Running agents" sidebar tree only ever listed agents running in external native terminals (a deliberate 7.15.0/#268 change) — an agent running inside codbash's own in-app Workspace pane silently disappeared from it. A project with both an in-app Claude session and an iTerm one only showed half the picture, which read as confusing/inconsistent grouping (see conversation screenshot: market-analytics/~/codbash rows with some dimmed "idle" dots that read as ambiguous "maybe gone").

  • _wsRunningGroups(mode) replaces _wsRunningByProject(): still built from activeSessions (a live ps-scan re-polled every 5s — an exited process is simply absent on the next tick, so there's no separate "ghost" filtering to get right), but now includes local (in-codbash) agents alongside external ones instead of dropping them.
  • Grouping is now a toggle — project → agent (default, same as before) or agent → project — a compact 2-button segmented control in the tree header, persisted to localStorage['codedash-running-group'] (per-browser display preference, not a synced setting).
  • Rows are color-coded by where they run: blue dot = inside codbash, orange dot = external native terminal (iTerm/Terminal.app/Warp/cmux/Windows Terminal/etc). Idle (waiting for input, still a live process) still dims to muted gray on top of either color, so dimmed reliably means "idle", not a collision with the local/external legend.
  • jumpToRunningAgent now dispatches on the local tag: local agents jump straight to their Workspace tab/pane (found by matching cwd against the live pane list, so a tab opened after the tree last rendered still resolves); external agents keep the existing /api/focus-by-PID path (never spawns a blank terminal, per the existing design doc's rule).

Updates docs/design/running-agents-external.md (amended, not rewritten — the external-focus mechanics section is unchanged) and CLAUDE.md, both of which documented "external only" as intentional. Updates test/running-agents-external.test.js for the new function name/shape.

Test plan

  • node --test "test/**/*.test.js" — 260 passed, 1 skipped (win32-only)
  • Ran the app locally, verified in a real browser: project-mode grouping shows all 5 running Claude sessions across 4 projects with orange (external) dots; toggled to agent-mode grouping — single "Claude" header with 5 project rows underneath; toggle choice persists across a full page reload
  • Internal (blue, in-codbash) dot + jump-to-pane path verified by code review + the updated unit tests, not a live screenshot — spawning a real competing agent inside an in-app pane just to screenshot it isn't worth the side effect

🤖 Generated with Claude Code

The tree only ever showed agents in external native terminals — an agent
running inside codbash's own Workspace pane silently disappeared from it,
so a project with both an in-app Claude session and an iTerm one only
showed half the picture. That asymmetry (plus dimmed "idle" rows reading
as ambiguous "maybe gone") is what read as messy/hard-to-trust grouping.

- _wsRunningGroups(mode) replaces _wsRunningByProject(): still built from
  activeSessions (a live ps-scan re-polled every 5s, so an exited process
  is simply absent next tick — no separate "ghost" filtering needed), but
  now includes local (in-codbash) agents alongside external ones instead
  of dropping them.
- Grouping is now a per-browser toggle (project → agent, or agent →
  project), persisted to localStorage['codedash-running-group'], exposed
  as a compact 2-button segmented control in the tree header.
- Rows are color-coded by where they run: blue dot = inside codbash,
  orange dot = external native terminal (iTerm/Terminal.app/Warp/cmux).
  Idle still dims to muted gray, on top of either color.
- jumpToRunningAgent now dispatches on the `local` tag: local agents jump
  straight to their Workspace tab/pane (found by matching cwd against the
  live pane list); external agents keep the existing /api/focus path.

Updates the design doc and CLAUDE.md (which documented "external only" as
intentional) and the existing test suite for the new function names/shape.
The first pass grouped project/agent as a flat 2-level list — one header,
then every session underneath as a same-labeled row ("Claude", "Claude",
…). That read as alternating noise (session, agent, session, agent) rather
than a real hierarchy, especially once a project had 2+ live sessions of
the same agent.

_wsRunningTree(mode) replaces _wsRunningGroups(mode): a real 3-level tree
— outer group -> inner group -> individual sessions — built via a small
generic _wsGroupBy() applied twice. mode:'project' nests project -> agent
-> sessions; mode:'agent' nests the mirror, agent -> project -> sessions
(re-parenting the whole tree, not just relabeling a flat list).

A project+agent pair with exactly one live session collapses its leaf row
into the subgroup row itself (.ws-run-leaf) — no redundant single-child
row. Once it holds 2+ sessions, the subgroup renders as a real subheader
and each session gets its own leaf row, labeled via _wsSessionLeafLabel
(a live pane's name if local and matched, else the session-id prefix —
same convention as the session cards' "Resume last session (id12345)" —
else a bare pid) so same-project/same-agent sessions read as genuinely
distinct instead of the same label repeated.
@NovakPAai

Copy link
Copy Markdown
Collaborator Author

Follow-up commit: turned this into an actual 3-level tree instead of a flat project→(agent rows) / agent→(project rows) list.

The flat version still read as "session, agent, session, agent" once a project had 2+ live sessions of the same tool — every session showed up as a same-labeled row directly under the project header, no real hierarchy. Now:

  • Project mode: project → agent kind → individual sessions
  • Agent mode: agent kind → project → individual sessions (true mirror — re-parents the whole tree, not a relabel)
  • A project+agent pair with exactly one live session collapses to a single row (no pointless 1-child nesting) and takes that session's real color/idle state directly
  • A pair with 2+ sessions gets a real subheader + one leaf row per session, each labeled distinctly (pane name if local and matched, else session-id prefix, else pid) — no more identical "Claude"/"Claude" rows

Verified locally with a real 2-session case (market-analytics running two Claude sessions) in both grouping directions — screenshots match the requested project → agent → sessions / agent → project → sessions shape exactly. Full suite: 261 passed, 1 skipped (win32-only).

Top-level (L1) groups — project in project-mode, agent kind in agent-mode
— now start collapsed. Clicking a header expands it in place to reveal
its agent/project subgroups and individual sessions; the same accordion
logic applies to both grouping directions.

- _wsRunExpanded (in-memory, keyed `mode|groupKey`) tracks open/closed per
  group so switching the Project/Agent toggle doesn't share expand state
  across the two different hierarchies.
- _wsToggleRunGroup flips a `collapsed` class directly on the group's
  wrapper DOM node instead of forcing a full tree rebuild — cheap, and a
  later rebuild (triggered by a real activeSessions change) re-reads
  _wsRunExpanded so the user's open/closed choices survive it.
- The L1 header's click now means "toggle" rather than "jump to the first
  session" — with a header disclosing multiple children there's no single
  unambiguous default target, so the jump action lives entirely on leaf
  rows (.ws-run-l2.ws-run-leaf / .ws-run-l3), unchanged from before.
- Basic keyboard support: role="button", aria-expanded, Enter/Space to
  toggle.
@NovakPAai

Copy link
Copy Markdown
Collaborator Author

Added the accordion: top-level groups (project or agent, depending on the toggle) now render collapsed by default. Clicking a header expands it in place to reveal its agent/project subgroups and sessions — same logic in both directions.

  • Clicking the header toggles expand/collapse (cheap DOM class flip, no full rebuild); the "jump to a session" action now lives entirely on the leaf rows, since a collapsed header disclosing several children has no single obvious default target.
  • Expand/collapse choice is tracked per group (mode|groupKey) so switching Project↔Agent doesn't mix up state between the two hierarchies, and survives a background rebuild when a new session starts elsewhere.
  • Basic keyboard support (role="button", aria-expanded, Enter/Space).

Verified locally: collapsed by default in both Project and Agent mode; expanding market-analytics (2) reveals Claude (2) → ffa52a5e / 160a8f32; expanding Claude (3) in agent-mode shows the mirrored codbash (collapsed leaf) / market-analytics (2) → ... structure. Full suite: 264 passed, 1 skipped (win32-only).

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