use std::env;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
#[derive(Debug, Clone)]
pub struct BeamPaths {
root: PathBuf,
}
impl BeamPaths {
pub fn from_root(root: impl Into<PathBuf>) -> Self {
Self { root: root.into() }
}
pub fn discover() -> Result<Self> {
if let Ok(root) = env::var("BEAM_HOME") {
return Ok(Self::from_root(root));
}
let home =
env::var("HOME").context("HOME is not set and BEAM_HOME was not provided")?;
Ok(Self::from_root(Path::new(&home).join(".beam")))
}
pub fn root(&self) -> &Path {
&self.root
}
pub fn run_dir(&self) -> PathBuf {
self.root.join("run")
}
pub fn logs_dir(&self) -> PathBuf {
self.root.join("logs")
}
pub fn state_dir(&self) -> PathBuf {
self.root.join("state")
}
pub fn sessions_dir(&self) -> PathBuf {
self.root.join("sessions")
}
pub fn workflows_dir(&self) -> PathBuf {
self.root.join("workflows")
}
pub fn workflow_runs_dir(&self) -> PathBuf {
self.workflows_dir().join("runs")
}
pub fn workflow_run_dir(&self, run_id: &str) -> PathBuf {
self.workflow_runs_dir().join(run_id)
}
pub fn config_toml(&self) -> PathBuf {
self.root.join("config.toml")
}
pub fn bots_json(&self) -> PathBuf {
self.root.join("bots.json")
}
pub fn connectors_json(&self) -> PathBuf {
self.root.join("connectors.json")
}
pub fn webhook_master_key(&self) -> PathBuf {
self.root.join("webhook-master.key")
}
pub fn webhook_secrets_json(&self) -> PathBuf {
self.root.join("webhook-secrets.json")
}
pub fn trigger_logs_jsonl(&self) -> PathBuf {
self.root.join("trigger-logs.jsonl")
}
pub fn schedules_json(&self) -> PathBuf {
self.root.join("schedules.json")
}
pub fn observed_bots_dir(&self) -> PathBuf {
self.root.join("observed-bots")
}
pub fn webhook_triggers_json(&self) -> PathBuf {
self.root.join("webhook-triggers.json")
}
pub fn webhook_lifecycle_json(&self) -> PathBuf {
self.root.join("webhook-lifecycle.json")
}
pub fn schedules_output_dir(&self) -> PathBuf {
self.root.join("schedules-output")
}
pub fn runtime_state_json(&self) -> PathBuf {
self.run_dir().join("daemon.json")
}
pub fn daemon_log(&self) -> PathBuf {
self.logs_dir().join("daemon.log")
}
pub fn session_store_json(&self) -> PathBuf {
self.sessions_dir().join("sessions.json")
}
pub fn frozen_cards_dir(&self) -> PathBuf {
self.sessions_dir().join("frozen-cards")
}
pub fn frozen_cards_json(&self, session_id: &str) -> PathBuf {
self.frozen_cards_dir().join(format!("{}.json", session_id))
}
pub fn pending_response_patches_dir(&self) -> PathBuf {
self.sessions_dir().join("pending-response-patches")
}
pub fn pending_response_patch_json(&self, session_id: &str) -> PathBuf {
self.pending_response_patches_dir()
.join(format!("{}.json", session_id))
}
pub fn workflow_approval_cards_dir(&self) -> PathBuf {
self.sessions_dir().join("workflow-approval-cards")
}
pub fn workflow_approval_cards_json(&self, run_id: &str) -> PathBuf {
self.workflow_approval_cards_dir()
.join(format!("{}.json", run_id))
}
pub fn attempt_resume_dir(&self, run_id: &str, activity_id: &str, attempt_id: &str) -> PathBuf {
self.workflow_run_dir(run_id)
.join("attempts")
.join(activity_id)
.join(attempt_id)
.join("resumes")
}
pub fn attempt_resume_json(
&self,
run_id: &str,
activity_id: &str,
attempt_id: &str,
resume_id: &str,
) -> PathBuf {
self.attempt_resume_dir(run_id, activity_id, attempt_id)
.join(resume_id)
.join("resume.json")
}
pub fn worker_init_json(&self, session_id: &str) -> PathBuf {
self.run_dir()
.join(format!("worker-init-{}.json", session_id))
}
pub fn worker_wrapper_sh(&self, session_id: &str) -> PathBuf {
self.run_dir()
.join(format!("worker-wrapper-{}.sh", session_id))
}
pub fn cli_pid_markers_dir(&self) -> PathBuf {
self.state_dir().join(".beam-cli-pids")
}
}