@@ -253,7 +253,7 @@ impl std::fmt::Display for UsageLimitReachedError {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let message = match self.plan_type.as_ref() {
|
let message = match self.plan_type.as_ref() {
|
||||||
Some(PlanType::Known(KnownPlan::Plus)) => format!(
|
Some(PlanType::Known(KnownPlan::Plus)) => format!(
|
||||||
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing){}",
|
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing), visit chatgpt.com/codex/settings/usage to purchase more credits{}",
|
||||||
retry_suffix_after_or(self.resets_at.as_ref())
|
retry_suffix_after_or(self.resets_at.as_ref())
|
||||||
),
|
),
|
||||||
Some(PlanType::Known(KnownPlan::Team)) | Some(PlanType::Known(KnownPlan::Business)) => {
|
Some(PlanType::Known(KnownPlan::Team)) | Some(PlanType::Known(KnownPlan::Business)) => {
|
||||||
@@ -266,8 +266,11 @@ impl std::fmt::Display for UsageLimitReachedError {
|
|||||||
"You've hit your usage limit. Upgrade to Plus to continue using Codex (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()
|
.to_string()
|
||||||
}
|
}
|
||||||
Some(PlanType::Known(KnownPlan::Pro))
|
Some(PlanType::Known(KnownPlan::Pro)) => format!(
|
||||||
| Some(PlanType::Known(KnownPlan::Enterprise))
|
"You've hit your usage limit. Visit chatgpt.com/codex/settings/usage to purchase more credits{}",
|
||||||
|
retry_suffix_after_or(self.resets_at.as_ref())
|
||||||
|
),
|
||||||
|
Some(PlanType::Known(KnownPlan::Enterprise))
|
||||||
| Some(PlanType::Known(KnownPlan::Edu)) => format!(
|
| Some(PlanType::Known(KnownPlan::Edu)) => format!(
|
||||||
"You've hit your usage limit.{}",
|
"You've hit your usage limit.{}",
|
||||||
retry_suffix(self.resets_at.as_ref())
|
retry_suffix(self.resets_at.as_ref())
|
||||||
@@ -467,7 +470,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing) or try again later."
|
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing), visit chatgpt.com/codex/settings/usage to purchase more credits or try again later."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,7 +600,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn usage_limit_reached_error_formats_default_for_other_plans() {
|
fn usage_limit_reached_error_formats_default_for_other_plans() {
|
||||||
let err = UsageLimitReachedError {
|
let err = UsageLimitReachedError {
|
||||||
plan_type: Some(PlanType::Known(KnownPlan::Pro)),
|
plan_type: Some(PlanType::Known(KnownPlan::Enterprise)),
|
||||||
resets_at: None,
|
resets_at: None,
|
||||||
rate_limits: Some(rate_limit_snapshot()),
|
rate_limits: Some(rate_limit_snapshot()),
|
||||||
};
|
};
|
||||||
@@ -607,6 +610,23 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn usage_limit_reached_error_formats_pro_plan_with_reset() {
|
||||||
|
let base = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap();
|
||||||
|
let resets_at = base + ChronoDuration::hours(1);
|
||||||
|
with_now_override(base, move || {
|
||||||
|
let err = UsageLimitReachedError {
|
||||||
|
plan_type: Some(PlanType::Known(KnownPlan::Pro)),
|
||||||
|
resets_at: Some(resets_at),
|
||||||
|
rate_limits: Some(rate_limit_snapshot()),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
err.to_string(),
|
||||||
|
"You've hit your usage limit. Visit chatgpt.com/codex/settings/usage to purchase more credits or try again in 1 hour."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn usage_limit_reached_includes_minutes_when_available() {
|
fn usage_limit_reached_includes_minutes_when_available() {
|
||||||
let base = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap();
|
let base = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap();
|
||||||
@@ -636,7 +656,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing) or try again in 3 hours 32 minutes."
|
"You've hit your usage limit. Upgrade to Pro (https://openai.com/chatgpt/pricing), visit chatgpt.com/codex/settings/usage to purchase more credits or try again in 3 hours 32 minutes."
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ use super::rate_limits::StatusRateLimitRow;
|
|||||||
use super::rate_limits::compose_rate_limit_data;
|
use super::rate_limits::compose_rate_limit_data;
|
||||||
use super::rate_limits::format_status_limit_summary;
|
use super::rate_limits::format_status_limit_summary;
|
||||||
use super::rate_limits::render_status_limit_progress_bar;
|
use super::rate_limits::render_status_limit_progress_bar;
|
||||||
|
use crate::wrapping::RtOptions;
|
||||||
|
use crate::wrapping::word_wrap_lines;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct StatusContextWindowData {
|
struct StatusContextWindowData {
|
||||||
@@ -195,13 +197,7 @@ impl StatusHistoryCell {
|
|||||||
lines
|
lines
|
||||||
}
|
}
|
||||||
StatusRateLimitData::Missing => {
|
StatusRateLimitData::Missing => {
|
||||||
vec![formatter.line(
|
vec![formatter.line("Limits", vec![Span::from("data not available yet").dim()])]
|
||||||
"Limits",
|
|
||||||
vec![
|
|
||||||
Span::from("visit ").dim(),
|
|
||||||
"chatgpt.com/codex/settings/usage".cyan().underlined(),
|
|
||||||
],
|
|
||||||
)]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,6 +311,21 @@ impl HistoryCell for StatusHistoryCell {
|
|||||||
let formatter = FieldFormatter::from_labels(labels.iter().map(String::as_str));
|
let formatter = FieldFormatter::from_labels(labels.iter().map(String::as_str));
|
||||||
let value_width = formatter.value_width(available_inner_width);
|
let value_width = formatter.value_width(available_inner_width);
|
||||||
|
|
||||||
|
let note_first_line = Line::from(vec![
|
||||||
|
Span::from("Visit ").cyan(),
|
||||||
|
"chatgpt.com/codex/settings/usage".cyan().underlined(),
|
||||||
|
Span::from(" for up-to-date").cyan(),
|
||||||
|
]);
|
||||||
|
let note_second_line = Line::from(vec![
|
||||||
|
Span::from("information on rate limits and credits").cyan(),
|
||||||
|
]);
|
||||||
|
let note_lines = word_wrap_lines(
|
||||||
|
[note_first_line, note_second_line],
|
||||||
|
RtOptions::new(available_inner_width),
|
||||||
|
);
|
||||||
|
lines.extend(note_lines);
|
||||||
|
lines.push(Line::from(Vec::<Span<'static>>::new()));
|
||||||
|
|
||||||
let mut model_spans = vec![Span::from(self.model_name.clone())];
|
let mut model_spans = vec![Span::from(self.model_name.clone())];
|
||||||
if !self.model_details.is_empty() {
|
if !self.model_details.is_empty() {
|
||||||
model_spans.push(Span::from(" (").dim());
|
model_spans.push(Span::from(" (").dim());
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ expression: sanitized
|
|||||||
╭────────────────────────────────────────────────────────────────────────────╮
|
╭────────────────────────────────────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ expression: sanitized
|
|||||||
╭─────────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning high, summaries detailed) │
|
│ Model: gpt-5-codex (reasoning high, summaries detailed) │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ expression: sanitized
|
|||||||
╭─────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ expression: sanitized
|
|||||||
╭─────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
@@ -15,5 +18,5 @@ expression: sanitized
|
|||||||
│ │
|
│ │
|
||||||
│ Token usage: 750 total (500 input + 250 output) │
|
│ Token usage: 750 total (500 input + 250 output) │
|
||||||
│ Context window: 100% left (750 used / 272K) │
|
│ Context window: 100% left (750 used / 272K) │
|
||||||
│ Limits: visit chatgpt.com/codex/settings/usage │
|
│ Limits: data not available yet │
|
||||||
╰─────────────────────────────────────────────────────────────────╯
|
╰─────────────────────────────────────────────────────────────────╯
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ expression: sanitized
|
|||||||
╭─────────────────────────────────────────────────────────────────────╮
|
╭─────────────────────────────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
│ Model: gpt-5-codex (reasoning none, summaries auto) │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ expression: sanitized
|
|||||||
╭────────────────────────────────────────────╮
|
╭────────────────────────────────────────────╮
|
||||||
│ >_ OpenAI Codex (v0.0.0) │
|
│ >_ OpenAI Codex (v0.0.0) │
|
||||||
│ │
|
│ │
|
||||||
|
│ Visit chatgpt.com/codex/settings/usage for │
|
||||||
|
│ up-to-date │
|
||||||
|
│ information on rate limits and credits │
|
||||||
|
│ │
|
||||||
│ Model: gpt-5-codex (reasoning │
|
│ Model: gpt-5-codex (reasoning │
|
||||||
│ Directory: [[workspace]] │
|
│ Directory: [[workspace]] │
|
||||||
│ Approval: on-request │
|
│ Approval: on-request │
|
||||||
|
|||||||
Reference in New Issue
Block a user