1use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
12pub struct ToolCall {
13 #[serde(default)]
15 pub id: String,
16 #[serde(rename = "type", default)]
18 pub kind: String,
19 pub function: FunctionCall,
21 #[serde(skip_serializing_if = "Option::is_none", default)]
23 pub index: Option<u32>,
24}
25
26#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
28pub struct FunctionCall {
29 #[serde(skip_serializing_if = "Option::is_none", default)]
32 pub name: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none", default)]
36 pub arguments: Option<String>,
37}
38
39#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
41#[serde(tag = "type", rename_all = "snake_case")]
42pub enum Tool {
43 Function {
45 function: FunctionDef,
47 },
48}
49
50#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
52pub struct FunctionDef {
53 pub name: String,
55 #[serde(skip_serializing_if = "Option::is_none", default)]
57 pub description: Option<String>,
58 #[serde(skip_serializing_if = "Option::is_none", default)]
60 pub parameters: Option<serde_json::Value>,
61 #[serde(skip_serializing_if = "Option::is_none", default)]
63 pub strict: Option<bool>,
64}
65
66#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
68#[serde(untagged)]
69pub enum ToolChoice {
70 Mode(String),
72 Specific {
74 #[serde(rename = "type")]
76 kind: String,
77 function: FunctionRef,
79 },
80}
81
82#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
84pub struct FunctionRef {
85 pub name: String,
87}
88
89impl ToolChoice {
90 pub fn auto() -> Self {
92 ToolChoice::Mode("auto".to_string())
93 }
94
95 pub fn none() -> Self {
97 ToolChoice::Mode("none".to_string())
98 }
99
100 pub fn required() -> Self {
102 ToolChoice::Mode("required".to_string())
103 }
104
105 pub fn function(name: impl Into<String>) -> Self {
107 ToolChoice::Specific {
108 kind: "function".to_string(),
109 function: FunctionRef { name: name.into() },
110 }
111 }
112}
113
114impl Tool {
115 pub fn function(def: FunctionDef) -> Self {
117 Tool::Function { function: def }
118 }
119}
120
121impl FunctionDef {
122 pub fn new(name: impl Into<String>, parameters: serde_json::Value) -> Self {
124 Self {
125 name: name.into(),
126 description: None,
127 parameters: Some(parameters),
128 strict: None,
129 }
130 }
131
132 pub fn with_description(mut self, description: impl Into<String>) -> Self {
134 self.description = Some(description.into());
135 self
136 }
137
138 pub fn with_strict(mut self, strict: bool) -> Self {
140 self.strict = Some(strict);
141 self
142 }
143}
144
145#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
147#[serde(tag = "type", rename_all = "snake_case")]
148pub enum ResponseFormat {
149 Text,
151 JsonObject,
153 JsonSchema {
155 json_schema: JsonSchema,
157 },
158}
159
160#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
162pub struct JsonSchema {
163 pub name: String,
165 #[serde(skip_serializing_if = "Option::is_none", default)]
167 pub description: Option<String>,
168 pub schema: serde_json::Value,
170 #[serde(skip_serializing_if = "Option::is_none", default)]
172 pub strict: Option<bool>,
173}
174
175impl ResponseFormat {
176 pub fn json_object() -> Self {
179 ResponseFormat::JsonObject
180 }
181
182 pub fn json_schema(name: impl Into<String>, strict: bool, schema: serde_json::Value) -> Self {
184 ResponseFormat::JsonSchema {
185 json_schema: JsonSchema {
186 name: name.into(),
187 description: None,
188 schema,
189 strict: Some(strict),
190 },
191 }
192 }
193}
194
195#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
197pub struct Provider {
198 #[serde(skip_serializing_if = "Option::is_none", default)]
200 pub order: Option<Vec<String>>,
201 #[serde(skip_serializing_if = "Option::is_none", default)]
203 pub allow_fallbacks: Option<bool>,
204 #[serde(skip_serializing_if = "Option::is_none", default)]
206 pub require_parameters: Option<bool>,
207 #[serde(skip_serializing_if = "Option::is_none", default)]
209 pub data_collection: Option<String>,
210 #[serde(skip_serializing_if = "Option::is_none", default)]
212 pub only: Option<Vec<String>>,
213 #[serde(skip_serializing_if = "Option::is_none", default)]
215 pub ignore: Option<Vec<String>>,
216 #[serde(skip_serializing_if = "Option::is_none", default)]
218 pub quantizations: Option<Vec<String>>,
219 #[serde(skip_serializing_if = "Option::is_none", default)]
221 pub sort: Option<String>,
222 #[serde(skip_serializing_if = "Option::is_none", default)]
224 pub max_price: Option<serde_json::Value>,
225 #[serde(skip_serializing_if = "Option::is_none", default)]
227 pub zdr: Option<bool>,
228}
229
230impl Provider {
231 pub fn new() -> Self {
233 Self::default()
234 }
235
236 pub fn with_order<S, I>(mut self, order: I) -> Self
238 where
239 S: Into<String>,
240 I: IntoIterator<Item = S>,
241 {
242 self.order = Some(order.into_iter().map(Into::into).collect());
243 self
244 }
245
246 pub fn with_sort(mut self, sort: impl Into<String>) -> Self {
248 self.sort = Some(sort.into());
249 self
250 }
251
252 pub fn with_allow_fallbacks(mut self, allow: bool) -> Self {
254 self.allow_fallbacks = Some(allow);
255 self
256 }
257
258 pub fn with_only<S, I>(mut self, only: I) -> Self
260 where
261 S: Into<String>,
262 I: IntoIterator<Item = S>,
263 {
264 self.only = Some(only.into_iter().map(Into::into).collect());
265 self
266 }
267
268 pub fn with_ignore<S, I>(mut self, ignore: I) -> Self
270 where
271 S: Into<String>,
272 I: IntoIterator<Item = S>,
273 {
274 self.ignore = Some(ignore.into_iter().map(Into::into).collect());
275 self
276 }
277
278 pub fn with_quantizations<S, I>(mut self, q: I) -> Self
280 where
281 S: Into<String>,
282 I: IntoIterator<Item = S>,
283 {
284 self.quantizations = Some(q.into_iter().map(Into::into).collect());
285 self
286 }
287
288 pub fn with_max_price(mut self, price: serde_json::Value) -> Self {
290 self.max_price = Some(price);
291 self
292 }
293
294 pub fn with_data_collection(mut self, policy: impl Into<String>) -> Self {
296 self.data_collection = Some(policy.into());
297 self
298 }
299
300 pub fn with_require_parameters(mut self, required: bool) -> Self {
302 self.require_parameters = Some(required);
303 self
304 }
305
306 pub fn with_zdr(mut self, zdr: bool) -> Self {
308 self.zdr = Some(zdr);
309 self
310 }
311}
312
313#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
319pub struct ReasoningConfig {
320 #[serde(skip_serializing_if = "Option::is_none", default)]
322 pub effort: Option<String>,
323 #[serde(skip_serializing_if = "Option::is_none", default)]
325 pub max_tokens: Option<u32>,
326 #[serde(skip_serializing_if = "Option::is_none", default)]
328 pub exclude: Option<bool>,
329}
330
331#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
335#[serde(tag = "id", rename_all = "kebab-case")]
336pub enum Plugin {
337 Web(WebPluginConfig),
339 #[serde(rename = "file-parser")]
341 File(FilePluginConfig),
342}
343
344impl Plugin {
345 pub fn web() -> Self {
347 Plugin::Web(WebPluginConfig::default())
348 }
349
350 pub fn web_with(config: WebPluginConfig) -> Self {
352 Plugin::Web(config)
353 }
354
355 pub fn file_parser(pdf_engine: Option<&str>) -> Self {
358 let pdf = pdf_engine.map(|e| FilePdfConfig {
359 engine: Some(e.to_string()),
360 });
361 Plugin::File(FilePluginConfig { pdf })
362 }
363}
364
365#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
367pub struct FilePluginConfig {
368 #[serde(skip_serializing_if = "Option::is_none", default)]
370 pub pdf: Option<FilePdfConfig>,
371}
372
373#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
375pub struct FilePdfConfig {
376 #[serde(skip_serializing_if = "Option::is_none", default)]
378 pub engine: Option<String>,
379}
380
381#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
383pub struct WebPluginConfig {
384 #[serde(skip_serializing_if = "Option::is_none", default)]
386 pub max_results: Option<u32>,
387 #[serde(skip_serializing_if = "Option::is_none", default)]
389 pub search_prompt: Option<String>,
390 #[serde(skip_serializing_if = "Option::is_none", default)]
392 pub engine: Option<String>,
393}
394
395impl WebPluginConfig {
396 pub fn new() -> Self {
398 Self::default()
399 }
400 pub fn with_max_results(mut self, n: u32) -> Self {
402 self.max_results = Some(n);
403 self
404 }
405 pub fn with_search_prompt(mut self, prompt: impl Into<String>) -> Self {
407 self.search_prompt = Some(prompt.into());
408 self
409 }
410 pub fn with_engine(mut self, engine: impl Into<String>) -> Self {
412 self.engine = Some(engine.into());
413 self
414 }
415}
416
417#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
421#[serde(tag = "type", rename_all = "snake_case")]
422pub enum Annotation {
423 UrlCitation {
425 url_citation: UrlCitation,
427 },
428 File {
430 file: FileAnnotation,
432 },
433}
434
435#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
438pub struct FileAnnotation {
439 pub filename: String,
441 pub file_data: String,
443}
444
445#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
447pub struct UrlCitation {
448 pub url: String,
450 #[serde(skip_serializing_if = "Option::is_none", default)]
452 pub title: Option<String>,
453 #[serde(skip_serializing_if = "Option::is_none", default)]
455 pub content: Option<String>,
456 #[serde(skip_serializing_if = "Option::is_none", default)]
458 pub start_index: Option<u32>,
459 #[serde(skip_serializing_if = "Option::is_none", default)]
461 pub end_index: Option<u32>,
462}
463
464impl ReasoningConfig {
465 pub fn new() -> Self {
467 Self::default()
468 }
469
470 pub fn with_effort(mut self, effort: impl Into<String>) -> Self {
472 self.effort = Some(effort.into());
473 self
474 }
475
476 pub fn with_max_tokens(mut self, max_tokens: u32) -> Self {
478 self.max_tokens = Some(max_tokens);
479 self
480 }
481
482 pub fn with_exclude(mut self, exclude: bool) -> Self {
485 self.exclude = Some(exclude);
486 self
487 }
488}