1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize, de};
4use serde_json::Value;
5
6use super::super::common::*;
7use super::{
8 ResponseContentPart, ResponseObject, ResponseOutputItem, ResponseReasoningSummaryPart,
9};
10
11#[derive(Debug, Clone, PartialEq)]
12pub enum ResponseStreamEvent {
13 Known(KnownResponseStreamEvent),
14 Unknown(UnknownResponseStreamEvent),
15}
16
17impl Serialize for ResponseStreamEvent {
18 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
19 where
20 S: serde::Serializer,
21 {
22 match self {
23 Self::Known(event) => event.serialize(serializer),
24 Self::Unknown(event) => event.serialize(serializer),
25 }
26 }
27}
28
29impl<'de> Deserialize<'de> for ResponseStreamEvent {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where
32 D: serde::Deserializer<'de>,
33 {
34 let value = Value::deserialize(deserializer)?;
35 let Some(type_name) = value.get("type").and_then(Value::as_str) else {
36 return serde_json::from_value(value)
37 .map(Self::Unknown)
38 .map_err(de::Error::custom);
39 };
40
41 let event_type =
42 serde_json::from_value::<ResponseStreamEventType>(Value::String(type_name.to_owned()))
43 .map_err(de::Error::custom)?;
44
45 match event_type {
46 ResponseStreamEventType::Known(_) => serde_json::from_value(value)
47 .map(Self::Known)
48 .map_err(de::Error::custom),
49 ResponseStreamEventType::Unknown(_) => serde_json::from_value(value)
50 .map(Self::Unknown)
51 .map_err(de::Error::custom),
52 }
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57#[serde(tag = "type")]
58pub enum KnownResponseStreamEvent {
59 #[serde(rename = "response.created")]
60 ResponseCreated {
61 response: Box<ResponseObject>,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 sequence_number: Option<u64>,
64 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
65 extra: Extra,
66 },
67 #[serde(rename = "response.in_progress")]
68 ResponseInProgress {
69 response: Box<ResponseObject>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 sequence_number: Option<u64>,
72 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
73 extra: Extra,
74 },
75 #[serde(rename = "response.completed")]
76 ResponseCompleted {
77 response: Box<ResponseObject>,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 sequence_number: Option<u64>,
80 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
81 extra: Extra,
82 },
83 #[serde(rename = "response.failed")]
84 ResponseFailed {
85 response: Box<ResponseObject>,
86 #[serde(skip_serializing_if = "Option::is_none")]
87 sequence_number: Option<u64>,
88 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
89 extra: Extra,
90 },
91 #[serde(rename = "response.incomplete")]
92 ResponseIncomplete {
93 response: Box<ResponseObject>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 sequence_number: Option<u64>,
96 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
97 extra: Extra,
98 },
99 #[serde(rename = "response.queued")]
100 ResponseQueued {
101 response: Box<ResponseObject>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 sequence_number: Option<u64>,
104 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
105 extra: Extra,
106 },
107 #[serde(rename = "response.output_item.added")]
108 ResponseOutputItemAdded {
109 item: Box<ResponseOutputItem>,
110 output_index: u32,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 sequence_number: Option<u64>,
113 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
114 extra: Extra,
115 },
116 #[serde(rename = "response.output_item.done")]
117 ResponseOutputItemDone {
118 item: Box<ResponseOutputItem>,
119 output_index: u32,
120 #[serde(skip_serializing_if = "Option::is_none")]
121 sequence_number: Option<u64>,
122 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
123 extra: Extra,
124 },
125 #[serde(rename = "response.content_part.added")]
126 ResponseContentPartAdded {
127 content_index: u32,
128 item_id: String,
129 output_index: u32,
130 part: ResponseContentPart,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 sequence_number: Option<u64>,
133 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
134 extra: Extra,
135 },
136 #[serde(rename = "response.content_part.done")]
137 ResponseContentPartDone {
138 content_index: u32,
139 item_id: String,
140 output_index: u32,
141 part: ResponseContentPart,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 sequence_number: Option<u64>,
144 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
145 extra: Extra,
146 },
147 #[serde(rename = "response.output_text.delta")]
148 ResponseOutputTextDelta {
149 content_index: u32,
150 delta: String,
151 item_id: String,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 logprobs: Option<Vec<StreamTokenLogprob>>,
154 output_index: u32,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 sequence_number: Option<u64>,
157 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
158 extra: Extra,
159 },
160 #[serde(rename = "response.output_text.done")]
161 ResponseOutputTextDone {
162 content_index: u32,
163 item_id: String,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 logprobs: Option<Vec<StreamTokenLogprob>>,
166 output_index: u32,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 sequence_number: Option<u64>,
169 text: String,
170 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
171 extra: Extra,
172 },
173 #[serde(rename = "response.output_text.annotation.added")]
174 ResponseOutputTextAnnotationAdded {
175 annotation: Value,
176 annotation_index: u32,
177 content_index: u32,
178 item_id: String,
179 output_index: u32,
180 #[serde(skip_serializing_if = "Option::is_none")]
181 sequence_number: Option<u64>,
182 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
183 extra: Extra,
184 },
185 #[serde(rename = "response.function_call_arguments.delta")]
186 ResponseFunctionCallArgumentsDelta {
187 delta: String,
188 item_id: String,
189 output_index: u32,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 sequence_number: Option<u64>,
192 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
193 extra: Extra,
194 },
195 #[serde(rename = "response.function_call_arguments.done")]
196 ResponseFunctionCallArgumentsDone {
197 arguments: String,
198 item_id: String,
199 name: String,
200 output_index: u32,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 sequence_number: Option<u64>,
203 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
204 extra: Extra,
205 },
206 #[serde(rename = "response.custom_tool_call_input.delta")]
207 ResponseCustomToolCallInputDelta {
208 delta: String,
209 item_id: String,
210 output_index: u32,
211 #[serde(skip_serializing_if = "Option::is_none")]
212 sequence_number: Option<u64>,
213 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
214 extra: Extra,
215 },
216 #[serde(rename = "response.custom_tool_call_input.done")]
217 ResponseCustomToolCallInputDone {
218 input: String,
219 item_id: String,
220 output_index: u32,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 sequence_number: Option<u64>,
223 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
224 extra: Extra,
225 },
226 #[serde(rename = "response.refusal.delta")]
227 ResponseRefusalDelta {
228 content_index: u32,
229 delta: String,
230 item_id: String,
231 output_index: u32,
232 #[serde(skip_serializing_if = "Option::is_none")]
233 sequence_number: Option<u64>,
234 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
235 extra: Extra,
236 },
237 #[serde(rename = "response.refusal.done")]
238 ResponseRefusalDone {
239 content_index: u32,
240 item_id: String,
241 output_index: u32,
242 refusal: String,
243 #[serde(skip_serializing_if = "Option::is_none")]
244 sequence_number: Option<u64>,
245 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
246 extra: Extra,
247 },
248 #[serde(rename = "response.reasoning_summary_part.added")]
249 ResponseReasoningSummaryPartAdded {
250 item_id: String,
251 output_index: u32,
252 part: ResponseReasoningSummaryPart,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 sequence_number: Option<u64>,
255 summary_index: u32,
256 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
257 extra: Extra,
258 },
259 #[serde(rename = "response.reasoning_summary_part.done")]
260 ResponseReasoningSummaryPartDone {
261 item_id: String,
262 output_index: u32,
263 part: ResponseReasoningSummaryPart,
264 #[serde(skip_serializing_if = "Option::is_none")]
265 sequence_number: Option<u64>,
266 summary_index: u32,
267 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
268 extra: Extra,
269 },
270 #[serde(rename = "response.reasoning_summary_text.delta")]
271 ResponseReasoningSummaryTextDelta {
272 delta: String,
273 item_id: String,
274 output_index: u32,
275 #[serde(skip_serializing_if = "Option::is_none")]
276 sequence_number: Option<u64>,
277 summary_index: u32,
278 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
279 extra: Extra,
280 },
281 #[serde(rename = "response.reasoning_summary_text.done")]
282 ResponseReasoningSummaryTextDone {
283 item_id: String,
284 output_index: u32,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 sequence_number: Option<u64>,
287 summary_index: u32,
288 text: String,
289 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
290 extra: Extra,
291 },
292 #[serde(rename = "response.reasoning_text.delta")]
293 ResponseReasoningTextDelta {
294 content_index: u32,
295 delta: String,
296 item_id: String,
297 output_index: u32,
298 #[serde(skip_serializing_if = "Option::is_none")]
299 sequence_number: Option<u64>,
300 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
301 extra: Extra,
302 },
303 #[serde(rename = "response.reasoning_text.done")]
304 ResponseReasoningTextDone {
305 content_index: u32,
306 item_id: String,
307 output_index: u32,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 sequence_number: Option<u64>,
310 text: String,
311 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
312 extra: Extra,
313 },
314 #[serde(rename = "response.audio.delta")]
315 ResponseAudioDelta {
316 delta: String,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 sequence_number: Option<u64>,
319 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
320 extra: Extra,
321 },
322 #[serde(rename = "response.audio.done")]
323 ResponseAudioDone {
324 #[serde(skip_serializing_if = "Option::is_none")]
325 sequence_number: Option<u64>,
326 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
327 extra: Extra,
328 },
329 #[serde(rename = "response.audio.transcript.delta")]
330 ResponseAudioTranscriptDelta {
331 delta: String,
332 #[serde(skip_serializing_if = "Option::is_none")]
333 sequence_number: Option<u64>,
334 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
335 extra: Extra,
336 },
337 #[serde(rename = "response.audio.transcript.done")]
338 ResponseAudioTranscriptDone {
339 #[serde(skip_serializing_if = "Option::is_none")]
340 sequence_number: Option<u64>,
341 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
342 extra: Extra,
343 },
344 #[serde(rename = "response.image_generation_call.completed")]
345 ResponseImageGenerationCallCompleted {
346 item_id: String,
347 output_index: u32,
348 #[serde(skip_serializing_if = "Option::is_none")]
349 sequence_number: Option<u64>,
350 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
351 extra: Extra,
352 },
353 #[serde(rename = "response.image_generation_call.generating")]
354 ResponseImageGenerationCallGenerating {
355 item_id: String,
356 output_index: u32,
357 #[serde(skip_serializing_if = "Option::is_none")]
358 sequence_number: Option<u64>,
359 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
360 extra: Extra,
361 },
362 #[serde(rename = "response.image_generation_call.in_progress")]
363 ResponseImageGenerationCallInProgress {
364 item_id: String,
365 output_index: u32,
366 #[serde(skip_serializing_if = "Option::is_none")]
367 sequence_number: Option<u64>,
368 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
369 extra: Extra,
370 },
371 #[serde(rename = "response.image_generation_call.partial_image")]
372 ResponseImageGenerationCallPartialImage {
373 item_id: String,
374 output_index: u32,
375 partial_image_b64: String,
376 partial_image_index: u32,
377 #[serde(skip_serializing_if = "Option::is_none")]
378 sequence_number: Option<u64>,
379 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
380 extra: Extra,
381 },
382 #[serde(rename = "response.file_search_call.in_progress")]
383 ResponseFileSearchCallInProgress {
384 item_id: String,
385 output_index: u32,
386 #[serde(skip_serializing_if = "Option::is_none")]
387 sequence_number: Option<u64>,
388 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
389 extra: Extra,
390 },
391 #[serde(rename = "response.file_search_call.searching")]
392 ResponseFileSearchCallSearching {
393 item_id: String,
394 output_index: u32,
395 #[serde(skip_serializing_if = "Option::is_none")]
396 sequence_number: Option<u64>,
397 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
398 extra: Extra,
399 },
400 #[serde(rename = "response.file_search_call.completed")]
401 ResponseFileSearchCallCompleted {
402 item_id: String,
403 output_index: u32,
404 #[serde(skip_serializing_if = "Option::is_none")]
405 sequence_number: Option<u64>,
406 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
407 extra: Extra,
408 },
409 #[serde(rename = "response.web_search_call.in_progress")]
410 ResponseWebSearchCallInProgress {
411 item_id: String,
412 output_index: u32,
413 #[serde(skip_serializing_if = "Option::is_none")]
414 sequence_number: Option<u64>,
415 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
416 extra: Extra,
417 },
418 #[serde(rename = "response.web_search_call.searching")]
419 ResponseWebSearchCallSearching {
420 item_id: String,
421 output_index: u32,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 sequence_number: Option<u64>,
424 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
425 extra: Extra,
426 },
427 #[serde(rename = "response.web_search_call.completed")]
428 ResponseWebSearchCallCompleted {
429 item_id: String,
430 output_index: u32,
431 #[serde(skip_serializing_if = "Option::is_none")]
432 sequence_number: Option<u64>,
433 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
434 extra: Extra,
435 },
436 #[serde(rename = "response.code_interpreter_call.in_progress")]
437 ResponseCodeInterpreterCallInProgress {
438 item_id: String,
439 output_index: u32,
440 #[serde(skip_serializing_if = "Option::is_none")]
441 sequence_number: Option<u64>,
442 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
443 extra: Extra,
444 },
445 #[serde(rename = "response.code_interpreter_call.interpreting")]
446 ResponseCodeInterpreterCallInterpreting {
447 item_id: String,
448 output_index: u32,
449 #[serde(skip_serializing_if = "Option::is_none")]
450 sequence_number: Option<u64>,
451 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
452 extra: Extra,
453 },
454 #[serde(rename = "response.code_interpreter_call.completed")]
455 ResponseCodeInterpreterCallCompleted {
456 item_id: String,
457 output_index: u32,
458 #[serde(skip_serializing_if = "Option::is_none")]
459 sequence_number: Option<u64>,
460 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
461 extra: Extra,
462 },
463 #[serde(rename = "response.code_interpreter_call_code.delta")]
464 ResponseCodeInterpreterCallCodeDelta {
465 delta: String,
466 item_id: String,
467 output_index: u32,
468 #[serde(skip_serializing_if = "Option::is_none")]
469 sequence_number: Option<u64>,
470 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
471 extra: Extra,
472 },
473 #[serde(rename = "response.code_interpreter_call_code.done")]
474 ResponseCodeInterpreterCallCodeDone {
475 code: String,
476 item_id: String,
477 output_index: u32,
478 #[serde(skip_serializing_if = "Option::is_none")]
479 sequence_number: Option<u64>,
480 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
481 extra: Extra,
482 },
483 #[serde(rename = "response.mcp_call_arguments.delta")]
484 ResponseMcpCallArgumentsDelta {
485 delta: String,
486 item_id: String,
487 output_index: u32,
488 #[serde(skip_serializing_if = "Option::is_none")]
489 sequence_number: Option<u64>,
490 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
491 extra: Extra,
492 },
493 #[serde(rename = "response.mcp_call_arguments.done")]
494 ResponseMcpCallArgumentsDone {
495 arguments: String,
496 item_id: String,
497 output_index: u32,
498 #[serde(skip_serializing_if = "Option::is_none")]
499 sequence_number: Option<u64>,
500 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
501 extra: Extra,
502 },
503 #[serde(rename = "response.mcp_call.in_progress")]
504 ResponseMcpCallInProgress {
505 item_id: String,
506 output_index: u32,
507 #[serde(skip_serializing_if = "Option::is_none")]
508 sequence_number: Option<u64>,
509 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
510 extra: Extra,
511 },
512 #[serde(rename = "response.mcp_call.completed")]
513 ResponseMcpCallCompleted {
514 item_id: String,
515 output_index: u32,
516 #[serde(skip_serializing_if = "Option::is_none")]
517 sequence_number: Option<u64>,
518 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
519 extra: Extra,
520 },
521 #[serde(rename = "response.mcp_call.failed")]
522 ResponseMcpCallFailed {
523 item_id: String,
524 output_index: u32,
525 #[serde(skip_serializing_if = "Option::is_none")]
526 sequence_number: Option<u64>,
527 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
528 extra: Extra,
529 },
530 #[serde(rename = "response.mcp_list_tools.in_progress")]
531 ResponseMcpListToolsInProgress {
532 item_id: String,
533 output_index: u32,
534 #[serde(skip_serializing_if = "Option::is_none")]
535 sequence_number: Option<u64>,
536 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
537 extra: Extra,
538 },
539 #[serde(rename = "response.mcp_list_tools.completed")]
540 ResponseMcpListToolsCompleted {
541 item_id: String,
542 output_index: u32,
543 #[serde(skip_serializing_if = "Option::is_none")]
544 sequence_number: Option<u64>,
545 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
546 extra: Extra,
547 },
548 #[serde(rename = "response.mcp_list_tools.failed")]
549 ResponseMcpListToolsFailed {
550 item_id: String,
551 output_index: u32,
552 #[serde(skip_serializing_if = "Option::is_none")]
553 sequence_number: Option<u64>,
554 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
555 extra: Extra,
556 },
557 #[serde(rename = "error")]
558 Error {
559 code: String,
560 message: String,
561 param: String,
562 #[serde(skip_serializing_if = "Option::is_none")]
563 sequence_number: Option<u64>,
564 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
565 extra: Extra,
566 },
567}
568
569#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
570pub struct UnknownResponseStreamEvent {
571 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
572 pub type_: Option<ResponseStreamEventType>,
573 #[serde(skip_serializing_if = "Option::is_none")]
574 pub sequence_number: Option<u64>,
575 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
576 pub extra: Extra,
577}