1use serde::{Deserialize, Serialize};
4
5use crate::common::models::LiveModel;
6
7use super::session::{LiveAudioConfig, LiveSessionConfig, LiveSessionUpdate};
8
9#[derive(Debug, Clone, Serialize)]
11#[serde(tag = "type")]
12pub enum ClientEvent {
13 #[serde(rename = "session.start")]
14 SessionStart {
15 #[serde(skip_serializing_if = "Option::is_none")]
16 event_id: Option<String>,
17 session: LiveSessionConfig,
18 },
19 #[serde(rename = "session.update")]
20 SessionUpdate {
21 #[serde(skip_serializing_if = "Option::is_none")]
22 event_id: Option<String>,
23 session: LiveSessionUpdate,
24 },
25 #[serde(rename = "session.input_audio.append")]
26 InputAudioAppend {
27 #[serde(skip_serializing_if = "Option::is_none")]
28 event_id: Option<String>,
29 audio: String,
30 },
31 #[serde(rename = "session.input_audio.mute")]
32 InputAudioMute {
33 #[serde(skip_serializing_if = "Option::is_none")]
34 event_id: Option<String>,
35 },
36 #[serde(rename = "session.input_audio.unmute")]
37 InputAudioUnmute {
38 #[serde(skip_serializing_if = "Option::is_none")]
39 event_id: Option<String>,
40 },
41 #[serde(rename = "session.instructions.append")]
42 InstructionsAppend {
43 #[serde(skip_serializing_if = "Option::is_none")]
44 event_id: Option<String>,
45 content: String,
46 delegation_id: Option<String>,
47 },
48 #[serde(rename = "session.thinking.append")]
49 ThinkingAppend {
50 #[serde(skip_serializing_if = "Option::is_none")]
51 event_id: Option<String>,
52 content: String,
53 delegation_id: Option<String>,
54 },
55 #[serde(rename = "session.commentary.append")]
56 CommentaryAppend {
57 #[serde(skip_serializing_if = "Option::is_none")]
58 event_id: Option<String>,
59 content: String,
60 delegation_id: Option<String>,
61 },
62 #[serde(rename = "response.item.create")]
63 ResponseItemCreate {
64 #[serde(skip_serializing_if = "Option::is_none")]
65 event_id: Option<String>,
66 item: serde_json::Value,
67 },
68 #[serde(rename = "response.create")]
69 ResponseCreate {
70 #[serde(skip_serializing_if = "Option::is_none")]
71 event_id: Option<String>,
72 },
73 #[serde(rename = "session.close")]
74 SessionClose {
75 #[serde(skip_serializing_if = "Option::is_none")]
76 event_id: Option<String>,
77 },
78}
79
80#[derive(Debug, Clone, Deserialize)]
82#[serde(tag = "type")]
83#[non_exhaustive]
84pub enum ServerEvent {
85 #[serde(rename = "session.started")]
86 SessionStarted(SessionStartedEvent),
87 #[serde(rename = "session.updated")]
88 SessionUpdated(SessionUpdatedEvent),
89 #[serde(rename = "session.input_audio.muted")]
90 InputAudioMuted(AcknowledgementEvent),
91 #[serde(rename = "session.input_audio.unmuted")]
92 InputAudioUnmuted(AcknowledgementEvent),
93 #[serde(rename = "session.instructions.appended")]
94 InstructionsAppended(TimelineEvent),
95 #[serde(rename = "session.thinking.appended")]
96 ThinkingAppended(TimelineEvent),
97 #[serde(rename = "session.commentary.appended")]
98 CommentaryAppended(TimelineEvent),
99 #[serde(rename = "session.output_audio.delta")]
100 OutputAudioDelta(OutputAudioDeltaEvent),
101 #[serde(rename = "session.input_transcript.delta")]
102 InputTranscriptDelta(TranscriptDeltaEvent),
103 #[serde(rename = "session.output_transcript.delta")]
104 OutputTranscriptDelta(TranscriptDeltaEvent),
105 #[serde(rename = "session.delegation.created")]
106 DelegationCreated(DelegationCreatedEvent),
107 #[serde(rename = "response.event")]
108 ResponseEvent(ResponseEvent),
109 #[serde(rename = "session.usage.updated")]
110 SessionUsageUpdated(SessionUsageUpdatedEvent),
111 #[serde(rename = "session.closed")]
112 SessionClosed(SessionClosedEvent),
113 #[serde(rename = "error")]
114 Error(ErrorEvent),
115 #[serde(rename = "info")]
116 Info(InfoEvent),
117 #[serde(other)]
119 Unknown,
120}
121
122#[derive(Debug, Clone, Deserialize)]
124pub struct SessionResource {
125 pub id: String,
126 pub expires_at: u64,
127 pub model: LiveModel,
128 pub status: String,
129 pub audio: Option<LiveAudioConfig>,
130 pub client: Option<serde_json::Value>,
131 pub delegation: Option<serde_json::Value>,
132 #[serde(default)]
133 pub input: Vec<serde_json::Value>,
134 pub instructions: Option<String>,
135 pub store: Option<bool>,
136}
137
138#[derive(Debug, Clone, Deserialize)]
140pub struct SessionStartedEvent {
141 pub event_id: Option<String>,
142 pub client_event_id: Option<String>,
143 pub session: SessionResource,
144}
145
146#[derive(Debug, Clone, Deserialize)]
148pub struct SessionUpdatedEvent {
149 pub event_id: Option<String>,
150 pub client_event_id: Option<String>,
151 pub session: SessionResource,
152}
153
154#[derive(Debug, Clone, Deserialize)]
156pub struct AcknowledgementEvent {
157 pub event_id: Option<String>,
158 pub client_event_id: Option<String>,
159}
160
161#[derive(Debug, Clone, Deserialize)]
163pub struct TimelineEvent {
164 pub event_id: Option<String>,
165 pub client_event_id: Option<String>,
166 pub start_ms: Option<u64>,
167 pub end_ms: Option<u64>,
168}
169
170#[derive(Debug, Clone, Deserialize)]
172pub struct OutputAudioDeltaEvent {
173 pub event_id: Option<String>,
174 pub client_event_id: Option<String>,
175 pub delta: String,
176 pub start_ms: Option<u64>,
177 pub end_ms: Option<u64>,
178}
179
180#[derive(Debug, Clone, Deserialize)]
182pub struct TranscriptDeltaEvent {
183 pub event_id: Option<String>,
184 pub client_event_id: Option<String>,
185 pub delta: String,
186 pub start_ms: Option<u64>,
187 pub end_ms: Option<u64>,
188}
189
190#[derive(Debug, Clone, Deserialize)]
192pub struct DelegationCreatedEvent {
193 pub event_id: Option<String>,
194 pub client_event_id: Option<String>,
195 pub offset_ms: Option<u64>,
196 pub delegation: DelegationResource,
197}
198
199#[derive(Debug, Clone, Deserialize)]
201pub struct DelegationResource {
202 pub id: String,
203 #[serde(rename = "type")]
204 pub type_name: String,
205 pub target: DelegationTarget,
206 pub response_id: Option<String>,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
211#[serde(rename_all = "snake_case")]
212#[non_exhaustive]
213pub enum DelegationTarget {
214 Client,
215 Responses,
216 #[serde(untagged)]
218 Other(String),
219}
220
221#[derive(Debug, Clone, Deserialize)]
223pub struct ResponseEvent {
224 pub event_id: Option<String>,
225 pub client_event_id: Option<String>,
226 pub delegation_id: Option<String>,
227 pub event: serde_json::Value,
228}
229
230#[derive(Debug, Clone, Deserialize)]
234pub struct SessionUsage {
235 pub seconds: f64,
236}
237
238#[derive(Debug, Clone, Deserialize)]
240pub struct ContextWindowUsage {
241 pub usage_ratio: f64,
242}
243
244#[derive(Debug, Clone, Deserialize)]
246pub struct SessionUsageUpdatedEvent {
247 pub event_id: Option<String>,
248 pub client_event_id: Option<String>,
249 pub usage: SessionUsage,
250 pub context_window: Option<ContextWindowUsage>,
251}
252
253#[derive(Debug, Clone, Deserialize)]
255pub struct SessionClosedEvent {
256 pub event_id: Option<String>,
257 pub client_event_id: Option<String>,
258 pub reason: CloseReason,
259 pub session: SessionResource,
260 pub usage: SessionUsage,
261}
262
263#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
265#[serde(rename_all = "snake_case")]
266#[non_exhaustive]
267pub enum CloseReason {
268 CloseRequested,
269 Expired,
270 Content,
271 RemoteHangup,
272 ConnectionLost,
273 #[serde(untagged)]
275 Other(String),
276}
277
278#[derive(Debug, Clone, Deserialize)]
280pub struct LiveError {
281 #[serde(rename = "type")]
282 pub type_name: String,
283 pub code: String,
284 pub message: String,
285 pub param: Option<String>,
286 pub client_event_id: Option<String>,
287}
288
289#[derive(Debug, Clone, Deserialize)]
291pub struct ErrorEvent {
292 pub event_id: Option<String>,
293 pub client_event_id: Option<String>,
294 pub error: LiveError,
295}
296
297#[derive(Debug, Clone, Deserialize)]
299pub struct InfoEvent {
300 pub event_id: Option<String>,
301 pub client_event_id: Option<String>,
302 pub code: String,
303 pub message: String,
304}