From 4c0ca09d696e03653beb073086fba0bac3b607ef Mon Sep 17 00:00:00 2001 From: Charles Cunningham Date: Wed, 18 Feb 2026 01:41:37 -0800 Subject: [PATCH] Rename compact callsite vars and document reinjection policy --- codex-rs/core/src/codex.rs | 10 +++++----- codex-rs/core/src/compact.rs | 29 ++++++++++++++------------- codex-rs/core/src/compact_remote.rs | 31 ++++++++++++----------------- 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index f624370d59..81df6149f6 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -4803,7 +4803,7 @@ async fn run_pre_turn_auto_compaction_if_needed( CodexErr::ContextWindowExceeded => { error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?CompactCallsite::PreTurnIncludingIncomingUserMessage, + compact_callsite = ?CompactCallsite::PreTurnIncludingIncomingUserMessage, incoming_items_tokens_estimate, auto_compact_limit, reason = "pre-turn compaction exceeded context window", @@ -4859,14 +4859,14 @@ fn is_projected_submission_over_auto_compact_limit( async fn run_auto_compact( sess: &Arc, turn_context: &Arc, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { let result = if should_use_remote_compact_task(&turn_context.provider) { run_inline_remote_auto_compact_task( Arc::clone(sess), Arc::clone(turn_context), - auto_compact_callsite, + compact_callsite, incoming_items, ) .await @@ -4874,7 +4874,7 @@ async fn run_auto_compact( run_inline_auto_compact_task( Arc::clone(sess), Arc::clone(turn_context), - auto_compact_callsite, + compact_callsite, incoming_items, ) .await @@ -4883,7 +4883,7 @@ async fn run_auto_compact( if let Err(err) = &result { error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, compact_error = %err, "auto compaction failed" ); diff --git a/codex-rs/core/src/compact.rs b/codex-rs/core/src/compact.rs index 95a79673ba..2c8ca1528b 100644 --- a/codex-rs/core/src/compact.rs +++ b/codex-rs/core/src/compact.rs @@ -53,6 +53,14 @@ pub(crate) enum CompactCallsite { MidTurnContinuation, } +// Canonical context reinjection policy for compacted replacement history: +// - `MidTurnContinuation` and `PreSamplingModelSwitch`: reinsert canonical initial context above +// the last real user message because compaction is rewriting in-flight history that the model +// will continue sampling from immediately. +// - `ManualCompact`: do not reinsert during compaction; `/compact` reseeds on the next user turn. +// - `PreTurn*`: do not reinsert into replacement history; `run_turn` persists canonical context +// directly above the incoming user message after compaction. + pub(crate) fn should_use_remote_compact_task(provider: &ModelProviderInfo) -> bool { provider.is_openai() } @@ -96,7 +104,7 @@ pub(crate) fn extract_latest_model_switch_update_from_items( pub(crate) async fn run_inline_auto_compact_task( sess: Arc, turn_context: Arc, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { let prompt = turn_context.compact_prompt().to_string(); @@ -106,14 +114,7 @@ pub(crate) async fn run_inline_auto_compact_task( text_elements: Vec::new(), }]; - run_compact_task_inner( - sess, - turn_context, - input, - auto_compact_callsite, - incoming_items, - ) - .await?; + run_compact_task_inner(sess, turn_context, input, compact_callsite, incoming_items).await?; Ok(()) } @@ -142,7 +143,7 @@ async fn run_compact_task_inner( sess: Arc, turn_context: Arc, input: Vec, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { let compaction_item = TurnItem::ContextCompaction(ContextCompactionItem::new()); @@ -240,7 +241,7 @@ async fn run_compact_task_inner( // messages intact. error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, "Context window exceeded while compacting; removing oldest history item. Error: {e}" ); history.remove_first_item(); @@ -251,7 +252,7 @@ async fn run_compact_task_inner( sess.set_total_tokens_full(turn_context.as_ref()).await; error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, compact_error = %e, "compaction failed after history truncation could not proceed" ); @@ -272,7 +273,7 @@ async fn run_compact_task_inner( } error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, retries, max_retries, compact_error = %e, @@ -294,7 +295,7 @@ async fn run_compact_task_inner( COMPACT_USER_MESSAGE_MAX_TOKENS, ); let mut new_history = process_compacted_history(compacted_history); - match auto_compact_callsite { + match compact_callsite { CompactCallsite::MidTurnContinuation | CompactCallsite::PreSamplingModelSwitch => { // Mid-turn and pre-sampling model-switch compaction continue the in-flight turn and // therefore must keep canonical context anchored above the latest real user turn. diff --git a/codex-rs/core/src/compact_remote.rs b/codex-rs/core/src/compact_remote.rs index 5d60703cef..92d11b7598 100644 --- a/codex-rs/core/src/compact_remote.rs +++ b/codex-rs/core/src/compact_remote.rs @@ -32,11 +32,10 @@ use tracing::info; pub(crate) async fn run_inline_remote_auto_compact_task( sess: Arc, turn_context: Arc, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { - run_remote_compact_task_inner(&sess, &turn_context, auto_compact_callsite, incoming_items) - .await?; + run_remote_compact_task_inner(&sess, &turn_context, compact_callsite, incoming_items).await?; Ok(()) } @@ -57,20 +56,16 @@ pub(crate) async fn run_remote_compact_task( async fn run_remote_compact_task_inner( sess: &Arc, turn_context: &Arc, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { - if let Err(err) = run_remote_compact_task_inner_impl( - sess, - turn_context, - auto_compact_callsite, - incoming_items, - ) - .await + if let Err(err) = + run_remote_compact_task_inner_impl(sess, turn_context, compact_callsite, incoming_items) + .await { error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, compact_error = %err, "remote compaction task failed" ); @@ -82,7 +77,7 @@ async fn run_remote_compact_task_inner( async fn run_remote_compact_task_inner_impl( sess: &Arc, turn_context: &Arc, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, incoming_items: Option>, ) -> CodexResult<()> { let compaction_item = TurnItem::ContextCompaction(ContextCompactionItem::new()); @@ -116,7 +111,7 @@ async fn run_remote_compact_task_inner_impl( if deleted_items > 0 { info!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, deleted_items, "trimmed history items before remote compaction" ); @@ -153,7 +148,7 @@ async fn run_remote_compact_task_inner_impl( build_compact_request_log_data(&prompt.input, &prompt.base_instructions.text); log_remote_compact_failure( turn_context, - auto_compact_callsite, + compact_callsite, &compact_request_log_data, total_usage_breakdown, &err, @@ -162,7 +157,7 @@ async fn run_remote_compact_task_inner_impl( }) .await?; new_history = process_compacted_history(new_history); - match auto_compact_callsite { + match compact_callsite { CompactCallsite::MidTurnContinuation | CompactCallsite::PreSamplingModelSwitch => { // Mid-turn and pre-sampling model-switch compaction continue the in-flight turn and // therefore must keep canonical context anchored above the latest real user turn. @@ -275,14 +270,14 @@ fn remove_incoming_echoes_from_compacted_history( fn log_remote_compact_failure( turn_context: &TurnContext, - auto_compact_callsite: CompactCallsite, + compact_callsite: CompactCallsite, log_data: &CompactRequestLogData, total_usage_breakdown: TotalTokenUsageBreakdown, err: &CodexErr, ) { error!( turn_id = %turn_context.sub_id, - auto_compact_callsite = ?auto_compact_callsite, + compact_callsite = ?compact_callsite, last_api_response_total_tokens = total_usage_breakdown.last_api_response_total_tokens, all_history_items_model_visible_bytes = total_usage_breakdown.all_history_items_model_visible_bytes, estimated_tokens_of_items_added_since_last_successful_api_response = total_usage_breakdown.estimated_tokens_of_items_added_since_last_successful_api_response,