diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 28dcd981c5..b6c0faad62 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -83,8 +83,6 @@ use crate::context_manager::ContextManager; use crate::environment_context::EnvironmentContext; use crate::error::CodexErr; use crate::error::Result as CodexResult; -use crate::error::error_event_with_update_nudge; -use crate::error::stream_error_event_with_update_nudge; #[cfg(test)] use crate::exec::StreamOutput; use crate::exec_policy::ExecPolicyUpdateError; @@ -98,7 +96,6 @@ use crate::protocol::ApplyPatchApprovalRequestEvent; use crate::protocol::AskForApproval; use crate::protocol::BackgroundEventEvent; use crate::protocol::DeprecationNoticeEvent; -use crate::protocol::ErrorEvent; use crate::protocol::Event; use crate::protocol::EventMsg; use crate::protocol::ExecApprovalRequestEvent; @@ -248,19 +245,11 @@ impl Codex { let exec_policy = Arc::new(RwLock::new(exec_policy)); let config = Arc::new(config); - let mut remote_models_error: Option = None; - let is_up_to_date = compute_is_up_to_date(&config); if config.features.enabled(Feature::RemoteModels) && let Err(err) = models_manager.refresh_available_models(&config).await { error!("failed to refresh available models: {err:?}"); - if !is_up_to_date { - remote_models_error = Some(EventMsg::Error(ErrorEvent { - message: "failed to refresh available models.".to_string(), - codex_error_info: None, - })); - } } let model = models_manager.get_model(&config.model, &config).await; let session_configuration = SessionConfiguration { @@ -278,7 +267,6 @@ impl Codex { original_config_do_not_use: Arc::clone(&config), exec_policy, session_source, - is_up_to_date, }; // Generate a unique ID for the lifetime of this Codex session. @@ -309,14 +297,6 @@ impl Codex { rx_event, }; - if let Some(remote_models_error) = remote_models_error { - let event = Event { - id: INITIAL_SUBMIT_ID.to_string(), - msg: remote_models_error, - }; - session.send_event_raw(event).await; - } - Ok(CodexSpawnOk { codex, conversation_id, @@ -452,8 +432,6 @@ pub(crate) struct SessionConfiguration { original_config_do_not_use: Arc, /// Source of the session (cli, vscode, exec, mcp, ...) session_source: SessionSource, - /// Whether the CLI is up to date with the latest known version at session start. - is_up_to_date: bool, } impl SessionConfiguration { @@ -784,11 +762,6 @@ impl Session { state.get_total_token_usage() } - pub(crate) async fn is_up_to_date(&self) -> bool { - let state = self.state.lock().await; - state.session_configuration.is_up_to_date - } - async fn record_initial_history(&self, conversation_history: InitialHistory) { let turn_context = self.new_turn(SessionSettingsUpdate::default()).await; match conversation_history { @@ -953,25 +926,7 @@ impl Session { } } - pub(crate) async fn send_event_raw(&self, mut event: Event) { - if matches!(&event.msg, EventMsg::Error(_) | EventMsg::StreamError(_)) { - let is_up_to_date = self.is_up_to_date().await; - event.msg = match event.msg { - EventMsg::Error(error_event) => EventMsg::Error(error_event_with_update_nudge( - error_event.message, - error_event.codex_error_info, - is_up_to_date, - )), - EventMsg::StreamError(error_event) => { - EventMsg::StreamError(stream_error_event_with_update_nudge( - error_event.message, - error_event.codex_error_info, - is_up_to_date, - )) - } - other => other, - }; - } + pub(crate) async fn send_event_raw(&self, event: Event) { // Persist the event into rollout (recorder filters as needed) let rollout_items = vec![RolloutItem::EventMsg(event.msg.clone())]; self.persist_rollout_items(&rollout_items).await; @@ -2832,7 +2787,6 @@ mod tests { original_config_do_not_use: Arc::clone(&config), exec_policy: Arc::new(RwLock::new(ExecPolicy::empty())), session_source: SessionSource::Exec, - is_up_to_date: true, }; let mut state = SessionState::new(session_configuration); @@ -2905,7 +2859,6 @@ mod tests { original_config_do_not_use: Arc::clone(&config), exec_policy: Arc::new(RwLock::new(ExecPolicy::empty())), session_source: SessionSource::Exec, - is_up_to_date: true, }; let mut state = SessionState::new(session_configuration); @@ -3110,7 +3063,6 @@ mod tests { original_config_do_not_use: Arc::clone(&config), exec_policy: Arc::new(RwLock::new(ExecPolicy::empty())), session_source: SessionSource::Exec, - is_up_to_date: true, }; let per_turn_config = Session::build_per_turn_config(&session_configuration); let model_family = ModelsManager::construct_model_family_offline( @@ -3202,7 +3154,6 @@ mod tests { original_config_do_not_use: Arc::clone(&config), exec_policy: Arc::new(RwLock::new(ExecPolicy::empty())), session_source: SessionSource::Exec, - is_up_to_date: true, }; let per_turn_config = Session::build_per_turn_config(&session_configuration); let model_family = ModelsManager::construct_model_family_offline( diff --git a/codex-rs/core/src/error.rs b/codex-rs/core/src/error.rs index e8cff309e4..e8fa91d26e 100644 --- a/codex-rs/core/src/error.rs +++ b/codex-rs/core/src/error.rs @@ -3,7 +3,6 @@ use crate::token_data::KnownPlan; use crate::token_data::PlanType; use crate::truncate::TruncationPolicy; use crate::truncate::truncate_text; -use crate::update_action::update_available_nudge; use chrono::DateTime; use chrono::Datelike; use chrono::Local; @@ -13,7 +12,6 @@ use codex_protocol::ConversationId; use codex_protocol::protocol::CodexErrorInfo; use codex_protocol::protocol::ErrorEvent; use codex_protocol::protocol::RateLimitSnapshot; -use codex_protocol::protocol::StreamErrorEvent; use reqwest::StatusCode; use serde_json; use std::io; @@ -26,43 +24,6 @@ pub type Result = std::result::Result; /// Limit UI error messages to a reasonable size while keeping useful context. const ERROR_MESSAGE_UI_MAX_BYTES: usize = 2 * 1024; // 4 KiB -pub(crate) fn error_event_with_update_nudge( - message: String, - codex_error_info: Option, - is_up_to_date: bool, -) -> ErrorEvent { - let message = maybe_append_update_nudge(message, is_up_to_date); - ErrorEvent { - message, - codex_error_info, - } -} - -pub(crate) fn stream_error_event_with_update_nudge( - message: String, - codex_error_info: Option, - is_up_to_date: bool, -) -> StreamErrorEvent { - StreamErrorEvent { - message: maybe_append_update_nudge(message, is_up_to_date), - codex_error_info, - } -} - -fn maybe_append_update_nudge(message: String, is_up_to_date: bool) -> String { - // skip if version is 0.0.0 - let is_dev = env!("CARGO_PKG_VERSION") == "0.0.0"; - if is_up_to_date || is_dev { - return message; - } - let nudge = update_available_nudge(); - if message.is_empty() { - nudge - } else { - format!("{message}\n{nudge}") - } -} - #[derive(Error, Debug)] pub enum SandboxErr { /// Error from sandbox execution diff --git a/codex-rs/core/src/update_action.rs b/codex-rs/core/src/update_action.rs index 99dc52188d..3c56a59cdf 100644 --- a/codex-rs/core/src/update_action.rs +++ b/codex-rs/core/src/update_action.rs @@ -48,7 +48,8 @@ pub fn get_update_action() -> Option { None } -pub(crate) fn update_available_nudge() -> String { +/// Returns the standard update-available message for clients to display. +pub fn update_available_nudge() -> String { match get_update_action() { Some(action) => { let command = action.command_str(); diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 37cd004a15..494405d531 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -676,7 +676,33 @@ impl ChatWidget { self.model_family.clone() } + fn maybe_append_update_nudge(&self, message: String) -> String { + if !self.should_show_update_nudge() { + return message; + } + let nudge = crate::update_action::update_available_nudge(); + if message.is_empty() { + nudge + } else { + format!("{message}\n{nudge}") + } + } + + #[cfg(not(debug_assertions))] + fn should_show_update_nudge(&self) -> bool { + if env!("CARGO_PKG_VERSION") == "0.0.0" { + return false; + } + crate::updates::get_upgrade_version(&self.config).is_some() + } + + #[cfg(debug_assertions)] + fn should_show_update_nudge(&self) -> bool { + false + } + fn on_error(&mut self, message: String) { + let message = self.maybe_append_update_nudge(message); self.finalize_turn(); self.add_to_history(history_cell::new_error_event(message)); self.request_redraw(); @@ -955,6 +981,7 @@ impl ChatWidget { } fn on_stream_error(&mut self, message: String) { + let message = self.maybe_append_update_nudge(message); if self.retry_status_header.is_none() { self.retry_status_header = Some(self.current_status_header.clone()); }