Merge upstream/main: adopt rate limit struct changes; keep TUI behavior

- Prefer ours for TUI conflicted files (chatwidget.rs, history_cell.rs)
- Adopt upstream protocol rate limit renames (primary/secondary)
- Update core + exec + TUI to new fields and labels
- Purge check: no reintroduced images
- verify.sh + build-fast.sh: pass (zero warnings)
This commit is contained in:
just-every-code
2025-09-22 21:24:09 +00:00
9 changed files with 46 additions and 46 deletions
+7 -7
View File
@@ -663,18 +663,18 @@ fn attach_item_ids(payload_json: &mut Value, original_items: &[ResponseItem]) {
fn parse_rate_limit_snapshot(headers: &HeaderMap) -> Option<RateLimitSnapshotEvent> {
let primary_used_percent = parse_header_f64(headers, "x-codex-primary-used-percent")?;
let weekly_used_percent = parse_header_f64(headers, "x-codex-protection-used-percent")?;
let primary_to_weekly_ratio_percent =
parse_header_f64(headers, "x-codex-primary-over-protection-limit-percent")?;
let secondary_used_percent = parse_header_f64(headers, "x-codex-secondary-used-percent")?;
let primary_to_secondary_ratio_percent =
parse_header_f64(headers, "x-codex-primary-over-secondary-limit-percent")?;
let primary_window_minutes = parse_header_u64(headers, "x-codex-primary-window-minutes")?;
let weekly_window_minutes = parse_header_u64(headers, "x-codex-protection-window-minutes")?;
let secondary_window_minutes = parse_header_u64(headers, "x-codex-secondary-window-minutes")?;
Some(RateLimitSnapshotEvent {
primary_used_percent,
weekly_used_percent,
primary_to_weekly_ratio_percent,
secondary_used_percent,
primary_to_secondary_ratio_percent,
primary_window_minutes,
weekly_window_minutes,
secondary_window_minutes,
})
}
+3 -3
View File
@@ -3927,10 +3927,10 @@ async fn try_run_turn(
let mut state = sess.state.lock().unwrap();
state.latest_rate_limits = Some(RateLimitSnapshotEvent {
primary_used_percent: snapshot.primary_used_percent,
weekly_used_percent: snapshot.weekly_used_percent,
primary_to_weekly_ratio_percent: snapshot.primary_to_weekly_ratio_percent,
secondary_used_percent: snapshot.secondary_used_percent,
primary_to_secondary_ratio_percent: snapshot.primary_to_secondary_ratio_percent,
primary_window_minutes: snapshot.primary_window_minutes,
weekly_window_minutes: snapshot.weekly_window_minutes,
secondary_window_minutes: snapshot.secondary_window_minutes,
});
}
// Note: ReasoningSummaryPartAdded handled above without scratchpad mutation.
+6 -6
View File
@@ -779,14 +779,14 @@ impl TokenUsageInfo {
pub struct RateLimitSnapshotEvent {
/// Percentage (0-100) of the primary window that has been consumed.
pub primary_used_percent: f64,
/// Percentage (0-100) of the protection window that has been consumed.
pub weekly_used_percent: f64,
/// Size of the primary window relative to weekly (0-100).
pub primary_to_weekly_ratio_percent: f64,
/// Percentage (0-100) of the secondary window that has been consumed.
pub secondary_used_percent: f64,
/// Size of the primary window relative to secondary (0-100).
pub primary_to_secondary_ratio_percent: f64,
/// Rolling window duration for the primary limit, in minutes.
pub primary_window_minutes: u64,
/// Rolling window duration for the weekly limit, in minutes.
pub weekly_window_minutes: u64,
/// Rolling window duration for the secondary limit, in minutes.
pub secondary_window_minutes: u64,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
+6 -6
View File
@@ -860,10 +860,10 @@ async fn token_count_includes_rate_limits_snapshot() {
let response = ResponseTemplate::new(200)
.insert_header("content-type", "text/event-stream")
.insert_header("x-codex-primary-used-percent", "12.5")
.insert_header("x-codex-protection-used-percent", "40.0")
.insert_header("x-codex-primary-over-protection-limit-percent", "75.0")
.insert_header("x-codex-secondary-used-percent", "40.0")
.insert_header("x-codex-primary-over-secondary-limit-percent", "75.0")
.insert_header("x-codex-primary-window-minutes", "10")
.insert_header("x-codex-protection-window-minutes", "60")
.insert_header("x-codex-secondary-window-minutes", "60")
.set_body_raw(sse_body, "text/event-stream");
Mock::given(method("POST"))
@@ -926,10 +926,10 @@ async fn token_count_includes_rate_limits_snapshot() {
},
"rate_limits": {
"primary_used_percent": 12.5,
"weekly_used_percent": 40.0,
"primary_to_weekly_ratio_percent": 75.0,
"secondary_used_percent": 40.0,
"primary_to_secondary_ratio_percent": 75.0,
"primary_window_minutes": 10,
"weekly_window_minutes": 60
"secondary_window_minutes": 60
}
})
);
@@ -294,9 +294,9 @@ impl EventProcessor for EventProcessorWithHumanOutput {
if let Some(snapshot) = &ev.rate_limits {
ts_println!(
self,
"rate limits: hourly {:.1}% • weekly {:.1}%",
"rate limits: hourly {:.1}% • secondary {:.1}%",
snapshot.primary_used_percent,
snapshot.weekly_used_percent
snapshot.secondary_used_percent
);
}
}
+6 -6
View File
@@ -647,14 +647,14 @@ pub struct TokenCountEvent {
pub struct RateLimitSnapshotEvent {
/// Percentage (0-100) of the primary window that has been consumed.
pub primary_used_percent: f64,
/// Percentage (0-100) of the protection window that has been consumed.
pub weekly_used_percent: f64,
/// Size of the primary window relative to weekly (0-100).
pub primary_to_weekly_ratio_percent: f64,
/// Percentage (0-100) of the secondary window that has been consumed.
pub secondary_used_percent: f64,
/// Size of the primary window relative to secondary (0-100).
pub primary_to_secondary_ratio_percent: f64,
/// Rolling window duration for the primary limit, in minutes.
pub primary_window_minutes: u64,
/// Rolling window duration for the weekly limit, in minutes.
pub weekly_window_minutes: u64,
/// Rolling window duration for the secondary limit, in minutes.
pub secondary_window_minutes: u64,
}
/// Payload for `ReplayHistory` containing prior `ResponseItem`s and optional events.
+4 -4
View File
@@ -242,7 +242,7 @@ impl RateLimitWarningState {
{
let threshold = RATE_LIMIT_WARNING_THRESHOLDS[self.weekly_index];
warnings.push(format!(
"Weekly usage exceeded {threshold:.0}% of the limit. Run /limits for detailed usage."
"Secondary usage exceeded {threshold:.0}% of the limit. Run /limits for detailed usage."
));
self.weekly_index += 1;
}
@@ -4244,7 +4244,7 @@ impl ChatWidget<'_> {
self.update_rate_limit_resets(previous_snapshot.as_ref(), &snapshot);
let warnings = self
.rate_limit_warnings
.take_warnings(snapshot.weekly_used_percent, snapshot.primary_used_percent);
.take_warnings(snapshot.secondary_used_percent, snapshot.primary_used_percent);
self.rate_limit_snapshot = Some(snapshot);
if !warnings.is_empty() {
for warning in warnings {
@@ -5260,7 +5260,7 @@ fn update_rate_limit_resets(
changed_primary = true;
}
}
if current.weekly_used_percent + 0.5 < prev.weekly_used_percent {
if current.secondary_used_percent + 0.5 < prev.secondary_used_percent {
if self
.rate_limit_last_weekly_reset_at
.map_or(true, |existing| now > existing)
@@ -5276,7 +5276,7 @@ fn update_rate_limit_resets(
self.rate_limit_last_primary_reset_at = Some(now);
changed_primary = true;
}
if current.weekly_used_percent <= 1.0
if current.secondary_used_percent <= 1.0
&& self.rate_limit_last_weekly_reset_at.is_none()
{
self.rate_limit_last_weekly_reset_at = Some(now);
@@ -82,10 +82,10 @@ fn run_refresh(
let snapshot = CoreRateLimitSnapshotEvent {
primary_used_percent: proto_snapshot.primary_used_percent,
weekly_used_percent: proto_snapshot.weekly_used_percent,
primary_to_weekly_ratio_percent: proto_snapshot.primary_to_weekly_ratio_percent,
secondary_used_percent: proto_snapshot.secondary_used_percent,
primary_to_secondary_ratio_percent: proto_snapshot.primary_to_secondary_ratio_percent,
primary_window_minutes: proto_snapshot.primary_window_minutes,
weekly_window_minutes: proto_snapshot.weekly_window_minutes,
secondary_window_minutes: proto_snapshot.secondary_window_minutes,
};
let event = Event {
+9 -9
View File
@@ -128,14 +128,14 @@ struct RateLimitMetrics {
impl RateLimitMetrics {
fn from_snapshot(snapshot: &RateLimitSnapshotEvent) -> Self {
let hourly_used = snapshot.primary_used_percent.clamp(0.0, 100.0);
let weekly_used = snapshot.weekly_used_percent.clamp(0.0, 100.0);
let weekly_used = snapshot.secondary_used_percent.clamp(0.0, 100.0);
Self {
hourly_used,
weekly_used,
hourly_remaining: (100.0 - hourly_used).max(0.0),
weekly_remaining: (100.0 - weekly_used).max(0.0),
primary_window_minutes: snapshot.primary_window_minutes,
weekly_window_minutes: snapshot.weekly_window_minutes,
weekly_window_minutes: snapshot.secondary_window_minutes,
}
}
@@ -181,7 +181,7 @@ fn build_summary_lines(
lines.push("".into());
lines.push(section_header("Weekly Limit"));
lines.push(section_header("Secondary Limit"));
lines.push(build_bar_line(
"Usage",
metrics.weekly_used,
@@ -193,7 +193,7 @@ fn build_summary_lines(
reset_info.weekly_last_reset,
));
lines.push(build_weekly_reset_line(
snapshot.weekly_window_minutes,
snapshot.secondary_window_minutes,
reset_info.weekly_last_reset,
));
@@ -800,7 +800,7 @@ fn format_minutes_round_units(minutes: u64) -> String {
}
fn extract_capacity_fraction(snapshot: &RateLimitSnapshotEvent) -> Option<f64> {
let ratio = snapshot.primary_to_weekly_ratio_percent;
let ratio = snapshot.primary_to_secondary_ratio_percent;
if ratio.is_finite() {
Some((ratio / 100.0).clamp(0.0, 1.0))
} else {
@@ -958,10 +958,10 @@ mod tests {
fn snapshot() -> RateLimitSnapshotEvent {
RateLimitSnapshotEvent {
primary_used_percent: 30.0,
weekly_used_percent: 60.0,
primary_to_weekly_ratio_percent: 40.0,
secondary_used_percent: 60.0,
primary_to_secondary_ratio_percent: 40.0,
primary_window_minutes: 300,
weekly_window_minutes: 10_080,
secondary_window_minutes: 10_080,
}
}
@@ -1026,7 +1026,7 @@ mod tests {
#[test]
fn build_display_without_ratio_skips_gauge() {
let mut s = snapshot();
s.primary_to_weekly_ratio_percent = f64::NAN;
s.primary_to_secondary_ratio_percent = f64::NAN;
let display = build_limits_view(&s, RateLimitResetInfo::default(), DEFAULT_GRID_CONFIG);
assert!(display.gauge_lines(80).is_empty());
assert!(display.legend_lines.is_empty());