Auto compact at ~90% (#5292)

Users now hit a window exceeded limit and they usually don't know what
to do. This starts auto compact at ~90% of the window.
This commit is contained in:
Ahmed Ibrahim
2025-10-20 11:29:49 -07:00
committed by GitHub
parent cda6db6ccf
commit 049a61bcfc
21 changed files with 236 additions and 110 deletions

View File

@@ -108,7 +108,7 @@ pub(crate) struct ChatComposer {
custom_prompts: Vec<CustomPrompt>,
footer_mode: FooterMode,
footer_hint_override: Option<Vec<(String, String)>>,
context_window_percent: Option<u8>,
context_window_percent: Option<i64>,
}
/// Popup state at most one can be visible at any time.
@@ -1511,7 +1511,7 @@ impl ChatComposer {
self.is_task_running = running;
}
pub(crate) fn set_context_window_percent(&mut self, percent: Option<u8>) {
pub(crate) fn set_context_window_percent(&mut self, percent: Option<i64>) {
if self.context_window_percent != percent {
self.context_window_percent = percent;
}

View File

@@ -17,7 +17,7 @@ pub(crate) struct FooterProps {
pub(crate) esc_backtrack_hint: bool,
pub(crate) use_shift_enter_hint: bool,
pub(crate) is_task_running: bool,
pub(crate) context_window_percent: Option<u8>,
pub(crate) context_window_percent: Option<i64>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -221,8 +221,8 @@ fn build_columns(entries: Vec<Line<'static>>) -> Vec<Line<'static>> {
.collect()
}
fn context_window_line(percent: Option<u8>) -> Line<'static> {
let percent = percent.unwrap_or(100);
fn context_window_line(percent: Option<i64>) -> Line<'static> {
let percent = percent.unwrap_or(100).clamp(0, 100);
Line::from(vec![Span::from(format!("{percent}% context left")).dim()])
}

View File

@@ -70,7 +70,7 @@ pub(crate) struct BottomPane {
status: Option<StatusIndicatorWidget>,
/// Queued user messages to show under the status indicator.
queued_user_messages: Vec<String>,
context_window_percent: Option<u8>,
context_window_percent: Option<i64>,
}
pub(crate) struct BottomPaneParams {
@@ -357,7 +357,7 @@ impl BottomPane {
}
}
pub(crate) fn set_context_window_percent(&mut self, percent: Option<u8>) {
pub(crate) fn set_context_window_percent(&mut self, percent: Option<i64>) {
if self.context_window_percent == percent {
return;
}

View File

@@ -142,9 +142,9 @@ impl RateLimitWarningState {
fn take_warnings(
&mut self,
secondary_used_percent: Option<f64>,
secondary_window_minutes: Option<u64>,
secondary_window_minutes: Option<i64>,
primary_used_percent: Option<f64>,
primary_window_minutes: Option<u64>,
primary_window_minutes: Option<i64>,
) -> Vec<String> {
let reached_secondary_cap =
matches!(secondary_used_percent, Some(percent) if percent == 100.0);
@@ -195,12 +195,14 @@ impl RateLimitWarningState {
}
}
pub(crate) 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;
pub(crate) fn get_limits_duration(windows_minutes: i64) -> String {
const MINUTES_PER_HOUR: i64 = 60;
const MINUTES_PER_DAY: i64 = 24 * MINUTES_PER_HOUR;
const MINUTES_PER_WEEK: i64 = 7 * MINUTES_PER_DAY;
const MINUTES_PER_MONTH: i64 = 30 * MINUTES_PER_DAY;
const ROUNDING_BIAS_MINUTES: i64 = 3;
let windows_minutes = windows_minutes.max(0);
if windows_minutes <= MINUTES_PER_DAY.saturating_add(ROUNDING_BIAS_MINUTES) {
let adjusted = windows_minutes.saturating_add(ROUNDING_BIAS_MINUTES);

View File

@@ -31,16 +31,16 @@ use super::rate_limits::render_status_limit_progress_bar;
#[derive(Debug, Clone)]
struct StatusContextWindowData {
percent_remaining: u8,
tokens_in_context: u64,
window: u64,
percent_remaining: i64,
tokens_in_context: i64,
window: i64,
}
#[derive(Debug, Clone)]
pub(crate) struct StatusTokenUsageData {
total: u64,
input: u64,
output: u64,
total: i64,
input: i64,
output: i64,
context_window: Option<StatusContextWindowData>,
}

View File

@@ -103,7 +103,8 @@ pub(crate) fn compose_account_display(config: &Config) -> Option<StatusAccountDi
None
}
pub(crate) fn format_tokens_compact(value: u64) -> String {
pub(crate) fn format_tokens_compact(value: i64) -> String {
let value = value.max(0);
if value == 0 {
return "0".to_string();
}
@@ -111,14 +112,15 @@ pub(crate) fn format_tokens_compact(value: u64) -> String {
return value.to_string();
}
let value_f64 = value as f64;
let (scaled, suffix) = if value >= 1_000_000_000_000 {
(value as f64 / 1_000_000_000_000.0, "T")
(value_f64 / 1_000_000_000_000.0, "T")
} else if value >= 1_000_000_000 {
(value as f64 / 1_000_000_000.0, "B")
(value_f64 / 1_000_000_000.0, "B")
} else if value >= 1_000_000 {
(value as f64 / 1_000_000.0, "M")
(value_f64 / 1_000_000.0, "M")
} else {
(value as f64 / 1_000.0, "K")
(value_f64 / 1_000.0, "K")
};
let decimals = if scaled < 10.0 {

View File

@@ -27,7 +27,7 @@ pub(crate) enum StatusRateLimitData {
pub(crate) struct RateLimitWindowDisplay {
pub used_percent: f64,
pub resets_at: Option<String>,
pub window_minutes: Option<u64>,
pub window_minutes: Option<i64>,
}
impl RateLimitWindowDisplay {