mermaid_cli/providers/tool/computer_use/
list_windows.rs1use std::sync::Arc;
6use std::time::Instant;
7
8use async_trait::async_trait;
9use serde_json::Value;
10
11use crate::domain::{ToolDefinition, ToolOutcome};
12use crate::providers::ctx::ExecContext;
13
14use super::super::ToolExecutor;
15use super::computer_use_success;
16use super::driver::ComputerUseDriver;
17
18pub struct ListWindowsTool {
19 driver: Arc<ComputerUseDriver>,
20}
21
22impl ListWindowsTool {
23 pub fn new(driver: Arc<ComputerUseDriver>) -> Self {
24 Self { driver }
25 }
26}
27
28#[async_trait]
29impl ToolExecutor for ListWindowsTool {
30 fn name(&self) -> &'static str {
31 "list_windows"
32 }
33
34 fn schema(&self) -> ToolDefinition {
35 ToolDefinition {
36 name: "list_windows".to_string(),
37 description: "List visible window titles. X11 only. On Wayland, use screenshot mode \
38 'fullscreen' or 'monitor' instead — window enumeration is not portable \
39 across compositors."
40 .to_string(),
41 input_schema: serde_json::json!({ "type": "object", "properties": {} }),
42 }
43 }
44
45 async fn execute(&self, args: Value, ctx: ExecContext) -> ToolOutcome {
46 let started = Instant::now();
47 if let Err(error) = self.driver.ensure_alive() {
48 return ToolOutcome::error(error, started.elapsed().as_secs_f64());
49 }
50
51 let windows = tokio::select! {
52 biased;
53 _ = ctx.token.cancelled() => return ToolOutcome::cancelled(),
54 r = self.driver.list_windows(&ctx.token) => match r {
55 Ok(w) => w,
56 Err(e) => return ToolOutcome::error(
57 format!("list_windows failed: {}", e),
58 started.elapsed().as_secs_f64(),
59 ),
60 },
61 };
62
63 let output = if windows.is_empty() {
64 "No visible windows found.".to_string()
65 } else {
66 let list = windows
67 .iter()
68 .map(|w| format!(" - {}", w))
69 .collect::<Vec<_>>()
70 .join("\n");
71 format!("Visible windows ({}):\n{}", windows.len(), list)
72 };
73
74 computer_use_success(
75 "list_windows",
76 args,
77 output,
78 started.elapsed().as_secs_f64(),
79 )
80 }
81}