realtime: add AVAS architecture override (#27720)

## Summary

Adds a `RealtimeConversationArchitecture` option for realtime
conversation startup, with `realtimeapi` as the default and `avas` as an
opt-in architecture.

The AVAS path is limited to realtime v1 conversational WebRTC starts,
and WebRTC call creation appends `intent=quicksilver&architecture=avas`
to `/v1/realtime/calls`. The existing sideband websocket still joins by
`call_id`.

This also exposes the per-session architecture override through
app-server v2 `thread/realtime/start` params and updates the config
schema for `[realtime].architecture`.

## Validation

- `just fmt`
- `just write-config-schema`
- `just test -p codex-api sends_avas_session_call_query_params`
- `just test -p codex-core -E
'test(~conversation_webrtc_start_uses_avas_architecture_query)'`
- `just test -p codex-core -E 'test(realtime_loads_from_config_toml)'`
- `just test -p codex-app-server-protocol -E
'test(~serialize_thread_realtime_start) |
test(generated_ts_optional_nullable_fields_only_in_params)'`
- `just test -p codex-app-server -E
'test(realtime_webrtc_start_emits_sdp_notification)'`
This commit is contained in:
Peter Bakkum authored and GitHub committed 2026-06-12 18:11:13 +00:00
1 parent 94427aaf46
commit 6652e82dd0
22 files changed
+521 -11

No files matched your search

+13 -5
View File
@@ -77,6 +77,7 @@ use codex_protocol::models::ResponseItem;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
use codex_protocol::protocol::InternalSessionSource;
use codex_protocol::protocol::RealtimeConversationArchitecture;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::W3cTraceContext;
use codex_rollout_trace::CompactionTraceContext;
@@ -522,7 +523,9 @@ impl ModelClient {
&self,
sdp: String,
session_config: ApiRealtimeSessionConfig,
architecture: RealtimeConversationArchitecture,
mut extra_headers: ApiHeaderMap,
api_provider_override: Option<ApiProvider>,
) -> Result<RealtimeWebrtcCallStart> {
// Create the media call over HTTP first, then retain matching auth so realtime can attach
// the server-side control WebSocket to the call id from that HTTP response.
@@ -535,11 +538,16 @@ impl ModelClient {
client_setup.api_auth.as_ref(),
));
let transport = ReqwestTransport::new(build_reqwest_client());
let response =
ApiRealtimeCallClient::new(transport, client_setup.api_provider, client_setup.api_auth)
.create_with_session_and_headers(sdp, session_config, extra_headers)
.await
.map_err(map_api_error)?;
let api_provider = api_provider_override.unwrap_or(client_setup.api_provider);
let response = ApiRealtimeCallClient::new(transport, api_provider, client_setup.api_auth)
.create_with_session_architecture_and_headers(
sdp,
session_config,
architecture,
extra_headers,
)
.await
.map_err(map_api_error)?;
Ok(RealtimeWebrtcCallStart {
sdp: response.sdp,
call_id: response.call_id,