Skip to main content

hyper_agent_runtime/
daemon.rs

1use std::path::PathBuf;
2
3pub const DEFAULT_PORT: u16 = 3847;
4pub const VERSION: &str = env!("CARGO_PKG_VERSION");
5
6pub fn daemon_dir() -> PathBuf {
7    dirs::home_dir()
8        .unwrap_or_else(|| PathBuf::from("."))
9        .join(".hyper-agent")
10}
11
12pub fn pid_file() -> PathBuf {
13    daemon_dir().join("daemon.pid")
14}
15pub fn port_file() -> PathBuf {
16    daemon_dir().join("daemon.port")
17}
18pub fn token_file() -> PathBuf {
19    daemon_dir().join("daemon.token")
20}
21pub fn log_dir() -> PathBuf {
22    daemon_dir().join("logs")
23}
24pub fn config_file() -> PathBuf {
25    daemon_dir().join("config.toml")
26}
27pub fn db_file() -> PathBuf {
28    daemon_dir().join("positions.db")
29}
30pub fn history_db_file() -> PathBuf {
31    daemon_dir().join("agent_history.db")
32}
33pub fn equity_db_file() -> PathBuf {
34    daemon_dir().join("equity.db")
35}
36pub fn adjustment_db_file() -> PathBuf {
37    daemon_dir().join("adjustments.db")
38}
39
40pub fn is_running() -> bool {
41    if let Ok(pid_str) = std::fs::read_to_string(pid_file()) {
42        if let Ok(pid) = pid_str.trim().parse::<i32>() {
43            unsafe { libc::kill(pid, 0) == 0 }
44        } else {
45            false
46        }
47    } else {
48        false
49    }
50}
51
52pub fn read_port() -> Option<u16> {
53    std::fs::read_to_string(port_file())
54        .ok()
55        .and_then(|s| s.trim().parse().ok())
56}
57
58pub fn read_token() -> Option<String> {
59    std::fs::read_to_string(token_file())
60        .ok()
61        .map(|s| s.trim().to_string())
62}
63
64pub fn write_pid_port(port: u16) {
65    let dir = daemon_dir();
66    std::fs::create_dir_all(&dir).ok();
67    std::fs::write(pid_file(), std::process::id().to_string()).ok();
68    std::fs::write(port_file(), port.to_string()).ok();
69}
70
71/// Write only the PID file (used for ordered startup: PID → token → port).
72pub fn write_pid() {
73    let dir = daemon_dir();
74    std::fs::create_dir_all(&dir).ok();
75    std::fs::write(pid_file(), std::process::id().to_string()).ok();
76}
77
78/// Write only the port file. Must be called LAST during startup,
79/// because `from_port_file()` uses the port file as the discovery trigger.
80pub fn write_port(port: u16) {
81    std::fs::write(port_file(), port.to_string()).ok();
82}
83
84pub fn write_token(token: &str) {
85    std::fs::write(token_file(), token).ok();
86    // Set 0600 permissions (owner-only)
87    #[cfg(unix)]
88    {
89        use std::os::unix::fs::PermissionsExt;
90        std::fs::set_permissions(token_file(), std::fs::Permissions::from_mode(0o600)).ok();
91    }
92}
93
94pub fn cleanup() {
95    std::fs::remove_file(pid_file()).ok();
96    std::fs::remove_file(port_file()).ok();
97    std::fs::remove_file(token_file()).ok();
98}