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 Text,
141 Audio,
142}
143
144#[derive(Debug, Serialize, Deserialize, Clone)]
145pub struct ItemContent {
146 pub r#type: ItemContentType,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub text: Option<String>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub audio: Option<String>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub transcript: Option<String>,
153}
154
155#[derive(Debug, Serialize, Deserialize, Clone, Default)]
156pub struct Item {
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub id: Option<String>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub r#type: Option<ItemType>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub status: Option<ItemStatus>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub role: Option<ItemRole>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub content: Option<Vec<ItemContent>>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub call_id: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub name: Option<String>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub arguments: Option<String>,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub output: Option<String>,
175}
176
177impl TryFrom<serde_json::Value> for Item {
178 type Error = serde_json::Error;
179
180 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
181 serde_json::from_value(value)
182 }
183}
184
185#[derive(Debug, Serialize, Deserialize, Clone)]
186pub struct APIError {
187 pub r#type: String,
188 pub code: Option<String>,
189 pub message: String,
190 pub param: Option<String>,
191 pub event_id: Option<String>,
192}
193
194#[derive(Debug, Serialize, Deserialize, Clone)]
195pub struct Conversation {
196 pub id: String,
197 pub object: String,
198}
199
200#[derive(Debug, Serialize, Deserialize, Clone)]
201pub struct Response {
202 pub id: String,
203 pub object: String,
204 pub status: ResponseStatus,
205 pub status_details: Option<ResponseStatusDetail>,
206 pub output: Vec<Item>,
207 pub usage: Option<Usage>,
208}
209
210#[derive(Debug, Serialize, Deserialize, Clone)]
211pub struct Usage {
212 pub total_tokens: u32,
213 pub input_tokens: u32,
214 pub output_tokens: u32,
215}
216
217#[derive(Debug, Serialize, Deserialize, Clone)]
218#[serde(rename_all = "snake_case")]
219pub enum ResponseStatus {
220 InProgress,
221 Completed,
222 Cancelled,
223 Failed,
224 Incomplete,
225}
226
227#[derive(Debug, Serialize, Deserialize, Clone)]
228#[serde(tag = "type")]
229pub enum ResponseStatusDetail {
230 #[serde(rename = "cancelled")]
231 Cancelled { reason: CancelledReason },
232 #[serde(rename = "incomplete")]
233 Incomplete { reason: IncompleteReason },
234 #[serde(rename = "failed")]
235 Failed { error: Option<FailedError> },
236}
237
238#[derive(Debug, Serialize, Deserialize, Clone)]
239pub struct FailedError {
240 pub code: Option<String>,
241 pub message: Option<String>,
242 pub r#type: Option<String>,
243}
244
245#[derive(Debug, Serialize, Deserialize, Clone)]
246#[serde(rename_all = "snake_case")]
247pub enum CancelledReason {
248 TurnDetected,
249 ClientCancelled,
250}
251
252#[derive(Debug, Serialize, Deserialize, Clone)]
253#[serde(rename_all = "snake_case")]
254pub enum IncompleteReason {
255 Interruption,
256 MaxOutputTokens,
257 ContentFilter,
258}
259
260#[derive(Debug, Serialize, Deserialize, Clone)]
261#[serde(tag = "type")]
262pub enum ContentPart {
263 #[serde(rename = "text")]
264 Text { text: String },
265 #[serde(rename = "audio")]
266 Audio {
267 audio: Option<String>,
268 transcript: String,
269 },
270}
271
272#[derive(Debug, Serialize, Deserialize, Clone)]
273pub struct RateLimit {
274 pub name: String,
275 pub limit: u32,
276 pub remaining: u32,
277 pub reset_seconds: f32,
278}