Skip to main content

outfox_openai/spec/realtime/
conversation_item.rs

1use serde::{Deserialize, Serialize};
2
3use crate::spec::mcp::MCPListToolsTool;
4use crate::spec::realtime::{ErrorCodeMessage, ErrorMessage};
5
6#[derive(Debug, Serialize, Deserialize, Clone)]
7pub struct SystemMessageContent {
8    /// The text content.
9    pub text: String,
10    /// The content type. Always `input_text` for system messages.
11    pub kind: String,
12}
13
14#[derive(Debug, Serialize, Deserialize, Clone)]
15pub struct RealtimeConversationItemMessageSystem {
16    /// The content of the message.
17    pub content: Vec<SystemMessageContent>,
18
19    /// The unique ID of the item. This may be provided by the client or generated by the server.
20    pub id: Option<String>,
21
22    /// Identifier for the API object being returned - always `realtime.item`.
23    /// Optional when creating a new item.
24    pub object: Option<String>,
25
26    /// The status of the item. Has no effect on the conversation.
27    pub status: Option<String>,
28}
29
30#[derive(Debug, Serialize, Deserialize, Clone)]
31pub struct UserMessageContentInputText {
32    /// The text content (for `input_text`).
33    pub text: String,
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone)]
37pub struct UserMessageContentInputAudio {
38    /// Base64-encoded audio bytes (for `input_audio`), these will be parsed as the
39    /// format specified in the session input audio type configuration.
40    /// This defaults to PCM 16-bit 24kHz mono if not specified.
41    pub audio: String,
42    /// Transcript of the audio (for `input_audio`). This is not sent to the model,
43    /// but will be attached to the message item for reference.
44    pub transcript: String,
45}
46
47#[derive(Debug, Serialize, Deserialize, Clone, Default)]
48#[serde(rename_all = "snake_case")]
49pub enum ImageDetail {
50    #[default]
51    Auto,
52    Low,
53    High,
54}
55
56#[derive(Debug, Serialize, Deserialize, Clone)]
57pub struct UserMessageContentInputImage {
58    /// Base64-encoded image bytes (for `input_image`) as a data URI.
59    /// For example `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...`.
60    /// Supported formats are PNG and JPEG.
61    pub image_url: String,
62    /// The detail level of the image (for `input_image`). `auto` will default to `high`.
63    pub detail: ImageDetail,
64}
65
66#[derive(Debug, Serialize, Deserialize, Clone)]
67#[serde(tag = "type")]
68#[serde(rename_all = "snake_case")]
69pub enum UserMessageContent {
70    InputText(UserMessageContentInputText),
71    InputAudio(UserMessageContentInputAudio),
72    InputImage(UserMessageContentInputImage),
73}
74
75#[derive(Debug, Serialize, Deserialize, Clone)]
76pub struct RealtimeConversationItemMessageUser {
77    /// The content of the message.
78    pub content: Vec<UserMessageContent>,
79
80    /// The unique ID of the item. This may be provided by the client or generated by the server.
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub id: Option<String>,
83
84    /// Identifier for the API object being returned - always `realtime.item`.
85    /// Optional when creating a new item.
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub object: Option<String>,
88
89    /// The status of the item. Has no effect on the conversation.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub status: Option<String>,
92}
93
94#[derive(Debug, Serialize, Deserialize, Clone)]
95pub struct AssistantMessageContentOutputText {
96    /// The text content
97    pub text: String,
98}
99
100#[derive(Debug, Serialize, Deserialize, Clone)]
101pub struct AssistantMessageContentOutputAudio {
102    /// Base64-encoded audio bytes, these will be parsed as the format specified
103    /// in the session output audio type configuration. This defaults to PCM 16-bit
104    /// 24kHz mono if not specified.
105    pub audio: Option<String>,
106    /// The transcript of the audio content, this will always be present if the
107    /// output type is `audio`.
108    pub transcript: String,
109}
110
111#[derive(Debug, Serialize, Deserialize, Clone)]
112#[serde(tag = "type")]
113#[serde(rename_all = "snake_case")]
114pub enum AssistantMessageContent {
115    OutputText(AssistantMessageContentOutputText),
116    OutputAudio(AssistantMessageContentOutputAudio),
117}
118
119#[derive(Debug, Serialize, Deserialize, Clone)]
120pub struct RealtimeConversationItemMessageAssistant {
121    /// The content of the message.
122    pub content: Vec<AssistantMessageContent>,
123
124    /// The unique ID of the item. This may be provided by the client or generated by the server.
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub id: Option<String>,
127
128    /// Identifier for the API object being returned - always `realtime.item`.
129    /// Optional when creating a new item.
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub object: Option<String>,
132
133    /// The status of the item. Has no effect on the conversation.
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub status: Option<String>,
136}
137
138#[derive(Debug, Serialize, Deserialize, Clone)]
139#[serde(tag = "role")]
140#[serde(rename_all = "lowercase")]
141pub enum RealtimeConversationItemMessage {
142    System(RealtimeConversationItemMessageSystem),
143    User(RealtimeConversationItemMessageUser),
144    Assistant(RealtimeConversationItemMessageAssistant),
145}
146
147#[derive(Debug, Serialize, Deserialize, Clone)]
148pub struct RealtimeConversationItemFunctionCall {
149    /// The arguments of the function call. This is a JSON-encoded string representing
150    /// the arguments passed to the function, for example {"arg1": "value1", "arg2": 42}.
151    pub arguments: String,
152
153    /// The name of the function being called.
154    pub name: String,
155
156    /// The ID of the function call.
157    pub call_id: String,
158
159    /// The unique ID of the item. This may be provided by the client or generated by the server.
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub id: Option<String>,
162
163    /// Identifier for the API object being returned - always `realtime.item`.
164    /// Optional when creating a new item.
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub object: Option<String>,
167
168    /// The status of the item. Has no effect on the conversation.
169    pub status: String,
170}
171
172#[derive(Debug, Serialize, Deserialize, Clone)]
173pub struct RealtimeConversationItemFunctionCallOutput {
174    /// The ID of the function call this output is for.
175    pub call_id: String,
176
177    /// The output of the function call, this is free text and can contain any information
178    /// or simply be empty.
179    pub output: String,
180
181    /// The unique ID of the item. This may be provided by the client or generated by the server.
182    #[serde(skip_serializing_if = "Option::is_none")]
183    pub id: Option<String>,
184
185    /// Identifier for the API object being returned - always `realtime.item`.
186    /// Optional when creating a new item.
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub object: Option<String>,
189
190    /// The status of the item. Has no effect on the conversation.
191    pub status: String,
192}
193
194#[derive(Debug, Serialize, Deserialize, Clone)]
195pub struct RealtimeMCPApprovalResponse {
196    /// The ID of the approval request being answered.
197    pub approval_request_id: String,
198
199    /// Whether the request was approved.
200    pub approved: bool,
201
202    /// The unique ID of the approval response.
203    pub id: String,
204
205    /// Optional reason for the decision.
206    pub reason: Option<String>,
207}
208
209#[derive(Debug, Serialize, Deserialize, Clone)]
210pub struct RealtimeMCPListTools {
211    /// The label of the MCP server.
212    pub server_label: String,
213
214    /// The tools available on the server.
215    pub tools: Vec<MCPListToolsTool>,
216
217    /// The unique ID of the list.
218    pub id: String,
219}
220
221#[derive(Debug, Serialize, Deserialize, Clone)]
222pub struct RealtimeMCPApprovalRequest {
223    /// A JSON string of arguments for the tool.
224    pub arguments: String,
225
226    /// The unique ID of the approval request.
227    pub id: String,
228
229    /// The name of the tool to run.
230    pub name: String,
231
232    /// The label of the MCP server making the request.
233    pub server_label: String,
234}
235
236#[derive(Debug, Serialize, Deserialize, Clone)]
237pub struct RealtimeMCPProtocolError {}
238
239#[derive(Debug, Serialize, Deserialize, Clone)]
240#[serde(tag = "type", rename_all = "snake_case")]
241pub enum RealtimeMCPToolCallError {
242    ProtocolError(ErrorCodeMessage),
243    ToolExecutionError(ErrorMessage),
244    HttpError(ErrorCodeMessage),
245}
246
247#[derive(Debug, Serialize, Deserialize, Clone)]
248pub struct RealtimeMCPToolCall {
249    /// A JSON string of the arguments passed to the tool.
250    pub arguments: String,
251
252    /// The unique ID of the tool call.
253    pub id: String,
254
255    /// The name of the tool that was run.
256    pub name: String,
257
258    /// The label of the MCP server running the tool.
259    pub server_label: String,
260
261    /// The ID of an associated approval request, if any.
262    pub approval_request_id: Option<String>,
263
264    /// The error from the tool call, if any.
265    pub error: Option<RealtimeMCPToolCallError>,
266
267    /// The output from the tool call.
268    pub output: Option<String>,
269}
270
271#[derive(Debug, Serialize, Deserialize, Clone)]
272#[serde(tag = "type", rename_all = "snake_case")]
273pub enum RealtimeConversationItem {
274    Message(RealtimeConversationItemMessage),
275    FunctionCall(RealtimeConversationItemFunctionCall),
276    FunctionCallOutput(RealtimeConversationItemFunctionCallOutput),
277    McpApprovalResponse(RealtimeMCPApprovalResponse),
278    McpListTools(RealtimeMCPListTools),
279    McpCall(RealtimeMCPToolCall),
280    McpApprovalRequest(RealtimeMCPApprovalRequest),
281}
282
283impl TryFrom<serde_json::Value> for RealtimeConversationItem {
284    type Error = serde_json::Error;
285
286    fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
287        serde_json::from_value(value)
288    }
289}