Skip to content

Commit f48a23a

Browse files
etraut-openaicopyberry
authored andcommitted
Remove randomized greetings from TUI session headers
## What changed Remove startup greeting phrases and the shared greeting state from startup drafts, session headers, and the empty-state animation. Raw session headers now consistently include `model:` and `directory:` fields. ## Testing Update startup and fresh-thread snapshots to omit greetings, and adjust raw-header assertions to check model and directory fields. GitOrigin-RevId: 531b5ba42d7a88f86b1c7f69030f3560abc25198
1 parent 05ea5f7 commit f48a23a

19 files changed

Lines changed: 22 additions & 279 deletions

‎codex-rs/tui/src/app/empty_state_animation_tests.rs‎

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,6 @@ async fn empty_state_animation_preserves_header_cursor_and_footer() -> Result<()
181181
let size = Size::new(/*width*/ 120, /*height*/ 44);
182182
let mut tui = crate::tui::test_support::make_test_tui()?;
183183
tui.set_owned_screen(/*owned*/ true)?;
184-
app.chat_widget
185-
.empty_state_animation
186-
.borrow()
187-
.greeting
188-
.set(crate::empty_state_animation::Greeting {
189-
phrase: "Pull up a prompt.",
190-
})
191-
.expect("initial greeting");
192184
app.queue_clear_ui_header(&mut tui);
193185
app.transcript_cells
194186
.push(Arc::new(history_cell::StartupWarningsCell::mcp(
@@ -209,7 +201,6 @@ async fn empty_state_animation_preserves_header_cursor_and_footer() -> Result<()
209201
let after = crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal);
210202
assert!(has_blossom(&tui));
211203
assert_eq!(tui.terminal.last_known_cursor_pos, cursor);
212-
assert!(text(&before).contains("Pull up a prompt."));
213204
assert_eq!(
214205
&after.content[after.index_of(/*x*/ 0, before_bottom.y)..],
215206
&before.content[before.index_of(/*x*/ 0, before_bottom.y)..]
@@ -222,14 +213,6 @@ async fn empty_state_animation_preserves_header_cursor_and_footer() -> Result<()
222213
text(&before)
223214
)
224215
);
225-
// Editing, clearing, and resizing must never choose another phrase.
226-
let phrase_pos = after
227-
.content
228-
.iter()
229-
.position(|cell| cell.symbol() == "P")
230-
.expect("the phrase is visible above the composer");
231-
assert_eq!(after.content[phrase_pos].fg, crate::style::accent_color());
232-
233216
let short = Size::new(/*width*/ 120, /*height*/ 12);
234217
draw(&mut app, &mut tui, short)?;
235218
assert!(!has_blossom(&tui));
@@ -242,12 +225,6 @@ async fn empty_state_animation_preserves_header_cursor_and_footer() -> Result<()
242225
app.chat_widget.apply_external_edit(String::new());
243226
draw(&mut app, &mut tui, size)?;
244227
assert!(has_blossom(&tui));
245-
assert!(
246-
text(crate::custom_terminal::test_support::last_rendered_buffer(
247-
&tui.terminal
248-
))
249-
.contains("Pull up a prompt.")
250-
);
251228
assert_eq!(app.transcript_cells.len(), history_len);
252229
app.local_settings.tui.animations = false;
253230
draw(&mut app, &mut tui, size)?;
@@ -269,7 +246,7 @@ async fn empty_state_animation_preserves_header_cursor_and_footer() -> Result<()
269246
}
270247

