Skip to main content

agent_office/domain/
mod.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4pub type NodeId = uuid::Uuid;
5pub type EdgeId = uuid::Uuid;
6pub type Timestamp = chrono::DateTime<chrono::Utc>;
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9#[serde(rename_all = "snake_case")]
10pub enum PropertyValue {
11    String(String),
12    Integer(i64),
13    Float(f64),
14    Boolean(bool),
15    Timestamp(Timestamp),
16    List(Vec<PropertyValue>),
17    Map(HashMap<String, PropertyValue>),
18    Null,
19}
20
21pub type Properties = HashMap<String, PropertyValue>;
22
23impl PropertyValue {
24    pub fn as_str(&self) -> Option<&str> {
25        match self {
26            PropertyValue::String(s) => Some(s.as_str()),
27            _ => None,
28        }
29    }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
33pub struct Node {
34    pub id: NodeId,
35    pub node_type: String,
36    pub properties: Properties,
37    pub created_at: Timestamp,
38    pub updated_at: Timestamp,
39}
40
41impl Node {
42    pub fn new(node_type: impl Into<String>, properties: Properties) -> Self {
43        let now = chrono::Utc::now();
44        Self {
45            id: NodeId::new_v4(),
46            node_type: node_type.into(),
47            properties,
48            created_at: now,
49            updated_at: now,
50        }
51    }
52
53    pub fn with_id(mut self, id: NodeId) -> Self {
54        self.id = id;
55        self
56    }
57
58    pub fn get_property(&self, key: &str) -> Option<&PropertyValue> {
59        self.properties.get(key)
60    }
61
62    pub fn set_property(&mut self, key: impl Into<String>, value: PropertyValue) {
63        self.properties.insert(key.into(), value);
64        self.updated_at = chrono::Utc::now();
65    }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
69pub struct Edge {
70    pub id: EdgeId,
71    pub edge_type: String,
72    pub from_node_id: NodeId,
73    pub to_node_id: NodeId,
74    pub properties: Properties,
75    pub created_at: Timestamp,
76}
77
78impl Edge {
79    pub fn new(
80        edge_type: impl Into<String>,
81        from_node_id: NodeId,
82        to_node_id: NodeId,
83        properties: Properties,
84    ) -> Self {
85        Self {
86            id: EdgeId::new_v4(),
87            edge_type: edge_type.into(),
88            from_node_id,
89            to_node_id,
90            properties,
91            created_at: chrono::Utc::now(),
92        }
93    }
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct GraphQuery {
98    pub node_types: Option<Vec<String>>,
99    pub edge_types: Option<Vec<String>>,
100    pub property_filters: Option<HashMap<String, PropertyValue>>,
101    pub limit: Option<usize>,
102}
103
104impl GraphQuery {
105    pub fn new() -> Self {
106        Self {
107            node_types: None,
108            edge_types: None,
109            property_filters: None,
110            limit: None,
111        }
112    }
113
114    pub fn with_node_type(mut self, node_type: impl Into<String>) -> Self {
115        self.node_types = Some(vec![node_type.into()]);
116        self
117    }
118
119    pub fn with_edge_type(mut self, edge_type: impl Into<String>) -> Self {
120        self.edge_types = Some(vec![edge_type.into()]);
121        self
122    }
123
124    pub fn with_filter(mut self, key: impl Into<String>, value: PropertyValue) -> Self {
125        let mut filters = self.property_filters.unwrap_or_default();
126        filters.insert(key.into(), value);
127        self.property_filters = Some(filters);
128        self
129    }
130
131    pub fn with_limit(mut self, limit: usize) -> Self {
132        self.limit = Some(limit);
133        self
134    }
135}
136
137impl Default for GraphQuery {
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143/// Convert a string ID (like "intern_0") to a deterministic UUID
144/// This allows using string identifiers while maintaining UUID-based storage
145pub fn string_to_node_id(s: &str) -> NodeId {
146    // Use UUID v5 with a custom namespace for our application
147    // The namespace is a fixed UUID: 6ba7b810-9dad-11d1-80b4-00c04fd430c8 (OID namespace)
148    let namespace = uuid::Uuid::from_bytes([
149        0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
150        0xc8,
151    ]);
152    uuid::Uuid::new_v5(&namespace, s.as_bytes())
153}