mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[1 of 7] Add thread settings to UserInput (#23080)
**Stack position:** [1 of 7] ## Summary The first three PRs in this stack are a cleanup pass before the actual thread settings API work. Today, core has several overlapping "user input" ops: `UserInput`, `UserInputWithTurnContext`, and `UserTurn`. They differ mostly in how much next-turn state they carry, which makes the later queued thread settings update harder to reason about and review. This PR starts that cleanup by adding the shared `ThreadSettingsOverrides` payload and allowing `Op::UserInput` to carry it. Existing variants remain in place here, so this layer is mostly a behavior-preserving API shape change plus mechanical constructor updates. ## End State After PR3 By the end of PR3, `Op::UserInput` is the only "user input" core op. It can carry optional thread settings overrides for callers that need to update stored defaults with a turn, while callers without updates use empty settings. `Op::UserInputWithTurnContext` and `Op::UserTurn` are deleted. ## End State After PR5 By the end of PR5, core will have only two ops for this area: - `Op::UserInput` for user-input-bearing submissions. - `Op::ThreadSettings` for settings-only updates. ## Stack 1. [1 of 7] [Add thread settings to UserInput](https://github.com/openai/codex/pull/23080) (this PR) 2. [2 of 7] [Remove UserInputWithTurnContext](https://github.com/openai/codex/pull/23081) 3. [3 of 7] [Remove UserTurn](https://github.com/openai/codex/pull/23075) 4. [4 of 7] [Placeholder for OverrideTurnContext cleanup](https://github.com/openai/codex/pull/23087) 5. [5 of 7] [Replace OverrideTurnContext with ThreadSettings](https://github.com/openai/codex/pull/22508) 6. [6 of 7] [Add app-server thread settings API](https://github.com/openai/codex/pull/22509) 7. [7 of 7] [Sync TUI thread settings](https://github.com/openai/codex/pull/22510)
This commit is contained in:
@@ -396,6 +396,80 @@ pub struct ConversationTextParams {
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
/// Persistent thread-settings overrides that can be applied before user input.
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
pub struct ThreadSettingsOverrides {
|
||||
/// Updated `cwd` for sandbox/tool calls.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub cwd: Option<PathBuf>,
|
||||
|
||||
/// Updated runtime workspace roots used to materialize symbolic
|
||||
/// `:workspace_roots` filesystem permissions.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub workspace_roots: Option<Vec<AbsolutePathBuf>>,
|
||||
|
||||
/// Updated profile-defined workspace roots for status summaries and
|
||||
/// per-turn config reconstruction.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub profile_workspace_roots: Option<Vec<AbsolutePathBuf>>,
|
||||
|
||||
/// Updated command approval policy.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub approval_policy: Option<AskForApproval>,
|
||||
|
||||
/// Updated approval reviewer for future approval prompts.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub approvals_reviewer: Option<ApprovalsReviewer>,
|
||||
|
||||
/// Updated sandbox policy for tool calls.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub sandbox_policy: Option<SandboxPolicy>,
|
||||
|
||||
/// Updated permissions profile for tool calls.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub permission_profile: Option<PermissionProfile>,
|
||||
|
||||
/// Named or built-in profile that produced `permission_profile`, if the
|
||||
/// update selected a profile rather than supplying raw permissions.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub active_permission_profile: Option<ActivePermissionProfile>,
|
||||
|
||||
/// Updated Windows sandbox mode for tool execution.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub windows_sandbox_level: Option<WindowsSandboxLevel>,
|
||||
|
||||
/// Updated model slug. When set, the model info is derived automatically.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub model: Option<String>,
|
||||
|
||||
/// Updated reasoning effort (honored only for reasoning-capable models).
|
||||
///
|
||||
/// Use `Some(Some(_))` to set a specific effort, `Some(None)` to clear the
|
||||
/// effort, or `None` to leave the existing value unchanged.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub effort: Option<Option<ReasoningEffortConfig>>,
|
||||
|
||||
/// Updated reasoning summary preference (honored only for reasoning-capable models).
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub summary: Option<ReasoningSummaryConfig>,
|
||||
|
||||
/// Updated service tier preference for future turns.
|
||||
///
|
||||
/// Use `Some(Some(_))` to set a specific tier, `Some(None)` to clear the
|
||||
/// preference, or `None` to leave the existing value unchanged.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub service_tier: Option<Option<String>>,
|
||||
|
||||
/// EXPERIMENTAL - set a pre-set collaboration mode.
|
||||
/// Takes precedence over model, effort, and developer instructions if set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub collaboration_mode: Option<CollaborationMode>,
|
||||
|
||||
/// Updated personality preference.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub personality: Option<Personality>,
|
||||
}
|
||||
|
||||
/// Submission operation
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
@@ -425,10 +499,7 @@ pub enum Op {
|
||||
/// Request the list of voices supported by realtime conversation streams.
|
||||
RealtimeConversationListVoices,
|
||||
|
||||
/// Legacy user input.
|
||||
///
|
||||
/// Prefer [`Op::UserTurn`] so the caller provides full turn context
|
||||
/// (cwd/approval/sandbox/model/etc.) for each turn.
|
||||
/// User input, optionally with thread-settings overrides applied first.
|
||||
UserInput {
|
||||
/// User input items, see `InputItem`
|
||||
items: Vec<UserInput>,
|
||||
@@ -441,9 +512,13 @@ pub enum Op {
|
||||
/// Optional turn-scoped Responses API `client_metadata`.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
responsesapi_client_metadata: Option<HashMap<String, String>>,
|
||||
|
||||
/// Persistent thread-settings overrides to apply before the input.
|
||||
#[serde(default, flatten)]
|
||||
thread_settings: ThreadSettingsOverrides,
|
||||
},
|
||||
|
||||
/// Similar to [`Op::UserInput`], but first applies persistent turn-context
|
||||
/// Similar to [`Op::UserInput`], but first applies persistent thread-settings
|
||||
/// overrides in the same queued operation. This preserves submission order
|
||||
/// and prevents the input from starting if the overrides are rejected.
|
||||
UserInputWithTurnContext {
|
||||
@@ -606,11 +681,11 @@ pub enum Op {
|
||||
communication: InterAgentCommunication,
|
||||
},
|
||||
|
||||
/// Override parts of the persistent turn context for subsequent turns.
|
||||
/// Override parts of the persistent thread settings for subsequent turns.
|
||||
///
|
||||
/// All fields are optional; when omitted, the existing value is preserved.
|
||||
/// This does not enqueue any input – it only updates defaults used for
|
||||
/// turns that rely on persistent session-level context (for example,
|
||||
/// turns that rely on persistent session-level settings (for example,
|
||||
/// [`Op::UserInput`]).
|
||||
OverrideTurnContext {
|
||||
/// Updated `cwd` for sandbox/tool calls.
|
||||
@@ -790,6 +865,7 @@ impl From<Vec<UserInput>> for Op {
|
||||
items: value,
|
||||
final_output_json_schema: None,
|
||||
responsesapi_client_metadata: None,
|
||||
thread_settings: ThreadSettingsOverrides::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5028,6 +5104,7 @@ mod tests {
|
||||
items: Vec::new(),
|
||||
final_output_json_schema: None,
|
||||
responsesapi_client_metadata: None,
|
||||
thread_settings: Default::default(),
|
||||
};
|
||||
|
||||
let json_op = serde_json::to_value(op)?;
|
||||
@@ -5047,6 +5124,7 @@ mod tests {
|
||||
items: Vec::new(),
|
||||
final_output_json_schema: None,
|
||||
responsesapi_client_metadata: None,
|
||||
thread_settings: Default::default(),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -5068,6 +5146,7 @@ mod tests {
|
||||
items: Vec::new(),
|
||||
final_output_json_schema: Some(schema.clone()),
|
||||
responsesapi_client_metadata: None,
|
||||
thread_settings: Default::default(),
|
||||
};
|
||||
|
||||
let json_op = serde_json::to_value(op)?;
|
||||
@@ -5093,6 +5172,7 @@ mod tests {
|
||||
"fiber_run_id".to_string(),
|
||||
"fiber-123".to_string(),
|
||||
)])),
|
||||
thread_settings: Default::default(),
|
||||
};
|
||||
|
||||
let json_op = serde_json::to_value(&op)?;
|
||||
|
||||
Reference in New Issue
Block a user