outfox_openai/spec/realtime/
client_event.rs1use serde::{Deserialize, Serialize};
2use tokio_tungstenite::tungstenite::Message;
3
4use super::{item::Item, session_resource::SessionResource};
5
6#[derive(Debug, Serialize, Deserialize, Clone, Default)]
7pub struct SessionUpdateEvent {
8 #[serde(skip_serializing_if = "Option::is_none")]
10 pub event_id: Option<String>,
11 pub session: SessionResource,
13}
14
15#[derive(Debug, Serialize, Deserialize, Clone, Default)]
16pub struct InputAudioBufferAppendEvent {
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub event_id: Option<String>,
20 pub audio: String,
22}
23
24#[derive(Debug, Serialize, Deserialize, Clone, Default)]
25pub struct InputAudioBufferCommitEvent {
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub event_id: Option<String>,
29}
30
31#[derive(Debug, Serialize, Deserialize, Clone, Default)]
32pub struct InputAudioBufferClearEvent {
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub event_id: Option<String>,
36}
37
38#[derive(Debug, Serialize, Deserialize, Clone)]
39pub struct ConversationItemCreateEvent {
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub event_id: Option<String>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub previous_item_id: Option<String>,
47
48 pub item: Item,
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone, Default)]
53pub struct ConversationItemTruncateEvent {
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub event_id: Option<String>,
57
58 pub item_id: String,
60
61 pub content_index: u32,
63
64 pub audio_end_ms: u32,
66}
67
68#[derive(Debug, Serialize, Deserialize, Clone, Default)]
69pub struct ConversationItemDeleteEvent {
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub event_id: Option<String>,
73
74 pub item_id: String,
76}
77
78#[derive(Debug, Serialize, Deserialize, Clone, Default)]
79pub struct ResponseCreateEvent {
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub event_id: Option<String>,
83
84 pub response: Option<SessionResource>,
86}
87
88#[derive(Debug, Serialize, Deserialize, Clone, Default)]
89pub struct ResponseCancelEvent {
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub event_id: Option<String>,
93}
94
95#[derive(Debug, Serialize, Deserialize)]
97#[serde(tag = "type")]
98pub enum ClientEvent {
99 #[serde(rename = "session.update")]
101 SessionUpdate(SessionUpdateEvent),
102
103 #[serde(rename = "input_audio_buffer.append")]
105 InputAudioBufferAppend(InputAudioBufferAppendEvent),
106
107 #[serde(rename = "input_audio_buffer.commit")]
109 InputAudioBufferCommit(InputAudioBufferCommitEvent),
110
111 #[serde(rename = "input_audio_buffer.clear")]
113 InputAudioBufferClear(InputAudioBufferClearEvent),
114
115 #[serde(rename = "conversation.item.create")]
117 ConversationItemCreate(ConversationItemCreateEvent),
118
119 #[serde(rename = "conversation.item.truncate")]
121 ConversationItemTruncate(ConversationItemTruncateEvent),
122
123 #[serde(rename = "conversation.item.delete")]
125 ConversationItemDelete(ConversationItemDeleteEvent),
126
127 #[serde(rename = "response.create")]
129 ResponseCreate(ResponseCreateEvent),
130
131 #[serde(rename = "response.cancel")]
133 ResponseCancel(ResponseCancelEvent),
134}
135
136impl From<&ClientEvent> for String {
137 fn from(value: &ClientEvent) -> Self {
138 serde_json::to_string(value).unwrap()
139 }
140}
141
142impl From<ClientEvent> for Message {
143 fn from(value: ClientEvent) -> Self {
144 Message::Text(String::from(&value).into())
145 }
146}
147
148macro_rules! message_from_event {
149 ($from_typ:ty, $evt_typ:ty) => {
150 impl From<$from_typ> for Message {
151 fn from(value: $from_typ) -> Self {
152 Self::from(<$evt_typ>::from(value))
153 }
154 }
155 };
156}
157
158macro_rules! event_from {
159 ($from_typ:ty, $evt_typ:ty, $variant:ident) => {
160 impl From<$from_typ> for $evt_typ {
161 fn from(value: $from_typ) -> Self {
162 <$evt_typ>::$variant(value)
163 }
164 }
165 };
166}
167
168event_from!(SessionUpdateEvent, ClientEvent, SessionUpdate);
169event_from!(
170 InputAudioBufferAppendEvent,
171 ClientEvent,
172 InputAudioBufferAppend
173);
174event_from!(
175 InputAudioBufferCommitEvent,
176 ClientEvent,
177 InputAudioBufferCommit
178);
179event_from!(
180 InputAudioBufferClearEvent,
181 ClientEvent,
182 InputAudioBufferClear
183);
184event_from!(
185 ConversationItemCreateEvent,
186 ClientEvent,
187 ConversationItemCreate
188);
189event_from!(
190 ConversationItemTruncateEvent,
191 ClientEvent,
192 ConversationItemTruncate
193);
194event_from!(
195 ConversationItemDeleteEvent,
196 ClientEvent,
197 ConversationItemDelete
198);
199event_from!(ResponseCreateEvent, ClientEvent, ResponseCreate);
200event_from!(ResponseCancelEvent, ClientEvent, ResponseCancel);
201
202message_from_event!(SessionUpdateEvent, ClientEvent);
203message_from_event!(InputAudioBufferAppendEvent, ClientEvent);
204message_from_event!(InputAudioBufferCommitEvent, ClientEvent);
205message_from_event!(InputAudioBufferClearEvent, ClientEvent);
206message_from_event!(ConversationItemCreateEvent, ClientEvent);
207message_from_event!(ConversationItemTruncateEvent, ClientEvent);
208message_from_event!(ConversationItemDeleteEvent, ClientEvent);
209message_from_event!(ResponseCreateEvent, ClientEvent);
210message_from_event!(ResponseCancelEvent, ClientEvent);
211
212impl From<Item> for ConversationItemCreateEvent {
213 fn from(value: Item) -> Self {
214 Self {
215 event_id: None,
216 previous_item_id: None,
217 item: value,
218 }
219 }
220}