fix(tui): keep /copy aligned with rollback (#18739)

## Why

Fixes #18718.

After rewinding a thread, `/copy` could still copy the latest assistant
response from before the rewind. The transcript cells were rolled back,
but the copy source was a single `last_agent_markdown` cache that was
not synchronized with backtracking, so the visible conversation and
copied content could diverge.

## What changed

`ChatWidget` now keeps a bounded copy history for the most recent 32
assistant responses, keyed by the visible user-turn count. When local
rollback trims transcript cells, the copy cache is trimmed to the same
surviving user-turn count so `/copy` uses the latest visible assistant
response.

If the user rewinds past the retained copy window, `/copy` now reports:

```text
Cannot copy that response after rewinding. Only the most recent 32 responses are available to /copy.
```

The change also adds coverage for copying the latest surviving response
after rollback and for the over-limit rewind message.

## Verification

- Manually resumed a synthetic 35-turn session, rewound within the
retained window, and verified `/copy` copied the surviving response.
- Manually rewound past the retained window and verified `/copy` showed
the 32-response limit message.
- `cargo test -p codex-tui slash_copy`
- `just fix -p codex-tui`
- `cargo insta pending-snapshots`

Note: `cargo test -p codex-tui` currently fails on unrelated model
catalog and snapshot drift around the default model changing to
`gpt-5.4`; the focused `/copy` tests pass after fixing the new test
setup.
This commit is contained in:
Felipe Coury
2026-04-20 19:24:10 -03:00
committed by GitHub
parent 46e5814f77
commit cebe57b723
4 changed files with 162 additions and 7 deletions

View File

@@ -482,6 +482,8 @@ impl App {
if !trim_transcript_cells_drop_last_n_user_turns(&mut self.transcript_cells, num_turns) {
return false;
}
self.chat_widget
.truncate_agent_copy_history_to_user_turn_count(user_count(&self.transcript_cells));
self.sync_overlay_after_transcript_trim();
self.backtrack_render_pending = true;
true
@@ -503,6 +505,8 @@ impl App {
&mut self.transcript_cells,
pending.selection.nth_user_message,
) {
self.chat_widget
.truncate_agent_copy_history_to_user_turn_count(user_count(&self.transcript_cells));
self.sync_overlay_after_transcript_trim();
self.backtrack_render_pending = true;
}