construct/memory/
backend.rs1#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2pub enum MemoryBackendKind {
3 Kumiho,
4 None,
5 Unknown,
6}
7
8#[allow(clippy::struct_excessive_bools)]
9#[derive(Debug, Clone, Copy, Eq, PartialEq)]
10pub struct MemoryBackendProfile {
11 pub key: &'static str,
12 pub label: &'static str,
13 pub auto_save_default: bool,
14 pub uses_sqlite_hygiene: bool,
15 pub sqlite_based: bool,
16 pub optional_dependency: bool,
17}
18
19const KUMIHO_PROFILE: MemoryBackendProfile = MemoryBackendProfile {
20 key: "kumiho",
21 label: "Kumiho — graph-native cognitive memory (recommended)",
22 auto_save_default: true,
23 uses_sqlite_hygiene: false,
24 sqlite_based: false,
25 optional_dependency: false,
26};
27
28const NONE_PROFILE: MemoryBackendProfile = MemoryBackendProfile {
29 key: "none",
30 label: "None — disable persistent memory",
31 auto_save_default: false,
32 uses_sqlite_hygiene: false,
33 sqlite_based: false,
34 optional_dependency: false,
35};
36
37const CUSTOM_PROFILE: MemoryBackendProfile = MemoryBackendProfile {
38 key: "custom",
39 label: "Custom backend — extension point",
40 auto_save_default: true,
41 uses_sqlite_hygiene: false,
42 sqlite_based: false,
43 optional_dependency: false,
44};
45
46const SELECTABLE_MEMORY_BACKENDS: [MemoryBackendProfile; 2] = [KUMIHO_PROFILE, NONE_PROFILE];
48
49pub fn selectable_memory_backends() -> &'static [MemoryBackendProfile] {
50 &SELECTABLE_MEMORY_BACKENDS
51}
52
53pub fn default_memory_backend_key() -> &'static str {
55 KUMIHO_PROFILE.key
56}
57
58pub fn classify_memory_backend(backend: &str) -> MemoryBackendKind {
59 match backend {
60 "kumiho" => MemoryBackendKind::Kumiho,
61 "none" => MemoryBackendKind::None,
62 _ => MemoryBackendKind::Unknown,
63 }
64}
65
66pub fn memory_backend_profile(backend: &str) -> MemoryBackendProfile {
67 match classify_memory_backend(backend) {
68 MemoryBackendKind::Kumiho => KUMIHO_PROFILE,
69 MemoryBackendKind::None => NONE_PROFILE,
70 MemoryBackendKind::Unknown => CUSTOM_PROFILE,
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn classify_known_backends() {
80 assert_eq!(classify_memory_backend("kumiho"), MemoryBackendKind::Kumiho);
81 assert_eq!(classify_memory_backend("none"), MemoryBackendKind::None);
82 }
83
84 #[test]
85 fn classify_removed_backends_are_unknown() {
86 for name in ["sqlite", "lucid", "markdown", "qdrant"] {
87 assert_eq!(
88 classify_memory_backend(name),
89 MemoryBackendKind::Unknown,
90 "'{name}' should be treated as Unknown after removal"
91 );
92 }
93 }
94
95 #[test]
96 fn classify_unknown_backend() {
97 assert_eq!(classify_memory_backend("redis"), MemoryBackendKind::Unknown);
98 }
99
100 #[test]
101 fn default_backend_is_kumiho() {
102 assert_eq!(default_memory_backend_key(), "kumiho");
103 }
104
105 #[test]
106 fn selectable_backends_are_kumiho_and_none() {
107 let backends = selectable_memory_backends();
108 assert_eq!(backends.len(), 2);
109 assert_eq!(backends[0].key, "kumiho");
110 assert_eq!(backends[1].key, "none");
111 }
112
113 #[test]
114 fn unknown_profile_preserves_extensibility_defaults() {
115 let profile = memory_backend_profile("custom-memory");
116 assert_eq!(profile.key, "custom");
117 assert!(profile.auto_save_default);
118 assert!(!profile.uses_sqlite_hygiene);
119 }
120}