ubermind_core/
protocol.rs1use crate::types::ServiceStatus;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(tag = "cmd", rename_all = "snake_case")]
6pub enum Request {
7 Start {
8 names: Vec<String>,
9 #[serde(default)]
10 all: bool,
11 #[serde(default)]
12 processes: Vec<String>,
13 },
14 Stop { names: Vec<String> },
15 Reload {
16 names: Vec<String>,
17 #[serde(default)]
18 all: bool,
19 #[serde(default)]
20 processes: Vec<String>,
21 },
22 Restart { service: String, process: String },
23 Kill { service: String, process: String },
24 Status,
25 Logs { service: String, process: Option<String>, follow: bool },
26 Ping,
27 Shutdown,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(tag = "type", rename_all = "snake_case")]
32pub enum Response {
33 Ok { message: Option<String> },
34 Status { services: Vec<ServiceStatus>, http_port: Option<u16> },
35 Log { line: String },
36 Error { message: String },
37 Progress { service: String, message: String },
38 Pong,
39}
40
41pub const SOCKET_NAME: &str = "daemon.sock";
42
43pub fn socket_path() -> std::path::PathBuf {
44 state_dir().join(SOCKET_NAME)
45}
46
47pub fn pid_path() -> std::path::PathBuf {
48 state_dir().join("daemon.pid")
49}
50
51pub fn state_dir() -> std::path::PathBuf {
52 if let Ok(dir) = std::env::var("XDG_STATE_HOME") {
53 std::path::PathBuf::from(dir).join("ubermind")
54 } else if let Some(home) = home_dir() {
55 home.join(".local").join("state").join("ubermind")
56 } else {
57 std::path::PathBuf::from("/tmp/ubermind")
58 }
59}
60
61pub fn config_dir() -> std::path::PathBuf {
62 if let Ok(dir) = std::env::var("XDG_CONFIG_HOME") {
63 std::path::PathBuf::from(dir).join("ubermind")
64 } else if let Some(home) = home_dir() {
65 home.join(".config").join("ubermind")
66 } else {
67 std::path::PathBuf::from("/tmp/ubermind/config")
68 }
69}
70
71fn home_dir() -> Option<std::path::PathBuf> {
72 std::env::var("HOME").ok().map(std::path::PathBuf::from)
73}