@@ -49,6 +49,7 @@ import { fn } from "@/util/fn"
4949import { SessionRetry } from "./retry"
5050import { SessionProcessor } from "./processor"
5151import { iife } from "@/util/iife"
52+ import { TaskTool } from "@/tool/task"
5253
5354export namespace SessionPrompt {
5455 const log = Log . create ( { service : "session.prompt" } )
@@ -173,6 +174,16 @@ export namespace SessionPrompt {
173174 . meta ( {
174175 ref : "AgentPartInput" ,
175176 } ) ,
177+ MessageV2 . SubtaskPart . omit ( {
178+ messageID : true ,
179+ sessionID : true ,
180+ } )
181+ . partial ( {
182+ id : true ,
183+ } )
184+ . meta ( {
185+ ref : "SubtaskPartInput" ,
186+ } ) ,
176187 ] ) ,
177188 ) ,
178189 } )
@@ -290,17 +301,17 @@ export namespace SessionPrompt {
290301 let lastUser : MessageV2 . User | undefined
291302 let lastAssistant : MessageV2 . Assistant | undefined
292303 let lastFinished : MessageV2 . Assistant | undefined
293- let tasks : MessageV2 . CompactionPart [ ] = [ ]
304+ let tasks : ( MessageV2 . CompactionPart | MessageV2 . SubtaskPart ) [ ] = [ ]
294305 for ( let i = msgs . length - 1 ; i >= 0 ; i -- ) {
295306 const msg = msgs [ i ]
296307 if ( ! lastUser && msg . info . role === "user" ) lastUser = msg . info as MessageV2 . User
297308 if ( ! lastAssistant && msg . info . role === "assistant" ) lastAssistant = msg . info as MessageV2 . Assistant
298309 if ( ! lastFinished && msg . info . role === "assistant" && msg . info . finish )
299310 lastFinished = msg . info as MessageV2 . Assistant
300311 if ( lastUser && lastFinished ) break
301- const compaction = msg . parts . find ( ( part ) => part . type === "compaction" )
302- if ( compaction && ! lastFinished ) {
303- tasks . push ( compaction )
312+ const task = msg . parts . filter ( ( part ) => part . type === "compaction" || part . type === "subtask ")
313+ if ( task && ! lastFinished ) {
314+ tasks . push ( ... task )
304315 }
305316 }
306317
@@ -313,6 +324,87 @@ export namespace SessionPrompt {
313324 const model = await Provider . getModel ( lastUser . model . providerID , lastUser . model . modelID )
314325 const task = tasks . pop ( )
315326
327+ // pending subtask
328+ if ( task ?. type === "subtask" ) {
329+ const taskTool = await TaskTool . init ( )
330+ const assistantMessage = await Session . updateMessage ( {
331+ id : Identifier . ascending ( "message" ) ,
332+ role : "assistant" ,
333+ parentID : lastUser . id ,
334+ sessionID,
335+ mode : task . agent ,
336+ path : {
337+ cwd : Instance . directory ,
338+ root : Instance . worktree ,
339+ } ,
340+ cost : 0 ,
341+ tokens : {
342+ input : 0 ,
343+ output : 0 ,
344+ reasoning : 0 ,
345+ cache : { read : 0 , write : 0 } ,
346+ } ,
347+ modelID : model . modelID ,
348+ providerID : model . providerID ,
349+ time : {
350+ created : Date . now ( ) ,
351+ } ,
352+ } )
353+ let part = await Session . updatePart ( {
354+ id : Identifier . ascending ( "part" ) ,
355+ messageID : assistantMessage . id ,
356+ sessionID : assistantMessage . sessionID ,
357+ type : "tool" ,
358+ callID : ulid ( ) ,
359+ tool : TaskTool . id ,
360+ state : {
361+ status : "running" ,
362+ input : {
363+ prompt : task . prompt ,
364+ description : task . description ,
365+ subagent_type : task . agent ,
366+ } ,
367+ time : {
368+ start : Date . now ( ) ,
369+ } ,
370+ } ,
371+ } )
372+ const result = await taskTool
373+ . execute (
374+ {
375+ prompt : task . prompt ,
376+ description : task . description ,
377+ subagent_type : task . agent ,
378+ } ,
379+ {
380+ agent : task . agent ,
381+ messageID : assistantMessage . id ,
382+ sessionID : sessionID ,
383+ abort,
384+ async metadata ( input ) {
385+ part = await Session . updatePart ( {
386+ ...part ,
387+ type : "tool" ,
388+ state : {
389+ ...( part as any ) . state ,
390+ ...input ,
391+ } as any ,
392+ } as any )
393+ } ,
394+ } ,
395+ )
396+ . catch ( ( ) => { } )
397+ await Session . updatePart ( {
398+ ...part ,
399+ state : {
400+ ...( part as any ) . state ,
401+ type : "completed" ,
402+ ...result ,
403+ } ,
404+ } as any )
405+ continue
406+ }
407+
316408 // pending compaction
317409 if ( task ?. type === "compaction" ) {
318410 await SessionCompaction . process ( {
@@ -1289,8 +1381,10 @@ export namespace SessionPrompt {
12891381
12901382 if ( ( agent . mode === "subagent" && command . subtask !== false ) || command . subtask === true ) {
12911383 parts . push ( {
1292- type : "agent" ,
1293- name : agent . name ,
1384+ type : "subtask" ,
1385+ agent : agent . name ,
1386+ description : command . description ?? "" ,
1387+ prompt : command . template ,
12941388 } )
12951389 }
12961390
0 commit comments