@@ -146,6 +146,28 @@ fn exit_messages(exit: &devo_tui::AppExit, color_enabled: bool) -> Vec<String> {
146146 lines
147147}
148148
149+ fn onboarding_exit_messages ( exit : & devo_tui:: AppExit , color_enabled : bool ) -> Vec < String > {
150+ if !exit. onboarding_completed {
151+ return Vec :: new ( ) ;
152+ }
153+ let complete = if color_enabled {
154+ "\u{1b} [1;32mConfiguration complete\u{1b} [0m" . to_string ( )
155+ } else {
156+ "Configuration complete" . to_string ( )
157+ } ;
158+ let command = if color_enabled {
159+ "\u{1b} [1;36mdevo\u{1b} [0m" . to_string ( )
160+ } else {
161+ "devo" . to_string ( )
162+ } ;
163+ vec ! [
164+ complete,
165+ String :: new( ) ,
166+ "Next step:" . to_string( ) ,
167+ format!( " {command}" ) ,
168+ ]
169+ }
170+
149171async fn run_cli ( ) -> Result < ( ) > {
150172 let cli = Cli :: parse ( ) ;
151173 let log_level = cli. log_level . map ( |level| level. to_string ( ) ) ;
@@ -155,8 +177,14 @@ async fn run_cli() -> Result<()> {
155177 // Resolve logging config early, install the process-wide file subscriber,
156178 // and keep its non-blocking writer guard alive for the command lifetime.
157179 let _logging = install_logging ( & cli) ?;
158- let exit = run_agent ( /*force_onboarding*/ true , log_level. as_deref ( ) , None ) . await ?;
159- for line in exit_messages ( & exit, /*color_enabled*/ true ) {
180+ let exit = run_agent (
181+ /*force_onboarding*/ true ,
182+ /*exit_after_onboarding*/ true ,
183+ log_level. as_deref ( ) ,
184+ None ,
185+ )
186+ . await ?;
187+ for line in onboarding_exit_messages ( & exit, /*color_enabled*/ true ) {
160188 println ! ( "{line}" ) ;
161189 }
162190 Ok ( ( ) )
@@ -176,6 +204,7 @@ async fn run_cli() -> Result<()> {
176204 let _logging = install_logging ( & cli) ?;
177205 let exit = run_agent (
178206 /*force_onboarding*/ false ,
207+ /*exit_after_onboarding*/ false ,
179208 log_level. as_deref ( ) ,
180209 Some ( * session_id) ,
181210 )
@@ -202,7 +231,13 @@ async fn run_cli() -> Result<()> {
202231 maybe_print_startup_update ( & cli) . await ;
203232 let _logging = install_logging ( & cli) ?;
204233 tracing:: info!( "default interactive command starting" ) ;
205- let exit = run_agent ( /*force_onboarding*/ false , log_level. as_deref ( ) , None ) . await ?;
234+ let exit = run_agent (
235+ /*force_onboarding*/ false ,
236+ /*exit_after_onboarding*/ false ,
237+ log_level. as_deref ( ) ,
238+ None ,
239+ )
240+ . await ?;
206241 let exit_lines = exit_messages ( & exit, /*color_enabled*/ true ) ;
207242 tracing:: info!(
208243 line_count = exit_lines. len( ) ,
@@ -339,6 +374,7 @@ mod tests {
339374 use super :: cli_logging_overrides;
340375 use super :: exit_messages;
341376 use super :: format_token_usage_line;
377+ use super :: onboarding_exit_messages;
342378
343379 #[ test]
344380 fn cli_parses_supported_log_levels ( ) {
@@ -527,6 +563,7 @@ mod tests {
527563 let session_id = SessionId :: new ( ) ;
528564 let exit = devo_tui:: AppExit {
529565 session_id : Some ( session_id) ,
566+ onboarding_completed : false ,
530567 turn_count : 1 ,
531568 total_input_tokens : 10 ,
532569 total_output_tokens : 2 ,
@@ -549,6 +586,7 @@ mod tests {
549586 let session_id = SessionId :: new ( ) ;
550587 let exit = devo_tui:: AppExit {
551588 session_id : Some ( session_id) ,
589+ onboarding_completed : false ,
552590 turn_count : 1 ,
553591 total_input_tokens : 10 ,
554592 total_output_tokens : 2 ,
@@ -561,4 +599,65 @@ mod tests {
561599 let lines = exit_messages ( & exit, /*color_enabled*/ true ) ;
562600 assert ! ( lines[ 1 ] . contains( "\u{1b} [" ) ) ;
563601 }
602+
603+ #[ test]
604+ fn onboarding_exit_messages_include_next_step_after_success ( ) {
605+ let session_id = SessionId :: new ( ) ;
606+ let exit = devo_tui:: AppExit {
607+ session_id : Some ( session_id) ,
608+ onboarding_completed : true ,
609+ turn_count : 0 ,
610+ total_input_tokens : 0 ,
611+ total_output_tokens : 0 ,
612+ total_cache_read_tokens : 0 ,
613+ } ;
614+
615+ let lines = onboarding_exit_messages ( & exit, /*color_enabled*/ false ) ;
616+
617+ assert_eq ! (
618+ lines,
619+ vec![
620+ "Configuration complete" . to_string( ) ,
621+ String :: new( ) ,
622+ "Next step:" . to_string( ) ,
623+ " devo" . to_string( ) ,
624+ ]
625+ ) ;
626+ assert_eq ! ( lines. iter( ) . any( |line| line. contains( "devo resume" ) ) , false ) ;
627+ }
628+
629+ #[ test]
630+ fn onboarding_exit_messages_are_empty_without_success ( ) {
631+ let session_id = SessionId :: new ( ) ;
632+ let exit = devo_tui:: AppExit {
633+ session_id : Some ( session_id) ,
634+ onboarding_completed : false ,
635+ turn_count : 0 ,
636+ total_input_tokens : 0 ,
637+ total_output_tokens : 0 ,
638+ total_cache_read_tokens : 0 ,
639+ } ;
640+
641+ assert_eq ! (
642+ onboarding_exit_messages( & exit, /*color_enabled*/ false ) ,
643+ Vec :: <String >:: new( )
644+ ) ;
645+ }
646+
647+ #[ test]
648+ fn colorized_onboarding_exit_messages_include_ansi_sequences ( ) {
649+ let exit = devo_tui:: AppExit {
650+ session_id : None ,
651+ onboarding_completed : true ,
652+ turn_count : 0 ,
653+ total_input_tokens : 0 ,
654+ total_output_tokens : 0 ,
655+ total_cache_read_tokens : 0 ,
656+ } ;
657+
658+ let lines = onboarding_exit_messages ( & exit, /*color_enabled*/ true ) ;
659+
660+ assert ! ( lines[ 0 ] . contains( "\u{1b} [" ) ) ;
661+ assert ! ( lines[ 3 ] . contains( "\u{1b} [" ) ) ;
662+ }
564663}
0 commit comments