vv-agent 0.1.3

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};

static SESSION_ID_COUNTER: AtomicU64 = AtomicU64::new(0);

pub(super) fn normalize_session_prompt(prompt: String, label: &str) -> Result<String, String> {
    let prompt = prompt.trim();
    if prompt.is_empty() {
        return Err(format!("{label} cannot be empty"));
    }
    Ok(prompt.to_string())
}

pub(super) fn absolutize_workspace(path: PathBuf) -> PathBuf {
    let path = expand_user_path(path);
    let path = if path.is_absolute() {
        path
    } else {
        std::env::current_dir()
            .map(|current_dir| current_dir.join(&path))
            .unwrap_or(path)
    };
    path.canonicalize().unwrap_or(path)
}

fn expand_user_path(path: PathBuf) -> PathBuf {
    let raw_path = path.to_string_lossy();
    if raw_path == "~" {
        return home_dir().unwrap_or(path);
    }
    if let Some(rest) = raw_path.strip_prefix("~/") {
        if let Some(home) = home_dir() {
            return home.join(rest);
        }
    }
    path
}

fn home_dir() -> Option<PathBuf> {
    std::env::var_os("HOME")
        .map(PathBuf::from)
        .or_else(|| std::env::var_os("USERPROFILE").map(PathBuf::from))
        .or_else(|| {
            let drive = std::env::var_os("HOMEDRIVE")?;
            let path = std::env::var_os("HOMEPATH")?;
            let mut home = PathBuf::from(drive);
            home.push(path);
            Some(home)
        })
}

pub(super) fn generate_session_id() -> String {
    let nanos = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|duration| duration.as_nanos())
        .unwrap_or_default();
    let counter = SESSION_ID_COUNTER.fetch_add(1, Ordering::Relaxed) as u128;
    format!("{:012x}", (nanos ^ counter) & 0xffff_ffff_ffff)
}

pub(super) fn normalize_session_id(session_id: impl Into<String>) -> String {
    let session_id = session_id.into().trim().to_string();
    if session_id.is_empty() {
        generate_session_id()
    } else {
        session_id
    }
}