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