From 7fa52013653465661441ac016886ee843855a08c Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Fri, 13 Mar 2026 16:17:13 -0700 Subject: [PATCH] Use parser-specific realtime voice enum (#14636) Model realtime session output voices with an enum and map by parser so v1 uses fathom and v2 uses alloy. Co-authored-by: Codex --- .../src/endpoint/realtime_websocket/methods.rs | 18 ++++++++++-------- .../endpoint/realtime_websocket/protocol.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs b/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs index 12293693e..e62649e42 100644 --- a/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs +++ b/codex-rs/codex-api/src/endpoint/realtime_websocket/methods.rs @@ -14,6 +14,7 @@ use crate::endpoint::realtime_websocket::protocol::SessionAudio; use crate::endpoint::realtime_websocket::protocol::SessionAudioFormat; use crate::endpoint::realtime_websocket::protocol::SessionAudioInput; use crate::endpoint::realtime_websocket::protocol::SessionAudioOutput; +use crate::endpoint::realtime_websocket::protocol::SessionAudioVoice; use crate::endpoint::realtime_websocket::protocol::SessionFunctionTool; use crate::endpoint::realtime_websocket::protocol::SessionUpdateSession; use crate::endpoint::realtime_websocket::protocol::parse_realtime_event; @@ -47,7 +48,6 @@ use tungstenite::protocol::WebSocketConfig; use url::Url; const REALTIME_AUDIO_SAMPLE_RATE: u32 = 24_000; -const REALTIME_AUDIO_VOICE: &str = "fathom"; const REALTIME_V1_SESSION_TYPE: &str = "quicksilver"; const REALTIME_V2_SESSION_TYPE: &str = "realtime"; const REALTIME_V2_CODEX_TOOL_NAME: &str = "codex"; @@ -353,13 +353,11 @@ impl RealtimeWebsocketWriter { RealtimeEventParser::V1 => REALTIME_V1_SESSION_TYPE.to_string(), RealtimeEventParser::RealtimeV2 => REALTIME_V2_SESSION_TYPE.to_string(), }; - ( - kind, - Some(instructions), - Some(SessionAudioOutput { - voice: REALTIME_AUDIO_VOICE.to_string(), - }), - ) + let voice = match self.event_parser { + RealtimeEventParser::V1 => SessionAudioVoice::Fathom, + RealtimeEventParser::RealtimeV2 => SessionAudioVoice::Alloy, + }; + (kind, Some(instructions), Some(SessionAudioOutput { voice })) } RealtimeSessionMode::Transcription => ("transcription".to_string(), None, None), }; @@ -1388,6 +1386,10 @@ mod tests { first_json["session"]["type"], Value::String("realtime".to_string()) ); + assert_eq!( + first_json["session"]["audio"]["output"]["voice"], + Value::String("alloy".to_string()) + ); assert_eq!( first_json["session"]["tools"][0]["type"], Value::String("function".to_string()) diff --git a/codex-rs/codex-api/src/endpoint/realtime_websocket/protocol.rs b/codex-rs/codex-api/src/endpoint/realtime_websocket/protocol.rs index 028f51cf3..73c2c1052 100644 --- a/codex-rs/codex-api/src/endpoint/realtime_websocket/protocol.rs +++ b/codex-rs/codex-api/src/endpoint/realtime_websocket/protocol.rs @@ -77,7 +77,15 @@ pub(super) struct SessionAudioFormat { #[derive(Debug, Clone, Serialize)] pub(super) struct SessionAudioOutput { - pub(super) voice: String, + pub(super) voice: SessionAudioVoice, +} + +#[derive(Debug, Clone, Copy, Serialize)] +pub(super) enum SessionAudioVoice { + #[serde(rename = "fathom")] + Fathom, + #[serde(rename = "alloy")] + Alloy, } #[derive(Debug, Clone, Serialize)]