From 637a2ac419dd7a46f631fe06d23eca5bfddaa123 Mon Sep 17 00:00:00 2001 From: jif-oai Date: Tue, 18 Nov 2025 20:32:26 +0000 Subject: [PATCH 1/3] fix: local compaction --- codex-rs/core/src/client.rs | 1 + codex-rs/core/src/codex.rs | 11 +++++++++-- codex-rs/core/src/compact_remote.rs | 14 +------------- codex-rs/core/src/tasks/compact.rs | 2 +- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index 13c277a776a..cc8ced21c8f 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -258,6 +258,7 @@ impl ModelClient { // // For Azure, we send `store: true` and preserve reasoning item IDs. let azure_workaround = self.provider.is_azure_responses_endpoint(); + tracing::warn!("Input: {input_with_instructions:#?}"); let payload = ResponsesApiRequest { model: &self.config.model, diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index e308601c55f..f3ed3d95317 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -1431,6 +1431,7 @@ mod handlers { use codex_protocol::protocol::ReviewRequest; use codex_protocol::protocol::TurnAbortReason; + use codex_protocol::user_input::UserInput; use std::sync::Arc; use tracing::info; use tracing::warn; @@ -1639,8 +1640,14 @@ mod handlers { .new_turn_with_sub_id(sub_id, SessionSettingsUpdate::default()) .await; - sess.spawn_task(Arc::clone(&turn_context), vec![], CompactTask) - .await; + sess.spawn_task( + Arc::clone(&turn_context), + vec![UserInput::Text { + text: turn_context.compact_prompt().to_string(), + }], + CompactTask, + ) + .await; } pub async fn shutdown(sess: &Arc, sub_id: String) -> bool { diff --git a/codex-rs/core/src/compact_remote.rs b/codex-rs/core/src/compact_remote.rs index 1726aad6f90..75b81d408c1 100644 --- a/codex-rs/core/src/compact_remote.rs +++ b/codex-rs/core/src/compact_remote.rs @@ -10,21 +10,18 @@ use crate::protocol::ErrorEvent; use crate::protocol::EventMsg; use crate::protocol::RolloutItem; use crate::protocol::TaskStartedEvent; -use codex_protocol::models::ResponseInputItem; use codex_protocol::models::ResponseItem; -use codex_protocol::user_input::UserInput; pub(crate) async fn run_remote_compact_task( sess: Arc, turn_context: Arc, - input: Vec, ) -> Option { let start_event = EventMsg::TaskStarted(TaskStartedEvent { model_context_window: turn_context.client.get_model_context_window(), }); sess.send_event(&turn_context, start_event).await; - match run_remote_compact_task_inner(&sess, &turn_context, input).await { + match run_remote_compact_task_inner(&sess, &turn_context).await { Ok(()) => { let event = EventMsg::AgentMessage(AgentMessageEvent { message: "Compact task completed".to_string(), @@ -45,17 +42,8 @@ pub(crate) async fn run_remote_compact_task( async fn run_remote_compact_task_inner( sess: &Arc, turn_context: &Arc, - input: Vec, ) -> CodexResult<()> { let mut history = sess.clone_history().await; - if !input.is_empty() { - let initial_input_for_turn: ResponseInputItem = ResponseInputItem::from(input); - history.record_items( - &[initial_input_for_turn.into()], - turn_context.truncation_policy, - ); - } - let prompt = Prompt { input: history.get_history_for_prompt(), tools: vec![], diff --git a/codex-rs/core/src/tasks/compact.rs b/codex-rs/core/src/tasks/compact.rs index e2e5625b5d5..4f161267a87 100644 --- a/codex-rs/core/src/tasks/compact.rs +++ b/codex-rs/core/src/tasks/compact.rs @@ -34,7 +34,7 @@ impl SessionTask for CompactTask { .is_some_and(|auth| auth.mode == AuthMode::ChatGPT) && session.enabled(Feature::RemoteCompaction).await { - crate::compact_remote::run_remote_compact_task(session, ctx, input).await + crate::compact_remote::run_remote_compact_task(session, ctx).await } else { crate::compact::run_compact_task(session, ctx, input).await } From a5b9a0045ee7c69c672745bd6053ec6e31345e71 Mon Sep 17 00:00:00 2001 From: jif-oai Date: Tue, 18 Nov 2025 21:18:05 +0000 Subject: [PATCH 2/3] Nit --- codex-rs/core/src/client.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index cc8ced21c8f..13c277a776a 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -258,7 +258,6 @@ impl ModelClient { // // For Azure, we send `store: true` and preserve reasoning item IDs. let azure_workaround = self.provider.is_azure_responses_endpoint(); - tracing::warn!("Input: {input_with_instructions:#?}"); let payload = ResponsesApiRequest { model: &self.config.model, From dee754e6194174a18345d9607f638f0342bd6c4c Mon Sep 17 00:00:00 2001 From: jif-oai Date: Tue, 18 Nov 2025 21:45:50 +0000 Subject: [PATCH 3/3] Add test --- codex-rs/core/tests/suite/compact.rs | 29 +++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index e8b3813c057..5359f3b1ad3 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -191,22 +191,19 @@ async fn summarize_context_three_requests_and_instructions() { let body2_str = body2.to_string(); let input2 = body2.get("input").and_then(|v| v.as_array()).unwrap(); let has_compact_prompt = body_contains_text(&body2_str, SUMMARIZATION_PROMPT); - if has_compact_prompt { - // The last item is the user message created from the injected input. - let last2 = input2.last().unwrap(); - assert_eq!(last2.get("type").unwrap().as_str().unwrap(), "message"); - assert_eq!(last2.get("role").unwrap().as_str().unwrap(), "user"); - let text2 = last2["content"][0]["text"].as_str().unwrap(); - assert_eq!( - text2, SUMMARIZATION_PROMPT, - "expected summarize trigger, got `{text2}`" - ); - } else { - assert!( - !has_compact_prompt, - "compaction request should not unexpectedly include the summarize trigger" - ); - } + assert!( + has_compact_prompt, + "compaction request should include the summarize trigger" + ); + // The last item is the user message created from the injected input. + let last2 = input2.last().unwrap(); + assert_eq!(last2.get("type").unwrap().as_str().unwrap(), "message"); + assert_eq!(last2.get("role").unwrap().as_str().unwrap(), "user"); + let text2 = last2["content"][0]["text"].as_str().unwrap(); + assert_eq!( + text2, SUMMARIZATION_PROMPT, + "expected summarize trigger, got `{text2}`" + ); // Third request must contain the refreshed instructions, compacted user history, and new user message. let input3 = body3.get("input").and_then(|v| v.as_array()).unwrap();