mirror of
https://github.com/openai/codex.git
synced 2026-05-04 11:26:33 +00:00
#### Summary - Emit a “Proposed Command” history cell when an ExecApprovalRequest arrives (parity with proposed patches). - Simplify the approval dialog: show only the reason/instructions; move the command preview into history. - Make approval/abort decision history concise: - Single line snippet; if multiline, show first line + " ...". - Truncate to 80 graphemes with ellipsis for very long commands. #### Details - History - Add `new_proposed_command` to render a header and indented command preview. - Use shared `prefix_lines` helper for first/subsequent line prefixes. - Approval UI - `UserApprovalWidget` no longer renders the command in the modal; shows optional `reason` text only. - Decision history renders an inline, dimmed snippet per rules above. - Tests (snapshot-based) - Proposed/decision flow for short command. - Proposed multi-line + aborted decision snippet with “ ...”. - Very long one-line command -> truncated snippet with “…”. - Updated existing exec approval snapshots and test reasons. <img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 57 35 AM" src="https://github.com/user-attachments/assets/9ed4c316-9daf-4ac1-80ff-7ae1f481dd10" /> after approving: <img width="1053" height="704" alt="Screenshot 2025-09-03 at 11 58 18 AM" src="https://github.com/user-attachments/assets/a44e243f-eb9d-42ea-87f4-171b3fb481e7" /> rejection: <img width="1053" height="207" alt="Screenshot 2025-09-03 at 11 58 45 AM" src="https://github.com/user-attachments/assets/a022664b-ae0e-4b70-a388-509208707934" /> big command: https://github.com/user-attachments/assets/2dd976e5-799f-4af7-9682-a046e66cc494
60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use ratatui::text::Line;
|
|
use ratatui::text::Span;
|
|
|
|
/// Clone a borrowed ratatui `Line` into an owned `'static` line.
|
|
pub fn line_to_static(line: &Line<'_>) -> Line<'static> {
|
|
Line {
|
|
style: line.style,
|
|
alignment: line.alignment,
|
|
spans: line
|
|
.spans
|
|
.iter()
|
|
.map(|s| Span {
|
|
style: s.style,
|
|
content: std::borrow::Cow::Owned(s.content.to_string()),
|
|
})
|
|
.collect(),
|
|
}
|
|
}
|
|
|
|
/// Append owned copies of borrowed lines to `out`.
|
|
pub fn push_owned_lines<'a>(src: &[Line<'a>], out: &mut Vec<Line<'static>>) {
|
|
for l in src {
|
|
out.push(line_to_static(l));
|
|
}
|
|
}
|
|
|
|
/// Consider a line blank if it has no spans or only spans whose contents are
|
|
/// empty or consist solely of spaces (no tabs/newlines).
|
|
pub fn is_blank_line_spaces_only(line: &Line<'_>) -> bool {
|
|
if line.spans.is_empty() {
|
|
return true;
|
|
}
|
|
line.spans
|
|
.iter()
|
|
.all(|s| s.content.is_empty() || s.content.chars().all(|c| c == ' '))
|
|
}
|
|
|
|
/// Prefix each line with `initial_prefix` for the first line and
|
|
/// `subsequent_prefix` for following lines. Returns a new Vec of owned lines.
|
|
pub fn prefix_lines(
|
|
lines: Vec<Line<'static>>,
|
|
initial_prefix: Span<'static>,
|
|
subsequent_prefix: Span<'static>,
|
|
) -> Vec<Line<'static>> {
|
|
lines
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(|(i, l)| {
|
|
let mut spans = Vec::with_capacity(l.spans.len() + 1);
|
|
spans.push(if i == 0 {
|
|
initial_prefix.clone()
|
|
} else {
|
|
subsequent_prefix.clone()
|
|
});
|
|
spans.extend(l.spans);
|
|
Line::from(spans)
|
|
})
|
|
.collect()
|
|
}
|