Revert "Option to Notify Workspace Owner When Usage Limit is Reached" (#17391)

Reverts openai/codex#16969

#sev3-2026-04-10-accountscheckversion-500s-for-openai-workspace-7300
This commit is contained in:
Shijie Rao
2026-04-10 16:33:13 -07:00
committed by GitHub
parent a3be74143a
commit 930e5adb7e
82 changed files with 60 additions and 3233 deletions

View File

@@ -16,7 +16,6 @@ use chrono::Utc;
use codex_protocol::protocol::CreditsSnapshot as CoreCreditsSnapshot;
use codex_protocol::protocol::RateLimitSnapshot;
use codex_protocol::protocol::RateLimitWindow;
use codex_protocol::protocol::SpendControlSnapshot as CoreSpendControlSnapshot;
const STATUS_LIMIT_BAR_SEGMENTS: usize = 20;
const STATUS_LIMIT_BAR_FILLED: &str = "";
@@ -99,8 +98,6 @@ pub(crate) struct RateLimitSnapshotDisplay {
pub secondary: Option<RateLimitWindowDisplay>,
/// Optional credits metadata when available.
pub credits: Option<CreditsSnapshotDisplay>,
/// Optional spend-control metadata for usage-based workspace plans.
pub spend_control: Option<SpendControlSnapshotDisplay>,
}
/// Display-ready credits state extracted from protocol snapshots.
@@ -114,13 +111,6 @@ pub(crate) struct CreditsSnapshotDisplay {
pub balance: Option<String>,
}
/// Display-ready spend-control state extracted from protocol snapshots.
#[derive(Debug, Clone)]
pub(crate) struct SpendControlSnapshotDisplay {
/// Whether a workspace spend cap is currently blocking usage.
pub reached: bool,
}
/// Converts a protocol snapshot into UI-friendly display data.
///
/// Pass the timestamp from the same observation point as `snapshot`; supplying a significantly
@@ -150,10 +140,6 @@ pub(crate) fn rate_limit_snapshot_display_for_limit(
.as_ref()
.map(|window| RateLimitWindowDisplay::from_window(window, captured_at)),
credits: snapshot.credits.as_ref().map(CreditsSnapshotDisplay::from),
spend_control: snapshot
.spend_control
.as_ref()
.map(SpendControlSnapshotDisplay::from),
}
}
@@ -167,14 +153,6 @@ impl From<&CoreCreditsSnapshot> for CreditsSnapshotDisplay {
}
}
impl From<&CoreSpendControlSnapshot> for SpendControlSnapshotDisplay {
fn from(value: &CoreSpendControlSnapshot) -> Self {
Self {
reached: value.reached,
}
}
}
/// Builds display rows from a snapshot and marks stale data by capture age.
///
/// Callers should pass `Local::now()` for `now` at render time; using a cached timestamp can make
@@ -197,7 +175,7 @@ pub(crate) fn compose_rate_limit_data_many(
return StatusRateLimitData::Missing;
}
let mut rows = Vec::with_capacity(snapshots.len().saturating_mul(4));
let mut rows = Vec::with_capacity(snapshots.len().saturating_mul(3));
let mut stale = false;
for snapshot in snapshots {
@@ -285,12 +263,6 @@ pub(crate) fn compose_rate_limit_data_many(
});
}
if let Some(spend_control) = snapshot.spend_control.as_ref()
&& let Some(row) = spend_control_status_row(spend_control)
{
rows.push(row);
}
if let Some(credits) = snapshot.credits.as_ref()
&& let Some(row) = credit_status_row(credits)
{
@@ -350,15 +322,6 @@ fn credit_status_row(credits: &CreditsSnapshotDisplay) -> Option<StatusRateLimit
})
}
fn spend_control_status_row(
spend_control: &SpendControlSnapshotDisplay,
) -> Option<StatusRateLimitRow> {
spend_control.reached.then(|| StatusRateLimitRow {
label: "Spend cap".to_string(),
value: StatusRateLimitValue::Text("Reached".to_string()),
})
}
fn format_credit_balance(raw: &str) -> Option<String> {
let trimmed = raw.trim();
if trimmed.is_empty() {
@@ -386,7 +349,6 @@ mod tests {
use super::CreditsSnapshotDisplay;
use super::RateLimitSnapshotDisplay;
use super::RateLimitWindowDisplay;
use super::SpendControlSnapshotDisplay;
use super::StatusRateLimitData;
use super::compose_rate_limit_data_many;
use chrono::Local;
@@ -413,7 +375,6 @@ mod tests {
unlimited: false,
balance: Some("25".to_string()),
}),
spend_control: None,
};
let other = RateLimitSnapshotDisplay {
limit_name: "codex-other".to_string(),
@@ -425,7 +386,6 @@ mod tests {
unlimited: false,
balance: Some("99".to_string()),
}),
spend_control: None,
};
let rows = match compose_rate_limit_data_many(&[codex, other], now) {
@@ -463,7 +423,6 @@ mod tests {
window_minutes: None,
}),
credits: None,
spend_control: None,
};
let rows = match compose_rate_limit_data_many(&[other], now) {
@@ -480,28 +439,4 @@ mod tests {
]
);
}
#[test]
fn spend_cap_reached_renders_status_row_without_windows() {
let now = Local::now();
let snapshot = RateLimitSnapshotDisplay {
limit_name: "codex".to_string(),
captured_at: now,
primary: None,
secondary: None,
credits: Some(CreditsSnapshotDisplay {
has_credits: true,
unlimited: false,
balance: None,
}),
spend_control: Some(SpendControlSnapshotDisplay { reached: true }),
};
let rows = match compose_rate_limit_data_many(&[snapshot], now) {
StatusRateLimitData::Available(rows) => rows,
other => panic!("unexpected status: {other:?}"),
};
let labels: Vec<String> = rows.iter().map(|row| row.label.clone()).collect();
assert_eq!(labels, vec!["Spend cap".to_string()]);
}
}

