pub mod amp;
pub mod antigravity;
pub mod campfire;
pub mod claude_code;
pub mod codex;
pub mod cursor;
pub mod cursor_desktop;
pub mod grok;
pub mod opencode;
pub mod pi;
pub(crate) mod jsonl;
pub(crate) fn checked_id_component(harness: &'static str, id: &str) -> crate::Result<()> {
let ok = !id.is_empty()
&& id != "."
&& id != ".."
&& !id.contains(['/', '\\', ':'])
&& !id.chars().any(char::is_control);
if ok {
Ok(())
} else {
Err(crate::Error::Malformed {
harness,
detail: format!(
"session id `{}` is not usable as a file name",
id.escape_debug()
),
})
}
}
pub(crate) fn home_dir() -> Option<std::path::PathBuf> {
#[cfg(windows)]
let home = std::env::var_os("USERPROFILE")
.filter(|v| !v.is_empty())
.or_else(|| std::env::var_os("HOME"));
#[cfg(not(windows))]
let home = std::env::var_os("HOME");
home.filter(|v| !v.is_empty()).map(std::path::PathBuf::from)
}