Show file destinations in TUI change approvals (#39285)

## What changed

- Show a description and the destination paths affected by each file-change approval.
- Include both source and target paths for moves, format cross-platform paths for display, and show `unavailable` when change details are missing.
- Recover file changes from buffered events and thread snapshots so live and replayed approvals retain their destination details.

## Testing

- Add coverage for active and replayed approvals, moved and cross-platform paths, and the missing-destination fallback.

GitOrigin-RevId: 24f90b313fd8643f90cbead1504c788b140d7fed
This commit is contained in:
Eric Traut authored and copyberry committed 2026-08-18 21:43:22 +00:00
1 parent ba37d0c45b
commit e7f9fa9cd9
14 files changed
+411 -73

No files matched your search

@@ -1691,6 +1691,7 @@ async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot()
#[tokio::test]
async fn approval_modal_patch_snapshot() -> anyhow::Result<()> {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.config.cwd = test_path_buf("/tmp/project").abs();
chat.config
.permissions
.approval_policy
@@ -1709,7 +1710,7 @@ async fn approval_modal_patch_snapshot() -> anyhow::Result<()> {
turn_id: "turn-approve-patch".into(),
changes,
reason: Some("The model wants to apply changes".into()),
grant_root: Some(PathBuf::from("/tmp")),
grant_root: Some(test_path_buf("/tmp/project")),
};
handle_apply_patch_approval_request(&mut chat, "sub-approve-patch", ev);
@@ -1722,7 +1723,7 @@ async fn approval_modal_patch_snapshot() -> anyhow::Result<()> {
.expect("draw patch approval modal");
let contents = terminal.backend().vt100().screen().contents();
assert!(!contents.contains("$ apply_patch"));
assert_chatwidget_snapshot!("approval_modal_patch", contents);
assert_chatwidget_snapshot!("approval_modal_patch", normalize_snapshot_paths(contents));
Ok(())
}