diff --git a/codex-rs/core/src/codex_thread.rs b/codex-rs/core/src/codex_thread.rs index 7b57bd74e5..b2df5cde07 100644 --- a/codex-rs/core/src/codex_thread.rs +++ b/codex-rs/core/src/codex_thread.rs @@ -593,6 +593,20 @@ impl CodexThread { /// Record raw Responses API items without starting a new turn. pub async fn inject_response_items(&self, items: Vec) -> CodexResult<()> { + self.inject_response_items_for_turn(items).await?; + self.session.flush_rollout().await?; + Ok(()) + } + + /// Record raw Responses API items immediately before admitting a user turn. + /// + /// The caller must submit the associated user input while retaining its + /// thread-operation lock. The subsequent turn persistence includes both + /// these items and the user input, without an independent rollout flush. + pub async fn inject_response_items_for_turn( + &self, + items: Vec, + ) -> CodexResult<()> { if items.is_empty() { return Err(CodexErr::InvalidRequest( "items must not be empty".to_string(), @@ -613,7 +627,6 @@ impl CodexThread { self.session .inject_no_new_turn(items, Some(turn_context.as_ref())) .await; - self.session.flush_rollout().await?; Ok(()) } diff --git a/codex-rs/core/tests/suite/user_message_admission.rs b/codex-rs/core/tests/suite/user_message_admission.rs index b3f3c7d8b7..e89c9ba6fb 100644 --- a/codex-rs/core/tests/suite/user_message_admission.rs +++ b/codex-rs/core/tests/suite/user_message_admission.rs @@ -54,7 +54,7 @@ async fn default_turn_start_persists_developer_and_user_input_before_model_reque .await .expect("build default thread-store session"); test.codex - .inject_response_items(vec![ResponseItem::Message { + .inject_response_items_for_turn(vec![ResponseItem::Message { id: None, role: "developer".to_string(), content: vec![ContentItem::InputText {