use std::{collections::HashSet, env, path::PathBuf}; use crate::{Result, collect_files_with_extension}; pub(super) const CODEBUFF_DATA_DIR_ENV: &str = "CODEBUFF_DATA_DIR"; const CHANNELS: &[&str] = &["manicode", "manicode-dev", "manicode-staging"]; pub(super) fn discover_chat_files() -> Result> { let mut files = Vec::new(); for root in codebuff_project_roots()? { collect_files_with_extension(&root, "json", &mut files); } Ok(files .into_iter() .filter(|path| { path.file_name() .is_some_and(|name| name == "chat-messages.json") }) .collect()) } fn codebuff_project_roots() -> Result> { let roots = if let Ok(paths) = env::var(CODEBUFF_DATA_DIR_ENV) { paths .split(',') .map(str::trim) .filter(|path| !path.is_empty()) .map(PathBuf::from) .collect::>() } else { let home = crate::home::home_dir().ok_or_else(|| crate::cli_error("home directory is not set"))?; CHANNELS .iter() .map(|channel| home.join(".config").join(channel)) .collect() }; let mut seen = HashSet::new(); let mut project_roots = Vec::new(); for root in roots { let project_root = if root.file_name().is_some_and(|name| name == "projects") { root } else { root.join("projects") }; if project_root.is_dir() && seen.insert(project_root.clone()) { project_roots.push(project_root); } } Ok(project_roots) }