mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
## What changed Render command, permission, patch, and MCP elicitation approval headers with `HyperlinkText`, which annotates web URLs and preserves their full destinations across wrapping and clipping. ## Testing Add a regression test covering wrapped URL destinations in all four header types, plus a snapshot of the wrapped command approval header. GitOrigin-RevId: 7f6b79484c9297cd03514da2d6805b0d239fee63
74 lines
2.3 KiB
Rust
74 lines
2.3 KiB
Rust
//! Render file-change approval descriptions and cross-platform destinations.
|
|
|
|
use super::approval_overlay::ApplyPatchApprovalRequest;
|
|
use crate::diff_model::FileChange;
|
|
use crate::render::renderable::Renderable;
|
|
use crate::terminal_hyperlinks::HyperlinkText;
|
|
use codex_utils_path_uri::LegacyAppPathString;
|
|
use ratatui::style::Stylize;
|
|
use ratatui::text::Line;
|
|
|
|
pub(super) fn build_header(request: &ApplyPatchApprovalRequest) -> Box<dyn Renderable> {
|
|
let mut header = Vec::new();
|
|
if let Some(thread_label) = &request.thread_label {
|
|
header.push(Line::from(vec![
|
|
"Thread: ".into(),
|
|
thread_label.clone().bold(),
|
|
]));
|
|
}
|
|
|
|
if !header.is_empty() {
|
|
header.push(Line::from(""));
|
|
}
|
|
|
|
let description = request
|
|
.reason
|
|
.as_deref()
|
|
.filter(|reason| !reason.is_empty())
|
|
.unwrap_or("Apply proposed file edits");
|
|
header.push(Line::from_iter([
|
|
"Description: ".into(),
|
|
description.to_string().italic(),
|
|
]));
|
|
|
|
let mut destinations: Vec<_> = request
|
|
.changes
|
|
.iter()
|
|
.flat_map(|(path, change)| {
|
|
let move_destination = match change {
|
|
FileChange::Update {
|
|
move_path: Some(move_path),
|
|
..
|
|
} => Some(move_path),
|
|
FileChange::Add { .. }
|
|
| FileChange::Delete { .. }
|
|
| FileChange::Update {
|
|
move_path: None, ..
|
|
} => None,
|
|
};
|
|
std::iter::once(path).chain(move_destination)
|
|
})
|
|
.map(|path| {
|
|
LegacyAppPathString::from_path(path)
|
|
.to_inferred_path_uri()
|
|
.map(|path| path.inferred_native_path_string())
|
|
.unwrap_or_else(|| request.cwd.join(path).display().to_string())
|
|
})
|
|
.collect();
|
|
destinations.sort();
|
|
destinations.dedup();
|
|
if destinations.is_empty() {
|
|
header.push(Line::from(vec![
|
|
"Destination: ".into(),
|
|
"unavailable".bold(),
|
|
]));
|
|
}
|
|
for destination in destinations {
|
|
header.push(Line::from_iter([
|
|
"Destination: ".into(),
|
|
destination.bold(),
|
|
]));
|
|
}
|
|
Box::new(HyperlinkText::new(header))
|
|
}
|