From ae5c75dbfc1a1e802db7ea9e4231f71ae86507a1 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 10 Nov 2026 08:18:43 +0000 Subject: [PATCH] Discard opening prompts when side chat creation fails (#60558) ## Why A failed side chat's opening prompt and image attachments could be restored into the parent chat's draft when dismissing the failure. ## What changed Clear the pending opening message when sidebar chat creation fails, and stop restoring the opening message when side conversation creation returns an error. ## Testing Update the sidebar chooser test to verify that dismissing a failed creation preserves the parent draft and a subsequent prompt without restoring the failed prompt or its image attachment. GitOrigin-RevId: 1423786b2209e9441e0bc1504ffcf51e74ba7cde --- codex-rs/tui/src/app/side.rs | 2 +- codex-rs/tui/src/app/tests/key_chords.rs | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/codex-rs/tui/src/app/side.rs b/codex-rs/tui/src/app/side.rs index 755d7366fa..a97fdeabf9 100644 --- a/codex-rs/tui/src/app/side.rs +++ b/codex-rs/tui/src/app/side.rs @@ -884,6 +884,7 @@ impl App { }; tui.frame_requester().schedule_frame(); if let Err(message) = result { + pending.message = None; pending.state = sidebar::CreationState::Failed { message, cleanup: None, @@ -1032,7 +1033,6 @@ impl App { } } Err(err) => { - self.restore_side_user_message(user_message.take()); self.chat_widget .set_side_conversation_context_label(/*label*/ None); self.chat_widget.add_error_message(err); diff --git a/codex-rs/tui/src/app/tests/key_chords.rs b/codex-rs/tui/src/app/tests/key_chords.rs index 5c164638e8..7a623c9ce3 100644 --- a/codex-rs/tui/src/app/tests/key_chords.rs +++ b/codex-rs/tui/src/app/tests/key_chords.rs @@ -1421,7 +1421,7 @@ async fn sidebar_chooser_preserves_the_parent_draft_and_starts_a_side_chat() -> request, started: std::time::Instant::now(), }, - message: Some(first_prompt.clone()), + message: Some(first_prompt), }); app.finish_side_creation( &mut tui, @@ -1471,15 +1471,10 @@ prepared. super::side_frame(&mut app, &mut tui, ratatui::layout::Size::new(30, 8))? .contains("Open in sidebar") ); - assert_eq!( - app.chat_widget.composer_draft_snapshot().remote_image_urls, - first_prompt.remote_image_urls - ); - let draft = app.chat_widget.composer_text_with_pending(); - assert!( - draft.contains("first prompt") && draft.contains("second prompt"), - "{draft}" - ); + let draft = app.chat_widget.composer_draft_snapshot(); + assert!(draft.remote_image_urls.is_empty()); + insta::assert_snapshot!(draft.text, @"second prompt +parent draft!"); // A page fits a chat with a subtitle or two title-only chats. let pane = app.sidebar_mut(); for _ in 0..4 { @@ -1506,7 +1501,7 @@ prepared. } Box::pin(press(&mut app, &mut tui, &mut server, ctrl('c'))).await?; assert_eq!(app.chooser_focus(), None); - assert_eq!(app.chat_widget.composer_text_with_pending(), draft); + assert_eq!(app.chat_widget.composer_text_with_pending(), draft.text); tokio::time::resume(); server.shutdown().await?; Ok(())