mirror of
https://github.com/openai/codex.git
synced 2026-09-09 15:58:47 +00:00
Simplify prefix compaction history handling
This commit is contained in:
@@ -6832,11 +6832,9 @@ async fn apply_prefix_compact_candidate(
|
||||
.reference_context_item()
|
||||
.await
|
||||
.or(candidate.captured_reference_context_item);
|
||||
let mut new_history = compact::build_prefix_compacted_history(
|
||||
candidate.replacement_prefix,
|
||||
candidate.captured_context,
|
||||
retained_suffix,
|
||||
);
|
||||
let mut new_history = candidate.replacement_prefix;
|
||||
new_history.extend(candidate.captured_context);
|
||||
new_history.extend(retained_suffix);
|
||||
|
||||
new_history.extend(
|
||||
current_items
|
||||
|
||||
@@ -481,22 +481,6 @@ pub(crate) fn insert_initial_context_before_last_real_user_or_summary(
|
||||
compacted_history
|
||||
}
|
||||
|
||||
/// Builds prefix-compaction replacement history from a processed compacted prefix, the context
|
||||
/// captured when that prefix snapshot was taken, and the live retained suffix.
|
||||
///
|
||||
/// The prefix has already gone through the same retention filtering as classic remote compaction.
|
||||
/// The captured context is inserted immediately after the prefix so the untouched suffix remains
|
||||
/// under the same chronological context state that existed when the suffix began.
|
||||
pub(crate) fn build_prefix_compacted_history(
|
||||
mut processed_prefix: Vec<ResponseItem>,
|
||||
captured_context: Vec<ResponseItem>,
|
||||
retained_suffix: Vec<ResponseItem>,
|
||||
) -> Vec<ResponseItem> {
|
||||
processed_prefix.extend(captured_context);
|
||||
processed_prefix.extend(retained_suffix);
|
||||
processed_prefix
|
||||
}
|
||||
|
||||
pub(crate) fn build_compacted_history(
|
||||
initial_context: Vec<ResponseItem>,
|
||||
user_messages: &[String],
|
||||
|
||||
@@ -23,30 +23,6 @@ async fn process_compacted_history_with_test_session(
|
||||
(refreshed, initial_context)
|
||||
}
|
||||
|
||||
fn input_message(role: &str, text: &str) -> ResponseItem {
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: role.to_string(),
|
||||
content: vec![ContentItem::InputText {
|
||||
text: text.to_string(),
|
||||
}],
|
||||
end_turn: None,
|
||||
phase: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn output_message(text: &str) -> ResponseItem {
|
||||
ResponseItem::Message {
|
||||
id: None,
|
||||
role: "assistant".to_string(),
|
||||
content: vec![ContentItem::OutputText {
|
||||
text: text.to_string(),
|
||||
}],
|
||||
end_turn: None,
|
||||
phase: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remote_compact_task_supports_openai_provider() {
|
||||
let provider = ModelProviderInfo::create_openai_provider(/*base_url*/ None);
|
||||
@@ -621,65 +597,3 @@ fn insert_initial_context_before_last_real_user_or_summary_keeps_compaction_last
|
||||
];
|
||||
assert_eq!(refreshed, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_prefix_compacted_history_inserts_captured_context_after_prefix() {
|
||||
let prefix_user = input_message("user", "older user in compacted prefix");
|
||||
let captured_developer = input_message("developer", "captured permissions");
|
||||
let captured_user = input_message("user", "captured environment");
|
||||
let suffix_assistant = output_message("working through suffix");
|
||||
let suffix_user = input_message("user", "latest user in retained suffix");
|
||||
|
||||
let refreshed = build_prefix_compacted_history(
|
||||
vec![prefix_user.clone()],
|
||||
vec![captured_developer.clone(), captured_user.clone()],
|
||||
vec![suffix_assistant.clone(), suffix_user.clone()],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
refreshed,
|
||||
vec![
|
||||
prefix_user,
|
||||
captured_developer,
|
||||
captured_user,
|
||||
suffix_assistant,
|
||||
suffix_user,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_prefix_compacted_history_preserves_suffix_context_items() {
|
||||
let prefix_user = input_message("user", "older user in compacted prefix");
|
||||
let captured_context = input_message("developer", "captured permissions");
|
||||
let suffix_developer = input_message("developer", "<permissions instructions>\nnew sandbox");
|
||||
let suffix_user_context = input_message(
|
||||
"user",
|
||||
r#"<environment_context>
|
||||
<cwd>/repo</cwd>
|
||||
<shell>zsh</shell>
|
||||
</environment_context>"#,
|
||||
);
|
||||
let suffix_assistant = output_message("continuing after context change");
|
||||
|
||||
let refreshed = build_prefix_compacted_history(
|
||||
vec![prefix_user.clone()],
|
||||
vec![captured_context.clone()],
|
||||
vec![
|
||||
suffix_developer.clone(),
|
||||
suffix_user_context.clone(),
|
||||
suffix_assistant.clone(),
|
||||
],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
refreshed,
|
||||
vec![
|
||||
prefix_user,
|
||||
captured_context,
|
||||
suffix_developer,
|
||||
suffix_user_context,
|
||||
suffix_assistant,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,33 +156,6 @@ impl Respond for PrefixRaceCompactResponder {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ModeAwareCompactResponder {
|
||||
requests: StdArc<StdMutex<Vec<serde_json::Value>>>,
|
||||
}
|
||||
|
||||
impl Respond for ModeAwareCompactResponder {
|
||||
fn respond(&self, request: &wiremock::Request) -> ResponseTemplate {
|
||||
let body = request
|
||||
.body_json::<serde_json::Value>()
|
||||
.expect("compact request body should be JSON");
|
||||
let prefix_mode = body.get("mode").and_then(serde_json::Value::as_str) == Some("prefix");
|
||||
self.requests
|
||||
.lock()
|
||||
.expect("request lock poisoned")
|
||||
.push(body);
|
||||
|
||||
let summary = if prefix_mode {
|
||||
"PREFIX_SUMMARY"
|
||||
} else {
|
||||
"NORMAL_FALLBACK_SUMMARY"
|
||||
};
|
||||
ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "application/json")
|
||||
.set_body_json(json!({ "output": compacted_summary_only_output(summary) }))
|
||||
}
|
||||
}
|
||||
|
||||
fn remote_realtime_test_codex_builder(
|
||||
realtime_server: &responses::WebSocketTestServer,
|
||||
) -> TestCodexBuilder {
|
||||
@@ -1330,7 +1303,7 @@ async fn oversized_prefix_snapshot_skips_prefix_compact_request() -> Result<()>
|
||||
let compact_requests = StdArc::new(StdMutex::new(Vec::new()));
|
||||
Mock::given(method("POST"))
|
||||
.and(path_regex(".*/responses/compact$"))
|
||||
.respond_with(ModeAwareCompactResponder {
|
||||
.respond_with(PrefixRaceCompactResponder {
|
||||
requests: StdArc::clone(&compact_requests),
|
||||
})
|
||||
.up_to_n_times(1)
|
||||
@@ -1385,7 +1358,7 @@ async fn oversized_prefix_snapshot_skips_prefix_compact_request() -> Result<()>
|
||||
assert_eq!(requests.len(), 3);
|
||||
let third_request_body = requests[2].body_json().to_string();
|
||||
assert!(third_request_body.contains("NORMAL_FALLBACK_SUMMARY"));
|
||||
assert!(!third_request_body.contains("PREFIX_SUMMARY"));
|
||||
assert!(!third_request_body.contains("PREFIX_STALE_SUMMARY"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user