Attach WebRTC realtime starts to sideband websocket (#17057)

Summary:
- parse the realtime call Location header and join that call over the
direct realtime WebSocket
- keep WebRTC starts alive on the existing realtime conversation path

Validation:
- just fmt
- git diff --check
- cargo check -p codex-api
- cargo check -p codex-core --tests
- local cargo tests not run; relying on PR CI
This commit is contained in:
Ahmed Ibrahim
2026-04-08 15:25:42 -07:00
committed by GitHub
parent 19bd018300
commit 794a0240f9
7 changed files with 534 additions and 89 deletions

View File

@@ -195,6 +195,82 @@ async fn realtime_ws_e2e_session_create_and_event_flow() {
server.await.expect("server task");
}
#[tokio::test]
async fn realtime_ws_connect_webrtc_sideband_retries_join_until_server_is_available() {
let reserving_listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let addr = reserving_listener.local_addr().expect("local addr");
drop(reserving_listener);
let server = tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(20)).await;
let listener = TcpListener::bind(addr).await.expect("bind delayed server");
let (stream, _) = listener.accept().await.expect("accept");
let mut ws = accept_async(stream).await.expect("accept ws");
let first = ws
.next()
.await
.expect("first msg")
.expect("first msg ok")
.into_text()
.expect("text");
let first_json: Value = serde_json::from_str(&first).expect("json");
assert_eq!(first_json["type"], "session.update");
assert_eq!(
first_json["session"]["instructions"],
Value::String("backend prompt".to_string())
);
ws.send(Message::Text(
json!({
"type": "session.updated",
"session": {"id": "sess_joined", "instructions": "backend prompt"}
})
.to_string()
.into(),
))
.await
.expect("send session.updated");
});
let mut provider = test_provider(format!("http://{addr}"));
provider.retry.max_attempts = 1;
provider.retry.base_delay = Duration::from_millis(100);
let client = RealtimeWebsocketClient::new(provider);
let connection = client
.connect_webrtc_sideband(
RealtimeSessionConfig {
instructions: "backend prompt".to_string(),
model: Some("realtime-test-model".to_string()),
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Conversational,
},
"rtc_test",
HeaderMap::new(),
HeaderMap::new(),
)
.await
.expect("connect on retry");
let event = connection
.next_event()
.await
.expect("next event")
.expect("event");
assert_eq!(
event,
RealtimeEvent::SessionUpdated {
session_id: "sess_joined".to_string(),
instructions: Some("backend prompt".to_string()),
}
);
connection.close().await.expect("close");
server.await.expect("server task");
}
#[tokio::test]
async fn realtime_ws_e2e_send_while_next_event_waits() {
let (addr, server) = spawn_realtime_ws_server(|mut ws: RealtimeWsStream| async move {