1use crate::context::ContextPacket;
6use crate::evolution::{Genome, LlmParams};
7use crate::merkle::Hash;
8use chrono::{DateTime, Utc};
9use serde::{Deserialize, Serialize};
10use std::sync::Arc;
11use tokio::sync::RwLock;
12use uuid::Uuid;
13
14pub type AgentId = Uuid;
16
17pub type AgentHandle = Arc<RwLock<Agent>>;
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct AgentConfig {
23 pub name: String,
25 pub role: String,
27 pub max_depth: u8,
29 pub spawn_shadow: bool,
31}
32
33impl Default for AgentConfig {
34 fn default() -> Self {
35 Self {
36 name: "Agent".to_string(),
37 role: "General purpose assistant".to_string(),
38 max_depth: 3,
39 spawn_shadow: true,
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct Agent {
47 pub id: AgentId,
49 pub config: AgentConfig,
51 pub generation: u32,
53 pub depth: u8,
55 pub context: ContextPacket,
57 pub merkle_root: Option<Hash>,
59 pub created_at: DateTime<Utc>,
61 #[serde(skip)]
63 pub children: Vec<AgentId>,
64 #[serde(skip)]
66 pub shadow_id: Option<AgentId>,
67 pub parent_id: Option<AgentId>,
69 pub fitness: f64,
71 pub genome: Genome,
73}
74
75impl Agent {
76 pub fn new(config: AgentConfig) -> Self {
78 let genome = Genome::new(&config.role);
80
81 Self {
82 id: Uuid::new_v4(),
83 config,
84 generation: 0,
85 depth: 0,
86 context: ContextPacket::new(""),
87 merkle_root: None,
88 created_at: Utc::now(),
89 children: Vec::new(),
90 shadow_id: None,
91 parent_id: None,
92 fitness: 0.0,
93 genome,
94 }
95 }
96
97 pub fn spawn_child(&self, config: AgentConfig) -> Self {
99 let mut child_genome = self.genome.clone();
101 child_genome.prompt = config.role.clone();
102
103 Self {
104 id: Uuid::new_v4(),
105 config,
106 generation: self.generation + 1,
107 depth: self.depth + 1,
108 context: ContextPacket::new(""),
109 merkle_root: None,
110 created_at: Utc::now(),
111 children: Vec::new(),
112 shadow_id: None,
113 parent_id: Some(self.id),
114 fitness: 0.0,
115 genome: child_genome,
116 }
117 }
118
119 pub fn can_spawn(&self) -> bool {
121 self.depth < self.config.max_depth
122 }
123
124 pub fn is_root(&self) -> bool {
126 self.parent_id.is_none()
127 }
128
129 pub fn llm_params(&self) -> LlmParams {
131 self.genome.to_llm_params()
132 }
133
134 pub fn apply_evolved_genome(&mut self, evolved: Genome) {
136 self.genome = evolved;
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_create_agent() {
146 let agent = Agent::new(AgentConfig::default());
147 assert!(agent.is_root());
148 assert_eq!(agent.generation, 0);
149 assert_eq!(agent.depth, 0);
150 }
151
152 #[test]
153 fn test_spawn_child() {
154 let parent = Agent::new(AgentConfig::default());
155 let child = parent.spawn_child(AgentConfig::default());
156
157 assert!(!child.is_root());
158 assert_eq!(child.generation, 1);
159 assert_eq!(child.depth, 1);
160 assert_eq!(child.parent_id, Some(parent.id));
161 }
162}