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