diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 119d41f2b0..8b90a8b5f4 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -10,9 +10,6 @@ use crate::external_editor; use crate::file_search::FileSearchManager; use crate::history_cell; use crate::history_cell::HistoryCell; -use crate::model_migration::ModelMigrationOutcome; -use crate::model_migration::migration_copy_for_models; -use crate::model_migration::run_model_migration_prompt; use crate::pager_overlay::Overlay; use crate::render::highlight::highlight_bash_to_lines; use crate::render::renderable::Renderable; @@ -28,7 +25,6 @@ use codex_core::config::edit::ConfigEdit; use codex_core::config::edit::ConfigEditsBuilder; #[cfg(target_os = "windows")] use codex_core::features::Feature; -use codex_core::models_manager::manager::ModelsManager; use codex_core::models_manager::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG; use codex_core::models_manager::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG; use codex_core::protocol::EventMsg; @@ -40,7 +36,6 @@ use codex_core::protocol::SkillErrorInfo; use codex_core::protocol::TokenUsage; use codex_protocol::ConversationId; use codex_protocol::openai_models::ModelPreset; -use codex_protocol::openai_models::ModelUpgrade; use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use color_eyre::eyre::Result; use color_eyre::eyre::WrapErr; @@ -173,118 +168,6 @@ fn migration_prompt_hidden(config: &Config, migration_config_key: &str) -> bool } } -fn target_preset_for_upgrade<'a>( - available_models: &'a [ModelPreset], - target_model: &str, -) -> Option<&'a ModelPreset> { - available_models - .iter() - .find(|preset| preset.model == target_model) -} - -async fn handle_model_migration_prompt_if_needed( - tui: &mut tui::Tui, - config: &mut Config, - model: &str, - app_event_tx: &AppEventSender, - models_manager: Arc, -) -> Option { - let available_models = models_manager.list_models(config).await; - let upgrade = available_models - .iter() - .find(|preset| preset.model == model) - .and_then(|preset| preset.upgrade.as_ref()); - - if let Some(ModelUpgrade { - id: target_model, - reasoning_effort_mapping, - migration_config_key, - model_link, - upgrade_copy, - }) = upgrade - { - if migration_prompt_hidden(config, migration_config_key.as_str()) { - return None; - } - - let target_model = target_model.to_string(); - if !should_show_model_migration_prompt( - model, - &target_model, - &config.notices.model_migrations, - &available_models, - ) { - return None; - } - - let current_preset = available_models.iter().find(|preset| preset.model == model); - let target_preset = target_preset_for_upgrade(&available_models, &target_model); - let target_preset = target_preset?; - let target_display_name = target_preset.display_name.clone(); - let heading_label = if target_display_name == model { - target_model.clone() - } else { - target_display_name.clone() - }; - let target_description = - (!target_preset.description.is_empty()).then(|| target_preset.description.clone()); - let can_opt_out = current_preset.is_some(); - let prompt_copy = migration_copy_for_models( - model, - &target_model, - model_link.clone(), - upgrade_copy.clone(), - heading_label, - target_description, - can_opt_out, - ); - match run_model_migration_prompt(tui, prompt_copy).await { - ModelMigrationOutcome::Accepted => { - app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged { - from_model: model.to_string(), - to_model: target_model.clone(), - }); - config.model = Some(target_model.clone()); - - let mapped_effort = if let Some(reasoning_effort_mapping) = reasoning_effort_mapping - && let Some(reasoning_effort) = config.model_reasoning_effort - { - reasoning_effort_mapping - .get(&reasoning_effort) - .cloned() - .or(config.model_reasoning_effort) - } else { - config.model_reasoning_effort - }; - - config.model_reasoning_effort = mapped_effort; - - app_event_tx.send(AppEvent::UpdateModel(target_model.clone())); - app_event_tx.send(AppEvent::UpdateReasoningEffort(mapped_effort)); - app_event_tx.send(AppEvent::PersistModelSelection { - model: target_model.clone(), - effort: mapped_effort, - }); - } - ModelMigrationOutcome::Rejected => { - app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged { - from_model: model.to_string(), - to_model: target_model.clone(), - }); - } - ModelMigrationOutcome::Exit => { - return Some(AppExitInfo { - token_usage: TokenUsage::default(), - conversation_id: None, - update_action: None, - }); - } - } - } - - None -} - pub(crate) struct App { pub(crate) server: Arc, pub(crate) app_event_tx: AppEventSender, @@ -424,7 +307,7 @@ impl App { pub async fn run( tui: &mut tui::Tui, auth_manager: Arc, - mut config: Config, + config: Config, active_profile: Option, initial_prompt: Option, initial_images: Vec, @@ -1143,24 +1026,6 @@ impl App { )); } } - AppEvent::PersistModelMigrationPromptAcknowledged { - from_model, - to_model, - } => { - if let Err(err) = ConfigEditsBuilder::new(&self.config.codex_home) - .record_model_migration_seen(from_model.as_str(), to_model.as_str()) - .apply() - .await - { - tracing::error!( - error = %err, - "failed to persist model migration prompt acknowledgement" - ); - self.chat_widget.add_error_message(format!( - "Failed to save model migration prompt preference: {err}" - )); - } - } AppEvent::OpenApprovalsPopup => { self.chat_widget.open_approvals_popup(); } @@ -1426,6 +1291,7 @@ mod tests { use codex_core::protocol::SandboxPolicy; use codex_core::protocol::SessionConfiguredEvent; use codex_protocol::ConversationId; + use codex_protocol::openai_models::ModelUpgrade; use ratatui::prelude::Line; use std::path::PathBuf; use std::sync::Arc; @@ -1591,7 +1457,11 @@ mod tests { &available, )); - assert!(target_preset_for_upgrade(&available, "missing-target").is_none()); + assert!( + !available + .iter() + .any(|preset| preset.model == "missing-target") + ); } #[tokio::test] diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs index 1f99e372e9..26edbe0641 100644 --- a/codex-rs/tui/src/app_event.rs +++ b/codex-rs/tui/src/app_event.rs @@ -143,12 +143,6 @@ pub(crate) enum AppEvent { /// Persist the acknowledgement flag for the rate limit switch prompt. PersistRateLimitSwitchPromptHidden, - /// Persist the acknowledgement flag for the model migration prompt. - PersistModelMigrationPromptAcknowledged { - from_model: String, - to_model: String, - }, - /// Skip the next world-writable scan (one-shot) after a user-confirmed continue. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] SkipNextWorldWritableScan, diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index bce9a350f4..1711c8f1f8 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -58,6 +58,8 @@ pub mod live_wrap; mod markdown; mod markdown_render; mod markdown_stream; +// Model migration prompt UI is no longer used in production; keep it for snapshot tests. +#[cfg(test)] mod model_migration; mod notifications; pub mod onboarding; diff --git a/codex-rs/tui/src/model_migration.rs b/codex-rs/tui/src/model_migration.rs index cf2208109a..3f46d962c7 100644 --- a/codex-rs/tui/src/model_migration.rs +++ b/codex-rs/tui/src/model_migration.rs @@ -1,9 +1,12 @@ +#![allow(dead_code)] + use crate::key_hint; use crate::render::Insets; use crate::render::renderable::ColumnRenderable; use crate::render::renderable::Renderable; use crate::render::renderable::RenderableExt as _; use crate::selection_list::selection_option_row; + use crate::tui::FrameRequester; use crate::tui::Tui; use crate::tui::TuiEvent; diff --git a/codex-rs/tui2/src/app.rs b/codex-rs/tui2/src/app.rs index 8b7acb658a..ddfcb45d17 100644 --- a/codex-rs/tui2/src/app.rs +++ b/codex-rs/tui2/src/app.rs @@ -10,9 +10,6 @@ use crate::exec_command::strip_bash_lc_and_escape; use crate::file_search::FileSearchManager; use crate::history_cell::HistoryCell; use crate::history_cell::UserHistoryCell; -use crate::model_migration::ModelMigrationOutcome; -use crate::model_migration::migration_copy_for_models; -use crate::model_migration::run_model_migration_prompt; use crate::pager_overlay::Overlay; use crate::render::highlight::highlight_bash_to_lines; use crate::render::renderable::Renderable; @@ -41,7 +38,6 @@ use codex_core::config::Config; use codex_core::config::edit::ConfigEditsBuilder; #[cfg(target_os = "windows")] use codex_core::features::Feature; -use codex_core::models_manager::manager::ModelsManager; use codex_core::models_manager::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG; use codex_core::models_manager::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG; use codex_core::protocol::EventMsg; @@ -54,7 +50,6 @@ use codex_core::protocol::TokenUsage; use codex_core::terminal::terminal_info; use codex_protocol::ConversationId; use codex_protocol::openai_models::ModelPreset; -use codex_protocol::openai_models::ModelUpgrade; use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use color_eyre::eyre::Result; use color_eyre::eyre::WrapErr; @@ -207,115 +202,6 @@ fn migration_prompt_hidden(config: &Config, migration_config_key: &str) -> bool } } -async fn handle_model_migration_prompt_if_needed( - tui: &mut tui::Tui, - config: &mut Config, - model: &str, - app_event_tx: &AppEventSender, - models_manager: Arc, -) -> Option { - let available_models = models_manager.list_models(config).await; - let upgrade = available_models - .iter() - .find(|preset| preset.model == model) - .and_then(|preset| preset.upgrade.as_ref()); - - if let Some(ModelUpgrade { - id: target_model, - reasoning_effort_mapping, - migration_config_key, - .. - }) = upgrade - { - if migration_prompt_hidden(config, migration_config_key.as_str()) { - return None; - } - - let target_model = target_model.to_string(); - if !should_show_model_migration_prompt( - model, - &target_model, - &config.notices.model_migrations, - &available_models, - ) { - return None; - } - - let current_preset = available_models.iter().find(|preset| preset.model == model); - let target_preset = available_models - .iter() - .find(|preset| preset.model == target_model); - let target_display_name = target_preset - .map(|preset| preset.display_name.clone()) - .unwrap_or_else(|| target_model.clone()); - let heading_label = if target_display_name == model { - target_model.clone() - } else { - target_display_name.clone() - }; - let target_description = target_preset.and_then(|preset| { - if preset.description.is_empty() { - None - } else { - Some(preset.description.clone()) - } - }); - let can_opt_out = current_preset.is_some(); - let prompt_copy = migration_copy_for_models( - model, - &target_model, - heading_label, - target_description, - can_opt_out, - ); - match run_model_migration_prompt(tui, prompt_copy).await { - ModelMigrationOutcome::Accepted => { - app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged { - from_model: model.to_string(), - to_model: target_model.clone(), - }); - config.model = Some(target_model.clone()); - - let mapped_effort = if let Some(reasoning_effort_mapping) = reasoning_effort_mapping - && let Some(reasoning_effort) = config.model_reasoning_effort - { - reasoning_effort_mapping - .get(&reasoning_effort) - .cloned() - .or(config.model_reasoning_effort) - } else { - config.model_reasoning_effort - }; - - config.model_reasoning_effort = mapped_effort; - - app_event_tx.send(AppEvent::UpdateModel(target_model.clone())); - app_event_tx.send(AppEvent::UpdateReasoningEffort(mapped_effort)); - app_event_tx.send(AppEvent::PersistModelSelection { - model: target_model.clone(), - effort: mapped_effort, - }); - } - ModelMigrationOutcome::Rejected => { - app_event_tx.send(AppEvent::PersistModelMigrationPromptAcknowledged { - from_model: model.to_string(), - to_model: target_model.clone(), - }); - } - ModelMigrationOutcome::Exit => { - return Some(AppExitInfo { - token_usage: TokenUsage::default(), - conversation_id: None, - update_action: None, - session_lines: Vec::new(), - }); - } - } - } - - None -} - pub(crate) struct App { pub(crate) server: Arc, pub(crate) app_event_tx: AppEventSender, @@ -465,7 +351,7 @@ impl App { pub async fn run( tui: &mut tui::Tui, auth_manager: Arc, - mut config: Config, + config: Config, active_profile: Option, initial_prompt: Option, initial_images: Vec, @@ -1990,24 +1876,6 @@ impl App { )); } } - AppEvent::PersistModelMigrationPromptAcknowledged { - from_model, - to_model, - } => { - if let Err(err) = ConfigEditsBuilder::new(&self.config.codex_home) - .record_model_migration_seen(from_model.as_str(), to_model.as_str()) - .apply() - .await - { - tracing::error!( - error = %err, - "failed to persist model migration prompt acknowledgement" - ); - self.chat_widget.add_error_message(format!( - "Failed to save model migration prompt preference: {err}" - )); - } - } AppEvent::OpenApprovalsPopup => { self.chat_widget.open_approvals_popup(); } diff --git a/codex-rs/tui2/src/app_event.rs b/codex-rs/tui2/src/app_event.rs index adb9c1308e..e4492f7ffc 100644 --- a/codex-rs/tui2/src/app_event.rs +++ b/codex-rs/tui2/src/app_event.rs @@ -137,12 +137,6 @@ pub(crate) enum AppEvent { /// Persist the acknowledgement flag for the rate limit switch prompt. PersistRateLimitSwitchPromptHidden, - /// Persist the acknowledgement flag for the model migration prompt. - PersistModelMigrationPromptAcknowledged { - from_model: String, - to_model: String, - }, - /// Skip the next world-writable scan (one-shot) after a user-confirmed continue. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] SkipNextWorldWritableScan, diff --git a/codex-rs/tui2/src/lib.rs b/codex-rs/tui2/src/lib.rs index e006ed8a72..5b0d2cae51 100644 --- a/codex-rs/tui2/src/lib.rs +++ b/codex-rs/tui2/src/lib.rs @@ -58,6 +58,8 @@ pub mod live_wrap; mod markdown; mod markdown_render; mod markdown_stream; +// Model migration prompt UI is no longer used in production; keep it for snapshot tests. +#[cfg(test)] mod model_migration; mod notifications; pub mod onboarding; diff --git a/codex-rs/tui2/src/model_migration.rs b/codex-rs/tui2/src/model_migration.rs index 0b74ad40a5..6e1b7e3c13 100644 --- a/codex-rs/tui2/src/model_migration.rs +++ b/codex-rs/tui2/src/model_migration.rs @@ -1,9 +1,12 @@ +#![allow(dead_code)] + use crate::key_hint; use crate::render::Insets; use crate::render::renderable::ColumnRenderable; use crate::render::renderable::Renderable; use crate::render::renderable::RenderableExt as _; use crate::selection_list::selection_option_row; + use crate::tui::FrameRequester; use crate::tui::Tui; use crate::tui::TuiEvent;