diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index a06a2cd073..55b185e5a8 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -294,25 +294,17 @@ pub(crate) async fn apply_bespoke_event_handling( }), }) .collect(); - let call_id = request.call_id.clone(); let params = ToolRequestUserInputParams { thread_id: conversation_id.to_string(), turn_id: request.turn_id, - item_id: call_id.clone(), + item_id: request.call_id, questions, }; let rx = outgoing .send_request(ServerRequestPayload::ToolRequestUserInput(params)) .await; - let response_call_id = call_id.clone(); tokio::spawn(async move { - on_request_user_input_response( - event_turn_id, - response_call_id, - rx, - conversation, - ) - .await; + on_request_user_input_response(event_turn_id, rx, conversation).await; }); } else { error!( @@ -325,7 +317,6 @@ pub(crate) async fn apply_bespoke_event_handling( if let Err(err) = conversation .submit(Op::UserInputAnswer { id: event_turn_id, - call_id: Some(request.call_id.clone()), response: empty, }) .await @@ -1492,7 +1483,6 @@ async fn on_exec_approval_response( async fn on_request_user_input_response( event_turn_id: String, - call_id: String, receiver: oneshot::Receiver, conversation: Arc, ) { @@ -1507,7 +1497,6 @@ async fn on_request_user_input_response( if let Err(err) = conversation .submit(Op::UserInputAnswer { id: event_turn_id, - call_id: Some(call_id.clone()), response: empty, }) .await @@ -1543,7 +1532,6 @@ async fn on_request_user_input_response( if let Err(err) = conversation .submit(Op::UserInputAnswer { id: event_turn_id, - call_id: Some(call_id), response, }) .await diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 03fdd15704..e71fb7cd1c 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -33,7 +33,6 @@ use crate::stream_events_utils::HandleOutputCtx; use crate::stream_events_utils::handle_non_tool_response_item; use crate::stream_events_utils::handle_output_item_done; use crate::stream_events_utils::last_assistant_message_from_item; -use crate::stream_events_utils::response_input_to_response_item; use crate::terminal; use crate::transport_manager::TransportManager; use crate::truncate::TruncationPolicy; @@ -212,7 +211,6 @@ use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig; use codex_protocol::config_types::WindowsSandboxLevel; use codex_protocol::models::ContentItem; use codex_protocol::models::DeveloperInstructions; -use codex_protocol::models::FunctionCallOutputPayload; use codex_protocol::models::ResponseInputItem; use codex_protocol::models::ResponseItem; use codex_protocol::protocol::CodexErrorInfo; @@ -1719,7 +1717,6 @@ impl Session { pub async fn notify_user_input_response( &self, sub_id: &str, - call_id: Option, response: RequestUserInputResponse, ) { let entry = { @@ -1738,36 +1735,6 @@ impl Session { } None => { warn!("No pending user input found for sub_id: {sub_id}"); - if response.answers.is_empty() { - warn!( - "dropping empty request_user_input response for sub_id: {sub_id}; likely cancelled" - ); - return; - } - let call_id = call_id.unwrap_or_else(|| sub_id.to_string()); - let content = match response.to_tool_output_content() { - Ok(content) => content, - Err(err) => { - warn!( - "failed to serialize request_user_input response for call_id: {call_id}: {err}" - ); - return; - } - }; - let response_input = ResponseInputItem::FunctionCallOutput { - call_id: call_id.clone(), - output: FunctionCallOutputPayload { - content, - success: Some(true), - ..Default::default() - }, - }; - let Some(response_item) = response_input_to_response_item(&response_input) else { - return; - }; - let turn_context = self.new_default_turn_with_sub_id(sub_id.to_string()).await; - self.record_conversation_items(&turn_context, &[response_item]) - .await; } } } @@ -2592,12 +2559,8 @@ async fn submission_loop(sess: Arc, config: Arc, rx_sub: Receiv Op::PatchApproval { id, decision } => { handlers::patch_approval(&sess, id, decision).await; } - Op::UserInputAnswer { - id, - call_id, - response, - } => { - handlers::request_user_input_response(&sess, id, call_id, response).await; + Op::UserInputAnswer { id, response } => { + handlers::request_user_input_response(&sess, id, response).await; } Op::DynamicToolResponse { id, response } => { handlers::dynamic_tool_response(&sess, id, response).await; @@ -2951,11 +2914,9 @@ mod handlers { pub async fn request_user_input_response( sess: &Arc, id: String, - call_id: Option, response: RequestUserInputResponse, ) { - sess.notify_user_input_response(&id, call_id, response) - .await; + sess.notify_user_input_response(&id, response).await; } pub async fn dynamic_tool_response( diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index 1f61ef711d..7a611c05e2 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -380,13 +380,7 @@ async fn handle_request_user_input( cancel_token, ) .await; - let _ = codex - .submit(Op::UserInputAnswer { - id, - call_id: Some(event.call_id.clone()), - response, - }) - .await; + let _ = codex.submit(Op::UserInputAnswer { id, response }).await; } async fn await_user_input_with_cancel( @@ -405,7 +399,7 @@ where answers: HashMap::new(), }; parent_session - .notify_user_input_response(sub_id, None, empty.clone()) + .notify_user_input_response(sub_id, empty.clone()) .await; empty } diff --git a/codex-rs/core/src/mcp/skill_dependencies.rs b/codex-rs/core/src/mcp/skill_dependencies.rs index 8fdc413312..8836e29c1f 100644 --- a/codex-rs/core/src/mcp/skill_dependencies.rs +++ b/codex-rs/core/src/mcp/skill_dependencies.rs @@ -106,7 +106,7 @@ async fn should_install_mcp_dependencies( let empty = RequestUserInputResponse { answers: HashMap::new(), }; - sess.notify_user_input_response(sub_id, None, empty.clone()) + sess.notify_user_input_response(sub_id, empty.clone()) .await; empty } diff --git a/codex-rs/core/tests/suite/request_user_input.rs b/codex-rs/core/tests/suite/request_user_input.rs index 4ba7502948..89a5ed3557 100644 --- a/codex-rs/core/tests/suite/request_user_input.rs +++ b/codex-rs/core/tests/suite/request_user_input.rs @@ -165,7 +165,6 @@ async fn request_user_input_round_trip_resolves_pending() -> anyhow::Result<()> codex .submit(Op::UserInputAnswer { id: request.turn_id.clone(), - call_id: Some(request.call_id.clone()), response, }) .await?; diff --git a/codex-rs/docs/protocol_v1.md b/codex-rs/docs/protocol_v1.md index 803119604e..8f68ecc9a6 100644 --- a/codex-rs/docs/protocol_v1.md +++ b/codex-rs/docs/protocol_v1.md @@ -69,7 +69,7 @@ For complete documentation of the `Op` and `EventMsg` variants, refer to [protoc - `Op::UserInput` – Legacy form of user input - `Op::Interrupt` – Interrupts a running turn - `Op::ExecApproval` – Approve or deny code execution - - `Op::UserInputAnswer` – Provide answers for a `request_user_input` tool call (optionally include `call_id`) + - `Op::UserInputAnswer` – Provide answers for a `request_user_input` tool call - `Op::ListSkills` – Request skills for one or more cwd values (optionally `force_reload`) - `Op::UserTurn` and `Op::OverrideTurnContext` accept an optional `personality` override that updates the model’s communication style - `EventMsg` diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index a7b72b21a3..bf193cca9c 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -222,9 +222,6 @@ pub enum Op { UserInputAnswer { /// Turn id for the in-flight request. id: String, - /// Tool call id for the in-flight request, if available. - #[serde(skip_serializing_if = "Option::is_none")] - call_id: Option, /// User-provided answers. response: RequestUserInputResponse, }, diff --git a/codex-rs/protocol/src/request_user_input.rs b/codex-rs/protocol/src/request_user_input.rs index fa5d20b1ab..cb076264dd 100644 --- a/codex-rs/protocol/src/request_user_input.rs +++ b/codex-rs/protocol/src/request_user_input.rs @@ -43,12 +43,6 @@ pub struct RequestUserInputResponse { pub answers: HashMap, } -impl RequestUserInputResponse { - pub fn to_tool_output_content(&self) -> Result { - serde_json::to_string(self) - } -} - #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)] pub struct RequestUserInputEvent { /// Responses API call id for the associated tool call, if available. diff --git a/codex-rs/tui/src/bottom_pane/request_user_input/mod.rs b/codex-rs/tui/src/bottom_pane/request_user_input/mod.rs index 59807a8a4c..a9e00a6bd1 100644 --- a/codex-rs/tui/src/bottom_pane/request_user_input/mod.rs +++ b/codex-rs/tui/src/bottom_pane/request_user_input/mod.rs @@ -1459,7 +1459,7 @@ mod tests { overlay.submit_answers(); let event = rx.try_recv().expect("expected AppEvent"); - let AppEvent::CodexOp(Op::UserInputAnswer { id, response, .. }) = event else { + let AppEvent::CodexOp(Op::UserInputAnswer { id, response }) = event else { panic!("expected UserInputAnswer"); }; assert_eq!(id, "turn-1");