1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::openai::common::*;
7
8use super::*;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(tag = "type")]
12#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
13pub enum ResponseTool {
14 #[serde(rename = "function")]
15 Function {
16 name: String,
17 parameters: ResponseFunctionParameters,
18 #[serde(default, skip_serializing_if = "ResponseFunctionStrict::is_absent")]
20 strict: ResponseFunctionStrict,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 defer_loading: Option<bool>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 description: Option<String>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 output_schema: Option<JsonSchema>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 allowed_callers: Option<Vec<ToolCaller>>,
29 #[serde(rename = "async", skip_serializing_if = "Option::is_none")]
30 async_: Option<bool>,
31 #[serde(default, flatten)]
32 rest: Rest,
33 },
34 #[serde(rename = "file_search")]
35 FileSearch {
36 vector_store_ids: Vec<String>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 filters: Option<FileSearchFilter>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 max_num_results: Option<u32>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 ranking_options: Option<FileSearchRankingOptions>,
43 #[serde(default, flatten)]
44 rest: Rest,
45 },
46 #[serde(rename = "computer")]
47 Computer {
48 #[serde(default, flatten)]
49 rest: Rest,
50 },
51 #[serde(rename = "computer_use_preview")]
52 ComputerUsePreview {
53 display_height: u32,
54 display_width: u32,
55 environment: ComputerUseEnvironment,
56 #[serde(default, flatten)]
57 rest: Rest,
58 },
59 #[serde(rename = "web_search")]
60 WebSearch {
61 #[serde(skip_serializing_if = "Option::is_none")]
62 filters: Option<WebSearchFilters>,
63 #[serde(skip_serializing_if = "Option::is_none")]
66 max_uses: Option<u64>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 search_context_size: Option<SearchContextSize>,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 user_location: Option<WebSearchUserLocation>,
71 #[serde(default, flatten)]
72 rest: Rest,
73 },
74 #[serde(rename = "web_search_2025_08_26")]
75 WebSearch20250826 {
76 #[serde(skip_serializing_if = "Option::is_none")]
77 filters: Option<WebSearchFilters>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 max_uses: Option<u64>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 search_context_size: Option<SearchContextSize>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 user_location: Option<WebSearchUserLocation>,
85 #[serde(default, flatten)]
86 rest: Rest,
87 },
88 #[serde(rename = "web_fetch")]
91 WebFetch {
92 #[serde(skip_serializing_if = "Option::is_none")]
93 allowed_domains: Option<Vec<String>>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 blocked_domains: Option<Vec<String>>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 max_content_tokens: Option<u64>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 max_uses: Option<u64>,
100 #[serde(default, flatten)]
101 rest: Rest,
102 },
103 #[serde(rename = "memory")]
105 Memory {
106 #[serde(default, flatten)]
107 rest: Rest,
108 },
109 #[serde(rename = "x_search")]
110 XSearch {
111 #[serde(default, flatten)]
112 rest: Rest,
113 },
114 #[serde(rename = "collections_search")]
115 CollectionsSearch {
116 vector_store_ids: Vec<String>,
117 #[serde(default, flatten)]
118 rest: Rest,
119 },
120 #[serde(rename = "mcp")]
121 Mcp {
122 server_label: String,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 allowed_tools: Option<McpAllowedTools>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 authorization: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 connector_id: Option<McpConnectorId>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 defer_loading: Option<bool>,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 headers: Option<BTreeMap<String, String>>,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 require_approval: Option<McpRequireApproval>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 server_description: Option<String>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 server_url: Option<String>,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 tunnel_id: Option<String>,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 allowed_callers: Option<Vec<ToolCaller>>,
143 #[serde(default, flatten)]
144 rest: Rest,
145 },
146 #[serde(rename = "code_execution")]
147 CodeExecution {
148 #[serde(default, flatten)]
149 rest: Rest,
150 },
151 #[serde(rename = "code_interpreter")]
152 CodeInterpreter {
153 container: CodeInterpreterContainer,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 allowed_callers: Option<Vec<ToolCaller>>,
156 #[serde(default, flatten)]
157 rest: Rest,
158 },
159 #[serde(rename = "image_generation")]
160 ImageGeneration {
161 #[serde(skip_serializing_if = "Option::is_none")]
162 action: Option<ImageGenerationAction>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 background: Option<ImageBackground>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 input_fidelity: Option<ImageInputFidelity>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 input_image_mask: Option<ImageMask>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 model: Option<OpenAiModelId>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 moderation: Option<ImageModeration>,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 output_compression: Option<u32>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 output_format: Option<ImageOutputFormat>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 partial_images: Option<u32>,
179 #[serde(skip_serializing_if = "Option::is_none")]
180 quality: Option<ImageEditQuality>,
181 #[serde(skip_serializing_if = "Option::is_none")]
182 size: Option<ResponseImageGenerationSize>,
183 #[serde(default, flatten)]
184 rest: Rest,
185 },
186 #[serde(rename = "local_shell")]
187 LocalShell {
188 #[serde(default, flatten)]
189 rest: Rest,
190 },
191 #[serde(rename = "shell")]
192 Shell {
193 #[serde(skip_serializing_if = "Option::is_none")]
194 environment: Option<ResponseShellEnvironment>,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 allowed_callers: Option<Vec<ToolCaller>>,
197 #[serde(default, flatten)]
198 rest: Rest,
199 },
200 #[serde(rename = "custom")]
201 Custom {
202 name: String,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 defer_loading: Option<bool>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 description: Option<String>,
207 #[serde(skip_serializing_if = "Option::is_none")]
208 format: Option<CustomToolInputFormat>,
209 #[serde(skip_serializing_if = "Option::is_none")]
210 allowed_callers: Option<Vec<ToolCaller>>,
211 #[serde(rename = "async", skip_serializing_if = "Option::is_none")]
212 async_: Option<bool>,
213 #[serde(default, flatten)]
214 rest: Rest,
215 },
216 #[serde(rename = "namespace")]
217 Namespace {
218 description: String,
219 name: String,
220 tools: Vec<ResponseNamespaceTool>,
221 #[serde(default, flatten)]
222 rest: Rest,
223 },
224 #[serde(rename = "tool_search")]
225 ToolSearch {
226 #[serde(skip_serializing_if = "Option::is_none")]
227 description: Option<String>,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 execution: Option<ToolSearchExecution>,
230 #[serde(skip_serializing_if = "Option::is_none")]
233 parameters: Option<Value>,
234 #[serde(default, flatten)]
235 rest: Rest,
236 },
237 #[serde(rename = "programmatic_tool_calling")]
238 ProgrammaticToolCalling {
239 #[serde(default, flatten)]
240 rest: Rest,
241 },
242 #[serde(rename = "web_search_preview")]
243 WebSearchPreview {
244 #[serde(skip_serializing_if = "Option::is_none")]
245 search_content_types: Option<Vec<SearchContentType>>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 search_context_size: Option<SearchContextSize>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 user_location: Option<WebSearchPreviewUserLocation>,
250 #[serde(default, flatten)]
251 rest: Rest,
252 },
253 #[serde(rename = "web_search_preview_2025_03_11")]
254 WebSearchPreview20250311 {
255 #[serde(skip_serializing_if = "Option::is_none")]
256 search_content_types: Option<Vec<SearchContentType>>,
257 #[serde(skip_serializing_if = "Option::is_none")]
258 search_context_size: Option<SearchContextSize>,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 user_location: Option<WebSearchPreviewUserLocation>,
261 #[serde(default, flatten)]
262 rest: Rest,
263 },
264 #[serde(rename = "apply_patch")]
265 ApplyPatch {
266 #[serde(skip_serializing_if = "Option::is_none")]
267 allowed_callers: Option<Vec<ToolCaller>>,
268 #[serde(skip_serializing_if = "Option::is_none")]
270 max_characters: Option<u64>,
271 #[serde(default, flatten)]
272 rest: Rest,
273 },
274}
275
276#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
277#[serde(tag = "type")]
278#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
279pub enum ResponseNamespaceTool {
280 #[serde(rename = "function")]
281 Function {
282 name: String,
283 #[serde(skip_serializing_if = "Option::is_none")]
284 defer_loading: Option<bool>,
285 #[serde(skip_serializing_if = "Option::is_none")]
286 description: Option<String>,
287 #[serde(skip_serializing_if = "Option::is_none")]
288 output_schema: Option<JsonSchema>,
289 #[serde(skip_serializing_if = "Option::is_none")]
292 parameters: Option<Value>,
293 #[serde(skip_serializing_if = "Option::is_none")]
294 strict: Option<bool>,
295 #[serde(skip_serializing_if = "Option::is_none")]
296 allowed_callers: Option<Vec<ToolCaller>>,
297 #[serde(rename = "async", skip_serializing_if = "Option::is_none")]
298 async_: Option<bool>,
299 #[serde(default, flatten)]
300 rest: Rest,
301 },
302 #[serde(rename = "custom")]
303 Custom {
304 name: String,
305 #[serde(skip_serializing_if = "Option::is_none")]
306 defer_loading: Option<bool>,
307 #[serde(skip_serializing_if = "Option::is_none")]
308 description: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 format: Option<CustomToolInputFormat>,
311 #[serde(skip_serializing_if = "Option::is_none")]
312 allowed_callers: Option<Vec<ToolCaller>>,
313 #[serde(rename = "async", skip_serializing_if = "Option::is_none")]
314 async_: Option<bool>,
315 #[serde(default, flatten)]
316 rest: Rest,
317 },
318}
319
320#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
321#[serde(untagged)]
322#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
323pub enum ResponseFunctionParameters {
324 Schema(JsonSchema),
325 Null,
326}
327
328#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
329#[serde(untagged)]
330#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
331pub enum ResponseFunctionStrict {
332 Value(bool),
333 Null,
334 #[default]
335 Absent,
336}
337
338impl ResponseFunctionStrict {
339 fn is_absent(&self) -> bool {
340 matches!(self, Self::Absent)
341 }
342}