1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct FileReadArgs {
6 #[serde(default, skip_serializing_if = "Option::is_none")]
7 pub file_path: Option<String>,
8 #[serde(default, skip_serializing_if = "Option::is_none")]
9 pub path: Option<String>,
10 #[serde(default, skip_serializing_if = "Option::is_none")]
11 pub pattern: Option<String>,
12 #[serde(flatten)]
13 pub extra: Value,
14}
15
16impl FileReadArgs {
17 pub fn path(&self) -> Option<&str> {
19 self.file_path.as_deref().or(self.path.as_deref())
20 }
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct FileEditArgs {
25 pub file_path: String,
26 pub old_string: String,
27 pub new_string: String,
28 #[serde(default)]
29 pub replace_all: bool,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct FileWriteArgs {
34 pub file_path: String,
35 pub content: String,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct ExecuteArgs {
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub command: Option<String>,
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub description: Option<String>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub timeout: Option<u64>,
46 #[serde(flatten)]
47 pub extra: Value,
48}
49
50impl ExecuteArgs {
51 pub fn command(&self) -> Option<&str> {
52 self.command.as_deref()
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct SearchArgs {
58 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub pattern: Option<String>,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub query: Option<String>,
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub input: Option<String>,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub path: Option<String>,
66 #[serde(flatten)]
67 pub extra: Value,
68}
69
70impl SearchArgs {
71 pub fn pattern(&self) -> Option<&str> {
73 self.pattern
74 .as_deref()
75 .or(self.query.as_deref())
76 .or(self.input.as_deref())
77 }
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct McpArgs {
87 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub server: Option<String>,
91
92 #[serde(default, skip_serializing_if = "Option::is_none")]
95 pub tool: Option<String>,
96
97 #[serde(flatten)]
99 pub inner: Value,
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_file_read_args_path_helper() {
108 let args1 = FileReadArgs {
109 file_path: Some("/path1".to_string()),
110 path: None,
111 pattern: None,
112 extra: serde_json::json!({}),
113 };
114 assert_eq!(args1.path(), Some("/path1"));
115
116 let args2 = FileReadArgs {
117 file_path: None,
118 path: Some("/path2".to_string()),
119 pattern: None,
120 extra: serde_json::json!({}),
121 };
122 assert_eq!(args2.path(), Some("/path2"));
123
124 let args3 = FileReadArgs {
125 file_path: Some("/path1".to_string()),
126 path: Some("/path2".to_string()),
127 pattern: None,
128 extra: serde_json::json!({}),
129 };
130 assert_eq!(args3.path(), Some("/path1"));
131 }
132
133 #[test]
134 fn test_search_args_pattern_helper() {
135 let args1 = SearchArgs {
136 pattern: Some("pattern1".to_string()),
137 query: None,
138 input: None,
139 path: None,
140 extra: serde_json::json!({}),
141 };
142 assert_eq!(args1.pattern(), Some("pattern1"));
143
144 let args2 = SearchArgs {
145 pattern: None,
146 query: Some("query2".to_string()),
147 input: None,
148 path: None,
149 extra: serde_json::json!({}),
150 };
151 assert_eq!(args2.pattern(), Some("query2"));
152
153 let args3 = SearchArgs {
154 pattern: None,
155 query: None,
156 input: Some("input3".to_string()),
157 path: None,
158 extra: serde_json::json!({}),
159 };
160 assert_eq!(args3.pattern(), Some("input3"));
161 }
162}