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 name: String,
212 output_index: u32,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 sequence_number: Option<u64>,
215 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
216 extra: Extra,
217 },
218 #[serde(rename = "response.custom_tool_call_input.delta")]
219 ResponseCustomToolCallInputDelta {
220 delta: String,
221 item_id: String,
222 output_index: u32,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 sequence_number: Option<u64>,
225 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
226 extra: Extra,
227 },
228 #[serde(rename = "response.custom_tool_call_input.done")]
229 ResponseCustomToolCallInputDone {
230 input: String,
231 item_id: String,
232 output_index: u32,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 sequence_number: Option<u64>,
235 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
236 extra: Extra,
237 },
238 #[serde(rename = "response.refusal.delta")]
239 ResponseRefusalDelta {
240 content_index: u32,
241 delta: String,
242 item_id: String,
243 output_index: u32,
244 #[serde(skip_serializing_if = "Option::is_none")]
245 sequence_number: Option<u64>,
246 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
247 extra: Extra,
248 },
249 #[serde(rename = "response.refusal.done")]
250 ResponseRefusalDone {
251 content_index: u32,
252 item_id: String,
253 output_index: u32,
254 refusal: String,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 sequence_number: Option<u64>,
257 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
258 extra: Extra,
259 },
260 #[serde(rename = "response.reasoning_summary_part.added")]
261 ResponseReasoningSummaryPartAdded {
262 item_id: String,
263 output_index: u32,
264 part: ResponseReasoningSummaryPart,
265 #[serde(skip_serializing_if = "Option::is_none")]
266 sequence_number: Option<u64>,
267 summary_index: u32,
268 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
269 extra: Extra,
270 },
271 #[serde(rename = "response.reasoning_summary_part.done")]
272 ResponseReasoningSummaryPartDone {
273 item_id: String,
274 output_index: u32,
275 part: ResponseReasoningSummaryPart,
276 #[serde(skip_serializing_if = "Option::is_none")]
277 sequence_number: Option<u64>,
278 summary_index: u32,
279 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
280 extra: Extra,
281 },
282 #[serde(rename = "response.reasoning_summary_text.delta")]
283 ResponseReasoningSummaryTextDelta {
284 delta: String,
285 item_id: String,
286 output_index: u32,
287 #[serde(skip_serializing_if = "Option::is_none")]
288 sequence_number: Option<u64>,
289 summary_index: u32,
290 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
291 extra: Extra,
292 },
293 #[serde(rename = "response.reasoning_summary_text.done")]
294 ResponseReasoningSummaryTextDone {
295 item_id: String,
296 output_index: u32,
297 #[serde(skip_serializing_if = "Option::is_none")]
298 sequence_number: Option<u64>,
299 summary_index: u32,
300 text: String,
301 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
302 extra: Extra,
303 },
304 #[serde(rename = "response.reasoning_text.delta")]
305 ResponseReasoningTextDelta {
306 content_index: u32,
307 delta: String,
308 item_id: String,
309 output_index: u32,
310 #[serde(skip_serializing_if = "Option::is_none")]
311 sequence_number: Option<u64>,
312 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
313 extra: Extra,
314 },
315 #[serde(rename = "response.reasoning_text.done")]
316 ResponseReasoningTextDone {
317 content_index: u32,
318 item_id: String,
319 output_index: u32,
320 #[serde(skip_serializing_if = "Option::is_none")]
321 sequence_number: Option<u64>,
322 text: String,
323 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
324 extra: Extra,
325 },
326 #[serde(rename = "response.audio.delta")]
327 ResponseAudioDelta {
328 delta: String,
329 #[serde(skip_serializing_if = "Option::is_none")]
330 sequence_number: Option<u64>,
331 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
332 extra: Extra,
333 },
334 #[serde(rename = "response.audio.done")]
335 ResponseAudioDone {
336 #[serde(skip_serializing_if = "Option::is_none")]
337 sequence_number: Option<u64>,
338 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
339 extra: Extra,
340 },
341 #[serde(rename = "response.audio.transcript.delta")]
342 ResponseAudioTranscriptDelta {
343 delta: String,
344 #[serde(skip_serializing_if = "Option::is_none")]
345 sequence_number: Option<u64>,
346 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
347 extra: Extra,
348 },
349 #[serde(rename = "response.audio.transcript.done")]
350 ResponseAudioTranscriptDone {
351 #[serde(skip_serializing_if = "Option::is_none")]
352 sequence_number: Option<u64>,
353 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
354 extra: Extra,
355 },
356 #[serde(rename = "response.image_generation_call.completed")]
357 ResponseImageGenerationCallCompleted {
358 item_id: String,
359 output_index: u32,
360 #[serde(skip_serializing_if = "Option::is_none")]
361 sequence_number: Option<u64>,
362 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
363 extra: Extra,
364 },
365 #[serde(rename = "response.image_generation_call.generating")]
366 ResponseImageGenerationCallGenerating {
367 item_id: String,
368 output_index: u32,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 sequence_number: Option<u64>,
371 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
372 extra: Extra,
373 },
374 #[serde(rename = "response.image_generation_call.in_progress")]
375 ResponseImageGenerationCallInProgress {
376 item_id: String,
377 output_index: u32,
378 #[serde(skip_serializing_if = "Option::is_none")]
379 sequence_number: Option<u64>,
380 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
381 extra: Extra,
382 },
383 #[serde(rename = "response.image_generation_call.partial_image")]
384 ResponseImageGenerationCallPartialImage {
385 item_id: String,
386 output_index: u32,
387 partial_image_b64: String,
388 partial_image_index: u32,
389 #[serde(skip_serializing_if = "Option::is_none")]
390 sequence_number: Option<u64>,
391 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
392 extra: Extra,
393 },
394 #[serde(rename = "response.file_search_call.in_progress")]
395 ResponseFileSearchCallInProgress {
396 item_id: String,
397 output_index: u32,
398 #[serde(skip_serializing_if = "Option::is_none")]
399 sequence_number: Option<u64>,
400 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
401 extra: Extra,
402 },
403 #[serde(rename = "response.file_search_call.searching")]
404 ResponseFileSearchCallSearching {
405 item_id: String,
406 output_index: u32,
407 #[serde(skip_serializing_if = "Option::is_none")]
408 sequence_number: Option<u64>,
409 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
410 extra: Extra,
411 },
412 #[serde(rename = "response.file_search_call.completed")]
413 ResponseFileSearchCallCompleted {
414 item_id: String,
415 output_index: u32,
416 #[serde(skip_serializing_if = "Option::is_none")]
417 sequence_number: Option<u64>,
418 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
419 extra: Extra,
420 },
421 #[serde(rename = "response.web_search_call.in_progress")]
422 ResponseWebSearchCallInProgress {
423 item_id: String,
424 output_index: u32,
425 #[serde(skip_serializing_if = "Option::is_none")]
426 sequence_number: Option<u64>,
427 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
428 extra: Extra,
429 },
430 #[serde(rename = "response.web_search_call.searching")]
431 ResponseWebSearchCallSearching {
432 item_id: String,
433 output_index: u32,
434 #[serde(skip_serializing_if = "Option::is_none")]
435 sequence_number: Option<u64>,
436 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
437 extra: Extra,
438 },
439 #[serde(rename = "response.web_search_call.completed")]
440 ResponseWebSearchCallCompleted {
441 item_id: String,
442 output_index: u32,
443 #[serde(skip_serializing_if = "Option::is_none")]
444 sequence_number: Option<u64>,
445 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
446 extra: Extra,
447 },
448 #[serde(rename = "response.code_interpreter_call.in_progress")]
449 ResponseCodeInterpreterCallInProgress {
450 item_id: String,
451 output_index: u32,
452 #[serde(skip_serializing_if = "Option::is_none")]
453 sequence_number: Option<u64>,
454 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
455 extra: Extra,
456 },
457 #[serde(rename = "response.code_interpreter_call.interpreting")]
458 ResponseCodeInterpreterCallInterpreting {
459 item_id: String,
460 output_index: u32,
461 #[serde(skip_serializing_if = "Option::is_none")]
462 sequence_number: Option<u64>,
463 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
464 extra: Extra,
465 },
466 #[serde(rename = "response.code_interpreter_call.completed")]
467 ResponseCodeInterpreterCallCompleted {
468 item_id: String,
469 output_index: u32,
470 #[serde(skip_serializing_if = "Option::is_none")]
471 sequence_number: Option<u64>,
472 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
473 extra: Extra,
474 },
475 #[serde(rename = "response.code_interpreter_call_code.delta")]
476 ResponseCodeInterpreterCallCodeDelta {
477 delta: String,
478 item_id: String,
479 output_index: u32,
480 #[serde(skip_serializing_if = "Option::is_none")]
481 sequence_number: Option<u64>,
482 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
483 extra: Extra,
484 },
485 #[serde(rename = "response.code_interpreter_call_code.done")]
486 ResponseCodeInterpreterCallCodeDone {
487 code: String,
488 item_id: String,
489 output_index: u32,
490 #[serde(skip_serializing_if = "Option::is_none")]
491 sequence_number: Option<u64>,
492 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
493 extra: Extra,
494 },
495 #[serde(rename = "response.mcp_call_arguments.delta")]
496 ResponseMcpCallArgumentsDelta {
497 delta: String,
498 item_id: String,
499 output_index: u32,
500 #[serde(skip_serializing_if = "Option::is_none")]
501 sequence_number: Option<u64>,
502 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
503 extra: Extra,
504 },
505 #[serde(rename = "response.mcp_call_arguments.done")]
506 ResponseMcpCallArgumentsDone {
507 arguments: String,
508 item_id: String,
509 output_index: u32,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 sequence_number: Option<u64>,
512 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
513 extra: Extra,
514 },
515 #[serde(rename = "response.mcp_call.in_progress")]
516 ResponseMcpCallInProgress {
517 item_id: String,
518 output_index: u32,
519 #[serde(skip_serializing_if = "Option::is_none")]
520 sequence_number: Option<u64>,
521 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
522 extra: Extra,
523 },
524 #[serde(rename = "response.mcp_call.completed")]
525 ResponseMcpCallCompleted {
526 item_id: String,
527 output_index: u32,
528 #[serde(skip_serializing_if = "Option::is_none")]
529 sequence_number: Option<u64>,
530 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
531 extra: Extra,
532 },
533 #[serde(rename = "response.mcp_call.failed")]
534 ResponseMcpCallFailed {
535 item_id: String,
536 output_index: u32,
537 #[serde(skip_serializing_if = "Option::is_none")]
538 sequence_number: Option<u64>,
539 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
540 extra: Extra,
541 },
542 #[serde(rename = "response.mcp_list_tools.in_progress")]
543 ResponseMcpListToolsInProgress {
544 item_id: String,
545 output_index: u32,
546 #[serde(skip_serializing_if = "Option::is_none")]
547 sequence_number: Option<u64>,
548 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
549 extra: Extra,
550 },
551 #[serde(rename = "response.mcp_list_tools.completed")]
552 ResponseMcpListToolsCompleted {
553 item_id: String,
554 output_index: u32,
555 #[serde(skip_serializing_if = "Option::is_none")]
556 sequence_number: Option<u64>,
557 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
558 extra: Extra,
559 },
560 #[serde(rename = "response.mcp_list_tools.failed")]
561 ResponseMcpListToolsFailed {
562 item_id: String,
563 output_index: u32,
564 #[serde(skip_serializing_if = "Option::is_none")]
565 sequence_number: Option<u64>,
566 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
567 extra: Extra,
568 },
569 #[serde(rename = "error")]
570 Error {
571 code: String,
572 message: String,
573 param: String,
574 #[serde(skip_serializing_if = "Option::is_none")]
575 sequence_number: Option<u64>,
576 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
577 extra: Extra,
578 },
579}
580
581impl KnownResponseStreamEvent {
582 pub fn event_type(&self) -> ResponseStreamEventTypeKnown {
584 use ResponseStreamEventTypeKnown as T;
585 match self {
586 Self::ResponseCreated { .. } => T::ResponseCreated,
587 Self::ResponseInProgress { .. } => T::ResponseInProgress,
588 Self::ResponseCompleted { .. } => T::ResponseCompleted,
589 Self::ResponseFailed { .. } => T::ResponseFailed,
590 Self::ResponseIncomplete { .. } => T::ResponseIncomplete,
591 Self::ResponseQueued { .. } => T::ResponseQueued,
592 Self::ResponseOutputItemAdded { .. } => T::ResponseOutputItemAdded,
593 Self::ResponseOutputItemDone { .. } => T::ResponseOutputItemDone,
594 Self::ResponseContentPartAdded { .. } => T::ResponseContentPartAdded,
595 Self::ResponseContentPartDone { .. } => T::ResponseContentPartDone,
596 Self::ResponseOutputTextDelta { .. } => T::ResponseOutputTextDelta,
597 Self::ResponseOutputTextDone { .. } => T::ResponseOutputTextDone,
598 Self::ResponseOutputTextAnnotationAdded { .. } => T::ResponseOutputTextAnnotationAdded,
599 Self::ResponseFunctionCallArgumentsDelta { .. } => {
600 T::ResponseFunctionCallArgumentsDelta
601 }
602 Self::ResponseFunctionCallArgumentsDone { .. } => T::ResponseFunctionCallArgumentsDone,
603 Self::ResponseCustomToolCallInputDelta { .. } => T::ResponseCustomToolCallInputDelta,
604 Self::ResponseCustomToolCallInputDone { .. } => T::ResponseCustomToolCallInputDone,
605 Self::ResponseRefusalDelta { .. } => T::ResponseRefusalDelta,
606 Self::ResponseRefusalDone { .. } => T::ResponseRefusalDone,
607 Self::ResponseReasoningSummaryPartAdded { .. } => T::ResponseReasoningSummaryPartAdded,
608 Self::ResponseReasoningSummaryPartDone { .. } => T::ResponseReasoningSummaryPartDone,
609 Self::ResponseReasoningSummaryTextDelta { .. } => T::ResponseReasoningSummaryTextDelta,
610 Self::ResponseReasoningSummaryTextDone { .. } => T::ResponseReasoningSummaryTextDone,
611 Self::ResponseReasoningTextDelta { .. } => T::ResponseReasoningTextDelta,
612 Self::ResponseReasoningTextDone { .. } => T::ResponseReasoningTextDone,
613 Self::ResponseAudioDelta { .. } => T::ResponseAudioDelta,
614 Self::ResponseAudioDone { .. } => T::ResponseAudioDone,
615 Self::ResponseAudioTranscriptDelta { .. } => T::ResponseAudioTranscriptDelta,
616 Self::ResponseAudioTranscriptDone { .. } => T::ResponseAudioTranscriptDone,
617 Self::ResponseImageGenerationCallCompleted { .. } => {
618 T::ResponseImageGenerationCallCompleted
619 }
620 Self::ResponseImageGenerationCallGenerating { .. } => {
621 T::ResponseImageGenerationCallGenerating
622 }
623 Self::ResponseImageGenerationCallInProgress { .. } => {
624 T::ResponseImageGenerationCallInProgress
625 }
626 Self::ResponseImageGenerationCallPartialImage { .. } => {
627 T::ResponseImageGenerationCallPartialImage
628 }
629 Self::ResponseFileSearchCallInProgress { .. } => T::ResponseFileSearchCallInProgress,
630 Self::ResponseFileSearchCallSearching { .. } => T::ResponseFileSearchCallSearching,
631 Self::ResponseFileSearchCallCompleted { .. } => T::ResponseFileSearchCallCompleted,
632 Self::ResponseWebSearchCallInProgress { .. } => T::ResponseWebSearchCallInProgress,
633 Self::ResponseWebSearchCallSearching { .. } => T::ResponseWebSearchCallSearching,
634 Self::ResponseWebSearchCallCompleted { .. } => T::ResponseWebSearchCallCompleted,
635 Self::ResponseCodeInterpreterCallInProgress { .. } => {
636 T::ResponseCodeInterpreterCallInProgress
637 }
638 Self::ResponseCodeInterpreterCallInterpreting { .. } => {
639 T::ResponseCodeInterpreterCallInterpreting
640 }
641 Self::ResponseCodeInterpreterCallCompleted { .. } => {
642 T::ResponseCodeInterpreterCallCompleted
643 }
644 Self::ResponseCodeInterpreterCallCodeDelta { .. } => {
645 T::ResponseCodeInterpreterCallCodeDelta
646 }
647 Self::ResponseCodeInterpreterCallCodeDone { .. } => {
648 T::ResponseCodeInterpreterCallCodeDone
649 }
650 Self::ResponseMcpCallArgumentsDelta { .. } => T::ResponseMcpCallArgumentsDelta,
651 Self::ResponseMcpCallArgumentsDone { .. } => T::ResponseMcpCallArgumentsDone,
652 Self::ResponseMcpCallInProgress { .. } => T::ResponseMcpCallInProgress,
653 Self::ResponseMcpCallCompleted { .. } => T::ResponseMcpCallCompleted,
654 Self::ResponseMcpCallFailed { .. } => T::ResponseMcpCallFailed,
655 Self::ResponseMcpListToolsInProgress { .. } => T::ResponseMcpListToolsInProgress,
656 Self::ResponseMcpListToolsCompleted { .. } => T::ResponseMcpListToolsCompleted,
657 Self::ResponseMcpListToolsFailed { .. } => T::ResponseMcpListToolsFailed,
658 Self::Error { .. } => T::Error,
659 }
660 }
661
662 pub fn event_name(&self) -> &'static str {
664 self.event_type().as_str()
665 }
666}
667
668#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
669#[non_exhaustive]
670pub struct UnknownResponseStreamEvent {
671 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
672 pub type_: Option<ResponseStreamEventType>,
673 #[serde(skip_serializing_if = "Option::is_none")]
674 pub sequence_number: Option<u64>,
675 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
676 pub extra: Extra,
677}
678
679#[cfg(test)]
680mod tests {
681 use super::*;
682
683 #[test]
685 fn event_name_matches_serialized_type_tag() {
686 let events: Vec<ResponseStreamEvent> = [
687 r#"{"type":"response.output_text.delta","content_index":0,"delta":"hi","item_id":"msg_0","output_index":0}"#,
688 r#"{"type":"response.output_item.done","output_index":0,"item":{"id":"fc_1","type":"function_call","call_id":"c1","name":"f","arguments":"{}"}}"#,
689 r#"{"type":"response.function_call_arguments.done","arguments":"{}","item_id":"fc_1","name":"f","output_index":0}"#,
690 r#"{"type":"response.completed","response":{"id":"r","object":"response","created_at":0,"output":[]}}"#,
691 r#"{"type":"response.some_future_event","sequence_number":1}"#,
692 ]
693 .iter()
694 .map(|raw| serde_json::from_str(raw).unwrap())
695 .collect();
696 for event in events {
697 let value = serde_json::to_value(&event).unwrap();
698 assert_eq!(
699 event.event_name(),
700 value.get("type").and_then(Value::as_str),
701 "{value}"
702 );
703 }
704 }
705}