[core] Fix empty-history inline summary replacement [ci changed_files]

Handle repeated inline compactions on turns that started from empty history by stripping leading compaction items after prefix calculation, and add regression coverage for the fresh-session case.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Cooper Gamble
2026-03-11 02:48:35 +00:00
co-authored by Codex
parent bdadb141f2
commit 9d20427fc2
2 changed files with 54 additions and 15 deletions
+15 -15
View File
@@ -5951,21 +5951,21 @@ fn build_server_side_compaction_replacement_history(
history_before_turn: &[ResponseItem],
current_history: &[ResponseItem],
) -> Vec<ResponseItem> {
let current_turn_items =
if let Some(current_turn_items) = current_history.strip_prefix(history_before_turn) {
current_turn_items
} else if matches!(
current_history.first(),
Some(ResponseItem::Compaction { .. })
) {
let first_non_compaction = current_history
.iter()
.position(|item| !matches!(item, ResponseItem::Compaction { .. }))
.unwrap_or(current_history.len());
&current_history[first_non_compaction..]
} else {
current_history
};
let current_turn_items = current_history
.strip_prefix(history_before_turn)
.unwrap_or(current_history);
let current_turn_items = if matches!(
current_turn_items.first(),
Some(ResponseItem::Compaction { .. })
) {
let first_non_compaction = current_turn_items
.iter()
.position(|item| !matches!(item, ResponseItem::Compaction { .. }))
.unwrap_or(current_turn_items.len());
&current_turn_items[first_non_compaction..]
} else {
current_turn_items
};
let mut replacement_history = vec![compaction_item];
replacement_history.extend(
current_turn_items
+39
View File
@@ -341,6 +341,45 @@ fn build_server_side_compaction_replacement_history_replaces_prior_same_turn_sum
);
}
#[test]
fn build_server_side_compaction_replacement_history_replaces_prior_summary_with_empty_history() {
let same_turn_snapshot = ghost_snapshot("ghost-during");
let history_before_turn = Vec::new();
let current_turn_user = user_message("current turn");
let current_turn_tool_output = ResponseItem::FunctionCallOutput {
call_id: "call-1".to_string(),
output: FunctionCallOutputPayload::from_text("tool result".to_string()),
};
let prior_compaction = ResponseItem::Compaction {
encrypted_content: "INLINE_SUMMARY_1".to_string(),
};
let new_compaction = ResponseItem::Compaction {
encrypted_content: "INLINE_SUMMARY_2".to_string(),
};
let current_history = vec![
prior_compaction,
current_turn_user.clone(),
current_turn_tool_output.clone(),
same_turn_snapshot.clone(),
];
let replacement_history = build_server_side_compaction_replacement_history(
new_compaction.clone(),
&history_before_turn,
&current_history,
);
assert_eq!(
replacement_history,
vec![
new_compaction,
current_turn_user,
current_turn_tool_output,
same_turn_snapshot,
]
);
}
fn make_mcp_tool(
server_name: &str,
tool_name: &str,