Skip to content

Commit f23c197

Browse files
committed
refactr
1 parent 2a88b14 commit f23c197

18 files changed

+384
-368
lines changed

codex-rs/core/src/client.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -572,21 +572,12 @@ fn parse_rate_limit_window(
572572
window_minutes_header: &str,
573573
resets_header: &str,
574574
) -> Option<RateLimitWindow> {
575-
let used_percent: Option<f64> = parse_header_f64(headers, used_percent_header);
575+
let used_percent = parse_header_f64(headers, used_percent_header)?;
576576

577-
used_percent.and_then(|used_percent| {
578-
let window_minutes = parse_header_u64(headers, window_minutes_header);
579-
let resets_in_seconds = parse_header_u64(headers, resets_header);
580-
581-
let has_data = used_percent != 0.0
582-
|| window_minutes.is_some_and(|minutes| minutes != 0)
583-
|| resets_in_seconds.is_some_and(|seconds| seconds != 0);
584-
585-
has_data.then_some(RateLimitWindow {
586-
used_percent,
587-
window_minutes,
588-
resets_in_seconds,
589-
})
577+
Some(RateLimitWindow {
578+
used_percent,
579+
window_minutes: parse_header_u64(headers, window_minutes_header),
580+
resets_in_seconds: parse_header_u64(headers, resets_header),
590581
})
591582
}
592583

codex-rs/next_step.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Next Step: Restore "Plus" Edits
2+
3+
This branch now carries only the exec cell refactor. Reapply the functionality changes documented below on the follow-up branch.
4+
5+
## Code patches to restore
6+
7+
### core/src/client.rs
8+
```diff
9+
diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs
10+
index 1d1082c2..aedea488 100644
11+
--- a/codex-rs/core/src/client.rs
12+
+++ b/codex-rs/core/src/client.rs
13+
@@ -572,12 +572,21 @@ fn parse_rate_limit_window(
14+
window_minutes_header: &str,
15+
resets_header: &str,
16+
) -> Option<RateLimitWindow> {
17+
- let used_percent = parse_header_f64(headers, used_percent_header)?;
18+
+ let used_percent: Option<f64> = parse_header_f64(headers, used_percent_header);
19+
20+
- Some(RateLimitWindow {
21+
- used_percent,
22+
- window_minutes: parse_header_u64(headers, window_minutes_header),
23+
- resets_in_seconds: parse_header_u64(headers, resets_header),
24+
+ used_percent.and_then(|used_percent| {
25+
+ let window_minutes = parse_header_u64(headers, window_minutes_header);
26+
+ let resets_in_seconds = parse_header_u64(headers, resets_header);
27+
+
28+
+ let has_data = used_percent != 0.0
29+
+ || window_minutes.is_some_and(|minutes| minutes != 0)
30+
+ || resets_in_seconds.is_some_and(|seconds| seconds != 0);
31+
+
32+
+ has_data.then_some(RateLimitWindow {
33+
+ used_percent,
34+
+ window_minutes,
35+
+ resets_in_seconds,
36+
+ })
37+
})
38+
}
39+
```
40+
41+
### tui/src/bottom_pane/chat_composer.rs
42+
```diff
43+
diff --git a/codex-rs/tui/src/bottom_pane/chat_composer.rs b/codex-rs/tui/src/bottom_pane/chat_composer.rs
44+
index eb654815..7530794c 100644
45+
--- a/codex-rs/tui/src/bottom_pane/chat_composer.rs
46+
+++ b/codex-rs/tui/src/bottom_pane/chat_composer.rs
47+
@@ -1330,9 +1330,11 @@ impl WidgetRef for ChatComposer {
48+
}
49+
}
50+
51+
- Line::from(hint)
52+
- .style(Style::default().dim())
53+
- .render_ref(hint_rect, buf);
54+
+ let hint = hint
55+
+ .into_iter()
56+
+ .map(|span| span.patch_style(Style::default().dim()))
57+
+ .collect::<Vec<_>>();
58+
+ Line::from(hint).render_ref(hint_rect, buf);
59+
}
60+
}
61+
let border_style = if self.has_focus {
62+
@@ -1356,9 +1358,8 @@ impl WidgetRef for ChatComposer {
63+
let mut state = self.textarea_state.borrow_mut();
64+
StatefulWidgetRef::render_ref(&(&self.textarea), textarea_rect, buf, &mut state);
65+
if self.textarea.text().is_empty() {
66+
- Line::from(self.placeholder_text.as_str())
67+
- .style(Style::default().dim())
68+
- .render_ref(textarea_rect.inner(Margin::new(0, 0)), buf);
69+
+ let placeholder = Span::from(self.placeholder_text.as_str()).dim();
70+
+ Line::from(vec![placeholder]).render_ref(textarea_rect.inner(Margin::new(0, 0)), buf);
71+
}
72+
}
73+
}
74+
```
75+
76+
### tui/src/chatwidget.rs (rate-limit label helper)
77+
```diff
78+
diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs
79+
index 8bd15b53..66e54cf6 100644
80+
--- a/codex-rs/tui/src/chatwidget.rs
81+
+++ b/codex-rs/tui/src/chatwidget.rs
82+
@@
83+
-fn get_limits_duration(windows_minutes: u64) -> String {
84+
+pub(crate) fn get_limits_duration(windows_minutes: u64) -> String {
85+
```
86+
87+
### tui/src/status/card.rs
88+
```diff
89+
diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs
90+
index a977240b..8f7188d5 100644
91+
--- a/codex-rs/tui/src/status/card.rs
92+
+++ b/codex-rs/tui/src/status/card.rs
93+
@@ -145,7 +145,7 @@ impl StatusHistoryCell {
94+
- let base_spans = formatter.full_spans(row.label, value_spans);
95+
+ let base_spans = formatter.full_spans(row.label.as_str(), value_spans);
96+
@@
97+
- fn collect_rate_limit_labels(
98+
- &self,
99+
- seen: &mut BTreeSet<&'static str>,
100+
- labels: &mut Vec<&'static str>,
101+
- ) {
102+
+ fn collect_rate_limit_labels(&self, seen: &mut BTreeSet<String>, labels: &mut Vec<String>) {
103+
@@
104+
- push_label(labels, seen, row.label);
105+
+ push_label(labels, seen, row.label.as_str());
106+
@@
107+
- let mut labels: Vec<&'static str> =
108+
- vec!["Model", "Directory", "Approval", "Sandbox", "Agents.md"];
109+
- let mut seen: BTreeSet<&'static str> = labels.iter().copied().collect();
110+
+ let mut labels: Vec<String> =
111+
+ vec!["Model", "Directory", "Approval", "Sandbox", "Agents.md"]
112+
+ .into_iter()
113+
+ .map(str::to_string)
114+
+ .collect();
115+
+ let mut seen: BTreeSet<String> = labels.iter().cloned().collect();
116+
@@
117+
- let formatter = FieldFormatter::from_labels(labels.iter().copied());
118+
+ let formatter = FieldFormatter::from_labels(labels.iter().map(String::as_str));
119+
```
120+
121+
### tui/src/status/format.rs
122+
```diff
123+
diff --git a/codex-rs/tui/src/status/format.rs b/codex-rs/tui/src/status/format.rs
124+
index 556e5bd1..fda72904 100644
125+
--- a/codex-rs/tui/src/status/format.rs
126+
+++ b/codex-rs/tui/src/status/format.rs
127+
@@ -15,10 +15,13 @@ pub(crate) struct FieldFormatter {
128+
-pub(crate) fn from_labels(labels: impl IntoIterator<Item = &'static str>) -> Self {
129+
+pub(crate) fn from_labels<S>(labels: impl IntoIterator<Item = S>) -> Self
130+
+where
131+
+ S: AsRef<str>,
132+
+{
133+
@@
134+
- .map(UnicodeWidthStr::width)
135+
+ .map(|label| UnicodeWidthStr::width(label.as_ref()))
136+
@@
137+
- label: &'static str,
138+
+ label: &str,
139+
@@
140+
-pub(crate) fn push_label(
141+
- labels: &mut Vec<&'static str>,
142+
- seen: &mut BTreeSet<&'static str>,
143+
- label: &'static str,
144+
-) {
145+
- if seen.insert(label) {
146+
- labels.push(label);
147+
+pub(crate) fn push_label(labels: &mut Vec<String>, seen: &mut BTreeSet<String>, label: &str) {
148+
+ if seen.contains(label) {
149+
+ return;
150+
+ }
151+
+
152+
+ let owned = label.to_string();
153+
+ seen.insert(owned.clone());
154+
+ labels.push(owned);
155+
}
156+
```
157+
158+
### tui/src/status/rate_limits.rs
159+
```diff
160+
diff --git a/codex-rs/tui/src/status/rate_limits.rs b/codex-rs/tui/src/status/rate_limits.rs
161+
index 17d2f170..8da3a1c6 100644
162+
--- a/codex-rs/tui/src/status/rate_limits.rs
163+
+++ b/codex-rs/tui/src/status/rate_limits.rs
164+
@@ -1,3 +1,5 @@
165+
+use crate::chatwidget::get_limits_duration;
166+
+
167+
@@
168+
- pub label: &'static str,
169+
+ pub label: String,
170+
@@
171+
- pub resets_at: Option<String>,
172+
+ pub resets_at: Option<String>,
173+
+ pub window_minutes: Option<u64>,
174+
@@
175+
- let mut rows = Vec::with_capacity(2);
176+
-
177+
- if let Some(primary) = snapshot.primary.as_ref() {
178+
- rows.push(StatusRateLimitRow {
179+
- label: "5h limit",
180+
- percent_used: primary.used_percent,
181+
- resets_at: primary.resets_at.clone(),
182+
- });
183+
- }
184+
-
185+
- if let Some(secondary) = snapshot.secondary.as_ref() {
186+
- rows.push(StatusRateLimitRow {
187+
- label: "Weekly limit",
188+
- percent_used: secondary.used_percent,
189+
- resets_at: secondary.resets_at.clone(),
190+
- });
191+
- }
192+
+ let mut rows = Vec::with_capacity(2);
193+
+
194+
+ if let Some(primary) = snapshot.primary.as_ref() {
195+
+ let label: String = primary
196+
+ .window_minutes
197+
+ .map(get_limits_duration)
198+
+ .unwrap_or_else(|| "5h".to_string());
199+
+ let label = capitalize_first(&label);
200+
+ rows.push(StatusRateLimitRow {
201+
+ label: format!("{label} limit"),
202+
+ percent_used: primary.used_percent,
203+
+ resets_at: primary.resets_at.clone(),
204+
+ });
205+
+ }
206+
+
207+
+ if let Some(secondary) = snapshot.secondary.as_ref() {
208+
+ let label: String = secondary
209+
+ .window_minutes
210+
+ .map(get_limits_duration)
211+
+ .unwrap_or_else(|| "weekly".to_string());
212+
+ let label = capitalize_first(&label);
213+
+ rows.push(StatusRateLimitRow {
214+
+ label: format!("{label} limit"),
215+
+ percent_used: secondary.used_percent,
216+
+ resets_at: secondary.resets_at.clone(),
217+
+ });
218+
+ }
219+
@@
220+
+fn capitalize_first(label: &str) -> String {
221+
+ let mut chars = label.chars();
222+
+ match chars.next() {
223+
+ Some(first) => {
224+
+ let mut capitalized = first.to_uppercase().collect::<String>();
225+
+ capitalized.push_str(chars.as_str());
226+
+ capitalized
227+
+ }
228+
+ None => String::new(),
229+
+ }
230+
+}
231+
```
232+
233+
### tui/src/status/tests.rs
234+
```diff
235+
diff --git a/codex-rs/tui/src/status/tests.rs b/codex-rs/tui/src/status/tests.rs
236+
index 467b9dd7..d583a5e5 100644
237+
--- a/codex-rs/tui/src/status/tests.rs
238+
+++ b/codex-rs/tui/src/status/tests.rs
239+
@@ -93,7 +93,7 @@ fn status_snapshot_includes_reasoning_details() {
240+
- secondary: Some(RateLimitWindow {
241+
- used_percent: 45.0,
242+
- window_minutes: Some(1_440),
243+
- resets_in_seconds: Some(1_200),
244+
- }),
245+
+ secondary: Some(RateLimitWindow {
246+
+ used_percent: 45.0,
247+
+ window_minutes: Some(10_080),
248+
+ resets_in_seconds: Some(1_200),
249+
+ }),
250+
@@
251+
+#[test]
252+
+fn status_snapshot_includes_monthly_limit() { /* … */ }
253+
+
254+
@@
255+
+#[test]
256+
+fn status_snapshot_shows_missing_limits_message() { /* … */ }
257+
```
258+
259+
## Snapshot updates to recreate
260+
261+
Regenerate the following snapshots after restoring the code above:
262+
263+
- `tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__binary_size_ideal_response.snap`
264+
- `tui/src/snapshots/codex_tui__history_cell__tests__multiline_command_both_lines_wrap_with_correct_prefixes.snap`
265+
- `tui/src/snapshots/codex_tui__history_cell__tests__multiline_command_without_wrap_uses_branch_then_eight_spaces.snap`
266+
- `tui/src/snapshots/codex_tui__history_cell__tests__multiline_command_wraps_with_extra_indent_on_subsequent_lines.snap`
267+
- `tui/src/snapshots/codex_tui__history_cell__tests__ran_cell_multiline_with_stderr_snapshot.snap`
268+
- `tui/src/snapshots/codex_tui__history_cell__tests__single_line_command_wraps_with_four_space_continuation.snap`
269+
- `tui/src/snapshots/codex_tui__history_cell__tests__stderr_tail_more_than_five_lines_snapshot.snap`
270+
- `tui/src/status/snapshots/codex_tui__status__tests__status_snapshot_includes_monthly_limit.snap`
271+
- `tui/src/status/snapshots/codex_tui__status__tests__status_snapshot_shows_missing_limits_message.snap`
272+
273+
Re-run `cargo test -p codex-tui` and accept the new snapshots (`cargo insta accept -p codex-tui`) when reintroducing the "Plus" feature work.

codex-rs/tui/src/bottom_pane/chat_composer.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,11 +1330,9 @@ impl WidgetRef for ChatComposer {
13301330
}
13311331
}
13321332

1333-
let hint = hint
1334-
.into_iter()
1335-
.map(|span| span.patch_style(Style::default().dim()))
1336-
.collect::<Vec<_>>();
1337-
Line::from(hint).render_ref(hint_rect, buf);
1333+
Line::from(hint)
1334+
.style(Style::default().dim())
1335+
.render_ref(hint_rect, buf);
13381336
}
13391337
}
13401338
let border_style = if self.has_focus {
@@ -1358,8 +1356,9 @@ impl WidgetRef for ChatComposer {
13581356
let mut state = self.textarea_state.borrow_mut();
13591357
StatefulWidgetRef::render_ref(&(&self.textarea), textarea_rect, buf, &mut state);
13601358
if self.textarea.text().is_empty() {
1361-
let placeholder = Span::from(self.placeholder_text.as_str()).dim();
1362-
Line::from(vec![placeholder]).render_ref(textarea_rect.inner(Margin::new(0, 0)), buf);
1359+
Line::from(self.placeholder_text.as_str())
1360+
.style(Style::default().dim())
1361+
.render_ref(textarea_rect.inner(Margin::new(0, 0)), buf);
13631362
}
13641363
}
13651364
}