271248
#[tokio::test]
272-
async fn submitting_a_draft_keeps_greeting_and_dismisses_logo_even_after_clear() -> Result<()> {
249+
async fn submitting_a_draft_dismisses_logo_even_after_clear() -> Result<()> {
273250
let (mut app, _events, _ops) = crate::app::tests::make_test_app_with_channels().await;
274251
app.local_settings.tui.animations = true;
275252
let size = Size::new(/*width*/ 120, /*height*/ 44);
@@ -282,20 +259,12 @@ async fn submitting_a_draft_keeps_greeting_and_dismisses_logo_even_after_clear()
282259
.start_fresh();
283260
draw(&mut app, &mut tui, size)?;
284261
assert!(has_blossom(&tui));
285-
let greeting = *app
286-
.chat_widget
287-
.empty_state_animation
288-
.borrow()
289-
.greeting
290-
.get()
291-
.expect("choose a greeting for the fresh thread");
292262
app.chat_widget
293263
.apply_external_edit("first prompt".to_string());
294264
draw(&mut app, &mut tui, size)?;
295265
let drafting = crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal);
296266
assert!(!has_blossom(&tui));
297267
assert!(text(drafting).contains("first prompt"));
298-
assert!(text(drafting).contains(greeting.phrase));
299268
app.chat_widget.apply_external_edit(String::new());
300269
draw(&mut app, &mut tui, size)?;
301270
assert!(has_blossom(&tui));
@@ -305,14 +274,9 @@ async fn submitting_a_draft_keeps_greeting_and_dismisses_logo_even_after_clear()
305274
.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
306275
draw(&mut app, &mut tui, size)?;
307276
assert!(!has_blossom(&tui));
308-
let submitted = crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal);
309-
assert_eq!(text(submitted).matches(greeting.phrase).count(), 1);
310-
// The header is also stable when it scrolls out and back into the viewport.
311277
let short = Size::new(/*width*/ 120, /*height*/ 8);
312278
draw(&mut app, &mut tui, short)?;
313279
draw(&mut app, &mut tui, size)?;
314-
let restored = crate::custom_terminal::test_support::last_rendered_buffer(&tui.terminal);
315-
assert!(text(restored).contains(greeting.phrase));
316280
assert!(!has_blossom(&tui));
317281
app.reset_transcript_state_after_clear();
318282
draw(&mut app, &mut tui, size)?;

