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
2026-08-13 00:00:16 +00:00
committed by copyberry
parent 4b07886d59
commit cbb7e82a8b
137 changed files with 5217 additions and 6812 deletions
@@ -688,7 +688,7 @@ async fn turn_start_jsonrpc_span_parents_core_turn_spans() -> Result<()> {
&& span_attr(span, "rpc.method") == Some("turn/start")
&& span.span_context.trace_id() == remote_trace_id
}) && spans.iter().any(|span| {
span_attr(span, "codex.op") == Some("user_input")
span_attr(span, "codex.op") == Some("turn_input")
&& span.span_context.trace_id() == remote_trace_id
})
})
@@ -697,8 +697,8 @@ async fn turn_start_jsonrpc_span_parents_core_turn_spans() -> Result<()> {
let server_request_span =
find_rpc_span_with_trace(&spans, SpanKind::Server, "turn/start", remote_trace_id);
let core_turn_span =
find_span_with_trace(&spans, remote_trace_id, "codex.op=user_input", |span| {
span_attr(span, "codex.op") == Some("user_input")
find_span_with_trace(&spans, remote_trace_id, "codex.op=turn_input", |span| {
span_attr(span, "codex.op") == Some("turn_input")
});
assert_eq!(server_request_span.parent_span_id, remote_parent_span_id);