//! init: generate a local agent-manager.yaml for the current directory, //! based on the detected technology stack or an explicit template //! (issue #52: 'am init --template web|python|rust|cli'). use super::*; use crate::context; use anyhow::{anyhow, Context, Result}; use std::path::{Path, PathBuf}; /// Generate a local config file in dir; refuses to overwrite unless force. /// `template` renders a pre-filled config for a stack ('am init --template'); /// None falls back on the automatic stack detection. Returns the written path. pub fn generate(dir: &Path, force: bool, template: Option<&str>) -> Result { let target = dir.join(crate::config::LOCAL_CONFIG_NAME); if target.exists() && !force { return Err(anyhow!( "{} already exists — use --force to overwrite it", target.display() )); } let project = dir .file_name() .map(|n| n.to_string_lossy().to_string()) .unwrap_or_else(|| "project".to_string()); let dir_str = dir.to_string_lossy().to_string(); let content = if let Some(t) = template { crate::templates::render(t, &project, &dir_str)? } else { let ctx = context::detect(dir); let agents = context::recommended_agents(&ctx.stack); let members = agents .iter() .map(|a| a.to_string()) .collect::>() .join(", "); let stack = if ctx.stack.is_empty() { crate::i18n::tr("aucune détectée").to_string() } else { ctx.stack.join(", ") }; format!( "# Généré par 'am init' le {date} # Pile détectée : {stack} version: \"1.0\" groups: dev: [{members}] agents: [] ", date = crate::installers::now_rfc3339(), ) }; std::fs::write(&target, content) .with_context(|| format!("cannot write {}", target.display()))?; Ok(target) } pub fn run(app: &App, force: bool, template: Option<&str>) -> Result { // 'am init --template list' prints the available templates. if template == Some("list") { println!("available templates:"); for (name, desc) in crate::templates::TEMPLATES { println!(" {name:<8} {desc}"); } return Ok(0); } if app.dry_run() { app.log.dry(format!( "would generate {} in the current directory", crate::config::LOCAL_CONFIG_NAME )); return Ok(0); } let cwd = std::env::current_dir().context("cannot determine the current directory")?; let ctx = context::detect(&cwd); let path = generate(&cwd, force, template)?; match template { Some(t) => app.log.success(&format!( "wrote {} (template: {t})", path.display() )), None => app.log.success(&format!( "wrote {} (stack: {})", path.display(), if ctx.stack.is_empty() { crate::i18n::tr("aucune détectée").to_string() } else { ctx.stack.join(", ") } )), } app.log.info(&format!( "group 'dev' prêt : am start group:dev — ajustez ensuite la config générée" )); Ok(0) }