use std::io::IsTerminal;
use anyhow::Result;
use crate::{blobstore::BlobStore, config::Config, diff, llm, snapshot, storage};
fn use_color() -> bool {
if std::env::var_os("NO_COLOR").is_some() {
return false;
}
std::io::stdout().is_terminal()
}
fn colorize(text: &str, ansi_code: &str, colored: bool) -> String {
if colored {
format!("\x1b[{ansi_code}m{text}\x1b[0m")
} else {
text.to_string()
}
}
pub fn run(once: bool, interval: Option<u64>, no_llm: bool, cfg: &Config) -> Result<()> {
let secs = interval.unwrap_or(cfg.daemon.interval_seconds);
let paths = storage::StoragePaths::new();
let blob_store = BlobStore::new(&paths.objects);
let colored = use_color();
loop {
let snap = snapshot::take_snapshot(
&cfg.watch.roots,
&cfg.filter.include,
&cfg.filter.exclude,
Some(&blob_store),
)?;
let count = snap.files.len();
let saved = storage::save_snapshot(&snap)?;
println!(
"[{}] snapshot {} — {} files → {}",
snap.created_at,
snap.snapshot_id,
count,
saved.display()
);
let all = storage::list_snapshots()?;
if all.len() >= 2 {
let prev = storage::load_snapshot(&all[all.len() - 2])?;
let mut event = diff::compute_diff(&prev, &snap);
diff::enrich_with_diffs(&mut event, &blob_store);
if !event.changes.is_empty() {
storage::save_diff(&event)?;
println!(" {} changes:", event.changes.len());
for c in &event.changes {
let (sym, ansi) = match c.change_type {
diff::ChangeType::Added => ("+", "32"),
diff::ChangeType::Removed => ("-", "31"),
diff::ChangeType::Modified => ("~", "33"),
diff::ChangeType::Renamed => ("→", "2"),
};
println!(" {} {}", colorize(sym, ansi, colored), c.path);
}
if cfg.llm.enabled && !no_llm {
match llm::summarize_diff(&event, &cfg.llm) {
Ok(summary) => {
event.summary = Some(summary);
if let Err(e) = storage::save_diff(&event) {
eprintln!("warning: could not re-save diff with summary: {e}");
}
}
Err(e) => {
eprintln!(
"warning: LLM summarization failed (diff persisted without summary): {e}"
);
}
}
}
} else {
println!(" no changes.");
}
}
if once {
break;
}
println!("sleeping {}s…", secs);
std::thread::sleep(std::time::Duration::from_secs(secs));
}
Ok(())
}