rusty-beads 0.1.0

Git-backed graph issue tracker for AI coding agents - a Rust implementation with context store, dependency tracking, and semantic compaction
Documentation
//! Agent-related type definitions.

use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;

/// Self-reported state of an agent.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum AgentState {
    /// Agent is not currently working.
    #[default]
    Idle,
    /// Agent is starting up.
    Spawning,
    /// Agent is running but not on a specific task.
    Running,
    /// Agent is actively working on a task.
    Working,
    /// Agent is stuck and needs help.
    Stuck,
    /// Agent has completed its work.
    Done,
    /// Agent has been stopped.
    Stopped,
    /// Agent has crashed or is unreachable.
    Dead,
}

impl AgentState {
    /// Returns the string representation for database storage.
    pub fn as_str(&self) -> &'static str {
        match self {
            AgentState::Idle => "idle",
            AgentState::Spawning => "spawning",
            AgentState::Running => "running",
            AgentState::Working => "working",
            AgentState::Stuck => "stuck",
            AgentState::Done => "done",
            AgentState::Stopped => "stopped",
            AgentState::Dead => "dead",
        }
    }

    /// Returns true if the agent is in an active state.
    pub fn is_active(&self) -> bool {
        matches!(
            self,
            AgentState::Spawning | AgentState::Running | AgentState::Working
        )
    }

    /// Returns true if the agent is in a terminal state.
    pub fn is_terminal(&self) -> bool {
        matches!(self, AgentState::Done | AgentState::Stopped | AgentState::Dead)
    }
}

impl fmt::Display for AgentState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl FromStr for AgentState {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "idle" => Ok(AgentState::Idle),
            "spawning" => Ok(AgentState::Spawning),
            "running" => Ok(AgentState::Running),
            "working" => Ok(AgentState::Working),
            "stuck" => Ok(AgentState::Stuck),
            "done" => Ok(AgentState::Done),
            "stopped" => Ok(AgentState::Stopped),
            "dead" => Ok(AgentState::Dead),
            _ => Err(format!("unknown agent state: {}", s)),
        }
    }
}

/// The type of molecule (coordinated work).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum MolType {
    /// Coordinated multi-agent operations.
    Swarm,
    /// Recurring work (witness/deacon roles).
    Patrol,
    /// Standard work (default).
    #[default]
    Work,
}

impl MolType {
    /// Returns the string representation for database storage.
    pub fn as_str(&self) -> &'static str {
        match self {
            MolType::Swarm => "swarm",
            MolType::Patrol => "patrol",
            MolType::Work => "work",
        }
    }
}

impl fmt::Display for MolType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl FromStr for MolType {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "swarm" => Ok(MolType::Swarm),
            "patrol" => Ok(MolType::Patrol),
            "work" => Ok(MolType::Work),
            _ => Err(format!("unknown molecule type: {}", s)),
        }
    }
}