ai_providers/openai/request/input_models/
item.rs

1use crate::openai::errors::InputError;
2use crate::openai::request::input_models::common::{Content, Role};
3
4use crate::openai::common::{
5    computer_tool_call_item::ComputerToolCallItem, file_search_tool_item::FileSearchToolCallItem,
6    function_tool_call_item::FunctionToolCallItem, output_message_item::OutputMessageItem,
7    reasoning_item::ReasoningItem, status::Status,
8    web_search_tool_call_item::WebSearchToolCallItem,
9};
10use std::str::FromStr;
11
12use serde::{Deserialize, Serialize};
13
14#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Default)]
15pub struct InputMessageItem {
16    pub content: Vec<Content>,
17    pub role: Role,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub status: Option<Status>,
20    #[serde(rename = "type")]
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub type_field: Option<String>,
23}
24
25impl InputMessageItem {
26    pub fn new() -> Self {
27        Self::default()
28    }
29
30    pub fn role(mut self, role: impl AsRef<str>) -> Result<Self, InputError> {
31        if role.as_ref().eq("assistant") {
32            Err(InputError::InvalidRole("assistant".to_string()))
33        } else {
34            self.role = Role::from_str(role.as_ref()).map_err(InputError::ConversionError)?;
35            Ok(self)
36        }
37    }
38
39    pub fn insert_type(mut self) -> Self {
40        self.type_field = Some("message".to_string());
41        self
42    }
43}
44
45#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
46pub struct ComputerToolCallOutputItemOutput {
47    #[serde(rename = "type")]
48    pub type_field: String,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub file_id: Option<String>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub image_url: Option<String>,
53}
54
55impl Default for ComputerToolCallOutputItemOutput {
56    fn default() -> Self {
57        Self {
58            type_field: "computer_screenshot".to_string(),
59            image_url: None,
60            file_id: None,
61        }
62    }
63}
64
65impl ComputerToolCallOutputItemOutput {
66    pub fn new() -> Self {
67        Self::default()
68    }
69
70    pub fn file_id(mut self, value: impl Into<String>) -> Self {
71        self.file_id = Some(value.into());
72        self
73    }
74
75    pub fn image_url(mut self, value: impl Into<String>) -> Self {
76        self.image_url = Some(value.into());
77        self
78    }
79}
80
81#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
82pub struct AcknowledgedSafetyChecks {
83    pub id: String,
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub code: Option<String>,
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub message: Option<String>,
88}
89
90impl AcknowledgedSafetyChecks {
91    pub fn new(id: impl Into<String>) -> Self {
92        Self {
93            id: id.into(),
94            code: None,
95            message: None,
96        }
97    }
98
99    pub fn code(mut self, value: impl Into<String>) -> Self {
100        self.code = Some(value.into());
101        self
102    }
103
104    pub fn message(mut self, value: impl Into<String>) -> Self {
105        self.message = Some(value.into());
106        self
107    }
108}
109
110#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
111pub struct ComputerToolCallOutputItem {
112    pub call_id: String,
113    pub output: ComputerToolCallOutputItemOutput,
114    #[serde(rename = "type")]
115    pub type_field: String,
116    pub acknowledged_safety_checks: Option<Vec<AcknowledgedSafetyChecks>>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub id: Option<String>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub status: Option<Status>,
121}
122
123impl ComputerToolCallOutputItem {
124    pub fn new(call_id: impl Into<String>, output: ComputerToolCallOutputItemOutput) -> Self {
125        Self {
126            call_id: call_id.into(),
127            output,
128            type_field: "computer_call_output".to_string(),
129            acknowledged_safety_checks: None,
130            id: None,
131            status: None,
132        }
133    }
134
135    pub fn acknowledged_safety_checks(mut self, value: Vec<AcknowledgedSafetyChecks>) -> Self {
136        self.acknowledged_safety_checks = Some(value);
137        self
138    }
139
140    pub fn id(mut self, value: impl Into<String>) -> Self {
141        self.id = Some(value.into());
142        self
143    }
144
145    pub fn status(mut self, value: Status) -> Self {
146        self.status = Some(value);
147        self
148    }
149}
150
151#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
152pub struct FunctionToolCallOutputItem {
153    pub call_id: String,
154    pub output: String,
155    #[serde(rename = "type")]
156    pub type_field: String,
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub id: Option<String>,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub status: Option<Status>,
161}
162
163impl FunctionToolCallOutputItem {
164    pub fn new(call_id: impl Into<String>, output: impl Into<String>) -> Self {
165        Self {
166            call_id: call_id.into(),
167            output: output.into(),
168            type_field: "function_call_output".to_string(),
169            id: None,
170            status: None,
171        }
172    }
173
174    pub fn id(mut self, value: impl Into<String>) -> Self {
175        self.id = Some(value.into());
176        self
177    }
178
179    pub fn status(mut self, value: Status) -> Self {
180        self.status = Some(value);
181        self
182    }
183}
184
185#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
186pub struct Summary {
187    pub text: String,
188    #[serde(rename = "type")]
189    pub type_field: String,
190}
191
192impl Summary {
193    pub fn new(text: impl Into<String>) -> Self {
194        Self {
195            text: text.into(),
196            type_field: "summary_text".to_string(),
197        }
198    }
199}
200
201#[derive(Debug, PartialEq, Serialize, Deserialize)]
202#[serde(untagged)]
203pub enum Item {
204    InputMessage(InputMessageItem),
205    OutputMessage(OutputMessageItem),
206    FileSearchToolCall(FileSearchToolCallItem),
207    ComputerToolCall(ComputerToolCallItem),
208    ComputerToolCallOutput(ComputerToolCallOutputItem),
209    WebSearchToolCall(WebSearchToolCallItem),
210    FunctionToolCall(FunctionToolCallItem),
211    FunctionToolCallOutput(FunctionToolCallOutputItem),
212    Reasoning(ReasoningItem),
213}
214
215impl From<InputMessageItem> for Item {
216    fn from(item: InputMessageItem) -> Self {
217        Item::InputMessage(item)
218    }
219}
220
221impl From<OutputMessageItem> for Item {
222    fn from(item: OutputMessageItem) -> Self {
223        Item::OutputMessage(item)
224    }
225}
226
227impl From<FileSearchToolCallItem> for Item {
228    fn from(item: FileSearchToolCallItem) -> Self {
229        Item::FileSearchToolCall(item)
230    }
231}
232
233impl From<ComputerToolCallItem> for Item {
234    fn from(item: ComputerToolCallItem) -> Self {
235        Item::ComputerToolCall(item)
236    }
237}
238
239impl From<ComputerToolCallOutputItem> for Item {
240    fn from(item: ComputerToolCallOutputItem) -> Self {
241        Item::ComputerToolCallOutput(item)
242    }
243}
244
245impl From<WebSearchToolCallItem> for Item {
246    fn from(item: WebSearchToolCallItem) -> Self {
247        Item::WebSearchToolCall(item)
248    }
249}
250
251impl From<FunctionToolCallItem> for Item {
252    fn from(item: FunctionToolCallItem) -> Self {
253        Item::FunctionToolCall(item)
254    }
255}
256
257impl From<FunctionToolCallOutputItem> for Item {
258    fn from(item: FunctionToolCallOutputItem) -> Self {
259        Item::FunctionToolCallOutput(item)
260    }
261}
262
263impl From<ReasoningItem> for Item {
264    fn from(item: ReasoningItem) -> Self {
265        Item::Reasoning(item)
266    }
267}