Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/background-worktree-activity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---

Keep Agent Manager worktree spinners active while background agents are running.
36 changes: 16 additions & 20 deletions packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { forkSession } from "./fork-session"
import { AgentManagerVisiblePresence } from "./am-visible-presence"
import { continueInWorktree } from "./continue-in-worktree"
import { WorktreeDiffController } from "./worktree-diff-controller"
import { createWorktreeActivity } from "./worktree-activity"
import { sendDiffBranches as postDiffBranches } from "./project/diff-branches"
import { WorktreeImporter } from "./worktree-importer"
import {
Expand Down Expand Up @@ -106,8 +107,7 @@ export class AgentManagerProvider implements Disposable {
private cachedWorktreeStats: { type: "agentManager.worktreeStats"; stats: WorktreeStats[] } | undefined
private cachedLocalStats: { type: "agentManager.localStats"; stats: LocalStats } | undefined
private unsubTool: (() => void) | undefined
private unsubStatus: (() => void) | undefined
private unsubSessions: (() => void) | undefined
private activity: ReturnType<typeof createWorktreeActivity>
private unsubFont: (() => void) | undefined
private unsubProjects: (() => void) | undefined
/** Scratch set returned when no active context exists; mutations are discarded. */
Expand Down Expand Up @@ -284,22 +284,15 @@ export class AgentManagerProvider implements Disposable {
(event) => (event as { type?: string }).type === "kilocode.agent_manager.start",
(event, directory) => this.onToolEvent(event, directory),
)
this.unsubStatus = this.connectionService.onEventFiltered(
(event) => (event as { type?: string }).type === "session.status",
(event) => this.onSessionStatus(event),
)
this.unsubSessions = this.connectionService.onEventFiltered(
(event) => {
const type = (event as { type?: string }).type
return (
type === "session.created" ||
type === "session.updated" ||
type === "session.deleted" ||
type === "session.error"
)
},
(event) => this.onSessionLifecycle(event),
)
this.activity = createWorktreeActivity({
connection: this.connectionService,
paths: () =>
[...this.contexts.values()].flatMap((ctx) => ctx.peekState()?.getWorktrees() ?? []).map((wt) => wt.path),
post: (active) => this.postToWebview({ type: "agentManager.worktreeActivity", active }),
status: (event) => this.onSessionStatus(event),
lifecycle: (event) => this.onSessionLifecycle(event),
log: (err) => this.log("Failed to load worktree activity:", err),
})
}
/**
* Keep each project's cached sidebar session list in sync with backend
Expand Down Expand Up @@ -906,6 +899,7 @@ export class AgentManagerProvider implements Disposable {
// instance are reaped by the router's generation guard.
void this.terminalRouter.dispose()
this.scripts.manager.snapshot()
void this.activity.sync(true)
this.log(
`onRequestState: stateReady=${this.stateReady ? "pending" : "missing"}, state=${this.state ? "ok" : "missing"}`,
)
Expand Down Expand Up @@ -1428,6 +1422,7 @@ export class AgentManagerProvider implements Disposable {
activeTarget: state.getActiveTarget(),
...(active ? this.runStateFor(target) : {}),
})
void this.activity.sync()
void pushProjectSessions(target, this.panel?.sessions, (message) => this.postToWebview(message))
if (!active) return

Expand All @@ -1441,6 +1436,7 @@ export class AgentManagerProvider implements Disposable {

/** Push empty state when the folder is not a git repo or has no folder open. */
private pushEmptyState(): void {
void this.activity.sync()
this.staleWorktreeIds.clear()
this.postToWebview({
type: "agentManager.state",
Expand Down Expand Up @@ -1621,6 +1617,7 @@ export class AgentManagerProvider implements Disposable {

private pushProjects(): void {
const projects = this.contexts.snapshots()
void this.activity.sync()
this.postToWebview({
type: "agentManager.projects",
multiProject: this.host.multiProject(),
Expand Down Expand Up @@ -1872,8 +1869,7 @@ export class AgentManagerProvider implements Disposable {
await this.stateReady?.catch((err) => this.log("dispose: stateReady rejected:", err))
await this.contexts.dispose()
this.unsubTool?.()
this.unsubStatus?.()
this.unsubSessions?.()
this.activity.dispose()
this.unsubFont?.()
this.unsubProjects?.()
this.unsubDestination?.()
Expand Down
6 changes: 6 additions & 0 deletions packages/kilo-vscode/src/agent-manager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ interface WorktreeStatsMessage {
stats: WorktreeStats[]
}

interface WorktreeActivityMessage {
type: "agentManager.worktreeActivity"
active: string[]
}

interface LocalStatsMessage {
type: "agentManager.localStats"
/** Owning project; absent in single-project mode. */
Expand Down Expand Up @@ -452,6 +457,7 @@ interface RunStatusMessage extends RunStatus {

/** All messages the Agent Manager extension sends to the webview. */
export type AgentManagerOutMessage =
| WorktreeActivityMessage
| WorktreeStatsMessage
| LocalStatsMessage
| WorktreeSetupMessage
Expand Down
Loading
Loading