mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
216ce03031
## 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`
62 lines
2.1 KiB
Rust
62 lines
2.1 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
use ts_rs::TS;
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputQuestionOption {
|
|
pub label: String,
|
|
pub description: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputQuestion {
|
|
pub id: String,
|
|
pub header: String,
|
|
pub question: String,
|
|
#[serde(rename = "isOther", default)]
|
|
#[schemars(rename = "isOther")]
|
|
#[ts(rename = "isOther")]
|
|
pub is_other: bool,
|
|
#[serde(rename = "isSecret", default)]
|
|
#[schemars(rename = "isSecret")]
|
|
#[ts(rename = "isSecret")]
|
|
pub is_secret: bool,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub options: Option<Vec<RequestUserInputQuestionOption>>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputArgs {
|
|
pub questions: Vec<RequestUserInputQuestion>,
|
|
#[serde(rename = "autoResolutionMs", skip_serializing_if = "Option::is_none")]
|
|
#[schemars(rename = "autoResolutionMs")]
|
|
pub auto_resolution_ms: Option<u64>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputAnswer {
|
|
pub answers: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputResponse {
|
|
pub answers: HashMap<String, RequestUserInputAnswer>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
|
pub struct RequestUserInputEvent {
|
|
/// Responses API call id for the associated tool call, if available.
|
|
pub call_id: String,
|
|
/// Turn ID that this request belongs to.
|
|
/// Uses `#[serde(default)]` for backwards compatibility.
|
|
#[serde(default)]
|
|
pub turn_id: String,
|
|
pub questions: Vec<RequestUserInputQuestion>,
|
|
#[serde(rename = "autoResolutionMs", skip_serializing_if = "Option::is_none")]
|
|
#[schemars(rename = "autoResolutionMs")]
|
|
pub auto_resolution_ms: Option<u64>,
|
|
}
|