mirror of
https://github.com/openai/codex.git
synced 2026-04-26 15:45:02 +00:00
turn metadata: per-turn non-blocking (#11677)
This commit is contained in:
@@ -375,6 +375,15 @@ async fn responses_stream_includes_turn_metadata_header_for_git_workspace_e2e()
|
||||
.expect("x-codex-turn-metadata header should be present");
|
||||
let initial_parsed: serde_json::Value =
|
||||
serde_json::from_str(&initial_header).expect("x-codex-turn-metadata should be valid JSON");
|
||||
let initial_turn_id = initial_parsed
|
||||
.get("turn_id")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.expect("turn_id should be present")
|
||||
.to_string();
|
||||
assert!(
|
||||
!initial_turn_id.is_empty(),
|
||||
"turn_id should not be empty in x-codex-turn-metadata"
|
||||
);
|
||||
assert_eq!(
|
||||
initial_parsed
|
||||
.get("sandbox")
|
||||
@@ -424,56 +433,95 @@ async fn responses_stream_includes_turn_metadata_header_for_git_workspace_e2e()
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(5);
|
||||
loop {
|
||||
let request_recorder = responses::mount_sse_once(&server, response_body.clone()).await;
|
||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
||||
test.submit_turn("hello")
|
||||
.await
|
||||
.expect("submit post-git turn prompt");
|
||||
let first_response = responses::sse(vec![
|
||||
responses::ev_response_created("resp-2"),
|
||||
responses::ev_reasoning_item("rsn-1", &["thinking"], &[]),
|
||||
responses::ev_shell_command_call("call-1", "echo turn-metadata"),
|
||||
responses::ev_completed("resp-2"),
|
||||
]);
|
||||
let follow_up_response = responses::sse(vec![
|
||||
responses::ev_response_created("resp-3"),
|
||||
responses::ev_assistant_message("msg-1", "done"),
|
||||
responses::ev_completed("resp-3"),
|
||||
]);
|
||||
let request_log = responses::mount_response_sequence(
|
||||
&server,
|
||||
vec![
|
||||
responses::sse_response(first_response),
|
||||
responses::sse_response(follow_up_response),
|
||||
],
|
||||
)
|
||||
.await;
|
||||
|
||||
let maybe_metadata = request_recorder
|
||||
.single_request()
|
||||
test.submit_turn("hello")
|
||||
.await
|
||||
.expect("submit post-git turn prompt");
|
||||
|
||||
let requests = request_log.requests();
|
||||
assert_eq!(requests.len(), 2, "expected two requests in one turn");
|
||||
|
||||
let first_parsed: serde_json::Value = serde_json::from_str(
|
||||
&requests[0]
|
||||
.header("x-codex-turn-metadata")
|
||||
.and_then(|header_value| {
|
||||
let parsed: serde_json::Value = serde_json::from_str(&header_value).ok()?;
|
||||
let workspace = parsed
|
||||
.get("workspaces")
|
||||
.and_then(serde_json::Value::as_object)
|
||||
.and_then(|workspaces| workspaces.values().next())
|
||||
.cloned()?;
|
||||
Some((parsed, workspace))
|
||||
});
|
||||
let Some((parsed, workspace)) = maybe_metadata else {
|
||||
if tokio::time::Instant::now() >= deadline {
|
||||
break;
|
||||
}
|
||||
tokio::time::sleep(std::time::Duration::from_millis(25)).await;
|
||||
continue;
|
||||
};
|
||||
.expect("first request should include turn metadata"),
|
||||
)
|
||||
.expect("first metadata should be valid json");
|
||||
let second_parsed: serde_json::Value = serde_json::from_str(
|
||||
&requests[1]
|
||||
.header("x-codex-turn-metadata")
|
||||
.expect("second request should include turn metadata"),
|
||||
)
|
||||
.expect("second metadata should be valid json");
|
||||
|
||||
assert_eq!(
|
||||
parsed.get("sandbox").and_then(serde_json::Value::as_str),
|
||||
Some("none")
|
||||
);
|
||||
assert_eq!(
|
||||
workspace
|
||||
.get("latest_git_commit_hash")
|
||||
.and_then(serde_json::Value::as_str),
|
||||
Some(expected_head.as_str())
|
||||
);
|
||||
assert_eq!(
|
||||
workspace
|
||||
.get("associated_remote_urls")
|
||||
.and_then(serde_json::Value::as_object)
|
||||
.and_then(|remotes| remotes.get("origin"))
|
||||
.and_then(serde_json::Value::as_str),
|
||||
Some(expected_origin.as_str())
|
||||
);
|
||||
return;
|
||||
}
|
||||
let first_turn_id = first_parsed
|
||||
.get("turn_id")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.expect("first turn_id should be present");
|
||||
let second_turn_id = second_parsed
|
||||
.get("turn_id")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.expect("second turn_id should be present");
|
||||
assert_eq!(
|
||||
first_turn_id, second_turn_id,
|
||||
"requests should share turn_id"
|
||||
);
|
||||
assert_ne!(
|
||||
second_turn_id,
|
||||
initial_turn_id.as_str(),
|
||||
"post-git turn should have a new turn_id"
|
||||
);
|
||||
|
||||
panic!(
|
||||
"x-codex-turn-metadata with git workspace info was never observed within 5s after git setup"
|
||||
assert_eq!(
|
||||
second_parsed
|
||||
.get("sandbox")
|
||||
.and_then(serde_json::Value::as_str),
|
||||
Some("none")
|
||||
);
|
||||
|
||||
let workspace = second_parsed
|
||||
.get("workspaces")
|
||||
.and_then(serde_json::Value::as_object)
|
||||
.and_then(|workspaces| workspaces.values().next())
|
||||
.cloned()
|
||||
.expect("second request should include git workspace metadata");
|
||||
assert_eq!(
|
||||
workspace
|
||||
.get("latest_git_commit_hash")
|
||||
.and_then(serde_json::Value::as_str),
|
||||
Some(expected_head.as_str())
|
||||
);
|
||||
assert_eq!(
|
||||
workspace
|
||||
.get("associated_remote_urls")
|
||||
.and_then(serde_json::Value::as_object)
|
||||
.and_then(|remotes| remotes.get("origin"))
|
||||
.and_then(serde_json::Value::as_str),
|
||||
Some(expected_origin.as_str())
|
||||
);
|
||||
assert_eq!(
|
||||
workspace
|
||||
.get("has_changes")
|
||||
.and_then(serde_json::Value::as_bool),
|
||||
Some(false)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user