use anyhow::{Context, Result};
use std::process::Command;
use tracing::{debug, error, info};
pub struct AIChatIntegration;
impl AIChatIntegration {
#[must_use]
pub fn is_available() -> bool {
Command::new("aichat")
.arg("--version")
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
pub async fn execute(prompt: &str, model: Option<&str>) -> Result<String> {
if !Self::is_available() {
return Err(anyhow::anyhow!(
"AIChat is not available. Install with: cargo install aichat"
));
}
info!("Running aichat with prompt: {}", prompt);
debug!("Using model: {:?}", model);
let output = tokio::task::spawn_blocking({
let prompt = prompt.to_owned();
let model = model.map(std::borrow::ToOwned::to_owned);
move || {
let mut cmd = Command::new("aichat");
if let Some(model) = model {
cmd.arg("--model").arg(model);
}
cmd.arg(prompt).output()
}
})
.await?
.context("Failed to execute aichat command")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!("AIChat execution failed: {}", stderr);
return Err(anyhow::anyhow!("AIChat failed: {}", stderr));
}
let stdout = String::from_utf8_lossy(&output.stdout);
info!("AIChat completed successfully");
Ok(stdout.into_owned())
}
pub fn get_version() -> Result<String> {
let output = Command::new("aichat")
.arg("--version")
.output()
.context("Failed to get aichat version")?;
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
} else {
Err(anyhow::anyhow!("Failed to get aichat version"))
}
}
}