gproxy_protocol/openai/realtime/
items.rs1use serde::{Deserialize, Serialize, de};
2use serde_json::Value;
3
4use crate::openai::common::Rest;
5
6#[derive(Debug, Clone, PartialEq, Serialize)]
7#[serde(untagged)]
8#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
9pub enum RealtimeItem {
10 Known(KnownRealtimeItem),
11 Unknown(UnknownRealtimeItem),
12}
13
14impl<'de> Deserialize<'de> for RealtimeItem {
15 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
16 let value = Value::deserialize(deserializer)?;
17 if let Ok(item) = serde_json::from_value(value.clone()) {
18 return Ok(Self::Known(item));
19 }
20 serde_json::from_value(value)
21 .map(Self::Unknown)
22 .map_err(de::Error::custom)
23 }
24}
25
26extensible_string!(RealtimeRole, KnownRealtimeRole {
27 User => "user", Assistant => "assistant", System => "system",
28});
29extensible_string!(RealtimeItemStatus, KnownRealtimeItemStatus {
30 InProgress => "in_progress", Completed => "completed", Incomplete => "incomplete",
31});
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
34#[serde(tag = "type")]
35#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
36pub enum KnownRealtimeItem {
37 #[serde(rename = "message")]
38 Message {
39 #[serde(skip_serializing_if = "Option::is_none")]
40 id: Option<String>,
41 role: RealtimeRole,
42 content: Vec<RealtimeContentPart>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 status: Option<RealtimeItemStatus>,
45 #[serde(default, flatten)]
46 rest: Rest,
47 },
48 #[serde(rename = "function_call")]
49 FunctionCall {
50 #[serde(skip_serializing_if = "Option::is_none")]
51 id: Option<String>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 call_id: Option<String>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 name: Option<String>,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 arguments: Option<String>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 status: Option<RealtimeItemStatus>,
60 #[serde(default, flatten)]
61 rest: Rest,
62 },
63 #[serde(rename = "function_call_output")]
64 FunctionCallOutput {
65 #[serde(skip_serializing_if = "Option::is_none")]
66 id: Option<String>,
67 call_id: String,
68 output: String,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 status: Option<RealtimeItemStatus>,
71 #[serde(default, flatten)]
72 rest: Rest,
73 },
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
77#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
78pub struct UnknownRealtimeItem {
79 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
80 pub type_: Option<String>,
81 #[serde(default, flatten)]
82 pub rest: Rest,
83}
84
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
86#[serde(tag = "type")]
87#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
88pub enum RealtimeContentPart {
89 #[serde(rename = "input_text")]
90 InputText {
91 #[serde(skip_serializing_if = "Option::is_none")]
92 text: Option<String>,
93 #[serde(default, flatten)]
94 rest: Rest,
95 },
96 #[serde(rename = "input_audio")]
97 InputAudio {
98 #[serde(skip_serializing_if = "Option::is_none")]
99 audio: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 transcript: Option<String>,
102 #[serde(default, flatten)]
103 rest: Rest,
104 },
105 #[serde(rename = "text")]
106 Text {
107 #[serde(skip_serializing_if = "Option::is_none")]
108 text: Option<String>,
109 #[serde(default, flatten)]
110 rest: Rest,
111 },
112 #[serde(rename = "audio")]
113 Audio {
114 #[serde(skip_serializing_if = "Option::is_none")]
115 audio: Option<String>,
116 #[serde(skip_serializing_if = "Option::is_none")]
117 transcript: Option<String>,
118 #[serde(default, flatten)]
119 rest: Rest,
120 },
121 #[serde(rename = "output_text")]
122 OutputText {
123 #[serde(skip_serializing_if = "Option::is_none")]
124 text: Option<String>,
125 #[serde(default, flatten)]
126 rest: Rest,
127 },
128 #[serde(rename = "output_audio")]
129 OutputAudio {
130 #[serde(skip_serializing_if = "Option::is_none")]
131 audio: Option<String>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 transcript: Option<String>,
134 #[serde(default, flatten)]
135 rest: Rest,
136 },
137}