adk_browser/tools/
windows.rs1use crate::session::BrowserSession;
4use adk_core::{AdkError, Result, Tool, ToolContext};
5use async_trait::async_trait;
6use serde_json::{json, Value};
7use std::sync::Arc;
8
9pub struct ListWindowsTool {
11 browser: Arc<BrowserSession>,
12}
13
14impl ListWindowsTool {
15 pub fn new(browser: Arc<BrowserSession>) -> Self {
16 Self { browser }
17 }
18}
19
20#[async_trait]
21impl Tool for ListWindowsTool {
22 fn name(&self) -> &str {
23 "browser_list_windows"
24 }
25
26 fn description(&self) -> &str {
27 "List all open browser windows/tabs."
28 }
29
30 fn parameters_schema(&self) -> Option<Value> {
31 Some(json!({
32 "type": "object",
33 "properties": {}
34 }))
35 }
36
37 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
38 let (windows, current) = self.browser.list_windows().await?;
39
40 Ok(json!({
41 "success": true,
42 "windows": windows,
43 "current_window": current,
44 "count": windows.len()
45 }))
46 }
47}
48
49pub struct NewTabTool {
51 browser: Arc<BrowserSession>,
52}
53
54impl NewTabTool {
55 pub fn new(browser: Arc<BrowserSession>) -> Self {
56 Self { browser }
57 }
58}
59
60#[async_trait]
61impl Tool for NewTabTool {
62 fn name(&self) -> &str {
63 "browser_new_tab"
64 }
65
66 fn description(&self) -> &str {
67 "Open a new browser tab and switch to it."
68 }
69
70 fn parameters_schema(&self) -> Option<Value> {
71 Some(json!({
72 "type": "object",
73 "properties": {
74 "url": {
75 "type": "string",
76 "description": "Optional URL to navigate to in the new tab"
77 }
78 }
79 }))
80 }
81
82 async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
83 let url = args.get("url").and_then(|v| v.as_str());
84
85 let handle = self.browser.new_tab().await?;
86
87 if let Some(url) = url {
88 self.browser.navigate(url).await?;
89 }
90
91 let current_url = self.browser.current_url().await.unwrap_or_default();
92
93 Ok(json!({
94 "success": true,
95 "window_handle": handle,
96 "url": current_url
97 }))
98 }
99}
100
101pub struct NewWindowTool {
103 browser: Arc<BrowserSession>,
104}
105
106impl NewWindowTool {
107 pub fn new(browser: Arc<BrowserSession>) -> Self {
108 Self { browser }
109 }
110}
111
112#[async_trait]
113impl Tool for NewWindowTool {
114 fn name(&self) -> &str {
115 "browser_new_window"
116 }
117
118 fn description(&self) -> &str {
119 "Open a new browser window and switch to it."
120 }
121
122 fn parameters_schema(&self) -> Option<Value> {
123 Some(json!({
124 "type": "object",
125 "properties": {
126 "url": {
127 "type": "string",
128 "description": "Optional URL to navigate to in the new window"
129 }
130 }
131 }))
132 }
133
134 async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
135 let url = args.get("url").and_then(|v| v.as_str());
136
137 let handle = self.browser.new_window().await?;
138
139 if let Some(url) = url {
140 self.browser.navigate(url).await?;
141 }
142
143 let current_url = self.browser.current_url().await.unwrap_or_default();
144
145 Ok(json!({
146 "success": true,
147 "window_handle": handle,
148 "url": current_url
149 }))
150 }
151}
152
153pub struct SwitchWindowTool {
155 browser: Arc<BrowserSession>,
156}
157
158impl SwitchWindowTool {
159 pub fn new(browser: Arc<BrowserSession>) -> Self {
160 Self { browser }
161 }
162}
163
164#[async_trait]
165impl Tool for SwitchWindowTool {
166 fn name(&self) -> &str {
167 "browser_switch_window"
168 }
169
170 fn description(&self) -> &str {
171 "Switch to a different browser window/tab by its handle."
172 }
173
174 fn parameters_schema(&self) -> Option<Value> {
175 Some(json!({
176 "type": "object",
177 "properties": {
178 "handle": {
179 "type": "string",
180 "description": "The window handle to switch to"
181 }
182 },
183 "required": ["handle"]
184 }))
185 }
186
187 async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
188 let handle = args
189 .get("handle")
190 .and_then(|v| v.as_str())
191 .ok_or_else(|| AdkError::Tool("Missing 'handle' parameter".to_string()))?;
192
193 self.browser.switch_to_window(handle).await?;
194
195 let url = self.browser.current_url().await.unwrap_or_default();
196 let title = self.browser.title().await.unwrap_or_default();
197
198 Ok(json!({
199 "success": true,
200 "switched_to": handle,
201 "url": url,
202 "title": title
203 }))
204 }
205}
206
207pub struct CloseWindowTool {
209 browser: Arc<BrowserSession>,
210}
211
212impl CloseWindowTool {
213 pub fn new(browser: Arc<BrowserSession>) -> Self {
214 Self { browser }
215 }
216}
217
218#[async_trait]
219impl Tool for CloseWindowTool {
220 fn name(&self) -> &str {
221 "browser_close_window"
222 }
223
224 fn description(&self) -> &str {
225 "Close the current browser window/tab."
226 }
227
228 fn parameters_schema(&self) -> Option<Value> {
229 Some(json!({
230 "type": "object",
231 "properties": {}
232 }))
233 }
234
235 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
236 self.browser.close_window().await?;
237
238 Ok(json!({
239 "success": true,
240 "message": "Window closed"
241 }))
242 }
243}
244
245pub struct MaximizeWindowTool {
247 browser: Arc<BrowserSession>,
248}
249
250impl MaximizeWindowTool {
251 pub fn new(browser: Arc<BrowserSession>) -> Self {
252 Self { browser }
253 }
254}
255
256#[async_trait]
257impl Tool for MaximizeWindowTool {
258 fn name(&self) -> &str {
259 "browser_maximize_window"
260 }
261
262 fn description(&self) -> &str {
263 "Maximize the browser window."
264 }
265
266 fn parameters_schema(&self) -> Option<Value> {
267 Some(json!({
268 "type": "object",
269 "properties": {}
270 }))
271 }
272
273 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
274 self.browser.maximize_window().await?;
275
276 Ok(json!({
277 "success": true,
278 "message": "Window maximized"
279 }))
280 }
281}
282
283pub struct MinimizeWindowTool {
285 browser: Arc<BrowserSession>,
286}
287
288impl MinimizeWindowTool {
289 pub fn new(browser: Arc<BrowserSession>) -> Self {
290 Self { browser }
291 }
292}
293
294#[async_trait]
295impl Tool for MinimizeWindowTool {
296 fn name(&self) -> &str {
297 "browser_minimize_window"
298 }
299
300 fn description(&self) -> &str {
301 "Minimize the browser window."
302 }
303
304 fn parameters_schema(&self) -> Option<Value> {
305 Some(json!({
306 "type": "object",
307 "properties": {}
308 }))
309 }
310
311 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
312 self.browser.minimize_window().await?;
313
314 Ok(json!({
315 "success": true,
316 "message": "Window minimized"
317 }))
318 }
319}
320
321pub struct SetWindowSizeTool {
323 browser: Arc<BrowserSession>,
324}
325
326impl SetWindowSizeTool {
327 pub fn new(browser: Arc<BrowserSession>) -> Self {
328 Self { browser }
329 }
330}
331
332#[async_trait]
333impl Tool for SetWindowSizeTool {
334 fn name(&self) -> &str {
335 "browser_set_window_size"
336 }
337
338 fn description(&self) -> &str {
339 "Set the browser window size and position."
340 }
341
342 fn parameters_schema(&self) -> Option<Value> {
343 Some(json!({
344 "type": "object",
345 "properties": {
346 "width": {
347 "type": "integer",
348 "description": "Window width in pixels"
349 },
350 "height": {
351 "type": "integer",
352 "description": "Window height in pixels"
353 },
354 "x": {
355 "type": "integer",
356 "description": "Window X position (default: 0)"
357 },
358 "y": {
359 "type": "integer",
360 "description": "Window Y position (default: 0)"
361 }
362 },
363 "required": ["width", "height"]
364 }))
365 }
366
367 async fn execute(&self, _ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
368 let width = args
369 .get("width")
370 .and_then(|v| v.as_u64())
371 .ok_or_else(|| AdkError::Tool("Missing 'width' parameter".to_string()))?
372 as u32;
373
374 let height = args
375 .get("height")
376 .and_then(|v| v.as_u64())
377 .ok_or_else(|| AdkError::Tool("Missing 'height' parameter".to_string()))?
378 as u32;
379
380 let x = args.get("x").and_then(|v| v.as_i64()).unwrap_or(0) as i32;
381 let y = args.get("y").and_then(|v| v.as_i64()).unwrap_or(0) as i32;
382
383 self.browser.set_window_rect(x, y, width, height).await?;
384
385 Ok(json!({
386 "success": true,
387 "width": width,
388 "height": height,
389 "x": x,
390 "y": y
391 }))
392 }
393}