Skip to main content

gproxy_protocol/wire/openai/realtime/
response.rs

1//! Native Realtime wire DTOs. Source definitions are cited on each object.
2//! Verified with Realtime.md and openai-python snapshot
3//! e12b81d3bbf644ec7045e152d69bc4b68d69cd48 (2026-09-13).
4//! https://github.com/openai/openai-python/tree/e12b81d3bbf644ec7045e152d69bc4b68d69cd48/src/openai/types/realtime
5use super::wire::present_nullable;
6use super::{ConversationItem, Metadata, RealtimeAudioFormats};
7use crate::Rest;
8use serde::{Deserialize, Serialize};
9
10/// Source: `openai/types/realtime/realtime_response.py`, `RealtimeResponse`.
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
12#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
13#[derive(gproxy_protocol_macros::DeclaredFields)]
14pub struct RealtimeResponse {
15    #[serde(
16        default,
17        deserialize_with = "present_nullable",
18        skip_serializing_if = "Option::is_none"
19    )]
20    pub id: Option<Option<String>>,
21    #[serde(
22        default,
23        deserialize_with = "present_nullable",
24        skip_serializing_if = "Option::is_none"
25    )]
26    pub audio: Option<Option<RealtimeResponseAudio>>,
27    #[serde(
28        default,
29        deserialize_with = "present_nullable",
30        skip_serializing_if = "Option::is_none"
31    )]
32    pub conversation_id: Option<Option<String>>,
33    #[serde(
34        default,
35        deserialize_with = "present_nullable",
36        skip_serializing_if = "Option::is_none"
37    )]
38    pub max_output_tokens: Option<Option<RealtimeResponseMaxOutputTokens>>,
39    #[serde(
40        default,
41        deserialize_with = "present_nullable",
42        skip_serializing_if = "Option::is_none"
43    )]
44    pub metadata: Option<Option<Metadata>>,
45    #[serde(
46        default,
47        deserialize_with = "present_nullable",
48        skip_serializing_if = "Option::is_none"
49    )]
50    pub object: Option<Option<RealtimeResponseObject>>,
51    #[serde(
52        default,
53        deserialize_with = "present_nullable",
54        skip_serializing_if = "Option::is_none"
55    )]
56    pub output: Option<Option<Vec<ConversationItem>>>,
57    #[serde(
58        default,
59        deserialize_with = "present_nullable",
60        skip_serializing_if = "Option::is_none"
61    )]
62    pub output_modalities: Option<Option<Vec<RealtimeResponseOutputModalitiesItem>>>,
63    #[serde(
64        default,
65        deserialize_with = "present_nullable",
66        skip_serializing_if = "Option::is_none"
67    )]
68    pub status: Option<Option<RealtimeResponseStatusValue>>,
69    #[serde(
70        default,
71        deserialize_with = "present_nullable",
72        skip_serializing_if = "Option::is_none"
73    )]
74    pub status_details: Option<Option<RealtimeResponseStatus>>,
75    #[serde(
76        default,
77        deserialize_with = "present_nullable",
78        skip_serializing_if = "Option::is_none"
79    )]
80    pub usage: Option<Option<RealtimeResponseUsage>>,
81    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
82    pub rest: Rest,
83}
84
85/// Source: `openai/types/realtime/realtime_response.py`, `Audio`.
86#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
87#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
88#[derive(gproxy_protocol_macros::DeclaredFields)]
89pub struct RealtimeResponseAudio {
90    #[serde(
91        default,
92        deserialize_with = "present_nullable",
93        skip_serializing_if = "Option::is_none"
94    )]
95    pub output: Option<Option<RealtimeResponseAudioOutput>>,
96    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
97    pub rest: Rest,
98}
99
100/// Source: `openai/types/realtime/realtime_response_status.py`, `RealtimeResponseStatus`.
101#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
102#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
103#[derive(gproxy_protocol_macros::DeclaredFields)]
104pub struct RealtimeResponseStatus {
105    #[serde(
106        default,
107        deserialize_with = "present_nullable",
108        skip_serializing_if = "Option::is_none"
109    )]
110    pub error: Option<Option<RealtimeResponseStatusError>>,
111    #[serde(
112        default,
113        deserialize_with = "present_nullable",
114        skip_serializing_if = "Option::is_none"
115    )]
116    pub reason: Option<Option<RealtimeResponseStatusReason>>,
117    #[serde(rename = "type")]
118    #[serde(
119        default,
120        deserialize_with = "present_nullable",
121        skip_serializing_if = "Option::is_none"
122    )]
123    pub type_: Option<Option<RealtimeResponseStatusType>>,
124    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
125    pub rest: Rest,
126}
127
128/// Source: `openai/types/realtime/realtime_response_usage.py`, `RealtimeResponseUsage`.
129#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
130#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
131#[derive(gproxy_protocol_macros::DeclaredFields)]
132pub struct RealtimeResponseUsage {
133    #[serde(
134        default,
135        deserialize_with = "present_nullable",
136        skip_serializing_if = "Option::is_none"
137    )]
138    pub input_token_details: Option<Option<RealtimeResponseUsageInputTokenDetails>>,
139    #[serde(
140        default,
141        deserialize_with = "present_nullable",
142        skip_serializing_if = "Option::is_none"
143    )]
144    pub input_tokens: Option<Option<i64>>,
145    #[serde(
146        default,
147        deserialize_with = "present_nullable",
148        skip_serializing_if = "Option::is_none"
149    )]
150    pub output_token_details: Option<Option<RealtimeResponseUsageOutputTokenDetails>>,
151    #[serde(
152        default,
153        deserialize_with = "present_nullable",
154        skip_serializing_if = "Option::is_none"
155    )]
156    pub output_tokens: Option<Option<i64>>,
157    #[serde(
158        default,
159        deserialize_with = "present_nullable",
160        skip_serializing_if = "Option::is_none"
161    )]
162    pub total_tokens: Option<Option<i64>>,
163    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
164    pub rest: Rest,
165}
166
167/// Source: `openai/types/realtime/realtime_response.py`, `AudioOutput`.
168#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
169#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
170#[derive(gproxy_protocol_macros::DeclaredFields)]
171pub struct RealtimeResponseAudioOutput {
172    #[serde(
173        default,
174        deserialize_with = "present_nullable",
175        skip_serializing_if = "Option::is_none"
176    )]
177    pub format: Option<Option<RealtimeAudioFormats>>,
178    #[serde(
179        default,
180        deserialize_with = "present_nullable",
181        skip_serializing_if = "Option::is_none"
182    )]
183    pub voice: Option<Option<String>>,
184    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
185    pub rest: Rest,
186}
187
188/// Source: `openai/types/realtime/realtime_response_status.py`, `Error`.
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
190#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
191#[derive(gproxy_protocol_macros::DeclaredFields)]
192pub struct RealtimeResponseStatusError {
193    #[serde(
194        default,
195        deserialize_with = "present_nullable",
196        skip_serializing_if = "Option::is_none"
197    )]
198    pub code: Option<Option<String>>,
199    #[serde(rename = "type")]
200    #[serde(
201        default,
202        deserialize_with = "present_nullable",
203        skip_serializing_if = "Option::is_none"
204    )]
205    pub type_: Option<Option<String>>,
206    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
207    pub rest: Rest,
208}
209
210/// Source: `openai/types/realtime/realtime_response_usage_input_token_details.py`, `RealtimeResponseUsageInputTokenDetails`.
211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
212#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
213#[derive(gproxy_protocol_macros::DeclaredFields)]
214pub struct RealtimeResponseUsageInputTokenDetails {
215    #[serde(
216        default,
217        deserialize_with = "present_nullable",
218        skip_serializing_if = "Option::is_none"
219    )]
220    pub audio_tokens: Option<Option<i64>>,
221    #[serde(
222        default,
223        deserialize_with = "present_nullable",
224        skip_serializing_if = "Option::is_none"
225    )]
226    pub cached_tokens: Option<Option<i64>>,
227    #[serde(
228        default,
229        deserialize_with = "present_nullable",
230        skip_serializing_if = "Option::is_none"
231    )]
232    pub cached_tokens_details:
233        Option<Option<RealtimeResponseUsageInputTokenDetailsCachedTokensDetails>>,
234    #[serde(
235        default,
236        deserialize_with = "present_nullable",
237        skip_serializing_if = "Option::is_none"
238    )]
239    pub image_tokens: Option<Option<i64>>,
240    #[serde(
241        default,
242        deserialize_with = "present_nullable",
243        skip_serializing_if = "Option::is_none"
244    )]
245    pub text_tokens: Option<Option<i64>>,
246    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
247    pub rest: Rest,
248}
249
250/// Source: `openai/types/realtime/realtime_response_usage_output_token_details.py`, `RealtimeResponseUsageOutputTokenDetails`.
251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
252#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
253#[derive(gproxy_protocol_macros::DeclaredFields)]
254pub struct RealtimeResponseUsageOutputTokenDetails {
255    #[serde(
256        default,
257        deserialize_with = "present_nullable",
258        skip_serializing_if = "Option::is_none"
259    )]
260    pub audio_tokens: Option<Option<i64>>,
261    #[serde(
262        default,
263        deserialize_with = "present_nullable",
264        skip_serializing_if = "Option::is_none"
265    )]
266    pub text_tokens: Option<Option<i64>>,
267    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
268    pub rest: Rest,
269}
270
271/// Source: `openai/types/realtime/realtime_response_usage_input_token_details.py`, `CachedTokensDetails`.
272#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
273#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
274#[derive(gproxy_protocol_macros::DeclaredFields)]
275pub struct RealtimeResponseUsageInputTokenDetailsCachedTokensDetails {
276    #[serde(
277        default,
278        deserialize_with = "present_nullable",
279        skip_serializing_if = "Option::is_none"
280    )]
281    pub audio_tokens: Option<Option<i64>>,
282    #[serde(
283        default,
284        deserialize_with = "present_nullable",
285        skip_serializing_if = "Option::is_none"
286    )]
287    pub image_tokens: Option<Option<i64>>,
288    #[serde(
289        default,
290        deserialize_with = "present_nullable",
291        skip_serializing_if = "Option::is_none"
292    )]
293    pub text_tokens: Option<Option<i64>>,
294    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
295    pub rest: Rest,
296}
297
298#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
299#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
300#[derive(gproxy_protocol_macros::DeclaredFields)]
301pub enum RealtimeResponseMaxOutputTokensVariant2 {
302    #[serde(rename = "inf")]
303    Inf,
304}
305
306#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
307#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
308#[serde(untagged)]
309#[derive(gproxy_protocol_macros::DeclaredFields)]
310pub enum RealtimeResponseMaxOutputTokens {
311    Number(i64),
312    Literal(RealtimeResponseMaxOutputTokensVariant2),
313}
314
315#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
316#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
317#[derive(gproxy_protocol_macros::DeclaredFields)]
318pub enum RealtimeResponseObject {
319    #[serde(rename = "realtime.response")]
320    RealtimeResponse,
321}
322
323#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
324#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
325#[derive(gproxy_protocol_macros::DeclaredFields)]
326pub enum RealtimeResponseOutputModalitiesItem {
327    #[serde(rename = "text")]
328    Text,
329    #[serde(rename = "audio")]
330    Audio,
331}
332
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
334#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
335#[derive(gproxy_protocol_macros::DeclaredFields)]
336pub enum RealtimeResponseStatusValue {
337    #[serde(rename = "completed")]
338    Completed,
339    #[serde(rename = "cancelled")]
340    Cancelled,
341    #[serde(rename = "failed")]
342    Failed,
343    #[serde(rename = "incomplete")]
344    Incomplete,
345    #[serde(rename = "in_progress")]
346    InProgress,
347}
348
349#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
350#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
351#[derive(gproxy_protocol_macros::DeclaredFields)]
352pub enum RealtimeResponseStatusReason {
353    #[serde(rename = "turn_detected")]
354    TurnDetected,
355    #[serde(rename = "client_cancelled")]
356    ClientCancelled,
357    #[serde(rename = "max_output_tokens")]
358    MaxOutputTokens,
359    #[serde(rename = "content_filter")]
360    ContentFilter,
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
364#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
365#[derive(gproxy_protocol_macros::DeclaredFields)]
366pub enum RealtimeResponseStatusType {
367    #[serde(rename = "completed")]
368    Completed,
369    #[serde(rename = "cancelled")]
370    Cancelled,
371    #[serde(rename = "incomplete")]
372    Incomplete,
373    #[serde(rename = "failed")]
374    Failed,
375}