1use crate::cli;
2use crate::config::{discover_config, ProjectConfig};
3use crate::protocol::{Request, Response};
4
5pub async fn execute(session: &str, only: Option<&str>, config_path: Option<&str>) -> i32 {
6 let path = match config_path {
7 Some(p) => std::path::PathBuf::from(p),
8 None => match discover_config(&std::env::current_dir().unwrap()) {
9 Some(p) => p,
10 None => { eprintln!("error: no agent-procs.yaml found"); return 1; }
11 },
12 };
13
14 let content = match std::fs::read_to_string(&path) {
15 Ok(c) => c,
16 Err(e) => { eprintln!("error: cannot read config: {}", e); return 1; }
17 };
18
19 let config: ProjectConfig = match serde_yaml::from_str(&content) {
20 Ok(c) => c,
21 Err(e) => { eprintln!("error: invalid config: {}", e); return 1; }
22 };
23
24 let only_set: Option<Vec<&str>> = only.map(|s| s.split(',').collect());
25
26 let groups = match config.startup_order() {
27 Ok(g) => g,
28 Err(e) => { eprintln!("error: {}", e); return 1; }
29 };
30
31 for group in &groups {
32 for name in group {
33 if let Some(ref only) = only_set {
34 if !only.contains(&name.as_str()) { continue; }
35 }
36
37 let def = &config.processes[name];
38
39 let resolved_cwd = def.cwd.as_ref().map(|c| {
41 let p = std::path::Path::new(c);
42 if p.is_relative() {
43 path.parent().unwrap_or(std::path::Path::new(".")).join(p).to_string_lossy().to_string()
44 } else {
45 c.clone()
46 }
47 });
48
49 let env = if def.env.is_empty() { None } else { Some(def.env.clone()) };
51
52 let req = Request::Run {
54 command: def.cmd.clone(),
55 name: Some(name.clone()),
56 cwd: resolved_cwd,
57 env,
58 };
59 match cli::request(session, &req, true).await {
60 Ok(Response::RunOk { name, id, pid }) => {
61 println!("started {} (id: {}, pid: {})", name, id, pid);
62 }
63 Ok(Response::Error { code, message }) => {
64 eprintln!("error starting {}: {}", name, message);
65 return code;
66 }
67 _ => return 1,
68 }
69
70 if let Some(ref ready) = def.ready {
72 let req = Request::Wait {
73 target: name.clone(), until: Some(ready.clone()),
74 regex: false, exit: false, timeout_secs: Some(30),
75 };
76 match cli::request(session, &req, false).await {
77 Ok(Response::WaitMatch { .. }) => println!("{} is ready", name),
78 Ok(Response::WaitTimeout) => {
79 eprintln!("warning: {} did not become ready within 30s", name);
80 }
81 Ok(Response::Error { message, .. }) => {
82 eprintln!("error waiting for {}: {}", name, message);
83 return 1;
84 }
85 _ => {}
86 }
87 }
88 }
89 }
90
91 println!("all processes started");
92 0
93}