mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
## Why Persisted transcripts rendered tool calls individually and displayed reasoning differently from live replay. Enabling raw reasoning also replaced the summary instead of retaining it. ## What changed - Group computer activity and compatible exploration commands across intervening reasoning, retaining details for the expanded transcript. Respect visible content, command failure boundaries, and turn boundaries. - Separate paginated history at every turn boundary before filtering hidden items, while adding completion metadata only for successful turns. - Keep persisted reasoning out of the compact display, preserve hyperlinks in detailed rendering, and append enabled raw reasoning to the summary. Preserve standalone reasoning Markdown in transcript exports. - Add helpers to rejoin activity groups and attach reasoning across page boundaries using persisted item identities and turn adjacency. ## Testing Add regression coverage for reasoning replay parity, computer groups split across history pages, turn boundaries, and grouped terminal input. Update export and raw-reasoning tests to verify retained summaries and Markdown. GitOrigin-RevId: a716db571440f891cc2c6894ae93fbe0e149aed4
76 lines
3.0 KiB
Rust
76 lines
3.0 KiB
Rust
//! Expanded command history with source-backed selection and chronological activity details.
|
|
//! Raw history omits transcript-only reasoning while retaining full command output.
|
|
|
|
use super::model::ExecCell;
|
|
use crate::exec_command::strip_bash_lc_and_escape;
|
|
use crate::history_cell::HistoryRenderMode;
|
|
use crate::render::highlight::highlight_bash_to_lines;
|
|
use crate::terminal_hyperlinks::HyperlinkLine;
|
|
use crate::terminal_hyperlinks::adaptive_wrap_hyperlink_lines;
|
|
use crate::terminal_hyperlinks::plain_hyperlink_lines;
|
|
use crate::wrapping::RtOptions;
|
|
use codex_ansi_escape::ansi_escape_line;
|
|
use codex_utils_elapsed::format_duration;
|
|
use ratatui::prelude::*;
|
|
|
|
impl ExecCell {
|
|
pub(super) fn detailed_hyperlink_lines(
|
|
&self,
|
|
width: u16,
|
|
mode: HistoryRenderMode,
|
|
) -> Vec<HyperlinkLine> {
|
|
let mut lines: Vec<HyperlinkLine> = vec![];
|
|
for (i, call) in self.iter_calls().enumerate() {
|
|
if i > 0 {
|
|
lines.push("".into());
|
|
}
|
|
let script = strip_bash_lc_and_escape(&call.command);
|
|
let highlighted_script = highlight_bash_to_lines(&script);
|
|
let cmd_display = adaptive_wrap_hyperlink_lines(
|
|
&plain_hyperlink_lines(highlighted_script),
|
|
RtOptions::new(width as usize)
|
|
.initial_indent("$ ".magenta().into())
|
|
.subsequent_indent(" ".into()),
|
|
);
|
|
lines.extend(cmd_display);
|
|
|
|
if let Some(output) = call.output.as_ref() {
|
|
if !call.is_unified_exec_interaction() {
|
|
let wrap_width = width.max(/*other*/ 1) as usize;
|
|
let wrap_opts = RtOptions::new(wrap_width);
|
|
for unwrapped in output
|
|
.transcript_lines()
|
|
.map(|line| ansi_escape_line(line.as_ref()))
|
|
{
|
|
lines.extend(adaptive_wrap_hyperlink_lines(
|
|
&[unwrapped.into()],
|
|
wrap_opts.clone(),
|
|
));
|
|
}
|
|
}
|
|
if call.duration.is_some() || output.exit_code != 0 {
|
|
let mut result: Line = if output.exit_code == 0 {
|
|
Line::from("✓".green().bold())
|
|
} else {
|
|
Line::from(vec![
|
|
"✗".red().bold(),
|
|
format!(" ({})", output.exit_code).into(),
|
|
])
|
|
};
|
|
if let Some(duration) = call.duration {
|
|
let duration = format_duration(duration);
|
|
result.push_span(format!(" • {duration}").dim());
|
|
}
|
|
lines.push(result.into());
|
|
}
|
|
}
|
|
lines.extend(self.group.details.lines_after(i + 1, width, mode));
|
|
}
|
|
lines
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "transcript_tests.rs"]
|
|
mod tests;
|