Add WebRTC transport to realtime start (#16960)

Adds WebRTC startup to the experimental app-server
`thread/realtime/start` method with an optional transport enum. The
websocket path remains the default; WebRTC offers create the realtime
session through the shared start flow and emit the answer SDP via
`thread/realtime/sdp`.

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Ahmed Ibrahim
2026-04-07 15:43:38 -07:00
committed by GitHub
Unverified
parent 6c36e7d688
commit fb3dcfde1d
42 changed files with 1574 additions and 85 deletions
@@ -391,6 +391,9 @@ fn server_notification_thread_target(
ServerNotification::ThreadRealtimeOutputAudioDelta(notification) => {
Some(notification.thread_id.as_str())
}
ServerNotification::ThreadRealtimeSdp(notification) => {
Some(notification.thread_id.as_str())
}
ServerNotification::ThreadRealtimeError(notification) => {
Some(notification.thread_id.as_str())
}
@@ -625,6 +628,17 @@ fn server_notification_thread_events(
}),
}],
)),
ServerNotification::ThreadRealtimeSdp(notification) => Some((
ThreadId::from_string(&notification.thread_id).ok()?,
vec![Event {
id: String::new(),
msg: EventMsg::RealtimeConversationSdp(
codex_protocol::protocol::RealtimeConversationSdpEvent {
sdp: notification.sdp,
},
),
}],
)),
ServerNotification::ThreadRealtimeError(notification) => Some((
ThreadId::from_string(&notification.thread_id).ok()?,
vec![Event {
+10
View File
@@ -42,6 +42,7 @@ use codex_app_server_protocol::ThreadRealtimeAppendTextParams;
use codex_app_server_protocol::ThreadRealtimeAppendTextResponse;
use codex_app_server_protocol::ThreadRealtimeStartParams;
use codex_app_server_protocol::ThreadRealtimeStartResponse;
use codex_app_server_protocol::ThreadRealtimeStartTransport;
use codex_app_server_protocol::ThreadRealtimeStopParams;
use codex_app_server_protocol::ThreadRealtimeStopResponse;
use codex_app_server_protocol::ThreadResumeParams;
@@ -76,6 +77,7 @@ use codex_protocol::openai_models::ReasoningEffortPreset;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::ConversationAudioParams;
use codex_protocol::protocol::ConversationStartParams;
use codex_protocol::protocol::ConversationStartTransport;
use codex_protocol::protocol::ConversationTextParams;
use codex_protocol::protocol::CreditsSnapshot;
use codex_protocol::protocol::RateLimitSnapshot;
@@ -660,6 +662,14 @@ impl AppServerSession {
thread_id: thread_id.to_string(),
prompt: params.prompt,
session_id: params.session_id,
transport: params.transport.map(|transport| match transport {
ConversationStartTransport::Websocket => {
ThreadRealtimeStartTransport::Websocket
}
ConversationStartTransport::Webrtc { sdp } => {
ThreadRealtimeStartTransport::Webrtc { sdp }
}
}),
},
})
.await
+2
View File
@@ -6501,6 +6501,7 @@ impl ChatWidget {
);
}
}
ServerNotification::ThreadRealtimeSdp(_) => {}
ServerNotification::ServerRequestResolved(_)
| ServerNotification::AccountUpdated(_)
| ServerNotification::AccountRateLimitsUpdated(_)
@@ -7020,6 +7021,7 @@ impl ChatWidget {
self.on_realtime_conversation_started(ev);
}
}
EventMsg::RealtimeConversationSdp(_) => {}
EventMsg::RealtimeConversationRealtime(ev) => {
if !from_replay {
self.on_realtime_conversation_realtime(ev);
+1
View File
@@ -229,6 +229,7 @@ impl ChatWidget {
ConversationStartParams {
prompt: REALTIME_CONVERSATION_PROMPT.to_string(),
session_id: None,
transport: None,
},
));
self.request_redraw();