Skip to main content

microscope_memory/
lib.rs

1#![recursion_limit = "512"]
2//! Microscope Memory library interface.
3//! Re-exports core types and functions for integration tests and external use.
4
5pub mod archetype;
6pub mod attention;
7#[cfg(not(target_arch = "wasm32"))]
8pub mod build;
9#[cfg(not(target_arch = "wasm32"))]
10pub mod cache;
11pub mod config;
12#[cfg(not(target_arch = "wasm32"))]
13pub mod doctor;
14#[cfg(not(target_arch = "wasm32"))]
15pub mod embedding_index;
16pub mod embeddings;
17#[cfg(not(target_arch = "wasm32"))]
18pub mod emotional;
19#[cfg(not(target_arch = "wasm32"))]
20pub mod emotional_state;
21#[cfg(not(target_arch = "wasm32"))]
22pub mod federation;
23pub mod fingerprint;
24pub mod hebbian;
25pub mod no_learn;
26pub mod parallel;
27pub mod sync_guard;
28pub mod types;
29
30#[cfg(not(target_arch = "wasm32"))]
31pub mod ai_adapter;
32#[cfg(not(target_arch = "wasm32"))]
33pub mod bridge;
34#[cfg(not(target_arch = "wasm32"))]
35pub mod mcp;
36#[cfg(all(not(target_arch = "wasm32"), feature = "mcp_http"))]
37pub mod mcp_http;
38pub mod merkle;
39pub mod mirror;
40#[cfg(not(target_arch = "wasm32"))]
41pub mod query;
42#[cfg(not(target_arch = "wasm32"))]
43pub mod reader;
44#[cfg(not(target_arch = "wasm32"))]
45pub mod recall_ctx;
46pub mod resonance;
47#[cfg(not(target_arch = "wasm32"))]
48pub mod sequential_thinking;
49pub mod snapshot;
50#[cfg(not(target_arch = "wasm32"))]
51pub mod text_index;
52
53#[cfg(not(target_arch = "wasm32"))]
54pub mod consciousness_seqlock;
55#[cfg(not(target_arch = "wasm32"))]
56pub mod consciousness_stream;
57#[cfg(not(target_arch = "wasm32"))]
58pub mod daydream;
59#[cfg(not(target_arch = "wasm32"))]
60pub mod dream;
61#[cfg(not(target_arch = "wasm32"))]
62pub mod emotion_extraction;
63pub mod emotional_contagion;
64#[cfg(not(target_arch = "wasm32"))]
65pub mod emotional_episode;
66#[cfg(not(target_arch = "wasm32"))]
67pub mod emotional_gate;
68#[cfg(not(target_arch = "wasm32"))]
69pub mod eureka;
70#[cfg(not(target_arch = "wasm32"))]
71#[cfg(not(target_arch = "wasm32"))]
72pub mod narrative;
73#[cfg(not(target_arch = "wasm32"))]
74pub mod pipeline;
75#[cfg(not(target_arch = "wasm32"))]
76pub mod reconsolidation;
77#[cfg(not(target_arch = "wasm32"))]
78pub mod salience;
79#[cfg(not(target_arch = "wasm32"))]
80pub mod spaced_repetition;
81#[cfg(not(target_arch = "wasm32"))]
82pub mod working_memory;
83
84// New cognitive enhancement modules
85#[cfg(not(target_arch = "wasm32"))]
86pub mod absentia;
87#[cfg(not(target_arch = "wasm32"))]
88pub mod advanced_cognition;
89#[cfg(not(target_arch = "wasm32"))]
90pub mod architecture_generator;
91#[cfg(not(target_arch = "wasm32"))]
92pub mod architecture_simulator;
93#[cfg(not(target_arch = "wasm32"))]
94pub mod autopoiesis;
95#[cfg(not(target_arch = "wasm32"))]
96pub mod chatgpt;
97#[cfg(not(target_arch = "wasm32"))]
98pub mod code_memory;
99#[cfg(not(target_arch = "wasm32"))]
100pub mod cognitive_morphogenesis;
101#[cfg(not(target_arch = "wasm32"))]
102pub mod enforcement;
103#[cfg(not(target_arch = "wasm32"))]
104pub mod executive;
105#[cfg(not(target_arch = "wasm32"))]
106pub mod explicit_memory;
107#[cfg(not(target_arch = "wasm32"))]
108pub mod functional_plasticity;
109#[cfg(not(target_arch = "wasm32"))]
110pub mod heuristic_decision;
111#[cfg(not(target_arch = "wasm32"))]
112pub mod hippocampus;
113#[cfg(not(target_arch = "wasm32"))]
114pub mod hyperfocus;
115#[cfg(not(target_arch = "wasm32"))]
116pub mod implicit_memory;
117#[cfg(not(target_arch = "wasm32"))]
118pub mod impulse_control;
119#[cfg(not(target_arch = "wasm32"))]
120pub mod intent;
121pub mod keystore;
122#[cfg(not(target_arch = "wasm32"))]
123pub mod knowledge_base;
124#[cfg(not(target_arch = "wasm32"))]
125pub mod mental_sandbox;
126#[cfg(not(target_arch = "wasm32"))]
127pub mod mental_stimulation;
128#[cfg(not(target_arch = "wasm32"))]
129pub mod meta_supervision;
130pub mod morphogenesis;
131pub mod multimodal;
132#[cfg(not(target_arch = "wasm32"))]
133pub mod neuroplasticity;
134#[cfg(not(target_arch = "wasm32"))]
135pub mod pattern_recognition;
136#[cfg(not(target_arch = "wasm32"))]
137pub mod planning;
138pub mod predictive_cache;
139pub mod relevance;
140#[cfg(not(target_arch = "wasm32"))]
141pub mod spine;
142#[cfg(not(target_arch = "wasm32"))]
143pub mod structural_plasticity;
144#[cfg(not(target_arch = "wasm32"))]
145pub mod synaptic_plasticity;
146pub mod temporal_archetype;
147pub mod thought_graph;
148#[cfg(not(target_arch = "wasm32"))]
149pub mod vagus;
150#[cfg(not(target_arch = "wasm32"))]
151pub mod viz;
152pub mod zen_keystore;
153
154#[cfg(target_arch = "wasm32")]
155pub mod wasm;
156
157#[cfg(feature = "python")]
158#[allow(non_local_definitions)]
159pub mod python;
160
161#[cfg(feature = "gpu")]
162pub mod gpu;
163
164#[cfg(not(target_arch = "wasm32"))]
165pub mod cli;
166pub mod open_loops;
167pub mod timeline;
168
169// Re-export commonly used items
170#[cfg(not(target_arch = "wasm32"))]
171pub use emotional_state::{emotional_prime_weight, EmotionalStateRing};
172#[cfg(not(target_arch = "wasm32"))]
173pub use reader::{
174    append_emotion_log, build_emotions_from_log, emotional_similarity, format_emotion,
175    load_emotion_lookup, read_append_log, store_memory, store_memory_temporary,
176    store_memory_with_embedding, store_memory_with_emotion, DataStore, MicroscopeReader,
177    RadialResult, ResultSet, EMOTION_DIMS, EMOTION_VECTOR_SIZE,
178};
179#[cfg(not(target_arch = "wasm32"))]
180pub use types::{AppendEntry, BlockHeader, MemoryBlockHeader, MemoryQueryOptions, ProjectId};
181
182#[cfg(target_arch = "wasm32")]
183pub use types::{AppendEntry, BlockHeader, MemoryBlockHeader, MemoryQueryOptions, ProjectId};
184
185// Re-export CLI
186#[cfg(not(target_arch = "wasm32"))]
187pub use cli::{Cli, Cmd};
188
189// ─── Shared constants ────────────────────────────────
190pub const DEFAULT_CONFIG_PATH: &str = "config.toml";
191
192/// Maximum bytes of text stored in one block.
193///
194/// Raised from 1024 on the evidence of the BEIR SciFact run, and the reason is
195/// worth recording because the fix looked like a storage-format change and was
196/// not. At 1024, `to_block` truncated 4,300 of the 5,183 abstracts at byte 1,021,
197/// so most of that corpus was silently cut. Splitting the tail into further
198/// blocks stopped the data loss but cost 9.4 points of R@1 (51.0% -> 41.6%),
199/// because a 1,400-character abstract is a better retrieval unit than two
200/// ~700-character fragments: the sentence that answers a query gets separated
201/// from the title that the query matches against.
202///
203/// 16 KiB is large enough to hold the longest SciFact abstract (10,127 bytes)
204/// whole, so the index stores one block per document and the embedded set
205/// matches what the FAISS baseline embeds -- one vector per abstract. It does
206/// not mean long inputs are embedded whole: the MiniLM provider truncates at
207/// 512 tokens regardless, exactly as the reference encoder does, so the two
208/// systems see the same text.
209///
210/// This was always safe to raise. data.bin is a packed, variable-length file
211/// whose real span lives in BlockHeader's data_offset (u32) and data_len (u16),
212/// not a fixed-stride grid, so no reader assumes a particular block size. The
213/// u16 is the real ceiling: 65,535 bytes. Entries longer than BLOCK_DATA_SIZE
214/// are still split rather than truncated, by `build::split_oversized_entry`.
215pub const BLOCK_DATA_SIZE: usize = 16384;
216pub const HEADER_SIZE: usize = 50;
217pub const LEGACY_HEADER_SIZE: usize = 32;
218pub const APV3_MAGIC: &[u8] = b"APv3";
219pub const META_HEADER_SIZE: usize = 16;
220pub const DEPTH_ENTRY_SIZE: usize = 8;
221pub const LAYER_NAMES: &[&str] = &[
222    "identity",
223    "long_term",
224    "short_term",
225    "associative",
226    "emotional",
227    "relational",
228    "reflections",
229    "crypto_chain",
230    "echo_cache",
231    "rust_state",
232    "code",
233    "session",
234];
235
236// ─── Shared utility functions ────────────────────────
237
238pub fn layer_to_id(name: &str) -> u8 {
239    LAYER_NAMES.iter().position(|&n| n == name).unwrap_or(0) as u8
240}
241
242/// CRC16-CCITT (poly=0x1021, init=0xFFFF) over arbitrary data.
243pub fn crc16_ccitt(data: &[u8]) -> u16 {
244    let mut crc: u16 = 0xFFFF;
245    for &byte in data {
246        crc ^= (byte as u16) << 8;
247        for _ in 0..8 {
248            if crc & 0x8000 != 0 {
249                crc = (crc << 1) ^ 0x1021;
250            } else {
251                crc <<= 1;
252            }
253        }
254    }
255    crc
256}
257
258pub fn content_coords(text: &str, layer: &str) -> (f32, f32, f32) {
259    let mut h: [u64; 3] = [0xcbf29ce484222325, 0x100000001b3, 0xa5a5a5a5a5a5a5a5];
260    for &b in text.as_bytes().iter().take(128) {
261        h[0] = h[0].wrapping_mul(0x100000001b3) ^ b as u64;
262        h[1] = h[1].wrapping_mul(0x100000001b3) ^ b as u64;
263        h[2] = h[2].wrapping_mul(0x1000193) ^ b as u64;
264    }
265    let bx = (h[0] & 0xFFFF) as f32 / 65535.0;
266    let by = (h[1] & 0xFFFF) as f32 / 65535.0;
267    let bz = (h[2] & 0xFFFF) as f32 / 65535.0;
268
269    let (ox, oy, oz) = match layer {
270        "long_term" => (0.0, 0.0, 0.0),
271        "associative" => (0.3, 0.0, 0.0),
272        "emotional" => (0.1, 0.3, 0.2),
273        "relational" => (0.3, 0.3, 0.0),
274        "reflections" => (0.0, 0.0, 0.3),
275        "crypto_chain" => (0.3, 0.0, 0.3),
276        "echo_cache" => (0.0, 0.3, 0.3),
277        "short_term" => (0.15, 0.15, 0.15),
278        "rust_state" => (0.15, 0.0, 0.15),
279        "session" => (0.0, 0.0, 0.0),
280        _ => (0.25, 0.25, 0.25),
281    };
282
283    (ox + bx * 0.25, oy + by * 0.25, oz + bz * 0.25)
284}
285
286fn semantic_coords(text: &str, weight: f32) -> Option<(f32, f32, f32)> {
287    if weight <= 0.0 {
288        return None;
289    }
290    use embeddings::{EmbeddingProvider, MockEmbeddingProvider};
291    let provider = MockEmbeddingProvider::new(128);
292    if let Ok(emb) = provider.embed(text) {
293        if emb.len() >= 3 {
294            let sx = (emb[0] + 1.0) / 2.0;
295            let sy = (emb[1] + 1.0) / 2.0;
296            let sz = (emb[2] + 1.0) / 2.0;
297            return Some((sx, sy, sz));
298        }
299    }
300    None
301}
302
303pub fn content_coords_blended(text: &str, layer: &str, weight: f32) -> (f32, f32, f32) {
304    let (hx, hy, hz) = content_coords(text, layer);
305    if weight <= 0.0 {
306        return (hx, hy, hz);
307    }
308    match semantic_coords(text, weight) {
309        Some((sx, sy, sz)) => {
310            let w = weight.clamp(0.0, 1.0);
311            (
312                (1.0 - w) * hx + w * sx,
313                (1.0 - w) * hy + w * sy,
314                (1.0 - w) * hz + w * sz,
315            )
316        }
317        None => (hx, hy, hz),
318    }
319}
320
321pub fn hex_str(bytes: &[u8]) -> String {
322    bytes
323        .iter()
324        .map(|b| format!("{:02x}", b))
325        .collect::<Vec<_>>()
326        .join("")
327}
328
329pub fn safe_truncate(s: &str, max_bytes: usize) -> String {
330    if s.len() <= max_bytes {
331        return s.to_string();
332    }
333    let mut end = max_bytes;
334    while end > 0 && !s.is_char_boundary(end) {
335        end -= 1;
336    }
337    s[..end].to_string()
338}
339
340pub fn to_block(text: &str) -> Vec<u8> {
341    let bytes = text.as_bytes();
342    if bytes.len() <= BLOCK_DATA_SIZE {
343        bytes.to_vec()
344    } else {
345        let mut v = bytes[..BLOCK_DATA_SIZE - 3].to_vec();
346        v.extend_from_slice(b"...");
347        v
348    }
349}
350
351// ─── AUTO ZOOM / AUTO DEPTH ──────────────────────────
352
353pub fn auto_zoom(query: &str) -> (u8, u8) {
354    let stopwords = ["a", "the", "is", "of", "and", "to", "in", "it", "on", "for"];
355    let unique_content_words = query
356        .to_lowercase()
357        .split_whitespace()
358        .filter(|w| !stopwords.contains(w) && w.len() > 2)
359        .count();
360
361    if unique_content_words <= 1 {
362        return (1, 1);
363    }
364    if unique_content_words <= 3 {
365        return (2, 1);
366    }
367    if unique_content_words <= 6 {
368        return (3, 1);
369    }
370    if unique_content_words <= 10 {
371        return (4, 1);
372    }
373    (5, 1)
374}
375
376pub fn auto_depth(text: &str) -> u8 {
377    let len = text.len();
378    if len >= 100 {
379        3
380    } else if len >= 40 {
381        4
382    } else if len >= 15 {
383        5
384    } else {
385        6
386    }
387}
388
389#[cfg(test)]
390mod tests {
391    use super::*;
392
393    #[test]
394    fn test_crc16_ccitt_known_vector() {
395        let data = b"123456789";
396        assert_eq!(crc16_ccitt(data), 0x29B1);
397    }
398
399    #[test]
400    fn test_crc16_empty() {
401        assert_eq!(crc16_ccitt(b""), 0xFFFF);
402    }
403
404    #[test]
405    fn test_crc16_deterministic() {
406        let a = crc16_ccitt(b"hello world");
407        let b = crc16_ccitt(b"hello world");
408        assert_eq!(a, b);
409        assert_ne!(a, crc16_ccitt(b"hello worl!"));
410    }
411}
412
413// Additional modules for main binary
414#[cfg(not(target_arch = "wasm32"))]
415pub mod auto_context;
416#[cfg(not(target_arch = "wasm32"))]
417pub mod autonomous;
418#[cfg(not(target_arch = "wasm32"))]
419pub mod curiosity;
420pub mod emotional_21d;
421pub mod epistemic;
422#[cfg(not(target_arch = "wasm32"))]
423pub mod inner_monologue;
424#[cfg(not(target_arch = "wasm32"))]
425pub mod mermaid;
426#[cfg(not(target_arch = "wasm32"))]
427pub mod narrative_memory;
428#[cfg(not(target_arch = "wasm32"))]
429pub mod self_model;
430#[cfg(not(target_arch = "wasm32"))]
431pub mod self_reflect;