exo_temporal/
types.rs

1//! Core type definitions for temporal memory
2
3use serde::{Deserialize, Serialize};
4use std::hash::{Hash, Hasher};
5
6// Re-export core types from exo-core
7pub use exo_core::{Metadata, MetadataValue, Pattern, PatternId, SubstrateTime};
8
9/// Extended pattern with temporal tracking
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct TemporalPattern {
12    /// Base pattern
13    pub pattern: Pattern,
14    /// Access count
15    pub access_count: usize,
16    /// Last access time
17    pub last_accessed: SubstrateTime,
18}
19
20impl TemporalPattern {
21    /// Create new temporal pattern
22    pub fn new(pattern: Pattern) -> Self {
23        Self {
24            pattern,
25            access_count: 0,
26            last_accessed: SubstrateTime::now(),
27        }
28    }
29
30    /// Create from components
31    pub fn from_embedding(embedding: Vec<f32>, metadata: Metadata) -> Self {
32        let pattern = Pattern {
33            id: PatternId::new(),
34            embedding,
35            metadata,
36            timestamp: SubstrateTime::now(),
37            antecedents: Vec::new(),
38            salience: 1.0,
39        };
40        Self::new(pattern)
41    }
42
43    /// Create with antecedents
44    pub fn with_antecedents(
45        embedding: Vec<f32>,
46        metadata: Metadata,
47        antecedents: Vec<PatternId>,
48    ) -> Self {
49        let pattern = Pattern {
50            id: PatternId::new(),
51            embedding,
52            metadata,
53            timestamp: SubstrateTime::now(),
54            antecedents,
55            salience: 1.0,
56        };
57        Self::new(pattern)
58    }
59
60    /// Update access tracking
61    pub fn mark_accessed(&mut self) {
62        self.access_count += 1;
63        self.last_accessed = SubstrateTime::now();
64    }
65
66    /// Get pattern ID
67    pub fn id(&self) -> PatternId {
68        self.pattern.id
69    }
70}
71
72/// Query for pattern retrieval
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct Query {
75    /// Query vector embedding
76    pub embedding: Vec<f32>,
77    /// Origin pattern (for causal queries)
78    pub origin: Option<PatternId>,
79    /// Number of results requested
80    pub k: usize,
81}
82
83impl Query {
84    /// Create from embedding
85    pub fn from_embedding(embedding: Vec<f32>) -> Self {
86        Self {
87            embedding,
88            origin: None,
89            k: 10,
90        }
91    }
92
93    /// Set origin for causal queries
94    pub fn with_origin(mut self, origin: PatternId) -> Self {
95        self.origin = Some(origin);
96        self
97    }
98
99    /// Set number of results
100    pub fn with_k(mut self, k: usize) -> Self {
101        self.k = k;
102        self
103    }
104
105    /// Compute hash for caching
106    pub fn hash(&self) -> u64 {
107        use ahash::AHasher;
108        let mut hasher = AHasher::default();
109        for &val in &self.embedding {
110            val.to_bits().hash(&mut hasher);
111        }
112        if let Some(origin) = &self.origin {
113            origin.hash(&mut hasher);
114        }
115        self.k.hash(&mut hasher);
116        hasher.finish()
117    }
118}
119
120/// Result from causal query
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct CausalResult {
123    /// Retrieved pattern
124    pub pattern: TemporalPattern,
125    /// Similarity score
126    pub similarity: f32,
127    /// Causal distance (edges in causal graph)
128    pub causal_distance: Option<usize>,
129    /// Temporal distance in nanoseconds
130    pub temporal_distance_ns: i64,
131    /// Combined relevance score
132    pub combined_score: f32,
133}
134
135/// Search result
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct SearchResult {
138    /// Pattern ID
139    pub id: PatternId,
140    /// Pattern
141    pub pattern: TemporalPattern,
142    /// Similarity score
143    pub score: f32,
144}
145
146/// Time range for queries
147#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
148pub struct TimeRange {
149    /// Start time (inclusive)
150    pub start: SubstrateTime,
151    /// End time (inclusive)
152    pub end: SubstrateTime,
153}
154
155impl TimeRange {
156    /// Create new time range
157    pub fn new(start: SubstrateTime, end: SubstrateTime) -> Self {
158        Self { start, end }
159    }
160
161    /// Check if time is within range
162    pub fn contains(&self, time: &SubstrateTime) -> bool {
163        time >= &self.start && time <= &self.end
164    }
165
166    /// Past cone (everything before reference time)
167    pub fn past(reference: SubstrateTime) -> Self {
168        Self {
169            start: SubstrateTime::MIN,
170            end: reference,
171        }
172    }
173
174    /// Future cone (everything after reference time)
175    pub fn future(reference: SubstrateTime) -> Self {
176        Self {
177            start: reference,
178            end: SubstrateTime::MAX,
179        }
180    }
181}