@@ -404,7 +404,7 @@ impl fmt::Display for Role {
404404}
405405
406406#[ derive( Debug , Clone , Serialize , Deserialize ) ]
407- #[ serde( untagged, rename_all = "camelCase" ) ]
407+ #[ serde( untagged, rename_all = "camelCase" , rename_all_fields = "camelCase" ) ]
408408pub enum Tool {
409409 FunctionDeclaration {
410410 function_declarations : Vec < FunctionDeclaration > ,
@@ -413,6 +413,21 @@ pub enum Tool {
413413 CodeExecution {
414414 code_execution : CodeExecution ,
415415 } ,
416+
417+ /// Enable Google Search grounding with (optional) dynamic retrieval settings.
418+ GoogleSearchRetrieval {
419+ google_search_retrieval : GoogleSearchRetrieval ,
420+ } ,
421+
422+ /// Enable Google Search tool.
423+ GoogleSearch {
424+ google_search : GoogleSearch ,
425+ } ,
426+
427+ /// Enable URL context tool.
428+ UrlContext {
429+ url_context : UrlContext ,
430+ } ,
416431}
417432
418433impl From < Vec < FunctionDefinition > > for Tool {
@@ -435,6 +450,37 @@ impl From<Vec<FunctionDefinition>> for Tool {
435450#[ serde( rename_all = "camelCase" ) ]
436451pub struct CodeExecution { }
437452
453+ #[ derive( Debug , Default , Clone , Serialize , Deserialize , PartialEq ) ]
454+ #[ serde( rename_all = "camelCase" ) ]
455+ pub struct GoogleSearch { }
456+
457+ #[ derive( Debug , Default , Clone , Serialize , Deserialize , PartialEq ) ]
458+ #[ serde( rename_all = "camelCase" ) ]
459+ pub struct UrlContext { }
460+
461+ #[ derive( Debug , Default , Clone , Serialize , Deserialize , PartialEq ) ]
462+ #[ serde( rename_all = "camelCase" ) ]
463+ pub struct GoogleSearchRetrieval {
464+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
465+ pub dynamic_retrieval_config : Option < DynamicRetrievalConfig > ,
466+
467+ #[ serde( flatten) ]
468+ pub extra : Map < String , Value > ,
469+ }
470+
471+ #[ derive( Debug , Default , Clone , Serialize , Deserialize , PartialEq ) ]
472+ #[ serde( rename_all = "camelCase" ) ]
473+ pub struct DynamicRetrievalConfig {
474+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
475+ pub mode : Option < String > ,
476+
477+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
478+ pub dynamic_threshold : Option < f64 > ,
479+
480+ #[ serde( flatten) ]
481+ pub extra : Map < String , Value > ,
482+ }
483+
438484#[ derive( Debug , Serialize , Deserialize , Clone ) ]
439485#[ serde( rename_all = "camelCase" ) ]
440486pub struct ToolConfig {
@@ -1028,4 +1074,148 @@ mod tests {
10281074 // let val = into_parts(json!(vec![string_value, complex_value])).unwrap();
10291075 // assert_eq!(val, vec![content_part, content_part2]);
10301076 }
1077+
1078+ #[ test]
1079+ fn test_tool_serde ( ) {
1080+ let tool = Tool :: FunctionDeclaration {
1081+ function_declarations : vec ! [ FunctionDeclaration {
1082+ name: "get_weather" . to_string( ) ,
1083+ description: "Get current weather" . to_string( ) ,
1084+ parameters: Some ( json!( {
1085+ "type" : "object" ,
1086+ "properties" : {
1087+ "location" : { "type" : "string" }
1088+ } ,
1089+ "required" : [ "location" ]
1090+ } ) ) ,
1091+ response: None ,
1092+ } ] ,
1093+ } ;
1094+
1095+ let json_value = serde_json:: to_value ( & tool) . unwrap ( ) ;
1096+ assert_eq ! (
1097+ json_value,
1098+ json!( {
1099+ "functionDeclarations" : [
1100+ {
1101+ "name" : "get_weather" ,
1102+ "description" : "Get current weather" ,
1103+ "parameters" : {
1104+ "type" : "object" ,
1105+ "properties" : {
1106+ "location" : { "type" : "string" }
1107+ } ,
1108+ "required" : [ "location" ]
1109+ }
1110+ }
1111+ ]
1112+ } )
1113+ ) ;
1114+
1115+ let deserialized: Tool = serde_json:: from_value ( json_value) . unwrap ( ) ;
1116+ assert_eq ! (
1117+ serde_json:: to_value( deserialized) . unwrap( ) ,
1118+ serde_json:: to_value( tool) . unwrap( )
1119+ ) ;
1120+
1121+ let code_tool = Tool :: CodeExecution {
1122+ code_execution : CodeExecution { } ,
1123+ } ;
1124+ let json_value = serde_json:: to_value ( & code_tool) . unwrap ( ) ;
1125+ assert_eq ! ( json_value, json!( { "codeExecution" : { } } ) ) ;
1126+ let deserialized: Tool = serde_json:: from_value ( json_value) . unwrap ( ) ;
1127+ assert_eq ! (
1128+ serde_json:: to_value( deserialized) . unwrap( ) ,
1129+ serde_json:: to_value( code_tool) . unwrap( )
1130+ ) ;
1131+
1132+ let search_retrieval_tool = Tool :: GoogleSearchRetrieval {
1133+ google_search_retrieval : GoogleSearchRetrieval {
1134+ dynamic_retrieval_config : Some ( DynamicRetrievalConfig {
1135+ mode : Some ( "MODE_DYNAMIC" . to_string ( ) ) ,
1136+ dynamic_threshold : Some ( 0.3 ) ,
1137+ extra : Map :: new ( ) ,
1138+ } ) ,
1139+ extra : Map :: new ( ) ,
1140+ } ,
1141+ } ;
1142+ let json_value = serde_json:: to_value ( & search_retrieval_tool) . unwrap ( ) ;
1143+ assert_eq ! (
1144+ json_value,
1145+ json!( {
1146+ "googleSearchRetrieval" : {
1147+ "dynamicRetrievalConfig" : {
1148+ "mode" : "MODE_DYNAMIC" ,
1149+ "dynamicThreshold" : 0.3
1150+ }
1151+ }
1152+ } )
1153+ ) ;
1154+ let deserialized: Tool = serde_json:: from_value ( json_value) . unwrap ( ) ;
1155+ assert_eq ! (
1156+ serde_json:: to_value( deserialized) . unwrap( ) ,
1157+ serde_json:: to_value( search_retrieval_tool) . unwrap( )
1158+ ) ;
1159+
1160+ let search_tool = Tool :: GoogleSearch {
1161+ google_search : GoogleSearch { } ,
1162+ } ;
1163+ let json_value = serde_json:: to_value ( & search_tool) . unwrap ( ) ;
1164+ assert_eq ! ( json_value, json!( { "googleSearch" : { } } ) ) ;
1165+ let deserialized: Tool = serde_json:: from_value ( json_value) . unwrap ( ) ;
1166+ assert_eq ! (
1167+ serde_json:: to_value( deserialized) . unwrap( ) ,
1168+ serde_json:: to_value( search_tool) . unwrap( )
1169+ ) ;
1170+
1171+ let url_context_tool = Tool :: UrlContext {
1172+ url_context : UrlContext { } ,
1173+ } ;
1174+ let json_value = serde_json:: to_value ( & url_context_tool) . unwrap ( ) ;
1175+ assert_eq ! ( json_value, json!( { "urlContext" : { } } ) ) ;
1176+ let deserialized: Tool = serde_json:: from_value ( json_value) . unwrap ( ) ;
1177+ assert_eq ! (
1178+ serde_json:: to_value( deserialized) . unwrap( ) ,
1179+ serde_json:: to_value( url_context_tool) . unwrap( )
1180+ ) ;
1181+ }
1182+
1183+ #[ test]
1184+ fn test_tool_from_function_definitions ( ) {
1185+ let defs = vec ! [ FunctionDefinition {
1186+ name: "sum" . to_string( ) ,
1187+ description: "Sum two integers" . to_string( ) ,
1188+ parameters: json!( {
1189+ "type" : "object" ,
1190+ "properties" : {
1191+ "a" : { "type" : "integer" } ,
1192+ "b" : { "type" : "integer" }
1193+ } ,
1194+ "required" : [ "a" , "b" ]
1195+ } ) ,
1196+ strict: None ,
1197+ } ] ;
1198+
1199+ let tool: Tool = defs. into ( ) ;
1200+ let json_value = serde_json:: to_value ( & tool) . unwrap ( ) ;
1201+ assert_eq ! (
1202+ json_value,
1203+ json!( {
1204+ "functionDeclarations" : [
1205+ {
1206+ "name" : "sum" ,
1207+ "description" : "Sum two integers" ,
1208+ "parameters" : {
1209+ "type" : "object" ,
1210+ "properties" : {
1211+ "a" : { "type" : "integer" } ,
1212+ "b" : { "type" : "integer" }
1213+ } ,
1214+ "required" : [ "a" , "b" ]
1215+ }
1216+ }
1217+ ]
1218+ } )
1219+ ) ;
1220+ }
10311221}
0 commit comments