oxios_kernel/persona/
store.rs1use anyhow::{Result, anyhow};
10use parking_lot::RwLock;
11use std::collections::HashMap;
12use std::sync::Arc;
13
14use super::Persona;
15
16#[derive(Debug, Default)]
18pub struct PersonaStore {
19 personas: RwLock<HashMap<String, Persona>>,
20}
21
22impl PersonaStore {
23 pub fn new() -> Self {
25 Self {
26 personas: RwLock::new(HashMap::new()),
27 }
28 }
29
30 pub fn register(&self, persona: Persona) {
32 let mut personas = self.personas.write();
33 personas.insert(persona.id.clone(), persona);
34 }
35
36 pub fn get(&self, id: &str) -> Option<Persona> {
38 let personas = self.personas.read();
39 personas.get(id).cloned()
40 }
41
42 pub fn list_enabled(&self) -> Vec<Persona> {
44 let personas = self.personas.read();
45 let mut result: Vec<Persona> = personas.values().filter(|p| p.enabled).cloned().collect();
46 result.sort_by(|a, b| a.id.cmp(&b.id));
47 result
48 }
49
50 pub fn list_all(&self) -> Vec<Persona> {
52 let personas = self.personas.read();
53 personas.values().cloned().collect()
54 }
55
56 pub fn set_enabled(&self, id: &str, enabled: bool) -> Result<()> {
58 let mut personas = self.personas.write();
59 match personas.get_mut(id) {
60 Some(p) => {
61 p.enabled = enabled;
62 Ok(())
63 }
64 None => Err(anyhow!("Persona '{id}' not found")),
65 }
66 }
67
68 pub fn delete(&self, id: &str) -> Result<()> {
70 let mut personas = self.personas.write();
71 if personas.remove(id).is_some() {
72 Ok(())
73 } else {
74 Err(anyhow!("Persona '{id}' not found"))
75 }
76 }
77
78 pub fn update(&self, id: &str, updated: Persona) -> Result<()> {
80 let mut personas = self.personas.write();
81 if personas.contains_key(id) {
82 personas.insert(id.to_string(), updated);
83 Ok(())
84 } else {
85 Err(anyhow!("Persona '{id}' not found"))
86 }
87 }
88
89 pub fn len(&self) -> usize {
91 let personas = self.personas.read();
92 personas.len()
93 }
94
95 pub fn is_empty(&self) -> bool {
97 let personas = self.personas.read();
98 personas.is_empty()
99 }
100
101 pub fn load_from_slice(&self, personas: &[Persona]) {
103 let mut store = self.personas.write();
104 for p in personas {
105 store.insert(p.id.clone(), p.clone());
106 }
107 }
108}
109
110#[derive(Clone)]
112pub struct PersonaStoreHandle {
113 store: Arc<PersonaStore>,
114}
115
116impl PersonaStoreHandle {
117 pub fn from_store(store: Arc<PersonaStore>) -> Self {
119 Self { store }
120 }
121
122 pub fn inner(&self) -> Arc<PersonaStore> {
124 Arc::clone(&self.store)
125 }
126}
127
128impl Default for PersonaStoreHandle {
129 fn default() -> Self {
130 Self {
131 store: Arc::new(PersonaStore::new()),
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn test_register_and_get() {
142 let store = PersonaStore::new();
143 let persona = Persona::new("Test", "assistant", "A test persona", "You are a test.");
144 store.register(persona.clone());
145 assert_eq!(store.get(&persona.id).unwrap().name, "Test");
146 }
147
148 #[test]
149 fn test_list_enabled() {
150 let store = PersonaStore::new();
151 let mut p1 = Persona::new("A", "dev", "Desc A", "Prompt A");
152 p1.enabled = true;
153 let mut p2 = Persona::new("B", "dev", "Desc B", "Prompt B");
154 p2.enabled = false;
155 store.register(p1);
156 store.register(p2);
157
158 let enabled = store.list_enabled();
159 assert_eq!(enabled.len(), 1);
160 assert_eq!(enabled[0].name, "A");
161 }
162
163 #[test]
164 fn test_set_enabled() {
165 let store = PersonaStore::new();
166 let persona = Persona::new("Test", "dev", "Desc", "Prompt");
167 store.register(persona.clone());
168 store.set_enabled(&persona.id, false).unwrap();
169 assert!(store.list_enabled().is_empty());
170
171 store.set_enabled(&persona.id, true).unwrap();
172 assert_eq!(store.list_enabled().len(), 1);
173 }
174
175 #[test]
176 fn test_delete() {
177 let store = PersonaStore::new();
178 let persona = Persona::new("Test", "dev", "Desc", "Prompt");
179 let id = persona.id.clone();
180 store.register(persona);
181 store.delete(&id).unwrap();
182 assert!(store.get(&id).is_none());
183 }
184}