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#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
199pub struct FunctionCall {
200 pub name: String,
202 pub args: serde_json::Value,
204}
205
206impl FunctionCall {
207 pub fn new(name: impl Into<String>, args: serde_json::Value) -> Self {
209 Self {
210 name: name.into(),
211 args,
212 }
213 }
214
215 pub fn get<T: serde::de::DeserializeOwned>(&self, key: &str) -> crate::Result<T> {
217 match &self.args {
218 serde_json::Value::Object(obj) => {
219 if let Some(value) = obj.get(key) {
220 serde_json::from_value(value.clone()).map_err(|e| {
221 crate::Error::FunctionCallError(format!(
222 "Error deserializing parameter {key}: {e}"
223 ))
224 })
225 } else {
226 Err(crate::Error::FunctionCallError(format!(
227 "Missing parameter: {key}"
228 )))
229 }
230 }
231 _ => Err(crate::Error::FunctionCallError(
232 "Arguments are not an object".to_string(),
233 )),
234 }
235 }
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
240pub struct FunctionResponse {
241 pub name: String,
243 #[serde(skip_serializing_if = "Option::is_none")]
246 pub response: Option<serde_json::Value>,
247}
248
249impl FunctionResponse {
250 pub fn new(name: impl Into<String>, response: serde_json::Value) -> Self {
252 Self {
253 name: name.into(),
254 response: Some(response),
255 }
256 }
257
258 pub fn from_str(
260 name: impl Into<String>,
261 response: impl Into<String>,
262 ) -> Result<Self, serde_json::Error> {
263 let json = serde_json::from_str(&response.into())?;
264 Ok(Self {
265 name: name.into(),
266 response: Some(json),
267 })
268 }
269}