mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Track root turns across delegated Codex requests (#38232)
## Why `parent_turn_id` identifies the immediate caller of a nested request, but not the top-level turn that initiated a multi-level chain of work. ## What changed - Add `root_turn_id` to turn state, submissions, and Responses API metadata. - Propagate the root through spawned agents, delegated work, review sessions, and turn-triggering inter-agent messages. - Omit the root when background work has no user turn or combined input makes the root ambiguous. ## Testing Added coverage for nested agent resumes, reviews, mailbox delivery, steered input, and reserved metadata handling. GitOrigin-RevId: 60057db2ee81f4efefa946a9f63c74ff98b93929
This commit is contained in:
1 parent
9df9ff6ad9
commit
1f4ea79853
38 files changed
+470
-65
No files matched your search
@@ -830,8 +830,10 @@ impl Session {
|
||||
impl SessionIo {
|
||||
/// Submit the `op` wrapped in a `Submission` with a unique ID.
|
||||
pub(crate) async fn submit(&self, op: Op) -> CodexResult<String> {
|
||||
self.submit_with_trace(op, /*trace*/ None, /*parent_turn_id*/ None)
|
||||
.await
|
||||
self.submit_with_trace(
|
||||
op, /*trace*/ None, /*parent_turn_id*/ None, /*root_turn_id*/ None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn submit_with_trace(
|
||||
@@ -839,6 +841,7 @@ impl SessionIo {
|
||||
op: Op,
|
||||
trace: Option<W3cTraceContext>,
|
||||
parent_turn_id: Option<String>,
|
||||
root_turn_id: Option<String>,
|
||||
) -> CodexResult<String> {
|
||||
let id = new_submission_id();
|
||||
let sub = Submission {
|
||||
@@ -847,6 +850,7 @@ impl SessionIo {
|
||||
client_user_message_id: None,
|
||||
trace,
|
||||
parent_turn_id,
|
||||
root_turn_id,
|
||||
};
|
||||
self.submit_with_id(sub).await?;
|
||||
Ok(id)
|
||||
@@ -866,6 +870,7 @@ impl SessionIo {
|
||||
client_user_message_id,
|
||||
trace,
|
||||
parent_turn_id: None,
|
||||
root_turn_id: None,
|
||||
};
|
||||
self.submit_with_id(sub).await?;
|
||||
Ok(id)
|
||||
@@ -1259,6 +1264,7 @@ impl Session {
|
||||
},
|
||||
/*client_user_message_id*/ None,
|
||||
/*parent_turn_id*/ None,
|
||||
/*root_turn_id*/ None,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -2046,6 +2052,7 @@ impl Session {
|
||||
communication,
|
||||
context,
|
||||
/*parent_turn_id*/ None,
|
||||
/*root_turn_id*/ None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -4025,6 +4032,7 @@ impl Session {
|
||||
expected_turn_id: Option<&str>,
|
||||
client_user_message_id: Option<String>,
|
||||
responsesapi_client_metadata: Option<HashMap<String, String>>,
|
||||
incoming_turn_metadata: Option<&TurnMetadataState>,
|
||||
) -> Result<String, SteerInputError> {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
let Some(active_turn) = active.as_mut() else {
|
||||
@@ -4084,6 +4092,15 @@ impl Session {
|
||||
content: input,
|
||||
client_id: client_user_message_id.clone(),
|
||||
});
|
||||
if let Some(incoming_turn_metadata) = incoming_turn_metadata
|
||||
&& active_task.turn_context.turn_metadata_state.root_turn_id()
|
||||
!= incoming_turn_metadata.root_turn_id()
|
||||
{
|
||||
active_task
|
||||
.turn_context
|
||||
.turn_metadata_state
|
||||
.mark_root_turn_ambiguous();
|
||||
}
|
||||
self.input_queue
|
||||
.extend_pending_input_and_accept_mailbox_delivery_for_turn_state(
|
||||
active_turn.turn_state.as_ref(),
|
||||
|
||||
Reference in new issue
Block a user