//! Shared in-container filesystem-path resolution. //! //! Every process that runs inside an agent container - the harness plus //! the out-of-process MCP daemons (bash, matrix, ...) - must resolve the //! harness directory layout identically. These helpers live here so the //! resolution exists in exactly one place rather than being mirrored //! across crates. use std::path::PathBuf; /// Base harness directory for the current agent. Uses `HYPERHIVE_HARNESS_DIR` /// if set (injected by the hive-c0re meta flake after the harness/state /// split). For pre-split / dev deployments where it isn't set, falls back to /// a `harness/` sibling of `HYPERHIVE_STATE_DIR`, and finally to /// `/agents/{HIVE_LABEL}/harness` when neither dir env var is present — the /// shape the harness derives from its label alone. #[must_use] pub fn harness_dir() -> PathBuf { if let Some(p) = std::env::var_os("HYPERHIVE_HARNESS_DIR") { return PathBuf::from(p); } if let Some(state) = std::env::var_os("HYPERHIVE_STATE_DIR") { let state_path = PathBuf::from(&state); if let Some(parent) = state_path.parent() { return parent.join("harness"); } } let label = std::env::var("HIVE_LABEL").unwrap_or_default(); PathBuf::from(format!("/agents/{label}/harness")) } /// File name of the pause marker inside the harness dir. Re-exported from /// `hive-priv-sock`, which owns the definition because hive-priv (root) is /// the component that actually creates and unlinks the marker — hive-c0re /// runs unprivileged and cannot write to the agent-owned harness dir — and /// hive-priv deliberately does not depend on this crate. Shared so the /// in-container resolver below, hive-c0re's host-side one (which builds the /// same path from `/var/lib/hyperhive/agents/{name}/harness`) and the /// privileged writer cannot drift apart. pub use hive_priv_sock::PAUSED_MARKER_FILE; /// Marker file whose presence means "this agent is paused": the harness /// keeps serving its web UI and MCP daemons but drives no turns, so /// inbox messages queue up unacked until it's removed. /// /// It lives in the harness dir rather than `state/` because `state/` is /// the agent's own scratch space — this is harness control state. The /// harness dir is bind-mounted from the host, so the marker is the /// single source of truth for both sides: the harness stats it to gate /// the turn loop, and hive-c0re stats it to render the paused /// indicator and creates/removes it for `hivectl pause|resume`. Being a /// plain file, it survives container restarts — pause is sticky by /// construction, and works even when the harness isn't running. #[must_use] pub fn paused_marker() -> PathBuf { harness_dir().join(PAUSED_MARKER_FILE) }