1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9pub type FeatureVector = Vec<f32>;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Embedding {
15 pub vector: FeatureVector,
17 pub dim: usize,
19}
20
21impl Embedding {
22 pub fn new(vector: FeatureVector) -> Self {
24 let dim = vector.len();
25 Self { vector, dim }
26 }
27
28 pub fn zeros(dim: usize) -> Self {
30 Self {
31 vector: vec![0.0; dim],
32 dim,
33 }
34 }
35
36 pub fn cosine_similarity(&self, other: &Embedding) -> f32 {
38 if self.dim != other.dim {
39 return 0.0;
40 }
41
42 let dot: f32 = self
43 .vector
44 .iter()
45 .zip(other.vector.iter())
46 .map(|(a, b)| a * b)
47 .sum();
48
49 let norm_a: f32 = self.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
50 let norm_b: f32 = other.vector.iter().map(|x| x * x).sum::<f32>().sqrt();
51
52 if norm_a == 0.0 || norm_b == 0.0 {
53 0.0
54 } else {
55 dot / (norm_a * norm_b)
56 }
57 }
58
59 pub fn l2_distance(&self, other: &Embedding) -> f32 {
61 if self.dim != other.dim {
62 return f32::MAX;
63 }
64
65 self.vector
66 .iter()
67 .zip(other.vector.iter())
68 .map(|(a, b)| (a - b).powi(2))
69 .sum::<f32>()
70 .sqrt()
71 }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Pattern {
77 pub id: PatternId,
79 pub embedding: Embedding,
81 pub metadata: HashMap<String, String>,
83 pub created_at: u64,
85}
86
87pub type PatternId = [u8; 32];
89
90pub fn pattern_id(data: &[u8]) -> PatternId {
92 use blake2::{Blake2b512, Digest};
93 let mut hasher = Blake2b512::new();
94 hasher.update(data);
95 let result = hasher.finalize();
96 let mut id = [0u8; 32];
97 id.copy_from_slice(&result[..32]);
98 id
99}
100
101#[derive(Debug, Clone)]
103pub struct MemoryMatch {
104 pub pattern: Pattern,
106 pub similarity: f32,
108 pub source: MemorySource,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub enum MemorySource {
115 ShortTerm,
117 LongTerm,
119}
120
121#[derive(Debug, Clone)]
123pub struct ProcessResult {
124 pub relevance: f32,
126 pub surprise: f32,
128 pub stored_long_term: bool,
130 pub anomaly: Option<AnomalyResult>,
132}
133
134#[derive(Debug, Clone)]
136pub struct AnomalyResult {
137 pub is_anomaly: bool,
139 pub confidence: f32,
141 pub reason: String,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct AiTransaction {
148 pub hash: [u8; 32],
150 pub timestamp: u64,
152 pub agent: [u8; 32],
154 pub entry_type: String,
156 pub data: Vec<u8>,
158 pub size: usize,
160}
161
162impl AiTransaction {
163 pub fn extract_features(&self) -> FeatureVector {
165 let mut features = Vec::with_capacity(16);
166
167 features.push((self.size as f32).ln().max(0.0) / 20.0);
169
170 let timestamp_secs = self.timestamp / 1000;
172 let hour = ((timestamp_secs / 3600) % 24) as f32 / 24.0;
173 features.push(hour);
174
175 let type_hash = pattern_id(self.entry_type.as_bytes());
177 for i in 0..4 {
178 features.push(type_hash[i] as f32 / 255.0);
179 }
180
181 for i in 0..4 {
183 features.push(self.agent[i] as f32 / 255.0);
184 }
185
186 if !self.data.is_empty() {
188 let mut byte_counts = [0u32; 256];
189 for &byte in &self.data {
190 byte_counts[byte as usize] += 1;
191 }
192 let len = self.data.len() as f32;
193 let entropy: f32 = byte_counts
194 .iter()
195 .filter(|&&c| c > 0)
196 .map(|&c| {
197 let p = c as f32 / len;
198 -p * p.ln()
199 })
200 .sum();
201 features.push(entropy / 8.0); } else {
203 features.push(0.0);
204 }
205
206 while features.len() < 16 {
208 features.push(0.0);
209 }
210
211 features
212 }
213
214 pub fn to_pattern(&self) -> Pattern {
216 let embedding = Embedding::new(self.extract_features());
217 Pattern {
218 id: self.hash,
219 embedding,
220 metadata: HashMap::new(),
221 created_at: self.timestamp,
222 }
223 }
224}
225
226#[derive(Debug, Clone)]
228pub struct ValidationPrediction {
229 pub likely_valid: bool,
231 pub confidence: f32,
233 pub estimated_time_ms: u64,
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub enum ConsensusLevel {
240 Full,
242 Majority,
244 Quorum,
246 Local,
248}
249
250#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252pub enum ResourceCategory {
253 Abundant,
255 Normal,
257 Limited,
259 Critical,
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn test_embedding_cosine_similarity() {
269 let a = Embedding::new(vec![1.0, 0.0, 0.0]);
270 let b = Embedding::new(vec![1.0, 0.0, 0.0]);
271 assert!((a.cosine_similarity(&b) - 1.0).abs() < 0.001);
272
273 let c = Embedding::new(vec![0.0, 1.0, 0.0]);
274 assert!(a.cosine_similarity(&c).abs() < 0.001);
275 }
276
277 #[test]
278 fn test_transaction_features() {
279 let tx = AiTransaction {
280 hash: [1u8; 32],
281 timestamp: 1702656000000, agent: [2u8; 32],
283 entry_type: "test_entry".to_string(),
284 data: vec![0, 1, 2, 3, 4, 5],
285 size: 6,
286 };
287
288 let features = tx.extract_features();
289 assert_eq!(features.len(), 16);
290 assert!(features.iter().all(|&f| f >= 0.0 && f <= 2.0));
291 }
292}