use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
fn epoch() -> DateTime<Utc> {
DateTime::UNIX_EPOCH
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MemoryType {
Episodic,
Semantic,
Procedural,
Decision,
Architecture,
Debugging,
Task,
Question,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Memory {
pub id: Uuid,
pub content: String,
pub embedding: Vec<f32>,
pub memory_type: MemoryType,
pub confidence: f32,
pub created_at: DateTime<Utc>,
pub last_accessed: DateTime<Utc>,
pub access_count: u32,
pub source: String,
pub source_id: String,
#[serde(default)]
pub project_path: Option<String>,
#[serde(default)]
pub machine_id: String,
#[serde(default = "epoch")]
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entity {
pub id: Uuid,
pub name: String,
pub entity_type: String,
pub embedding: Vec<f32>,
pub aliases: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Conversation {
pub id: Uuid,
pub source: String,
pub machine_id: String,
pub started_at: DateTime<Utc>,
pub project_path: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RelationType {
RelatesTo,
Mentions,
DerivedFrom,
Contradicts,
Reinforces,
Supersedes,
DistilledFrom,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Relation {
pub from_id: Uuid,
pub to_id: Uuid,
pub relation_type: RelationType,
pub strength: f32,
pub context: Option<String>,
}
impl Memory {
pub fn new(
content: String,
memory_type: MemoryType,
source: String,
source_id: String,
) -> Self {
let now = Utc::now();
Self {
id: Uuid::new_v4(),
content,
embedding: Vec::new(),
memory_type,
confidence: 1.0,
created_at: now,
last_accessed: now,
access_count: 0,
source,
source_id,
project_path: None,
machine_id: String::new(),
updated_at: now,
}
}
pub fn with_project_path(mut self, path: Option<String>) -> Self {
self.project_path = path;
self
}
pub fn with_machine_id(mut self, machine_id: String) -> Self {
self.machine_id = machine_id;
self
}
pub fn reinforce(&mut self) {
self.access_count += 1;
self.last_accessed = Utc::now();
self.confidence = (self.confidence + 0.1).min(1.0);
}
}
impl Entity {
pub fn new(name: String, entity_type: String) -> Self {
Self {
id: Uuid::new_v4(),
name,
entity_type,
embedding: Vec::new(),
aliases: Vec::new(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SyncOp {
Create,
Update,
Delete,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SyncNodeType {
Memory,
Entity,
Conversation,
Relation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncEntry {
pub id: String,
pub local_seq: i64,
pub origin_machine_id: String,
pub origin_seq: i64,
pub op: SyncOp,
pub node_type: SyncNodeType,
pub node_id: String,
pub timestamp: DateTime<Utc>,
pub data: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncState {
pub peer_id: String,
pub last_seq: u64,
pub last_sync_at: DateTime<Utc>,
}