feat(jetbrains): add background agents and subagent avatars - #14311
Conversation
Port VS Code's background-agents feature to the JetBrains plugin: a collapsible strip in the session header that lists running/finished background subagents, alongside a shared Strip base class the to-do strip now also uses. - New shared BackgroundJobDto and KiloSessionRpcApi.backgroundJobs / cancelBackgroundJob / promoteBackgroundJob. - Backend polls GET /kilocode/background-jobs (adaptive 1s/5s cadence, one poller shared across subscribers via shareIn) and posts cancel/promote via raw OkHttp, matching the sessionBoard precedent for routes newer than the generated client. - SessionModel.backgroundAgents / dismissBackgroundAgents feed a new BackgroundAgentsUpdated event; SessionController keeps the "needs input" badge live off the existing pending-permission tracking. - Strip (shared base), TodoStrip (extracted, now always visible instead of hidden inside the collapsible header body), and BackgroundAgentStrip (new): hover fill matching the collapsed session-view card header, horizontal-only scrolling for long content, full-row click to expand/collapse and to open a row's transcript, hidden entirely when there are no agents. - TaskToolView gets a "Continue in background" action, gated live on GET /experimental/capabilities (backgroundSubagents) so it never offers a promote that would fail against a CLI with the background- subagent kill switch off. - Agent Behavior settings: renamed the "Kilo Swarm" group to "Extended agents" (Swarm row unchanged); no new toggle yet, since background subagents have no CLI config key today, only an env var the pinned CLI can't be configured through from a setting. Tests: pure derivation (BackgroundAgentsTest), shared strip mechanics (StripTest), agent strip behavior + stress/leak (BackgroundAgentStrip* Test), controller wiring (BackgroundAgentControllerTest), CLI parsing and backend polling/HTTP (KiloCliDataParserTest, KiloBackendSession ManagerBackgroundJobsTest, KiloBackendAppServiceTest), and the capability-gated promote button (TaskToolViewTest).
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (5 files)
Resolved since the previous review (5)
Previous Review Summaries (4 snapshots, latest commit 79ae22f)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 79ae22f)Status: 5 Issues Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)SUGGESTION
Files Reviewed (25 files)
Previous review (commit 905f933)Status: No Issues Found | Recommendation: Merge Files Reviewed (3 files)
Previous review (commit 0bfcf75)Status: 3 Issues Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)WARNING
SUGGESTION
The 4 findings from the previous review are resolved in Files Reviewed (9 files)
Previous review (commit cfe8d2a)Status: 4 Issues Found | Recommendation: Address before merge Overview
Fix these issues in Kilo Cloud Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (43 files)
Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0 Review guidance: REVIEW.md from base branch |
- Evict the per-(directory, session) background-jobs flow cache when sharing stops, and clear it in stop(). WhileSubscribed halts the poller but retains the SharedFlow and its replayed jobs list, so the map previously grew with every session opened during an IDE run. - Take the capability probe off the load's critical path. It ran inside the load's coroutineScope, and since the generated client's call is blocking, a timeout could not release it — structured concurrency would wait on the socket and fail an otherwise-successful load. It now runs after Ready and publishes into a separate capabilities StateFlow, so it is also no longer part of AppData: folding it in churned AppData's identity, which updateConfig/refreshConfigState use to detect a concurrent reload, silently cancelling a config write. Also rethrow CancellationException instead of swallowing it. - Skip the agents strip update when the list is unchanged. The header re-syncs on every HeaderUpdated as tokens stream, so the retained strip was revalidating and repainting in the streaming hot path. - Reorder existing agent rows. Rows were updated in place, so a finished agent kept its slot above still-active ones instead of honoring BackgroundAgents.order's active-first intent. Tests: no-op update makes no dirty/invalid regions via a tracking RepaintManager, finished agents drop below active ones, a hung capability probe still reaches Ready, and the jobs flow still serves and shares one poller after the last collector left. The two strip tests were confirmed to fail without their fixes.
The previous reorder used setComponentZOrder, which reorders the AWT component array — but Stack lays out from its own entries list, so the active-first order never took effect visually. Re-add each row instead: Stack's addLayoutComponent re-appends, which is what actually moves a row in the layout. The earlier test passed against the broken fix because rowOrder() read body.components, the array Stack's layout does not consult. Replaced that test-only seam with an assertion on real laid-out y positions, which is the layout's actual output, and confirmed it fails without the fix. Also drop the dto() helper in KiloAppRpcApiImpl, unused since state() moved to combine().
|
Screenshots would be nice :) |
Will add, it was WIP on Friday, just wanted the badge. |
Give subagents deterministic animated identities across task cards, background rows, boards, and editor tabs. Keep background-agent actions visible with width-tracking rows and a five-row vertical scroll cap.
Prevent long agent titles from influencing strip width, align the status documentation with cancellation behavior, and replace tautological icon tests with rendered-pixel assertions.
Issue
No linked issue. This was scoped directly as JetBrains feature parity with the VS Code background-agent experience.
Context
The JetBrains plugin had no equivalent of the VS Code background-agents strip, no way to promote a running foreground subagent into the background, and no stable visual identity for child agents across the UI. This PR adds the complete background-job lifecycle and gives each subagent the same deterministic generated identity used by VS Code.
What Changed
Background Agent Lifecycle
Session Header UI
Generated Subagent Identities
FileIconProviderintegration so Kilo virtual-file kind icons reach editor tabs instead of falling back to the unknown-file question-mark icon.Settings
Rename the Kilo Swarm settings group to Extended agents while keeping the existing Swarm toggle unchanged. No additional background-agent setting is added because the current CLI exposes the feature through its experimental capability rather than a configuration key.
Implementation Constraints
The cancel, promote, capability, and background-job routes are newer than the pinned generated OpenAPI client. The backend therefore uses plain HTTP for these calls, matching the existing session-board boundary, while keeping shared DTO serialization isolated from frontend/backend classloaders.
Needs Input currently reflects pending child permissions. Child questions are not routed through the JetBrains controller today, so question-based waiting remains a known limitation.
How To Test
Verification
./gradlew typecheckpasses frompackages/kilo-jetbrains/../gradlew testpasses across frontend, backend, and shared modules: 347 test suites with zero failures../gradlew detektremains non-blocking because the repository has thousands of pre-existing baseline findings and no configured baseline; the documented JetBrains quality gates are typecheck and tests.Screenshots / Video
Checklist
jetbrains/v*changelog flow rather than.changeset