1use serde::{Deserialize, Serialize};
4use std::hash::{Hash, Hasher};
5
6pub use exo_core::{Metadata, MetadataValue, Pattern, PatternId, SubstrateTime};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct TemporalPattern {
12 pub pattern: Pattern,
14 pub access_count: usize,
16 pub last_accessed: SubstrateTime,
18}
19
20impl TemporalPattern {
21 pub fn new(pattern: Pattern) -> Self {
23 Self {
24 pattern,
25 access_count: 0,
26 last_accessed: SubstrateTime::now(),
27 }
28 }
29
30 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 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 pub fn mark_accessed(&mut self) {
62 self.access_count += 1;
63 self.last_accessed = SubstrateTime::now();
64 }
65
66 pub fn id(&self) -> PatternId {
68 self.pattern.id
69 }
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct Query {
75 pub embedding: Vec<f32>,
77 pub origin: Option<PatternId>,
79 pub k: usize,
81}
82
83impl Query {
84 pub fn from_embedding(embedding: Vec<f32>) -> Self {
86 Self {
87 embedding,
88 origin: None,
89 k: 10,
90 }
91 }
92
93 pub fn with_origin(mut self, origin: PatternId) -> Self {
95 self.origin = Some(origin);
96 self
97 }
98
99 pub fn with_k(mut self, k: usize) -> Self {
101 self.k = k;
102 self
103 }
104
105 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#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct CausalResult {
123 pub pattern: TemporalPattern,
125 pub similarity: f32,
127 pub causal_distance: Option<usize>,
129 pub temporal_distance_ns: i64,
131 pub combined_score: f32,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct SearchResult {
138 pub id: PatternId,
140 pub pattern: TemporalPattern,
142 pub score: f32,
144}
145
146#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
148pub struct TimeRange {
149 pub start: SubstrateTime,
151 pub end: SubstrateTime,
153}
154
155impl TimeRange {
156 pub fn new(start: SubstrateTime, end: SubstrateTime) -> Self {
158 Self { start, end }
159 }
160
161 pub fn contains(&self, time: &SubstrateTime) -> bool {
163 time >= &self.start && time <= &self.end
164 }
165
166 pub fn past(reference: SubstrateTime) -> Self {
168 Self {
169 start: SubstrateTime::MIN,
170 end: reference,
171 }
172 }
173
174 pub fn future(reference: SubstrateTime) -> Self {
176 Self {
177 start: reference,
178 end: SubstrateTime::MAX,
179 }
180 }
181}