subcog/models/memory.rs
1//! Memory types and identifiers.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7/// Unique identifier for a memory.
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(transparent)]
10pub struct MemoryId(String);
11
12impl MemoryId {
13 /// Creates a new memory ID.
14 #[must_use]
15 pub fn new(id: impl Into<String>) -> Self {
16 Self(id.into())
17 }
18
19 /// Returns the ID as a string slice.
20 #[must_use]
21 pub fn as_str(&self) -> &str {
22 &self.0
23 }
24}
25
26impl fmt::Display for MemoryId {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "{}", self.0)
29 }
30}
31
32impl From<String> for MemoryId {
33 fn from(s: String) -> Self {
34 Self(s)
35 }
36}
37
38impl From<&str> for MemoryId {
39 fn from(s: &str) -> Self {
40 Self(s.to_string())
41 }
42}
43
44/// A captured memory entry.
45#[derive(Debug, Clone)]
46pub struct Memory {
47 /// Unique identifier.
48 pub id: MemoryId,
49 /// The memory content.
50 pub content: String,
51 /// The namespace this memory belongs to.
52 pub namespace: super::Namespace,
53 /// The domain this memory is associated with.
54 pub domain: super::Domain,
55 /// Optional project identifier (normalized git remote URL).
56 pub project_id: Option<String>,
57 /// Optional branch name for project-scoped memories.
58 pub branch: Option<String>,
59 /// Optional file path relative to repository root.
60 pub file_path: Option<String>,
61 /// Current status of the memory.
62 pub status: super::MemoryStatus,
63 /// Creation timestamp (Unix epoch seconds).
64 pub created_at: u64,
65 /// Last update timestamp (Unix epoch seconds).
66 pub updated_at: u64,
67 /// Tombstone timestamp (UTC) when soft-deleted.
68 ///
69 /// Compatibility is handled in storage adapters, so explicit versioning
70 /// of the Memory struct is not required at this time.
71 pub tombstoned_at: Option<DateTime<Utc>>,
72 /// Expiration timestamp (Unix epoch seconds).
73 ///
74 /// Memory is eligible for automatic cleanup after this timestamp.
75 /// Set at capture time as `created_at + ttl_seconds`. Preserved on updates.
76 /// `None` means no expiration (memory lives until manually deleted).
77 pub expires_at: Option<u64>,
78 /// Optional embedding vector.
79 pub embedding: Option<Vec<f32>>,
80 /// Optional tags for categorization.
81 pub tags: Vec<String>,
82 /// Optional group identifier for group-scoped memories.
83 ///
84 /// When set, this memory belongs to a specific group within an organization.
85 /// Group members with sufficient permissions can access these memories.
86 #[cfg(feature = "group-scope")]
87 pub group_id: Option<String>,
88 /// Optional source reference (file path, URL, etc.).
89 pub source: Option<String>,
90 /// Whether this memory is a consolidation summary.
91 ///
92 /// When `true`, this memory represents a consolidated summary of multiple
93 /// related memories. The original memories are preserved and linked via
94 /// `source_memory_ids`.
95 pub is_summary: bool,
96 /// IDs of memories that were consolidated into this summary.
97 ///
98 /// Only populated when `is_summary` is `true`. These represent the original
99 /// memories that were analyzed and combined to create this summary.
100 pub source_memory_ids: Option<Vec<MemoryId>>,
101 /// Timestamp when this memory was consolidated (Unix epoch seconds).
102 ///
103 /// Only populated for consolidated memories (both summaries and source memories
104 /// that have been included in a consolidation).
105 pub consolidation_timestamp: Option<u64>,
106}
107
108/// Result of a memory operation with optional metadata.
109#[derive(Debug, Clone)]
110pub struct MemoryResult {
111 /// The memory data.
112 pub memory: Memory,
113 /// Similarity score (0.0 to 1.0) if from a search.
114 pub score: Option<f32>,
115 /// BM25 score if text search was used.
116 pub bm25_score: Option<f32>,
117}