Add request_user_input auto-resolution window contract (#27256)

## Why

`request_user_input` is moving beyond its original plan-mode-only
workflow, and future default/goal-mode usage needs a way for the model
to ask helpful but non-blocking questions without forcing the turn to
wait forever. This PR adds an explicit `autoResolutionMs` contract so a
later client/runtime change can auto-resolve unanswered prompts after a
bounded window while leaving truly blocking questions unchanged.

This is contract plumbing only; it does not implement the client-side
timer or auto-selection behavior, and the model-facing description
treats the field as reserved unless the current runtime explicitly
supports auto-resolution.

## What Changed

- Added optional `autoResolutionMs` to the model-facing
`request_user_input` args and core `RequestUserInputEvent`.
- Added model-facing schema text for `autoResolutionMs` while marking it
reserved for runtimes that explicitly support auto-resolution.
- Bounds `autoResolutionMs` to `60_000..=240_000` ms during argument
normalization by clamping out-of-range model-provided values.
- Propagated the field through app-server v2
`ToolRequestUserInputParams`, app-server request forwarding, generated
TypeScript, and JSON schema fixtures.
- Updated app-server, core, protocol, and TUI call sites/tests so
omitted values preserve existing `None`/`null` behavior and coverage
verifies a `Some(60_000)` round trip.

## Verification

- `just test -p codex-app-server-protocol`
- `just test -p codex-core request_user_input`
- `just test -p codex-app-server request_user_input_round_trip`
- `just test -p codex-tui request_user_input`
- `just test -p codex-protocol`
This commit is contained in:
Shijie Rao
2026-06-11 22:30:41 -07:00
committed by GitHub
Unverified
parent 78bab04116
commit 216ce03031
25 changed files with 243 additions and 16 deletions
@@ -687,6 +687,7 @@ pub(crate) async fn apply_bespoke_event_handling(
turn_id: request.turn_id,
item_id: request.call_id,
questions,
auto_resolution_ms: request.auto_resolution_ms,
};
let (pending_request_id, rx) = outgoing
.send_request(ServerRequestPayload::ToolRequestUserInput(params))
@@ -1259,6 +1259,7 @@ mod tests {
turn_id: "turn-1".to_string(),
item_id: "call-1".to_string(),
questions: vec![],
auto_resolution_ms: None,
},
))
.await;
@@ -1321,6 +1322,7 @@ mod tests {
turn_id: "turn-1".to_string(),
item_id: "call-1".to_string(),
questions: vec![],
auto_resolution_ms: None,
},
))
.await;
@@ -1140,6 +1140,7 @@ mod thread_processor_behavior_tests {
turn_id: "turn-1".to_string(),
item_id: "call-1".to_string(),
questions: vec![],
auto_resolution_ms: None,
},
))
.await;