Skip to content
This repository was archived by the owner on Feb 25, 2026. It is now read-only.

Commit 1ca23dd

Browse files
committed
fix(vscode): display sub-agent task tool list in webview
The task tool's child session data was never populated in the VSCode webview's DataProvider store, causing the task-tools list to render empty. Two root causes: 1. DataBridge only mapped the current session's messages/parts, so getSessionToolParts() always returned [] for child session IDs. 2. No syncSession callback was provided to DataProvider, so the task tool renderer's createEffect that triggers child session loading was a no-op. Add a syncSession message round-trip: the webview sends syncSession to the extension, which tracks the child session ID for SSE events and fetches its messages via HTTP, sending them back as messagesLoaded. The DataBridge now exposes the full allMessages/allParts store so all sessions (including child sessions) are visible to the shared message-part renderer.
1 parent 4b7e20b commit 1ca23dd

4 files changed

Lines changed: 75 additions & 11 deletions

File tree

packages/kilo-vscode/src/KiloProvider.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ export class KiloProvider implements vscode.WebviewViewProvider {
263263
case "loadMessages":
264264
await this.handleLoadMessages(message.sessionID)
265265
break
266+
case "syncSession":
267+
await this.handleSyncSession(message.sessionID)
268+
break
266269
case "loadSessions":
267270
await this.handleLoadSessions()
268271
break
@@ -579,6 +582,44 @@ export class KiloProvider implements vscode.WebviewViewProvider {
579582
}
580583
}
581584

585+
/**
586+
* Handle syncing a child session (e.g. spawned by the task tool).
587+
* Tracks the session for SSE events and fetches its messages.
588+
*/
589+
private async handleSyncSession(sessionID: string): Promise<void> {
590+
if (!this.httpClient) return
591+
if (this.trackedSessionIds.has(sessionID)) return
592+
593+
this.trackedSessionIds.add(sessionID)
594+
595+
try {
596+
const workspaceDir = this.getWorkspaceDirectory(sessionID)
597+
const messagesData = await this.httpClient.getMessages(sessionID, workspaceDir)
598+
599+
const messages = messagesData.map((m) => ({
600+
id: m.info.id,
601+
sessionID: m.info.sessionID,
602+
role: m.info.role,
603+
parts: m.parts,
604+
createdAt: new Date(m.info.time.created).toISOString(),
605+
cost: m.info.cost,
606+
tokens: m.info.tokens,
607+
}))
608+
609+
for (const message of messages) {
610+
this.connectionService.recordMessageSessionId(message.id, message.sessionID)
611+
}
612+
613+
this.postMessage({
614+
type: "messagesLoaded",
615+
sessionID,
616+
messages,
617+
})
618+
} catch (err) {
619+
console.error("[Kilo New] KiloProvider: Failed to sync child session:", err)
620+
}
621+
}
622+
582623
/**
583624
* Handle loading all sessions.
584625
*/

packages/kilo-vscode/webview-ui/src/App.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,14 @@ export const DataBridge: Component<{ children: any }> = (props) => {
5050

5151
const data = createMemo(() => {
5252
const id = session.currentSessionID()
53+
const msgs = session.allMessages()
54+
const parts = session.allParts()
5355
return {
54-
session: session.sessions().map((s) => ({ ...s, id: s.id, role: "user" as const })),
56+
session: session.sessions().map((s) => ({ ...s, id: s.id, role: "user" as const })) as unknown as any[],
5557
session_status: {} as Record<string, any>,
5658
session_diff: {} as Record<string, any[]>,
57-
message: id ? { [id]: session.messages() as unknown as SDKMessage[] } : {},
58-
part: id
59-
? Object.fromEntries(
60-
session
61-
.messages()
62-
.map((msg) => [msg.id, session.getParts(msg.id) as unknown as SDKPart[]])
63-
.filter(([, parts]) => (parts as SDKPart[]).length > 0),
64-
)
65-
: {},
59+
message: msgs as unknown as Record<string, SDKMessage[]>,
60+
part: parts as unknown as Record<string, SDKPart[]>,
6661
permission: id ? { [id]: session.permissions() as unknown as any[] } : {},
6762
}
6863
})
@@ -71,8 +66,12 @@ export const DataBridge: Component<{ children: any }> = (props) => {
7166
session.respondToPermission(input.permissionID, input.response)
7267
}
7368

69+
const sync = (sessionID: string) => {
70+
session.syncSession(sessionID)
71+
}
72+
7473
return (
75-
<DataProvider data={data()} directory="" onPermissionRespond={respond}>
74+
<DataProvider data={data()} directory="" onPermissionRespond={respond} onSyncSession={sync}>
7675
{props.children}
7776
</DataProvider>
7877
)

packages/kilo-vscode/webview-ui/src/context/session.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ interface SessionContextValue {
102102
// Messages for current session
103103
messages: Accessor<Message[]>
104104

105+
// All messages keyed by sessionID (includes child sessions)
106+
allMessages: () => Record<string, Message[]>
107+
108+
// All parts keyed by messageID (includes child sessions)
109+
allParts: () => Record<string, Part[]>
110+
105111
// Parts for a specific message
106112
getParts: (messageID: string) => Part[]
107113

@@ -143,6 +149,7 @@ interface SessionContextValue {
143149
selectSession: (id: string) => void
144150
deleteSession: (id: string) => void
145151
renameSession: (id: string, title: string) => void
152+
syncSession: (sessionID: string) => void
146153
}
147154

148155
const SessionContext = createContext<SessionContextValue>()
@@ -790,6 +797,14 @@ export const SessionProvider: ParentComponent = (props) => {
790797
return store.parts[messageID] || []
791798
}
792799

800+
const allMessages = () => store.messages
801+
802+
const allParts = () => store.parts
803+
804+
function syncSession(sessionID: string) {
805+
vscode.postMessage({ type: "syncSession", sessionID })
806+
}
807+
793808
const todos = () => {
794809
const id = currentSessionID()
795810
return id ? store.todos[id] || [] : []
@@ -865,6 +880,8 @@ export const SessionProvider: ParentComponent = (props) => {
865880
selectAgent,
866881
getSessionAgent: (sessionID: string) => store.agentSelections[sessionID] ?? defaultAgent(),
867882
getSessionModel: (sessionID: string) => store.modelSelections[sessionID] ?? provider.defaultSelection(),
883+
allMessages,
884+
allParts,
868885
sendMessage,
869886
abort,
870887
compact,
@@ -877,6 +894,7 @@ export const SessionProvider: ParentComponent = (props) => {
877894
selectSession,
878895
deleteSession,
879896
renameSession,
897+
syncSession,
880898
}
881899

882900
return <SessionContext.Provider value={value}>{props.children}</SessionContext.Provider>

packages/kilo-vscode/webview-ui/src/types/messages.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,11 @@ export interface ResetAllSettingsRequest {
729729
type: "resetAllSettings"
730730
}
731731

732+
export interface SyncSessionRequest {
733+
type: "syncSession"
734+
sessionID: string
735+
}
736+
732737
// Agent Manager worktree messages
733738
export interface CreateWorktreeSessionRequest {
734739
type: "agentManager.createWorktreeSession"
@@ -772,6 +777,7 @@ export type WebviewMessage =
772777
| UpdateConfigMessage
773778
| RequestNotificationSettingsMessage
774779
| ResetAllSettingsRequest
780+
| SyncSessionRequest
775781
| CreateWorktreeSessionRequest
776782

777783
// ============================================

0 commit comments

Comments
 (0)