Unify turn input submission and routing (#38275)

## What changed

- Add `TurnInputRequest` and typed submission results for atomically starting a turn, steering the active turn, or declining input with a specific reason.
- Expose `start_or_steer_turn`, `start_turn_if_idle`, and `steer_turn` on `CodexThread`, and migrate Core consumers to these APIs.
- Make app-server `turn/start` steer an active regular turn and return that turn's ID. Reject incompatible output schemas and non-steerable turns without applying settings or enqueueing input.

## Testing

- Cover concurrent start-or-steer submissions, accepted and rejected settings updates, output-schema compatibility, idle-start rejection, and app-server steering.

GitOrigin-RevId: dd9b5528d76ec650c019e97af420bc13190ea86a
This commit is contained in:
Owen Lin authored and copyberry committed 2026-08-13 00:00:16 +00:00
1 parent 4b07886d59
commit cbb7e82a8b
137 files changed
+5217 -6812

No files matched your search

+17 -7
View File
@@ -3,8 +3,10 @@ use std::sync::Weak;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use codex_core::StartIfIdleSubmission;
use codex_core::ThreadManager;
use codex_core::TurnInput;
use codex_core::TurnInputRequest;
use codex_protocol::ThreadId;
use codex_protocol::models::ResponseItem;
use codex_protocol::protocol::ThreadGoal;
@@ -403,15 +405,23 @@ impl GoalRuntimeHandle {
}
let item = continuation_steering_item(&protocol_goal_from_state(goal));
if let Err(err) = thread
.try_start_turn_if_idle(vec![TurnInput::ResponseItem(item.into())])
match thread
.start_turn_if_idle(TurnInputRequest::new(TurnInput::ResponseItem(item)))
.await
{
let reason = err.reason();
tracing::debug!(
?reason,
"skipping goal continuation because automatic idle work was rejected"
);
Ok(StartIfIdleSubmission::Started { .. }) => {}
Ok(StartIfIdleSubmission::NotSubmitted { reason }) => {
tracing::debug!(
?reason,
"skipping goal continuation because automatic idle work was rejected"
);
}
Err(error) => {
tracing::debug!(
%error,
"skipping goal continuation because turn input submission failed"
);
}
}
let current_turn_is_goal_active = self