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