Skip to main content

oxios_kernel/
types.rs

1//! Core types for the Oxios kernel.
2//!
3//! Defines agent identity, status, and metadata.
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8/// Unique identifier for an agent instance.
9pub type AgentId = uuid::Uuid;
10
11/// Current status of an agent instance.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13pub enum AgentStatus {
14    /// Agent is being initialized.
15    Starting,
16    /// Agent is actively executing tasks.
17    Running,
18    /// Agent is alive but not currently working.
19    Idle,
20    /// Agent has been stopped.
21    Stopped,
22    /// Agent has encountered an error.
23    Failed,
24}
25
26impl std::fmt::Display for AgentStatus {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            AgentStatus::Starting => write!(f, "starting"),
30            AgentStatus::Running => write!(f, "running"),
31            AgentStatus::Idle => write!(f, "idle"),
32            AgentStatus::Stopped => write!(f, "stopped"),
33            AgentStatus::Failed => write!(f, "failed"),
34        }
35    }
36}
37
38/// Metadata about an agent instance.
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct AgentInfo {
41    /// Unique identifier for this agent.
42    pub id: AgentId,
43    /// Human-readable name of the agent.
44    pub name: String,
45    /// Current status of the agent.
46    pub status: AgentStatus,
47    /// Timestamp when the agent was created.
48    pub created_at: DateTime<Utc>,
49    /// The seed this agent was forked from, if any.
50    pub seed_id: Option<uuid::Uuid>,
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_agent_status_display_all_variants() {
59        assert_eq!(AgentStatus::Starting.to_string(), "starting");
60        assert_eq!(AgentStatus::Running.to_string(), "running");
61        assert_eq!(AgentStatus::Idle.to_string(), "idle");
62        assert_eq!(AgentStatus::Stopped.to_string(), "stopped");
63        assert_eq!(AgentStatus::Failed.to_string(), "failed");
64    }
65
66    #[test]
67    fn test_agent_status_equality() {
68        assert_eq!(AgentStatus::Running, AgentStatus::Running);
69        assert_ne!(AgentStatus::Running, AgentStatus::Idle);
70    }
71
72    #[test]
73    fn test_agent_status_serialization_roundtrip() {
74        for status in [
75            AgentStatus::Starting,
76            AgentStatus::Running,
77            AgentStatus::Idle,
78            AgentStatus::Stopped,
79            AgentStatus::Failed,
80        ] {
81            let json = serde_json::to_string(&status).unwrap();
82            let restored: AgentStatus = serde_json::from_str(&json).unwrap();
83            assert_eq!(status, restored);
84        }
85    }
86
87    #[test]
88    fn test_agent_info_construction() {
89        let id = AgentId::new_v4();
90        let seed_id = uuid::Uuid::new_v4();
91        let now = Utc::now();
92
93        let info = AgentInfo {
94            id,
95            name: "test-agent".to_string(),
96            status: AgentStatus::Running,
97            created_at: now,
98            seed_id: Some(seed_id),
99        };
100
101        assert_eq!(info.id, id);
102        assert_eq!(info.name, "test-agent");
103        assert_eq!(info.status, AgentStatus::Running);
104        assert_eq!(info.created_at, now);
105        assert_eq!(info.seed_id, Some(seed_id));
106    }
107
108    #[test]
109    fn test_agent_info_serialization_roundtrip() {
110        let info = AgentInfo {
111            id: AgentId::new_v4(),
112            name: "serializer".to_string(),
113            status: AgentStatus::Idle,
114            created_at: Utc::now(),
115            seed_id: None,
116        };
117
118        let json = serde_json::to_string(&info).unwrap();
119        let restored: AgentInfo = serde_json::from_str(&json).unwrap();
120        assert_eq!(restored.id, info.id);
121        assert_eq!(restored.name, info.name);
122        assert_eq!(restored.status, info.status);
123        assert_eq!(restored.seed_id, None);
124    }
125
126    #[test]
127    fn test_agent_status_copy() {
128        let status = AgentStatus::Running;
129        let copied = status; // Copy semantics
130        assert_eq!(status, copied); // status is still valid because Copy
131    }
132}