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:
Ahmed Ibrahim
2026-04-30 13:39:48 +03:00
committed by GitHub
Unverified
parent c37f7434ba
commit 8a97f3cf03
23 changed files with 271 additions and 146 deletions
+25 -9
View File
@@ -163,7 +163,7 @@ pub struct ConversationStartParams {
)]
pub prompt: Option<Option<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
pub realtime_session_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub transport: Option<ConversationStartTransport>,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -366,7 +366,7 @@ pub struct RealtimeResponseDone {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
pub enum RealtimeEvent {
SessionUpdated {
session_id: String,
realtime_session_id: String,
instructions: Option<String>,
},
InputAudioSpeechStarted(RealtimeInputAudioSpeechStarted),
@@ -1667,7 +1667,7 @@ pub enum RealtimeConversationVersion {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, TS)]
pub struct RealtimeConversationStartedEvent {
pub session_id: Option<String>,
pub realtime_session_id: Option<String>,
pub version: RealtimeConversationVersion,
}
@@ -4764,14 +4764,14 @@ mod tests {
let start = Op::RealtimeConversationStart(ConversationStartParams {
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("be helpful".to_string())),
session_id: Some("conv_1".to_string()),
realtime_session_id: Some("conv_1".to_string()),
transport: None,
voice: None,
});
let webrtc_start = Op::RealtimeConversationStart(ConversationStartParams {
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("be helpful".to_string())),
session_id: Some("conv_1".to_string()),
realtime_session_id: Some("conv_1".to_string()),
transport: Some(ConversationStartTransport::Webrtc {
sdp: "v=offer\r\n".to_string(),
}),
@@ -4784,14 +4784,14 @@ mod tests {
let default_prompt_start = Op::RealtimeConversationStart(ConversationStartParams {
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
realtime_session_id: None,
transport: None,
voice: None,
});
let null_prompt_start = Op::RealtimeConversationStart(ConversationStartParams {
output_modality: RealtimeOutputModality::Audio,
prompt: Some(None),
session_id: None,
realtime_session_id: None,
transport: None,
voice: None,
});
@@ -4803,7 +4803,7 @@ mod tests {
"type": "realtime_conversation_start",
"output_modality": "audio",
"prompt": "be helpful",
"session_id": "conv_1"
"realtime_session_id": "conv_1"
})
);
assert_eq!(
@@ -4880,7 +4880,7 @@ mod tests {
"type": "realtime_conversation_start",
"output_modality": "audio",
"prompt": "be helpful",
"session_id": "conv_1",
"realtime_session_id": "conv_1",
"transport": {
"type": "webrtc",
"sdp": "v=offer\r\n"
@@ -4890,6 +4890,22 @@ mod tests {
);
}
#[test]
fn realtime_conversation_started_event_uses_realtime_session_id() {
let event = RealtimeConversationStartedEvent {
realtime_session_id: Some("conv_1".to_string()),
version: RealtimeConversationVersion::V2,
};
assert_eq!(
serde_json::to_value(&event).unwrap(),
json!({
"realtime_session_id": "conv_1",
"version": "v2"
})
);
}
#[test]
fn realtime_voice_list_is_stable() {
assert_eq!(