Add Reset in for rate limits (#4111)
- Parse the headers - Reorganize the struct because it's getting too long - show the resets at in the tui <img width="324" height="79" alt="image" src="https://github.com/user-attachments/assets/ca15cd48-f112-4556-91ab-1e3a9bc4683d" />
This commit is contained in:
@@ -77,6 +77,7 @@ use crate::history_cell::CommandOutput;
|
||||
use crate::history_cell::ExecCell;
|
||||
use crate::history_cell::HistoryCell;
|
||||
use crate::history_cell::PatchEventType;
|
||||
use crate::history_cell::RateLimitSnapshotDisplay;
|
||||
use crate::markdown::append_markdown;
|
||||
use crate::slash_command::SlashCommand;
|
||||
use crate::text_formatting::truncate_text;
|
||||
@@ -94,6 +95,7 @@ use crate::streaming::controller::AppEventHistorySink;
|
||||
use crate::streaming::controller::StreamController;
|
||||
use std::path::Path;
|
||||
|
||||
use chrono::Local;
|
||||
use codex_common::approval_presets::ApprovalPreset;
|
||||
use codex_common::approval_presets::builtin_approval_presets;
|
||||
use codex_common::model_presets::ModelPreset;
|
||||
@@ -129,39 +131,46 @@ struct RateLimitWarningState {
|
||||
impl RateLimitWarningState {
|
||||
fn take_warnings(
|
||||
&mut self,
|
||||
secondary_used_percent: f64,
|
||||
primary_used_percent: f64,
|
||||
secondary_used_percent: Option<f64>,
|
||||
primary_used_percent: Option<f64>,
|
||||
) -> Vec<String> {
|
||||
if secondary_used_percent == 100.0 || primary_used_percent == 100.0 {
|
||||
let reached_secondary_cap =
|
||||
matches!(secondary_used_percent, Some(percent) if percent == 100.0);
|
||||
let reached_primary_cap = matches!(primary_used_percent, Some(percent) if percent == 100.0);
|
||||
if reached_secondary_cap || reached_primary_cap {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut warnings = Vec::new();
|
||||
|
||||
let mut highest_secondary: Option<f64> = None;
|
||||
while self.secondary_index < RATE_LIMIT_WARNING_THRESHOLDS.len()
|
||||
&& secondary_used_percent >= RATE_LIMIT_WARNING_THRESHOLDS[self.secondary_index]
|
||||
{
|
||||
highest_secondary = Some(RATE_LIMIT_WARNING_THRESHOLDS[self.secondary_index]);
|
||||
self.secondary_index += 1;
|
||||
}
|
||||
if let Some(threshold) = highest_secondary {
|
||||
warnings.push(format!(
|
||||
"Heads up, you've used over {threshold:.0}% of your weekly limit. Run /status for a breakdown."
|
||||
));
|
||||
if let Some(secondary_used_percent) = secondary_used_percent {
|
||||
let mut highest_secondary: Option<f64> = None;
|
||||
while self.secondary_index < RATE_LIMIT_WARNING_THRESHOLDS.len()
|
||||
&& secondary_used_percent >= RATE_LIMIT_WARNING_THRESHOLDS[self.secondary_index]
|
||||
{
|
||||
highest_secondary = Some(RATE_LIMIT_WARNING_THRESHOLDS[self.secondary_index]);
|
||||
self.secondary_index += 1;
|
||||
}
|
||||
if let Some(threshold) = highest_secondary {
|
||||
warnings.push(format!(
|
||||
"Heads up, you've used over {threshold:.0}% of your weekly limit. Run /status for a breakdown."
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut highest_primary: Option<f64> = None;
|
||||
while self.primary_index < RATE_LIMIT_WARNING_THRESHOLDS.len()
|
||||
&& primary_used_percent >= RATE_LIMIT_WARNING_THRESHOLDS[self.primary_index]
|
||||
{
|
||||
highest_primary = Some(RATE_LIMIT_WARNING_THRESHOLDS[self.primary_index]);
|
||||
self.primary_index += 1;
|
||||
}
|
||||
if let Some(threshold) = highest_primary {
|
||||
warnings.push(format!(
|
||||
"Heads up, you've used over {threshold:.0}% of your 5h limit. Run /status for a breakdown."
|
||||
));
|
||||
if let Some(primary_used_percent) = primary_used_percent {
|
||||
let mut highest_primary: Option<f64> = None;
|
||||
while self.primary_index < RATE_LIMIT_WARNING_THRESHOLDS.len()
|
||||
&& primary_used_percent >= RATE_LIMIT_WARNING_THRESHOLDS[self.primary_index]
|
||||
{
|
||||
highest_primary = Some(RATE_LIMIT_WARNING_THRESHOLDS[self.primary_index]);
|
||||
self.primary_index += 1;
|
||||
}
|
||||
if let Some(threshold) = highest_primary {
|
||||
warnings.push(format!(
|
||||
"Heads up, you've used over {threshold:.0}% of your 5h limit. Run /status for a breakdown."
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
warnings
|
||||
@@ -189,7 +198,7 @@ pub(crate) struct ChatWidget {
|
||||
session_header: SessionHeader,
|
||||
initial_user_message: Option<UserMessage>,
|
||||
token_info: Option<TokenUsageInfo>,
|
||||
rate_limit_snapshot: Option<RateLimitSnapshot>,
|
||||
rate_limit_snapshot: Option<RateLimitSnapshotDisplay>,
|
||||
rate_limit_warnings: RateLimitWarningState,
|
||||
// Stream lifecycle controller
|
||||
stream_controller: Option<StreamController>,
|
||||
@@ -366,16 +375,24 @@ impl ChatWidget {
|
||||
fn on_rate_limit_snapshot(&mut self, snapshot: Option<RateLimitSnapshot>) {
|
||||
if let Some(snapshot) = snapshot {
|
||||
let warnings = self.rate_limit_warnings.take_warnings(
|
||||
snapshot.secondary_used_percent,
|
||||
snapshot.primary_used_percent,
|
||||
snapshot
|
||||
.secondary
|
||||
.as_ref()
|
||||
.map(|window| window.used_percent),
|
||||
snapshot.primary.as_ref().map(|window| window.used_percent),
|
||||
);
|
||||
self.rate_limit_snapshot = Some(snapshot);
|
||||
|
||||
let display = history_cell::rate_limit_snapshot_display(&snapshot, Local::now());
|
||||
self.rate_limit_snapshot = Some(display);
|
||||
|
||||
if !warnings.is_empty() {
|
||||
for warning in warnings {
|
||||
self.add_to_history(history_cell::new_warning_event(warning));
|
||||
}
|
||||
self.request_redraw();
|
||||
}
|
||||
} else {
|
||||
self.rate_limit_snapshot = None;
|
||||
}
|
||||
}
|
||||
/// Finalize any active exec as failed and stop/clear running UI state.
|
||||
|
||||
Reference in New Issue
Block a user