codex-rs/tui/src/chatwidget.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ impl RateLimitWarningState {
186186
}
187187
}
188188

189-
pub(crate) fn get_limits_duration(windows_minutes: u64) -> String {
189+
fn get_limits_duration(windows_minutes: u64) -> String {
190190
const MINUTES_PER_HOUR: u64 = 60;
191191
const MINUTES_PER_DAY: u64 = 24 * MINUTES_PER_HOUR;
192192
const MINUTES_PER_WEEK: u64 = 7 * MINUTES_PER_DAY;

codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__binary_size_ideal_response.snap

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@ expression: visible_after
1717
through crates for heavy dependencies in Cargo.toml, including cli, core,
1818
exec, linux-sandbox, tui, login, ollama, and mcp.
1919

20-
Ran for d in ansi-escape apply-patch arg0 cli common core exec execpolicy
21-
file-search linux-sandbox login mcp-client mcp-server mcp-types ollama
22-
tui; do echo "--- $d/Cargo.toml"; sed -n '1,200p' $d/Cargo.toml; echo;
23-
│ … +1 lines
24-
--- ansi-escape/Cargo.toml
25-
[package]
26-
+7 lines
27-
] }
28-
tracing = { version
20+
Ran
21+
for d in ansi-escape apply-patch arg0 cli common core exec execpolicy
22+
file-search linux-sandbox login mcp-client mcp-server mcp-types ollama
23+
tui; do echo "--- $d/Cargo.toml"; sed -n '1,200p' $d/Cargo.toml; echo;
24+
done
2925

3026
Explored
3127
Read Cargo.toml

0 commit comments

Comments
 (0)