@@ -693,7 +693,8 @@ where
693693 }
694694 }
695695
696- if !skip_printing_tools && pending_tool_index. is_some ( ) {
696+ let show_tool_use_confirmation_dialog = !skip_printing_tools && pending_tool_index. is_some ( ) ;
697+ if show_tool_use_confirmation_dialog {
697698 execute ! (
698699 self . output,
699700 style:: SetForegroundColor ( Color :: DarkGrey ) ,
@@ -718,36 +719,9 @@ where
718719 ) ?;
719720 }
720721
721- // Require two consecutive sigint's to exit.
722- let mut ctrl_c = false ;
723- let user_input = loop {
724- let all_tools_trusted = self . conversation_state . tools . iter ( ) . all ( |t| match t {
725- FigTool :: ToolSpecification ( t) => self . tool_permissions . is_trusted ( & t. name ) ,
726- } ) ;
727-
728- // Generate prompt based on active context profile and trusted tools
729- let prompt = prompt:: generate_prompt ( self . conversation_state . current_profile ( ) , all_tools_trusted) ;
730-
731- match ( self . input_source . read_line ( Some ( & prompt) ) ?, ctrl_c) {
732- ( Some ( line) , _) => {
733- // Handle empty line case - reprompt the user
734- if line. trim ( ) . is_empty ( ) {
735- continue ;
736- }
737- break line;
738- } ,
739- ( None , false ) => {
740- execute ! (
741- self . output,
742- style:: Print ( format!(
743- "\n (To exit, press Ctrl+C or Ctrl+D again or type {})\n \n " ,
744- "/quit" . green( )
745- ) )
746- ) ?;
747- ctrl_c = true ;
748- } ,
749- ( None , true ) => return Ok ( ChatState :: Exit ) ,
750- }
722+ let user_input = match self . read_user_input ( & self . generate_tool_trust_prompt ( ) , false ) {
723+ Some ( input) => input,
724+ None => return Ok ( ChatState :: Exit ) ,
751725 } ;
752726
753727 self . conversation_state . append_user_transcript ( & user_input) ;
@@ -837,16 +811,39 @@ where
837811 }
838812 } ,
839813 Command :: Clear => {
840- // Clear the conversation including summary
841- self . conversation_state . clear ( false ) ;
842-
814+ execute ! ( self . output, cursor:: Show ) ?;
843815 execute ! (
844816 self . output,
817+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
818+ style:: Print ( "\n Are you sure? This will erase the conversation history for the current session. " ) ,
819+ style:: Print ( "[" ) ,
845820 style:: SetForegroundColor ( Color :: Green ) ,
846- style:: Print ( "\n Conversation history cleared.\n \n " ) ,
847- style:: SetForegroundColor ( Color :: Reset )
821+ style:: Print ( "y" ) ,
822+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
823+ style:: Print ( "/" ) ,
824+ style:: SetForegroundColor ( Color :: Green ) ,
825+ style:: Print ( "n" ) ,
826+ style:: SetForegroundColor ( Color :: DarkGrey ) ,
827+ style:: Print ( "]:\n \n " ) ,
828+ style:: SetForegroundColor ( Color :: Reset ) ,
848829 ) ?;
849830
831+ // Setting `exit_on_single_ctrl_c` for better ux: exit the confirmation dialog rather than the CLI
832+ let user_input = match self . read_user_input ( "> " . yellow ( ) . to_string ( ) . as_str ( ) , true ) {
833+ Some ( input) => input,
834+ None => "" . to_string ( ) ,
835+ } ;
836+
837+ if [ "y" , "Y" ] . contains ( & user_input. as_str ( ) ) {
838+ self . conversation_state . clear ( true ) ;
839+ execute ! (
840+ self . output,
841+ style:: SetForegroundColor ( Color :: Green ) ,
842+ style:: Print ( "\n Conversation history cleared.\n \n " ) ,
843+ style:: SetForegroundColor ( Color :: Reset )
844+ ) ?;
845+ }
846+
850847 ChatState :: PromptUser {
851848 tool_uses : None ,
852849 pending_tool_index : None ,
@@ -2150,6 +2147,46 @@ where
21502147 Ok ( ( ) )
21512148 }
21522149
2150+ /// Helper function to read user input with a prompt and Ctrl+C handling
2151+ fn read_user_input ( & mut self , prompt : & str , exit_on_single_ctrl_c : bool ) -> Option < String > {
2152+ let mut ctrl_c = false ;
2153+ loop {
2154+ match ( self . input_source . read_line ( Some ( prompt) ) , ctrl_c) {
2155+ ( Ok ( Some ( line) ) , _) => {
2156+ if line. trim ( ) . is_empty ( ) {
2157+ continue ; // Reprompt if the input is empty
2158+ }
2159+ return Some ( line) ;
2160+ } ,
2161+ ( Ok ( None ) , false ) => {
2162+ if exit_on_single_ctrl_c {
2163+ return None ;
2164+ }
2165+ execute ! (
2166+ self . output,
2167+ style:: Print ( format!(
2168+ "\n (To exit the CLI, press Ctrl+C or Ctrl+D again or type {})\n \n " ,
2169+ "/quit" . green( )
2170+ ) )
2171+ )
2172+ . unwrap_or_default ( ) ;
2173+ ctrl_c = true ;
2174+ } ,
2175+ ( Ok ( None ) , true ) => return None , // Exit if Ctrl+C was pressed twice
2176+ ( Err ( _) , _) => return None ,
2177+ }
2178+ }
2179+ }
2180+
2181+ /// Helper function to generate a prompt based on the current context
2182+ fn generate_tool_trust_prompt ( & self ) -> String {
2183+ let all_tools_trusted = self . conversation_state . tools . iter ( ) . all ( |t| match t {
2184+ FigTool :: ToolSpecification ( t) => self . tool_permissions . is_trusted ( & t. name ) ,
2185+ } ) ;
2186+
2187+ prompt:: generate_prompt ( self . conversation_state . current_profile ( ) , all_tools_trusted)
2188+ }
2189+
21532190 async fn send_tool_use_telemetry ( & mut self ) {
21542191 for ( _, mut event) in self . tool_use_telemetry_events . drain ( ) {
21552192 event. user_input_id = match self . tool_use_status {
0 commit comments