@@ -253,15 +253,11 @@ enum ChatState {
253253 PromptUser {
254254 /// Tool uses to present to the user.
255255 tool_uses : Option < Vec < QueuedTool > > ,
256- /// Whether or not the associated tool uses were previously interrupted.
257- tools_were_interrupted : bool ,
258256 } ,
259257 /// Handle the user input, depending on if any tools require execution.
260258 HandleInput {
261259 input : String ,
262260 tool_uses : Option < Vec < QueuedTool > > ,
263- /// Whether or not the associated tool uses were previously interrupted.
264- tools_were_interrupted : bool ,
265261 } ,
266262 /// Validate the list of tool uses provided by the model.
267263 ValidateTools ( Vec < ToolUse > ) ,
@@ -275,10 +271,7 @@ enum ChatState {
275271
276272impl Default for ChatState {
277273 fn default ( ) -> Self {
278- Self :: PromptUser {
279- tool_uses : None ,
280- tools_were_interrupted : false ,
281- }
274+ Self :: PromptUser { tool_uses : None }
282275 }
283276}
284277
@@ -293,10 +286,7 @@ where
293286
294287 let mut ctrl_c_stream = signal ( SignalKind :: interrupt ( ) ) ?;
295288
296- let mut next_state = Some ( ChatState :: PromptUser {
297- tool_uses : None ,
298- tools_were_interrupted : false ,
299- } ) ;
289+ let mut next_state = Some ( ChatState :: PromptUser { tool_uses : None } ) ;
300290
301291 if let Some ( user_input) = self . initial_input . take ( ) {
302292 execute ! (
@@ -310,7 +300,6 @@ where
310300 next_state = Some ( ChatState :: HandleInput {
311301 input : user_input,
312302 tool_uses : None ,
313- tools_were_interrupted : false ,
314303 } ) ;
315304 }
316305
@@ -320,15 +309,8 @@ where
320309 debug ! ( ?chat_state, "changing to state" ) ;
321310
322311 let result = match chat_state {
323- ChatState :: PromptUser {
324- tool_uses,
325- tools_were_interrupted,
326- } => self . prompt_user ( tool_uses, tools_were_interrupted) . await ,
327- ChatState :: HandleInput {
328- input,
329- tool_uses,
330- tools_were_interrupted,
331- } => self . handle_input ( input, tool_uses, tools_were_interrupted) . await ,
312+ ChatState :: PromptUser { tool_uses } => self . prompt_user ( tool_uses) . await ,
313+ ChatState :: HandleInput { input, tool_uses } => self . handle_input ( input, tool_uses) . await ,
332314 ChatState :: ExecuteTools ( tool_uses) => {
333315 let tool_uses_clone = tool_uses. clone ( ) ;
334316 tokio:: select! {
@@ -424,42 +406,20 @@ where
424406 } ,
425407 }
426408 self . conversation_state . fix_history ( ) ;
427- next_state = Some ( ChatState :: PromptUser {
428- tool_uses : None ,
429- tools_were_interrupted : false ,
430- } ) ;
409+ next_state = Some ( ChatState :: PromptUser { tool_uses : None } ) ;
431410 } ,
432411 }
433412 }
434413 }
435414
436415 /// Read input from the user.
437- async fn prompt_user (
438- & mut self ,
439- mut tool_uses : Option < Vec < QueuedTool > > ,
440- tools_were_interrupted : bool ,
441- ) -> Result < ChatState , ChatError > {
416+ async fn prompt_user ( & mut self , mut tool_uses : Option < Vec < QueuedTool > > ) -> Result < ChatState , ChatError > {
442417 if self . interactive {
443418 execute ! ( self . output, cursor:: Show ) ?;
444419 }
445420 let tool_uses = tool_uses. take ( ) . unwrap_or_default ( ) ;
446- // Don't print the tools if they were previously interrupted.
447- if !tool_uses. is_empty ( ) && !tools_were_interrupted {
448- let terminal_width = self . terminal_width ( ) ;
449- for ( i, ( _, tool) ) in tool_uses. iter ( ) . enumerate ( ) {
450- queue ! (
451- self . output,
452- style:: SetForegroundColor ( Color :: Cyan ) ,
453- style:: Print ( format!( "{}. {}\n " , i + 1 , tool. display_name( ) ) ) ,
454- style:: SetForegroundColor ( Color :: Reset ) ,
455- style:: SetForegroundColor ( Color :: DarkGrey ) ,
456- style:: Print ( format!( "{}\n " , "▔" . repeat( terminal_width) ) ) ,
457- style:: SetForegroundColor ( Color :: Reset ) ,
458- ) ?;
459- tool. queue_description ( & self . ctx , & mut self . output )
460- . map_err ( |e| ChatError :: Custom ( format ! ( "failed to print tool: {}" , e) . into ( ) ) ) ?;
461- queue ! ( self . output, style:: Print ( "\n " ) ) ?;
462- }
421+ if !tool_uses. is_empty ( ) {
422+ self . print_tool_descriptions ( & tool_uses) ?;
463423
464424 execute ! (
465425 self . output,
@@ -485,21 +445,16 @@ where
485445 Ok ( ChatState :: HandleInput {
486446 input : user_input,
487447 tool_uses : Some ( tool_uses) ,
488- tools_were_interrupted,
489448 } )
490449 }
491450
492451 async fn handle_input (
493452 & mut self ,
494453 user_input : String ,
495454 tool_uses : Option < Vec < QueuedTool > > ,
496- tools_were_interrupted : bool ,
497455 ) -> Result < ChatState , ChatError > {
498456 let Ok ( command) = Command :: parse ( & user_input) else {
499- return Ok ( ChatState :: PromptUser {
500- tool_uses,
501- tools_were_interrupted,
502- } ) ;
457+ return Ok ( ChatState :: PromptUser { tool_uses } ) ;
503458 } ;
504459
505460 let tool_uses = tool_uses. unwrap_or_default ( ) ;
@@ -518,10 +473,10 @@ where
518473 self . spinner = Some ( Spinner :: new ( Spinners :: Dots , "Thinking..." . to_owned ( ) ) ) ;
519474 }
520475
521- match ( tool_uses. is_empty ( ) , tools_were_interrupted ) {
522- ( false , false ) => self . conversation_state . abandon_tool_use ( tool_uses , user_input) ,
523- ( false , true ) => self . conversation_state . interrupt_tool_use ( tool_uses , user_input ) ,
524- _ => self . conversation_state . append_new_user_message ( user_input) ,
476+ if tool_uses. is_empty ( ) {
477+ self . conversation_state . append_new_user_message ( user_input) ;
478+ } else {
479+ self . conversation_state . abandon_tool_use ( tool_uses , user_input) ;
525480 }
526481
527482 self . send_tool_use_telemetry ( ) . await ;
@@ -536,10 +491,7 @@ where
536491 queue ! ( self . output, style:: Print ( '\n' ) ) ?;
537492 std:: process:: Command :: new ( "bash" ) . args ( [ "-c" , & command] ) . status ( ) . ok ( ) ;
538493 queue ! ( self . output, style:: Print ( '\n' ) ) ?;
539- ChatState :: PromptUser {
540- tool_uses : None ,
541- tools_were_interrupted,
542- }
494+ ChatState :: PromptUser { tool_uses : None }
543495 } ,
544496 Command :: Clear => {
545497 self . conversation_state . clear ( ) ;
@@ -551,17 +503,11 @@ where
551503 style:: SetForegroundColor ( Color :: Reset )
552504 ) ?;
553505
554- ChatState :: PromptUser {
555- tool_uses : None ,
556- tools_were_interrupted,
557- }
506+ ChatState :: PromptUser { tool_uses : None }
558507 } ,
559508 Command :: Help => {
560509 execute ! ( self . output, style:: Print ( HELP_TEXT ) ) ?;
561- ChatState :: PromptUser {
562- tool_uses : None ,
563- tools_were_interrupted,
564- }
510+ ChatState :: PromptUser { tool_uses : None }
565511 } ,
566512 Command :: Quit => ChatState :: Exit ,
567513 } )
@@ -571,15 +517,15 @@ where
571517 // Execute the requested tools.
572518 let terminal_width = self . terminal_width ( ) ;
573519 let mut tool_results = vec ! [ ] ;
574- for ( i , tool) in tool_uses. into_iter ( ) . enumerate ( ) {
520+ for tool in tool_uses {
575521 let mut tool_telemetry = self . tool_use_telemetry_events . entry ( tool. 0 . clone ( ) ) ;
576522 tool_telemetry = tool_telemetry. and_modify ( |ev| ev. is_accepted = true ) ;
577523
578524 let tool_start = std:: time:: Instant :: now ( ) ;
579525 queue ! (
580526 self . output,
581527 style:: SetForegroundColor ( Color :: Cyan ) ,
582- style:: Print ( format!( "\n {}. {}... \n " , i + 1 , tool. 1 . display_name_action( ) ) ) ,
528+ style:: Print ( format!( "\n {}... \n " , tool. 1 . display_name_action( ) ) ) ,
583529 style:: SetForegroundColor ( Color :: DarkGrey ) ,
584530 style:: Print ( format!( "{}\n " , "▔" . repeat( terminal_width) ) ) ,
585531 style:: SetForegroundColor ( Color :: Reset ) ,
@@ -820,10 +766,7 @@ where
820766 if !tool_uses. is_empty ( ) {
821767 Ok ( ChatState :: ValidateTools ( tool_uses) )
822768 } else {
823- Ok ( ChatState :: PromptUser {
824- tool_uses : None ,
825- tools_were_interrupted : false ,
826- } )
769+ Ok ( ChatState :: PromptUser { tool_uses : None } )
827770 }
828771 }
829772
@@ -916,15 +859,34 @@ where
916859 || queued_tools. iter ( ) . all ( |tool| !tool. 1 . requires_consent ( & self . ctx ) ) ;
917860
918861 if skip_consent {
862+ self . print_tool_descriptions ( & queued_tools) ?;
919863 Ok ( ChatState :: ExecuteTools ( queued_tools) )
920864 } else {
921865 Ok ( ChatState :: PromptUser {
922866 tool_uses : Some ( queued_tools) ,
923- tools_were_interrupted : false ,
924867 } )
925868 }
926869 }
927870
871+ fn print_tool_descriptions ( & mut self , tool_uses : & [ QueuedTool ] ) -> Result < ( ) , ChatError > {
872+ let terminal_width = self . terminal_width ( ) ;
873+ for ( _, tool) in tool_uses. iter ( ) {
874+ queue ! (
875+ self . output,
876+ style:: SetForegroundColor ( Color :: Cyan ) ,
877+ style:: Print ( format!( "{}\n " , tool. display_name( ) ) ) ,
878+ style:: SetForegroundColor ( Color :: Reset ) ,
879+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
880+ style:: Print ( format!( "{}\n " , "▔" . repeat( terminal_width) ) ) ,
881+ style:: SetForegroundColor ( Color :: Reset ) ,
882+ ) ?;
883+ tool. queue_description ( & self . ctx , & mut self . output )
884+ . map_err ( |e| ChatError :: Custom ( format ! ( "failed to print tool: {}" , e) . into ( ) ) ) ?;
885+ queue ! ( self . output, style:: Print ( "\n " ) ) ?;
886+ }
887+ Ok ( ( ) )
888+ }
889+
928890 async fn send_tool_use_telemetry ( & mut self ) {
929891 for ( _, mut event) in self . tool_use_telemetry_events . drain ( ) {
930892 event. user_input_id = match self . tool_use_status {
0 commit comments