[codex] Add Ultra reasoning effort (#29899)

## Why

Ultra should be one user-facing reasoning selection for work that
benefits from both maximum reasoning and proactive multi-agent
delegation. Without it, clients must coordinate maximum reasoning with
the experimental `multiAgentMode` setting, even though the inference
backend still expects its existing `max` effort value.

This change makes reasoning effort the source of truth: clients select
`ultra`, core derives proactive multi-agent behavior when the turn is
eligible for multi-agent V2, and inference requests continue to use the
backend-compatible `max` value.

## What changed

- Add `ultra` as a first-class reasoning effort and preserve
model-catalog ordering when exposing it to clients.
- Convert `ultra` to `max` at the inference request boundary, including
Responses HTTP/WebSocket requests, startup prewarm, compaction, and
memory summarization.
- Derive effective multi-agent mode per turn from effective reasoning
effort:
  - eligible multi-agent V2 + `ultra` → `proactive`
  - eligible multi-agent V2 + any other effort → `explicitRequestOnly`
- V1 or otherwise ineligible sessions → no multi-agent mode instruction
- Keep the derived effective mode in turn context history so successive
turns can emit a developer-message update only when the effective mode
changes.
- Remove selected multi-agent mode from core session configuration, turn
construction, thread settings, resume/fork restoration, and subagent
spawn plumbing. Subagents inherit reasoning effort and derive their own
effective mode.
- Retain the experimental app-server `multiAgentMode` fields for wire
compatibility while marking them deprecated. Request values are accepted
but ignored; compatibility response fields report `explicitRequestOnly`.
- Display Ultra in the TUI using the order supplied by `model/list`.

## Validation

- `just test -p codex-core ultra_reasoning_uses_max_for_requests`
- `just test -p codex-tui model_reasoning_selection_popup`
This commit is contained in:
Shijie Rao
2026-06-24 20:13:52 -07:00
committed by GitHub
Unverified
parent fa036d39aa
commit df1199fddb
41 changed files with 172 additions and 651 deletions
+8
View File
@@ -45,6 +45,7 @@ pub enum ReasoningEffort {
Medium,
High,
XHigh,
Ultra,
/// A model-defined effort value that this client does not know yet.
Custom(String),
}
@@ -59,6 +60,7 @@ impl ReasoningEffort {
Self::Medium => "medium",
Self::High => "high",
Self::XHigh => "xhigh",
Self::Ultra => "ultra",
Self::Custom(effort) => effort,
}
}
@@ -123,6 +125,7 @@ impl FromStr for ReasoningEffort {
"medium" => Ok(Self::Medium),
"high" => Ok(Self::High),
"xhigh" => Ok(Self::XHigh),
"ultra" => Ok(Self::Ultra),
"" => Err("reasoning_effort must not be empty".to_string()),
effort => Ok(Self::Custom(effort.to_string())),
}
@@ -701,20 +704,25 @@ mod tests {
let deserialized = from_str::<ReasoningEffort>(r#""max""#)
.expect("custom reasoning effort should deserialize");
let serialized = to_string(&custom).expect("custom reasoning effort should serialize");
let serialized_ultra = to_string(&ReasoningEffort::Ultra).expect("Ultra should serialize");
assert_eq!(
(
"high".parse(),
"ultra".parse(),
"max".parse(),
deserialized,
serialized,
serialized_ultra,
custom.to_string(),
),
(
Ok(ReasoningEffort::High),
Ok(ReasoningEffort::Ultra),
Ok(custom.clone()),
custom,
r#""max""#.to_string(),
r#""ultra""#.to_string(),
"max".to_string(),
)
);
-5
View File
@@ -489,9 +489,6 @@ pub struct ThreadSettingsOverrides {
/// Takes precedence over model, effort, and developer instructions if set.
pub collaboration_mode: Option<CollaborationMode>,
/// Updated multi-agent mode for this turn and subsequent turns.
pub multi_agent_mode: Option<MultiAgentMode>,
/// Updated personality preference.
pub personality: Option<Personality>,
}
@@ -2023,8 +2020,6 @@ pub struct ThreadSettingsSnapshot {
#[serde(skip_serializing_if = "Option::is_none")]
pub personality: Option<Personality>,
pub collaboration_mode: CollaborationMode,
#[serde(default)]
pub multi_agent_mode: MultiAgentMode,
}
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, JsonSchema, TS)]