Add limits to /status (#4053)

Add limits to status

<img width="579" height="430" alt="image"
src="https://github.com/user-attachments/assets/d3794d92-ffca-47be-8011-b4452223cc89"
/>
This commit is contained in:
Ahmed Ibrahim
2025-09-22 11:13:34 -07:00
committed by GitHub
parent 19f46439ae
commit 434eb4fd49
2 changed files with 65 additions and 0 deletions

View File

@@ -1368,6 +1368,7 @@ impl ChatWidget {
&self.config,
usage_ref,
&self.conversation_id,
self.rate_limit_snapshot.as_ref(),
));
}

View File

@@ -58,6 +58,10 @@ use std::time::Instant;
use tracing::error;
use unicode_width::UnicodeWidthStr;
const STATUS_LIMIT_BAR_SEGMENTS: usize = 20;
const STATUS_LIMIT_BAR_FILLED: &str = "";
const STATUS_LIMIT_BAR_EMPTY: &str = " ";
#[derive(Clone, Debug)]
pub(crate) struct CommandOutput {
pub(crate) exit_code: i32,
@@ -1123,6 +1127,7 @@ pub(crate) fn new_status_output(
config: &Config,
usage: &TokenUsage,
session_id: &Option<ConversationId>,
rate_limits: Option<&RateLimitSnapshotEvent>,
) -> PlainHistoryCell {
let mut lines: Vec<Line<'static>> = Vec::new();
lines.push("/status".magenta().into());
@@ -1283,6 +1288,9 @@ pub(crate) fn new_status_output(
format_with_separators(usage.blended_total()).into(),
]));
lines.push("".into());
lines.extend(build_status_limit_lines(rate_limits));
PlainHistoryCell { lines }
}
@@ -1640,6 +1648,62 @@ fn format_mcp_invocation<'a>(invocation: McpInvocation) -> Line<'a> {
invocation_spans.into()
}
fn build_status_limit_lines(snapshot: Option<&RateLimitSnapshotEvent>) -> Vec<Line<'static>> {
let mut lines: Vec<Line<'static>> =
vec![vec![padded_emoji("⏱️").into(), "Usage Limits".bold()].into()];
match snapshot {
Some(snapshot) => {
let rows = [
("5h limit".to_string(), snapshot.primary_used_percent),
("Weekly limit".to_string(), snapshot.weekly_used_percent),
];
let label_width = rows
.iter()
.map(|(label, _)| UnicodeWidthStr::width(label.as_str()))
.max()
.unwrap_or(0);
for (label, percent) in rows {
lines.push(build_status_limit_line(&label, percent, label_width));
}
}
None => lines.push(" • Rate limit data not available yet.".dim().into()),
}
lines
}
fn build_status_limit_line(label: &str, percent_used: f64, label_width: usize) -> Line<'static> {
let clamped_percent = percent_used.clamp(0.0, 100.0);
let progress = render_status_limit_progress_bar(clamped_percent);
let summary = format_status_limit_summary(clamped_percent);
let mut spans: Vec<Span<'static>> = Vec::with_capacity(5);
let padded_label = format!("{label:<label_width$}");
spans.push(format!("{padded_label}: ").into());
spans.push(progress.into());
spans.push(" ".into());
spans.push(summary.into());
Line::from(spans)
}
fn render_status_limit_progress_bar(percent_used: f64) -> String {
let ratio = (percent_used / 100.0).clamp(0.0, 1.0);
let filled = (ratio * STATUS_LIMIT_BAR_SEGMENTS as f64).round() as usize;
let filled = filled.min(STATUS_LIMIT_BAR_SEGMENTS);
let empty = STATUS_LIMIT_BAR_SEGMENTS.saturating_sub(filled);
format!(
"[{}{}]",
STATUS_LIMIT_BAR_FILLED.repeat(filled),
STATUS_LIMIT_BAR_EMPTY.repeat(empty)
)
}
fn format_status_limit_summary(percent_used: f64) -> String {
format!("{percent_used:.0}% used")
}
#[cfg(test)]
mod tests {
use super::*;