Support attaching to existing realtime calls (#39876)

## Why

Clients that create and negotiate realtime calls themselves need Codex to join
those calls without creating another call or overwriting the client-owned
session configuration.

## What changed

- Add the `existingCall` transport to `thread/realtime/start`, accepting a
  client-provided `callId` and optional `realtimeSessionId`.
- Attach Codex over the call's sideband WebSocket without SDP negotiation or a
  session update, and reconnect that sideband while preserving transcript
  state.
- Default existing calls to realtime v1, support v1 and v3, and reject v2 or
  options that would reconfigure the client-owned session.
- Encode call IDs as a single URL path segment for v3 sideband connections.

## Testing

Add protocol, app-server, core, reconnection, authentication-header, and URL
encoding coverage for existing-call attachments.

GitOrigin-RevId: 2046b70566f98efa55381bb1e461ea3cc68256c5
This commit is contained in:
Zahan Malkani
2026-08-21 06:41:28 +00:00
committed by copyberry
parent 2aaefa32b0
commit 536f86e5cc
18 changed files with 765 additions and 34 deletions
@@ -4526,6 +4526,27 @@
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"callId": {
"description": "Identifier of a realtime call already created and negotiated by the client.",
"type": "string"
},
"type": {
"enum": [
"existingCall"
],
"title": "ExistingCallThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"callId",
"type"
],
"title": "ExistingCallThreadRealtimeStartTransport",
"type": "object"
}
]
},
@@ -21178,6 +21178,27 @@
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"callId": {
"description": "Identifier of a realtime call already created and negotiated by the client.",
"type": "string"
},
"type": {
"enum": [
"existingCall"
],
"title": "ExistingCallThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"callId",
"type"
],
"title": "ExistingCallThreadRealtimeStartTransport",
"type": "object"
}
]
},
@@ -18930,6 +18930,27 @@
],
"title": "WebrtcThreadRealtimeStartTransport",
"type": "object"
},
{
"properties": {
"callId": {
"description": "Identifier of a realtime call already created and negotiated by the client.",
"type": "string"
},
"type": {
"enum": [
"existingCall"
],
"title": "ExistingCallThreadRealtimeStartTransportType",
"type": "string"
}
},
"required": [
"callId",
"type"
],
"title": "ExistingCallThreadRealtimeStartTransport",
"type": "object"
}
]
},
@@ -10,4 +10,8 @@ export type ThreadRealtimeStartTransport = { "type": "websocket" } | { "type": "
* SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the
* realtime events data channel.
*/
sdp: string, };
sdp: string, } | { "type": "existingCall",
/**
* Identifier of a realtime call already created and negotiated by the client.
*/
callId: string, };
@@ -155,6 +155,12 @@ pub enum ThreadRealtimeStartTransport {
/// realtime events data channel.
sdp: String,
},
ExistingCall {
/// Identifier of a realtime call already created and negotiated by the client.
#[serde(rename = "callId")]
#[ts(rename = "callId")]
call_id: String,
},
}
/// EXPERIMENTAL - response for starting thread realtime.