From da7ee5ce30154c1579b9239f7506a3e646f7f4f0 Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Fri, 30 Jan 2026 15:26:06 -0800 Subject: [PATCH] address --- codex-rs/core/src/rollout/truncation.rs | 50 ++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/codex-rs/core/src/rollout/truncation.rs b/codex-rs/core/src/rollout/truncation.rs index 58b5e19f89..500d5e1695 100644 --- a/codex-rs/core/src/rollout/truncation.rs +++ b/codex-rs/core/src/rollout/truncation.rs @@ -185,16 +185,19 @@ pub(crate) fn truncate_rollout_drop_last_n_user_turns( } let user_turns = effective_user_turns(items); - let Some(first_turn) = user_turns.first() else { + let Some(_) = user_turns.first() else { return items.to_vec(); }; let n_from_end = usize::try_from(num_turns).unwrap_or(usize::MAX); - let cut_idx = if n_from_end >= user_turns.len() { - first_turn.source_index - } else { - user_turns[user_turns.len().saturating_sub(n_from_end)].source_index - }; + if n_from_end >= user_turns.len() { + let Some(first_user_idx) = user_message_positions_in_rollout(items).first().copied() else { + return items.to_vec(); + }; + return items[..first_user_idx].to_vec(); + } + + let cut_idx = user_turns[user_turns.len().saturating_sub(n_from_end)].source_index; items[..cut_idx].to_vec() } @@ -246,6 +249,17 @@ mod tests { } } + fn system_msg(text: &str) -> ResponseItem { + ResponseItem::Message { + id: None, + role: "system".to_string(), + content: vec![ContentItem::OutputText { + text: text.to_string(), + }], + end_turn: None, + } + } + fn user_input_msg(text: &str) -> ResponseItem { ResponseItem::Message { id: None, @@ -372,6 +386,30 @@ mod tests { assert_eq!(indices, vec![2, 2, 3]); } + #[test] + fn truncate_rollout_drop_last_n_user_turns_oversize_clears_user_history() { + let summary = format!("{SUMMARY_PREFIX}\nsummary"); + let system = system_msg("system"); + let rollout_items = vec![ + RolloutItem::ResponseItem(system.clone()), + RolloutItem::ResponseItem(user_input_msg("u1")), + RolloutItem::ResponseItem(assistant_msg("a1")), + RolloutItem::ResponseItem(user_input_msg("u2")), + RolloutItem::ResponseItem(assistant_msg("a2")), + RolloutItem::Compacted(CompactedItem { + message: summary, + replacement_history: None, + }), + ]; + + let truncated = truncate_rollout_drop_last_n_user_turns(&rollout_items, 99); + let expected = vec![RolloutItem::ResponseItem(system)]; + assert_eq!( + serde_json::to_value(&truncated).unwrap(), + serde_json::to_value(&expected).unwrap() + ); + } + #[test] fn effective_user_turns_skip_prior_compaction_summaries() { let summary_one = format!("{SUMMARY_PREFIX}\nsummary one");