[codex] handle request_user_input in app-server test client (#29476)

## Why

`codex-app-server-test-client` previously treated
`item/tool/requestUserInput` as an unsupported server request and
terminated the connection. That made it impossible to use the client for
end-to-end testing of interactive turns: an operator could observe the
request, but could not answer it and confirm that the same turn resumed.

## What changed

- Handle `ToolRequestUserInput` server requests in the test client's
central request dispatcher.
- Render numbered terminal choices, accept exact option labels, support
free-form `Other` and text-only questions, and collect multiple answers.
- Send a protocol-native `ToolRequestUserInputResponse` and continue
streaming the active turn.
- Fail clearly when interactive input is requested without a terminal.
- Document the interactive behavior and add focused tests for option
selection, free-form answers, multiple questions, and invalid-selection
retries.

## Testing

- `just test -p codex-app-server-test-client`
- `just bazel-lock-check`
- Manually exercised the app-server flow, selected `TUI`, observed
`serverRequest/resolved`, and verified that the same turn completed with
the selected answer.
This commit is contained in:
Celia Chen authored and GitHub committed 2026-06-22 13:55:32 -07:00
1 parent ced3e4b9a7
commit cb255c52e9
6 files changed
+286

No files matched your search

@@ -91,6 +91,7 @@ mod loopback_responses_server;
mod plugin_analytics_capture;
mod plugin_analytics_mutation_smoke;
mod plugin_analytics_smoke;
mod request_user_input;
const NOTIFICATIONS_TO_OPT_OUT: &[&str] = &[
// v2 item deltas.
@@ -2040,6 +2041,10 @@ impl CodexClient {
ServerRequest::FileChangeRequestApproval { request_id, params } => {
self.approve_file_change_request(request_id, params)?;
}
ServerRequest::ToolRequestUserInput { request_id, params } => {
let response = request_user_input::prompt_for_answers(&params)?;
self.send_server_request_response(request_id, &response)?;
}
other => {
bail!("received unsupported server request: {other:?}");
}