mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
realtime: rename provider session ids (#20361)
## Summary Codex is repurposing `session` to mean a thread group, so the realtime provider session id should no longer use `session_id` / `sessionId` in Codex-facing protocol payloads. This PR renames that provider-specific field to `realtime_session_id` / `realtimeSessionId` and intentionally breaks clients that still send the old field names. ## What Changed - Renamed realtime provider session fields in `ConversationStartParams`, `RealtimeConversationStartedEvent`, and `RealtimeEvent::SessionUpdated`. - Renamed app-server v2 realtime request and notification fields to `realtimeSessionId`. - Removed legacy serde aliases for `session_id` / `sessionId`; clients must send the new names. - Propagated the rename through core realtime startup, app-server adapters, codex-api websocket handling, and TUI realtime state. - Regenerated app-server protocol schema/TypeScript outputs and updated app-server README examples. - Kept upstream Realtime API concepts unchanged: provider `session.id` parsing and `x-session-id` headers still use the upstream wire names. ## Testing - CI is running on the latest pushed commit. - Earlier local verification on this PR: - `cargo test -p codex-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-core realtime_conversation` - `cargo test -p codex-app-server-protocol` - `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-app-server realtime_conversation` - attempted `CODEX_SKIP_VENDORED_BWRAP=1 cargo test -p codex-tui` (local linker bus error while linking the test binary) --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
c37f7434ba
commit
8a97f3cf03
@@ -761,14 +761,14 @@ const offer = await pc.createOffer();
|
||||
await pc.setLocalDescription(offer);
|
||||
```
|
||||
|
||||
Then send `offer.sdp` to app-server. Core uses `experimental_realtime_ws_backend_prompt` for the backend instructions and the thread conversation id for the realtime session id. The start response is `{}`; the remote answer SDP arrives later as `thread/realtime/sdp` and should be passed to `setRemoteDescription()`:
|
||||
Then send `offer.sdp` to app-server. Core uses `experimental_realtime_ws_backend_prompt` for the backend instructions and the thread conversation id as the default Realtime API session identifier. This `realtimeSessionId` value refers to the upstream Realtime API session, not a Codex session/thread-group id. The start response is `{}`; the remote answer SDP arrives later as `thread/realtime/sdp` and should be passed to `setRemoteDescription()`:
|
||||
|
||||
```json
|
||||
{ "method": "thread/realtime/start", "id": 40, "params": {
|
||||
"threadId": "thr_123",
|
||||
"outputModality": "audio",
|
||||
"prompt": "You are on a call.",
|
||||
"sessionId": null,
|
||||
"realtimeSessionId": null,
|
||||
"transport": { "type": "webrtc", "sdp": "v=0\r\no=..." }
|
||||
} }
|
||||
{ "id": 40, "result": {} }
|
||||
@@ -1100,7 +1100,7 @@ The fuzzy file search session API emits per-query notifications:
|
||||
|
||||
The thread realtime API emits thread-scoped notifications for session lifecycle and streaming media:
|
||||
|
||||
- `thread/realtime/started` — `{ threadId, sessionId }` once realtime starts for the thread (experimental).
|
||||
- `thread/realtime/started` — `{ threadId, realtimeSessionId }` once realtime starts for the thread (experimental). `realtimeSessionId` is the upstream Realtime API session identifier, not a Codex session/thread-group id.
|
||||
- `thread/realtime/itemAdded` — `{ threadId, item }` for raw non-audio realtime items that do not have a dedicated typed app-server notification, including `handoff_request` (experimental). `item` is forwarded as raw JSON while the upstream websocket item schema remains unstable.
|
||||
- `thread/realtime/transcript/delta` — `{ threadId, role, delta }` for live realtime transcript deltas (experimental).
|
||||
- `thread/realtime/transcript/done` — `{ threadId, role, text }` when realtime emits the final full text for a transcript part (experimental).
|
||||
|
||||
@@ -387,7 +387,7 @@ pub(crate) async fn apply_bespoke_event_handling(
|
||||
EventMsg::RealtimeConversationStarted(event) => {
|
||||
let notification = ThreadRealtimeStartedNotification {
|
||||
thread_id: conversation_id.to_string(),
|
||||
session_id: event.session_id,
|
||||
realtime_session_id: event.realtime_session_id,
|
||||
version: event.version,
|
||||
};
|
||||
outgoing
|
||||
|
||||
@@ -6994,7 +6994,7 @@ impl CodexMessageProcessor {
|
||||
Op::RealtimeConversationStart(ConversationStartParams {
|
||||
output_modality: params.output_modality,
|
||||
prompt: params.prompt,
|
||||
session_id: params.session_id,
|
||||
realtime_session_id: params.realtime_session_id,
|
||||
transport: params.transport.map(|transport| match transport {
|
||||
ThreadRealtimeStartTransport::Websocket => {
|
||||
ConversationStartTransport::Websocket
|
||||
|
||||
@@ -79,7 +79,7 @@ async fn realtime_conversation_start_requires_experimental_api_capability() -> R
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("hello".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: None,
|
||||
voice: None,
|
||||
})
|
||||
@@ -149,7 +149,7 @@ async fn realtime_webrtc_start_requires_experimental_api_capability() -> Result<
|
||||
thread_id: "thr_123".to_string(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("hello".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: Some(ThreadRealtimeStartTransport::Webrtc {
|
||||
sdp: "v=offer\r\n".to_string(),
|
||||
}),
|
||||
|
||||
@@ -313,7 +313,7 @@ impl RealtimeE2eHarness {
|
||||
thread_id: self.thread_id.clone(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("backend prompt".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: Some(ThreadRealtimeStartTransport::Webrtc {
|
||||
sdp: offer_sdp.to_string(),
|
||||
}),
|
||||
@@ -440,10 +440,10 @@ fn open_realtime_sideband_connection(
|
||||
}
|
||||
}
|
||||
|
||||
fn session_updated(session_id: &str) -> Value {
|
||||
fn session_updated(realtime_session_id: &str) -> Value {
|
||||
json!({
|
||||
"type": "session.updated",
|
||||
"session": { "id": session_id, "instructions": "backend prompt" }
|
||||
"session": { "id": realtime_session_id, "instructions": "backend prompt" }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -558,7 +558,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
|
||||
thread_id: thread_start.thread.id.clone(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: None,
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: None,
|
||||
voice: Some(RealtimeVoice::Cedar),
|
||||
})
|
||||
@@ -574,7 +574,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
|
||||
read_notification::<ThreadRealtimeStartedNotification>(&mut mcp, "thread/realtime/started")
|
||||
.await?;
|
||||
assert_eq!(started.thread_id, thread_start.thread.id);
|
||||
assert!(started.session_id.is_some());
|
||||
assert!(started.realtime_session_id.is_some());
|
||||
assert_eq!(started.version, RealtimeConversationVersion::V2);
|
||||
|
||||
let startup_context_request = realtime_server
|
||||
@@ -807,7 +807,7 @@ async fn realtime_text_output_modality_requests_text_output_and_final_transcript
|
||||
thread_id: thread_start.thread.id.clone(),
|
||||
output_modality: RealtimeOutputModality::Text,
|
||||
prompt: None,
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: None,
|
||||
voice: None,
|
||||
})
|
||||
@@ -981,7 +981,7 @@ async fn realtime_conversation_stop_emits_closed_notification() -> Result<()> {
|
||||
thread_id: thread_start.thread.id.clone(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("backend prompt".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: None,
|
||||
voice: None,
|
||||
})
|
||||
@@ -1078,7 +1078,7 @@ async fn realtime_webrtc_start_emits_sdp_notification() -> Result<()> {
|
||||
thread_id: thread_id.clone(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("backend prompt".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: Some(ThreadRealtimeStartTransport::Webrtc {
|
||||
sdp: "v=offer\r\n".to_string(),
|
||||
}),
|
||||
@@ -1208,7 +1208,7 @@ async fn webrtc_v1_start_posts_offer_returns_sdp_and_joins_sideband() -> Result<
|
||||
StartedWebrtcRealtime {
|
||||
started: ThreadRealtimeStartedNotification {
|
||||
thread_id: harness.thread_id.clone(),
|
||||
session_id: Some(harness.thread_id.clone()),
|
||||
realtime_session_id: Some(harness.thread_id.clone()),
|
||||
version: RealtimeConversationVersion::V1,
|
||||
},
|
||||
sdp: ThreadRealtimeSdpNotification {
|
||||
@@ -1993,7 +1993,7 @@ async fn realtime_webrtc_start_surfaces_backend_error() -> Result<()> {
|
||||
thread_id: thread_start.thread.id,
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("backend prompt".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: Some(ThreadRealtimeStartTransport::Webrtc {
|
||||
sdp: "v=offer\r\n".to_string(),
|
||||
}),
|
||||
@@ -2052,7 +2052,7 @@ async fn realtime_conversation_requires_feature_flag() -> Result<()> {
|
||||
thread_id: thread_start.thread.id.clone(),
|
||||
output_modality: RealtimeOutputModality::Audio,
|
||||
prompt: Some(Some("backend prompt".to_string())),
|
||||
session_id: None,
|
||||
realtime_session_id: None,
|
||||
transport: None,
|
||||
voice: None,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user