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::providers::ctx::ExecContext;
12use mermaid_domain::{ToolDefinition, ToolOutcome};
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_async().await {
48 return ToolOutcome::error(error, started.elapsed().as_secs_f64());
49 }
50 if let Some(blocked) = super::super::policy_gate::gate_external(
51 &ctx,
52 "list_windows",
53 mermaid_runtime::ToolCategory::ComputerUse,
54 "computer-use: list_windows".to_string(),
55 &args,
56 )
57 .await
58 {
59 return blocked;
60 }
61
62 let windows = tokio::select! {
63 biased;
64 _ = ctx.token.cancelled() => return ToolOutcome::cancelled(),
65 r = self.driver.list_windows(&ctx.token) => match r {
66 Ok(w) => w,
67 Err(e) => return ToolOutcome::error(
68 format!("list_windows failed: {e}"),
69 started.elapsed().as_secs_f64(),
70 ),
71 },
72 };
73
74 let output = if windows.is_empty() {
75 "No visible windows found.".to_string()
76 } else {
77 let list = windows
78 .iter()
79 .map(|w| format!(" - {w}"))
80 .collect::<Vec<_>>()
81 .join("\n");
82 format!("Visible windows ({}):\n{}", windows.len(), list)
83 };
84
85 computer_use_success(
86 "list_windows",
87 args,
88 output,
89 started.elapsed().as_secs_f64(),
90 )
91 }
92}