use std::fs;
use std::path::PathBuf;
pub fn project_hash() -> String {
let cwd = std::env::current_dir()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default();
let mut h: u64 = 0xcbf29ce484222325;
for b in cwd.as_bytes() {
h ^= *b as u64;
h = h.wrapping_mul(0x100000001b3);
}
format!("{:016x}", h)
}
pub fn session_file_path() -> PathBuf {
PathBuf::from(format!("/tmp/hiboss-session-{}", project_hash()))
}
pub fn ttl_file_path() -> PathBuf {
PathBuf::from(format!("/tmp/hiboss-urgent-check-{}", project_hash()))
}
pub fn a2a_ttl_file_path() -> PathBuf {
PathBuf::from(format!("/tmp/hiboss-a2a-check-{}", project_hash()))
}
pub fn daemon_pid_path() -> PathBuf {
PathBuf::from(format!("/tmp/hiboss-daemon-{}.pid", project_hash()))
}
pub fn daemon_pending_path() -> PathBuf {
PathBuf::from(format!("/tmp/hiboss-daemon-{}.pending", project_hash()))
}
pub fn is_daemon_running() -> Option<u32> {
let pid_str = fs::read_to_string(daemon_pid_path()).ok()?;
let pid: u32 = pid_str.trim().parse().ok()?;
let status = std::process::Command::new("kill")
.args(["-0", &pid.to_string()])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.ok()?;
if status.success() { Some(pid) } else { None }
}
pub fn drain_pending_messages() -> Vec<String> {
let path = daemon_pending_path();
let tmp = path.with_extension("draining");
if fs::rename(&path, &tmp).is_err() {
return vec![];
}
let content = fs::read_to_string(&tmp).unwrap_or_default();
let _ = fs::remove_file(&tmp);
content.lines().filter(|l| !l.is_empty()).map(|l| l.to_owned()).collect()
}
pub fn read_session_id() -> Option<String> {
let path = session_file_path();
fs::read_to_string(path)
.ok()
.map(|s| s.trim().to_owned())
.filter(|s| !s.is_empty())
}
pub fn write_session_id(id: &str) -> Result<(), std::io::Error> {
fs::write(session_file_path(), id)
}