Fix error message (#4204)

Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
This commit is contained in:
pakrym-oai
2025-09-25 11:10:40 -07:00
committed by GitHub
parent 344d4a1d68
commit acc2b63dfb
3 changed files with 61 additions and 10 deletions

View File

@@ -156,7 +156,7 @@ impl std::fmt::Display for UsageLimitReachedError {
)
}
Some(PlanType::Known(KnownPlan::Free)) => {
"To use Codex with your ChatGPT plan, upgrade to Plus: https://openai.com/chatgpt/pricing."
"You've hit your usage limit. Upgrade to Plus to continue using Codex (https://openai.com/chatgpt/pricing)."
.to_string()
}
Some(PlanType::Known(KnownPlan::Pro))
@@ -306,7 +306,7 @@ mod tests {
};
assert_eq!(
err.to_string(),
"To use Codex with your ChatGPT plan, upgrade to Plus: https://openai.com/chatgpt/pricing."
"You've hit your usage limit. Upgrade to Plus to continue using Codex (https://openai.com/chatgpt/pricing)."
);
}

View File

@@ -132,7 +132,9 @@ impl RateLimitWarningState {
fn take_warnings(
&mut self,
secondary_used_percent: Option<f64>,
secondary_window_minutes: Option<u64>,
primary_used_percent: Option<f64>,
primary_window_minutes: Option<u64>,
) -> Vec<String> {
let reached_secondary_cap =
matches!(secondary_used_percent, Some(percent) if percent == 100.0);
@@ -152,8 +154,11 @@ impl RateLimitWarningState {
self.secondary_index += 1;
}
if let Some(threshold) = highest_secondary {
let limit_label = secondary_window_minutes
.map(get_limits_duration)
.unwrap_or_else(|| "weekly".to_string());
warnings.push(format!(
"Heads up, you've used over {threshold:.0}% of your weekly limit. Run /status for a breakdown."
"Heads up, you've used over {threshold:.0}% of your {limit_label} limit. Run /status for a breakdown."
));
}
}
@@ -167,8 +172,11 @@ impl RateLimitWarningState {
self.primary_index += 1;
}
if let Some(threshold) = highest_primary {
let limit_label = primary_window_minutes
.map(get_limits_duration)
.unwrap_or_else(|| "5h".to_string());
warnings.push(format!(
"Heads up, you've used over {threshold:.0}% of your 5h limit. Run /status for a breakdown."
"Heads up, you've used over {threshold:.0}% of your {limit_label} limit. Run /status for a breakdown."
));
}
}
@@ -177,6 +185,26 @@ impl RateLimitWarningState {
}
}
fn get_limits_duration(windows_minutes: u64) -> String {
const MINUTES_PER_HOUR: u64 = 60;
const MINUTES_PER_DAY: u64 = 24 * MINUTES_PER_HOUR;
const MINUTES_PER_WEEK: u64 = 7 * MINUTES_PER_DAY;
const MINUTES_PER_MONTH: u64 = 30 * MINUTES_PER_DAY;
const ROUNDING_BIAS_MINUTES: u64 = 3;
if windows_minutes <= MINUTES_PER_DAY.saturating_add(ROUNDING_BIAS_MINUTES) {
let adjusted = windows_minutes.saturating_add(ROUNDING_BIAS_MINUTES);
let hours = std::cmp::max(1, adjusted / MINUTES_PER_HOUR);
format!("{hours}h")
} else if windows_minutes <= MINUTES_PER_WEEK.saturating_add(ROUNDING_BIAS_MINUTES) {
"weekly".to_string()
} else if windows_minutes <= MINUTES_PER_MONTH.saturating_add(ROUNDING_BIAS_MINUTES) {
"monthly".to_string()
} else {
"annual".to_string()
}
}
/// Common initialization parameters shared by all `ChatWidget` constructors.
pub(crate) struct ChatWidgetInit {
pub(crate) config: Config,
@@ -377,7 +405,15 @@ impl ChatWidget {
.secondary
.as_ref()
.map(|window| window.used_percent),
snapshot
.secondary
.as_ref()
.and_then(|window| window.window_minutes),
snapshot.primary.as_ref().map(|window| window.used_percent),
snapshot
.primary
.as_ref()
.and_then(|window| window.window_minutes),
);
let display = history_cell::rate_limit_snapshot_display(&snapshot, Local::now());

View File

@@ -384,12 +384,12 @@ fn rate_limit_warnings_emit_thresholds() {
let mut state = RateLimitWarningState::default();
let mut warnings: Vec<String> = Vec::new();
warnings.extend(state.take_warnings(Some(10.0), Some(55.0)));
warnings.extend(state.take_warnings(Some(55.0), Some(10.0)));
warnings.extend(state.take_warnings(Some(10.0), Some(80.0)));
warnings.extend(state.take_warnings(Some(80.0), Some(10.0)));
warnings.extend(state.take_warnings(Some(10.0), Some(95.0)));
warnings.extend(state.take_warnings(Some(95.0), Some(10.0)));
warnings.extend(state.take_warnings(Some(10.0), Some(10079), Some(55.0), Some(299)));
warnings.extend(state.take_warnings(Some(55.0), Some(10081), Some(10.0), Some(299)));
warnings.extend(state.take_warnings(Some(10.0), Some(10081), Some(80.0), Some(299)));
warnings.extend(state.take_warnings(Some(80.0), Some(10081), Some(10.0), Some(299)));
warnings.extend(state.take_warnings(Some(10.0), Some(10081), Some(95.0), Some(299)));
warnings.extend(state.take_warnings(Some(95.0), Some(10079), Some(10.0), Some(299)));
assert_eq!(
warnings,
@@ -411,6 +411,21 @@ fn rate_limit_warnings_emit_thresholds() {
);
}
#[test]
fn test_rate_limit_warnings_monthly() {
let mut state = RateLimitWarningState::default();
let mut warnings: Vec<String> = Vec::new();
warnings.extend(state.take_warnings(Some(75.0), Some(43199), None, None));
assert_eq!(
warnings,
vec![String::from(
"Heads up, you've used over 75% of your monthly limit. Run /status for a breakdown.",
),],
"expected one warning per limit for the highest crossed threshold"
);
}
// (removed experimental resize snapshot test)
#[test]