1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
8#[serde(rename_all = "lowercase")]
9pub enum MemoryTier {
10 Working,
12 Episodic,
14 Semantic,
17 Persona,
20}
21
22impl MemoryTier {
23 #[must_use]
34 pub fn as_str(self) -> &'static str {
35 match self {
36 Self::Working => "working",
37 Self::Episodic => "episodic",
38 Self::Semantic => "semantic",
39 Self::Persona => "persona",
40 }
41 }
42}
43
44impl std::fmt::Display for MemoryTier {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 f.write_str(self.as_str())
47 }
48}
49
50impl std::str::FromStr for MemoryTier {
51 type Err = String;
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s {
54 "working" => Ok(Self::Working),
55 "episodic" => Ok(Self::Episodic),
56 "semantic" => Ok(Self::Semantic),
57 "persona" => Ok(Self::Persona),
58 other => Err(format!("unknown memory tier: {other}")),
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
77#[sqlx(transparent)]
78pub struct ConversationId(pub i64);
79
80impl std::fmt::Display for ConversationId {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 write!(f, "{}", self.0)
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
100#[sqlx(transparent)]
101pub struct MessageId(pub i64);
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
117#[sqlx(transparent)]
118pub struct MemSceneId(pub i64);
119
120impl std::fmt::Display for MemSceneId {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 write!(f, "{}", self.0)
123 }
124}
125
126impl std::fmt::Display for MessageId {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 write!(f, "{}", self.0)
129 }
130}
131
132#[derive(
146 Debug,
147 Clone,
148 Copy,
149 PartialEq,
150 Eq,
151 PartialOrd,
152 Ord,
153 Hash,
154 sqlx::Type,
155 serde::Serialize,
156 serde::Deserialize,
157)]
158#[sqlx(transparent)]
159pub struct ExperienceId(pub i64);
160
161impl std::fmt::Display for ExperienceId {
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 write!(f, "{}", self.0)
164 }
165}
166
167#[derive(
181 Debug,
182 Clone,
183 Copy,
184 PartialEq,
185 Eq,
186 PartialOrd,
187 Ord,
188 Hash,
189 sqlx::Type,
190 serde::Serialize,
191 serde::Deserialize,
192)]
193#[sqlx(transparent)]
194pub struct EntityId(pub i64);
195
196impl std::fmt::Display for EntityId {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 write!(f, "{}", self.0)
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn memory_tier_round_trip() {
208 for tier in [
209 MemoryTier::Working,
210 MemoryTier::Episodic,
211 MemoryTier::Semantic,
212 MemoryTier::Persona,
213 ] {
214 let s = tier.as_str();
215 let parsed: MemoryTier = s.parse().expect("should parse");
216 assert_eq!(parsed, tier);
217 assert_eq!(format!("{tier}"), s);
218 }
219 }
220
221 #[test]
222 fn memory_tier_unknown_string_errors() {
223 assert!("unknown".parse::<MemoryTier>().is_err());
224 }
225
226 #[test]
227 fn memory_tier_serde_round_trip() {
228 let json = serde_json::to_string(&MemoryTier::Semantic).unwrap();
229 assert_eq!(json, "\"semantic\"");
230 let parsed: MemoryTier = serde_json::from_str(&json).unwrap();
231 assert_eq!(parsed, MemoryTier::Semantic);
232 }
233
234 #[test]
235 fn conversation_id_display() {
236 let id = ConversationId(42);
237 assert_eq!(format!("{id}"), "42");
238 }
239
240 #[test]
241 fn message_id_display() {
242 let id = MessageId(7);
243 assert_eq!(format!("{id}"), "7");
244 }
245
246 #[test]
247 fn conversation_id_eq() {
248 assert_eq!(ConversationId(1), ConversationId(1));
249 assert_ne!(ConversationId(1), ConversationId(2));
250 }
251
252 #[test]
253 fn message_id_copy() {
254 let id = MessageId(5);
255 let copied = id;
256 assert_eq!(id, copied);
257 }
258
259 #[test]
260 fn experience_id_display() {
261 let id = ExperienceId(10);
262 assert_eq!(format!("{id}"), "10");
263 }
264
265 #[test]
266 fn entity_id_display() {
267 let id = EntityId(5);
268 assert_eq!(format!("{id}"), "5");
269 }
270
271 #[test]
272 fn experience_id_ord() {
273 assert!(ExperienceId(1) < ExperienceId(2));
274 assert_eq!(ExperienceId(3), ExperienceId(3));
275 }
276
277 #[test]
278 fn entity_id_hash() {
279 use std::collections::HashSet;
280 let mut set = HashSet::new();
281 set.insert(EntityId(1));
282 set.insert(EntityId(2));
283 set.insert(EntityId(1));
284 assert_eq!(set.len(), 2);
285 }
286}