Skip to main content

locus_sdk/application/
memory_schema.rs

1use crate::domain::memory::{MEMORY_SCHEMA_VERSION, MemorySchemaResult};
2use crate::domain::reflex::MemoryAction;
3
4pub struct MemorySchemaService;
5
6impl MemorySchemaService {
7    pub fn new() -> Self {
8        Self
9    }
10
11    pub fn execute(&self) -> MemorySchemaResult {
12        MemorySchemaResult {
13            schema_version: MEMORY_SCHEMA_VERSION.to_string(),
14            sort_fields: vec![
15                "timestamp".to_string(),
16                "updated_at".to_string(),
17                "psi".to_string(),
18                "rho".to_string(),
19                "kappa".to_string(),
20            ],
21            filter_fields: vec![
22                "has_embedding".to_string(),
23                "embedding_model".to_string(),
24                "psi".to_string(),
25                "rho".to_string(),
26                "kappa".to_string(),
27                "text_contains".to_string(),
28                "tags_contains".to_string(),
29                "has_tag".to_string(),
30                "indexed_tags".to_string(),
31                "tag_prefix".to_string(),
32                "has_semantic_links".to_string(),
33                "link_rel".to_string(),
34                "link_target".to_string(),
35                "links_to_ref".to_string(),
36            ],
37            group_by_fields: vec![
38                "session_id".to_string(),
39                "tier".to_string(),
40                "embedding_model".to_string(),
41                "date_day".to_string(),
42                "semantic_tag".to_string(),
43            ],
44            fallback_policies: vec![
45                "never".to_string(),
46                "on_empty".to_string(),
47                "always".to_string(),
48            ],
49            strictness_modes: vec![
50                "precision".to_string(),
51                "balanced".to_string(),
52                "recall".to_string(),
53            ],
54            transform_operations: vec![
55                "embed_backfill".to_string(),
56                "reindex_embeddings".to_string(),
57                "embed_tag_backfill".to_string(),
58                "reindex_tag_embeddings".to_string(),
59            ],
60            evict_operations: vec!["delete_nodes".to_string(), "purge_session".to_string()],
61            reflex_actions: MemoryAction::all()
62                .iter()
63                .map(|action| action.as_str().to_string())
64                .collect(),
65            decision_types: vec![
66                "choice".to_string(),
67                "score".to_string(),
68                "noul".to_string(),
69            ],
70        }
71    }
72}
73
74impl Default for MemorySchemaService {
75    fn default() -> Self {
76        Self::new()
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::MemorySchemaService;
83
84    #[test]
85    fn schema_contains_expected_core_fields() {
86        let service = MemorySchemaService::new();
87        let schema = service.execute();
88
89        assert_eq!(schema.schema_version, "locus-sdk.memory.v4");
90        assert!(schema.reflex_actions.contains(&"recall".to_string()));
91        assert!(schema.decision_types.contains(&"noul".to_string()));
92        assert!(schema.sort_fields.contains(&"timestamp".to_string()));
93        assert!(schema.group_by_fields.contains(&"session_id".to_string()));
94        assert!(schema.fallback_policies.contains(&"on_empty".to_string()));
95        assert!(
96            schema
97                .transform_operations
98                .contains(&"embed_backfill".to_string())
99        );
100        assert!(schema.filter_fields.contains(&"has_tag".to_string()));
101    }
102
103    #[test]
104    fn schema_contains_semantic_tag_filters() {
105        let service = MemorySchemaService::new();
106        let schema = service.execute();
107
108        assert!(schema.filter_fields.contains(&"tags_contains".to_string()));
109        assert!(schema.filter_fields.contains(&"indexed_tags".to_string()));
110        assert!(schema.filter_fields.contains(&"link_rel".to_string()));
111    }
112}