use std::collections::BTreeMap;
use std::path::{Component, Path};
use serde::{Deserialize, Serialize};
pub(crate) const BUNDLE_VERSION: u32 = 1;
#[derive(Serialize, Deserialize)]
pub(crate) struct Bundle {
pub(crate) version: u32,
pub(crate) files: BTreeMap<String, String>,
}
pub(crate) fn is_tracked_rel_path(rel: &Path) -> bool {
let Some(parts) = plain_components(rel) else {
return false;
};
match parts.as_slice() {
["notifications.toml" | "user_prompt.md"] => true,
["agents", file] => {
Path::new(file).extension() == Some(std::ffi::OsStr::new("toml"))
&& !file.contains(".local.")
}
["routines", middle @ .., file] => is_tracked_routine_file(middle, file),
_ => false,
}
}
fn is_tracked_routine_file(middle: &[&str], file: &str) -> bool {
match file {
"routine.toml" | "schedule.cron" | "disabled.json" => !middle.is_empty(),
"prompt.pure.md" => middle.len() >= 2 && middle.last() == Some(&"prompts"),
_ => false,
}
}
fn plain_components(rel: &Path) -> Option<Vec<&str>> {
rel.components()
.map(|component| match component {
Component::Normal(part) => part.to_str(),
_ => None,
})
.collect()
}
#[cfg(test)]
#[path = "bundle_tests.rs"]
mod bundle_tests;