1use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use meerkat_core::types::SessionId;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct RuntimeEventId(pub Uuid);
14
15impl RuntimeEventId {
16 pub fn new() -> Self {
17 Self(meerkat_core::time_compat::new_uuid_v7())
18 }
19}
20
21impl Default for RuntimeEventId {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl std::fmt::Display for RuntimeEventId {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "{}", self.0)
30 }
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
35pub struct LogicalRuntimeId(pub String);
36
37impl LogicalRuntimeId {
38 const SESSION_RUNTIME_PREFIX: &'static str = "rt:session:";
39
40 pub fn new(id: impl Into<String>) -> Self {
41 Self(id.into())
42 }
43
44 pub fn for_session(session_id: &SessionId) -> Self {
45 Self(format!("{}{session_id}", Self::SESSION_RUNTIME_PREFIX))
46 }
47
48 pub fn legacy_session_uuid_alias(session_id: &SessionId) -> Self {
49 Self(session_id.to_string())
50 }
51}
52
53impl std::fmt::Display for LogicalRuntimeId {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{}", self.0)
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
61pub struct ConversationId(pub Uuid);
62
63impl ConversationId {
64 pub fn new() -> Self {
65 Self(meerkat_core::time_compat::new_uuid_v7())
66 }
67}
68
69impl Default for ConversationId {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl std::fmt::Display for ConversationId {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{}", self.0)
78 }
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
83pub struct CausationId(pub Uuid);
84
85impl Default for CausationId {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl CausationId {
92 pub fn new() -> Self {
93 Self(meerkat_core::time_compat::new_uuid_v7())
94 }
95
96 pub fn from_uuid(uuid: Uuid) -> Self {
97 Self(uuid)
98 }
99}
100
101impl std::fmt::Display for CausationId {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 write!(f, "{}", self.0)
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
109pub struct CorrelationId(pub Uuid);
110
111impl Default for CorrelationId {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117impl CorrelationId {
118 pub fn new() -> Self {
119 Self(meerkat_core::time_compat::new_uuid_v7())
120 }
121
122 pub fn from_uuid(uuid: Uuid) -> Self {
123 Self(uuid)
124 }
125}
126
127impl std::fmt::Display for CorrelationId {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 write!(f, "{}", self.0)
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
135pub struct IdempotencyKey(pub String);
136
137impl IdempotencyKey {
138 pub fn new(key: impl Into<String>) -> Self {
139 Self(key.into())
140 }
141}
142
143impl std::fmt::Display for IdempotencyKey {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "{}", self.0)
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
151pub struct SupersessionKey(pub String);
152
153impl SupersessionKey {
154 pub fn new(key: impl Into<String>) -> Self {
155 Self(key.into())
156 }
157}
158
159impl std::fmt::Display for SupersessionKey {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 write!(f, "{}", self.0)
162 }
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
167pub struct PolicyVersion(pub u64);
168
169impl std::fmt::Display for PolicyVersion {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 write!(f, "{}", self.0)
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
182#[serde(rename_all = "snake_case")]
183#[non_exhaustive]
184pub enum InputKind {
185 Prompt,
187 PeerMessage,
189 PeerRequest,
191 PeerResponseProgress,
193 PeerResponseTerminal,
195 FlowStep,
197 ExternalEvent,
199 Continuation,
201 Operation,
203}
204
205impl InputKind {
206 pub fn as_str(self) -> &'static str {
209 match self {
210 InputKind::Prompt => "prompt",
211 InputKind::PeerMessage => "peer_message",
212 InputKind::PeerRequest => "peer_request",
213 InputKind::PeerResponseProgress => "peer_response_progress",
214 InputKind::PeerResponseTerminal => "peer_response_terminal",
215 InputKind::FlowStep => "flow_step",
216 InputKind::ExternalEvent => "external_event",
217 InputKind::Continuation => "continuation",
218 InputKind::Operation => "operation",
219 }
220 }
221}
222
223impl std::fmt::Display for InputKind {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 f.write_str(self.as_str())
226 }
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
231pub struct KindId(pub InputKind);
232
233impl KindId {
234 pub const fn new(kind: InputKind) -> Self {
235 Self(kind)
236 }
237
238 pub const fn kind(self) -> InputKind {
239 self.0
240 }
241}
242
243impl From<InputKind> for KindId {
244 fn from(kind: InputKind) -> Self {
245 Self(kind)
246 }
247}
248
249impl std::fmt::Display for KindId {
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251 std::fmt::Display::fmt(&self.0, f)
252 }
253}
254
255#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
257pub struct SchemaId(pub String);
258
259impl SchemaId {
260 pub fn new(id: impl Into<String>) -> Self {
261 Self(id.into())
262 }
263}
264
265impl std::fmt::Display for SchemaId {
266 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267 write!(f, "{}", self.0)
268 }
269}
270
271#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
273pub struct ProjectionRuleId(pub String);
274
275impl ProjectionRuleId {
276 pub fn new(id: impl Into<String>) -> Self {
277 Self(id.into())
278 }
279}
280
281impl std::fmt::Display for ProjectionRuleId {
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 write!(f, "{}", self.0)
284 }
285}
286
287#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
289pub struct EventCodeId(pub String);
290
291impl EventCodeId {
292 pub fn new(id: impl Into<String>) -> Self {
293 Self(id.into())
294 }
295}
296
297impl std::fmt::Display for EventCodeId {
298 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299 write!(f, "{}", self.0)
300 }
301}
302
303#[cfg(test)]
304#[allow(clippy::unwrap_used)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn runtime_event_id_unique() {
310 let a = RuntimeEventId::new();
311 let b = RuntimeEventId::new();
312 assert_ne!(a, b);
313 }
314
315 #[test]
316 fn runtime_event_id_serde() {
317 let id = RuntimeEventId::new();
318 let json = serde_json::to_string(&id).unwrap();
319 let parsed: RuntimeEventId = serde_json::from_str(&json).unwrap();
320 assert_eq!(id, parsed);
321 }
322
323 #[test]
324 fn logical_runtime_id_serde() {
325 let id = LogicalRuntimeId::new("agent-1");
326 let json = serde_json::to_string(&id).unwrap();
327 let parsed: LogicalRuntimeId = serde_json::from_str(&json).unwrap();
328 assert_eq!(id, parsed);
329 assert_eq!(id.to_string(), "agent-1");
330 }
331
332 #[test]
333 fn conversation_id_unique() {
334 let a = ConversationId::new();
335 let b = ConversationId::new();
336 assert_ne!(a, b);
337 }
338
339 #[test]
340 fn idempotency_key_serde() {
341 let key = IdempotencyKey::new("req-abc-123");
342 let json = serde_json::to_string(&key).unwrap();
343 let parsed: IdempotencyKey = serde_json::from_str(&json).unwrap();
344 assert_eq!(key, parsed);
345 }
346
347 #[test]
348 fn supersession_key_serde() {
349 let key = SupersessionKey::new("peer-status");
350 let json = serde_json::to_string(&key).unwrap();
351 let parsed: SupersessionKey = serde_json::from_str(&json).unwrap();
352 assert_eq!(key, parsed);
353 }
354
355 #[test]
356 fn policy_version_serde() {
357 let v = PolicyVersion(42);
358 let json = serde_json::to_string(&v).unwrap();
359 let parsed: PolicyVersion = serde_json::from_str(&json).unwrap();
360 assert_eq!(v, parsed);
361 }
362
363 #[test]
364 fn kind_id_display() {
365 let id = KindId::new(InputKind::Prompt);
366 assert_eq!(id.to_string(), "prompt");
367 assert_eq!(
368 KindId::new(InputKind::PeerResponseProgress).to_string(),
369 "peer_response_progress"
370 );
371 }
372
373 #[test]
374 fn kind_id_serde_roundtrips_typed_variant() {
375 let id = KindId::new(InputKind::PeerResponseTerminal);
376 let json = serde_json::to_string(&id).unwrap();
377 let parsed: KindId = serde_json::from_str(&json).unwrap();
378 assert_eq!(id, parsed);
379 }
380}