neomemx 0.1.2

A high-performance memory library for AI agents with semantic search
Documentation
//! Change tracking and history

use crate::core::scope::ScopeIdentifiers;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

/// Type of modification to a fact
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChangeType {
    /// Fact was created
    Created,
    /// Fact was updated
    Updated,
    /// Fact was deleted
    Deleted,
    /// Fact was consolidated with another
    Consolidated,
}

impl ChangeType {
    /// Convert to string representation
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Created => "created",
            Self::Updated => "updated",
            Self::Deleted => "deleted",
            Self::Consolidated => "consolidated",
        }
    }
}

impl std::fmt::Display for ChangeType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

/// Record of a change to a fact
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangeLog {
    /// ID of the fact that changed
    pub fact_id: String,

    /// Type of change
    pub change_type: ChangeType,

    /// Timestamp of the change
    pub timestamp: DateTime<Utc>,

    /// Previous content (if applicable)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub previous_content: Option<String>,

    /// New content (if applicable)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub new_content: Option<String>,

    /// Scope identifiers
    pub scope: ScopeIdentifiers,

    /// Actor who made the change
    #[serde(skip_serializing_if = "Option::is_none")]
    pub actor: Option<String>,
}

impl ChangeLog {
    /// Create a new change log entry
    pub fn new(
        fact_id: impl Into<String>,
        change_type: ChangeType,
        scope: ScopeIdentifiers,
    ) -> Self {
        Self {
            fact_id: fact_id.into(),
            change_type,
            timestamp: Utc::now(),
            previous_content: None,
            new_content: None,
            scope,
            actor: None,
        }
    }

    /// Set previous content
    pub fn with_previous_content(mut self, content: impl Into<String>) -> Self {
        self.previous_content = Some(content.into());
        self
    }

    /// Set new content
    pub fn with_new_content(mut self, content: impl Into<String>) -> Self {
        self.new_content = Some(content.into());
        self
    }

    /// Set actor
    pub fn with_actor(mut self, actor: impl Into<String>) -> Self {
        self.actor = Some(actor.into());
        self
    }
}