diff --git a/codex-rs/core/src/compact.rs b/codex-rs/core/src/compact.rs index 9806d34d1e..4056deb4e2 100644 --- a/codex-rs/core/src/compact.rs +++ b/codex-rs/core/src/compact.rs @@ -88,7 +88,7 @@ pub(crate) fn extract_trailing_model_switch_update_for_compaction_request( Some(model_switch_item) } -fn extract_latest_model_switch_update_from_items( +pub(crate) fn extract_latest_model_switch_update_from_items( items: &mut Vec, ) -> Option { let model_switch_index = items diff --git a/codex-rs/core/src/compact_remote.rs b/codex-rs/core/src/compact_remote.rs index b338686ea0..4768abe0d6 100644 --- a/codex-rs/core/src/compact_remote.rs +++ b/codex-rs/core/src/compact_remote.rs @@ -5,6 +5,7 @@ use crate::codex::Session; use crate::codex::TurnContext; use crate::compact::AutoCompactCallsite; use crate::compact::TurnContextReinjection; +use crate::compact::extract_latest_model_switch_update_from_items; use crate::compact::extract_trailing_model_switch_update_for_compaction_request; use crate::context_manager::ContextManager; use crate::context_manager::TotalTokenUsageBreakdown; @@ -106,10 +107,14 @@ async fn run_remote_compact_task_inner_impl( sess.emit_turn_item_started(turn_context, &compaction_item) .await; let mut history = sess.clone_history().await; + let mut incoming_items = incoming_items; // Keep compaction prompts in-distribution: if a model-switch update was injected at the - // tail of history (between turns), exclude it from the compaction request payload. - let stripped_model_switch_item = - extract_trailing_model_switch_update_for_compaction_request(&mut history); + // tail of incoming turn items (pre-turn path) or between turns in history, exclude it from + // the compaction request payload. + let stripped_model_switch_item = incoming_items + .as_mut() + .and_then(extract_latest_model_switch_update_from_items) + .or_else(|| extract_trailing_model_switch_update_for_compaction_request(&mut history)); let base_instructions = sess.get_base_instructions().await; let deleted_items = trim_function_call_history_to_fit_context_window( &mut history, diff --git a/codex-rs/core/tests/suite/compact_remote.rs b/codex-rs/core/tests/suite/compact_remote.rs index e1c0af92ec..9f91e6c147 100644 --- a/codex-rs/core/tests/suite/compact_remote.rs +++ b/codex-rs/core/tests/suite/compact_remote.rs @@ -1501,8 +1501,8 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model let compact_request = compact_mock.single_request(); let compact_body = compact_request.body_json().to_string(); assert!( - !compact_body.contains("AFTER_SWITCH_USER"), - "current behavior excludes incoming user from the pre-turn remote compaction request" + compact_body.contains("AFTER_SWITCH_USER"), + "pre-turn remote compaction request should include incoming user message" ); assert!( !compact_body.contains(""), @@ -1516,7 +1516,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model ); assert!( follow_up_body.contains("AFTER_SWITCH_USER"), - "post-compaction follow-up should preserve incoming user message via runtime append" + "post-compaction follow-up should preserve incoming user message" ); assert!( follow_up_body.contains(""), @@ -1526,7 +1526,7 @@ async fn snapshot_request_shape_remote_pre_turn_compaction_strips_incoming_model insta::assert_snapshot!( "remote_pre_turn_compaction_strips_incoming_model_switch_shapes", format_labeled_requests_snapshot( - "Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming from the compact request payload, and restores it in the post-compaction follow-up request.", + "Remote pre-turn compaction during model switch strips incoming from the compact request and restores it in the post-compaction follow-up request.", &[ ("Initial Request (Previous Model)", &requests[0]), ("Remote Compaction Request", &compact_request), diff --git a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_pre_turn_compaction_strips_incoming_model_switch_shapes.snap b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_pre_turn_compaction_strips_incoming_model_switch_shapes.snap index fba17d719e..0a789f5b69 100644 --- a/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_pre_turn_compaction_strips_incoming_model_switch_shapes.snap +++ b/codex-rs/core/tests/suite/snapshots/all__suite__compact_remote__remote_pre_turn_compaction_strips_incoming_model_switch_shapes.snap @@ -1,8 +1,8 @@ --- source: core/tests/suite/compact_remote.rs -expression: "format_labeled_requests_snapshot(\"Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming from the compact request payload, and restores it in the post-compaction follow-up request.\",\n&[(\"Initial Request (Previous Model)\", &requests[0]),\n(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])" +expression: "format_labeled_requests_snapshot(\"Remote pre-turn compaction during model switch strips incoming from the compact request and restores it in the post-compaction follow-up request.\",\n&[(\"Initial Request (Previous Model)\", &requests[0]),\n(\"Remote Compaction Request\", &compact_request),\n(\"Remote Post-Compaction History Layout\", &requests[1]),])" --- -Scenario: Remote pre-turn compaction during model switch currently excludes incoming user input, strips incoming from the compact request payload, and restores it in the post-compaction follow-up request. +Scenario: Remote pre-turn compaction during model switch strips incoming from the compact request and restores it in the post-compaction follow-up request. ## Initial Request (Previous Model) 00:message/developer: @@ -16,6 +16,7 @@ Scenario: Remote pre-turn compaction during model switch currently excludes inco 02:message/user:> 03:message/user:BEFORE_SWITCH_USER 04:message/assistant:BEFORE_SWITCH_REPLY +05:message/user:AFTER_SWITCH_USER ## Remote Post-Compaction History Layout 00:message/user:BEFORE_SWITCH_USER @@ -23,6 +24,6 @@ Scenario: Remote pre-turn compaction during model switch currently excludes inco 02:message/developer: The user has requested a new communication st... 03:message/user: 04:message/user:> -05:message/user:\nREMOTE_SWITCH_SUMMARY -06:message/developer:\nThe user was previously using a different model.... -07:message/user:AFTER_SWITCH_USER +05:message/user:AFTER_SWITCH_USER +06:message/user:\nREMOTE_SWITCH_SUMMARY +07:message/developer:\nThe user was previously using a different model....