mirror of
https://github.com/openai/codex.git
synced 2026-06-01 19:02:59 +00:00
fix(tui): persist ctrl-c draft via app event (#21397)
## Why The main branch started failing after #21351 merged because the merge commit kept calling `AppCommand::add_to_history` from `BottomPane::clear_composer_for_ctrl_c`, but main had already removed that helper as part of the history persistence refactor. The PR head passed because it was based on an older main commit where the helper still existed. This restores the Ctrl+C draft-stashing behavior using the current app-event path instead of the removed command helper. ## What Changed - Store the active `ThreadId` in `BottomPane` when history metadata is provided. - Emit `AppEvent::AppendMessageHistoryEntry` for Ctrl+C-cleared drafts. - Update the slash-clear regression test to assert the current history event shape. ## How to Test Targeted tests: - `cargo test -p codex-tui slash_clear_after_ctrl_c_keeps_stashed_draft_recallable` Broader local checks: - `just fix -p codex-tui` - `just argument-comment-lint -p codex-tui` - `git diff --check origin/main...HEAD` - `cargo test -p codex-tui` reached completion; the fixed test passed, and the only local failures were `status::tests::status_permissions_full_disk_managed_*`, blocked by this machine config rejecting `DangerFullAccess` via `/etc/codex/requirements.toml`.
This commit is contained in:
@@ -17,7 +17,6 @@ use std::collections::VecDeque;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::app::app_server_requests::ResolvedAppServerRequest;
|
||||
use crate::app_command::AppCommand;
|
||||
use crate::app_event::AppEvent;
|
||||
use crate::app_event::ConnectorsSnapshot;
|
||||
use crate::app_event_sender::AppEventSender;
|
||||
@@ -209,6 +208,7 @@ pub(crate) struct BottomPane {
|
||||
|
||||
app_event_tx: AppEventSender,
|
||||
frame_requester: FrameRequester,
|
||||
thread_id: Option<ThreadId>,
|
||||
|
||||
has_input_focus: bool,
|
||||
enhanced_keys_supported: bool,
|
||||
@@ -274,6 +274,7 @@ impl BottomPane {
|
||||
last_composer_activity_at: None,
|
||||
app_event_tx,
|
||||
frame_requester,
|
||||
thread_id: None,
|
||||
has_input_focus,
|
||||
enhanced_keys_supported,
|
||||
disable_paste_burst,
|
||||
@@ -780,8 +781,14 @@ impl BottomPane {
|
||||
|
||||
pub(crate) fn clear_composer_for_ctrl_c(&mut self) {
|
||||
if let Some(text) = self.composer.clear_for_ctrl_c() {
|
||||
self.app_event_tx
|
||||
.send(AppEvent::CodexOp(AppCommand::add_to_history(text)));
|
||||
if let Some(thread_id) = self.thread_id {
|
||||
self.app_event_tx
|
||||
.send(AppEvent::AppendMessageHistoryEntry { thread_id, text });
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"failed to append Ctrl+C-cleared draft to history: no active thread id"
|
||||
);
|
||||
}
|
||||
}
|
||||
self.request_redraw();
|
||||
}
|
||||
@@ -1438,6 +1445,7 @@ impl BottomPane {
|
||||
log_id: u64,
|
||||
entry_count: usize,
|
||||
) {
|
||||
self.thread_id = Some(thread_id);
|
||||
self.composer
|
||||
.set_history_metadata(thread_id, log_id, entry_count);
|
||||
}
|
||||
|
||||
@@ -1584,7 +1584,13 @@ async fn slash_clear_requests_ui_clear_when_idle() {
|
||||
#[tokio::test]
|
||||
async fn slash_clear_after_ctrl_c_keeps_stashed_draft_recallable() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
let thread_id = ThreadId::new();
|
||||
chat.thread_id = Some(thread_id);
|
||||
chat.bottom_pane
|
||||
.set_history_metadata(thread_id, /*log_id*/ 1, /*entry_count*/ 0);
|
||||
|
||||
submit_composer_text(&mut chat, "ok");
|
||||
assert_eq!(next_add_to_history_event(&mut rx), "ok");
|
||||
|
||||
let stashed_draft = "explain why history recall lost this draft";
|
||||
|
||||
@@ -1592,10 +1598,7 @@ async fn slash_clear_after_ctrl_c_keeps_stashed_draft_recallable() {
|
||||
.set_composer_text(stashed_draft.to_string(), Vec::new(), Vec::new());
|
||||
chat.handle_key_event(KeyEvent::new(KeyCode::Char('c'), KeyModifiers::CONTROL));
|
||||
assert_eq!(chat.bottom_pane.composer_text(), "");
|
||||
assert_matches!(
|
||||
rx.try_recv(),
|
||||
Ok(AppEvent::CodexOp(Op::AddToHistory { text })) if text == stashed_draft
|
||||
);
|
||||
assert_eq!(next_add_to_history_event(&mut rx), stashed_draft);
|
||||
|
||||
chat.bottom_pane
|
||||
.set_composer_text("/clear".to_string(), Vec::new(), Vec::new());
|
||||
|
||||
Reference in New Issue
Block a user