View File

@@ -1,22 +0,0 @@
---
source: tui/src/status/tests.rs
assertion_line: 963
expression: sanitized
---
/status
╭───────────────────────────────────────────────────────────────────────╮
│ >_ OpenAI Codex (v0.0.0) │
│ │
│ Visit https://chatgpt.com/codex/settings/usage for up-to-date │
│ information on rate limits and credits │
│ │
│ Model: gpt-5.1-codex-max (reasoning none, summaries auto) │
│ Directory: [[workspace]] │
│ Permissions: Custom (read-only, on-request) │
│ Agents.md: <none> │
│ │
│ Token usage: 750 total (500 input + 250 output) │
│ Context window: 100% left (750 used / 272K) │
│ Spend cap: Reached │
╰───────────────────────────────────────────────────────────────────────╯

View File

@@ -136,7 +136,6 @@ async fn status_snapshot_includes_reasoning_details() {
resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 1_200)),
}),
credits: None,
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -320,7 +319,6 @@ async fn status_snapshot_includes_monthly_limit() {
}),
secondary: None,
credits: None,
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -372,7 +370,6 @@ async fn status_snapshot_shows_unlimited_credits() {
unlimited: true,
balance: None,
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -422,7 +419,6 @@ async fn status_snapshot_shows_positive_credits() {
unlimited: false,
balance: Some("12.5".to_string()),
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -472,7 +468,6 @@ async fn status_snapshot_hides_zero_credits() {
unlimited: false,
balance: Some("0".to_string()),
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -520,7 +515,6 @@ async fn status_snapshot_hides_when_has_no_credits_flag() {
unlimited: true,
balance: None,
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -626,7 +620,6 @@ async fn status_snapshot_truncates_in_narrow_terminal() {
}),
secondary: None,
credits: None,
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -740,7 +733,6 @@ async fn status_snapshot_shows_refreshing_limits_notice() {
resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 2_700)),
}),
credits: None,
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -811,7 +803,6 @@ async fn status_snapshot_includes_credits_and_limits() {
unlimited: false,
balance: Some("37.5".to_string()),
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -865,69 +856,6 @@ async fn status_snapshot_shows_unavailable_limits_message() {
primary: None,
secondary: None,
credits: None,
spend_control: None,
plan_type: None,
};
let captured_at = chrono::Local
.with_ymd_and_hms(2024, 6, 7, 8, 9, 10)
.single()
.expect("timestamp");
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
let model_slug = codex_core::test_support::get_model_offline(config.model.as_deref());
let token_info = token_info_for(&model_slug, &config, &usage);
let composite = new_status_output(
&config,
account_display.as_ref(),
Some(&token_info),
&usage,
&None,
/*thread_name*/ None,
/*forked_from*/ None,
Some(&rate_display),
None,
captured_at,
&model_slug,
/*collaboration_mode*/ None,
/*reasoning_effort_override*/ None,
);
let mut rendered_lines = render_lines(&composite.display_lines(/*width*/ 80));
if cfg!(windows) {
for line in &mut rendered_lines {
*line = line.replace('\\', "/");
}
}
let sanitized = sanitize_directory(rendered_lines).join("\n");
assert_snapshot!(sanitized);
}
#[tokio::test]
async fn status_snapshot_shows_spend_cap_reached_message() {
let temp_home = TempDir::new().expect("temp home");
let mut config = test_config(&temp_home).await;
config.model = Some("gpt-5.1-codex-max".to_string());
config.cwd = PathBuf::from("/workspace/tests").abs();
let account_display = test_status_account_display();
let usage = TokenUsage {
input_tokens: 500,
cached_input_tokens: 0,
output_tokens: 250,
reasoning_output_tokens: 0,
total_tokens: 750,
};
let snapshot = RateLimitSnapshot {
limit_id: None,
limit_name: None,
primary: None,
secondary: None,
credits: Some(CreditsSnapshot {
has_credits: true,
unlimited: false,
balance: None,
}),
spend_control: Some(codex_protocol::protocol::SpendControlSnapshot { reached: true }),
plan_type: None,
};
let captured_at = chrono::Local
@@ -984,7 +912,6 @@ async fn status_snapshot_treats_refreshing_empty_limits_as_unavailable() {
primary: None,
secondary: None,
credits: None,
spend_control: None,
plan_type: None,
};
let captured_at = chrono::Local
@@ -1055,7 +982,6 @@ async fn status_snapshot_shows_stale_limits_message() {
resets_at: Some(reset_at_from(&captured_at, /*seconds*/ 1_800)),
}),
credits: None,
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);
@@ -1126,7 +1052,6 @@ async fn status_snapshot_cached_limits_hide_credits_without_flag() {
unlimited: false,
balance: Some("80".to_string()),
}),
spend_control: None,
plan_type: None,
};
let rate_display = rate_limit_snapshot_display(&snapshot, captured_at);