Skip to main content

gproxy_protocol/protocol/openai/generate_content/
stream.rs

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