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 pub enabled: bool,
55 pub model: String,
56}
57
58#[derive(Debug, Serialize, Deserialize, Clone)]
59#[serde(tag = "type")]
60pub enum TurnDetection {
61 #[serde(rename = "server_vad")]
62 ServerVAD {
63 threshold: f32,
64 prefix_padding_ms: u32,
65 silence_duration_ms: u32,
66 },
67}
68
69#[derive(Debug, Serialize, Deserialize, Clone)]
70#[serde(tag = "type")]
71pub enum ToolDefinition {
72 #[serde(rename = "function")]
73 Function {
74 name: String,
75 description: String,
76 parameters: serde_json::Value,
77 },
78}
79
80#[derive(Debug, Serialize, Deserialize, Clone)]
81#[serde(rename_all = "lowercase")]
82pub enum ToolChoice {
83 Auto,
84 None,
85 Required,
86 #[serde(untagged)]
87 Function {
88 r#type: FunctionType,
89 name: String,
90 },
91}
92
93#[derive(Debug, Serialize, Deserialize, Clone)]
94#[serde(rename_all = "lowercase")]
95pub enum FunctionType {
96 Function,
97}
98
99#[derive(Debug, Serialize, Deserialize, Clone)]
100#[serde(untagged)]
101pub enum MaxOutputTokens {
102 Num(u16),
103 #[serde(rename = "inf")]
104 Inf,
105}
106
107#[derive(Debug, Serialize, Deserialize, Clone)]
108#[serde(rename_all = "snake_case")]
109pub enum ItemType {
110 Message,
111 FunctionCall,
112 FunctionCallOutput,
113}
114
115#[derive(Debug, Serialize, Deserialize, Clone)]
116#[serde(rename_all = "snake_case")]
117pub enum ItemStatus {
118 Completed,
119 InProgress,
120 Incomplete,
121}
122
123#[derive(Debug, Serialize, Deserialize, Clone)]
124#[serde(rename_all = "lowercase")]
125pub enum ItemRole {
126 User,
127 Assistant,
128 System,
129}
130
131#[derive(Debug, Serialize, Deserialize, Clone)]
132#[serde(rename_all = "snake_case")]
133pub enum ItemContentType {
134 InputText,
135 InputAudio,
136 Text,
137 Audio,
138}
139
140#[derive(Debug, Serialize, Deserialize, Clone)]
141pub struct ItemContent {
142 pub r#type: ItemContentType,
143 #[serde(skip_serializing_if = "Option::is_none")]
144 pub text: Option<String>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub audio: Option<String>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub transcript: Option<String>,
149}
150
151#[derive(Debug, Serialize, Deserialize, Clone, Default)]
152pub struct Item {
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub id: Option<String>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub r#type: Option<ItemType>,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub status: Option<ItemStatus>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub role: Option<ItemRole>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub content: Option<Vec<ItemContent>>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub call_id: Option<String>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub name: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub arguments: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub output: Option<String>,
171}
172
173impl TryFrom<serde_json::Value> for Item {
174 type Error = serde_json::Error;
175
176 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
177 serde_json::from_value(value)
178 }
179}
180
181#[derive(Debug, Serialize, Deserialize, Clone)]
182pub struct APIError {
183 pub r#type: String,
184 pub code: Option<String>,
185 pub message: String,
186 pub param: Option<String>,
187 pub event_id: Option<String>,
188}
189
190#[derive(Debug, Serialize, Deserialize, Clone)]
191pub struct Conversation {
192 pub id: String,
193 pub object: String,
194}
195
196#[derive(Debug, Serialize, Deserialize, Clone)]
197pub struct Response {
198 pub id: String,
199 pub object: String,
200 pub status: ResponseStatus,
201 pub status_details: Option<ResponseStatusDetail>,
202 pub output: Vec<Item>,
203 pub usage: Option<Usage>,
204}
205
206#[derive(Debug, Serialize, Deserialize, Clone)]
207pub struct Usage {
208 pub total_tokens: u32,
209 pub input_tokens: u32,
210 pub output_tokens: u32,
211}
212
213#[derive(Debug, Serialize, Deserialize, Clone)]
214#[serde(rename_all = "snake_case")]
215pub enum ResponseStatus {
216 InProgress,
217 Completed,
218 Cancelled,
219 Failed,
220 Incomplete,
221}
222
223#[derive(Debug, Serialize, Deserialize, Clone)]
224#[serde(tag = "type")]
225pub enum ResponseStatusDetail {
226 #[serde(rename = "cancelled")]
227 Cancelled { reason: CancelledReason },
228 #[serde(rename = "incomplete")]
229 Incomplete { reason: IncompleteReason },
230 #[serde(rename = "failed")]
231 Failed { error: Option<FailedError> },
232}
233
234#[derive(Debug, Serialize, Deserialize, Clone)]
235pub struct FailedError {
236 pub code: String,
237 pub message: String,
238}
239
240#[derive(Debug, Serialize, Deserialize, Clone)]
241#[serde(rename_all = "snake_case")]
242pub enum CancelledReason {
243 TurnDetected,
244 ClientCancelled,
245}
246
247#[derive(Debug, Serialize, Deserialize, Clone)]
248#[serde(rename_all = "snake_case")]
249pub enum IncompleteReason {
250 Interruption,
251 MaxOutputTokens,
252 ContentFilter,
253}
254
255#[derive(Debug, Serialize, Deserialize, Clone)]
256#[serde(tag = "type")]
257pub enum ContentPart {
258 #[serde(rename = "text")]
259 Text { text: String },
260 #[serde(rename = "audio")]
261 Audio {
262 audio: Option<String>,
263 transcript: String,
264 },
265}
266
267#[derive(Debug, Serialize, Deserialize, Clone)]
268pub struct RateLimit {
269 pub name: String,
270 pub limit: u32,
271 pub remaining: u32,
272 pub reset_seconds: f32,
273}