@@ -3,6 +3,8 @@ use crate::history_cell::HistoryCell;
33use crate :: history_cell:: PlainHistoryCell ;
44use crate :: history_cell:: with_border_with_inner_width;
55use crate :: version:: CODEX_CLI_VERSION ;
6+ use chrono:: DateTime ;
7+ use chrono:: Local ;
68use codex_common:: create_config_summary_entries;
79use codex_core:: config:: Config ;
810use codex_core:: protocol:: SandboxPolicy ;
@@ -25,6 +27,7 @@ use super::helpers::format_directory_display;
2527use super :: helpers:: format_tokens_compact;
2628use super :: rate_limits:: RateLimitSnapshotDisplay ;
2729use super :: rate_limits:: StatusRateLimitData ;
30+ use super :: rate_limits:: StatusRateLimitRow ;
2831use super :: rate_limits:: compose_rate_limit_data;
2932use super :: rate_limits:: format_status_limit_summary;
3033use super :: rate_limits:: render_status_limit_progress_bar;
@@ -64,9 +67,17 @@ pub(crate) fn new_status_output(
6467 context_usage : Option < & TokenUsage > ,
6568 session_id : & Option < ConversationId > ,
6669 rate_limits : Option < & RateLimitSnapshotDisplay > ,
70+ now : DateTime < Local > ,
6771) -> CompositeHistoryCell {
6872 let command = PlainHistoryCell :: new ( vec ! [ "/status" . magenta( ) . into( ) ] ) ;
69- let card = StatusHistoryCell :: new ( config, total_usage, context_usage, session_id, rate_limits) ;
73+ let card = StatusHistoryCell :: new (
74+ config,
75+ total_usage,
76+ context_usage,
77+ session_id,
78+ rate_limits,
79+ now,
80+ ) ;
7081
7182 CompositeHistoryCell :: new ( vec ! [ Box :: new( command) , Box :: new( card) ] )
7283}
@@ -78,6 +89,7 @@ impl StatusHistoryCell {
7889 context_usage : Option < & TokenUsage > ,
7990 session_id : & Option < ConversationId > ,
8091 rate_limits : Option < & RateLimitSnapshotDisplay > ,
92+ now : DateTime < Local > ,
8193 ) -> Self {
8294 let config_entries = create_config_summary_entries ( config) ;
8395 let ( model_name, model_details) = compose_model_display ( config, & config_entries) ;
@@ -108,7 +120,7 @@ impl StatusHistoryCell {
108120 output : total_usage. output_tokens ,
109121 context_window,
110122 } ;
111- let rate_limits = compose_rate_limit_data ( rate_limits) ;
123+ let rate_limits = compose_rate_limit_data ( rate_limits, now ) ;
112124
113125 Self {
114126 model_name,
@@ -171,47 +183,66 @@ impl StatusHistoryCell {
171183 ] ;
172184 }
173185
174- let mut lines = Vec :: with_capacity ( rows_data. len ( ) * 2 ) ;
175-
176- for row in rows_data {
177- let value_spans = vec ! [
178- Span :: from( render_status_limit_progress_bar( row. percent_used) ) ,
179- Span :: from( " " ) ,
180- Span :: from( format_status_limit_summary( row. percent_used) ) ,
181- ] ;
182- let base_spans = formatter. full_spans ( row. label . as_str ( ) , value_spans) ;
183- let base_line = Line :: from ( base_spans. clone ( ) ) ;
184-
185- if let Some ( resets_at) = row. resets_at . as_ref ( ) {
186- let resets_span = Span :: from ( format ! ( "(resets {resets_at})" ) ) . dim ( ) ;
187- let mut inline_spans = base_spans. clone ( ) ;
188- inline_spans. push ( Span :: from ( " " ) . dim ( ) ) ;
189- inline_spans. push ( resets_span. clone ( ) ) ;
190-
191- if line_display_width ( & Line :: from ( inline_spans. clone ( ) ) )
192- <= available_inner_width
193- {
194- lines. push ( Line :: from ( inline_spans) ) ;
195- } else {
196- lines. push ( base_line) ;
197- lines. push ( formatter. continuation ( vec ! [ resets_span] ) ) ;
198- }
199- } else {
200- lines. push ( base_line) ;
201- }
202- }
203-
186+ self . rate_limit_row_lines ( rows_data, available_inner_width, formatter)
187+ }
188+ StatusRateLimitData :: Stale ( rows_data) => {
189+ let mut lines =
190+ self . rate_limit_row_lines ( rows_data, available_inner_width, formatter) ;
191+ lines. push ( formatter. line (
192+ "Warning" ,
193+ vec ! [ Span :: from( "limits may be stale - start new turn to refresh." ) . dim( ) ] ,
194+ ) ) ;
204195 lines
205196 }
206197 StatusRateLimitData :: Missing => {
207198 vec ! [ formatter. line(
208199 "Limits" ,
209- vec![ Span :: from( "send a message to load usage data" ) . dim( ) ] ,
200+ vec![
201+ Span :: from( "visit " ) . dim( ) ,
202+ "chatgpt.com/codex/settings/usage" . cyan( ) . underlined( ) ,
203+ ] ,
210204 ) ]
211205 }
212206 }
213207 }
214208
209+ fn rate_limit_row_lines (
210+ & self ,
211+ rows : & [ StatusRateLimitRow ] ,
212+ available_inner_width : usize ,
213+ formatter : & FieldFormatter ,
214+ ) -> Vec < Line < ' static > > {
215+ let mut lines = Vec :: with_capacity ( rows. len ( ) . saturating_mul ( 2 ) ) ;
216+
217+ for row in rows {
218+ let value_spans = vec ! [
219+ Span :: from( render_status_limit_progress_bar( row. percent_used) ) ,
220+ Span :: from( " " ) ,
221+ Span :: from( format_status_limit_summary( row. percent_used) ) ,
222+ ] ;
223+ let base_spans = formatter. full_spans ( row. label . as_str ( ) , value_spans) ;
224+ let base_line = Line :: from ( base_spans. clone ( ) ) ;
225+
226+ if let Some ( resets_at) = row. resets_at . as_ref ( ) {
227+ let resets_span = Span :: from ( format ! ( "(resets {resets_at})" ) ) . dim ( ) ;
228+ let mut inline_spans = base_spans. clone ( ) ;
229+ inline_spans. push ( Span :: from ( " " ) . dim ( ) ) ;
230+ inline_spans. push ( resets_span. clone ( ) ) ;
231+
232+ if line_display_width ( & Line :: from ( inline_spans. clone ( ) ) ) <= available_inner_width {
233+ lines. push ( Line :: from ( inline_spans) ) ;
234+ } else {
235+ lines. push ( base_line) ;
236+ lines. push ( formatter. continuation ( vec ! [ resets_span] ) ) ;
237+ }
238+ } else {
239+ lines. push ( base_line) ;
240+ }
241+ }
242+
243+ lines
244+ }
245+
215246 fn collect_rate_limit_labels ( & self , seen : & mut BTreeSet < String > , labels : & mut Vec < String > ) {
216247 match & self . rate_limits {
217248 StatusRateLimitData :: Available ( rows) => {
@@ -223,6 +254,12 @@ impl StatusHistoryCell {
223254 }
224255 }
225256 }
257+ StatusRateLimitData :: Stale ( rows) => {
258+ for row in rows {
259+ push_label ( labels, seen, row. label . as_str ( ) ) ;
260+ }
261+ push_label ( labels, seen, "Warning" ) ;
262+ }
226263 StatusRateLimitData :: Missing => push_label ( labels, seen, "Limits" ) ,
227264 }
228265 }
0 commit comments