agtrace_types/tool/
args.rs

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    /// Get file path from various field names
18    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    /// Get search pattern from various field names
72    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/// MCP (Model Context Protocol) tool arguments
81///
82/// This struct captures structured information about MCP tools.
83/// The `server` and `tool` fields are populated by provider-specific
84/// normalization logic based on provider naming conventions.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct McpArgs {
87    /// MCP server identifier
88    /// Populated during normalization by provider-specific logic
89    #[serde(default, skip_serializing_if = "Option::is_none")]
90    pub server: Option<String>,
91
92    /// MCP tool identifier
93    /// Populated during normalization by provider-specific logic
94    #[serde(default, skip_serializing_if = "Option::is_none")]
95    pub tool: Option<String>,
96
97    /// Raw MCP tool arguments as JSON
98    #[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}