1use schemars::{JsonSchema, generate::SchemaSettings};
2use serde::Serialize;
3use serde_json::{Map, Value};
4
5#[derive(Serialize, Clone, Debug)]
7pub struct ToolDefinition {
8 #[serde(rename = "type")]
10 pub tool_type: String,
11 pub function: ToolFunction,
13}
14
15#[derive(Serialize, Clone, Debug)]
17pub struct ToolFunction {
18 pub name: String,
20 pub description: String,
22 pub parameters: Parameters,
24}
25
26#[derive(Serialize, Clone, Debug)]
28pub struct Parameters(Map<String, Value>);
29
30impl Parameters {
31 pub fn from_object(mut obj: Map<String, Value>) -> Self {
33 obj.remove("$schema");
35 obj.remove("title");
36 obj.remove("description");
37
38 Self(obj)
39 }
40
41 pub fn from_schema(schema: schemars::Schema) -> Self {
43 let obj = schema.to_value().as_object().unwrap().clone();
44 Self::from_object(obj)
45 }
46
47 pub fn from_type<T: JsonSchema>() -> Self {
49 let settings = SchemaSettings::default().with(|s| {
50 s.inline_subschemas = true;
51 });
52 let generator = settings.into_generator();
53 let schema = generator.into_root_schema_for::<T>();
54 Self::from_schema(schema)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_tool_definition_serialization() {
64 let td = ToolDefinition {
65 tool_type: "function".into(),
66 function: ToolFunction {
67 name: "test".into(),
68 description: "desc".into(),
69 parameters: Parameters::from_type::<String>(),
70 },
71 };
72 let json = serde_json::to_string(&td).unwrap();
73 assert!(json.contains(r#""type":"function"#));
74 assert!(json.contains(r#""name":"test"#));
75 }
76}