@@ -706,7 +706,8 @@ where
706706 }
707707 }
708708
709- if !skip_printing_tools && pending_tool_index. is_some ( ) {
709+ let show_tool_use_confirmation_dialog = !skip_printing_tools && pending_tool_index. is_some ( ) ;
710+ if show_tool_use_confirmation_dialog {
710711 execute ! (
711712 self . output,
712713 style:: SetForegroundColor ( Color :: DarkGrey ) ,
@@ -731,36 +732,9 @@ where
731732 ) ?;
732733 }
733734
734- // Require two consecutive sigint's to exit.
735- let mut ctrl_c = false ;
736- let user_input = loop {
737- let all_tools_trusted = self . conversation_state . tools . iter ( ) . all ( |t| match t {
738- FigTool :: ToolSpecification ( t) => self . tool_permissions . is_trusted ( & t. name ) ,
739- } ) ;
740-
741- // Generate prompt based on active context profile and trusted tools
742- let prompt = prompt:: generate_prompt ( self . conversation_state . current_profile ( ) , all_tools_trusted) ;
743-
744- match ( self . input_source . read_line ( Some ( & prompt) ) ?, ctrl_c) {
745- ( Some ( line) , _) => {
746- // Handle empty line case - reprompt the user
747- if line. trim ( ) . is_empty ( ) {
748- continue ;
749- }
750- break line;
751- } ,
752- ( None , false ) => {
753- execute ! (
754- self . output,
755- style:: Print ( format!(
756- "\n (To exit, press Ctrl+C or Ctrl+D again or type {})\n \n " ,
757- "/quit" . green( )
758- ) )
759- ) ?;
760- ctrl_c = true ;
761- } ,
762- ( None , true ) => return Ok ( ChatState :: Exit ) ,
763- }
735+ let user_input = match self . read_user_input ( & self . generate_tool_trust_prompt ( ) , false ) {
736+ Some ( input) => input,
737+ None => return Ok ( ChatState :: Exit ) ,
764738 } ;
765739
766740 self . conversation_state . append_user_transcript ( & user_input) ;
@@ -850,16 +824,39 @@ where
850824 }
851825 } ,
852826 Command :: Clear => {
853- // Clear the conversation including summary
854- self . conversation_state . clear ( false ) ;
855-
827+ execute ! ( self . output, cursor:: Show ) ?;
856828 execute ! (
857829 self . output,
830+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
831+ style:: Print ( "\n Are you sure? This will erase the conversation history for the current session. " ) ,
832+ style:: Print ( "[" ) ,
858833 style:: SetForegroundColor ( Color :: Green ) ,
859- style:: Print ( "\n Conversation history cleared.\n \n " ) ,
860- style:: SetForegroundColor ( Color :: Reset )
834+ style:: Print ( "y" ) ,
835+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
836+ style:: Print ( "/" ) ,
837+ style:: SetForegroundColor ( Color :: Green ) ,
838+ style:: Print ( "n" ) ,
839+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
840+ style:: Print ( "]:\n \n " ) ,
841+ style:: SetForegroundColor ( Color :: Reset ) ,
861842 ) ?;
862843
844+ // Setting `exit_on_single_ctrl_c` for better ux: exit the confirmation dialog rather than the CLI
845+ let user_input = match self . read_user_input ( "> " . yellow ( ) . to_string ( ) . as_str ( ) , true ) {
846+ Some ( input) => input,
847+ None => "" . to_string ( ) ,
848+ } ;
849+
850+ if [ "y" , "Y" ] . contains ( & user_input. as_str ( ) ) {
851+ self . conversation_state . clear ( true ) ;
852+ execute ! (
853+ self . output,
854+ style:: SetForegroundColor ( Color :: Green ) ,
855+ style:: Print ( "\n Conversation history cleared.\n \n " ) ,
856+ style:: SetForegroundColor ( Color :: Reset )
857+ ) ?;
858+ }
859+
863860 ChatState :: PromptUser {
864861 tool_uses : None ,
865862 pending_tool_index : None ,
@@ -2142,6 +2139,46 @@ where
21422139 Ok ( ( ) )
21432140 }
21442141
2142+ /// Helper function to read user input with a prompt and Ctrl+C handling
2143+ fn read_user_input ( & mut self , prompt : & str , exit_on_single_ctrl_c : bool ) -> Option < String > {
2144+ let mut ctrl_c = false ;
2145+ loop {
2146+ match ( self . input_source . read_line ( Some ( prompt) ) , ctrl_c) {
2147+ ( Ok ( Some ( line) ) , _) => {
2148+ if line. trim ( ) . is_empty ( ) {
2149+ continue ; // Reprompt if the input is empty
2150+ }
2151+ return Some ( line) ;
2152+ } ,
2153+ ( Ok ( None ) , false ) => {
2154+ if exit_on_single_ctrl_c {
2155+ return None ;
2156+ }
2157+ execute ! (
2158+ self . output,
2159+ style:: Print ( format!(
2160+ "\n (To exit the CLI, press Ctrl+C or Ctrl+D again or type {})\n \n " ,
2161+ "/quit" . green( )
2162+ ) )
2163+ )
2164+ . unwrap_or_default ( ) ;
2165+ ctrl_c = true ;
2166+ } ,
2167+ ( Ok ( None ) , true ) => return None , // Exit if Ctrl+C was pressed twice
2168+ ( Err ( _) , _) => return None ,
2169+ }
2170+ }
2171+ }
2172+
2173+ /// Helper function to generate a prompt based on the current context
2174+ fn generate_tool_trust_prompt ( & self ) -> String {
2175+ let all_tools_trusted = self . conversation_state . tools . iter ( ) . all ( |t| match t {
2176+ FigTool :: ToolSpecification ( t) => self . tool_permissions . is_trusted ( & t. name ) ,
2177+ } ) ;
2178+
2179+ prompt:: generate_prompt ( self . conversation_state . current_profile ( ) , all_tools_trusted)
2180+ }
2181+
21452182 async fn send_tool_use_telemetry ( & mut self ) {
21462183 for ( _, mut event) in self . tool_use_telemetry_events . drain ( ) {
21472184 event. user_input_id = match self . tool_use_status {
0 commit comments