1use serde::{Deserialize, Serialize};
9
10use crate::common::Redacted;
11
12#[serde_with::skip_serializing_none]
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(tag = "type", rename_all = "snake_case")]
38pub enum RealtimeConversationItem {
39 Message {
40 content: Vec<RealtimeContentPart>,
41 role: ConversationItemRole,
42 id: Option<String>,
43 object: Option<ConversationItemObject>,
44 status: Option<ConversationItemStatus>,
45 },
46 FunctionCall {
47 arguments: String,
48 name: String,
49 id: Option<String>,
50 call_id: Option<String>,
51 object: Option<ConversationItemObject>,
52 status: Option<ConversationItemStatus>,
53 },
54 FunctionCallOutput {
55 call_id: String,
56 output: String,
57 id: Option<String>,
58 object: Option<ConversationItemObject>,
59 status: Option<ConversationItemStatus>,
60 },
61 McpApprovalResponse {
62 id: String,
63 approval_request_id: String,
64 approve: bool,
65 reason: Option<String>,
66 },
67 McpListTools {
68 server_label: String,
69 tools: Vec<McpListToolEntry>,
70 id: Option<String>,
71 },
72 McpCall {
73 id: String,
74 arguments: String,
75 name: String,
76 server_label: String,
77 approval_request_id: Option<String>,
78 error: Option<McpCallError>,
79 output: Option<String>,
80 },
81 McpApprovalRequest {
82 id: String,
83 arguments: String,
84 name: String,
85 server_label: String,
86 },
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
91pub enum ConversationItemObject {
92 #[serde(rename = "realtime.item")]
93 RealtimeItem,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
98#[serde(rename_all = "snake_case")]
99pub enum ConversationItemStatus {
100 Completed,
101 Incomplete,
102 InProgress,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
107#[serde(rename_all = "snake_case")]
108pub enum ConversationItemRole {
109 User,
110 Assistant,
111 System,
112}
113
114#[serde_with::skip_serializing_none]
121#[derive(Debug, Clone, Serialize, Deserialize)]
122#[serde(tag = "type", rename_all = "snake_case")]
123pub enum RealtimeContentPart {
124 InputText {
125 text: Option<String>,
126 },
127 InputAudio {
128 audio: Option<Redacted>,
129 transcript: Option<String>,
130 },
131 InputImage {
132 detail: Option<ImageDetail>,
133 image_url: Option<Redacted>,
134 },
135 OutputText {
136 text: Option<String>,
137 },
138 OutputAudio {
139 audio: Option<Redacted>,
140 transcript: Option<String>,
141 },
142}
143
144impl RealtimeContentPart {
145 pub const fn type_name(&self) -> &'static str {
147 match self {
148 Self::InputText { .. } => "input_text",
149 Self::InputAudio { .. } => "input_audio",
150 Self::InputImage { .. } => "input_image",
151 Self::OutputText { .. } => "output_text",
152 Self::OutputAudio { .. } => "output_audio",
153 }
154 }
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize, Default)]
159#[serde(rename_all = "snake_case")]
160pub enum ImageDetail {
161 #[default]
162 Auto,
163 Low,
164 High,
165}
166
167#[serde_with::skip_serializing_none]
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct McpListToolEntry {
175 pub input_schema: serde_json::Value,
176 pub name: String,
177 pub annotations: Option<serde_json::Value>,
178 pub description: Option<String>,
179}
180
181#[expect(clippy::enum_variant_names)]
185#[serde_with::skip_serializing_none]
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(tag = "type", rename_all = "snake_case")]
188pub enum McpCallError {
189 ProtocolError { code: i64, message: String },
191 ToolExecutionError { message: String },
193 HttpError { code: i64, message: String },
195}