@@ -185,22 +185,23 @@ export async function handleTaskToolCompleted(event: any): Promise<void> {
185185}
186186
187187export async function collapseSubagentOnIdle ( childSessionId : string ) : Promise < void > {
188- const info = PluginState . subagentRegistry . get ( childSessionId ) ;
189- const mmClient = PluginState . mmClient ;
190- if ( ! info || ! mmClient ) return ;
191- if ( info . status !== "running" ) return ;
188+ const info = PluginState . subagentRegistry . get ( childSessionId ) ;
189+ const mmClient = PluginState . mmClient ;
190+ if ( ! info || ! mmClient ) return ;
191+ if ( info . status !== "running" ) return ;
192192
193- // Get child context before deleting it
194- const childCtx = PluginState . activeResponseContexts . get ( childSessionId ) ;
193+ // Get child context before deleting it
194+ const childCtx = PluginState . activeResponseContexts . get ( childSessionId ) ;
195195
196- const elapsed = formatElapsedTime ( Date . now ( ) - info . startTime ) ;
197- const costPart = childCtx ?. cost ?. currentMessage ? ` | 💰 $${ childCtx . cost . currentMessage . toFixed ( 2 ) } ` : "" ;
198- const modelPart = info . modelId ? ` | 🧠 ${ info . modelId } ` : ( childCtx ?. modelId ? ` | 🧠 ${ childCtx . modelId } ` : "" ) ;
199- const summary = `✅ ${ formatTaskLabel ( info . agentType , info . description ) } (${ elapsed } , ${ info . toolCount } tools)${ costPart } ${ modelPart } ` ;
196+ info . endTime = Date . now ( ) ;
197+ const elapsed = formatElapsedTime ( info . endTime - info . startTime ) ;
198+ const costPart = childCtx ?. cost ?. currentMessage ? ` | 💰 $${ childCtx . cost . currentMessage . toFixed ( 2 ) } ` : "" ;
199+ const modelPart = info . modelId ? ` | 🧠 ${ info . modelId } ` : ( childCtx ?. modelId ? ` | 🧠 ${ childCtx . modelId } ` : "" ) ;
200+ const summary = `✅ ${ formatTaskLabel ( info . agentType , info . description ) } (${ elapsed } , ${ info . toolCount } tools)${ costPart } ${ modelPart } ` ;
200201
201- log . info ( `[Subagent] Child idle — collapsing: child=${ childSessionId . substring ( 0 , 8 ) } , type=${ info . agentType } , ${ elapsed } , ${ info . toolCount } tools` ) ;
202- await mmClient . updatePost ( info . replyPostId , summary ) ;
203- info . status = "completed" ;
202+ log . info ( `[Subagent] Child idle — collapsing: child=${ childSessionId . substring ( 0 , 8 ) } , type=${ info . agentType } , ${ elapsed } , ${ info . toolCount } tools` ) ;
203+ await mmClient . updatePost ( info . replyPostId , summary ) ;
204+ info . status = "completed" ;
204205
205206 await updateResponseStream ( info . parentSessionId ) ;
206207
@@ -210,30 +211,31 @@ export async function collapseSubagentOnIdle(childSessionId: string): Promise<vo
210211}
211212
212213export async function handleTaskToolError ( event : any ) : Promise < void > {
213- const part = event . properties ?. part ;
214- if ( ! part || part . tool !== "task" ) return ;
215- if ( part . state ?. status !== "error" ) return ;
214+ const part = event . properties ?. part ;
215+ if ( ! part || part . tool !== "task" ) return ;
216+ if ( part . state ?. status !== "error" ) return ;
216217
217- const childSessionId = part . state ?. metadata ?. sessionId ;
218- if ( ! childSessionId ) return ;
218+ const childSessionId = part . state ?. metadata ?. sessionId ;
219+ if ( ! childSessionId ) return ;
219220
220- const info = PluginState . subagentRegistry . get ( childSessionId ) ;
221- const mmClient = PluginState . mmClient ;
222- if ( ! info || ! mmClient ) return ;
221+ const info = PluginState . subagentRegistry . get ( childSessionId ) ;
222+ const mmClient = PluginState . mmClient ;
223+ if ( ! info || ! mmClient ) return ;
223224
224- // Get child context before deleting it
225- const childCtx = PluginState . activeResponseContexts . get ( childSessionId ) ;
225+ // Get child context before deleting it
226+ const childCtx = PluginState . activeResponseContexts . get ( childSessionId ) ;
226227
227- const errorMessage = part . state ?. error || part . state ?. metadata ?. error ;
228- const costPart = childCtx ?. cost ?. currentMessage ? ` | 💰 $${ childCtx . cost . currentMessage . toFixed ( 2 ) } ` : "" ;
229- const modelPart = info . modelId ? ` | 🧠 ${ info . modelId } ` : ( childCtx ?. modelId ? ` | 🧠 ${ childCtx . modelId } ` : "" ) ;
230- const summary = errorMessage
231- ? `❌ ${ formatTaskLabel ( info . agentType , info . description ) } (failed: ${ errorMessage } )${ costPart } ${ modelPart } `
232- : `❌ ${ formatTaskLabel ( info . agentType , info . description ) } (failed)${ costPart } ${ modelPart } ` ;
228+ info . endTime = Date . now ( ) ;
229+ const errorMessage = part . state ?. error || part . state ?. metadata ?. error ;
230+ const costPart = childCtx ?. cost ?. currentMessage ? ` | 💰 $${ childCtx . cost . currentMessage . toFixed ( 2 ) } ` : "" ;
231+ const modelPart = info . modelId ? ` | 🧠 ${ info . modelId } ` : ( childCtx ?. modelId ? ` | 🧠 ${ childCtx . modelId } ` : "" ) ;
232+ const summary = errorMessage
233+ ? `❌ ${ formatTaskLabel ( info . agentType , info . description ) } (failed: ${ errorMessage } )${ costPart } ${ modelPart } `
234+ : `❌ ${ formatTaskLabel ( info . agentType , info . description ) } (failed)${ costPart } ${ modelPart } ` ;
233235
234- log . info ( `[Subagent] Error: child=${ childSessionId . substring ( 0 , 8 ) } , type=${ info . agentType } , error=${ errorMessage || 'unknown' } — collapsing reply` ) ;
235- await mmClient . updatePost ( info . replyPostId , summary ) ;
236- info . status = "error" ;
236+ log . info ( `[Subagent] Error: child=${ childSessionId . substring ( 0 , 8 ) } , type=${ info . agentType } , error=${ errorMessage || 'unknown' } — collapsing reply` ) ;
237+ await mmClient . updatePost ( info . replyPostId , summary ) ;
238+ info . status = "error" ;
237239
238240 await updateResponseStream ( info . parentSessionId ) ;
239241
@@ -243,28 +245,29 @@ export async function handleTaskToolError(event: any): Promise<void> {
243245}
244246
245247export async function cleanupSubagentsForParent ( parentSessionId : string ) : Promise < void > {
246- const mmClient = PluginState . mmClient ;
247- if ( ! mmClient ) return ;
248-
249- const entries = Array . from ( PluginState . subagentRegistry . values ( ) ) . filter (
250- ( entry ) => entry . parentSessionId === parentSessionId
251- ) ;
252-
253- log . info ( `[Subagent] Cleanup: parent=${ parentSessionId . substring ( 0 , 8 ) } , ${ entries . length } child subagents to clean up` ) ;
254- for ( const entry of entries ) {
255- if ( entry . status === "running" ) {
256- const summary = `❌ ${ formatTaskLabel ( entry . agentType , entry . description ) } (cancelled)` ;
257- try {
258- await mmClient . updatePost ( entry . replyPostId , summary ) ;
259- } catch ( e ) {
260- log . debug ( `[Subagent] Failed to collapse reply ${ entry . replyPostId } : ${ e } ` ) ;
261- }
262- } else {
263- log . debug ( `[Subagent] Cleanup: skipping ${ entry . childSessionId . substring ( 0 , 8 ) } (already ${ entry . status } )` ) ;
264- }
265- PluginState . activeResponseContexts . delete ( entry . childSessionId ) ;
266- stopActiveToolTimer ( entry . childSessionId ) ;
267- stopResponseTimer ( entry . childSessionId ) ;
268- PluginState . subagentRegistry . delete ( entry . childSessionId ) ;
269- }
248+ const mmClient = PluginState . mmClient ;
249+ if ( ! mmClient ) return ;
250+
251+ const entries = Array . from ( PluginState . subagentRegistry . values ( ) ) . filter (
252+ ( entry ) => entry . parentSessionId === parentSessionId
253+ ) ;
254+
255+ log . info ( `[Subagent] Cleanup: parent=${ parentSessionId . substring ( 0 , 8 ) } , ${ entries . length } child subagents to clean up` ) ;
256+ for ( const entry of entries ) {
257+ if ( entry . status === "running" ) {
258+ entry . endTime = Date . now ( ) ;
259+ const summary = `❌ ${ formatTaskLabel ( entry . agentType , entry . description ) } (cancelled)` ;
260+ try {
261+ await mmClient . updatePost ( entry . replyPostId , summary ) ;
262+ } catch ( e ) {
263+ log . debug ( `[Subagent] Failed to collapse reply ${ entry . replyPostId } : ${ e } ` ) ;
264+ }
265+ } else {
266+ log . debug ( `[Subagent] Cleanup: skipping ${ entry . childSessionId . substring ( 0 , 8 ) } (already ${ entry . status } )` ) ;
267+ }
268+ PluginState . activeResponseContexts . delete ( entry . childSessionId ) ;
269+ stopActiveToolTimer ( entry . childSessionId ) ;
270+ stopResponseTimer ( entry . childSessionId ) ;
271+ PluginState . subagentRegistry . delete ( entry . childSessionId ) ;
272+ }
270273}
0 commit comments