Skip to main content

netsky_core/
agent.rs

1//! Agent identity model.
2
3use std::fmt;
4
5use crate::consts::{AGENT0_NAME, AGENTINFINITY_NAME, CLONE_PREFIX};
6
7/// Identifies an agent in the netsky system.
8///
9/// Invariants (enforced by constructors):
10/// - `Clone(n)` has `n > 0`. `n == 0` is [`AgentId::Agent0`].
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12pub enum AgentId {
13    /// Root orchestrator.
14    Agent0,
15    /// Clone `agent<N>` where `N > 0`.
16    Clone(u32),
17    /// Watchdog.
18    Agentinfinity,
19}
20
21impl AgentId {
22    /// Parse a numeric input: `0 -> Agent0`, `N > 0 -> Clone(N)`.
23    pub fn from_number(n: u32) -> Self {
24        if n == 0 { Self::Agent0 } else { Self::Clone(n) }
25    }
26
27    /// Canonical session + id string: `agent0`, `agent5`, `agentinfinity`.
28    pub fn name(&self) -> String {
29        match self {
30            Self::Agent0 => AGENT0_NAME.to_string(),
31            Self::Clone(n) => format!("{CLONE_PREFIX}{n}"),
32            Self::Agentinfinity => AGENTINFINITY_NAME.to_string(),
33        }
34    }
35
36    /// The `AGENT_N` env var value for this agent.
37    /// Agent0 = `"0"`, Clone(N) = `"N"`, Agentinfinity = `"infinity"`.
38    pub fn env_n(&self) -> String {
39        match self {
40            Self::Agent0 => "0".to_string(),
41            Self::Clone(n) => n.to_string(),
42            Self::Agentinfinity => "infinity".to_string(),
43        }
44    }
45
46    /// Is this the root orchestrator?
47    pub fn is_agent0(&self) -> bool {
48        matches!(self, Self::Agent0)
49    }
50
51    /// Is this the watchdog?
52    pub fn is_agentinfinity(&self) -> bool {
53        matches!(self, Self::Agentinfinity)
54    }
55}
56
57impl fmt::Display for AgentId {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        f.write_str(&self.name())
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn name_roundtrip() {
69        assert_eq!(AgentId::Agent0.name(), "agent0");
70        assert_eq!(AgentId::Clone(5).name(), "agent5");
71        assert_eq!(AgentId::Agentinfinity.name(), "agentinfinity");
72    }
73
74    #[test]
75    fn from_number_zero_is_agent0() {
76        assert_eq!(AgentId::from_number(0), AgentId::Agent0);
77        assert_eq!(AgentId::from_number(3), AgentId::Clone(3));
78    }
79
80    #[test]
81    fn env_n_strings() {
82        assert_eq!(AgentId::Agent0.env_n(), "0");
83        assert_eq!(AgentId::Clone(7).env_n(), "7");
84        assert_eq!(AgentId::Agentinfinity.env_n(), "infinity");
85    }
86}