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