1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Serialize, Deserialize, Clone, Default)]
4pub struct Session {
5 #[serde(skip_serializing_if = "Option::is_none")]
6 pub modalities: Option<Vec<String>>,
7 #[serde(skip_serializing_if = "Option::is_none")]
8 pub instructions: Option<String>,
9 #[serde(skip_serializing_if = "Option::is_none")]
10 pub voice: Option<RealtimeVoice>,
11 #[serde(skip_serializing_if = "Option::is_none")]
12 pub input_audio_format: Option<AudioFormat>,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub output_audio_format: Option<AudioFormat>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub input_audio_transcription: Option<AudioTranscription>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub turn_detection: Option<TurnDetection>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub tools: Option<Vec<ToolDefinition>>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub tool_choice: Option<ToolChoice>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub temperature: Option<f32>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub max_output_tokens: Option<MaxOutputTokens>,
27}
28
29#[derive(Debug, Serialize, Deserialize, Clone)]
30#[serde(rename_all = "lowercase")]
31pub enum RealtimeVoice {
32 Alloy,
33 Ash,
34 Ballad,
35 Coral,
36 Echo,
37 Sage,
38 Shimmer,
39 Verse,
40}
41
42#[derive(Debug, Serialize, Deserialize, Clone)]
43pub enum AudioFormat {
44 #[serde(rename = "pcm16")]
45 PCM16,
46 #[serde(rename = "g711_ulaw")]
47 G711ULAW,
48 #[serde(rename = "g711_alaw")]
49 G711ALAW,
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone)]
53pub struct AudioTranscription {
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub language: Option<String>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub model: Option<String>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub prompt: Option<String>,
60}
61
62#[derive(Debug, Serialize, Deserialize, Clone)]
63#[serde(tag = "type")]
64pub enum TurnDetection {
65 #[serde(rename = "server_vad")]
66 ServerVAD {
67 threshold: f32,
68 prefix_padding_ms: u32,
69 silence_duration_ms: u32,
70 },
71}
72
73#[derive(Debug, Serialize, Deserialize, Clone)]
74#[serde(tag = "type")]
75pub enum ToolDefinition {
76 #[serde(rename = "function")]
77 Function {
78 name: String,
79 description: String,
80 parameters: serde_json::Value,
81 },
82}
83
84#[derive(Debug, Serialize, Deserialize, Clone)]
85#[serde(rename_all = "lowercase")]
86pub enum ToolChoice {
87 Auto,
88 None,
89 Required,
90 #[serde(untagged)]
91 Function {
92 r#type: FunctionType,
93 name: String,
94 },
95}
96
97#[derive(Debug, Serialize, Deserialize, Clone)]
98#[serde(rename_all = "lowercase")]
99pub enum FunctionType {
100 Function,
101}
102
103#[derive(Debug, Serialize, Deserialize, Clone)]
104#[serde(untagged)]
105pub enum MaxOutputTokens {
106 Num(u16),
107 #[serde(rename = "inf")]
108 Inf,
109}
110
111#[derive(Debug, Serialize, Deserialize, Clone)]
112#[serde(rename_all = "snake_case")]
113pub enum ItemType {
114 Message,
115 FunctionCall,
116 FunctionCallOutput,
117}
118
119#[derive(Debug, Serialize, Deserialize, Clone)]
120#[serde(rename_all = "snake_case")]
121pub enum ItemStatus {
122 Completed,
123 InProgress,
124 Incomplete,
125}
126
127#[derive(Debug, Serialize, Deserialize, Clone)]
128#[serde(rename_all = "lowercase")]
129pub enum ItemRole {
130 User,
131 Assistant,
132 System,
133}
134
135#[derive(Debug, Serialize, Deserialize, Clone)]
136#[serde(rename_all = "snake_case")]
137pub enum ItemContentType {
138 InputText,
139 InputAudio,
140 InputImage,
141 Text,
142 Audio,
143}
144
145#[derive(Debug, Serialize, Deserialize, Clone)]
146pub struct ItemContent {
147 pub r#type: ItemContentType,
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub text: Option<String>,
150 #[serde(skip_serializing_if = "Option::is_none")]
151 pub audio: Option<String>,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub transcript: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub image_url: Option<String>,
156}
157
158#[derive(Debug, Serialize, Deserialize, Clone, Default)]
159pub struct Item {
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub id: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub r#type: Option<ItemType>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub status: Option<ItemStatus>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub role: Option<ItemRole>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub content: Option<Vec<ItemContent>>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub call_id: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub name: Option<String>,
174 #[serde(skip_serializing_if = "Option::is_none")]
175 pub arguments: Option<String>,
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub output: Option<String>,
178}
179
180impl TryFrom<serde_json::Value> for Item {
181 type Error = serde_json::Error;
182
183 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
184 serde_json::from_value(value)
185 }
186}
187
188#[derive(Debug, Serialize, Deserialize, Clone)]
189pub struct APIError {
190 pub r#type: String,
191 pub code: Option<String>,
192 pub message: String,
193 pub param: Option<String>,
194 pub event_id: Option<String>,
195}
196
197#[derive(Debug, Serialize, Deserialize, Clone)]
198pub struct Conversation {
199 pub id: String,
200 pub object: String,
201}
202
203#[derive(Debug, Serialize, Deserialize, Clone)]
204pub struct Response {
205 pub id: String,
206 pub object: String,
207 pub status: ResponseStatus,
208 pub status_details: Option<ResponseStatusDetail>,
209 pub output: Vec<Item>,
210 pub usage: Option<Usage>,
211}
212
213#[derive(Debug, Serialize, Deserialize, Clone)]
214pub struct Usage {
215 pub total_tokens: u32,
216 pub input_tokens: u32,
217 pub output_tokens: u32,
218}
219
220#[derive(Debug, Serialize, Deserialize, Clone)]
221#[serde(rename_all = "snake_case")]
222pub enum ResponseStatus {
223 InProgress,
224 Completed,
225 Cancelled,
226 Failed,
227 Incomplete,
228}
229
230#[derive(Debug, Serialize, Deserialize, Clone)]
231#[serde(tag = "type")]
232pub enum ResponseStatusDetail {
233 #[serde(rename = "cancelled")]
234 Cancelled { reason: CancelledReason },
235 #[serde(rename = "incomplete")]
236 Incomplete { reason: IncompleteReason },
237 #[serde(rename = "failed")]
238 Failed { error: Option<FailedError> },
239}
240
241#[derive(Debug, Serialize, Deserialize, Clone)]
242pub struct FailedError {
243 pub code: Option<String>,
244 pub message: Option<String>,
245 pub r#type: Option<String>,
246}
247
248#[derive(Debug, Serialize, Deserialize, Clone)]
249#[serde(rename_all = "snake_case")]
250pub enum CancelledReason {
251 TurnDetected,
252 ClientCancelled,
253}
254
255#[derive(Debug, Serialize, Deserialize, Clone)]
256#[serde(rename_all = "snake_case")]
257pub enum IncompleteReason {
258 Interruption,
259 MaxOutputTokens,
260 ContentFilter,
261}
262
263#[derive(Debug, Serialize, Deserialize, Clone)]
264#[serde(tag = "type")]
265pub enum ContentPart {
266 #[serde(rename = "text")]
267 Text { text: String },
268 #[serde(rename = "audio")]
269 Audio {
270 audio: Option<String>,
271 transcript: String,
272 },
273}
274
275#[derive(Debug, Serialize, Deserialize, Clone)]
276pub struct RateLimit {
277 pub name: String,
278 pub limit: u32,
279 pub remaining: u32,
280 pub reset_seconds: f32,
281}