diff --git a/codex-rs/app-server-protocol/schema/json/EventMsg.json b/codex-rs/app-server-protocol/schema/json/EventMsg.json index f399912e03..c58e97b0e4 100644 --- a/codex-rs/app-server-protocol/schema/json/EventMsg.json +++ b/codex-rs/app-server-protocol/schema/json/EventMsg.json @@ -1486,6 +1486,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -1496,6 +1497,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", @@ -6086,6 +6093,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -6096,6 +6104,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 0e2f94f4d8..08bcc769b1 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -2064,6 +2064,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -2074,6 +2075,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", diff --git a/codex-rs/app-server-protocol/schema/json/ServerRequest.json b/codex-rs/app-server-protocol/schema/json/ServerRequest.json index ad0c2e3542..eae6be9b2f 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ServerRequest.json @@ -549,6 +549,7 @@ "ToolRequestUserInputParams": { "description": "EXPERIMENTAL. Params sent with a request_user_input event.", "properties": { + "arguments": true, "itemId": { "type": "string" }, @@ -561,6 +562,12 @@ "threadId": { "type": "string" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turnId": { "type": "string" } diff --git a/codex-rs/app-server-protocol/schema/json/ToolRequestUserInputParams.json b/codex-rs/app-server-protocol/schema/json/ToolRequestUserInputParams.json index 153d3bad67..ecdc8041bd 100644 --- a/codex-rs/app-server-protocol/schema/json/ToolRequestUserInputParams.json +++ b/codex-rs/app-server-protocol/schema/json/ToolRequestUserInputParams.json @@ -57,6 +57,7 @@ }, "description": "EXPERIMENTAL. Params sent with a request_user_input event.", "properties": { + "arguments": true, "itemId": { "type": "string" }, @@ -69,6 +70,12 @@ "threadId": { "type": "string" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turnId": { "type": "string" } diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 9b22ff2207..75ba51e494 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -3445,6 +3445,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -3455,6 +3456,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", @@ -8964,6 +8971,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "description": "EXPERIMENTAL. Params sent with a request_user_input event.", "properties": { + "arguments": true, "itemId": { "type": "string" }, @@ -8976,6 +8984,12 @@ "threadId": { "type": "string" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turnId": { "type": "string" } diff --git a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json index a5838e89e7..f66ff86bb3 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json @@ -1486,6 +1486,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -1496,6 +1497,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", diff --git a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json index 718b17aa28..251e6d6e09 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json @@ -1486,6 +1486,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -1496,6 +1497,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", diff --git a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json index a85b78281b..9c5979b7a0 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json @@ -1486,6 +1486,7 @@ }, { "properties": { + "arguments": true, "call_id": { "description": "Responses API call id for the associated tool call, if available.", "type": "string" @@ -1496,6 +1497,12 @@ }, "type": "array" }, + "tool": { + "type": [ + "string", + "null" + ] + }, "turn_id": { "default": "", "description": "Turn ID that this request belongs to. Uses `#[serde(default)]` for backwards compatibility.", diff --git a/codex-rs/app-server-protocol/schema/typescript/RequestUserInputEvent.ts b/codex-rs/app-server-protocol/schema/typescript/RequestUserInputEvent.ts index 8ea6453de9..5b7d0f47b1 100644 --- a/codex-rs/app-server-protocol/schema/typescript/RequestUserInputEvent.ts +++ b/codex-rs/app-server-protocol/schema/typescript/RequestUserInputEvent.ts @@ -2,6 +2,7 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { RequestUserInputQuestion } from "./RequestUserInputQuestion"; +import type { JsonValue } from "./serde_json/JsonValue"; export type RequestUserInputEvent = { /** @@ -12,4 +13,4 @@ call_id: string, * Turn ID that this request belongs to. * Uses `#[serde(default)]` for backwards compatibility. */ -turn_id: string, questions: Array, }; +turn_id: string, tool: string | null, arguments: JsonValue | null, questions: Array, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ToolRequestUserInputParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ToolRequestUserInputParams.ts index bee81cb8e2..1f06556b47 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ToolRequestUserInputParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ToolRequestUserInputParams.ts @@ -1,9 +1,10 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { JsonValue } from "../serde_json/JsonValue"; import type { ToolRequestUserInputQuestion } from "./ToolRequestUserInputQuestion"; /** * EXPERIMENTAL. Params sent with a request_user_input event. */ -export type ToolRequestUserInputParams = { threadId: string, turnId: string, itemId: string, questions: Array, }; +export type ToolRequestUserInputParams = { threadId: string, turnId: string, itemId: string, tool: string | null, arguments: JsonValue | null, questions: Array, }; diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index baafa84677..36d3a07e28 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -2886,6 +2886,8 @@ pub struct ToolRequestUserInputParams { pub thread_id: String, pub turn_id: String, pub item_id: String, + pub tool: Option, + pub arguments: Option, pub questions: Vec, } diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 4df8399e88..50fd2f416f 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -99,7 +99,7 @@ Example (from OpenAI's official VSCode extension): - `app/list` — list available apps. - `skills/config/write` — write user-level skill config by path. - `mcpServer/oauth/login` — start an OAuth login for a configured MCP server; returns an `authorization_url` and later emits `mcpServer/oauthLogin/completed` once the browser flow finishes. -- `tool/requestUserInput` — prompt the user with 1–3 short questions for a tool call and return their answers (experimental). +- `tool/requestUserInput` — prompt the user with 1–3 short questions for a tool call and return their answers (experimental; may include optional `tool` and JSON `arguments` context when available). - `config/mcpServer/reload` — reload MCP server config from disk and queue a refresh for loaded threads (applied on each thread's next active turn); returns `{}`. Use this after editing `config.toml` without restarting the server. - `mcpServerStatus/list` — enumerate configured MCP servers with their tools, resources, resource templates, and auth status; supports cursor+limit pagination. - `feedback/upload` — submit a feedback report (classification + optional reason/logs and conversation_id); returns the tracking thread id. diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index fd8db9cb62..012c76aaf2 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -299,6 +299,8 @@ pub(crate) async fn apply_bespoke_event_handling( thread_id: conversation_id.to_string(), turn_id: request.turn_id, item_id: request.call_id, + tool: request.tool, + arguments: request.arguments, questions, }; let rx = outgoing diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index cef00f64eb..80b84d38a6 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -1760,6 +1760,18 @@ impl Session { turn_context: &TurnContext, call_id: String, args: RequestUserInputArgs, + ) -> Option { + self.request_user_input_with_context(turn_context, call_id, args, None, None) + .await + } + + pub async fn request_user_input_with_context( + &self, + turn_context: &TurnContext, + call_id: String, + args: RequestUserInputArgs, + tool: Option, + arguments: Option, ) -> Option { let sub_id = turn_context.sub_id.clone(); let (tx_response, rx_response) = oneshot::channel(); @@ -1781,6 +1793,8 @@ impl Session { let event = EventMsg::RequestUserInput(RequestUserInputEvent { call_id, turn_id: turn_context.sub_id.clone(), + tool, + arguments, questions: args.questions, }); self.send_event(turn_context, event).await; diff --git a/codex-rs/core/src/mcp_tool_call.rs b/codex-rs/core/src/mcp_tool_call.rs index 737b130247..a7c3045d76 100644 --- a/codex-rs/core/src/mcp_tool_call.rs +++ b/codex-rs/core/src/mcp_tool_call.rs @@ -61,9 +61,15 @@ pub(crate) async fn handle_mcp_tool_call( arguments: arguments_value.clone(), }; - if let Some(decision) = - maybe_request_mcp_tool_approval(sess.as_ref(), turn_context, &call_id, &server, &tool_name) - .await + if let Some(decision) = maybe_request_mcp_tool_approval( + sess.as_ref(), + turn_context, + &call_id, + &server, + &tool_name, + arguments_value.clone(), + ) + .await { let result = match decision { McpToolApprovalDecision::Accept | McpToolApprovalDecision::AcceptAndRemember => { @@ -198,6 +204,7 @@ async fn maybe_request_mcp_tool_approval( call_id: &str, server: &str, tool_name: &str, + arguments: Option, ) -> Option { if is_full_access_mode(turn_context) { return None; @@ -237,7 +244,13 @@ async fn maybe_request_mcp_tool_approval( questions: vec![question], }; let response = sess - .request_user_input(turn_context, call_id.to_string(), args) + .request_user_input_with_context( + turn_context, + call_id.to_string(), + args, + Some(tool_name.to_string()), + arguments, + ) .await; let decision = parse_mcp_tool_approval_response(response, &question_id); if matches!(decision, McpToolApprovalDecision::AcceptAndRemember) diff --git a/codex-rs/protocol/src/request_user_input.rs b/codex-rs/protocol/src/request_user_input.rs index cb076264dd..2bf70d5924 100644 --- a/codex-rs/protocol/src/request_user_input.rs +++ b/codex-rs/protocol/src/request_user_input.rs @@ -51,5 +51,9 @@ pub struct RequestUserInputEvent { /// Uses `#[serde(default)]` for backwards compatibility. #[serde(default)] pub turn_id: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub tool: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub arguments: Option, pub questions: Vec, }