@@ -613,10 +613,58 @@ impl AppRunner {
613613 }
614614
615615 // ====================================================================
616- // PERFORMANCE OPTIMIZATION: Start TUI immediately, fetch data in background
616+ // Fetch user info BEFORE showing TUI to avoid "User" placeholder
617+ // ====================================================================
618+ let mut user_name: Option < String > = None ;
619+ let mut user_email: Option < String > = None ;
620+ let mut org_name: Option < String > = None ;
621+
622+ // Fetch user info from /me API - wait for this before showing TUI
623+ if let Some ( token) = cortex_login:: get_auth_token ( ) {
624+ tracing:: debug!( "Fetching user info from /me API..." ) ;
625+ if let Ok ( client) = cortex_engine:: create_default_client ( ) {
626+ match client
627+ . get ( "https://api.cortex.foundation/auth/me" )
628+ . bearer_auth ( & token)
629+ . timeout ( std:: time:: Duration :: from_secs ( 5 ) )
630+ . send ( )
631+ . await
632+ {
633+ Ok ( resp) if resp. status ( ) . is_success ( ) => {
634+ if let Ok ( json) = resp. json :: < serde_json:: Value > ( ) . await {
635+ if let Some ( name) = json. get ( "name" ) . and_then ( |v| v. as_str ( ) ) {
636+ user_name = Some ( name. to_string ( ) ) ;
637+ tracing:: info!( "User info loaded: {}" , name) ;
638+ }
639+ if let Some ( email) = json. get ( "email" ) . and_then ( |v| v. as_str ( ) ) {
640+ user_email = Some ( email. to_string ( ) ) ;
641+ }
642+ if let Some ( orgs) = json. get ( "organizations" ) . and_then ( |v| v. as_array ( ) )
643+ {
644+ if let Some ( first_org) = orgs. first ( ) {
645+ if let Some ( org) =
646+ first_org. get ( "org_name" ) . and_then ( |v| v. as_str ( ) )
647+ {
648+ org_name = Some ( org. to_string ( ) ) ;
649+ }
650+ }
651+ }
652+ }
653+ }
654+ Ok ( resp) => {
655+ tracing:: warn!( "Failed to fetch user info: HTTP {}" , resp. status( ) ) ;
656+ }
657+ Err ( e) => {
658+ tracing:: warn!( "Failed to fetch user info: {}" , e) ;
659+ }
660+ }
661+ }
662+ }
663+
664+ // ====================================================================
665+ // Now initialize TUI after we have user info
617666 // ====================================================================
618667
619- // Initialize terminal FIRST to minimize perceived latency
620668 let mut terminal = CortexTerminal :: with_options ( self . terminal_options ) ?;
621669 terminal. set_title ( "Cortex" ) ?;
622670
@@ -641,12 +689,17 @@ impl AppRunner {
641689
642690 let _session_id = cortex_session. id ( ) . to_string ( ) ;
643691
644- // Create app state
692+ // Create app state with user info already loaded
645693 let mut app_state = AppState :: new ( )
646694 . with_model ( model. clone ( ) )
647695 . with_provider ( provider. clone ( ) )
648696 . with_terminal_size ( width, height) ;
649697
698+ // Set user info from pre-fetched data
699+ app_state. user_name = user_name;
700+ app_state. user_email = user_email;
701+ app_state. org_name = org_name;
702+
650703 // ====================================================================
651704 // BACKGROUND TASKS: Spawn non-blocking operations in parallel
652705 // ====================================================================
@@ -655,31 +708,6 @@ impl AppRunner {
655708 let session_history_task =
656709 tokio:: task:: spawn_blocking ( || CortexSession :: list_recent ( 50 ) . ok ( ) ) ;
657710
658- // 2. Fetch user info from API (HTTP request) - spawn in background
659- let user_info_task = {
660- let token = cortex_login:: get_auth_token ( ) ;
661- tokio:: spawn ( async move {
662- if let Some ( token) = token {
663- if let Ok ( client) = cortex_engine:: create_default_client ( ) {
664- if let Ok ( resp) = client
665- . get ( "https://api.cortex.foundation/auth/me" )
666- . bearer_auth ( & token)
667- . timeout ( std:: time:: Duration :: from_secs ( 5 ) )
668- . send ( )
669- . await
670- {
671- if resp. status ( ) . is_success ( ) {
672- if let Ok ( json) = resp. json :: < serde_json:: Value > ( ) . await {
673- return Some ( json) ;
674- }
675- }
676- }
677- }
678- }
679- None
680- } )
681- } ;
682-
683711 // 3. Models prefetch and session validation - spawn in background
684712 // We use a channel to receive results and update provider_manager later
685713 let models_and_validation_task = {
@@ -769,27 +797,6 @@ impl AppRunner {
769797 ) ;
770798 }
771799
772- // Wait for user info (with short timeout - don't block TUI)
773- if let Ok ( Some ( json) ) =
774- tokio:: time:: timeout ( std:: time:: Duration :: from_millis ( 500 ) , user_info_task)
775- . await
776- . unwrap_or ( Ok ( None ) )
777- {
778- if let Some ( name) = json. get ( "name" ) . and_then ( |v| v. as_str ( ) ) {
779- app_state. user_name = Some ( name. to_string ( ) ) ;
780- }
781- if let Some ( email) = json. get ( "email" ) . and_then ( |v| v. as_str ( ) ) {
782- app_state. user_email = Some ( email. to_string ( ) ) ;
783- }
784- if let Some ( orgs) = json. get ( "organizations" ) . and_then ( |v| v. as_array ( ) ) {
785- if let Some ( first_org) = orgs. first ( ) {
786- if let Some ( org_name) = first_org. get ( "org_name" ) . and_then ( |v| v. as_str ( ) ) {
787- app_state. org_name = Some ( org_name. to_string ( ) ) ;
788- }
789- }
790- }
791- }
792-
793800 // Check validation result (with short timeout - don't block TUI)
794801 // We'll handle models update after event loop is created
795802 let validation_result = tokio:: time:: timeout (
0 commit comments