52 lines
1.7 KiB
Rust
52 lines
1.7 KiB
Rust
//! Login-state probe for the bind-mounted `~/.claude/` dir. The dir is
|
|
//! provided by hive-c0re (Phase 8 step 1) and persists across container
|
|
//! destroy/recreate so OAuth tokens survive.
|
|
//!
|
|
//! "Has session" today means "the dir contains at least one regular file."
|
|
//! That's a heuristic: a fresh bind-mount starts empty, and `claude auth login`
|
|
//! writes credentials into the dir. We may refine later (probe for the
|
|
//! specific credentials filename, or run a no-op `claude` call) once the
|
|
//! exact layout is locked in.
|
|
|
|
use std::path::Path;
|
|
|
|
/// Mount point of the per-agent Claude credentials dir inside the container.
|
|
/// Matches `hive_c0re::lifecycle::CONTAINER_CLAUDE_MOUNT`.
|
|
pub const DEFAULT_CLAUDE_DIR: &str = "/root/.claude";
|
|
|
|
/// Returns `true` if `dir` exists and contains any regular file. Used at
|
|
/// startup to decide whether to enter the turn loop (logged in) or stay in
|
|
/// the partial-run "needs login" state.
|
|
#[must_use]
|
|
pub fn has_session(dir: &Path) -> bool {
|
|
let Ok(entries) = std::fs::read_dir(dir) else {
|
|
return false;
|
|
};
|
|
for entry in entries.flatten() {
|
|
if entry.file_type().is_ok_and(|t| t.is_file()) {
|
|
return true;
|
|
}
|
|
}
|
|
false
|
|
}
|
|
|
|
/// Login state the harness reports to its web UI.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum LoginState {
|
|
/// `~/.claude/` has credentials; turn loop is running.
|
|
Online,
|
|
/// `~/.claude/` is empty; harness is up, web UI is bound, turn loop is NOT
|
|
/// running. Operator needs to complete login from the web UI.
|
|
NeedsLogin,
|
|
}
|
|
|
|
impl LoginState {
|
|
#[must_use]
|
|
pub fn from_dir(dir: &Path) -> Self {
|
|
if has_session(dir) {
|
|
Self::Online
|
|
} else {
|
|
Self::NeedsLogin
|
|
}
|
|
}
|
|
}
|