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