list_worktrees_tool.rs

 1use std::sync::Arc;
 2
 3use anyhow::{anyhow, Result};
 4use assistant_tool::Tool;
 5use gpui::{App, Task, WeakEntity, Window};
 6use schemars::JsonSchema;
 7use serde::{Deserialize, Serialize};
 8use workspace::Workspace;
 9
10#[derive(Debug, Serialize, Deserialize, JsonSchema)]
11pub struct ListWorktreesToolInput {}
12
13pub struct ListWorktreesTool;
14
15impl Tool for ListWorktreesTool {
16    fn name(&self) -> String {
17        "list-worktrees".into()
18    }
19
20    fn description(&self) -> String {
21        "Lists all worktrees in the current project. Use this tool when you need to find available worktrees and their IDs.".into()
22    }
23
24    fn input_schema(&self) -> serde_json::Value {
25        serde_json::json!(
26            {
27                "type": "object",
28                "properties": {},
29                "required": []
30            }
31        )
32    }
33
34    fn run(
35        self: Arc<Self>,
36        _input: serde_json::Value,
37        workspace: WeakEntity<Workspace>,
38        _window: &mut Window,
39        cx: &mut App,
40    ) -> Task<Result<String>> {
41        let Some(workspace) = workspace.upgrade() else {
42            return Task::ready(Err(anyhow!("workspace dropped")));
43        };
44
45        let project = workspace.read(cx).project().clone();
46
47        cx.spawn(|cx| async move {
48            cx.update(|cx| {
49                #[derive(Debug, Serialize)]
50                struct WorktreeInfo {
51                    id: usize,
52                    root_name: String,
53                    root_dir: Option<String>,
54                }
55
56                let worktrees = project.update(cx, |project, cx| {
57                    project
58                        .visible_worktrees(cx)
59                        .map(|worktree| {
60                            worktree.read_with(cx, |worktree, _cx| WorktreeInfo {
61                                id: worktree.id().to_usize(),
62                                root_dir: worktree
63                                    .root_dir()
64                                    .map(|root_dir| root_dir.to_string_lossy().to_string()),
65                                root_name: worktree.root_name().to_string(),
66                            })
67                        })
68                        .collect::<Vec<_>>()
69                });
70
71                if worktrees.is_empty() {
72                    return Ok("No worktrees found in the current project.".to_string());
73                }
74
75                let mut result = String::from("Worktrees in the current project:\n\n");
76                for worktree in worktrees {
77                    result.push_str(&serde_json::to_string(&worktree)?);
78                }
79
80                Ok(result)
81            })?
82        })
83    }
84}