Skip to main content

rtango/cmd/
init.rs

1use std::path::Path;
2
3use anyhow::bail;
4
5use crate::agent::{self, SourceKind};
6use crate::engine::{compute_plan, managed_gitignore_entries};
7use crate::error::RtangoError;
8use crate::spec::io::{gitignore_update, lock_path, rtango_dir, spec_path, write_gitignore};
9use crate::spec::{AgentName, Defaults, Lock, Rule, RuleKind, Source, Spec};
10
11pub fn exec(
12    root: &Path,
13    force: bool,
14    no_detect: bool,
15    gitignore_targets: bool,
16) -> anyhow::Result<()> {
17    let spec_path = spec_path(root);
18    let lock_path = lock_path(root);
19
20    if spec_path.exists() && !force {
21        bail!(RtangoError::SpecExists);
22    }
23
24    let detected = if no_detect {
25        Vec::new()
26    } else {
27        let detected = agent::detect_agents(root);
28        if detected.is_empty() {
29            bail!(RtangoError::NoAgentsDetected);
30        }
31        detected
32    };
33
34    let agent_names: Vec<AgentName> = detected.iter().map(|d| d.name.clone()).collect();
35
36    let mut rules = Vec::new();
37    for agent in &detected {
38        for source in &agent.sources {
39            rules.push(Rule {
40                id: source.id.clone(),
41                source: Source::Local(source.path.clone()),
42                schema_agent: agent.name.clone(),
43                on_target_modified: None,
44                kind: match source.kind {
45                    SourceKind::SkillSet => RuleKind::skill_set(),
46                    SourceKind::AgentSet => RuleKind::agent_set(),
47                },
48            });
49        }
50    }
51
52    let spec = Spec {
53        version: 1,
54        agents: agent_names.clone(),
55        defaults: Defaults {
56            gitignore_targets,
57            ..Defaults::default()
58        },
59        rules,
60    };
61
62    let lock = Lock {
63        version: 1,
64        tracked_agents: agent_names,
65        owners: vec![],
66        deployments: vec![],
67    };
68
69    let spec_yaml = serde_yml::to_string(&spec)?;
70    let lock_yaml = serde_yml::to_string(&lock)?;
71
72    std::fs::create_dir_all(rtango_dir(root))?;
73    std::fs::write(&spec_path, &spec_yaml)?;
74    std::fs::write(&lock_path, &lock_yaml)?;
75
76    if gitignore_targets {
77        let plan = compute_plan(root, &spec, &lock, true, true)?;
78        let update = gitignore_update(root, &managed_gitignore_entries(&plan, None))?;
79        if update.changed {
80            write_gitignore(root, &update.content)?;
81        }
82    }
83
84    Ok(())
85}