Skip to content

fix(jetbrains): wrap Swarm board messages, keep board open, add copy all - #14452

Merged
kirillk merged 2 commits into
mainfrom
fix/jetbrains-swarm-board-wrap-copy
Sep 22, 2026
Merged

kirillk merged 2 commits into
mainfrom
fix/jetbrains-swarm-board-wrap-copy

Conversation

@kirillk

@kirillk kirillk commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Issue

Fixes #

Context

The JetBrains Kilo Swarm board (SessionBoardDialog) had three UX problems reported by a user:

  1. Message bodies were clipped/faded to a single line, so most messages were unreadable without hovering for a tooltip.
  2. Clicking an agent row closed the whole board dialog before opening that agent's editor tab, making it hard to jump between several agents.
  3. There was no way to copy the full conversation for sharing/debugging outside the IDE.

Implementation

  • Wrapping: Added an opt-in wrapDescription flag to the shared ActiveListConfig/ActiveListRenderer (used by many other lists — settings, history, Agent Manager) so only the Swarm board's rows grow to their full wrapped height; every other caller is unaffected since the flag defaults to false. The renderer does a real (not just preferred-size) layout pass at the list's current width before reading the row's preferred size, so Swing's variable-height list measurement (ActiveListRowHeight.PREFERRED) gets the true wrapped height. Along the way I found and fixed a latent measurement bug: the discovery pass initially used Short.MAX_VALUE as a placeholder height, which leaked into LayeredOverlayPanel's absolutely-positioned overlay/blocker children (no layout manager, so in a renderer that's never been added to a real window they fall back to reporting their current bounds as "preferred size"), corrupting the measured row height. Fixed by using a minimal placeholder height instead, since column widths never depend on it. SessionBoardDialog also stopped flattening body.replace("\n", " "), so multi-line messages keep their line breaks.
  • Non-closing navigation: Removed the close(OK_EXIT_CODE) call from the row-click handler. The board is already modeless, so it now stays open behind the newly opened/focused subagent editor tab. Click targeting was also fixed: a route opens whichever endpoint is the actual subagent (main -> agent and agent -> main both open agent), a subagent-to-subagent route opens the sender, and main/ALL-only routes stay inert.
  • Copy all: Added a Copy all button next to Reset. It fetches the entire board history independent of what the dialog has paged in so far (starting fresh from the newest page, then walking every older page via the server's exclusive cursor, de-duplicating by message id), formats each message as sender -> recipient [TYPE]\nbody, and writes it to the clipboard via CopyPasteManager with a small balloon confirmation. A fetch/clipboard failure never publishes a partial copy and re-enables the actions. Added the new localized strings across all 19 locale bundles.

Screenshots / Video

GIF Recording 2026-09-22 at 12 06 50 PM

How to Test

Manual/local verification

  • Ran ./gradlew :frontend:test (full suite) and ./gradlew typecheck from packages/kilo-jetbrains/ — both pass.
  • Iteratively debugged the wrapping height calculation with a throwaway instrumented test against the real Swing renderer (ActiveListRenderer/LayeredOverlayPanel) until row heights reflected the wrapped text at both wide and narrow list widths; removed all debug instrumentation afterward and reran the suite clean.

Reviewer test steps

  1. In a session with subagents, open the Swarm board (board icon in the session header).
  2. Confirm long/multi-line messages now wrap to their full height instead of being clipped to one line.
  3. Click a row where the sender or recipient is a subagent (including main -> agent and agent -> main variants) and confirm the agent's editor tab opens/focuses while the board dialog stays open.
  4. Click Copy all, then paste into a plain-text editor and confirm every loaded and not-yet-loaded (older, paginated) message appears in sender -> recipient [TYPE] / body format, oldest first.
  5. Resize the board dialog narrower/wider and confirm rows reflow.

Blocked checks and substitute verification

  • Manual sandbox verification (./gradlew --no-configuration-cache runIdeSplitMode) was not run in this environment; substitute verification was the full automated test suite (ActiveListRowHeightTest, SessionBoardDialogTest, BoardDialogSizeTest, KiloBundleLocaleTest, and the full :frontend:test run), which exercises the real Swing renderer, real layout managers, and a fake paginated RPC end-to-end.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

Get in Touch

- Extend the shared active-list renderer with an opt-in wrapDescription
  mode so a row's body wraps to its full height instead of clipping to
  one line. Existing callers (settings, history, Agent Manager) are
  unaffected since the flag defaults to false.
- Opt the Swarm board into wrapping and stop flattening message bodies
  to a single line, preserving newlines.
- Keep the modeless board open when a row is clicked: open whichever
  route endpoint is the subagent (both main -> agent and agent -> main
  open agent) instead of closing the dialog.
- Add a Copy all action that fetches the full paginated board history
  and copies it to the clipboard as plain text.
- Add localized strings for the new action across all locale bundles.
- Add/extend tests for wrapping, click routing, and copy-all
  (including pagination and failure handling).
@kirillk
kirillk merged commit e9563f7 into main Sep 22, 2026
23 checks passed
@kirillk
kirillk deleted the fix/jetbrains-swarm-board-wrap-copy branch September 22, 2026 18:22
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.

2 participants