ai_agent/tools/
worktree.rs1use crate::types::*;
7
8pub struct EnterWorktreeTool;
10
11impl EnterWorktreeTool {
12 pub fn new() -> Self {
13 Self
14 }
15
16 pub fn input_schema(&self) -> ToolInputSchema {
17 ToolInputSchema {
18 schema_type: "object".to_string(),
19 properties: serde_json::json!({
20 "name": {
21 "type": "string",
22 "description": "Optional name for the worktree. If not provided, a random name is generated."
23 }
24 }),
25 required: None,
26 }
27 }
28
29 pub async fn execute(
30 &self,
31 input: serde_json::Value,
32 _context: &ToolContext,
33 ) -> Result<ToolResult, crate::error::AgentError> {
34 let name = input["name"].as_str();
35
36 let response = if let Some(n) = name {
37 format!(
38 "Creating worktree '{}'...\nNote: Full implementation would create a new git worktree at .ai/worktrees/{} and switch to it.",
39 n, n
40 )
41 } else {
42 "Creating worktree with random name...\nNote: Full implementation would create a new git worktree.".to_string()
43 };
44
45 Ok(ToolResult {
46 result_type: "text".to_string(),
47 tool_use_id: "enter_worktree".to_string(),
48 content: response,
49 is_error: Some(false),
50 })
51 }
52}
53
54impl Default for EnterWorktreeTool {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60pub struct ExitWorktreeTool;
62
63impl ExitWorktreeTool {
64 pub fn new() -> Self {
65 Self
66 }
67
68 pub fn input_schema(&self) -> ToolInputSchema {
69 ToolInputSchema {
70 schema_type: "object".to_string(),
71 properties: serde_json::json!({
72 "action": {
73 "type": "string",
74 "enum": ["keep", "remove"],
75 "description": "What to do with the worktree: 'keep' leaves it on disk, 'remove' deletes it"
76 },
77 "discardChanges": {
78 "type": "boolean",
79 "description": "If true, discard uncommitted changes before removing"
80 }
81 }),
82 required: None,
83 }
84 }
85
86 pub async fn execute(
87 &self,
88 input: serde_json::Value,
89 _context: &ToolContext,
90 ) -> Result<ToolResult, crate::error::AgentError> {
91 let action = input["action"].as_str().unwrap_or("keep");
92 let discard = input["discardChanges"].as_bool().unwrap_or(false);
93
94 let response = format!(
95 "Exiting worktree...\nAction: {}\nDiscard changes: {}\nNote: Full implementation would restore the session to the original working directory.",
96 action, discard
97 );
98
99 Ok(ToolResult {
100 result_type: "text".to_string(),
101 tool_use_id: "exit_worktree".to_string(),
102 content: response,
103 is_error: Some(false),
104 })
105 }
106}
107
108impl Default for ExitWorktreeTool {
109 fn default() -> Self {
110 Self::new()
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_enter_worktree_schema() {
120 let tool = EnterWorktreeTool::new();
121 let schema = tool.input_schema();
122 assert!(schema.properties.get("name").is_some());
123 }
124
125 #[test]
126 fn test_exit_worktree_schema() {
127 let tool = ExitWorktreeTool::new();
128 let schema = tool.input_schema();
129 assert!(schema.properties.get("action").is_some());
130 }
131}