netsky-core 0.1.7

netsky core: agent model, prompt loader, spawner, config
Documentation
//! Agent identity model.

use std::fmt;

use crate::consts::{AGENT0_NAME, AGENTINFINITY_NAME, CLONE_PREFIX};

/// Identifies an agent in the netsky system.
///
/// Invariants (enforced by constructors):
/// - `Clone(n)` has `n > 0`. `n == 0` is [`AgentId::Agent0`].
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum AgentId {
    /// Root orchestrator.
    Agent0,
    /// Clone `agent<N>` where `N > 0`.
    Clone(u32),
    /// Watchdog.
    Agentinfinity,
}

impl AgentId {
    /// Parse a numeric input: `0 -> Agent0`, `N > 0 -> Clone(N)`.
    pub fn from_number(n: u32) -> Self {
        if n == 0 { Self::Agent0 } else { Self::Clone(n) }
    }

    /// Canonical session + id string: `agent0`, `agent5`, `agentinfinity`.
    pub fn name(&self) -> String {
        match self {
            Self::Agent0 => AGENT0_NAME.to_string(),
            Self::Clone(n) => format!("{CLONE_PREFIX}{n}"),
            Self::Agentinfinity => AGENTINFINITY_NAME.to_string(),
        }
    }

    /// The `AGENT_N` env var value for this agent.
    /// Agent0 = `"0"`, Clone(N) = `"N"`, Agentinfinity = `"infinity"`.
    pub fn env_n(&self) -> String {
        match self {
            Self::Agent0 => "0".to_string(),
            Self::Clone(n) => n.to_string(),
            Self::Agentinfinity => "infinity".to_string(),
        }
    }

    /// Is this the root orchestrator?
    pub fn is_agent0(&self) -> bool {
        matches!(self, Self::Agent0)
    }

    /// Is this the watchdog?
    pub fn is_agentinfinity(&self) -> bool {
        matches!(self, Self::Agentinfinity)
    }
}

impl fmt::Display for AgentId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.name())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn name_roundtrip() {
        assert_eq!(AgentId::Agent0.name(), "agent0");
        assert_eq!(AgentId::Clone(5).name(), "agent5");
        assert_eq!(AgentId::Agentinfinity.name(), "agentinfinity");
    }

    #[test]
    fn from_number_zero_is_agent0() {
        assert_eq!(AgentId::from_number(0), AgentId::Agent0);
        assert_eq!(AgentId::from_number(3), AgentId::Clone(3));
    }

    #[test]
    fn env_n_strings() {
        assert_eq!(AgentId::Agent0.env_n(), "0");
        assert_eq!(AgentId::Clone(7).env_n(), "7");
        assert_eq!(AgentId::Agentinfinity.env_n(), "infinity");
    }
}