Rename realtime start field to output modality

This commit is contained in:
Ahmed Ibrahim
2026-04-13 15:34:39 -07:00
parent d405279c72
commit 4d57fd1caa
26 changed files with 135 additions and 135 deletions
@@ -1499,7 +1499,7 @@
}
]
},
"RealtimeConnection": {
"RealtimeOutputModality": {
"enum": [
"text",
"audio"
@@ -10608,13 +10608,6 @@
}
]
},
"RealtimeConnection": {
"enum": [
"text",
"audio"
],
"type": "string"
},
"RealtimeConversationVersion": {
"enum": [
"v1",
@@ -10622,6 +10615,13 @@
],
"type": "string"
},
"RealtimeOutputModality": {
"enum": [
"text",
"audio"
],
"type": "string"
},
"RealtimeTranscriptUpdateKind": {
"enum": [
"delta",
@@ -7404,13 +7404,6 @@
}
]
},
"RealtimeConnection": {
"enum": [
"text",
"audio"
],
"type": "string"
},
"RealtimeConversationVersion": {
"enum": [
"v1",
@@ -7418,6 +7411,13 @@
],
"type": "string"
},
"RealtimeOutputModality": {
"enum": [
"text",
"audio"
],
"type": "string"
},
"RealtimeTranscriptUpdateKind": {
"enum": [
"delta",
@@ -2,4 +2,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RealtimeConnection = "text" | "audio";
export type RealtimeOutputModality = "text" | "audio";
@@ -48,8 +48,8 @@ export type { NetworkPolicyRuleAction } from "./NetworkPolicyRuleAction";
export type { ParsedCommand } from "./ParsedCommand";
export type { Personality } from "./Personality";
export type { PlanType } from "./PlanType";
export type { RealtimeConnection } from "./RealtimeConnection";
export type { RealtimeConversationVersion } from "./RealtimeConversationVersion";
export type { RealtimeOutputModality } from "./RealtimeOutputModality";
export type { RealtimeTranscriptUpdateKind } from "./RealtimeTranscriptUpdateKind";
export type { RealtimeVoice } from "./RealtimeVoice";
export type { RealtimeVoicesList } from "./RealtimeVoicesList";
@@ -1050,8 +1050,8 @@ mod tests {
use codex_protocol::ThreadId;
use codex_protocol::account::PlanType;
use codex_protocol::parse_command::ParsedCommand;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeVoice;
use codex_utils_absolute_path::AbsolutePathBuf;
use pretty_assertions::assert_eq;
@@ -1781,7 +1781,7 @@ mod tests {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("You are on a call".to_string())),
session_id: Some("sess_456".to_string()),
transport: None,
@@ -1794,7 +1794,7 @@ mod tests {
"id": 9,
"params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"prompt": "You are on a call",
"sessionId": "sess_456",
"transport": null,
@@ -1812,7 +1812,7 @@ mod tests {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
transport: None,
@@ -1825,7 +1825,7 @@ mod tests {
"id": 9,
"params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"sessionId": null,
"transport": null,
"voice": null
@@ -1838,7 +1838,7 @@ mod tests {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(None),
session_id: None,
transport: None,
@@ -1851,7 +1851,7 @@ mod tests {
"id": 9,
"params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"prompt": null,
"sessionId": null,
"transport": null,
@@ -1866,7 +1866,7 @@ mod tests {
"id": 9,
"params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"sessionId": null,
"transport": null,
"voice": null
@@ -1882,7 +1882,7 @@ mod tests {
"id": 9,
"params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"prompt": null,
"sessionId": null,
"transport": null,
@@ -1967,7 +1967,7 @@ mod tests {
request_id: RequestId::Integer(1),
params: v2::ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("You are on a call".to_string())),
session_id: None,
transport: None,
@@ -73,8 +73,8 @@ use codex_protocol::protocol::RateLimitSnapshot as CoreRateLimitSnapshot;
use codex_protocol::protocol::RateLimitWindow as CoreRateLimitWindow;
use codex_protocol::protocol::ReadOnlyAccess as CoreReadOnlyAccess;
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeTranscriptUpdateKind;
use codex_protocol::protocol::RealtimeVoice;
use codex_protocol::protocol::RealtimeVoicesList;
@@ -3963,7 +3963,7 @@ pub struct ThreadRealtimeStartParams {
pub thread_id: String,
/// Selects text or audio output for the realtime session. Transport and voice stay
/// independent so clients can choose how they connect separately from what the model emits.
pub connection: RealtimeConnection,
pub output_modality: RealtimeOutputModality,
#[serde(
default,
deserialize_with = "super::serde_helpers::deserialize_double_option",
+2 -2
View File
@@ -153,7 +153,7 @@ Example with notification opt-out:
- `turn/start` — add user input to a thread and begin Codex generation; responds with the initial `turn` object and streams `turn/started`, `item/*`, and `turn/completed` notifications. For `collaborationMode`, `settings.developer_instructions: null` means "use built-in instructions for the selected mode".
- `turn/steer` — add user input to an already in-flight regular turn without starting a new turn; returns the active `turnId` that accepted the input. Review and manual compaction turns reject `turn/steer`.
- `turn/interrupt` — request cancellation of an in-flight turn by `(thread_id, turn_id)`; success is an empty `{}` response and the turn finishes with `status: "interrupted"`.
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); pass `connection: "text"` or `connection: "audio"` to choose model output, returns `{}` and streams `thread/realtime/*` notifications. Omit `transport` for the websocket transport, or pass `{ "type": "webrtc", "sdp": "..." }` to create a WebRTC session from a browser-generated SDP offer; the remote answer SDP is emitted as `thread/realtime/sdp`.
- `thread/realtime/start` — start a thread-scoped realtime session (experimental); pass `outputModality: "text"` or `outputModality: "audio"` to choose model output, returns `{}` and streams `thread/realtime/*` notifications. Omit `transport` for the websocket transport, or pass `{ "type": "webrtc", "sdp": "..." }` to create a WebRTC session from a browser-generated SDP offer; the remote answer SDP is emitted as `thread/realtime/sdp`.
- `thread/realtime/appendAudio` — append an input audio chunk to the active realtime session (experimental); returns `{}`.
- `thread/realtime/appendText` — append text input to the active realtime session (experimental); returns `{}`.
- `thread/realtime/stop` — stop the active realtime session for the thread (experimental); returns `{}`.
@@ -608,7 +608,7 @@ Then send `offer.sdp` to app-server. Core uses `experimental_realtime_ws_backend
```json
{ "method": "thread/realtime/start", "id": 40, "params": {
"threadId": "thr_123",
"connection": "audio",
"outputModality": "audio",
"prompt": "You are on a call.",
"sessionId": null,
"transport": { "type": "webrtc", "sdp": "v=0\r\no=..." }
@@ -7163,7 +7163,7 @@ impl CodexMessageProcessor {
&request_id,
thread.as_ref(),
Op::RealtimeConversationStart(ConversationStartParams {
connection: params.connection,
output_modality: params.output_modality,
prompt: params.prompt,
session_id: params.session_id,
transport: params.transport.map(|transport| match transport {
@@ -17,7 +17,7 @@ use codex_app_server_protocol::ThreadRealtimeStartParams;
use codex_app_server_protocol::ThreadRealtimeStartTransport;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeOutputModality;
use pretty_assertions::assert_eq;
use std::path::Path;
use std::time::Duration;
@@ -77,7 +77,7 @@ async fn realtime_conversation_start_requires_experimental_api_capability() -> R
let request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("hello".to_string())),
session_id: None,
transport: None,
@@ -147,7 +147,7 @@ async fn realtime_webrtc_start_requires_experimental_api_capability() -> Result<
let request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: "thr_123".to_string(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("hello".to_string())),
session_id: None,
transport: Some(ThreadRealtimeStartTransport::Webrtc {
@@ -38,8 +38,8 @@ use codex_app_server_protocol::TurnCompletedNotification;
use codex_app_server_protocol::TurnStartedNotification;
use codex_features::FEATURES;
use codex_features::Feature;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeTranscriptUpdateKind;
use codex_protocol::protocol::RealtimeVoice;
use codex_protocol::protocol::RealtimeVoicesList;
@@ -303,7 +303,7 @@ impl RealtimeE2eHarness {
.mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: self.thread_id.clone(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: Some(ThreadRealtimeStartTransport::Webrtc {
@@ -530,7 +530,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_start.thread.id.clone(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
transport: None,
@@ -727,7 +727,7 @@ async fn realtime_conversation_streams_v2_notifications() -> Result<()> {
}
#[tokio::test]
async fn realtime_text_connection_requests_text_output_and_final_transcript() -> Result<()> {
async fn realtime_text_output_modality_requests_text_output_and_final_transcript() -> Result<()> {
skip_if_no_network!(Ok(()));
let responses_server = create_mock_responses_server_sequence_unchecked(Vec::new()).await;
@@ -777,7 +777,7 @@ async fn realtime_text_connection_requests_text_output_and_final_transcript() ->
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_start.thread.id.clone(),
connection: RealtimeConnection::Text,
output_modality: RealtimeOutputModality::Text,
prompt: None,
session_id: None,
transport: None,
@@ -942,7 +942,7 @@ async fn realtime_conversation_stop_emits_closed_notification() -> Result<()> {
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_start.thread.id.clone(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1039,7 +1039,7 @@ async fn realtime_webrtc_start_emits_sdp_notification() -> Result<()> {
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_id.clone(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: Some(ThreadRealtimeStartTransport::Webrtc {
@@ -1889,7 +1889,7 @@ async fn realtime_webrtc_start_surfaces_backend_error() -> Result<()> {
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_start.thread.id,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: Some(ThreadRealtimeStartTransport::Webrtc {
@@ -1948,7 +1948,7 @@ async fn realtime_conversation_requires_feature_flag() -> Result<()> {
let start_request_id = mcp
.send_thread_realtime_start_request(ThreadRealtimeStartParams {
thread_id: thread_start.thread.id.clone(),
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
+1 -1
View File
@@ -12,8 +12,8 @@ pub use memories::MemoriesClient;
pub use models::ModelsClient;
pub use realtime_call::RealtimeCallClient;
pub use realtime_call::RealtimeCallResponse;
pub use realtime_websocket::RealtimeConnection;
pub use realtime_websocket::RealtimeEventParser;
pub use realtime_websocket::RealtimeOutputModality;
pub use realtime_websocket::RealtimeSessionConfig;
pub use realtime_websocket::RealtimeSessionMode;
pub use realtime_websocket::RealtimeTranscriptUpdateKind;
@@ -218,8 +218,8 @@ fn decode_call_id_from_location(headers: &HeaderMap) -> Result<String, ApiError>
#[cfg(test)]
mod tests {
use super::*;
use crate::endpoint::realtime_websocket::RealtimeConnection;
use crate::endpoint::realtime_websocket::RealtimeEventParser;
use crate::endpoint::realtime_websocket::RealtimeOutputModality;
use crate::endpoint::realtime_websocket::RealtimeSessionMode;
use crate::provider::RetryConfig;
use async_trait::async_trait;
@@ -310,7 +310,7 @@ mod tests {
session_id: Some(session_id.to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Marin,
}
}
@@ -4,10 +4,10 @@ use crate::endpoint::realtime_websocket::methods_common::normalized_session_mode
use crate::endpoint::realtime_websocket::methods_common::session_update_session;
use crate::endpoint::realtime_websocket::methods_common::websocket_intent;
use crate::endpoint::realtime_websocket::protocol::RealtimeAudioFrame;
use crate::endpoint::realtime_websocket::protocol::RealtimeConnection;
use crate::endpoint::realtime_websocket::protocol::RealtimeEvent;
use crate::endpoint::realtime_websocket::protocol::RealtimeEventParser;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutboundMessage;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutputModality;
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionConfig;
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionMode;
use crate::endpoint::realtime_websocket::protocol::RealtimeTranscriptDelta;
@@ -309,7 +309,7 @@ impl RealtimeWebsocketWriter {
&self,
instructions: String,
session_mode: RealtimeSessionMode,
connection: RealtimeConnection,
output_modality: RealtimeOutputModality,
voice: RealtimeVoice,
) -> Result<(), ApiError> {
let session_mode = normalized_session_mode(self.event_parser, session_mode);
@@ -317,7 +317,7 @@ impl RealtimeWebsocketWriter {
self.event_parser,
instructions,
session_mode,
connection,
output_modality,
voice,
);
self.send_json(&RealtimeOutboundMessage::SessionUpdate { session })
@@ -628,7 +628,7 @@ impl RealtimeWebsocketClient {
.send_session_update(
config.instructions,
config.session_mode,
config.connection,
config.output_modality,
config.voice,
)
.await?;
@@ -1445,7 +1445,7 @@ mod tests {
session_id: Some("conv_1".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Breeze,
},
HeaderMap::new(),
@@ -1723,7 +1723,7 @@ mod tests {
session_id: Some("conv_1".to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cedar,
},
HeaderMap::new(),
@@ -1829,7 +1829,7 @@ mod tests {
session_id: Some("conv_1".to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Transcription,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Marin,
},
HeaderMap::new(),
@@ -1933,7 +1933,7 @@ mod tests {
session_id: Some("conv_1".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Transcription,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -2023,7 +2023,7 @@ mod tests {
session_id: Some("conv_1".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -6,9 +6,9 @@ use crate::endpoint::realtime_websocket::methods_v2::conversation_handoff_append
use crate::endpoint::realtime_websocket::methods_v2::conversation_item_create_message as v2_conversation_item_create_message;
use crate::endpoint::realtime_websocket::methods_v2::session_update_session as v2_session_update_session;
use crate::endpoint::realtime_websocket::methods_v2::websocket_intent as v2_websocket_intent;
use crate::endpoint::realtime_websocket::protocol::RealtimeConnection;
use crate::endpoint::realtime_websocket::protocol::RealtimeEventParser;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutboundMessage;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutputModality;
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionConfig;
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionMode;
use crate::endpoint::realtime_websocket::protocol::RealtimeVoice;
@@ -58,14 +58,14 @@ pub(super) fn session_update_session(
event_parser: RealtimeEventParser,
instructions: String,
session_mode: RealtimeSessionMode,
connection: RealtimeConnection,
output_modality: RealtimeOutputModality,
voice: RealtimeVoice,
) -> SessionUpdateSession {
let session_mode = normalized_session_mode(event_parser, session_mode);
match event_parser {
RealtimeEventParser::V1 => v1_session_update_session(instructions, voice),
RealtimeEventParser::RealtimeV2 => {
v2_session_update_session(instructions, session_mode, connection, voice)
v2_session_update_session(instructions, session_mode, output_modality, voice)
}
}
}
@@ -75,7 +75,7 @@ pub fn session_update_session_json(config: RealtimeSessionConfig) -> JsonResult<
config.event_parser,
config.instructions,
config.session_mode,
config.connection,
config.output_modality,
config.voice,
);
session.id = config.session_id;
@@ -8,8 +8,8 @@ use crate::endpoint::realtime_websocket::protocol::ConversationItemType;
use crate::endpoint::realtime_websocket::protocol::ConversationMessageItem;
use crate::endpoint::realtime_websocket::protocol::ConversationRole;
use crate::endpoint::realtime_websocket::protocol::NoiseReductionType;
use crate::endpoint::realtime_websocket::protocol::RealtimeConnection;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutboundMessage;
use crate::endpoint::realtime_websocket::protocol::RealtimeOutputModality;
use crate::endpoint::realtime_websocket::protocol::RealtimeSessionMode;
use crate::endpoint::realtime_websocket::protocol::RealtimeVoice;
use crate::endpoint::realtime_websocket::protocol::SessionAudio;
@@ -61,7 +61,7 @@ pub(super) fn conversation_handoff_append_message(
pub(super) fn session_update_session(
instructions: String,
session_mode: RealtimeSessionMode,
connection: RealtimeConnection,
output_modality: RealtimeOutputModality,
voice: RealtimeVoice,
) -> SessionUpdateSession {
match session_mode {
@@ -70,7 +70,7 @@ pub(super) fn session_update_session(
r#type: SessionType::Realtime,
model: None,
instructions: Some(instructions),
output_modalities: Some(vec![output_modality(connection).to_string()]),
output_modalities: Some(vec![output_modality_value(output_modality).to_string()]),
audio: SessionAudio {
input: SessionAudioInput {
format: SessionAudioFormat {
@@ -135,10 +135,10 @@ pub(super) fn session_update_session(
}
}
fn output_modality(connection: RealtimeConnection) -> &'static str {
match connection {
RealtimeConnection::Text => REALTIME_V2_OUTPUT_MODALITY_TEXT,
RealtimeConnection::Audio => REALTIME_V2_OUTPUT_MODALITY_AUDIO,
fn output_modality_value(output_modality: RealtimeOutputModality) -> &'static str {
match output_modality {
RealtimeOutputModality::Text => REALTIME_V2_OUTPUT_MODALITY_TEXT,
RealtimeOutputModality::Audio => REALTIME_V2_OUTPUT_MODALITY_AUDIO,
}
}
@@ -12,8 +12,8 @@ pub use methods::RealtimeWebsocketConnection;
pub use methods::RealtimeWebsocketEvents;
pub use methods::RealtimeWebsocketWriter;
pub use methods_common::session_update_session_json;
pub use protocol::RealtimeConnection;
pub use protocol::RealtimeEventParser;
pub use protocol::RealtimeOutputModality;
pub use protocol::RealtimeSessionConfig;
pub use protocol::RealtimeSessionMode;
pub use protocol::RealtimeTranscriptUpdateKind;
@@ -1,8 +1,8 @@
use crate::endpoint::realtime_websocket::protocol_v1::parse_realtime_event_v1;
use crate::endpoint::realtime_websocket::protocol_v2::parse_realtime_event_v2;
pub use codex_protocol::protocol::RealtimeAudioFrame;
pub use codex_protocol::protocol::RealtimeConnection;
pub use codex_protocol::protocol::RealtimeEvent;
pub use codex_protocol::protocol::RealtimeOutputModality;
pub use codex_protocol::protocol::RealtimeTranscriptDelta;
pub use codex_protocol::protocol::RealtimeTranscriptEntry;
pub use codex_protocol::protocol::RealtimeTranscriptUpdateKind;
@@ -29,7 +29,7 @@ pub struct RealtimeSessionConfig {
pub session_id: Option<String>,
pub event_parser: RealtimeEventParser,
pub session_mode: RealtimeSessionMode,
pub connection: RealtimeConnection,
pub output_modality: RealtimeOutputModality,
pub voice: RealtimeVoice,
}
+1 -1
View File
@@ -40,8 +40,8 @@ pub use crate::endpoint::MemoriesClient;
pub use crate::endpoint::ModelsClient;
pub use crate::endpoint::RealtimeCallClient;
pub use crate::endpoint::RealtimeCallResponse;
pub use crate::endpoint::RealtimeConnection;
pub use crate::endpoint::RealtimeEventParser;
pub use crate::endpoint::RealtimeOutputModality;
pub use crate::endpoint::RealtimeSessionConfig;
pub use crate::endpoint::RealtimeSessionMode;
pub use crate::endpoint::RealtimeTranscriptUpdateKind;
@@ -4,9 +4,9 @@ use std::time::Duration;
use codex_api::Provider;
use codex_api::RealtimeAudioFrame;
use codex_api::RealtimeConnection;
use codex_api::RealtimeEvent;
use codex_api::RealtimeEventParser;
use codex_api::RealtimeOutputModality;
use codex_api::RealtimeSessionConfig;
use codex_api::RealtimeSessionMode;
use codex_api::RealtimeWebsocketClient;
@@ -146,7 +146,7 @@ async fn realtime_ws_e2e_session_create_and_event_flow() {
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -250,7 +250,7 @@ async fn realtime_ws_connect_webrtc_sideband_retries_join_until_server_is_availa
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Marin,
},
"rtc_test",
@@ -322,7 +322,7 @@ async fn realtime_ws_e2e_send_while_next_event_waits() {
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -390,7 +390,7 @@ async fn realtime_ws_e2e_disconnected_emitted_once() {
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -454,7 +454,7 @@ async fn realtime_ws_e2e_ignores_unknown_text_events() {
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::V1,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Cove,
},
HeaderMap::new(),
@@ -521,7 +521,7 @@ async fn realtime_ws_e2e_realtime_v2_parser_emits_handoff_requested() {
session_id: Some("conv_123".to_string()),
event_parser: RealtimeEventParser::RealtimeV2,
session_mode: RealtimeSessionMode::Conversational,
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
voice: RealtimeVoice::Marin,
},
HeaderMap::new(),
+6 -6
View File
@@ -37,12 +37,12 @@ use codex_protocol::protocol::ConversationTextParams;
use codex_protocol::protocol::ErrorEvent;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationClosedEvent;
use codex_protocol::protocol::RealtimeConversationRealtimeEvent;
use codex_protocol::protocol::RealtimeConversationSdpEvent;
use codex_protocol::protocol::RealtimeConversationStartedEvent;
use codex_protocol::protocol::RealtimeHandoffRequested;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeVoice;
use codex_protocol::protocol::RealtimeVoicesList;
use http::HeaderMap;
@@ -598,7 +598,7 @@ async fn prepare_realtime_start(
sess,
params.prompt,
params.session_id,
params.connection,
params.output_modality,
params.voice,
)
.await?;
@@ -629,7 +629,7 @@ pub(crate) async fn build_realtime_session_config(
sess: &Arc<Session>,
prompt: Option<Option<String>>,
session_id: Option<String>,
connection: RealtimeConnection,
output_modality: RealtimeOutputModality,
voice: Option<RealtimeVoice>,
) -> CodexResult<RealtimeSessionConfig> {
let config = sess.get_config().await;
@@ -662,10 +662,10 @@ pub(crate) async fn build_realtime_session_config(
RealtimeWsVersion::V2 => RealtimeEventParser::RealtimeV2,
};
if config.realtime.version == RealtimeWsVersion::V1
&& matches!(connection, RealtimeConnection::Text)
&& matches!(output_modality, RealtimeOutputModality::Text)
{
return Err(CodexErr::InvalidRequest(
"text realtime connection requires realtime v2".to_string(),
"text realtime output modality requires realtime v2".to_string(),
));
}
let session_mode = match config.realtime.session_type {
@@ -682,7 +682,7 @@ pub(crate) async fn build_realtime_session_config(
session_id: Some(session_id.unwrap_or_else(|| sess.conversation_id.to_string())),
event_parser,
session_mode,
connection,
output_modality,
voice,
})
}
+2 -2
View File
@@ -15,9 +15,9 @@ use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::ItemCompletedEvent;
use codex_protocol::protocol::ItemStartedEvent;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationRealtimeEvent;
use codex_protocol::protocol::RealtimeEvent;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RolloutItem;
use codex_protocol::protocol::RolloutLine;
use codex_protocol::user_input::UserInput;
@@ -117,7 +117,7 @@ async fn start_remote_realtime_server() -> responses::WebSocketTestServer {
async fn start_realtime_conversation(codex: &codex_core::CodexThread) -> Result<()> {
codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -18,10 +18,10 @@ use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::InitialHistory;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::RealtimeAudioFrame;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationRealtimeEvent;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeEvent;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeVoice;
use codex_protocol::protocol::RolloutItem;
use codex_protocol::protocol::SessionSource;
@@ -248,7 +248,7 @@ async fn conversation_start_audio_text_close_round_trip() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -382,7 +382,7 @@ async fn conversation_start_defaults_to_v2_and_gpt_realtime_1_5() -> Result<()>
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -466,7 +466,7 @@ async fn conversation_webrtc_start_posts_generated_session() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: Some(ConversationStartTransport::Webrtc {
@@ -604,7 +604,7 @@ async fn conversation_start_uses_openai_env_key_fallback_with_chatgpt_auth() ->
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -666,7 +666,7 @@ async fn conversation_transport_close_emits_closed_event() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -752,7 +752,7 @@ async fn conversation_start_preflight_failure_emits_realtime_error_only() -> Res
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -796,7 +796,7 @@ async fn conversation_start_connect_failure_emits_realtime_error_only() -> Resul
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -887,7 +887,7 @@ async fn conversation_second_start_replaces_runtime() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("old".to_string())),
session_id: Some("conv_old".to_string()),
transport: None,
@@ -906,7 +906,7 @@ async fn conversation_second_start_replaces_runtime() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("new".to_string())),
session_id: Some("conv_new".to_string()),
transport: None,
@@ -996,7 +996,7 @@ async fn conversation_uses_experimental_realtime_ws_base_url_override() -> Resul
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1054,7 +1054,7 @@ async fn conversation_uses_default_realtime_backend_prompt() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
transport: None,
@@ -1120,7 +1120,7 @@ async fn conversation_uses_empty_instructions_for_null_or_empty_prompt() -> Resu
] {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt,
session_id: None,
transport: None,
@@ -1179,7 +1179,7 @@ async fn conversation_uses_explicit_start_voice() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1230,7 +1230,7 @@ async fn conversation_uses_configured_realtime_voice() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1269,7 +1269,7 @@ async fn conversation_rejects_voice_for_wrong_realtime_version() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1313,7 +1313,7 @@ async fn conversation_uses_experimental_realtime_ws_backend_prompt_override() ->
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("prompt from op".to_string())),
session_id: None,
transport: None,
@@ -1379,7 +1379,7 @@ async fn conversation_uses_experimental_realtime_ws_startup_context_override() -
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("prompt from op".to_string())),
session_id: None,
transport: None,
@@ -1443,7 +1443,7 @@ async fn conversation_disables_realtime_startup_context_with_empty_override() ->
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("prompt from op".to_string())),
session_id: None,
transport: None,
@@ -1500,7 +1500,7 @@ async fn conversation_start_injects_startup_context_from_thread_history() -> Res
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1612,7 +1612,7 @@ async fn conversation_startup_context_current_thread_selects_many_turns_by_budge
codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1717,7 +1717,7 @@ async fn conversation_startup_context_falls_back_to_workspace_map() -> Result<()
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1772,7 +1772,7 @@ async fn conversation_startup_context_is_truncated_and_sent_once_per_start() ->
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1848,7 +1848,7 @@ async fn conversation_user_text_turn_is_sent_to_realtime_when_active() -> Result
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -1981,7 +1981,7 @@ async fn conversation_mirrors_assistant_message_text_to_realtime_handoff() -> Re
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2111,7 +2111,7 @@ async fn conversation_handoff_persists_across_item_done_until_turn_complete() ->
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2256,7 +2256,7 @@ async fn inbound_handoff_request_starts_turn() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2354,7 +2354,7 @@ async fn inbound_handoff_request_uses_active_transcript() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2450,7 +2450,7 @@ async fn inbound_handoff_request_clears_active_transcript_after_each_handoff() -
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2553,7 +2553,7 @@ async fn inbound_conversation_item_does_not_start_turn_and_still_forwards_audio(
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2669,7 +2669,7 @@ async fn delegated_turn_user_role_echo_does_not_redelegate_and_still_forwards_au
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2815,7 +2815,7 @@ async fn inbound_handoff_request_does_not_block_realtime_event_forwarding() -> R
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -2946,7 +2946,7 @@ async fn inbound_handoff_request_steers_active_turn() -> Result<()> {
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
@@ -3098,7 +3098,7 @@ async fn inbound_handoff_request_starts_turn_and_does_not_block_realtime_audio()
test.codex
.submit(Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("backend prompt".to_string())),
session_id: None,
transport: None,
+12 -12
View File
@@ -135,7 +135,7 @@ pub struct McpServerRefreshConfig {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, TS)]
pub struct ConversationStartParams {
/// Selects whether the realtime session should produce text or audio output.
pub connection: RealtimeConnection,
pub output_modality: RealtimeOutputModality,
#[serde(
default,
deserialize_with = "conversation_start_prompt_serde::deserialize",
@@ -161,7 +161,7 @@ pub enum ConversationStartTransport {
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "snake_case")]
pub enum RealtimeConnection {
pub enum RealtimeOutputModality {
Text,
Audio,
}
@@ -4603,14 +4603,14 @@ mod tests {
},
});
let start = Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("be helpful".to_string())),
session_id: Some("conv_1".to_string()),
transport: None,
voice: None,
});
let webrtc_start = Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(Some("be helpful".to_string())),
session_id: Some("conv_1".to_string()),
transport: Some(ConversationStartTransport::Webrtc {
@@ -4623,14 +4623,14 @@ mod tests {
});
let close = Op::RealtimeConversationClose;
let default_prompt_start = Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
transport: None,
voice: None,
});
let null_prompt_start = Op::RealtimeConversationStart(ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: Some(None),
session_id: None,
transport: None,
@@ -4642,7 +4642,7 @@ mod tests {
serde_json::to_value(&start).unwrap(),
json!({
"type": "realtime_conversation_start",
"connection": "audio",
"output_modality": "audio",
"prompt": "be helpful",
"session_id": "conv_1"
})
@@ -4651,21 +4651,21 @@ mod tests {
serde_json::to_value(&default_prompt_start).unwrap(),
json!({
"type": "realtime_conversation_start",
"connection": "audio"
"output_modality": "audio"
})
);
assert_eq!(
serde_json::to_value(&null_prompt_start).unwrap(),
json!({
"type": "realtime_conversation_start",
"connection": "audio",
"output_modality": "audio",
"prompt": null
})
);
assert_eq!(
serde_json::from_value::<Op>(json!({
"type": "realtime_conversation_start",
"connection": "audio"
"output_modality": "audio"
}))
.unwrap(),
default_prompt_start
@@ -4673,7 +4673,7 @@ mod tests {
assert_eq!(
serde_json::from_value::<Op>(json!({
"type": "realtime_conversation_start",
"connection": "audio",
"output_modality": "audio",
"prompt": null
}))
.unwrap(),
@@ -4719,7 +4719,7 @@ mod tests {
serde_json::to_value(&webrtc_start).unwrap(),
json!({
"type": "realtime_conversation_start",
"connection": "audio",
"output_modality": "audio",
"prompt": "be helpful",
"session_id": "conv_1",
"transport": {
+1 -1
View File
@@ -657,7 +657,7 @@ impl AppServerSession {
request_id,
params: ThreadRealtimeStartParams {
thread_id: thread_id.to_string(),
connection: params.connection,
output_modality: params.output_modality,
prompt: params.prompt,
session_id: params.session_id,
voice: params.voice,
+2 -2
View File
@@ -3,11 +3,11 @@ use codex_config::config_toml::RealtimeTransport;
use codex_protocol::protocol::ConversationStartParams;
use codex_protocol::protocol::ConversationStartTransport;
use codex_protocol::protocol::RealtimeAudioFrame;
use codex_protocol::protocol::RealtimeConnection;
use codex_protocol::protocol::RealtimeConversationClosedEvent;
use codex_protocol::protocol::RealtimeConversationRealtimeEvent;
use codex_protocol::protocol::RealtimeConversationStartedEvent;
use codex_protocol::protocol::RealtimeEvent;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_realtime_webrtc::RealtimeWebrtcEvent;
use codex_realtime_webrtc::RealtimeWebrtcSession;
use codex_realtime_webrtc::RealtimeWebrtcSessionHandle;
@@ -237,7 +237,7 @@ impl ChatWidget {
) {
self.submit_op(AppCommand::realtime_conversation_start(
ConversationStartParams {
connection: RealtimeConnection::Audio,
output_modality: RealtimeOutputModality::Audio,
prompt: None,
session_id: None,
transport,