1use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug)]
21#[non_exhaustive]
22pub enum Tool {
23 Function {
25 name: String,
26 description: String,
27 parameters: FunctionParameters,
28 },
29 GoogleSearch,
31 CodeExecution,
33 UrlContext,
35 ComputerUse {
45 environment: String,
47 excluded_predefined_functions: Vec<String>,
51 },
52 McpServer { name: String, url: String },
54 FileSearch {
56 store_names: Vec<String>,
58 top_k: Option<i32>,
60 metadata_filter: Option<String>,
62 },
63 Unknown {
72 tool_type: String,
74 data: serde_json::Value,
76 },
77}
78
79impl Serialize for Tool {
82 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83 where
84 S: serde::Serializer,
85 {
86 use serde::ser::SerializeMap;
87
88 match self {
89 Self::Function {
90 name,
91 description,
92 parameters,
93 } => {
94 let mut map = serializer.serialize_map(None)?;
95 map.serialize_entry("type", "function")?;
96 map.serialize_entry("name", name)?;
97 map.serialize_entry("description", description)?;
98 map.serialize_entry("parameters", parameters)?;
99 map.end()
100 }
101 Self::GoogleSearch => {
102 let mut map = serializer.serialize_map(None)?;
103 map.serialize_entry("type", "google_search")?;
104 map.end()
105 }
106 Self::CodeExecution => {
107 let mut map = serializer.serialize_map(None)?;
108 map.serialize_entry("type", "code_execution")?;
109 map.end()
110 }
111 Self::UrlContext => {
112 let mut map = serializer.serialize_map(None)?;
113 map.serialize_entry("type", "url_context")?;
114 map.end()
115 }
116 Self::ComputerUse {
117 environment,
118 excluded_predefined_functions,
119 } => {
120 let mut map = serializer.serialize_map(None)?;
121 map.serialize_entry("type", "computer_use")?;
122 map.serialize_entry("environment", environment)?;
123 if !excluded_predefined_functions.is_empty() {
124 map.serialize_entry(
125 "excludedPredefinedFunctions",
126 excluded_predefined_functions,
127 )?;
128 }
129 map.end()
130 }
131 Self::McpServer { name, url } => {
132 let mut map = serializer.serialize_map(None)?;
133 map.serialize_entry("type", "mcp_server")?;
134 map.serialize_entry("name", name)?;
135 map.serialize_entry("url", url)?;
136 map.end()
137 }
138 Self::FileSearch {
139 store_names,
140 top_k,
141 metadata_filter,
142 } => {
143 let mut map = serializer.serialize_map(None)?;
144 map.serialize_entry("type", "file_search")?;
145 map.serialize_entry("file_search_store_names", store_names)?;
146 if let Some(k) = top_k {
147 map.serialize_entry("top_k", k)?;
148 }
149 if let Some(filter) = metadata_filter {
150 map.serialize_entry("metadata_filter", filter)?;
151 }
152 map.end()
153 }
154 Self::Unknown { tool_type, data } => {
155 let mut map = serializer.serialize_map(None)?;
156 map.serialize_entry("type", tool_type)?;
157 if let serde_json::Value::Object(obj) = data {
159 for (key, value) in obj {
160 if key != "type" {
161 map.serialize_entry(key, value)?;
162 }
163 }
164 } else if !data.is_null() {
165 map.serialize_entry("data", data)?;
166 }
167 map.end()
168 }
169 }
170 }
171}
172
173impl<'de> Deserialize<'de> for Tool {
175 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
176 where
177 D: serde::Deserializer<'de>,
178 {
179 let value = serde_json::Value::deserialize(deserializer)?;
181
182 #[derive(Deserialize)]
185 #[serde(tag = "type")]
186 enum KnownTool {
187 #[serde(rename = "function")]
188 Function {
189 name: String,
190 description: String,
191 parameters: FunctionParameters,
192 },
193 #[serde(rename = "google_search")]
194 GoogleSearch,
195 #[serde(rename = "code_execution")]
196 CodeExecution,
197 #[serde(rename = "url_context")]
198 UrlContext,
199 #[serde(rename = "computer_use")]
200 ComputerUse {
201 environment: String,
202 #[serde(rename = "excludedPredefinedFunctions", default)]
203 excluded_predefined_functions: Vec<String>,
204 },
205 #[serde(rename = "mcp_server")]
206 McpServer { name: String, url: String },
207 #[serde(rename = "file_search")]
208 FileSearch {
209 #[serde(rename = "file_search_store_names")]
210 store_names: Vec<String>,
211 #[serde(default)]
212 top_k: Option<i32>,
213 #[serde(default)]
214 metadata_filter: Option<String>,
215 },
216 }
217
218 match serde_json::from_value::<KnownTool>(value.clone()) {
220 Ok(known) => Ok(match known {
221 KnownTool::Function {
222 name,
223 description,
224 parameters,
225 } => Tool::Function {
226 name,
227 description,
228 parameters,
229 },
230 KnownTool::GoogleSearch => Tool::GoogleSearch,
231 KnownTool::CodeExecution => Tool::CodeExecution,
232 KnownTool::UrlContext => Tool::UrlContext,
233 KnownTool::ComputerUse {
234 environment,
235 excluded_predefined_functions,
236 } => Tool::ComputerUse {
237 environment,
238 excluded_predefined_functions,
239 },
240 KnownTool::McpServer { name, url } => Tool::McpServer { name, url },
241 KnownTool::FileSearch {
242 store_names,
243 top_k,
244 metadata_filter,
245 } => Tool::FileSearch {
246 store_names,
247 top_k,
248 metadata_filter,
249 },
250 }),
251 Err(parse_error) => {
252 let tool_type = value
254 .get("type")
255 .and_then(|v| v.as_str())
256 .unwrap_or("<missing type>")
257 .to_string();
258
259 tracing::warn!(
262 "Encountered unknown Tool type '{}'. \
263 Parse error: {}. \
264 This may indicate a new API feature or a malformed response. \
265 The tool will be preserved in the Unknown variant.",
266 tool_type,
267 parse_error
268 );
269
270 Ok(Tool::Unknown {
271 tool_type,
272 data: value,
273 })
274 }
275 }
276 }
277}
278
279impl Tool {
280 #[must_use]
282 pub const fn is_unknown(&self) -> bool {
283 matches!(self, Self::Unknown { .. })
284 }
285
286 #[must_use]
290 pub fn unknown_tool_type(&self) -> Option<&str> {
291 match self {
292 Self::Unknown { tool_type, .. } => Some(tool_type),
293 _ => None,
294 }
295 }
296
297 #[must_use]
301 pub fn unknown_data(&self) -> Option<&serde_json::Value> {
302 match self {
303 Self::Unknown { data, .. } => Some(data),
304 _ => None,
305 }
306 }
307}
308
309#[derive(Clone, Serialize, Deserialize, Debug)]
311pub struct FunctionDeclaration {
312 name: String,
313 description: String,
314 parameters: FunctionParameters,
315}
316
317#[derive(Clone, Serialize, Deserialize, Debug)]
319pub struct FunctionParameters {
320 #[serde(rename = "type")]
321 type_: String,
322 properties: serde_json::Value,
323 #[serde(skip_serializing_if = "Vec::is_empty", default)]
324 required: Vec<String>,
325}
326
327impl FunctionDeclaration {
328 #[doc(hidden)]
333 pub fn new(name: String, description: String, parameters: FunctionParameters) -> Self {
334 Self {
335 name,
336 description,
337 parameters,
338 }
339 }
340
341 #[must_use]
343 pub fn builder(name: impl Into<String>) -> FunctionDeclarationBuilder {
344 FunctionDeclarationBuilder::new(name)
345 }
346
347 #[must_use]
349 pub fn name(&self) -> &str {
350 &self.name
351 }
352
353 #[must_use]
355 pub fn description(&self) -> &str {
356 &self.description
357 }
358
359 #[must_use]
361 pub fn parameters(&self) -> &FunctionParameters {
362 &self.parameters
363 }
364
365 pub fn into_tool(self) -> Tool {
367 Tool::Function {
368 name: self.name,
369 description: self.description,
370 parameters: self.parameters,
371 }
372 }
373}
374
375impl FunctionParameters {
376 #[doc(hidden)]
381 pub fn new(type_: String, properties: serde_json::Value, required: Vec<String>) -> Self {
382 Self {
383 type_,
384 properties,
385 required,
386 }
387 }
388
389 #[must_use]
391 pub fn type_(&self) -> &str {
392 &self.type_
393 }
394
395 #[must_use]
397 pub fn properties(&self) -> &serde_json::Value {
398 &self.properties
399 }
400
401 #[must_use]
403 pub fn required(&self) -> &[String] {
404 &self.required
405 }
406}
407
408#[derive(Debug)]
410pub struct FunctionDeclarationBuilder {
411 name: String,
412 description: String,
413 properties: serde_json::Value,
414 required: Vec<String>,
415}
416
417impl FunctionDeclarationBuilder {
418 pub fn new(name: impl Into<String>) -> Self {
420 Self {
421 name: name.into(),
422 description: String::new(),
423 properties: serde_json::Value::Object(serde_json::Map::new()),
424 required: Vec::new(),
425 }
426 }
427
428 pub fn description(mut self, description: impl Into<String>) -> Self {
430 self.description = description.into();
431 self
432 }
433
434 pub fn parameter(mut self, name: &str, schema: serde_json::Value) -> Self {
436 if let serde_json::Value::Object(ref mut map) = self.properties {
437 map.insert(name.to_string(), schema);
438 }
439 self
440 }
441
442 pub fn required(mut self, required: Vec<String>) -> Self {
444 self.required = required;
445 self
446 }
447
448 pub fn build(self) -> FunctionDeclaration {
459 if self.name.trim().is_empty() {
461 tracing::warn!(
462 "FunctionDeclaration built with empty or whitespace-only name. \
463 This will likely be rejected by the API."
464 );
465 }
466
467 if let serde_json::Value::Object(ref props) = self.properties {
469 for req in &self.required {
470 if !props.contains_key(req) {
471 tracing::warn!(
472 "FunctionDeclaration '{}' requires parameter '{}' which is not defined in properties. \
473 This will likely cause API errors.",
474 self.name,
475 req
476 );
477 }
478 }
479 }
480
481 FunctionDeclaration {
482 name: self.name,
483 description: self.description,
484 parameters: FunctionParameters {
485 type_: "object".to_string(),
486 properties: self.properties,
487 required: self.required,
488 },
489 }
490 }
491}
492
493#[derive(Clone, Debug, PartialEq)]
513#[non_exhaustive]
514pub enum FunctionCallingMode {
515 Auto,
517 Any,
519 None,
521 Validated,
526 Unknown {
534 mode_type: String,
536 data: serde_json::Value,
538 },
539}
540
541impl FunctionCallingMode {
542 #[must_use]
544 pub const fn is_unknown(&self) -> bool {
545 matches!(self, Self::Unknown { .. })
546 }
547
548 #[must_use]
552 pub fn unknown_mode_type(&self) -> Option<&str> {
553 match self {
554 Self::Unknown { mode_type, .. } => Some(mode_type),
555 _ => None,
556 }
557 }
558
559 #[must_use]
563 pub fn unknown_data(&self) -> Option<&serde_json::Value> {
564 match self {
565 Self::Unknown { data, .. } => Some(data),
566 _ => None,
567 }
568 }
569}
570
571impl Serialize for FunctionCallingMode {
572 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
573 where
574 S: serde::Serializer,
575 {
576 match self {
577 Self::Auto => serializer.serialize_str("AUTO"),
578 Self::Any => serializer.serialize_str("ANY"),
579 Self::None => serializer.serialize_str("NONE"),
580 Self::Validated => serializer.serialize_str("VALIDATED"),
581 Self::Unknown { mode_type, .. } => serializer.serialize_str(mode_type),
582 }
583 }
584}
585
586impl<'de> Deserialize<'de> for FunctionCallingMode {
587 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
588 where
589 D: serde::Deserializer<'de>,
590 {
591 let value = serde_json::Value::deserialize(deserializer)?;
592
593 match value.as_str() {
594 Some("AUTO") => Ok(Self::Auto),
595 Some("ANY") => Ok(Self::Any),
596 Some("NONE") => Ok(Self::None),
597 Some("VALIDATED") => Ok(Self::Validated),
598 Some(other) => {
599 tracing::warn!(
600 "Encountered unknown FunctionCallingMode '{}'. \
601 This may indicate a new API feature. \
602 The mode will be preserved in the Unknown variant.",
603 other
604 );
605 Ok(Self::Unknown {
606 mode_type: other.to_string(),
607 data: value,
608 })
609 }
610 Option::None => {
611 let mode_type = format!("<non-string: {}>", value);
613 tracing::warn!(
614 "FunctionCallingMode received non-string value: {}. \
615 Preserving in Unknown variant.",
616 value
617 );
618 Ok(Self::Unknown {
619 mode_type,
620 data: value,
621 })
622 }
623 }
624 }
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630 use serde_json;
631
632 #[test]
633 fn test_serialize_function_declaration() {
634 let function = FunctionDeclaration::builder("get_weather")
635 .description("Get the current weather in a given location")
636 .parameter(
637 "location",
638 serde_json::json!({
639 "type": "string",
640 "description": "The city and state, e.g. San Francisco, CA"
641 }),
642 )
643 .required(vec!["location".to_string()])
644 .build();
645
646 let json_string = serde_json::to_string(&function).expect("Serialization failed");
647 let parsed: FunctionDeclaration =
648 serde_json::from_str(&json_string).expect("Deserialization failed");
649
650 assert_eq!(parsed.name(), "get_weather");
651 assert_eq!(
652 parsed.description(),
653 "Get the current weather in a given location"
654 );
655 }
656
657 #[test]
658 fn test_function_calling_mode_serialization() {
659 let test_cases = [
661 (FunctionCallingMode::Auto, "\"AUTO\""),
662 (FunctionCallingMode::Any, "\"ANY\""),
663 (FunctionCallingMode::None, "\"NONE\""),
664 (FunctionCallingMode::Validated, "\"VALIDATED\""),
665 ];
666
667 for (mode, expected_json) in test_cases {
668 let json = serde_json::to_string(&mode).expect("Serialization failed");
669 assert_eq!(json, expected_json);
670
671 let parsed: FunctionCallingMode =
672 serde_json::from_str(&json).expect("Deserialization failed");
673 assert_eq!(parsed, mode);
674 }
675 }
676
677 #[test]
678 fn test_function_calling_mode_unknown_roundtrip() {
679 let json = "\"FUTURE_MODE\"";
681 let parsed: FunctionCallingMode =
682 serde_json::from_str(json).expect("Deserialization failed");
683
684 assert!(parsed.is_unknown());
685 assert_eq!(parsed.unknown_mode_type(), Some("FUTURE_MODE"));
686
687 let reserialized = serde_json::to_string(&parsed).expect("Serialization failed");
689 assert_eq!(reserialized, json);
690 }
691
692 #[test]
693 fn test_function_calling_mode_helper_methods() {
694 assert!(!FunctionCallingMode::Auto.is_unknown());
696 assert!(!FunctionCallingMode::Any.is_unknown());
697 assert!(!FunctionCallingMode::None.is_unknown());
698 assert!(!FunctionCallingMode::Validated.is_unknown());
699
700 assert!(FunctionCallingMode::Auto.unknown_mode_type().is_none());
701 assert!(FunctionCallingMode::Auto.unknown_data().is_none());
702
703 let unknown = FunctionCallingMode::Unknown {
705 mode_type: "NEW_MODE".to_string(),
706 data: serde_json::json!("NEW_MODE"),
707 };
708 assert!(unknown.is_unknown());
709 assert_eq!(unknown.unknown_mode_type(), Some("NEW_MODE"));
710 assert!(unknown.unknown_data().is_some());
711 }
712
713 #[test]
714 fn test_function_calling_mode_non_string_value() {
715 let json = "123";
717 let parsed: FunctionCallingMode =
718 serde_json::from_str(json).expect("Deserialization should succeed");
719
720 assert!(parsed.is_unknown());
721 assert!(parsed.unknown_mode_type().unwrap().contains("<non-string:"));
723 }
724
725 #[test]
726 fn test_tool_google_search_roundtrip() {
727 let tool = Tool::GoogleSearch;
728 let json = serde_json::to_string(&tool).expect("Serialization failed");
729 assert!(json.contains("\"type\":\"google_search\""));
730
731 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
732 assert!(matches!(parsed, Tool::GoogleSearch));
733 }
734
735 #[test]
736 fn test_tool_function_roundtrip() {
737 let tool = Tool::Function {
738 name: "get_weather".to_string(),
739 description: "Get weather".to_string(),
740 parameters: FunctionParameters::new(
741 "object".to_string(),
742 serde_json::json!({}),
743 vec![],
744 ),
745 };
746 let json = serde_json::to_string(&tool).expect("Serialization failed");
747 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
748
749 match parsed {
750 Tool::Function { name, .. } => assert_eq!(name, "get_weather"),
751 other => panic!("Expected Function variant, got {:?}", other),
752 }
753 }
754
755 #[test]
756 fn test_tool_mcp_server_roundtrip() {
757 let tool = Tool::McpServer {
758 name: "my-server".to_string(),
759 url: "https://mcp.example.com/api".to_string(),
760 };
761 let json = serde_json::to_string(&tool).expect("Serialization failed");
762 assert!(json.contains("\"type\":\"mcp_server\""));
763 assert!(json.contains("\"name\":\"my-server\""));
764 assert!(json.contains("\"url\":\"https://mcp.example.com/api\""));
765
766 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
767 match parsed {
768 Tool::McpServer { name, url } => {
769 assert_eq!(name, "my-server");
770 assert_eq!(url, "https://mcp.example.com/api");
771 }
772 other => panic!("Expected McpServer variant, got {:?}", other),
773 }
774 }
775
776 #[test]
777 fn test_tool_unknown_deserialization() {
778 let json = r#"{"type": "future_tool", "some_field": "value", "number": 42}"#;
780 let parsed: Tool = serde_json::from_str(json).expect("Deserialization failed");
781
782 match parsed {
783 Tool::Unknown { tool_type, data } => {
784 assert_eq!(tool_type, "future_tool");
785 assert_eq!(data.get("some_field").unwrap(), "value");
786 assert_eq!(data.get("number").unwrap(), 42);
787 }
788 _ => panic!("Expected Unknown variant"),
789 }
790 }
791
792 #[test]
793 fn test_tool_unknown_roundtrip() {
794 let tool = Tool::Unknown {
795 tool_type: "new_tool".to_string(),
796 data: serde_json::json!({"type": "new_tool", "config": {"enabled": true}}),
797 };
798 let json = serde_json::to_string(&tool).expect("Serialization failed");
799
800 assert!(json.contains("\"type\":\"new_tool\""));
802 assert!(json.contains("\"config\""));
803
804 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
805 match parsed {
806 Tool::Unknown { tool_type, .. } => assert_eq!(tool_type, "new_tool"),
807 _ => panic!("Expected Unknown variant"),
808 }
809 }
810
811 #[test]
812 fn test_tool_unknown_helper_methods() {
813 let unknown_tool = Tool::Unknown {
815 tool_type: "future_tool".to_string(),
816 data: serde_json::json!({"type": "future_tool", "setting": 123}),
817 };
818
819 assert!(unknown_tool.is_unknown());
820 assert_eq!(unknown_tool.unknown_tool_type(), Some("future_tool"));
821 let data = unknown_tool.unknown_data().expect("Should have data");
822 assert_eq!(data.get("setting").unwrap(), 123);
823 }
824
825 #[test]
826 fn test_tool_computer_use_roundtrip() {
827 let tool = Tool::ComputerUse {
828 environment: "browser".to_string(),
829 excluded_predefined_functions: vec!["submit_form".to_string(), "download".to_string()],
830 };
831 let json = serde_json::to_string(&tool).expect("Serialization failed");
832 assert!(json.contains("\"type\":\"computer_use\""));
833 assert!(json.contains("\"environment\":\"browser\""));
834 assert!(json.contains("\"excludedPredefinedFunctions\""));
835
836 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
837 match parsed {
838 Tool::ComputerUse {
839 environment,
840 excluded_predefined_functions,
841 } => {
842 assert_eq!(environment, "browser");
843 assert_eq!(excluded_predefined_functions.len(), 2);
844 assert!(excluded_predefined_functions.contains(&"submit_form".to_string()));
845 }
846 other => panic!("Expected ComputerUse variant, got {:?}", other),
847 }
848 }
849
850 #[test]
851 fn test_tool_computer_use_empty_exclusions() {
852 let tool = Tool::ComputerUse {
854 environment: "browser".to_string(),
855 excluded_predefined_functions: vec![],
856 };
857 let json = serde_json::to_string(&tool).expect("Serialization failed");
858 assert!(json.contains("\"type\":\"computer_use\""));
859 assert!(json.contains("\"environment\":\"browser\""));
860 assert!(!json.contains("excludedPredefinedFunctions"));
861
862 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
863 match parsed {
864 Tool::ComputerUse {
865 excluded_predefined_functions,
866 ..
867 } => {
868 assert!(excluded_predefined_functions.is_empty());
869 }
870 other => panic!("Expected ComputerUse variant, got {:?}", other),
871 }
872 }
873
874 #[test]
875 fn test_tool_known_types_helper_methods() {
876 let google_search = Tool::GoogleSearch;
878 assert!(!google_search.is_unknown());
879 assert_eq!(google_search.unknown_tool_type(), None);
880 assert_eq!(google_search.unknown_data(), None);
881
882 let code_execution = Tool::CodeExecution;
883 assert!(!code_execution.is_unknown());
884 assert_eq!(code_execution.unknown_tool_type(), None);
885 assert_eq!(code_execution.unknown_data(), None);
886
887 let url_context = Tool::UrlContext;
888 assert!(!url_context.is_unknown());
889 assert_eq!(url_context.unknown_tool_type(), None);
890 assert_eq!(url_context.unknown_data(), None);
891
892 let computer_use = Tool::ComputerUse {
893 environment: "browser".to_string(),
894 excluded_predefined_functions: vec![],
895 };
896 assert!(!computer_use.is_unknown());
897 assert_eq!(computer_use.unknown_tool_type(), None);
898 assert_eq!(computer_use.unknown_data(), None);
899
900 let function = Tool::Function {
901 name: "test".to_string(),
902 description: "Test function".to_string(),
903 parameters: FunctionParameters::new(
904 "object".to_string(),
905 serde_json::json!({}),
906 vec![],
907 ),
908 };
909 assert!(!function.is_unknown());
910 assert_eq!(function.unknown_tool_type(), None);
911 assert_eq!(function.unknown_data(), None);
912 }
913
914 #[test]
915 fn test_tool_file_search_roundtrip() {
916 let tool = Tool::FileSearch {
917 store_names: vec!["store1".to_string(), "store2".to_string()],
918 top_k: Some(5),
919 metadata_filter: Some("category:technical".to_string()),
920 };
921 let json = serde_json::to_string(&tool).expect("Serialization failed");
922 assert!(json.contains("\"type\":\"file_search\""));
923 assert!(json.contains("\"file_search_store_names\"")); assert!(json.contains("\"top_k\":5"));
925 assert!(json.contains("\"metadata_filter\":\"category:technical\""));
926
927 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
928 match parsed {
929 Tool::FileSearch {
930 store_names,
931 top_k,
932 metadata_filter,
933 } => {
934 assert_eq!(store_names, vec!["store1", "store2"]);
935 assert_eq!(top_k, Some(5));
936 assert_eq!(metadata_filter, Some("category:technical".to_string()));
937 }
938 other => panic!("Expected FileSearch variant, got {:?}", other),
939 }
940 }
941
942 #[test]
943 fn test_tool_file_search_minimal() {
944 let tool = Tool::FileSearch {
946 store_names: vec!["my-store".to_string()],
947 top_k: None,
948 metadata_filter: None,
949 };
950 let json = serde_json::to_string(&tool).expect("Serialization failed");
951 assert!(json.contains("\"type\":\"file_search\""));
952 assert!(json.contains("\"file_search_store_names\"")); assert!(!json.contains("\"top_k\""));
955 assert!(!json.contains("\"metadata_filter\""));
956
957 let parsed: Tool = serde_json::from_str(&json).expect("Deserialization failed");
958 match parsed {
959 Tool::FileSearch {
960 store_names,
961 top_k,
962 metadata_filter,
963 } => {
964 assert_eq!(store_names, vec!["my-store"]);
965 assert_eq!(top_k, None);
966 assert_eq!(metadata_filter, None);
967 }
968 other => panic!("Expected FileSearch variant, got {:?}", other),
969 }
970 }
971
972 #[test]
973 fn test_tool_file_search_helper_methods() {
974 let file_search = Tool::FileSearch {
975 store_names: vec!["store".to_string()],
976 top_k: None,
977 metadata_filter: None,
978 };
979 assert!(!file_search.is_unknown());
980 assert_eq!(file_search.unknown_tool_type(), None);
981 assert_eq!(file_search.unknown_data(), None);
982 }
983}