Tui: Rate limits (#3977)

### /limits: show rate limits graph

<img width="442" height="287" alt="image"
src="https://github.com/user-attachments/assets/3e29a241-a4b0-4df8-bf71-43dc4dd805ca"
/>

### Warning on close to rate limits:

<img width="507" height="96" alt="image"
src="https://github.com/user-attachments/assets/732a958b-d240-4a89-8289-caa92de83537"
/>

Based on #3965
This commit is contained in:
Ahmed Ibrahim
2025-09-21 10:20:49 -07:00
committed by GitHub
parent 04504d8218
commit a4ebd069e5
11 changed files with 910 additions and 1 deletions

View File

@@ -2,6 +2,9 @@ use crate::diff_render::create_diff_summary;
use crate::exec_command::relativize_to_home;
use crate::exec_command::strip_bash_lc_and_escape;
use crate::markdown::append_markdown;
use crate::rate_limits_view::DEFAULT_GRID_CONFIG;
use crate::rate_limits_view::LimitsView;
use crate::rate_limits_view::build_limits_view;
use crate::render::line_utils::line_to_static;
use crate::render::line_utils::prefix_lines;
use crate::render::line_utils::push_owned_lines;
@@ -24,6 +27,7 @@ use codex_core::plan_tool::UpdatePlanArgs;
use codex_core::project_doc::discover_project_doc_paths;
use codex_core::protocol::FileChange;
use codex_core::protocol::McpInvocation;
use codex_core::protocol::RateLimitSnapshotEvent;
use codex_core::protocol::SandboxPolicy;
use codex_core::protocol::SessionConfiguredEvent;
use codex_core::protocol::TokenUsage;
@@ -221,6 +225,20 @@ impl HistoryCell for PlainHistoryCell {
}
}
#[derive(Debug)]
pub(crate) struct LimitsHistoryCell {
display: LimitsView,
}
impl HistoryCell for LimitsHistoryCell {
fn display_lines(&self, width: u16) -> Vec<Line<'static>> {
let mut lines = self.display.summary_lines.clone();
lines.extend(self.display.gauge_lines(width));
lines.extend(self.display.legend_lines.clone());
lines
}
}
#[derive(Debug)]
pub(crate) struct TranscriptOnlyHistoryCell {
lines: Vec<Line<'static>>,
@@ -1075,6 +1093,33 @@ pub(crate) fn new_completed_mcp_tool_call(
Box::new(PlainHistoryCell { lines })
}
pub(crate) fn new_limits_output(snapshot: &RateLimitSnapshotEvent) -> LimitsHistoryCell {
LimitsHistoryCell {
display: build_limits_view(snapshot, DEFAULT_GRID_CONFIG),
}
}
pub(crate) fn new_limits_unavailable() -> PlainHistoryCell {
PlainHistoryCell {
lines: vec![
"/limits".magenta().into(),
"".into(),
vec!["Rate limit usage snapshot".bold()].into(),
vec![" Tip: run `/limits` right after Codex replies for freshest numbers.".dim()]
.into(),
vec![" Real usage data is not available yet.".into()].into(),
vec![" Send a message to Codex, then run /limits again.".dim()].into(),
],
}
}
#[allow(clippy::disallowed_methods)]
pub(crate) fn new_warning_event(message: String) -> PlainHistoryCell {
PlainHistoryCell {
lines: vec![vec![format!("{message}").yellow()].into()],
}
}
pub(crate) fn new_status_output(
config: &Config,
usage: &TokenUsage,