1use crate::session::BrowserSession;
4use crate::tools::*;
5use adk_core::{ReadonlyContext, Result, Tool, Toolset};
6use async_trait::async_trait;
7use std::sync::Arc;
8
9pub struct BrowserToolset {
14 browser: Arc<BrowserSession>,
15 include_navigation: bool,
17 include_interaction: bool,
19 include_extraction: bool,
21 include_wait: bool,
23 include_screenshot: bool,
25 include_js: bool,
27 include_cookies: bool,
29 include_windows: bool,
31 include_frames: bool,
33 include_actions: bool,
35}
36
37impl BrowserToolset {
38 pub fn new(browser: Arc<BrowserSession>) -> Self {
40 Self {
41 browser,
42 include_navigation: true,
43 include_interaction: true,
44 include_extraction: true,
45 include_wait: true,
46 include_screenshot: true,
47 include_js: true,
48 include_cookies: true,
49 include_windows: true,
50 include_frames: true,
51 include_actions: true,
52 }
53 }
54
55 pub fn with_navigation(mut self, enabled: bool) -> Self {
57 self.include_navigation = enabled;
58 self
59 }
60
61 pub fn with_interaction(mut self, enabled: bool) -> Self {
63 self.include_interaction = enabled;
64 self
65 }
66
67 pub fn with_extraction(mut self, enabled: bool) -> Self {
69 self.include_extraction = enabled;
70 self
71 }
72
73 pub fn with_wait(mut self, enabled: bool) -> Self {
75 self.include_wait = enabled;
76 self
77 }
78
79 pub fn with_screenshot(mut self, enabled: bool) -> Self {
81 self.include_screenshot = enabled;
82 self
83 }
84
85 pub fn with_js(mut self, enabled: bool) -> Self {
87 self.include_js = enabled;
88 self
89 }
90
91 pub fn with_cookies(mut self, enabled: bool) -> Self {
93 self.include_cookies = enabled;
94 self
95 }
96
97 pub fn with_windows(mut self, enabled: bool) -> Self {
99 self.include_windows = enabled;
100 self
101 }
102
103 pub fn with_frames(mut self, enabled: bool) -> Self {
105 self.include_frames = enabled;
106 self
107 }
108
109 pub fn with_actions(mut self, enabled: bool) -> Self {
111 self.include_actions = enabled;
112 self
113 }
114
115 pub fn all_tools(&self) -> Vec<Arc<dyn Tool>> {
117 let mut tools: Vec<Arc<dyn Tool>> = Vec::new();
118
119 if self.include_navigation {
120 tools.push(Arc::new(NavigateTool::new(self.browser.clone())));
121 tools.push(Arc::new(BackTool::new(self.browser.clone())));
122 tools.push(Arc::new(ForwardTool::new(self.browser.clone())));
123 tools.push(Arc::new(RefreshTool::new(self.browser.clone())));
124 }
125
126 if self.include_interaction {
127 tools.push(Arc::new(ClickTool::new(self.browser.clone())));
128 tools.push(Arc::new(DoubleClickTool::new(self.browser.clone())));
129 tools.push(Arc::new(TypeTool::new(self.browser.clone())));
130 tools.push(Arc::new(ClearTool::new(self.browser.clone())));
131 tools.push(Arc::new(SelectTool::new(self.browser.clone())));
132 }
133
134 if self.include_extraction {
135 tools.push(Arc::new(ExtractTextTool::new(self.browser.clone())));
136 tools.push(Arc::new(ExtractAttributeTool::new(self.browser.clone())));
137 tools.push(Arc::new(ExtractLinksTool::new(self.browser.clone())));
138 tools.push(Arc::new(PageInfoTool::new(self.browser.clone())));
139 tools.push(Arc::new(PageSourceTool::new(self.browser.clone())));
140 }
141
142 if self.include_wait {
143 tools.push(Arc::new(WaitForElementTool::new(self.browser.clone())));
144 tools.push(Arc::new(WaitTool::new()));
145 tools.push(Arc::new(WaitForPageLoadTool::new(self.browser.clone())));
146 tools.push(Arc::new(WaitForTextTool::new(self.browser.clone())));
147 }
148
149 if self.include_screenshot {
150 tools.push(Arc::new(ScreenshotTool::new(self.browser.clone())));
151 }
152
153 if self.include_js {
154 tools.push(Arc::new(EvaluateJsTool::new(self.browser.clone())));
155 tools.push(Arc::new(ScrollTool::new(self.browser.clone())));
156 tools.push(Arc::new(HoverTool::new(self.browser.clone())));
157 tools.push(Arc::new(AlertTool::new(self.browser.clone())));
158 }
159
160 if self.include_cookies {
161 tools.push(Arc::new(GetCookiesTool::new(self.browser.clone())));
162 tools.push(Arc::new(GetCookieTool::new(self.browser.clone())));
163 tools.push(Arc::new(AddCookieTool::new(self.browser.clone())));
164 tools.push(Arc::new(DeleteCookieTool::new(self.browser.clone())));
165 tools.push(Arc::new(DeleteAllCookiesTool::new(self.browser.clone())));
166 }
167
168 if self.include_windows {
169 tools.push(Arc::new(ListWindowsTool::new(self.browser.clone())));
170 tools.push(Arc::new(NewTabTool::new(self.browser.clone())));
171 tools.push(Arc::new(NewWindowTool::new(self.browser.clone())));
172 tools.push(Arc::new(SwitchWindowTool::new(self.browser.clone())));
173 tools.push(Arc::new(CloseWindowTool::new(self.browser.clone())));
174 tools.push(Arc::new(MaximizeWindowTool::new(self.browser.clone())));
175 tools.push(Arc::new(MinimizeWindowTool::new(self.browser.clone())));
176 tools.push(Arc::new(SetWindowSizeTool::new(self.browser.clone())));
177 }
178
179 if self.include_frames {
180 tools.push(Arc::new(SwitchToFrameTool::new(self.browser.clone())));
181 tools.push(Arc::new(SwitchToParentFrameTool::new(self.browser.clone())));
182 tools.push(Arc::new(SwitchToDefaultContentTool::new(self.browser.clone())));
183 }
184
185 if self.include_actions {
186 tools.push(Arc::new(DragAndDropTool::new(self.browser.clone())));
187 tools.push(Arc::new(RightClickTool::new(self.browser.clone())));
188 tools.push(Arc::new(FocusTool::new(self.browser.clone())));
189 tools.push(Arc::new(ElementStateTool::new(self.browser.clone())));
190 tools.push(Arc::new(PressKeyTool::new(self.browser.clone())));
191 tools.push(Arc::new(FileUploadTool::new(self.browser.clone())));
192 tools.push(Arc::new(PrintToPdfTool::new(self.browser.clone())));
193 }
194
195 tools
196 }
197}
198
199#[async_trait]
200impl Toolset for BrowserToolset {
201 fn name(&self) -> &str {
202 "browser"
203 }
204
205 async fn tools(&self, _ctx: Arc<dyn ReadonlyContext>) -> Result<Vec<Arc<dyn Tool>>> {
206 Ok(self.all_tools())
207 }
208}
209
210pub fn minimal_browser_tools(browser: Arc<BrowserSession>) -> Vec<Arc<dyn Tool>> {
212 vec![
213 Arc::new(NavigateTool::new(browser.clone())),
214 Arc::new(ClickTool::new(browser.clone())),
215 Arc::new(TypeTool::new(browser.clone())),
216 Arc::new(ExtractTextTool::new(browser.clone())),
217 Arc::new(WaitForElementTool::new(browser.clone())),
218 Arc::new(ScreenshotTool::new(browser)),
219 ]
220}
221
222pub fn readonly_browser_tools(browser: Arc<BrowserSession>) -> Vec<Arc<dyn Tool>> {
224 vec![
225 Arc::new(NavigateTool::new(browser.clone())),
226 Arc::new(ExtractTextTool::new(browser.clone())),
227 Arc::new(ExtractAttributeTool::new(browser.clone())),
228 Arc::new(ExtractLinksTool::new(browser.clone())),
229 Arc::new(PageInfoTool::new(browser.clone())),
230 Arc::new(ScreenshotTool::new(browser.clone())),
231 Arc::new(ScrollTool::new(browser)),
232 ]
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238 use crate::config::BrowserConfig;
239
240 #[test]
241 fn test_toolset_all_tools() {
242 let browser = Arc::new(BrowserSession::new(BrowserConfig::default()));
243 let toolset = BrowserToolset::new(browser);
244 let tools = toolset.all_tools();
245
246 assert!(tools.len() > 40);
248
249 let tool_names: Vec<&str> = tools.iter().map(|t| t.name()).collect();
251 assert!(tool_names.contains(&"browser_navigate"));
252 assert!(tool_names.contains(&"browser_click"));
253 assert!(tool_names.contains(&"browser_type"));
254 assert!(tool_names.contains(&"browser_screenshot"));
255 assert!(tool_names.contains(&"browser_get_cookies"));
257 assert!(tool_names.contains(&"browser_new_tab"));
258 assert!(tool_names.contains(&"browser_switch_to_frame"));
259 assert!(tool_names.contains(&"browser_drag_and_drop"));
260 }
261
262 #[test]
263 fn test_toolset_selective() {
264 let browser = Arc::new(BrowserSession::new(BrowserConfig::default()));
265 let toolset = BrowserToolset::new(browser)
266 .with_navigation(true)
267 .with_interaction(false)
268 .with_extraction(false)
269 .with_wait(false)
270 .with_screenshot(false)
271 .with_js(false)
272 .with_cookies(false)
273 .with_windows(false)
274 .with_frames(false)
275 .with_actions(false);
276
277 let tools = toolset.all_tools();
278
279 assert_eq!(tools.len(), 4);
281 }
282
283 #[test]
284 fn test_minimal_tools() {
285 let browser = Arc::new(BrowserSession::new(BrowserConfig::default()));
286 let tools = minimal_browser_tools(browser);
287
288 assert_eq!(tools.len(), 6);
289 }
290}