mirror of
https://github.com/openai/codex.git
synced 2026-10-19 16:17:49 +00:00
Allow /archive while a turn is running (#50764)
## Why `/archive` was disabled during a running turn, preventing users from archiving the current session until the turn ended. ## What changed Enable `/archive` during a running turn and warn in the confirmation dialog that archiving will stop the current turn. Cancelling the dialog leaves the turn running. ## Testing Extend confirmation tests to cover both idle and running sessions, add a snapshot of the running-turn warning, and verify that cancellation leaves the task running without emitting archive events or operations. GitOrigin-RevId: c7c530aa671b5f04e5dc2a637e3d27a81d98d8bf
This commit is contained in:
committed by
copyberry
parent
cd7d9e128c
commit
dde5f8c5ae
@@ -238,7 +238,12 @@ impl ChatWidget {
|
||||
self.bottom_pane.show_selection_view(SelectionViewParams {
|
||||
title: Some("Archive this session?".to_string()),
|
||||
subtitle: Some(
|
||||
"Are you sure? This will archive the current session".to_string(),
|
||||
if self.bottom_pane.is_task_running() {
|
||||
"This will stop the current turn and archive the session."
|
||||
} else {
|
||||
"Are you sure? This will archive the current session"
|
||||
}
|
||||
.to_string(),
|
||||
),
|
||||
footer_hint: Some(standard_popup_hint_line()),
|
||||
items: vec![
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/slash_commands.rs
|
||||
assertion_line: 2937
|
||||
expression: popup
|
||||
---
|
||||
• Wo Archive this session?
|
||||
This will stop the current turn and archive the session.
|
||||
|
||||
› As
|
||||
› 1. No, don't archive Return to the current session
|
||||
GP 2. Yes, archive Archive this session now
|
||||
|
||||
enter select · esc back
|
||||
@@ -2755,24 +2755,19 @@ async fn slash_clear_is_disabled_while_task_running() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn slash_archive_is_disabled_while_task_running() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
async fn slash_archive_cancellation_keeps_task_running() {
|
||||
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.bottom_pane.set_task_running(/*running*/ true);
|
||||
|
||||
chat.dispatch_command(SlashCommand::Archive);
|
||||
|
||||
let event = rx.try_recv().expect("expected disabled command error");
|
||||
match event {
|
||||
AppEvent::InsertHistoryCell(cell) => {
|
||||
let rendered = lines_to_single_string(&cell.display_lines(/*width*/ 80));
|
||||
assert!(
|
||||
rendered.contains("'/archive' is disabled while a task is in progress."),
|
||||
"expected /archive task-running error, got {rendered:?}"
|
||||
);
|
||||
}
|
||||
other => panic!("expected InsertHistoryCell error, got {other:?}"),
|
||||
}
|
||||
assert!(rx.try_recv().is_err(), "expected no follow-up events");
|
||||
assert!(chat.bottom_pane.has_active_view());
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
|
||||
assert!(!chat.bottom_pane.has_active_view());
|
||||
assert!(chat.bottom_pane.is_task_running());
|
||||
assert_matches!(rx.try_recv(), Err(TryRecvError::Empty));
|
||||
assert_matches!(op_rx.try_recv(), Err(TryRecvError::Empty));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -2927,20 +2922,28 @@ async fn slash_import_opens_claude_code_import_picker() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn slash_archive_confirmation_requests_current_thread_archive() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
for running in [false, true] {
|
||||
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.bottom_pane.set_task_running(running);
|
||||
|
||||
chat.dispatch_command(SlashCommand::Archive);
|
||||
chat.dispatch_command(SlashCommand::Archive);
|
||||
|
||||
assert!(chat.bottom_pane.has_active_view());
|
||||
assert_matches!(rx.try_recv(), Err(TryRecvError::Empty));
|
||||
assert!(chat.bottom_pane.has_active_view());
|
||||
assert_matches!(rx.try_recv(), Err(TryRecvError::Empty));
|
||||
assert_matches!(op_rx.try_recv(), Err(TryRecvError::Empty));
|
||||
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
assert_chatwidget_snapshot!("slash_archive_confirmation_popup", popup);
|
||||
let popup = render_bottom_popup(&chat, /*width*/ 80);
|
||||
if running {
|
||||
assert_chatwidget_snapshot!("slash_archive_running_confirmation_popup", popup);
|
||||
} else {
|
||||
assert_chatwidget_snapshot!("slash_archive_confirmation_popup", popup);
|
||||
}
|
||||
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Down));
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Down));
|
||||
chat.handle_key_event(KeyEvent::from(KeyCode::Enter));
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::ArchiveCurrentThread));
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::ArchiveCurrentThread));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -241,7 +241,6 @@ impl SlashCommand {
|
||||
pub fn available_during_task(self) -> bool {
|
||||
match self {
|
||||
SlashCommand::New
|
||||
| SlashCommand::Archive
|
||||
| SlashCommand::Delete
|
||||
| SlashCommand::Fork
|
||||
| SlashCommand::Worktree
|
||||
@@ -264,6 +263,7 @@ impl SlashCommand {
|
||||
| SlashCommand::MemoryDrop
|
||||
| SlashCommand::MemoryUpdate => false,
|
||||
SlashCommand::Diff
|
||||
| SlashCommand::Archive
|
||||
| SlashCommand::Resume
|
||||
| SlashCommand::Model
|
||||
| SlashCommand::Daybreak
|
||||
|
||||
Reference in New Issue
Block a user