1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum MemoryTier {
8 Working,
10 Episodic,
12 Semantic,
15 Persona,
18}
19
20impl MemoryTier {
21 #[must_use]
22 pub fn as_str(self) -> &'static str {
23 match self {
24 Self::Working => "working",
25 Self::Episodic => "episodic",
26 Self::Semantic => "semantic",
27 Self::Persona => "persona",
28 }
29 }
30}
31
32impl std::fmt::Display for MemoryTier {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.write_str(self.as_str())
35 }
36}
37
38impl std::str::FromStr for MemoryTier {
39 type Err = String;
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 match s {
42 "working" => Ok(Self::Working),
43 "episodic" => Ok(Self::Episodic),
44 "semantic" => Ok(Self::Semantic),
45 "persona" => Ok(Self::Persona),
46 other => Err(format!("unknown memory tier: {other}")),
47 }
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
53#[sqlx(transparent)]
54pub struct ConversationId(pub i64);
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
58#[sqlx(transparent)]
59pub struct MessageId(pub i64);
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type)]
63#[sqlx(transparent)]
64pub struct MemSceneId(pub i64);
65
66impl std::fmt::Display for MemSceneId {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 write!(f, "{}", self.0)
69 }
70}
71
72impl std::fmt::Display for ConversationId {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 write!(f, "{}", self.0)
75 }
76}
77
78impl std::fmt::Display for MessageId {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 write!(f, "{}", self.0)
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn memory_tier_round_trip() {
90 for tier in [
91 MemoryTier::Working,
92 MemoryTier::Episodic,
93 MemoryTier::Semantic,
94 MemoryTier::Persona,
95 ] {
96 let s = tier.as_str();
97 let parsed: MemoryTier = s.parse().expect("should parse");
98 assert_eq!(parsed, tier);
99 assert_eq!(format!("{tier}"), s);
100 }
101 }
102
103 #[test]
104 fn memory_tier_unknown_string_errors() {
105 assert!("unknown".parse::<MemoryTier>().is_err());
106 }
107
108 #[test]
109 fn memory_tier_serde_round_trip() {
110 let json = serde_json::to_string(&MemoryTier::Semantic).unwrap();
111 assert_eq!(json, "\"semantic\"");
112 let parsed: MemoryTier = serde_json::from_str(&json).unwrap();
113 assert_eq!(parsed, MemoryTier::Semantic);
114 }
115
116 #[test]
117 fn conversation_id_display() {
118 let id = ConversationId(42);
119 assert_eq!(format!("{id}"), "42");
120 }
121
122 #[test]
123 fn message_id_display() {
124 let id = MessageId(7);
125 assert_eq!(format!("{id}"), "7");
126 }
127
128 #[test]
129 fn conversation_id_eq() {
130 assert_eq!(ConversationId(1), ConversationId(1));
131 assert_ne!(ConversationId(1), ConversationId(2));
132 }
133
134 #[test]
135 fn message_id_copy() {
136 let id = MessageId(5);
137 let copied = id;
138 assert_eq!(id, copied);
139 }
140}