rollback cache reset

This commit is contained in:
won
2026-02-23 14:18:43 -08:00
parent c0ea9479c7
commit 09f68b4e0b
2 changed files with 42 additions and 0 deletions

View File

@@ -4284,6 +4284,10 @@ impl ChatWidget {
EventMsg::CollabResumeBegin(ev) => self.on_collab_event(multi_agents::resume_begin(ev)),
EventMsg::CollabResumeEnd(ev) => self.on_collab_event(multi_agents::resume_end(ev)),
EventMsg::ThreadRolledBack(rollback) => {
// Conservatively clear `/copy` state on rollback. The app layer trims visible
// transcript cells, but we do not maintain rollback-aware raw-markdown history yet,
// so keeping the previous cache can return content that was just removed.
self.last_copyable_output = None;
if from_replay {
self.app_event_tx.send(AppEvent::ApplyThreadRollback {
num_turns: rollback.num_turns,

View File

@@ -4577,6 +4577,44 @@ async fn slash_copy_uses_legacy_agent_message_item_when_turn_complete_last_messa
);
}
#[tokio::test]
async fn slash_copy_does_not_return_stale_output_after_thread_rollback() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;
let copied = install_clipboard_spy(&mut chat);
chat.handle_codex_event(Event {
id: "turn-1".into(),
msg: EventMsg::TurnComplete(TurnCompleteEvent {
turn_id: "turn-1".to_string(),
last_agent_message: Some("Reply that will be rolled back".to_string()),
}),
});
let _ = drain_insert_history(&mut rx);
chat.handle_codex_event(Event {
id: "rollback-1".into(),
msg: EventMsg::ThreadRolledBack(ThreadRolledBackEvent { num_turns: 1 }),
});
let _ = drain_insert_history(&mut rx);
chat.dispatch_command(SlashCommand::Copy);
assert!(
copied
.lock()
.expect("clipboard spy mutex poisoned")
.is_empty(),
"did not expect stale clipboard writes after rollback"
);
let cells = drain_insert_history(&mut rx);
assert_eq!(cells.len(), 1, "expected one info message");
let rendered = lines_to_single_string(&cells[0]);
assert!(
rendered.contains("No completed Codex output available to copy yet."),
"expected rollback-cleared copy state message, got {rendered:?}"
);
}
#[tokio::test]
async fn slash_exit_requests_exit() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;