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 ResponseStreamEvent {
18 pub fn event_name(&self) -> Option<&str> {
20 match self {
21 Self::Known(event) => Some(event.event_name()),
22 Self::Unknown(event) => event.type_.as_ref().map(ResponseStreamEventType::as_str),
23 }
24 }
25}
26
27impl Serialize for ResponseStreamEvent {
28 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
29 where
30 S: serde::Serializer,
31 {
32 match self {
33 Self::Known(event) => event.serialize(serializer),
34 Self::Unknown(event) => event.serialize(serializer),
35 }
36 }
37}
38
39impl<'de> Deserialize<'de> for ResponseStreamEvent {
40 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
41 where
42 D: serde::Deserializer<'de>,
43 {
44 let value = Value::deserialize(deserializer)?;
45 let Some(type_name) = value.get("type").and_then(Value::as_str) else {
46 return serde_json::from_value(value)
47 .map(Self::Unknown)
48 .map_err(de::Error::custom);
49 };
50
51 let event_type =
52 serde_json::from_value::<ResponseStreamEventType>(Value::String(type_name.to_owned()))
53 .map_err(de::Error::custom)?;
54
55 match event_type {
56 ResponseStreamEventType::Known(_) => serde_json::from_value(value)
57 .map(Self::Known)
58 .map_err(de::Error::custom),
59 ResponseStreamEventType::Unknown(_) => serde_json::from_value(value)
60 .map(Self::Unknown)
61 .map_err(de::Error::custom),
62 }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67#[serde(tag = "type")]
68pub enum KnownResponseStreamEvent {
69 #[serde(rename = "response.created")]
70 ResponseCreated {
71 response: Box<ResponseObject>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 sequence_number: Option<u64>,
74 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
75 extra: Extra,
76 },
77 #[serde(rename = "response.in_progress")]
78 ResponseInProgress {
79 response: Box<ResponseObject>,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 sequence_number: Option<u64>,
82 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
83 extra: Extra,
84 },
85 #[serde(rename = "response.completed")]
86 ResponseCompleted {
87 response: Box<ResponseObject>,
88 #[serde(skip_serializing_if = "Option::is_none")]
89 sequence_number: Option<u64>,
90 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
91 extra: Extra,
92 },
93 #[serde(rename = "response.failed")]
94 ResponseFailed {
95 response: Box<ResponseObject>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 sequence_number: Option<u64>,
98 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
99 extra: Extra,
100 },
101 #[serde(rename = "response.incomplete")]
102 ResponseIncomplete {
103 response: Box<ResponseObject>,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 sequence_number: Option<u64>,
106 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
107 extra: Extra,
108 },
109 #[serde(rename = "response.queued")]
110 ResponseQueued {
111 response: Box<ResponseObject>,
112 #[serde(skip_serializing_if = "Option::is_none")]
113 sequence_number: Option<u64>,
114 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
115 extra: Extra,
116 },
117 #[serde(rename = "response.output_item.added")]
118 ResponseOutputItemAdded {
119 item: Box<ResponseOutputItem>,
120 output_index: u32,
121 #[serde(skip_serializing_if = "Option::is_none")]
122 sequence_number: Option<u64>,
123 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
124 extra: Extra,
125 },
126 #[serde(rename = "response.output_item.done")]
127 ResponseOutputItemDone {
128 item: Box<ResponseOutputItem>,
129 output_index: u32,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 sequence_number: Option<u64>,
132 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
133 extra: Extra,
134 },
135 #[serde(rename = "response.content_part.added")]
136 ResponseContentPartAdded {
137 content_index: u32,
138 item_id: String,
139 output_index: u32,
140 part: ResponseContentPart,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 sequence_number: Option<u64>,
143 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
144 extra: Extra,
145 },
146 #[serde(rename = "response.content_part.done")]
147 ResponseContentPartDone {
148 content_index: u32,
149 item_id: String,
150 output_index: u32,
151 part: ResponseContentPart,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 sequence_number: Option<u64>,
154 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
155 extra: Extra,
156 },
157 #[serde(rename = "response.output_text.delta")]
158 ResponseOutputTextDelta {
159 content_index: u32,
160 delta: String,
161 item_id: String,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 logprobs: Option<Vec<StreamTokenLogprob>>,
164 output_index: u32,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 sequence_number: Option<u64>,
167 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
168 extra: Extra,
169 },
170 #[serde(rename = "response.output_text.done")]
171 ResponseOutputTextDone {
172 content_index: u32,
173 item_id: String,
174 #[serde(skip_serializing_if = "Option::is_none")]
175 logprobs: Option<Vec<StreamTokenLogprob>>,
176 output_index: u32,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 sequence_number: Option<u64>,
179 text: String,
180 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
181 extra: Extra,
182 },
183 #[serde(rename = "response.output_text.annotation.added")]
184 ResponseOutputTextAnnotationAdded {
185 annotation: Value,
186 annotation_index: u32,
187 content_index: u32,
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.delta")]
196 ResponseFunctionCallArgumentsDelta {
197 delta: String,
198 item_id: String,
199 output_index: u32,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 sequence_number: Option<u64>,
202 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
203 extra: Extra,
204 },
205 #[serde(rename = "response.function_call_arguments.done")]
206 ResponseFunctionCallArgumentsDone {
207 arguments: String,
208 item_id: String,
209 name: 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.delta")]
217 ResponseCustomToolCallInputDelta {
218 delta: 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.custom_tool_call_input.done")]
227 ResponseCustomToolCallInputDone {
228 input: String,
229 item_id: String,
230 output_index: u32,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 sequence_number: Option<u64>,
233 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
234 extra: Extra,
235 },
236 #[serde(rename = "response.refusal.delta")]
237 ResponseRefusalDelta {
238 content_index: u32,
239 delta: String,
240 item_id: String,
241 output_index: u32,
242 #[serde(skip_serializing_if = "Option::is_none")]
243 sequence_number: Option<u64>,
244 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
245 extra: Extra,
246 },
247 #[serde(rename = "response.refusal.done")]
248 ResponseRefusalDone {
249 content_index: u32,
250 item_id: String,
251 output_index: u32,
252 refusal: String,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 sequence_number: Option<u64>,
255 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
256 extra: Extra,
257 },
258 #[serde(rename = "response.reasoning_summary_part.added")]
259 ResponseReasoningSummaryPartAdded {
260 item_id: String,
261 output_index: u32,
262 part: ResponseReasoningSummaryPart,
263 #[serde(skip_serializing_if = "Option::is_none")]
264 sequence_number: Option<u64>,
265 summary_index: u32,
266 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
267 extra: Extra,
268 },
269 #[serde(rename = "response.reasoning_summary_part.done")]
270 ResponseReasoningSummaryPartDone {
271 item_id: String,
272 output_index: u32,
273 part: ResponseReasoningSummaryPart,
274 #[serde(skip_serializing_if = "Option::is_none")]
275 sequence_number: Option<u64>,
276 summary_index: u32,
277 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
278 extra: Extra,
279 },
280 #[serde(rename = "response.reasoning_summary_text.delta")]
281 ResponseReasoningSummaryTextDelta {
282 delta: String,
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 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
289 extra: Extra,
290 },
291 #[serde(rename = "response.reasoning_summary_text.done")]
292 ResponseReasoningSummaryTextDone {
293 item_id: String,
294 output_index: u32,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 sequence_number: Option<u64>,
297 summary_index: u32,
298 text: String,
299 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
300 extra: Extra,
301 },
302 #[serde(rename = "response.reasoning_text.delta")]
303 ResponseReasoningTextDelta {
304 content_index: u32,
305 delta: String,
306 item_id: String,
307 output_index: u32,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 sequence_number: Option<u64>,
310 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
311 extra: Extra,
312 },
313 #[serde(rename = "response.reasoning_text.done")]
314 ResponseReasoningTextDone {
315 content_index: u32,
316 item_id: String,
317 output_index: u32,
318 #[serde(skip_serializing_if = "Option::is_none")]
319 sequence_number: Option<u64>,
320 text: String,
321 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
322 extra: Extra,
323 },
324 #[serde(rename = "response.audio.delta")]
325 ResponseAudioDelta {
326 delta: String,
327 #[serde(skip_serializing_if = "Option::is_none")]
328 sequence_number: Option<u64>,
329 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
330 extra: Extra,
331 },
332 #[serde(rename = "response.audio.done")]
333 ResponseAudioDone {
334 #[serde(skip_serializing_if = "Option::is_none")]
335 sequence_number: Option<u64>,
336 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
337 extra: Extra,
338 },
339 #[serde(rename = "response.audio.transcript.delta")]
340 ResponseAudioTranscriptDelta {
341 delta: String,
342 #[serde(skip_serializing_if = "Option::is_none")]
343 sequence_number: Option<u64>,
344 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
345 extra: Extra,
346 },
347 #[serde(rename = "response.audio.transcript.done")]
348 ResponseAudioTranscriptDone {
349 #[serde(skip_serializing_if = "Option::is_none")]
350 sequence_number: Option<u64>,
351 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
352 extra: Extra,
353 },
354 #[serde(rename = "response.image_generation_call.completed")]
355 ResponseImageGenerationCallCompleted {
356 item_id: String,
357 output_index: u32,
358 #[serde(skip_serializing_if = "Option::is_none")]
359 sequence_number: Option<u64>,
360 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
361 extra: Extra,
362 },
363 #[serde(rename = "response.image_generation_call.generating")]
364 ResponseImageGenerationCallGenerating {
365 item_id: String,
366 output_index: u32,
367 #[serde(skip_serializing_if = "Option::is_none")]
368 sequence_number: Option<u64>,
369 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
370 extra: Extra,
371 },
372 #[serde(rename = "response.image_generation_call.in_progress")]
373 ResponseImageGenerationCallInProgress {
374 item_id: String,
375 output_index: u32,
376 #[serde(skip_serializing_if = "Option::is_none")]
377 sequence_number: Option<u64>,
378 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
379 extra: Extra,
380 },
381 #[serde(rename = "response.image_generation_call.partial_image")]
382 ResponseImageGenerationCallPartialImage {
383 item_id: String,
384 output_index: u32,
385 partial_image_b64: String,
386 partial_image_index: u32,
387 #[serde(skip_serializing_if = "Option::is_none")]
388 sequence_number: Option<u64>,
389 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
390 extra: Extra,
391 },
392 #[serde(rename = "response.file_search_call.in_progress")]
393 ResponseFileSearchCallInProgress {
394 item_id: String,
395 output_index: u32,
396 #[serde(skip_serializing_if = "Option::is_none")]
397 sequence_number: Option<u64>,
398 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
399 extra: Extra,
400 },
401 #[serde(rename = "response.file_search_call.searching")]
402 ResponseFileSearchCallSearching {
403 item_id: String,
404 output_index: u32,
405 #[serde(skip_serializing_if = "Option::is_none")]
406 sequence_number: Option<u64>,
407 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
408 extra: Extra,
409 },
410 #[serde(rename = "response.file_search_call.completed")]
411 ResponseFileSearchCallCompleted {
412 item_id: String,
413 output_index: u32,
414 #[serde(skip_serializing_if = "Option::is_none")]
415 sequence_number: Option<u64>,
416 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
417 extra: Extra,
418 },
419 #[serde(rename = "response.web_search_call.in_progress")]
420 ResponseWebSearchCallInProgress {
421 item_id: String,
422 output_index: u32,
423 #[serde(skip_serializing_if = "Option::is_none")]
424 sequence_number: Option<u64>,
425 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
426 extra: Extra,
427 },
428 #[serde(rename = "response.web_search_call.searching")]
429 ResponseWebSearchCallSearching {
430 item_id: String,
431 output_index: u32,
432 #[serde(skip_serializing_if = "Option::is_none")]
433 sequence_number: Option<u64>,
434 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
435 extra: Extra,
436 },
437 #[serde(rename = "response.web_search_call.completed")]
438 ResponseWebSearchCallCompleted {
439 item_id: String,
440 output_index: u32,
441 #[serde(skip_serializing_if = "Option::is_none")]
442 sequence_number: Option<u64>,
443 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
444 extra: Extra,
445 },
446 #[serde(rename = "response.code_interpreter_call.in_progress")]
447 ResponseCodeInterpreterCallInProgress {
448 item_id: String,
449 output_index: u32,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 sequence_number: Option<u64>,
452 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
453 extra: Extra,
454 },
455 #[serde(rename = "response.code_interpreter_call.interpreting")]
456 ResponseCodeInterpreterCallInterpreting {
457 item_id: String,
458 output_index: u32,
459 #[serde(skip_serializing_if = "Option::is_none")]
460 sequence_number: Option<u64>,
461 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
462 extra: Extra,
463 },
464 #[serde(rename = "response.code_interpreter_call.completed")]
465 ResponseCodeInterpreterCallCompleted {
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.delta")]
474 ResponseCodeInterpreterCallCodeDelta {
475 delta: 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.code_interpreter_call_code.done")]
484 ResponseCodeInterpreterCallCodeDone {
485 code: 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.delta")]
494 ResponseMcpCallArgumentsDelta {
495 delta: 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_arguments.done")]
504 ResponseMcpCallArgumentsDone {
505 arguments: String,
506 item_id: String,
507 output_index: u32,
508 #[serde(skip_serializing_if = "Option::is_none")]
509 sequence_number: Option<u64>,
510 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
511 extra: Extra,
512 },
513 #[serde(rename = "response.mcp_call.in_progress")]
514 ResponseMcpCallInProgress {
515 item_id: String,
516 output_index: u32,
517 #[serde(skip_serializing_if = "Option::is_none")]
518 sequence_number: Option<u64>,
519 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
520 extra: Extra,
521 },
522 #[serde(rename = "response.mcp_call.completed")]
523 ResponseMcpCallCompleted {
524 item_id: String,
525 output_index: u32,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 sequence_number: Option<u64>,
528 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
529 extra: Extra,
530 },
531 #[serde(rename = "response.mcp_call.failed")]
532 ResponseMcpCallFailed {
533 item_id: String,
534 output_index: u32,
535 #[serde(skip_serializing_if = "Option::is_none")]
536 sequence_number: Option<u64>,
537 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
538 extra: Extra,
539 },
540 #[serde(rename = "response.mcp_list_tools.in_progress")]
541 ResponseMcpListToolsInProgress {
542 item_id: String,
543 output_index: u32,
544 #[serde(skip_serializing_if = "Option::is_none")]
545 sequence_number: Option<u64>,
546 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
547 extra: Extra,
548 },
549 #[serde(rename = "response.mcp_list_tools.completed")]
550 ResponseMcpListToolsCompleted {
551 item_id: String,
552 output_index: u32,
553 #[serde(skip_serializing_if = "Option::is_none")]
554 sequence_number: Option<u64>,
555 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
556 extra: Extra,
557 },
558 #[serde(rename = "response.mcp_list_tools.failed")]
559 ResponseMcpListToolsFailed {
560 item_id: String,
561 output_index: u32,
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 #[serde(rename = "error")]
568 Error {
569 code: String,
570 message: String,
571 param: String,
572 #[serde(skip_serializing_if = "Option::is_none")]
573 sequence_number: Option<u64>,
574 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
575 extra: Extra,
576 },
577}
578
579impl KnownResponseStreamEvent {
580 pub fn event_type(&self) -> ResponseStreamEventTypeKnown {
582 use ResponseStreamEventTypeKnown as T;
583 match self {
584 Self::ResponseCreated { .. } => T::ResponseCreated,
585 Self::ResponseInProgress { .. } => T::ResponseInProgress,
586 Self::ResponseCompleted { .. } => T::ResponseCompleted,
587 Self::ResponseFailed { .. } => T::ResponseFailed,
588 Self::ResponseIncomplete { .. } => T::ResponseIncomplete,
589 Self::ResponseQueued { .. } => T::ResponseQueued,
590 Self::ResponseOutputItemAdded { .. } => T::ResponseOutputItemAdded,
591 Self::ResponseOutputItemDone { .. } => T::ResponseOutputItemDone,
592 Self::ResponseContentPartAdded { .. } => T::ResponseContentPartAdded,
593 Self::ResponseContentPartDone { .. } => T::ResponseContentPartDone,
594 Self::ResponseOutputTextDelta { .. } => T::ResponseOutputTextDelta,
595 Self::ResponseOutputTextDone { .. } => T::ResponseOutputTextDone,
596 Self::ResponseOutputTextAnnotationAdded { .. } => T::ResponseOutputTextAnnotationAdded,
597 Self::ResponseFunctionCallArgumentsDelta { .. } => {
598 T::ResponseFunctionCallArgumentsDelta
599 }
600 Self::ResponseFunctionCallArgumentsDone { .. } => T::ResponseFunctionCallArgumentsDone,
601 Self::ResponseCustomToolCallInputDelta { .. } => T::ResponseCustomToolCallInputDelta,
602 Self::ResponseCustomToolCallInputDone { .. } => T::ResponseCustomToolCallInputDone,
603 Self::ResponseRefusalDelta { .. } => T::ResponseRefusalDelta,
604 Self::ResponseRefusalDone { .. } => T::ResponseRefusalDone,
605 Self::ResponseReasoningSummaryPartAdded { .. } => T::ResponseReasoningSummaryPartAdded,
606 Self::ResponseReasoningSummaryPartDone { .. } => T::ResponseReasoningSummaryPartDone,
607 Self::ResponseReasoningSummaryTextDelta { .. } => T::ResponseReasoningSummaryTextDelta,
608 Self::ResponseReasoningSummaryTextDone { .. } => T::ResponseReasoningSummaryTextDone,
609 Self::ResponseReasoningTextDelta { .. } => T::ResponseReasoningTextDelta,
610 Self::ResponseReasoningTextDone { .. } => T::ResponseReasoningTextDone,
611 Self::ResponseAudioDelta { .. } => T::ResponseAudioDelta,
612 Self::ResponseAudioDone { .. } => T::ResponseAudioDone,
613 Self::ResponseAudioTranscriptDelta { .. } => T::ResponseAudioTranscriptDelta,
614 Self::ResponseAudioTranscriptDone { .. } => T::ResponseAudioTranscriptDone,
615 Self::ResponseImageGenerationCallCompleted { .. } => {
616 T::ResponseImageGenerationCallCompleted
617 }
618 Self::ResponseImageGenerationCallGenerating { .. } => {
619 T::ResponseImageGenerationCallGenerating
620 }
621 Self::ResponseImageGenerationCallInProgress { .. } => {
622 T::ResponseImageGenerationCallInProgress
623 }
624 Self::ResponseImageGenerationCallPartialImage { .. } => {
625 T::ResponseImageGenerationCallPartialImage
626 }
627 Self::ResponseFileSearchCallInProgress { .. } => T::ResponseFileSearchCallInProgress,
628 Self::ResponseFileSearchCallSearching { .. } => T::ResponseFileSearchCallSearching,
629 Self::ResponseFileSearchCallCompleted { .. } => T::ResponseFileSearchCallCompleted,
630 Self::ResponseWebSearchCallInProgress { .. } => T::ResponseWebSearchCallInProgress,
631 Self::ResponseWebSearchCallSearching { .. } => T::ResponseWebSearchCallSearching,
632 Self::ResponseWebSearchCallCompleted { .. } => T::ResponseWebSearchCallCompleted,
633 Self::ResponseCodeInterpreterCallInProgress { .. } => {
634 T::ResponseCodeInterpreterCallInProgress
635 }
636 Self::ResponseCodeInterpreterCallInterpreting { .. } => {
637 T::ResponseCodeInterpreterCallInterpreting
638 }
639 Self::ResponseCodeInterpreterCallCompleted { .. } => {
640 T::ResponseCodeInterpreterCallCompleted
641 }
642 Self::ResponseCodeInterpreterCallCodeDelta { .. } => {
643 T::ResponseCodeInterpreterCallCodeDelta
644 }
645 Self::ResponseCodeInterpreterCallCodeDone { .. } => {
646 T::ResponseCodeInterpreterCallCodeDone
647 }
648 Self::ResponseMcpCallArgumentsDelta { .. } => T::ResponseMcpCallArgumentsDelta,
649 Self::ResponseMcpCallArgumentsDone { .. } => T::ResponseMcpCallArgumentsDone,
650 Self::ResponseMcpCallInProgress { .. } => T::ResponseMcpCallInProgress,
651 Self::ResponseMcpCallCompleted { .. } => T::ResponseMcpCallCompleted,
652 Self::ResponseMcpCallFailed { .. } => T::ResponseMcpCallFailed,
653 Self::ResponseMcpListToolsInProgress { .. } => T::ResponseMcpListToolsInProgress,
654 Self::ResponseMcpListToolsCompleted { .. } => T::ResponseMcpListToolsCompleted,
655 Self::ResponseMcpListToolsFailed { .. } => T::ResponseMcpListToolsFailed,
656 Self::Error { .. } => T::Error,
657 }
658 }
659
660 pub fn event_name(&self) -> &'static str {
662 self.event_type().as_str()
663 }
664}
665
666#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
667pub struct UnknownResponseStreamEvent {
668 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
669 pub type_: Option<ResponseStreamEventType>,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 pub sequence_number: Option<u64>,
672 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
673 pub extra: Extra,
674}
675
676#[cfg(test)]
677mod tests {
678 use super::*;
679
680 #[test]
682 fn event_name_matches_serialized_type_tag() {
683 let events: Vec<ResponseStreamEvent> = [
684 r#"{"type":"response.output_text.delta","content_index":0,"delta":"hi","item_id":"msg_0","output_index":0}"#,
685 r#"{"type":"response.output_item.done","output_index":0,"item":{"id":"fc_1","type":"function_call","call_id":"c1","name":"f","arguments":"{}"}}"#,
686 r#"{"type":"response.function_call_arguments.done","arguments":"{}","item_id":"fc_1","name":"f","output_index":0}"#,
687 r#"{"type":"response.completed","response":{"id":"r","object":"response","created_at":0,"output":[]}}"#,
688 r#"{"type":"response.some_future_event","sequence_number":1}"#,
689 ]
690 .iter()
691 .map(|raw| serde_json::from_str(raw).unwrap())
692 .collect();
693 for event in events {
694 let value = serde_json::to_value(&event).unwrap();
695 assert_eq!(
696 event.event_name(),
697 value.get("type").and_then(Value::as_str),
698 "{value}"
699 );
700 }
701 }
702}