agent_cli/
lib.rs

1use std::collections::HashMap;
2use std::fs::File;
3use std::io::Write;
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug, Clone)]
7pub struct Agent {
8    pub id: String,
9    pub name: String,
10    pub skills: Vec<String>,
11    pub config: HashMap<String, String>,
12    pub state: AgentState,
13}
14
15#[derive(Serialize, Deserialize, Debug, Clone)]
16pub enum AgentState {
17    Created,
18    Configured,
19    Running,
20    Suspended,
21    Shutdown,
22}
23
24pub struct AgentCLI {
25    agent: Option<Agent>,
26}
27
28impl AgentCLI {
29    pub fn new() -> Self {
30        AgentCLI { agent: None }
31    }
32
33    pub fn create(&mut self, name: &str) -> Result<(), String> {
34        if self.agent.is_none() {
35            self.agent = Some(Agent {
36                id: format!("agent-{}", rand::random::<u64>()),
37                name: name.to_string(),
38                skills: Vec::new(),
39                config: HashMap::new(),
40                state: AgentState::Created,
41            });
42            Ok(())
43        } else {
44            Err("Agent already exists".to_string())
45        }
46    }
47
48    pub fn add_skill(&mut self, skill: &str) -> Result<(), String> {
49        if let Some(agent) = &mut self.agent {
50            if !agent.skills.contains(&skill.to_string()) {
51                agent.skills.push(skill.to_string());
52                Ok(())
53            } else {
54                Err(format!("Skill '{}' already exists", skill))
55            }
56        } else {
57            Err("No agent exists".to_string())
58        }
59    }
60
61    pub fn configure(&mut self, key: &str, value: &str) -> Result<(), String> {
62        if let Some(agent) = &mut self.agent {
63            agent.config.insert(key.to_string(), value.to_string());
64            agent.state = AgentState::Configured;
65            Ok(())
66        } else {
67            Err("No agent exists".to_string())
68        }
69    }
70
71    pub fn run(&mut self) -> Result<(), String> {
72        if let Some(agent) = &mut self.agent {
73            match agent.state {
74                AgentState::Created | AgentState::Configured | AgentState::Suspended => {
75                    agent.state = AgentState::Running;
76                    Ok(())
77                }
78                AgentState::Running => Err("Agent is already running".to_string()),
79                AgentState::Shutdown => Err("Agent is shutdown".to_string()),
80            }
81        } else {
82            Err("No agent exists".to_string())
83        }
84    }
85
86    pub fn shutdown(&mut self) -> Result<(), String> {
87        if let Some(agent) = &mut self.agent {
88            agent.state = AgentState::Shutdown;
89            let serialized = serde_json::to_string(&agent).map_err(|e| e.to_string())?;
90            let mut file = File::create(format!("{}.json", agent.id)).map_err(|e| e.to_string())?;
91            file.write_all(serialized.as_bytes()).map_err(|e| e.to_string())?;
92            self.agent = None;
93            Ok(())
94        } else {
95            Err("No agent exists".to_string())
96        }
97    }
98
99    pub fn get_agent(&self) -> Option<&Agent> {
100        self.agent.as_ref()
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_create_agent() {
110        let mut cli = AgentCLI::new();
111        assert!(cli.create("test-agent").is_ok());
112        let agent = cli.get_agent().unwrap();
113        assert_eq!(agent.name, "test-agent");
114        assert!(matches!(agent.state, AgentState::Created));
115        assert!(cli.create("another-agent").is_err()); // Should fail: agent exists
116    }
117    #[test]
118    fn test_add_skill() {
119        let mut cli = AgentCLI::new();
120        cli.create("test-agent").unwrap();
121        assert!(cli.add_skill("memory").is_ok());
122        assert!(cli.add_skill("memory").is_err()); // Duplicate skill
123        let agent = cli.get_agent().unwrap();
124        assert_eq!(agent.skills, vec!["memory"]);
125    }
126
127    #[test]
128    fn test_configure() {
129        let mut cli = AgentCLI::new();
130        cli.create("test-agent").unwrap();
131        assert!(cli.configure("goal", "assist user").is_ok());
132        let agent = cli.get_agent().unwrap();
133        assert_eq!(agent.config.get("goal"), Some(&"assist user".to_string()));
134        assert!(matches!(agent.state, AgentState::Configured));
135    }
136    #[test]
137    fn test_run() {
138        let mut cli = AgentCLI::new();
139        cli.create("test-agent").unwrap();
140        assert!(cli.run().is_ok());
141        let agent = cli.get_agent().unwrap();
142        assert!(matches!(agent.state, AgentState::Running));
143        assert!(cli.run().is_err()); // Already running
144    }
145    #[test]
146    fn test_shutdown() {
147        let mut cli = AgentCLI::new();
148        cli.create("test-agent").unwrap();
149        assert!(cli.shutdown().is_ok());
150        let agent = cli.get_agent();
151        assert!(agent.is_none());
152    }
153}
154
155#[cfg(not(test))]
156pub fn main() {
157    // Empty main function
158}