diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index ac3df37bd08..1e28b1b086e 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -2593,7 +2593,7 @@ pub struct ToolRequestUserInputOption { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] -/// EXPERIMENTAL. Represents one request_user_input question and its optional options. +/// EXPERIMENTAL. Represents one request_user_input question and its required options. pub struct ToolRequestUserInputQuestion { pub id: String, pub header: String, diff --git a/codex-rs/app-server/tests/common/responses.rs b/codex-rs/app-server/tests/common/responses.rs index 2a5b5d21597..e15319e02f9 100644 --- a/codex-rs/app-server/tests/common/responses.rs +++ b/codex-rs/app-server/tests/common/responses.rs @@ -67,7 +67,6 @@ pub fn create_request_user_input_sse_response(call_id: &str) -> anyhow::Result ToolSpec { let options_schema = JsonSchema::Array { description: Some( - "Optional 2-3 mutually exclusive choices. Put the recommended option first and suffix its label with \"(Recommended)\". Do not include an \"Other\" option in this list; use isOther on the question to request a free form choice. If the question is free form in nature, please do not have any option." + "Provide 2-3 mutually exclusive choices. Put the recommended option first and suffix its label with \"(Recommended)\". Do not include an \"Other\" option in this list; the client will add a free-form \"Other\" option automatically." .to_string(), ), items: Box::new(JsonSchema::Object { @@ -602,15 +602,6 @@ fn create_request_user_input_tool() -> ToolSpec { description: Some("Single-sentence prompt shown to the user.".to_string()), }, ); - question_props.insert( - "isOther".to_string(), - JsonSchema::Boolean { - description: Some( - "True when this question should include a free-form \"Other\" option. Otherwise false." - .to_string(), - ), - }, - ); question_props.insert("options".to_string(), options_schema); let questions_schema = JsonSchema::Array { @@ -621,7 +612,7 @@ fn create_request_user_input_tool() -> ToolSpec { "id".to_string(), "header".to_string(), "question".to_string(), - "isOther".to_string(), + "options".to_string(), ]), additional_properties: Some(false.into()), }), diff --git a/codex-rs/core/tests/suite/request_user_input.rs b/codex-rs/core/tests/suite/request_user_input.rs index 38729696105..89a5ed35570 100644 --- a/codex-rs/core/tests/suite/request_user_input.rs +++ b/codex-rs/core/tests/suite/request_user_input.rs @@ -94,7 +94,6 @@ async fn request_user_input_round_trip_resolves_pending() -> anyhow::Result<()> "id": "confirm_path", "header": "Confirm", "question": "Proceed with the plan?", - "isOther": false, "options": [{ "label": "Yes (Recommended)", "description": "Continue the current plan." @@ -153,6 +152,7 @@ async fn request_user_input_round_trip_resolves_pending() -> anyhow::Result<()> .await; assert_eq!(request.call_id, call_id); assert_eq!(request.questions.len(), 1); + assert_eq!(request.questions[0].is_other, true); let mut answers = HashMap::new(); answers.insert( @@ -214,7 +214,6 @@ where "id": "confirm_path", "header": "Confirm", "question": "Proceed with the plan?", - "isOther": false, "options": [{ "label": "Yes (Recommended)", "description": "Continue the current plan." diff --git a/codex-rs/docs/protocol_v1.md b/codex-rs/docs/protocol_v1.md index 8cdc5c9575c..74b55460126 100644 --- a/codex-rs/docs/protocol_v1.md +++ b/codex-rs/docs/protocol_v1.md @@ -75,7 +75,7 @@ For complete documentation of the `Op` and `EventMsg` variants, refer to [protoc - `EventMsg` - `EventMsg::AgentMessage` – Messages from the `Model` - `EventMsg::ExecApprovalRequest` – Request approval from user to execute a command - - `EventMsg::RequestUserInput` – Request user input for a tool call (questions can include options plus `isOther` to add a free-form choice) + - `EventMsg::RequestUserInput` – Request user input for a tool call (questions must include options; the client always adds a free-form choice) - `EventMsg::TurnComplete` – A turn completed successfully - `EventMsg::Error` – A turn stopped with an error - `EventMsg::Warning` – A non-fatal warning that the client should surface to the user