diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs index 955ae44c0..3be2404a9 100644 --- a/codex-rs/features/src/lib.rs +++ b/codex-rs/features/src/lib.rs @@ -231,7 +231,8 @@ pub enum Feature { TuiAppServer, /// Prevent idle system sleep while a turn is actively running. PreventIdleSleep, - /// Enable workspace-specific owner nudge copy and prompts in the TUI. + /// Removed compatibility flag retained as a no-op now that workspace owner + /// usage nudges are always enabled. WorkspaceOwnerUsageNudge, /// Legacy rollout flag for Responses API WebSocket transport experiments. ResponsesWebsockets, @@ -1153,7 +1154,7 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::WorkspaceOwnerUsageNudge, key: "workspace_owner_usage_nudge", - stage: Stage::UnderDevelopment, + stage: Stage::Removed, default_enabled: false, }, FeatureSpec { diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 9efc99531..38b618122 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -2890,18 +2890,7 @@ impl ChatWidget { self.maybe_send_next_queued_input(); } - fn workspace_owner_usage_nudge_enabled(&self) -> bool { - self.config - .features - .enabled(Feature::WorkspaceOwnerUsageNudge) - } - fn on_rate_limit_error(&mut self, error_kind: RateLimitErrorKind, message: String) { - if !self.workspace_owner_usage_nudge_enabled() { - self.on_error(message); - return; - } - let rate_limit_reached_type = self.codex_rate_limit_reached_type.map(|kind| { if matches!(error_kind, RateLimitErrorKind::UsageLimit) { match kind { @@ -6919,9 +6908,7 @@ impl ChatWidget { } fn open_workspace_owner_nudge_prompt(&mut self, credit_type: AddCreditsNudgeCreditType) { - if !self.workspace_owner_usage_nudge_enabled() - || self.add_credits_nudge_email_in_flight.is_some() - { + if self.add_credits_nudge_email_in_flight.is_some() { return; } @@ -6969,10 +6956,6 @@ impl ChatWidget { &mut self, credit_type: AddCreditsNudgeCreditType, ) -> bool { - if !self.workspace_owner_usage_nudge_enabled() { - return false; - } - self.add_credits_nudge_email_in_flight = Some(credit_type); true } @@ -6985,9 +6968,6 @@ impl ChatWidget { .add_credits_nudge_email_in_flight .take() .unwrap_or(AddCreditsNudgeCreditType::Credits); - if !self.workspace_owner_usage_nudge_enabled() { - return; - } let message = match (credit_type, result) { (AddCreditsNudgeCreditType::Credits, Ok(AddCreditsNudgeEmailStatus::Sent)) => { "Workspace owner notified." diff --git a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs index 8b24baeaf..4cc01d759 100644 --- a/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs +++ b/codex-rs/tui/src/chatwidget/tests/status_and_layout.rs @@ -797,57 +797,9 @@ async fn rate_limit_switch_prompt_popup_snapshot() { assert_chatwidget_snapshot!("rate_limit_switch_prompt_popup", popup); } -#[tokio::test] -async fn workspace_owner_usage_nudge_flag_disabled_keeps_generic_rate_limit_error() { - { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - let mut limits = snapshot(/*percent*/ 100.0); - limits.rate_limit_reached_type = - Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached); - chat.on_rate_limit_snapshot(Some(limits)); - - chat.on_rate_limit_error( - RateLimitErrorKind::UsageLimit, - "Usage limit reached.".to_string(), - ); - let rendered = drain_insert_history(&mut rx) - .into_iter() - .map(|lines| lines_to_single_string(&lines)) - .collect::(); - assert!( - rendered.contains("Usage limit reached."), - "rendered: {rendered}" - ); - } - - { - let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - let mut limits = snapshot(/*percent*/ 100.0); - limits.rate_limit_reached_type = - Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached); - chat.on_rate_limit_snapshot(Some(limits)); - - chat.on_rate_limit_error( - RateLimitErrorKind::UsageLimit, - "Usage limit reached.".to_string(), - ); - let popup = render_bottom_popup(&chat, /*width*/ 100); - assert!( - !popup.contains("Request a limit increase from your owner"), - "popup: {popup}" - ); - assert_no_owner_nudge_or_rate_limit_refresh(&mut rx); - } -} - -fn enable_workspace_owner_usage_nudge(chat: &mut ChatWidget) { - chat.set_feature_enabled(Feature::WorkspaceOwnerUsageNudge, /*enabled*/ true); -} - #[tokio::test] async fn workspace_member_credits_depleted_prompts_and_sends_credits() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted); chat.on_rate_limit_snapshot(Some(limits)); @@ -867,7 +819,6 @@ async fn workspace_member_credits_depleted_prompts_and_sends_credits() { #[tokio::test] async fn workspace_member_usage_limit_prompts_and_sends_usage_limit() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached); chat.on_rate_limit_snapshot(Some(limits)); @@ -887,7 +838,6 @@ async fn workspace_member_usage_limit_prompts_and_sends_usage_limit() { #[tokio::test] async fn header_rate_limit_snapshot_preserves_member_limit_type_for_error_prompt() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut usage_limits = snapshot(/*percent*/ 100.0); usage_limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached); @@ -917,7 +867,6 @@ async fn header_rate_limit_snapshot_preserves_member_limit_type_for_error_prompt #[tokio::test] async fn usage_limit_error_remaps_stale_member_credits_state_to_usage_limit_prompt() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted); chat.on_rate_limit_snapshot(Some(limits)); @@ -954,7 +903,6 @@ async fn workspace_owner_limit_states_do_not_prompt_for_owner_nudge() { ), ] { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(limit_type); chat.on_rate_limit_snapshot(Some(limits)); @@ -984,7 +932,6 @@ async fn workspace_owner_limit_states_render_state_specific_messages() { let mut rendered_cases = Vec::new(); for (limit_type, error_kind, expected) in cases { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(limit_type); chat.on_rate_limit_snapshot(Some(limits)); @@ -1007,7 +954,6 @@ async fn workspace_owner_limit_states_render_state_specific_messages() { #[tokio::test] async fn missing_rate_limit_reached_type_does_not_prompt_or_refresh() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); chat.on_rate_limit_snapshot(Some(snapshot(/*percent*/ 100.0))); chat.on_rate_limit_error( @@ -1022,7 +968,6 @@ async fn missing_rate_limit_reached_type_does_not_prompt_or_refresh() { #[tokio::test] async fn workspace_owner_nudge_default_no_dismisses_without_sending() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberCreditsDepleted); chat.on_rate_limit_snapshot(Some(limits)); @@ -1039,7 +984,6 @@ async fn workspace_owner_nudge_default_no_dismisses_without_sending() { #[tokio::test] async fn workspace_owner_nudge_reappears_after_dismissing_no() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); let mut limits = snapshot(/*percent*/ 100.0); limits.rate_limit_reached_type = Some(RateLimitReachedType::WorkspaceMemberUsageLimitReached); chat.on_rate_limit_snapshot(Some(limits)); @@ -1082,7 +1026,6 @@ async fn workspace_owner_credits_nudge_completion_renders_feedback() { let mut rendered_cases = Vec::new(); for (result, expected) in cases { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); chat.start_add_credits_nudge_email_request(AddCreditsNudgeCreditType::Credits); chat.finish_add_credits_nudge_email_request(result); let rendered = drain_insert_history(&mut rx) @@ -1119,7 +1062,6 @@ async fn workspace_owner_usage_limit_nudge_completion_renders_feedback() { let mut rendered_cases = Vec::new(); for (result, expected) in cases { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; - enable_workspace_owner_usage_nudge(&mut chat); chat.start_add_credits_nudge_email_request(AddCreditsNudgeCreditType::UsageLimit); chat.finish_add_credits_nudge_email_request(result); let rendered = drain_insert_history(&mut rx)