agents_launcher/
lib.rs

1pub fn generate_applescript(
2    _task: &str,
3    current_dir: &str,
4    prompt_file: &str,
5    _is_first: bool,
6    agent_command: &str,
7    agent_flag: &str,
8) -> String {
9    // Create a wrapper script that reads the prompt file and passes it to the agent
10    // This avoids both the raw mode error and AppleScript escaping issues
11    let wrapper_script = format!("{}.wrapper.sh", prompt_file);
12
13    // Create the wrapper script content
14    let wrapper_content = format!(
15        r#"#!/bin/bash
16cd "{}"
17PROMPT=$(cat "{}")
18{} {} "$PROMPT"
19rm "{}"
20rm "{}"
21"#,
22        current_dir, prompt_file, agent_command, agent_flag, prompt_file, wrapper_script
23    );
24    
25    // Write the wrapper script (create parent directory if needed)
26    if let Some(parent) = std::path::Path::new(&wrapper_script).parent() {
27        let _ = std::fs::create_dir_all(parent);
28    }
29    std::fs::write(&wrapper_script, wrapper_content)
30        .expect("Failed to write wrapper script");
31    
32    // Make it executable
33    std::process::Command::new("chmod")
34        .arg("+x")
35        .arg(&wrapper_script)
36        .output()
37        .expect("Failed to make wrapper script executable");
38    
39    // Use the wrapper script in AppleScript
40    let shell_command = format!("{}", wrapper_script);
41
42    // Both first and additional tabs use the same AppleScript
43    format!(
44        r#"tell application "iTerm"
45    tell current window
46        create tab with default profile
47        tell current session
48            write text "{}"
49        end tell
50    end tell
51end tell"#,
52        shell_command
53    )
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use tempfile::TempDir;
60
61    #[test]
62    fn test_generate_applescript_first_tab() {
63        let temp_dir = TempDir::new().unwrap();
64        let dir_path = temp_dir.path().to_str().unwrap();
65        let prompt_file = format!("{}/agent_prompt_task_1.txt", dir_path);
66
67        let script = generate_applescript(
68            "test task",
69            dir_path,
70            &prompt_file,
71            true,
72            "claude",
73            "--dangerously-skip-permissions",
74        );
75
76        assert!(script.contains("tell application \"iTerm\""));
77        assert!(script.contains("create tab with default profile"));
78        assert!(script.contains(&format!("{}.wrapper.sh", prompt_file)));
79    }
80
81    #[test]
82    fn test_generate_applescript_additional_tab() {
83        let temp_dir = TempDir::new().unwrap();
84        let dir_path = temp_dir.path().to_str().unwrap();
85        let prompt_file = format!("{}/agent_prompt_task_2.txt", dir_path);
86
87        let script = generate_applescript(
88            "another task",
89            dir_path,
90            &prompt_file,
91            false,
92            "claude",
93            "--dangerously-skip-permissions",
94        );
95
96        assert!(script.contains("tell application \"iTerm\""));
97        assert!(script.contains("create tab with default profile"));
98        assert!(script.contains(&format!("{}.wrapper.sh", prompt_file)));
99    }
100
101    #[test]
102    fn test_command_structure() {
103        let temp_dir = TempDir::new().unwrap();
104        let dir_path = temp_dir.path().to_str().unwrap();
105        let prompt_file = format!("{}/agent_prompt_task_1.txt", dir_path);
106
107        let script = generate_applescript(
108            "test",
109            dir_path,
110            &prompt_file,
111            true,
112            "claude",
113            "--dangerously-skip-permissions",
114        );
115
116        assert!(script.contains(&format!("{}.wrapper.sh", prompt_file)));
117    }
118
119    #[test]
120    fn test_generate_applescript_with_codex() {
121        let temp_dir = TempDir::new().unwrap();
122        let dir_path = temp_dir.path().to_str().unwrap();
123        let prompt_file = format!("{}/agent_prompt_task_codex.txt", dir_path);
124
125        let script = generate_applescript(
126            "test codex",
127            dir_path,
128            &prompt_file,
129            true,
130            "codex",
131            "--yolo",
132        );
133
134        assert!(script.contains("tell application \"iTerm\""));
135        assert!(script.contains("create tab with default profile"));
136        assert!(script.contains(&format!("{}.wrapper.sh", prompt_file)));
137
138        // Read the wrapper script to verify it uses codex
139        let wrapper_script = format!("{}.wrapper.sh", prompt_file);
140        let wrapper_content = std::fs::read_to_string(&wrapper_script).unwrap();
141        assert!(wrapper_content.contains("codex --yolo"));
142    }
143}