1use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct WorldStateSnapshot {
17 pub id: String,
19 pub timestamp: DateTime<Utc>,
21 pub nodes: Vec<StateNode>,
23 pub edges: Vec<StateEdge>,
25 pub layers: HashMap<StateLayer, bool>,
27 #[serde(default)]
29 pub metadata: HashMap<String, Value>,
30}
31
32impl WorldStateSnapshot {
33 pub fn new() -> Self {
35 Self {
36 id: uuid::Uuid::new_v4().to_string(),
37 timestamp: Utc::now(),
38 nodes: Vec::new(),
39 edges: Vec::new(),
40 layers: HashMap::new(),
41 metadata: HashMap::new(),
42 }
43 }
44
45 pub fn nodes_in_layer(&self, layer: &StateLayer) -> Vec<&StateNode> {
47 self.nodes.iter().filter(|node| node.layer == *layer).collect()
48 }
49
50 pub fn edges_for_node(&self, node_id: &str) -> Vec<&StateEdge> {
52 self.edges
53 .iter()
54 .filter(|edge| edge.from == node_id || edge.to == node_id)
55 .collect()
56 }
57
58 pub fn get_node(&self, node_id: &str) -> Option<&StateNode> {
60 self.nodes.iter().find(|node| node.id == node_id)
61 }
62}
63
64impl Default for WorldStateSnapshot {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
75pub struct StateNode {
76 pub id: String,
78 pub label: String,
80 pub node_type: NodeType,
82 pub layer: StateLayer,
84 pub state: Option<String>,
86 #[serde(default)]
88 pub properties: HashMap<String, Value>,
89 pub created_at: DateTime<Utc>,
91 pub updated_at: DateTime<Utc>,
93}
94
95impl StateNode {
96 pub fn new(id: String, label: String, node_type: NodeType, layer: StateLayer) -> Self {
98 let now = Utc::now();
99 Self {
100 id,
101 label,
102 node_type,
103 layer,
104 state: None,
105 properties: HashMap::new(),
106 created_at: now,
107 updated_at: now,
108 }
109 }
110
111 pub fn set_property(&mut self, key: String, value: Value) {
113 self.properties.insert(key, value);
114 self.updated_at = Utc::now();
115 }
116
117 pub fn get_property(&self, key: &str) -> Option<&Value> {
119 self.properties.get(key)
120 }
121
122 pub fn set_state(&mut self, state: String) {
124 self.state = Some(state);
125 self.updated_at = Utc::now();
126 }
127}
128
129#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
131#[serde(rename_all = "snake_case")]
132pub enum NodeType {
133 Persona,
135 Entity,
137 Session,
139 Protocol,
141 Behavior,
143 Schema,
145 Recorded,
147 AiModifier,
149 System,
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
158pub struct StateEdge {
159 pub from: String,
161 pub to: String,
163 pub relationship_type: String,
165 #[serde(default)]
167 pub properties: HashMap<String, Value>,
168 pub created_at: DateTime<Utc>,
170}
171
172impl StateEdge {
173 pub fn new(from: String, to: String, relationship_type: String) -> Self {
175 Self {
176 from,
177 to,
178 relationship_type,
179 properties: HashMap::new(),
180 created_at: Utc::now(),
181 }
182 }
183
184 pub fn set_property(&mut self, key: String, value: Value) {
186 self.properties.insert(key, value);
187 }
188}
189
190#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
194#[serde(rename_all = "snake_case")]
195pub enum StateLayer {
196 Personas,
198 Lifecycle,
200 Reality,
202 Time,
204 Protocols,
206 Behavior,
208 Schemas,
210 Recorded,
212 AiModifiers,
214 System,
216}
217
218impl StateLayer {
219 pub fn all() -> Vec<Self> {
221 vec![
222 Self::Personas,
223 Self::Lifecycle,
224 Self::Reality,
225 Self::Time,
226 Self::Protocols,
227 Self::Behavior,
228 Self::Schemas,
229 Self::Recorded,
230 Self::AiModifiers,
231 Self::System,
232 ]
233 }
234
235 pub fn name(&self) -> &'static str {
237 match self {
238 Self::Personas => "Personas",
239 Self::Lifecycle => "Lifecycle",
240 Self::Reality => "Reality",
241 Self::Time => "Time",
242 Self::Protocols => "Protocols",
243 Self::Behavior => "Behavior",
244 Self::Schemas => "Schemas",
245 Self::Recorded => "Recorded",
246 Self::AiModifiers => "AI Modifiers",
247 Self::System => "System",
248 }
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255
256 #[test]
257 fn test_world_state_snapshot_new() {
258 let snapshot = WorldStateSnapshot::new();
259 assert!(!snapshot.id.is_empty());
260 assert!(snapshot.nodes.is_empty());
261 assert!(snapshot.edges.is_empty());
262 assert!(snapshot.layers.is_empty());
263 assert!(snapshot.metadata.is_empty());
264 }
265
266 #[test]
267 fn test_world_state_snapshot_default() {
268 let snapshot = WorldStateSnapshot::default();
269 assert!(!snapshot.id.is_empty());
270 }
271
272 #[test]
273 fn test_world_state_snapshot_nodes_in_layer() {
274 let mut snapshot = WorldStateSnapshot::new();
275
276 let node1 = StateNode::new(
277 "node1".to_string(),
278 "Persona 1".to_string(),
279 NodeType::Persona,
280 StateLayer::Personas,
281 );
282 let node2 = StateNode::new(
283 "node2".to_string(),
284 "Entity 1".to_string(),
285 NodeType::Entity,
286 StateLayer::Lifecycle,
287 );
288 let node3 = StateNode::new(
289 "node3".to_string(),
290 "Persona 2".to_string(),
291 NodeType::Persona,
292 StateLayer::Personas,
293 );
294
295 snapshot.nodes.push(node1);
296 snapshot.nodes.push(node2);
297 snapshot.nodes.push(node3);
298
299 let persona_nodes = snapshot.nodes_in_layer(&StateLayer::Personas);
300 assert_eq!(persona_nodes.len(), 2);
301
302 let lifecycle_nodes = snapshot.nodes_in_layer(&StateLayer::Lifecycle);
303 assert_eq!(lifecycle_nodes.len(), 1);
304
305 let reality_nodes = snapshot.nodes_in_layer(&StateLayer::Reality);
306 assert!(reality_nodes.is_empty());
307 }
308
309 #[test]
310 fn test_world_state_snapshot_edges_for_node() {
311 let mut snapshot = WorldStateSnapshot::new();
312
313 let edge1 = StateEdge::new("node1".to_string(), "node2".to_string(), "owns".to_string());
314 let edge2 =
315 StateEdge::new("node2".to_string(), "node3".to_string(), "references".to_string());
316 let edge3 =
317 StateEdge::new("node1".to_string(), "node3".to_string(), "relates_to".to_string());
318
319 snapshot.edges.push(edge1);
320 snapshot.edges.push(edge2);
321 snapshot.edges.push(edge3);
322
323 let node1_edges = snapshot.edges_for_node("node1");
324 assert_eq!(node1_edges.len(), 2);
325
326 let node2_edges = snapshot.edges_for_node("node2");
327 assert_eq!(node2_edges.len(), 2);
328
329 let node4_edges = snapshot.edges_for_node("node4");
330 assert!(node4_edges.is_empty());
331 }
332
333 #[test]
334 fn test_world_state_snapshot_get_node() {
335 let mut snapshot = WorldStateSnapshot::new();
336
337 let node = StateNode::new(
338 "test-node".to_string(),
339 "Test Node".to_string(),
340 NodeType::Entity,
341 StateLayer::Lifecycle,
342 );
343 snapshot.nodes.push(node);
344
345 let found = snapshot.get_node("test-node");
346 assert!(found.is_some());
347 assert_eq!(found.unwrap().label, "Test Node");
348
349 let not_found = snapshot.get_node("nonexistent");
350 assert!(not_found.is_none());
351 }
352
353 #[test]
354 fn test_state_node_new() {
355 let node = StateNode::new(
356 "node-123".to_string(),
357 "My Node".to_string(),
358 NodeType::Persona,
359 StateLayer::Personas,
360 );
361
362 assert_eq!(node.id, "node-123");
363 assert_eq!(node.label, "My Node");
364 assert_eq!(node.node_type, NodeType::Persona);
365 assert_eq!(node.layer, StateLayer::Personas);
366 assert!(node.state.is_none());
367 assert!(node.properties.is_empty());
368 }
369
370 #[test]
371 fn test_state_node_set_property() {
372 let mut node = StateNode::new(
373 "node".to_string(),
374 "Node".to_string(),
375 NodeType::Entity,
376 StateLayer::Lifecycle,
377 );
378
379 let original_updated_at = node.updated_at;
380
381 std::thread::sleep(std::time::Duration::from_millis(1));
383
384 node.set_property("key".to_string(), serde_json::json!("value"));
385
386 assert_eq!(node.get_property("key"), Some(&serde_json::json!("value")));
387 assert!(node.updated_at >= original_updated_at);
388 }
389
390 #[test]
391 fn test_state_node_get_property() {
392 let mut node = StateNode::new(
393 "node".to_string(),
394 "Node".to_string(),
395 NodeType::Entity,
396 StateLayer::Lifecycle,
397 );
398
399 assert!(node.get_property("nonexistent").is_none());
400
401 node.set_property("exists".to_string(), serde_json::json!(42));
402 assert_eq!(node.get_property("exists"), Some(&serde_json::json!(42)));
403 }
404
405 #[test]
406 fn test_state_node_set_state() {
407 let mut node = StateNode::new(
408 "node".to_string(),
409 "Node".to_string(),
410 NodeType::Entity,
411 StateLayer::Lifecycle,
412 );
413
414 assert!(node.state.is_none());
415
416 node.set_state("active".to_string());
417 assert_eq!(node.state, Some("active".to_string()));
418 }
419
420 #[test]
421 fn test_node_type_serialize() {
422 let node_type = NodeType::Persona;
423 let json = serde_json::to_string(&node_type).unwrap();
424 assert_eq!(json, "\"persona\"");
425
426 let node_type = NodeType::AiModifier;
427 let json = serde_json::to_string(&node_type).unwrap();
428 assert_eq!(json, "\"ai_modifier\"");
429 }
430
431 #[test]
432 fn test_node_type_deserialize() {
433 let node_type: NodeType = serde_json::from_str("\"persona\"").unwrap();
434 assert_eq!(node_type, NodeType::Persona);
435
436 let node_type: NodeType = serde_json::from_str("\"entity\"").unwrap();
437 assert_eq!(node_type, NodeType::Entity);
438
439 let node_type: NodeType = serde_json::from_str("\"behavior\"").unwrap();
440 assert_eq!(node_type, NodeType::Behavior);
441 }
442
443 #[test]
444 fn test_node_type_all_variants() {
445 let variants = vec![
447 NodeType::Persona,
448 NodeType::Entity,
449 NodeType::Session,
450 NodeType::Protocol,
451 NodeType::Behavior,
452 NodeType::Schema,
453 NodeType::Recorded,
454 NodeType::AiModifier,
455 NodeType::System,
456 ];
457
458 for variant in variants {
459 let json = serde_json::to_string(&variant).unwrap();
460 let deserialized: NodeType = serde_json::from_str(&json).unwrap();
461 assert_eq!(variant, deserialized);
462 }
463 }
464
465 #[test]
466 fn test_state_edge_new() {
467 let edge = StateEdge::new("node1".to_string(), "node2".to_string(), "owns".to_string());
468
469 assert_eq!(edge.from, "node1");
470 assert_eq!(edge.to, "node2");
471 assert_eq!(edge.relationship_type, "owns");
472 assert!(edge.properties.is_empty());
473 }
474
475 #[test]
476 fn test_state_edge_set_property() {
477 let mut edge = StateEdge::new("a".to_string(), "b".to_string(), "relates".to_string());
478
479 edge.set_property("weight".to_string(), serde_json::json!(1.5));
480 assert_eq!(edge.properties.get("weight"), Some(&serde_json::json!(1.5)));
481 }
482
483 #[test]
484 fn test_state_layer_all() {
485 let layers = StateLayer::all();
486 assert_eq!(layers.len(), 10);
487 assert!(layers.contains(&StateLayer::Personas));
488 assert!(layers.contains(&StateLayer::Lifecycle));
489 assert!(layers.contains(&StateLayer::Reality));
490 assert!(layers.contains(&StateLayer::Time));
491 assert!(layers.contains(&StateLayer::Protocols));
492 assert!(layers.contains(&StateLayer::Behavior));
493 assert!(layers.contains(&StateLayer::Schemas));
494 assert!(layers.contains(&StateLayer::Recorded));
495 assert!(layers.contains(&StateLayer::AiModifiers));
496 assert!(layers.contains(&StateLayer::System));
497 }
498
499 #[test]
500 fn test_state_layer_name() {
501 assert_eq!(StateLayer::Personas.name(), "Personas");
502 assert_eq!(StateLayer::Lifecycle.name(), "Lifecycle");
503 assert_eq!(StateLayer::Reality.name(), "Reality");
504 assert_eq!(StateLayer::Time.name(), "Time");
505 assert_eq!(StateLayer::Protocols.name(), "Protocols");
506 assert_eq!(StateLayer::Behavior.name(), "Behavior");
507 assert_eq!(StateLayer::Schemas.name(), "Schemas");
508 assert_eq!(StateLayer::Recorded.name(), "Recorded");
509 assert_eq!(StateLayer::AiModifiers.name(), "AI Modifiers");
510 assert_eq!(StateLayer::System.name(), "System");
511 }
512
513 #[test]
514 fn test_state_layer_serialize() {
515 let layer = StateLayer::Personas;
516 let json = serde_json::to_string(&layer).unwrap();
517 assert_eq!(json, "\"personas\"");
518
519 let layer = StateLayer::AiModifiers;
520 let json = serde_json::to_string(&layer).unwrap();
521 assert_eq!(json, "\"ai_modifiers\"");
522 }
523
524 #[test]
525 fn test_state_layer_deserialize() {
526 let layer: StateLayer = serde_json::from_str("\"personas\"").unwrap();
527 assert_eq!(layer, StateLayer::Personas);
528
529 let layer: StateLayer = serde_json::from_str("\"ai_modifiers\"").unwrap();
530 assert_eq!(layer, StateLayer::AiModifiers);
531 }
532
533 #[test]
534 fn test_state_layer_hash() {
535 use std::collections::HashSet;
536 let mut set = HashSet::new();
537 set.insert(StateLayer::Personas);
538 set.insert(StateLayer::Lifecycle);
539 set.insert(StateLayer::Personas); assert_eq!(set.len(), 2);
541 }
542
543 #[test]
544 fn test_world_state_snapshot_serialize() {
545 let snapshot = WorldStateSnapshot::new();
546 let json = serde_json::to_string(&snapshot).unwrap();
547 assert!(json.contains("\"id\""));
548 assert!(json.contains("\"timestamp\""));
549 assert!(json.contains("\"nodes\""));
550 assert!(json.contains("\"edges\""));
551 }
552
553 #[test]
554 fn test_state_node_clone() {
555 let node = StateNode::new(
556 "node".to_string(),
557 "Node".to_string(),
558 NodeType::Entity,
559 StateLayer::Lifecycle,
560 );
561 let cloned = node.clone();
562 assert_eq!(node.id, cloned.id);
563 assert_eq!(node.label, cloned.label);
564 }
565
566 #[test]
567 fn test_state_edge_clone() {
568 let edge = StateEdge::new("a".to_string(), "b".to_string(), "relates".to_string());
569 let cloned = edge.clone();
570 assert_eq!(edge.from, cloned.from);
571 assert_eq!(edge.to, cloned.to);
572 }
573
574 #[test]
575 fn test_state_layer_ordering() {
576 let mut layers = vec![
578 StateLayer::System,
579 StateLayer::Personas,
580 StateLayer::Lifecycle,
581 ];
582 layers.sort();
583 assert_eq!(layers[0], StateLayer::Personas);
584 }
585}