@@ -330,10 +330,12 @@ impl SummonClient {
330330 "Load knowledge into your current context or discover available sources.\n \n \
331331 Call with no arguments to list all available sources (subrecipes, recipes, skills, agents).\n \
332332 Call with a source name to load its content into your context.\n \
333- For background tasks: load(source: \" task_id\" , cancel: true) stops and returns output.\n \n \
333+ For background tasks: load(source: \" task_id\" ) waits for the task and returns the result.\n \
334+ To cancel a running task: load(source: \" task_id\" , cancel: true) stops and returns output.\n \n \
334335 Examples:\n \
335336 - load() → Lists available sources\n \
336- - load(source: \" rust-patterns\" ) → Loads the rust-patterns skill"
337+ - load(source: \" rust-patterns\" ) → Loads the rust-patterns skill\n \
338+ - load(source: \" 20260219_1\" ) → Waits for background task, then returns result"
337339 . to_string ( ) ,
338340 schema. as_object ( ) . unwrap ( ) . clone ( ) ,
339341 )
@@ -880,7 +882,7 @@ impl SummonClient {
880882
881883 // Wait for the running task to complete, keeping the tool call
882884 // alive so notifications (subagent tool calls) stream in real time.
883- let task = running. remove ( task_id) . unwrap ( ) ;
885+ let mut task = running. remove ( task_id) . unwrap ( ) ;
884886 drop ( running) ;
885887
886888 let buffered = {
@@ -896,45 +898,37 @@ impl SummonClient {
896898 }
897899 }
898900
899- let description = task. description . clone ( ) ;
900- let mut handle = task. handle ;
901-
902- let ( output, timed_out) = tokio:: select! {
903- result = & mut handle => {
904- let s = match result {
901+ tokio:: select! {
902+ result = & mut task. handle => {
903+ let output = match result {
905904 Ok ( Ok ( s) ) => s,
906905 Ok ( Err ( e) ) => format!( "Error: {}" , e) ,
907906 Err ( e) => format!( "Task panicked: {}" , e) ,
908907 } ;
909- ( s, false )
908+
909+ return Ok ( vec![ Content :: text( format!(
910+ "# Background Task Result: {}\n \n \
911+ **Task:** {}\n \
912+ **Status:** ✓ Completed\n \
913+ **Duration:** {} ({} turns)\n \n \
914+ ## Output\n \n {}",
915+ task_id,
916+ task. description,
917+ round_duration( task. started_at. elapsed( ) ) ,
918+ task. turns. load( Ordering :: Relaxed ) ,
919+ output
920+ ) ) ] ) ;
910921 }
911922 _ = tokio:: time:: sleep( Duration :: from_secs( 300 ) ) => {
912- handle. abort( ) ;
913- ( "Task timed out waiting for completion (aborted after 5 min)" . to_string( ) , true )
914- }
915- } ;
923+ self . background_tasks. lock( ) . await . insert( task_id. to_string( ) , task) ;
916924
917- let duration = task. started_at . elapsed ( ) ;
918- let turns_taken = task. turns . load ( Ordering :: Relaxed ) ;
919- let status = if timed_out {
920- "⏱ Timed out"
921- } else {
922- "✓ Completed"
923- } ;
924-
925- return Ok ( vec ! [ Content :: text( format!(
926- "# Background Task Result: {}\n \n \
927- **Task:** {}\n \
928- **Status:** {}\n \
929- **Duration:** {} ({} turns)\n \n \
930- ## Output\n \n {}",
931- task_id,
932- description,
933- status,
934- round_duration( duration) ,
935- turns_taken,
936- output
937- ) ) ] ) ;
925+ return Err ( format!(
926+ "Task '{task_id}' is still running after waiting 5 min. \
927+ Use load(source: \" {task_id}\" ) to wait again, or \
928+ load(source: \" {task_id}\" , cancel: true) to stop."
929+ ) ) ;
930+ }
931+ }
938932 }
939933
940934 Err ( format ! ( "Task '{}' not found." , task_id) )
@@ -1628,7 +1622,8 @@ impl SummonClient {
16281622 . insert ( task_id. clone ( ) , task) ;
16291623
16301624 Ok ( vec ! [ Content :: text( format!(
1631- "Task {} started in background: \" {}\" \n Use load(source: \" {}\" ) to wait for the result (it will block until complete)." ,
1625+ "Task {} started in background: \" {}\" \n \
1626+ Continue with other work. When you need the result, use load(source: \" {}\" ).",
16321627 task_id, description, task_id
16331628 ) ) ] )
16341629 }
@@ -1714,19 +1709,13 @@ impl McpClientTrait for SummonClient {
17141709 let mut lines = vec ! [ "Background tasks:" . to_string( ) ] ;
17151710 let now = current_epoch_millis ( ) ;
17161711
1717- let mut shortest_elapsed_secs: Option < u64 > = None ;
1718-
17191712 let mut sorted_running: Vec < _ > = running. values ( ) . collect ( ) ;
17201713 sorted_running. sort_by_key ( |t| & t. id ) ;
17211714
17221715 for task in sorted_running {
17231716 let elapsed = task. started_at . elapsed ( ) ;
17241717 let idle_ms = now. saturating_sub ( task. last_activity . load ( Ordering :: Relaxed ) ) ;
17251718
1726- let elapsed_secs = elapsed. as_secs ( ) ;
1727- shortest_elapsed_secs =
1728- Some ( shortest_elapsed_secs. map_or ( elapsed_secs, |s| s. min ( elapsed_secs) ) ) ;
1729-
17301719 lines. push ( format ! (
17311720 "• {}: \" {}\" - running {}, {} turns, idle {}" ,
17321721 task. id,
@@ -1757,12 +1746,11 @@ impl McpClientTrait for SummonClient {
17571746 ) ) ;
17581747 }
17591748
1760- if let Some ( shortest) = shortest_elapsed_secs {
1761- let sleep_secs = 300u64 . saturating_sub ( shortest) . max ( 10 ) ;
1762- lines. push ( format ! (
1763- "\n → sleep {} to wait, or load(source: \" id\" , cancel: true) to stop" ,
1764- sleep_secs
1765- ) ) ;
1749+ if !running. is_empty ( ) {
1750+ lines. push (
1751+ "\n → Use load(source: \" <id>\" ) to wait for a task, or load(source: \" <id>\" , cancel: true) to stop it"
1752+ . to_string ( ) ,
1753+ ) ;
17661754 }
17671755
17681756 Some ( lines. join ( "\n " ) )
0 commit comments