hyperhive/hive-ag3nt/src/paths.rs

60 lines
2.5 KiB
Rust

//! Per-agent path resolution for state and credential directories.
//!
//! All agents (including the manager `hm1nd`) use `/agents/{label}/state`.
//! Claude credentials live at `$HOME/.claude` (resolves to
//! `/home/<agent-name>/.claude` because the harness service runs as a
//! non-root unix user matching the agent label — see
//! `docs/persistence.md::First-boot agent-user migration`).
//!
//! Both paths can be overridden via env vars (`HYPERHIVE_STATE_DIR`,
//! `HYPERHIVE_CLAUDE_DIR`) for dev / test scenarios.
use std::path::PathBuf;
/// Durable state directory for the current agent. Reads `HYPERHIVE_STATE_DIR`
/// first (always set by the meta flake to `/agents/{label}/state`); falls back
/// to the same pattern derived from `HIVE_LABEL` for dev/test environments
/// where the env var may not be set.
#[must_use]
pub fn state_dir() -> PathBuf {
if let Some(p) = std::env::var_os("HYPERHIVE_STATE_DIR") {
return PathBuf::from(p);
}
let label = std::env::var("HIVE_LABEL").unwrap_or_default();
PathBuf::from(format!("/agents/{label}/state"))
}
/// Per-turn config dir for the regenerated claude-{mcp-config,settings,
/// system-prompt} files the harness drops before each turn. Set by
/// systemd via `RuntimeDirectory = "hive-config"`: a per-service runtime
/// dir owned by the agent unix user, auto-cleared on stop. Kept separate
/// from `/run/hive` (the host-owned mcp.sock bind) so the harness owns
/// its own write surface and we don't have to chown a bind-mounted dir.
/// Overridable via `HYPERHIVE_CONFIG_DIR` for dev / test scenarios.
#[must_use]
pub fn config_dir() -> PathBuf {
if let Some(p) = std::env::var_os("HYPERHIVE_CONFIG_DIR") {
return PathBuf::from(p);
}
PathBuf::from("/run/hive-config")
}
/// Claude credentials directory for the current agent. `$HOME/.claude`
/// matches what the `claude` CLI reads at runtime — both binaries see
/// the same `$HOME` set by the per-service systemd `environment`
/// declaration (`/home/<agent>`). Falls back to `/root/.claude` for
/// dev / test environments where `HOME` isn't set so the previous
/// root-by-default shape keeps working without env wiring.
/// Overridable via `HYPERHIVE_CLAUDE_DIR` for dev / test scenarios.
#[must_use]
pub fn claude_dir() -> PathBuf {
if let Some(p) = std::env::var_os("HYPERHIVE_CLAUDE_DIR") {
return PathBuf::from(p);
}
if let Some(home) = std::env::var_os("HOME") {
let mut path = PathBuf::from(home);
path.push(".claude");
return path;
}
PathBuf::from("/root/.claude")
}