Skip to main content

agent_procs/cli/
up.rs

1use crate::cli;
2use crate::config::{load_config, resolve_session};
3use crate::protocol::{Request, Response};
4
5pub async fn execute(cli_session: Option<&str>, only: Option<&str>, config_path: Option<&str>) -> i32 {
6    let (path, config) = match load_config(config_path) {
7        Ok(c) => c,
8        Err(e) => { eprintln!("error: {}", e); return 1; }
9    };
10
11    let session = resolve_session(cli_session, config.session.as_deref());
12
13    let only_set: Option<Vec<&str>> = only.map(|s| s.split(',').collect());
14
15    let groups = match config.startup_order() {
16        Ok(g) => g,
17        Err(e) => { eprintln!("error: {}", e); return 1; }
18    };
19
20    for group in &groups {
21        for name in group {
22            if let Some(ref only) = only_set {
23                if !only.contains(&name.as_str()) { continue; }
24            }
25
26            let def = &config.processes[name];
27
28            // Resolve cwd relative to config file directory
29            let resolved_cwd = def.cwd.as_ref().map(|c| {
30                let p = std::path::Path::new(c);
31                if p.is_relative() {
32                    path.parent().unwrap_or(std::path::Path::new(".")).join(p).to_string_lossy().to_string()
33                } else {
34                    c.clone()
35                }
36            });
37
38            // Pass env vars through the protocol (no shell escaping needed)
39            let env = if def.env.is_empty() { None } else { Some(def.env.clone()) };
40
41            // Start the process
42            let req = Request::Run {
43                command: def.cmd.clone(),
44                name: Some(name.clone()),
45                cwd: resolved_cwd,
46                env,
47            };
48            match cli::request(session, &req, true).await {
49                Ok(Response::RunOk { name, id, pid }) => {
50                    println!("started {} (id: {}, pid: {})", name, id, pid);
51                }
52                Ok(Response::Error { code, message }) => {
53                    eprintln!("error starting {}: {}", name, message);
54                    return code;
55                }
56                _ => return 1,
57            }
58
59            // Wait for ready pattern
60            if let Some(ref ready) = def.ready {
61                let req = Request::Wait {
62                    target: name.clone(), until: Some(ready.clone()),
63                    regex: false, exit: false, timeout_secs: Some(30),
64                };
65                match cli::request(session, &req, false).await {
66                    Ok(Response::WaitMatch { .. }) => println!("{} is ready", name),
67                    Ok(Response::WaitTimeout) => {
68                        eprintln!("warning: {} did not become ready within 30s", name);
69                    }
70                    Ok(Response::Error { message, .. }) => {
71                        eprintln!("error waiting for {}: {}", name, message);
72                        return 1;
73                    }
74                    _ => {}
75                }
76            }
77        }
78    }
79
80    println!("all processes started");
81    0
82}