Wire realtime api to core (#12268)

- Introduce `RealtimeConversationManager` for realtime API management 
- Add `op::conversation` to start conversation, insert audio, insert
text, and close conversation.
- emit conversation lifecycle and realtime events.
- Move shared realtime payload types into codex-protocol and add core
e2e websocket tests for start/replace/transport-close paths.

Things to consider:
- Should we use the same `op::` and `Events` channel to carry audio? I
think we should try this simple approach and later we can create
separate one if the channels got congested.
- Sending text updates to the client: we can start simple and later
restrict that.
- Provider auth isn't wired for now intentionally
This commit is contained in:
Ahmed Ibrahim
2026-02-20 19:06:35 -08:00
committed by GitHub
parent 936e744c93
commit 6817f0be8a
28 changed files with 2102 additions and 42 deletions

View File

@@ -50,10 +50,10 @@ where
(addr, server)
}
fn test_provider() -> Provider {
fn test_provider(base_url: String) -> Provider {
Provider {
name: "test".to_string(),
base_url: "http://localhost".to_string(),
base_url,
query_params: Some(HashMap::new()),
headers: HeaderMap::new(),
retry: RetryConfig {
@@ -124,11 +124,10 @@ async fn realtime_ws_e2e_session_create_and_event_flow() {
})
.await;
let client = RealtimeWebsocketClient::new(test_provider());
let client = RealtimeWebsocketClient::new(test_provider(format!("http://{addr}")));
let connection = client
.connect(
RealtimeSessionConfig {
api_url: format!("ws://{addr}"),
prompt: "backend prompt".to_string(),
session_id: Some("conv_123".to_string()),
},
@@ -215,11 +214,10 @@ async fn realtime_ws_e2e_send_while_next_event_waits() {
})
.await;
let client = RealtimeWebsocketClient::new(test_provider());
let client = RealtimeWebsocketClient::new(test_provider(format!("http://{addr}")));
let connection = client
.connect(
RealtimeSessionConfig {
api_url: format!("ws://{addr}"),
prompt: "backend prompt".to_string(),
session_id: Some("conv_123".to_string()),
},
@@ -277,11 +275,10 @@ async fn realtime_ws_e2e_disconnected_emitted_once() {
})
.await;
let client = RealtimeWebsocketClient::new(test_provider());
let client = RealtimeWebsocketClient::new(test_provider(format!("http://{addr}")));
let connection = client
.connect(
RealtimeSessionConfig {
api_url: format!("ws://{addr}"),
prompt: "backend prompt".to_string(),
session_id: Some("conv_123".to_string()),
},
@@ -337,11 +334,10 @@ async fn realtime_ws_e2e_ignores_unknown_text_events() {
})
.await;
let client = RealtimeWebsocketClient::new(test_provider());
let client = RealtimeWebsocketClient::new(test_provider(format!("http://{addr}")));
let connection = client
.connect(
RealtimeSessionConfig {
api_url: format!("ws://{addr}"),
prompt: "backend prompt".to_string(),
session_id: Some("conv_123".to_string()),
},