‎codex-rs/tui/src/app/history_ui.rs‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,13 @@ impl App {
316316
&self,
317317
version: &'static str,
318318
) -> history_cell::SessionHeaderHistoryCell {
319-
let mut header = history_cell::SessionHeaderHistoryCell::new(
319+
history_cell::SessionHeaderHistoryCell::new(
320320
self.chat_widget.model_display_name().to_string(),
321321
self.chat_widget.current_reasoning_effort(),
322322
self.config.cwd.to_path_buf(),
323323
version,
324324
)
325-
.with_yolo_mode(history_cell::is_yolo_mode(&self.config));
326-
history_cell::set_session_greeting(
327-
&mut header,
328-
&self.chat_widget.empty_state_animation.borrow().greeting,
329-
);
330-
header
325+
.with_yolo_mode(history_cell::is_yolo_mode(&self.config))
331326
}
332327

333328
pub(super) fn clear_ui_header_lines(&self, width: u16) -> Vec<Line<'static>> {

‎codex-rs/tui/src/app/session_lifecycle.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ impl App {
11081108
ThreadAttachPresentation::Fresh | ThreadAttachPresentation::FreshWithDraft
11091109
) {
11101110
self.chat_widget.mark_fresh_task_for_sparkle(&started);
1111-
// FreshWithDraft inherits its provisional greeting and replay at the handoff.
1111+
// FreshWithDraft inherits its provisional replay at the handoff.
11121112
if matches!(presentation, ThreadAttachPresentation::Fresh) {
11131113
self.chat_widget
11141114
.empty_state_animation

‎codex-rs/tui/src/app/snapshots/codex_tui__app__owned_transcript__empty_state_animation_tests__fresh_thread_header.snap‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ enabled:
77
>_ OpenAI Codex (v0.0.0)
88
/tmp/project
99

10-
Pull up a prompt.
10+
1111

1212

1313

@@ -53,7 +53,7 @@ disabled:
5353
>_ OpenAI Codex (v0.0.0)
5454
/tmp/project
5555

56-
Pull up a prompt.
56+
5757

5858

5959

‎codex-rs/tui/src/app/tests/background_task_defaults_tests.rs‎

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,6 @@ async fn command_center_new_keeps_startup_draft_visible_through_handoff() -> Res
8686
app.chat_widget.composer_text_with_pending(),
8787
"draft during startup"
8888
);
89-
assert_eq!(
90-
app.chat_widget
91-
.empty_state_animation
92-
.borrow()
93-
.greeting
94-
.get()
95-
.unwrap()
96-
.phrase,
97-
"Pull up a prompt."
98-
);
9989

10090
while let Ok(event) = events.try_recv() {
10191
Box::pin(app.handle_event(&mut tui, &mut server, event)).await?;

‎codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__startup_frame_tests__startup_tip_in_transcript.snap‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
---
22
source: tui/src/app/tests/startup_frame_tests.rs
3-
assertion_line: 72
43
expression: "normalize_snapshot_paths(normalize_agent_center_snapshot(snapshots.join(\"\\n\\n\")))"
54
---
65
80 columns
76

87
>_ OpenAI Codex (v0.0.0)
98
/tmp/project
109

11-
Pull up a prompt.
12-
1310
• Conversation continues here.
1411

1512

@@ -20,6 +17,8 @@ expression: "normalize_snapshot_paths(normalize_agent_center_snapshot(snapshots.
2017

2118

2219

20+
21+
2322
› Ask Codex to do anything
2423

2524
GPT-5.6-Sol default · /tmp/project
@@ -30,8 +29,6 @@ expression: "normalize_snapshot_paths(normalize_agent_center_snapshot(snapshots.
3029
>_ OpenAI Codex (v0.0.0)
3130
/tmp/project
3231

33-
Pull up a prompt.
34-
3532
• Conversation continues here.
3633

3734

@@ -42,6 +39,8 @@ expression: "normalize_snapshot_paths(normalize_agent_center_snapshot(snapshots.
4239

4340

4441

42+
43+
4544
› Ask Codex to do anything
4645

4746
GPT-5.6-Sol default · /tmp/pr…

‎codex-rs/tui/src/app/tests/startup_frame_tests.rs‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,8 @@ async fn owned_startup_hides_tip_in_transcript() -> Result<()> {
2121
let mut app = crate::app::test_support::make_test_app().await;
2222
app.local_settings.tui.show_tooltips = true;
2323
app.local_settings.tui.animations = false;
24-
let greeting = Arc::new(std::sync::OnceLock::new());
25-
greeting
26-
.set(crate::empty_state_animation::Greeting {
27-
phrase: "Pull up a prompt.",
28-
})
29-
.unwrap();
3024
let session = test_thread_session(ThreadId::new(), app.config.cwd.to_path_buf());
31-
let mut session_info = new_session_info(
25+
let session_info = new_session_info(
3226
&app.config,
3327
&app.local_settings,
3428
&session.model,
@@ -38,7 +32,6 @@ async fn owned_startup_hides_tip_in_transcript() -> Result<()> {
3832
Some("Use /mcp to list configured MCP tools.".into()),
3933
/*auth_plan*/ None,
4034
);
41-
history_cell::set_session_greeting(&mut session_info, &greeting);
4235
app.transcript_cells = vec![
4336
Arc::new(session_info),
4437
Arc::new(AgentMessageCell::new(
@@ -80,9 +73,8 @@ async fn owned_startup_hides_tip_in_transcript() -> Result<()> {
8073
.map(ToString::to_string)
8174
.collect::<Vec<_>>()
8275
.join("\n");
83-
assert!(text.contains("Pull up a prompt."));
8476
assert!(text.contains("Use /mcp"));
85-
assert!(!text.contains("model:"));
77+
assert_eq!(text.contains("model:"), mode == HistoryRenderMode::Raw);
8678
assert!(!text.contains('╭'));
8779
}
8880
app.transcript_view.begin_search();

‎codex-rs/tui/src/chatwidget/constructor.rs‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ impl ChatWidget {
6464
};
6565

6666
let empty_state_animation = crate::empty_state_animation::EmptyStateAnimation::default();
67-
let mut header = Self::placeholder_session_header_cell(&config);
68-
history_cell::set_session_greeting(header.as_mut(), &empty_state_animation.greeting);
67+
let header = Self::placeholder_session_header_cell(&config);
6968
let active_cell = Some(header);
7069

7170
let current_cwd = Some(config.cwd.to_path_buf());

‎codex-rs/tui/src/chatwidget/session_flow.rs‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl ChatWidget {
201201
let model_for_header = self.current_model().to_string();
202202
if display == SessionConfiguredDisplay::Normal {
203203
let startup_tooltip_override = self.startup_tooltip_override.take();
204-
let mut session_info_cell = history_cell::new_session_info(
204+
let session_info_cell = history_cell::new_session_info(
205205
&self.config,
206206
&self.local_settings,
207207
&model_for_header,
@@ -211,10 +211,6 @@ impl ChatWidget {
211211
startup_tooltip_override,
212212
self.plan_type,
213213
);
214-
history_cell::set_session_greeting(
215-
&mut session_info_cell,
216-
&self.empty_state_animation.borrow().greeting,
217-
);
218214
self.apply_session_info_cell(session_info_cell);
219215
} else if self
220216
.transcript

‎codex-rs/tui/src/empty_state_animation.rs‎

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
//! Visible time pauses while hidden. Fresh conversations start settled and can replay on a click.
33
44
mod geometry;
5-
mod greetings;
65
mod lighting;
76
mod paths;
87
mod policy;
98
mod renderer;
109
mod sequence;
1110

12-
use std::sync::Arc;
1311
use std::sync::OnceLock;
1412
use std::time::Duration;
1513
use std::time::Instant;
@@ -24,7 +22,6 @@ use ratatui::style::Color;
2422

2523
use crate::motion::MotionMode;
2624
use crate::terminal_palette;
27-
pub(crate) use greetings::Greeting;
2825
use lighting::Lighting;
2926
pub(crate) use policy::Presentation;
3027
pub(crate) use policy::is_startup_cell;
@@ -45,9 +42,6 @@ pub(crate) enum ComposerState {
4542
#[derive(Default)]
4643
pub(crate) struct EmptyStateAnimation {
4744
eligible: bool,
48-
// Initialized once for fresh threads; never initialized for a resumed or forked thread.
49-
// Headers retain the selection after the temporary blossom is dismissed.
50-
pub(crate) greeting: Arc<OnceLock<Greeting>>,
5145
spin_elapsed: Duration,
5246
last_frame: Option<Instant>,
5347
fade_elapsed: Duration,
@@ -67,24 +61,19 @@ impl EmptyStateAnimation {
6761
pub(crate) fn start_fresh(&mut self) {
6862
self.cancel_replay();
6963
self.eligible = true;
70-
self.greeting.get_or_init(Greeting::choose);
7164
self.spin_elapsed = Duration::ZERO;
7265
self.last_frame = None;
7366
self.fade_elapsed = Duration::ZERO;
7467
self.static_mark = None;
7568
self.opacity = 1.0;
7669
}
7770

78-
/// Keep the provisional pose and phrase in headers already bound to the live thread.
71+
/// Keep the provisional pose when handing off to the live thread.
7972
pub(crate) fn continue_from(&mut self, source: &mut Self) {
8073
let mut previous = std::mem::take(source);
8174
if !previous.is_eligible() {
8275
previous.start_fresh();
8376
}
84-
if let Some(greeting) = previous.greeting.get() {
85-
let _ = self.greeting.set(*greeting);
86-
}
87-
previous.greeting = Arc::clone(&self.greeting);
8877
*self = previous;
8978
}
9079

0 commit comments

Comments
 (0)