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()); }
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()); 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()); }
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 }