mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +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
66 lines
2.6 KiB
Rust
66 lines
2.6 KiB
Rust
//! Attach transparent page-boundary details to a freshly rebuilt activity group.
|
|
|
|
use crate::exec_cell::ExecCell;
|
|
use crate::history_cell::ComputerActivityCell;
|
|
use crate::history_cell::HistoryCell;
|
|
use crate::history_cell::ReasoningSummaryCell;
|
|
use std::sync::Arc;
|
|
|
|
#[allow(dead_code, reason = "Used by later layers of the TUI refresh stack.")]
|
|
pub(crate) fn is_hidden_activity_detail(cell: &Arc<dyn HistoryCell>) -> bool {
|
|
cell.as_any()
|
|
.downcast_ref::<ReasoningSummaryCell>()
|
|
.is_some_and(ReasoningSummaryCell::is_transcript_only)
|
|
}
|
|
|
|
/// Fold standalone reasoning using exact persisted identities from one turn.
|
|
///
|
|
/// An older page can arrive after the final reasoning page even with no newer group or live tail.
|
|
/// Rebuild only known completed calls and share their immutable details; never infer adjacency
|
|
/// from identical reasoning text or attach a detail from the next turn.
|
|
#[allow(dead_code, reason = "Used by later layers of the TUI refresh stack.")]
|
|
pub(crate) fn fold_trailing_activity_details(
|
|
older: &Arc<dyn HistoryCell>,
|
|
details: &[Arc<dyn HistoryCell>],
|
|
turns: &[codex_app_server_protocol::Turn],
|
|
) -> Option<Arc<dyn HistoryCell>> {
|
|
let (mut ids, retained) =
|
|
if let Some(group) = older.as_any().downcast_ref::<ComputerActivityCell>() {
|
|
(group.call_ids().collect::<Vec<_>>(), &group.group.details)
|
|
} else {
|
|
let group = older.as_any().downcast_ref::<ExecCell>()?;
|
|
if !group.is_exploring_cell() || group.should_flush() {
|
|
return None;
|
|
}
|
|
(
|
|
group
|
|
.iter_calls()
|
|
.map(|call| call.call_id.as_str())
|
|
.collect::<Vec<_>>(),
|
|
&group.group.details,
|
|
)
|
|
};
|
|
let count = ids.len();
|
|
for detail in details {
|
|
let detail = detail.as_any().downcast_ref::<ReasoningSummaryCell>()?;
|
|
if !detail.is_transcript_only() {
|
|
return None;
|
|
}
|
|
ids.push(detail.source_item_id()?);
|
|
}
|
|
let items = super::computer_groups::adjacent_activity_items(&ids, turns)?;
|
|
let mut retained = retained.clone();
|
|
for detail in details {
|
|
retained.push(count, Arc::clone(detail));
|
|
}
|
|
if older.as_any().is::<ComputerActivityCell>() {
|
|
let mut group = super::computer_groups::completed_group(items)?;
|
|
group.group.details = retained;
|
|
Some(Arc::new(group))
|
|
} else {
|
|
let mut group = super::exploration_groups::completed_group(items)?;
|
|
group.group.details = retained;
|
|
Some(Arc::new(group))
|
|
}
|
|
}
|