diff --git a/codex-rs/core/src/codex_thread.rs b/codex-rs/core/src/codex_thread.rs index 21f9ec4549..dec1ce6895 100644 --- a/codex-rs/core/src/codex_thread.rs +++ b/codex-rs/core/src/codex_thread.rs @@ -18,7 +18,6 @@ use codex_protocol::mcp::CallToolResult; use codex_protocol::models::ActivePermissionProfile; use codex_protocol::models::ContentItem; use codex_protocol::models::PermissionProfile; -use codex_protocol::models::ResponseInputItem; use codex_protocol::models::ResponseItem; use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::protocol::AdditionalContextEntry; @@ -265,20 +264,16 @@ impl CodexThread { .await } - /// Injects hidden model-visible items into the currently active turn. + /// Injects model-visible items into the currently active turn. /// - /// This is the runtime-owned counterpart to user-facing `steer_input`. + /// This is the thread-level bridge to `Session::inject_if_running` for + /// callers that only hold a `CodexThread`. /// It returns the unchanged items when this thread has no active turn. - pub async fn inject_response_items_into_active_turn( + pub async fn inject_if_running( &self, - items: Vec, - ) -> Result<(), Vec> { - let response_items = items.iter().cloned().map(ResponseItem::from).collect(); - self.codex - .session - .inject_if_running(response_items) - .await - .map_err(|_| items) + items: Vec, + ) -> Result<(), Vec> { + self.codex.session.inject_if_running(items).await } pub async fn set_app_server_client_info( @@ -396,7 +391,7 @@ impl CodexThread { .await; } - /// Append raw Responses API items to the thread's model-visible history. + /// Record raw Responses API items without starting a new turn. pub async fn inject_response_items(&self, items: Vec) -> CodexResult<()> { if items.is_empty() { return Err(CodexErr::InvalidRequest( diff --git a/codex-rs/ext/goal/src/runtime.rs b/codex-rs/ext/goal/src/runtime.rs index d78eda3de5..f077ddc54c 100644 --- a/codex-rs/ext/goal/src/runtime.rs +++ b/codex-rs/ext/goal/src/runtime.rs @@ -5,7 +5,7 @@ use std::sync::atomic::Ordering; use codex_core::ThreadManager; use codex_protocol::ThreadId; -use codex_protocol::models::ResponseInputItem; +use codex_protocol::models::ResponseItem; use codex_protocol::protocol::ThreadGoal; use crate::accounting::BudgetLimitedGoalDisposition; @@ -275,7 +275,7 @@ impl GoalRuntimeHandle { Ok(()) } - pub(crate) async fn inject_active_turn_steering(&self, item: ResponseInputItem) { + pub(crate) async fn inject_active_turn_steering(&self, item: ResponseItem) { let Some(thread_manager) = self.inner.thread_manager.upgrade() else { tracing::debug!("skipping goal steering because thread manager is unavailable"); return; @@ -284,11 +284,7 @@ impl GoalRuntimeHandle { tracing::debug!("skipping goal steering because live thread is unavailable"); return; }; - if thread - .inject_response_items_into_active_turn(vec![item]) - .await - .is_err() - { + if thread.inject_if_running(vec![item]).await.is_err() { tracing::debug!("skipping goal steering because no turn is active"); } } diff --git a/codex-rs/ext/goal/src/steering.rs b/codex-rs/ext/goal/src/steering.rs index 580a4aa971..e540ee171d 100644 --- a/codex-rs/ext/goal/src/steering.rs +++ b/codex-rs/ext/goal/src/steering.rs @@ -1,20 +1,22 @@ use codex_core::context::ContextualUserFragment; use codex_core::context::InternalContextSource; use codex_core::context::InternalModelContextFragment; -use codex_protocol::models::ResponseInputItem; +use codex_protocol::models::ResponseItem; use codex_protocol::protocol::ThreadGoal; -pub(crate) fn budget_limit_steering_item(goal: &ThreadGoal) -> ResponseInputItem { +pub(crate) fn budget_limit_steering_item(goal: &ThreadGoal) -> ResponseItem { goal_context_input_item(budget_limit_prompt(goal)) } -pub(crate) fn objective_updated_steering_item(goal: &ThreadGoal) -> ResponseInputItem { +pub(crate) fn objective_updated_steering_item(goal: &ThreadGoal) -> ResponseItem { goal_context_input_item(objective_updated_prompt(goal)) } -fn goal_context_input_item(prompt: String) -> ResponseInputItem { - InternalModelContextFragment::new(InternalContextSource::from_static("goal"), prompt) - .into_response_input_item() +fn goal_context_input_item(prompt: String) -> ResponseItem { + ContextualUserFragment::into(InternalModelContextFragment::new( + InternalContextSource::from_static("goal"), + prompt, + )) } fn budget_limit_prompt(goal: &ThreadGoal) -> String {