@@ -68,45 +68,14 @@ mod text_formatting;
6868mod tui;
6969mod ui_consts;
7070mod update_prompt;
71+ pub mod updates;
7172mod version;
7273
73- /// Update action the CLI should perform after the TUI exits.
74- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
75- pub enum UpdateAction {
76- /// Update via `npm install -g @openai/codex@latest`.
77- NpmGlobalLatest ,
78- /// Update via `bun install -g @openai/codex@latest`.
79- BunGlobalLatest ,
80- /// Update via `brew upgrade codex`.
81- BrewUpgrade ,
82- }
83-
84- impl UpdateAction {
85- /// Returns the list of command-line arguments for invoking the update.
86- pub fn command_args ( & self ) -> ( & ' static str , & ' static [ & ' static str ] ) {
87- match self {
88- UpdateAction :: NpmGlobalLatest => ( "npm" , & [ "install" , "-g" , "@openai/codex@latest" ] ) ,
89- UpdateAction :: BunGlobalLatest => ( "bun" , & [ "install" , "-g" , "@openai/codex@latest" ] ) ,
90- UpdateAction :: BrewUpgrade => ( "brew" , & [ "upgrade" , "codex" ] ) ,
91- }
92- }
93-
94- /// Returns string representation of the command-line arguments for invoking the update.
95- pub fn command_str ( & self ) -> String {
96- let ( command, args) = self . command_args ( ) ;
97- let args_str = args. join ( " " ) ;
98- format ! ( "{command} {args_str}" )
99- }
100- }
101-
10274mod wrapping;
10375
10476#[ cfg( test) ]
10577pub mod test_backend;
10678
107- #[ cfg( not( debug_assertions) ) ]
108- mod updates;
109-
11079use crate :: onboarding:: TrustDirectorySelection ;
11180use crate :: onboarding:: WSL_INSTRUCTIONS ;
11281use crate :: onboarding:: onboarding_screen:: OnboardingScreenArgs ;
@@ -304,56 +273,6 @@ async fn run_ratatui_app(
304273 }
305274 }
306275
307- // Show update banner in terminal history (instead of stderr) so it is visible
308- // within the TUI scrollback. Building spans keeps styling consistent.
309- #[ cfg( not( debug_assertions) ) ]
310- if let Some ( latest_version) = updates:: get_upgrade_version ( & initial_config) {
311- use crate :: history_cell:: padded_emoji;
312- use crate :: history_cell:: with_border_with_inner_width;
313- use ratatui:: style:: Stylize as _;
314- use ratatui:: text:: Line ;
315-
316- let current_version = env ! ( "CARGO_PKG_VERSION" ) ;
317-
318- let mut content_lines: Vec < Line < ' static > > = vec ! [
319- Line :: from( vec![
320- padded_emoji( "✨" ) . bold( ) . cyan( ) ,
321- "Update available!" . bold( ) . cyan( ) ,
322- " " . into( ) ,
323- format!( "{current_version} -> {latest_version}." ) . bold( ) ,
324- ] ) ,
325- Line :: from( "" ) ,
326- Line :: from( "See full release notes:" ) ,
327- Line :: from( "" ) ,
328- Line :: from(
329- "https://github.com/openai/codex/releases/latest"
330- . cyan( )
331- . underlined( ) ,
332- ) ,
333- Line :: from( "" ) ,
334- ] ;
335-
336- if let Some ( update_action) = get_update_action ( ) {
337- content_lines. push ( Line :: from ( vec ! [
338- "Run " . into( ) ,
339- update_action. command_str( ) . cyan( ) ,
340- " to update." . into( ) ,
341- ] ) ) ;
342- } else {
343- content_lines. push ( Line :: from ( vec ! [
344- "See " . into( ) ,
345- "https://github.com/openai/codex" . cyan( ) . underlined( ) ,
346- " for installation options." . into( ) ,
347- ] ) ) ;
348- }
349-
350- let viewport_width = tui. terminal . viewport_area . width as usize ;
351- let inner_width = viewport_width. saturating_sub ( 4 ) . max ( 1 ) ;
352- let mut lines = with_border_with_inner_width ( content_lines, inner_width) ;
353- lines. push ( "" . into ( ) ) ;
354- tui. insert_history_lines ( lines) ;
355- }
356-
357276 // Initialize high-fidelity session event logging if enabled.
358277 session_log:: maybe_init ( & initial_config) ;
359278
@@ -472,47 +391,6 @@ async fn run_ratatui_app(
472391 app_result
473392}
474393
475- /// Get the update action from the environment.
476- /// Returns `None` if not managed by npm, bun, or brew.
477- #[ cfg( not( debug_assertions) ) ]
478- pub ( crate ) fn get_update_action ( ) -> Option < UpdateAction > {
479- let exe = std:: env:: current_exe ( ) . unwrap_or_default ( ) ;
480- let managed_by_npm = std:: env:: var_os ( "CODEX_MANAGED_BY_NPM" ) . is_some ( ) ;
481- let managed_by_bun = std:: env:: var_os ( "CODEX_MANAGED_BY_BUN" ) . is_some ( ) ;
482- if managed_by_npm {
483- Some ( UpdateAction :: NpmGlobalLatest )
484- } else if managed_by_bun {
485- Some ( UpdateAction :: BunGlobalLatest )
486- } else if cfg ! ( target_os = "macos" )
487- && ( exe. starts_with ( "/opt/homebrew" ) || exe. starts_with ( "/usr/local" ) )
488- {
489- Some ( UpdateAction :: BrewUpgrade )
490- } else {
491- None
492- }
493- }
494-
495- #[ test]
496- #[ cfg( not( debug_assertions) ) ]
497- fn test_get_update_action ( ) {
498- let prev = std:: env:: var_os ( "CODEX_MANAGED_BY_NPM" ) ;
499-
500- // First: no npm var -> expect None (we do not run from brew in CI)
501- unsafe { std:: env:: remove_var ( "CODEX_MANAGED_BY_NPM" ) } ;
502- assert_eq ! ( get_update_action( ) , None ) ;
503-
504- // Then: with npm var -> expect NpmGlobalLatest
505- unsafe { std:: env:: set_var ( "CODEX_MANAGED_BY_NPM" , "1" ) } ;
506- assert_eq ! ( get_update_action( ) , Some ( UpdateAction :: NpmGlobalLatest ) ) ;
507-
508- // Restore prior value to avoid leaking state
509- if let Some ( v) = prev {
510- unsafe { std:: env:: set_var ( "CODEX_MANAGED_BY_NPM" , v) } ;
511- } else {
512- unsafe { std:: env:: remove_var ( "CODEX_MANAGED_BY_NPM" ) } ;
513- }
514- }
515-
516394#[ expect(
517395 clippy:: print_stderr,
518396 reason = "TUI should no longer be displayed, so we can write to stderr."
0 commit comments