1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5fn epoch() -> DateTime<Utc> {
6 DateTime::UNIX_EPOCH
7}
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum MemoryType {
12 Episodic,
13 Semantic,
14 Procedural,
15 Decision,
16 Architecture,
17 Debugging,
18 Task,
19 Question,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct Memory {
24 pub id: Uuid,
25 pub content: String,
26 pub embedding: Vec<f32>,
27 pub memory_type: MemoryType,
28 pub confidence: f32,
29 pub created_at: DateTime<Utc>,
30 pub last_accessed: DateTime<Utc>,
31 pub access_count: u32,
32 pub source: String,
33 pub source_id: String,
34 #[serde(default)]
35 pub project_path: Option<String>,
36 #[serde(default)]
37 pub machine_id: String,
38 #[serde(default = "epoch")]
39 pub updated_at: DateTime<Utc>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct Entity {
44 pub id: Uuid,
45 pub name: String,
46 pub entity_type: String,
47 pub embedding: Vec<f32>,
48 pub aliases: Vec<String>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct Conversation {
53 pub id: Uuid,
54 pub source: String,
55 pub machine_id: String,
56 pub started_at: DateTime<Utc>,
57 pub project_path: Option<String>,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(rename_all = "snake_case")]
62pub enum RelationType {
63 RelatesTo,
64 Mentions,
65 DerivedFrom,
66 Contradicts,
67 Reinforces,
68 Supersedes,
69 DistilledFrom,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct Relation {
74 pub from_id: Uuid,
75 pub to_id: Uuid,
76 pub relation_type: RelationType,
77 pub strength: f32,
78 pub context: Option<String>,
79}
80
81impl Memory {
82 pub fn new(
83 content: String,
84 memory_type: MemoryType,
85 source: String,
86 source_id: String,
87 ) -> Self {
88 let now = Utc::now();
89 Self {
90 id: Uuid::new_v4(),
91 content,
92 embedding: Vec::new(),
93 memory_type,
94 confidence: 1.0,
95 created_at: now,
96 last_accessed: now,
97 access_count: 0,
98 source,
99 source_id,
100 project_path: None,
101 machine_id: String::new(),
102 updated_at: now,
103 }
104 }
105
106 pub fn with_project_path(mut self, path: Option<String>) -> Self {
107 self.project_path = path;
108 self
109 }
110
111 pub fn with_machine_id(mut self, machine_id: String) -> Self {
112 self.machine_id = machine_id;
113 self
114 }
115
116 pub fn reinforce(&mut self) {
117 self.access_count += 1;
118 self.last_accessed = Utc::now();
119 self.confidence = (self.confidence + 0.1).min(1.0);
120 }
121}
122
123impl Entity {
124 pub fn new(name: String, entity_type: String) -> Self {
125 Self {
126 id: Uuid::new_v4(),
127 name,
128 entity_type,
129 embedding: Vec::new(),
130 aliases: Vec::new(),
131 }
132 }
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
136#[serde(rename_all = "snake_case")]
137pub enum SyncOp {
138 Create,
139 Update,
140 Delete,
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
144#[serde(rename_all = "snake_case")]
145pub enum SyncNodeType {
146 Memory,
147 Entity,
148 Conversation,
149 Relation,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct SyncEntry {
154 pub id: String,
155 pub local_seq: i64,
156 pub origin_machine_id: String,
157 pub origin_seq: i64,
158 pub op: SyncOp,
159 pub node_type: SyncNodeType,
160 pub node_id: String,
161 pub timestamp: DateTime<Utc>,
162 pub data: Option<String>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct SyncState {
167 pub peer_id: String,
168 pub last_seq: u64,
169 pub last_sync_at: DateTime<Utc>,
170}