Skip to main content

openai_protocol/
event_types.rs

1use std::fmt;
2
3/// Response lifecycle events
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum ResponseEvent {
6    Created,
7    InProgress,
8    Completed,
9}
10
11impl ResponseEvent {
12    pub const CREATED: &'static str = "response.created";
13    pub const IN_PROGRESS: &'static str = "response.in_progress";
14    pub const COMPLETED: &'static str = "response.completed";
15
16    pub const fn as_str(self) -> &'static str {
17        match self {
18            Self::Created => Self::CREATED,
19            Self::InProgress => Self::IN_PROGRESS,
20            Self::Completed => Self::COMPLETED,
21        }
22    }
23}
24
25impl fmt::Display for ResponseEvent {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.write_str(self.as_str())
28    }
29}
30
31/// Output item events for streaming
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum OutputItemEvent {
34    Added,
35    Done,
36    Delta,
37}
38
39impl OutputItemEvent {
40    pub const ADDED: &'static str = "response.output_item.added";
41    pub const DONE: &'static str = "response.output_item.done";
42    pub const DELTA: &'static str = "response.output_item.delta";
43
44    pub const fn as_str(self) -> &'static str {
45        match self {
46            Self::Added => Self::ADDED,
47            Self::Done => Self::DONE,
48            Self::Delta => Self::DELTA,
49        }
50    }
51}
52
53impl fmt::Display for OutputItemEvent {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        f.write_str(self.as_str())
56    }
57}
58
59/// Function call argument streaming events
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61pub enum FunctionCallEvent {
62    ArgumentsDelta,
63    ArgumentsDone,
64}
65
66impl FunctionCallEvent {
67    pub const ARGUMENTS_DELTA: &'static str = "response.function_call_arguments.delta";
68    pub const ARGUMENTS_DONE: &'static str = "response.function_call_arguments.done";
69
70    pub const fn as_str(self) -> &'static str {
71        match self {
72            Self::ArgumentsDelta => Self::ARGUMENTS_DELTA,
73            Self::ArgumentsDone => Self::ARGUMENTS_DONE,
74        }
75    }
76}
77
78impl fmt::Display for FunctionCallEvent {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        f.write_str(self.as_str())
81    }
82}
83
84/// Content part streaming events
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
86pub enum ContentPartEvent {
87    Added,
88    Done,
89}
90
91impl ContentPartEvent {
92    pub const ADDED: &'static str = "response.content_part.added";
93    pub const DONE: &'static str = "response.content_part.done";
94
95    pub const fn as_str(self) -> &'static str {
96        match self {
97            Self::Added => Self::ADDED,
98            Self::Done => Self::DONE,
99        }
100    }
101}
102
103impl fmt::Display for ContentPartEvent {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        f.write_str(self.as_str())
106    }
107}
108
109/// Output text streaming events
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub enum OutputTextEvent {
112    Delta,
113    Done,
114}
115
116impl OutputTextEvent {
117    pub const DELTA: &'static str = "response.output_text.delta";
118    pub const DONE: &'static str = "response.output_text.done";
119
120    pub const fn as_str(self) -> &'static str {
121        match self {
122            Self::Delta => Self::DELTA,
123            Self::Done => Self::DONE,
124        }
125    }
126}
127
128impl fmt::Display for OutputTextEvent {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        f.write_str(self.as_str())
131    }
132}
133
134// ============================================================================
135// MCP Events
136// ============================================================================
137
138/// MCP (Model Context Protocol) call events
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
140pub enum McpEvent {
141    CallArgumentsDelta,
142    CallArgumentsDone,
143    CallInProgress,
144    CallCompleted,
145    CallFailed,
146    ListToolsInProgress,
147    ListToolsCompleted,
148}
149
150impl McpEvent {
151    pub const CALL_ARGUMENTS_DELTA: &'static str = "response.mcp_call_arguments.delta";
152    pub const CALL_ARGUMENTS_DONE: &'static str = "response.mcp_call_arguments.done";
153    pub const CALL_IN_PROGRESS: &'static str = "response.mcp_call.in_progress";
154    pub const CALL_COMPLETED: &'static str = "response.mcp_call.completed";
155    pub const CALL_FAILED: &'static str = "response.mcp_call.failed";
156    pub const LIST_TOOLS_IN_PROGRESS: &'static str = "response.mcp_list_tools.in_progress";
157    pub const LIST_TOOLS_COMPLETED: &'static str = "response.mcp_list_tools.completed";
158
159    pub const fn as_str(self) -> &'static str {
160        match self {
161            Self::CallArgumentsDelta => Self::CALL_ARGUMENTS_DELTA,
162            Self::CallArgumentsDone => Self::CALL_ARGUMENTS_DONE,
163            Self::CallInProgress => Self::CALL_IN_PROGRESS,
164            Self::CallCompleted => Self::CALL_COMPLETED,
165            Self::CallFailed => Self::CALL_FAILED,
166            Self::ListToolsInProgress => Self::LIST_TOOLS_IN_PROGRESS,
167            Self::ListToolsCompleted => Self::LIST_TOOLS_COMPLETED,
168        }
169    }
170}
171
172impl fmt::Display for McpEvent {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        f.write_str(self.as_str())
175    }
176}
177
178// ============================================================================
179// Built-in Tool Events
180// ============================================================================
181
182/// Web search call events for streaming
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
184pub enum WebSearchCallEvent {
185    InProgress,
186    Searching,
187    Completed,
188}
189
190impl WebSearchCallEvent {
191    pub const IN_PROGRESS: &'static str = "response.web_search_call.in_progress";
192    pub const SEARCHING: &'static str = "response.web_search_call.searching";
193    pub const COMPLETED: &'static str = "response.web_search_call.completed";
194
195    pub const fn as_str(self) -> &'static str {
196        match self {
197            Self::InProgress => Self::IN_PROGRESS,
198            Self::Searching => Self::SEARCHING,
199            Self::Completed => Self::COMPLETED,
200        }
201    }
202}
203
204impl fmt::Display for WebSearchCallEvent {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        f.write_str(self.as_str())
207    }
208}
209
210/// Code interpreter call events for streaming
211#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
212pub enum CodeInterpreterCallEvent {
213    InProgress,
214    Interpreting,
215    Completed,
216}
217
218impl CodeInterpreterCallEvent {
219    pub const IN_PROGRESS: &'static str = "response.code_interpreter_call.in_progress";
220    pub const INTERPRETING: &'static str = "response.code_interpreter_call.interpreting";
221    pub const COMPLETED: &'static str = "response.code_interpreter_call.completed";
222
223    pub const fn as_str(self) -> &'static str {
224        match self {
225            Self::InProgress => Self::IN_PROGRESS,
226            Self::Interpreting => Self::INTERPRETING,
227            Self::Completed => Self::COMPLETED,
228        }
229    }
230}
231
232impl fmt::Display for CodeInterpreterCallEvent {
233    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234        f.write_str(self.as_str())
235    }
236}
237
238/// File search call events for streaming
239#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
240pub enum FileSearchCallEvent {
241    InProgress,
242    Searching,
243    Completed,
244}
245
246impl FileSearchCallEvent {
247    pub const IN_PROGRESS: &'static str = "response.file_search_call.in_progress";
248    pub const SEARCHING: &'static str = "response.file_search_call.searching";
249    pub const COMPLETED: &'static str = "response.file_search_call.completed";
250
251    pub const fn as_str(self) -> &'static str {
252        match self {
253            Self::InProgress => Self::IN_PROGRESS,
254            Self::Searching => Self::SEARCHING,
255            Self::Completed => Self::COMPLETED,
256        }
257    }
258}
259
260impl fmt::Display for FileSearchCallEvent {
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        f.write_str(self.as_str())
263    }
264}
265
266/// Image generation call events for streaming.
267///
268/// Mirrors OpenAI Python SDK 2.8.1 `response_image_gen_call_*_event.py` and
269/// `.claude/_audit/openai-responses-api-spec.md` §tools (image_generation).
270/// `PartialImage` is emitted 0-3 times per call when the tool is configured
271/// with `partial_images`.
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
273pub enum ImageGenerationCallEvent {
274    InProgress,
275    Generating,
276    PartialImage,
277    Completed,
278}
279
280impl ImageGenerationCallEvent {
281    pub const IN_PROGRESS: &'static str = "response.image_generation_call.in_progress";
282    pub const GENERATING: &'static str = "response.image_generation_call.generating";
283    pub const PARTIAL_IMAGE: &'static str = "response.image_generation_call.partial_image";
284    pub const COMPLETED: &'static str = "response.image_generation_call.completed";
285
286    pub const fn as_str(self) -> &'static str {
287        match self {
288            Self::InProgress => Self::IN_PROGRESS,
289            Self::Generating => Self::GENERATING,
290            Self::PartialImage => Self::PARTIAL_IMAGE,
291            Self::Completed => Self::COMPLETED,
292        }
293    }
294}
295
296impl fmt::Display for ImageGenerationCallEvent {
297    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298        f.write_str(self.as_str())
299    }
300}
301
302/// Item type discriminators used in output items
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304pub enum ItemType {
305    FunctionCall,
306    FunctionToolCall,
307    McpCall,
308    Function,
309    McpListTools,
310    WebSearchCall,
311    CodeInterpreterCall,
312    FileSearchCall,
313    ImageGenerationCall,
314}
315
316impl ItemType {
317    pub const FUNCTION_CALL: &'static str = "function_call";
318    pub const FUNCTION_CALL_OUTPUT: &'static str = "function_call_output";
319    pub const FUNCTION_TOOL_CALL: &'static str = "function_tool_call";
320    pub const MCP_CALL: &'static str = "mcp_call";
321    pub const FUNCTION: &'static str = "function";
322    pub const MCP_LIST_TOOLS: &'static str = "mcp_list_tools";
323    pub const WEB_SEARCH_CALL: &'static str = "web_search_call";
324    pub const CODE_INTERPRETER_CALL: &'static str = "code_interpreter_call";
325    pub const FILE_SEARCH_CALL: &'static str = "file_search_call";
326    pub const IMAGE_GENERATION_CALL: &'static str = "image_generation_call";
327
328    pub const fn as_str(self) -> &'static str {
329        match self {
330            Self::FunctionCall => Self::FUNCTION_CALL,
331            Self::FunctionToolCall => Self::FUNCTION_TOOL_CALL,
332            Self::McpCall => Self::MCP_CALL,
333            Self::Function => Self::FUNCTION,
334            Self::McpListTools => Self::MCP_LIST_TOOLS,
335            Self::WebSearchCall => Self::WEB_SEARCH_CALL,
336            Self::CodeInterpreterCall => Self::CODE_INTERPRETER_CALL,
337            Self::FileSearchCall => Self::FILE_SEARCH_CALL,
338            Self::ImageGenerationCall => Self::IMAGE_GENERATION_CALL,
339        }
340    }
341
342    /// Check if this is a function call variant (FunctionCall or FunctionToolCall)
343    pub const fn is_function_call(self) -> bool {
344        matches!(self, Self::FunctionCall | Self::FunctionToolCall)
345    }
346
347    /// Check if this is a builtin tool call variant
348    pub const fn is_builtin_tool_call(self) -> bool {
349        matches!(
350            self,
351            Self::WebSearchCall
352                | Self::CodeInterpreterCall
353                | Self::FileSearchCall
354                | Self::ImageGenerationCall
355        )
356    }
357}
358
359impl fmt::Display for ItemType {
360    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361        f.write_str(self.as_str())
362    }
363}
364
365// ============================================================================
366// Realtime Client Events
367// ============================================================================
368
369/// Realtime API client events sent over WebSocket/WebRTC/SIP connections.
370#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
371pub enum RealtimeClientEvent {
372    ConversationItemCreate,
373    ConversationItemDelete,
374    ConversationItemRetrieve,
375    ConversationItemTruncate,
376    InputAudioBufferAppend,
377    InputAudioBufferClear,
378    InputAudioBufferCommit,
379    OutputAudioBufferClear,
380    ResponseCancel,
381    ResponseCreate,
382    SessionUpdate,
383}
384
385impl RealtimeClientEvent {
386    pub const CONVERSATION_ITEM_CREATE: &'static str = "conversation.item.create";
387    pub const CONVERSATION_ITEM_DELETE: &'static str = "conversation.item.delete";
388    pub const CONVERSATION_ITEM_RETRIEVE: &'static str = "conversation.item.retrieve";
389    pub const CONVERSATION_ITEM_TRUNCATE: &'static str = "conversation.item.truncate";
390    pub const INPUT_AUDIO_BUFFER_APPEND: &'static str = "input_audio_buffer.append";
391    pub const INPUT_AUDIO_BUFFER_CLEAR: &'static str = "input_audio_buffer.clear";
392    pub const INPUT_AUDIO_BUFFER_COMMIT: &'static str = "input_audio_buffer.commit";
393    pub const OUTPUT_AUDIO_BUFFER_CLEAR: &'static str = "output_audio_buffer.clear";
394    pub const RESPONSE_CANCEL: &'static str = "response.cancel";
395    pub const RESPONSE_CREATE: &'static str = "response.create";
396    pub const SESSION_UPDATE: &'static str = "session.update";
397
398    pub const fn as_str(self) -> &'static str {
399        match self {
400            Self::ConversationItemCreate => Self::CONVERSATION_ITEM_CREATE,
401            Self::ConversationItemDelete => Self::CONVERSATION_ITEM_DELETE,
402            Self::ConversationItemRetrieve => Self::CONVERSATION_ITEM_RETRIEVE,
403            Self::ConversationItemTruncate => Self::CONVERSATION_ITEM_TRUNCATE,
404            Self::InputAudioBufferAppend => Self::INPUT_AUDIO_BUFFER_APPEND,
405            Self::InputAudioBufferClear => Self::INPUT_AUDIO_BUFFER_CLEAR,
406            Self::InputAudioBufferCommit => Self::INPUT_AUDIO_BUFFER_COMMIT,
407            Self::OutputAudioBufferClear => Self::OUTPUT_AUDIO_BUFFER_CLEAR,
408            Self::ResponseCancel => Self::RESPONSE_CANCEL,
409            Self::ResponseCreate => Self::RESPONSE_CREATE,
410            Self::SessionUpdate => Self::SESSION_UPDATE,
411        }
412    }
413}
414
415impl fmt::Display for RealtimeClientEvent {
416    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417        f.write_str(self.as_str())
418    }
419}
420
421// ============================================================================
422// Realtime Server Events
423// ============================================================================
424
425/// Realtime API server events received over WebSocket/WebRTC/SIP connections.
426#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
427pub enum RealtimeServerEvent {
428    // Session events
429    SessionCreated,
430    SessionUpdated,
431    // Conversation events
432    ConversationCreated,
433    ConversationItemCreated,
434    ConversationItemAdded,
435    ConversationItemDone,
436    ConversationItemDeleted,
437    ConversationItemRetrieved,
438    ConversationItemTruncated,
439    // Input audio transcription events
440    ConversationItemInputAudioTranscriptionCompleted,
441    ConversationItemInputAudioTranscriptionDelta,
442    ConversationItemInputAudioTranscriptionFailed,
443    ConversationItemInputAudioTranscriptionSegment,
444    // Input audio buffer events
445    InputAudioBufferCleared,
446    InputAudioBufferCommitted,
447    InputAudioBufferSpeechStarted,
448    InputAudioBufferSpeechStopped,
449    InputAudioBufferTimeoutTriggered,
450    InputAudioBufferDtmfEventReceived,
451    // Output audio buffer events (WebRTC/SIP only)
452    OutputAudioBufferStarted,
453    OutputAudioBufferStopped,
454    OutputAudioBufferCleared,
455    // Response lifecycle events
456    ResponseCreated,
457    ResponseDone,
458    // Response output item events
459    ResponseOutputItemAdded,
460    ResponseOutputItemDone,
461    // Response content part events
462    ResponseContentPartAdded,
463    ResponseContentPartDone,
464    // Response text events
465    ResponseOutputTextDelta,
466    ResponseOutputTextDone,
467    // Response audio events
468    ResponseOutputAudioDelta,
469    ResponseOutputAudioDone,
470    // Response audio transcript events
471    ResponseOutputAudioTranscriptDelta,
472    ResponseOutputAudioTranscriptDone,
473    // Response function call events
474    ResponseFunctionCallArgumentsDelta,
475    ResponseFunctionCallArgumentsDone,
476    // Response MCP call events
477    ResponseMcpCallArgumentsDelta,
478    ResponseMcpCallArgumentsDone,
479    ResponseMcpCallInProgress,
480    ResponseMcpCallCompleted,
481    ResponseMcpCallFailed,
482    // MCP list tools events
483    McpListToolsInProgress,
484    McpListToolsCompleted,
485    McpListToolsFailed,
486    // Rate limits
487    RateLimitsUpdated,
488    // Error
489    Error,
490}
491
492impl RealtimeServerEvent {
493    // Session events
494    pub const SESSION_CREATED: &'static str = "session.created";
495    pub const SESSION_UPDATED: &'static str = "session.updated";
496    // Conversation events
497    pub const CONVERSATION_CREATED: &'static str = "conversation.created";
498    pub const CONVERSATION_ITEM_CREATED: &'static str = "conversation.item.created";
499    pub const CONVERSATION_ITEM_ADDED: &'static str = "conversation.item.added";
500    pub const CONVERSATION_ITEM_DONE: &'static str = "conversation.item.done";
501    pub const CONVERSATION_ITEM_DELETED: &'static str = "conversation.item.deleted";
502    pub const CONVERSATION_ITEM_RETRIEVED: &'static str = "conversation.item.retrieved";
503    pub const CONVERSATION_ITEM_TRUNCATED: &'static str = "conversation.item.truncated";
504    // Input audio transcription events
505    pub const CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED: &'static str =
506        "conversation.item.input_audio_transcription.completed";
507    pub const CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA: &'static str =
508        "conversation.item.input_audio_transcription.delta";
509    pub const CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_FAILED: &'static str =
510        "conversation.item.input_audio_transcription.failed";
511    pub const CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_SEGMENT: &'static str =
512        "conversation.item.input_audio_transcription.segment";
513    // Input audio buffer events
514    pub const INPUT_AUDIO_BUFFER_CLEARED: &'static str = "input_audio_buffer.cleared";
515    pub const INPUT_AUDIO_BUFFER_COMMITTED: &'static str = "input_audio_buffer.committed";
516    pub const INPUT_AUDIO_BUFFER_SPEECH_STARTED: &'static str = "input_audio_buffer.speech_started";
517    pub const INPUT_AUDIO_BUFFER_SPEECH_STOPPED: &'static str = "input_audio_buffer.speech_stopped";
518    pub const INPUT_AUDIO_BUFFER_TIMEOUT_TRIGGERED: &'static str =
519        "input_audio_buffer.timeout_triggered";
520    pub const INPUT_AUDIO_BUFFER_DTMF_EVENT_RECEIVED: &'static str =
521        "input_audio_buffer.dtmf_event_received";
522    // Output audio buffer events
523    pub const OUTPUT_AUDIO_BUFFER_STARTED: &'static str = "output_audio_buffer.started";
524    pub const OUTPUT_AUDIO_BUFFER_STOPPED: &'static str = "output_audio_buffer.stopped";
525    pub const OUTPUT_AUDIO_BUFFER_CLEARED: &'static str = "output_audio_buffer.cleared";
526    // Response lifecycle events
527    pub const RESPONSE_CREATED: &'static str = "response.created";
528    pub const RESPONSE_DONE: &'static str = "response.done";
529    // Response output item events
530    pub const RESPONSE_OUTPUT_ITEM_ADDED: &'static str = "response.output_item.added";
531    pub const RESPONSE_OUTPUT_ITEM_DONE: &'static str = "response.output_item.done";
532    // Response content part events
533    pub const RESPONSE_CONTENT_PART_ADDED: &'static str = "response.content_part.added";
534    pub const RESPONSE_CONTENT_PART_DONE: &'static str = "response.content_part.done";
535    // Response text events
536    pub const RESPONSE_OUTPUT_TEXT_DELTA: &'static str = "response.output_text.delta";
537    pub const RESPONSE_OUTPUT_TEXT_DONE: &'static str = "response.output_text.done";
538    // Response audio events
539    pub const RESPONSE_OUTPUT_AUDIO_DELTA: &'static str = "response.output_audio.delta";
540    pub const RESPONSE_OUTPUT_AUDIO_DONE: &'static str = "response.output_audio.done";
541    // Response audio transcript events
542    pub const RESPONSE_OUTPUT_AUDIO_TRANSCRIPT_DELTA: &'static str =
543        "response.output_audio_transcript.delta";
544    pub const RESPONSE_OUTPUT_AUDIO_TRANSCRIPT_DONE: &'static str =
545        "response.output_audio_transcript.done";
546    // Response function call events
547    pub const RESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA: &'static str =
548        "response.function_call_arguments.delta";
549    pub const RESPONSE_FUNCTION_CALL_ARGUMENTS_DONE: &'static str =
550        "response.function_call_arguments.done";
551    // Response MCP call events
552    pub const RESPONSE_MCP_CALL_ARGUMENTS_DELTA: &'static str = "response.mcp_call_arguments.delta";
553    pub const RESPONSE_MCP_CALL_ARGUMENTS_DONE: &'static str = "response.mcp_call_arguments.done";
554    pub const RESPONSE_MCP_CALL_IN_PROGRESS: &'static str = "response.mcp_call.in_progress";
555    pub const RESPONSE_MCP_CALL_COMPLETED: &'static str = "response.mcp_call.completed";
556    pub const RESPONSE_MCP_CALL_FAILED: &'static str = "response.mcp_call.failed";
557    // MCP list tools events
558    pub const MCP_LIST_TOOLS_IN_PROGRESS: &'static str = "mcp_list_tools.in_progress";
559    pub const MCP_LIST_TOOLS_COMPLETED: &'static str = "mcp_list_tools.completed";
560    pub const MCP_LIST_TOOLS_FAILED: &'static str = "mcp_list_tools.failed";
561    // Rate limits
562    pub const RATE_LIMITS_UPDATED: &'static str = "rate_limits.updated";
563    // Error
564    pub const ERROR: &'static str = "error";
565
566    pub const fn as_str(self) -> &'static str {
567        match self {
568            Self::SessionCreated => Self::SESSION_CREATED,
569            Self::SessionUpdated => Self::SESSION_UPDATED,
570            Self::ConversationCreated => Self::CONVERSATION_CREATED,
571            Self::ConversationItemCreated => Self::CONVERSATION_ITEM_CREATED,
572            Self::ConversationItemAdded => Self::CONVERSATION_ITEM_ADDED,
573            Self::ConversationItemDone => Self::CONVERSATION_ITEM_DONE,
574            Self::ConversationItemDeleted => Self::CONVERSATION_ITEM_DELETED,
575            Self::ConversationItemRetrieved => Self::CONVERSATION_ITEM_RETRIEVED,
576            Self::ConversationItemTruncated => Self::CONVERSATION_ITEM_TRUNCATED,
577            Self::ConversationItemInputAudioTranscriptionCompleted => {
578                Self::CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED
579            }
580            Self::ConversationItemInputAudioTranscriptionDelta => {
581                Self::CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA
582            }
583            Self::ConversationItemInputAudioTranscriptionFailed => {
584                Self::CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_FAILED
585            }
586            Self::ConversationItemInputAudioTranscriptionSegment => {
587                Self::CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_SEGMENT
588            }
589            Self::InputAudioBufferCleared => Self::INPUT_AUDIO_BUFFER_CLEARED,
590            Self::InputAudioBufferCommitted => Self::INPUT_AUDIO_BUFFER_COMMITTED,
591            Self::InputAudioBufferSpeechStarted => Self::INPUT_AUDIO_BUFFER_SPEECH_STARTED,
592            Self::InputAudioBufferSpeechStopped => Self::INPUT_AUDIO_BUFFER_SPEECH_STOPPED,
593            Self::InputAudioBufferTimeoutTriggered => Self::INPUT_AUDIO_BUFFER_TIMEOUT_TRIGGERED,
594            Self::InputAudioBufferDtmfEventReceived => Self::INPUT_AUDIO_BUFFER_DTMF_EVENT_RECEIVED,
595            Self::OutputAudioBufferStarted => Self::OUTPUT_AUDIO_BUFFER_STARTED,
596            Self::OutputAudioBufferStopped => Self::OUTPUT_AUDIO_BUFFER_STOPPED,
597            Self::OutputAudioBufferCleared => Self::OUTPUT_AUDIO_BUFFER_CLEARED,
598            Self::ResponseCreated => Self::RESPONSE_CREATED,
599            Self::ResponseDone => Self::RESPONSE_DONE,
600            Self::ResponseOutputItemAdded => Self::RESPONSE_OUTPUT_ITEM_ADDED,
601            Self::ResponseOutputItemDone => Self::RESPONSE_OUTPUT_ITEM_DONE,
602            Self::ResponseContentPartAdded => Self::RESPONSE_CONTENT_PART_ADDED,
603            Self::ResponseContentPartDone => Self::RESPONSE_CONTENT_PART_DONE,
604            Self::ResponseOutputTextDelta => Self::RESPONSE_OUTPUT_TEXT_DELTA,
605            Self::ResponseOutputTextDone => Self::RESPONSE_OUTPUT_TEXT_DONE,
606            Self::ResponseOutputAudioDelta => Self::RESPONSE_OUTPUT_AUDIO_DELTA,
607            Self::ResponseOutputAudioDone => Self::RESPONSE_OUTPUT_AUDIO_DONE,
608            Self::ResponseOutputAudioTranscriptDelta => {
609                Self::RESPONSE_OUTPUT_AUDIO_TRANSCRIPT_DELTA
610            }
611            Self::ResponseOutputAudioTranscriptDone => Self::RESPONSE_OUTPUT_AUDIO_TRANSCRIPT_DONE,
612            Self::ResponseFunctionCallArgumentsDelta => {
613                Self::RESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA
614            }
615            Self::ResponseFunctionCallArgumentsDone => Self::RESPONSE_FUNCTION_CALL_ARGUMENTS_DONE,
616            Self::ResponseMcpCallArgumentsDelta => Self::RESPONSE_MCP_CALL_ARGUMENTS_DELTA,
617            Self::ResponseMcpCallArgumentsDone => Self::RESPONSE_MCP_CALL_ARGUMENTS_DONE,
618            Self::ResponseMcpCallInProgress => Self::RESPONSE_MCP_CALL_IN_PROGRESS,
619            Self::ResponseMcpCallCompleted => Self::RESPONSE_MCP_CALL_COMPLETED,
620            Self::ResponseMcpCallFailed => Self::RESPONSE_MCP_CALL_FAILED,
621            Self::McpListToolsInProgress => Self::MCP_LIST_TOOLS_IN_PROGRESS,
622            Self::McpListToolsCompleted => Self::MCP_LIST_TOOLS_COMPLETED,
623            Self::McpListToolsFailed => Self::MCP_LIST_TOOLS_FAILED,
624            Self::RateLimitsUpdated => Self::RATE_LIMITS_UPDATED,
625            Self::Error => Self::ERROR,
626        }
627    }
628}
629
630impl fmt::Display for RealtimeServerEvent {
631    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632        f.write_str(self.as_str())
633    }
634}
635
636/// Check if an event type string matches any response lifecycle event
637pub fn is_response_event(event_type: &str) -> bool {
638    matches!(
639        event_type,
640        ResponseEvent::CREATED | ResponseEvent::IN_PROGRESS | ResponseEvent::COMPLETED
641    )
642}
643
644/// Check if an item type string is a function call variant
645pub fn is_function_call_type(item_type: &str) -> bool {
646    item_type == ItemType::FUNCTION_CALL || item_type == ItemType::FUNCTION_TOOL_CALL
647}