use anyhow::{Context, Result};
use std::path::Path;
use std::process::Command;
use tracing::{debug, error, info};
pub struct AiderIntegration;
impl AiderIntegration {
#[must_use]
pub fn is_available() -> bool {
Command::new("aider")
.arg("--version")
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
pub async fn execute(project_path: &Path, instructions: &str) -> Result<String> {
if !Self::is_available() {
return Err(anyhow::anyhow!(
"Aider is not available. Install with: pip install aider-chat"
));
}
info!("Running aider in directory: {:?}", project_path);
debug!("Aider instructions: {}", instructions);
let output = tokio::task::spawn_blocking({
let project_path = project_path.to_owned();
let instructions = instructions.to_owned();
move || {
Command::new("aider")
.current_dir(&project_path)
.arg("--message")
.arg(&instructions)
.arg("--yes") .arg("--no-pretty") .output()
}
})
.await?
.context("Failed to execute aider command")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!("Aider execution failed: {}", stderr);
return Err(anyhow::anyhow!("Aider failed: {}", stderr));
}
let stdout = String::from_utf8_lossy(&output.stdout);
info!("Aider completed successfully");
Ok(stdout.into_owned())
}
}