Avoid cloning thread data when rendering transcripts (#34194)

## What changed

Make `thread_to_transcript_cells` consume its `Thread` so transcript rendering can
move owned turn items, message content, IDs, and plan text into history cells
instead of cloning them.

GitOrigin-RevId: 80200ba8928a3ea0e91cbff8a13dd00e21432426
This commit is contained in:
Charlie Marsh
2026-07-19 16:46:58 +00:00
committed by copyberry
parent 0fb559f0f6
commit 9dc372fbaf
2 changed files with 21 additions and 19 deletions
+4 -4
View File
@@ -5844,7 +5844,7 @@ session_picker_view = "dense"
};
let rendered = thread_to_transcript_cells(
&thread,
thread,
RawReasoningVisibility::Visible,
/*codex_home*/ None,
)
@@ -5906,7 +5906,7 @@ session_picker_view = "dense"
};
let hidden = thread_to_transcript_cells(
&thread,
thread.clone(),
RawReasoningVisibility::Hidden,
/*codex_home*/ None,
)
@@ -5916,7 +5916,7 @@ session_picker_view = "dense"
.collect::<Vec<_>>()
.join("\n");
let visible = thread_to_transcript_cells(
&thread,
thread,
RawReasoningVisibility::Visible,
/*codex_home*/ None,
)
@@ -5976,7 +5976,7 @@ session_picker_view = "dense"
};
let rendered = thread_to_transcript_cells(
&thread,
thread,
RawReasoningVisibility::Visible,
/*codex_home*/ None,
)
+17 -15
View File
@@ -39,25 +39,25 @@ pub(crate) async fn load_session_transcript(
.await
.map_err(std::io::Error::other)?;
Ok(thread_to_transcript_cells(
&thread,
thread,
raw_reasoning_visibility,
codex_home,
))
}
pub(crate) fn thread_to_transcript_cells(
thread: &Thread,
thread: Thread,
raw_reasoning_visibility: RawReasoningVisibility,
codex_home: Option<&std::path::Path>,
) -> TranscriptCells {
let cwd = thread.cwd.as_path();
let cwd = thread.cwd;
let inline_visualization_context = codex_home.and_then(|codex_home| {
ThreadId::from_string(&thread.id)
.ok()
.and_then(|thread_id| InlineVisualizationContext::new(codex_home, thread_id))
});
let mut cells: TranscriptCells = Vec::new();
for item in thread.turns.iter().flat_map(|turn| turn.items.iter()) {
for item in thread.turns.into_iter().flat_map(|turn| turn.items) {
match item {
ThreadItem::UserMessage {
id,
@@ -76,11 +76,10 @@ pub(crate) fn thread_to_transcript_cells(
);
}
let item = UserMessageItem {
id: id.clone(),
client_id: client_id.clone(),
id,
client_id,
content: content
.iter()
.cloned()
.into_iter()
.map(codex_app_server_protocol::UserInput::into_core)
.collect(),
};
@@ -92,11 +91,11 @@ pub(crate) fn thread_to_transcript_cells(
}));
}
ThreadItem::AgentMessage { text, .. } => {
let parsed = parse_assistant_markdown(text, cwd);
let parsed = parse_assistant_markdown(&text, cwd.as_path());
if !parsed.visible_markdown.trim().is_empty() {
cells.push(Arc::new(AgentMarkdownCell::new_with_inline_visualizations(
parsed.visible_markdown,
cwd,
cwd.as_path(),
inline_visualization_context.clone(),
)));
}
@@ -104,8 +103,8 @@ pub(crate) fn thread_to_transcript_cells(
ThreadItem::Plan { text, .. } => {
if !text.trim().is_empty() {
cells.push(Arc::new(crate::history_cell::new_proposed_plan(
text.clone(),
cwd,
text,
cwd.as_path(),
)));
}
}
@@ -118,16 +117,19 @@ pub(crate) fn thread_to_transcript_cells(
{
("Reasoning".to_string(), content.join("\n\n"))
} else {
split_reasoning_summary_parts(summary)
split_reasoning_summary_parts(&summary)
};
if !text.trim().is_empty() {
cells.push(Arc::new(ReasoningSummaryCell::new(
header, text, cwd, /*transcript_only*/ false,
header,
text,
cwd.as_path(),
/*transcript_only*/ false,
)));
}
}
other => {
if let Some(cell) = fallback_transcript_cell(other) {
if let Some(cell) = fallback_transcript_cell(&other) {
cells.push(Arc::new(cell));
}
}