Refactor remote compaction incoming-item dedup

This commit is contained in:
Charles Cunningham
2026-02-17 23:12:56 -08:00
parent 868019da9b
commit 583dee056d

View File

@@ -189,39 +189,7 @@ async fn run_remote_compact_task_inner_impl(
.filter(|item| should_keep_compacted_history_item(item))
.cloned()
.collect();
for incoming_item in incoming_history_items {
if let Some(index) =
new_history
.iter()
.rposition(|candidate| match (candidate, &incoming_item) {
(
ResponseItem::Message {
role: candidate_role,
content: candidate_content,
..
},
ResponseItem::Message {
role: incoming_role,
content: incoming_content,
..
},
) => {
candidate_role == incoming_role && candidate_content == incoming_content
}
(
ResponseItem::Compaction {
encrypted_content: candidate_content,
},
ResponseItem::Compaction {
encrypted_content: incoming_content,
},
) => candidate_content == incoming_content,
_ => candidate == &incoming_item,
})
{
new_history.remove(index);
}
}
remove_incoming_echoes_from_compacted_history(&mut new_history, &incoming_history_items);
}
// Reattach stripped model-switch updates only for compaction paths that do not carry
// incoming turn items. Pre-turn compaction appends turn context and user input after
@@ -272,6 +240,51 @@ fn build_compact_request_log_data(
}
}
/// Remote compaction may echo incoming items in `new_history`. Because incoming items are
/// appended after compaction at the caller, remove one semantic duplicate for each incoming item
/// so turn-context/user entries do not appear twice.
fn remove_incoming_echoes_from_compacted_history(
new_history: &mut Vec<ResponseItem>,
incoming_history_items: &[ResponseItem],
) {
for incoming_item in incoming_history_items {
if let Some(index) = new_history.iter().rposition(|candidate| {
response_items_match_for_compaction_merge(candidate, incoming_item)
}) {
new_history.remove(index);
}
}
}
fn response_items_match_for_compaction_merge(
candidate: &ResponseItem,
incoming_item: &ResponseItem,
) -> bool {
match (candidate, incoming_item) {
(
ResponseItem::Message {
role: candidate_role,
content: candidate_content,
..
},
ResponseItem::Message {
role: incoming_role,
content: incoming_content,
..
},
) => candidate_role == incoming_role && candidate_content == incoming_content,
(
ResponseItem::Compaction {
encrypted_content: candidate_content,
},
ResponseItem::Compaction {
encrypted_content: incoming_content,
},
) => candidate_content == incoming_content,
_ => candidate == incoming_item,
}
}
fn log_remote_compact_failure(
turn_context: &TurnContext,
auto_compact_callsite: AutoCompactCallsite,