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
2026-06-12 18:11:13 +00:00
committed by GitHub
parent 94427aaf46
commit 6652e82dd0
22 changed files with 521 additions and 11 deletions
@@ -1993,6 +1993,13 @@
],
"type": "object"
},
"RealtimeConversationArchitecture": {
"enum": [
"realtimeapi",
"avas"
],
"type": "string"
},
"RealtimeConversationVersion": {
"enum": [
"v1",
@@ -13799,6 +13799,13 @@
"title": "RawResponseItemCompletedNotification",
"type": "object"
},
"RealtimeConversationArchitecture": {
"enum": [
"realtimeapi",
"avas"
],
"type": "string"
},
"RealtimeConversationVersion": {
"enum": [
"v1",
@@ -10272,6 +10272,13 @@
"title": "RawResponseItemCompletedNotification",
"type": "object"
},
"RealtimeConversationArchitecture": {
"enum": [
"realtimeapi",
"avas"
],
"type": "string"
},
"RealtimeConversationVersion": {
"enum": [
"v1",
@@ -0,0 +1,5 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type RealtimeConversationArchitecture = "realtimeapi" | "avas";
+1
View File
@@ -51,6 +51,7 @@ export type { NetworkPolicyRuleAction } from "./NetworkPolicyRuleAction";
export type { ParsedCommand } from "./ParsedCommand";
export type { Personality } from "./Personality";
export type { PlanType } from "./PlanType";
export type { RealtimeConversationArchitecture } from "./RealtimeConversationArchitecture";
export type { RealtimeConversationVersion } from "./RealtimeConversationVersion";
export type { RealtimeOutputModality } from "./RealtimeOutputModality";
export type { RealtimeVoice } from "./RealtimeVoice";
@@ -1647,6 +1647,7 @@ mod tests {
use codex_protocol::account::PlanType;
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_READ_ONLY;
use codex_protocol::parse_command::ParsedCommand;
use codex_protocol::protocol::RealtimeConversationArchitecture;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeVoice;
@@ -3012,6 +3013,7 @@ mod tests {
let request = ClientRequest::ThreadRealtimeStart {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
architecture: Some(RealtimeConversationArchitecture::Avas),
thread_id: "thr_123".to_string(),
model: Some("realtime-treatment-model".to_string()),
output_modality: RealtimeOutputModality::Audio,
@@ -3027,6 +3029,7 @@ mod tests {
"method": "thread/realtime/start",
"id": 9,
"params": {
"architecture": "avas",
"threadId": "thr_123",
"model": "realtime-treatment-model",
"outputModality": "audio",
@@ -3047,6 +3050,7 @@ mod tests {
let default_prompt_request = ClientRequest::ThreadRealtimeStart {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
architecture: None,
thread_id: "thr_123".to_string(),
model: None,
output_modality: RealtimeOutputModality::Audio,
@@ -3062,6 +3066,7 @@ mod tests {
"method": "thread/realtime/start",
"id": 9,
"params": {
"architecture": null,
"threadId": "thr_123",
"model": null,
"outputModality": "audio",
@@ -3077,6 +3082,7 @@ mod tests {
let null_prompt_request = ClientRequest::ThreadRealtimeStart {
request_id: RequestId::Integer(9),
params: v2::ThreadRealtimeStartParams {
architecture: None,
thread_id: "thr_123".to_string(),
model: None,
output_modality: RealtimeOutputModality::Audio,
@@ -3092,6 +3098,7 @@ mod tests {
"method": "thread/realtime/start",
"id": 9,
"params": {
"architecture": null,
"threadId": "thr_123",
"model": null,
"outputModality": "audio",
@@ -3250,6 +3257,7 @@ mod tests {
let request = ClientRequest::ThreadRealtimeStart {
request_id: RequestId::Integer(1),
params: v2::ThreadRealtimeStartParams {
architecture: None,
thread_id: "thr_123".to_string(),
model: None,
output_modality: RealtimeOutputModality::Audio,
@@ -1,4 +1,5 @@
use codex_protocol::protocol::RealtimeAudioFrame as CoreRealtimeAudioFrame;
use codex_protocol::protocol::RealtimeConversationArchitecture;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_protocol::protocol::RealtimeOutputModality;
use codex_protocol::protocol::RealtimeVoice;
@@ -65,6 +66,9 @@ impl From<ThreadRealtimeAudioChunk> for CoreRealtimeAudioFrame {
#[ts(export_to = "v2/")]
pub struct ThreadRealtimeStartParams {
pub thread_id: String,
/// Overrides the configured realtime architecture for this session only.
#[ts(optional = nullable)]
pub architecture: Option<RealtimeConversationArchitecture>,
/// Overrides the configured realtime model for this session only.
#[ts(optional = nullable)]
pub model: Option<String>,