1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(untagged)]
7pub enum Tool {
8 Function {
10 function_declarations: Vec<FunctionDeclaration>,
12 },
13 GoogleSearch {
15 google_search: GoogleSearchConfig,
17 },
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct GoogleSearchConfig {}
23
24impl Tool {
25 pub fn new(function_declaration: FunctionDeclaration) -> Self {
27 Self::Function {
28 function_declarations: vec![function_declaration],
29 }
30 }
31
32 pub fn with_functions(function_declarations: Vec<FunctionDeclaration>) -> Self {
34 Self::Function {
35 function_declarations,
36 }
37 }
38
39 pub fn google_search() -> Self {
41 Self::GoogleSearch {
42 google_search: GoogleSearchConfig {},
43 }
44 }
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct FunctionDeclaration {
50 pub name: String,
52 pub description: String,
54 pub parameters: FunctionParameters,
56}
57
58impl FunctionDeclaration {
59 pub fn new(
61 name: impl Into<String>,
62 description: impl Into<String>,
63 parameters: FunctionParameters,
64 ) -> Self {
65 Self {
66 name: name.into(),
67 description: description.into(),
68 parameters,
69 }
70 }
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct FunctionParameters {
76 #[serde(rename = "type")]
78 pub param_type: String,
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub properties: Option<HashMap<String, PropertyDetails>>,
82 #[serde(skip_serializing_if = "Option::is_none")]
84 pub required: Option<Vec<String>>,
85}
86
87impl FunctionParameters {
88 pub fn object() -> Self {
90 Self {
91 param_type: "OBJECT".to_string(),
92 properties: Some(HashMap::new()),
93 required: Some(Vec::new()),
94 }
95 }
96
97 pub fn with_property(
99 mut self,
100 name: impl Into<String>,
101 details: PropertyDetails,
102 required: bool,
103 ) -> Self {
104 let name = name.into();
105 if let Some(props) = &mut self.properties {
106 props.insert(name.clone(), details);
107 }
108 if required {
109 if let Some(req) = &mut self.required {
110 req.push(name);
111 }
112 }
113 self
114 }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct PropertyDetails {
120 #[serde(rename = "type")]
122 pub property_type: String,
123 pub description: String,
125 #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
127 pub enum_values: Option<Vec<String>>,
128 #[serde(skip_serializing_if = "Option::is_none")]
130 pub items: Option<Box<PropertyDetails>>,
131}
132
133impl PropertyDetails {
134 pub fn string(description: impl Into<String>) -> Self {
136 Self {
137 property_type: "STRING".to_string(),
138 description: description.into(),
139 enum_values: None,
140 items: None,
141 }
142 }
143
144 pub fn number(description: impl Into<String>) -> Self {
146 Self {
147 property_type: "NUMBER".to_string(),
148 description: description.into(),
149 enum_values: None,
150 items: None,
151 }
152 }
153
154 pub fn integer(description: impl Into<String>) -> Self {
156 Self {
157 property_type: "INTEGER".to_string(),
158 description: description.into(),
159 enum_values: None,
160 items: None,
161 }
162 }
163
164 pub fn boolean(description: impl Into<String>) -> Self {
166 Self {
167 property_type: "BOOLEAN".to_string(),
168 description: description.into(),
169 enum_values: None,
170 items: None,
171 }
172 }
173
174 pub fn array(description: impl Into<String>, items: PropertyDetails) -> Self {
176 Self {
177 property_type: "ARRAY".to_string(),
178 description: description.into(),
179 enum_values: None,
180 items: Some(Box::new(items)),
181 }
182 }
183
184 pub fn enum_type(
186 description: impl Into<String>,
187 enum_values: impl IntoIterator<Item = impl Into<String>>,
188 ) -> Self {
189 Self {
190 property_type: "STRING".to_string(),
191 description: description.into(),
192 enum_values: Some(enum_values.into_iter().map(|s| s.into()).collect()),
193 items: None,
194 }
195 }
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct FunctionCall {
201 pub name: String,
203 pub args: serde_json::Value,
205}
206
207impl FunctionCall {
208 pub fn new(name: impl Into<String>, args: serde_json::Value) -> Self {
210 Self {
211 name: name.into(),
212 args,
213 }
214 }
215
216 pub fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> crate::Result<T> {
218 match &self.args {
219 serde_json::Value::Object(obj) => {
220 if let Some(value) = obj.get(key) {
221 serde_json::from_value(value.clone()).map_err(|e| {
222 crate::Error::FunctionCallError(format!(
223 "Error deserializing parameter {}: {}",
224 key, e
225 ))
226 })
227 } else {
228 Err(crate::Error::FunctionCallError(format!(
229 "Missing parameter: {}",
230 key
231 )))
232 }
233 }
234 _ => Err(crate::Error::FunctionCallError(
235 "Arguments are not an object".to_string(),
236 )),
237 }
238 }
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct FunctionResponse {
244 pub name: String,
246 #[serde(skip_serializing_if = "Option::is_none")]
249 pub response: Option<serde_json::Value>,
250}
251
252impl FunctionResponse {
253 pub fn new(name: impl Into<String>, response: serde_json::Value) -> Self {
255 Self {
256 name: name.into(),
257 response: Some(response),
258 }
259 }
260
261 pub fn from_str(
263 name: impl Into<String>,
264 response: impl Into<String>,
265 ) -> Result<Self, serde_json::Error> {
266 let json = serde_json::from_str(&response.into())?;
267 Ok(Self {
268 name: name.into(),
269 response: Some(json),
270 })
271 }
272}