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)]
181#[serde(rename_all = "snake_case")]
182#[non_exhaustive]
183pub enum InputKind {
184 Prompt,
186 PeerMessage,
188 PeerRequest,
190 PeerResponseProgress,
192 PeerResponseTerminal,
194 FlowStep,
196 ExternalEvent,
198 Continuation,
200 Operation,
202}
203
204impl InputKind {
205 pub fn as_str(self) -> &'static str {
208 match self {
209 InputKind::Prompt => "prompt",
210 InputKind::PeerMessage => "peer_message",
211 InputKind::PeerRequest => "peer_request",
212 InputKind::PeerResponseProgress => "peer_response_progress",
213 InputKind::PeerResponseTerminal => "peer_response_terminal",
214 InputKind::FlowStep => "flow_step",
215 InputKind::ExternalEvent => "external_event",
216 InputKind::Continuation => "continuation",
217 InputKind::Operation => "operation",
218 }
219 }
220}
221
222impl std::fmt::Display for InputKind {
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 f.write_str(self.as_str())
225 }
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
230pub struct KindId(pub InputKind);
231
232impl KindId {
233 pub const fn new(kind: InputKind) -> Self {
234 Self(kind)
235 }
236
237 pub const fn kind(self) -> InputKind {
238 self.0
239 }
240}
241
242impl From<InputKind> for KindId {
243 fn from(kind: InputKind) -> Self {
244 Self(kind)
245 }
246}
247
248impl std::fmt::Display for KindId {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 std::fmt::Display::fmt(&self.0, f)
251 }
252}
253
254#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
256pub struct SchemaId(pub String);
257
258impl SchemaId {
259 pub fn new(id: impl Into<String>) -> Self {
260 Self(id.into())
261 }
262}
263
264impl std::fmt::Display for SchemaId {
265 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 write!(f, "{}", self.0)
267 }
268}
269
270#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
272pub struct ProjectionRuleId(pub String);
273
274impl ProjectionRuleId {
275 pub fn new(id: impl Into<String>) -> Self {
276 Self(id.into())
277 }
278}
279
280impl std::fmt::Display for ProjectionRuleId {
281 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
282 write!(f, "{}", self.0)
283 }
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
288pub struct EventCodeId(pub String);
289
290impl EventCodeId {
291 pub fn new(id: impl Into<String>) -> Self {
292 Self(id.into())
293 }
294}
295
296impl std::fmt::Display for EventCodeId {
297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298 write!(f, "{}", self.0)
299 }
300}
301
302#[cfg(test)]
303#[allow(clippy::unwrap_used)]
304mod tests {
305 use super::*;
306
307 #[test]
308 fn runtime_event_id_unique() {
309 let a = RuntimeEventId::new();
310 let b = RuntimeEventId::new();
311 assert_ne!(a, b);
312 }
313
314 #[test]
315 fn runtime_event_id_serde() {
316 let id = RuntimeEventId::new();
317 let json = serde_json::to_string(&id).unwrap();
318 let parsed: RuntimeEventId = serde_json::from_str(&json).unwrap();
319 assert_eq!(id, parsed);
320 }
321
322 #[test]
323 fn logical_runtime_id_serde() {
324 let id = LogicalRuntimeId::new("agent-1");
325 let json = serde_json::to_string(&id).unwrap();
326 let parsed: LogicalRuntimeId = serde_json::from_str(&json).unwrap();
327 assert_eq!(id, parsed);
328 assert_eq!(id.to_string(), "agent-1");
329 }
330
331 #[test]
332 fn conversation_id_unique() {
333 let a = ConversationId::new();
334 let b = ConversationId::new();
335 assert_ne!(a, b);
336 }
337
338 #[test]
339 fn idempotency_key_serde() {
340 let key = IdempotencyKey::new("req-abc-123");
341 let json = serde_json::to_string(&key).unwrap();
342 let parsed: IdempotencyKey = serde_json::from_str(&json).unwrap();
343 assert_eq!(key, parsed);
344 }
345
346 #[test]
347 fn supersession_key_serde() {
348 let key = SupersessionKey::new("peer-status");
349 let json = serde_json::to_string(&key).unwrap();
350 let parsed: SupersessionKey = serde_json::from_str(&json).unwrap();
351 assert_eq!(key, parsed);
352 }
353
354 #[test]
355 fn policy_version_serde() {
356 let v = PolicyVersion(42);
357 let json = serde_json::to_string(&v).unwrap();
358 let parsed: PolicyVersion = serde_json::from_str(&json).unwrap();
359 assert_eq!(v, parsed);
360 }
361
362 #[test]
363 fn kind_id_display() {
364 let id = KindId::new(InputKind::Prompt);
365 assert_eq!(id.to_string(), "prompt");
366 assert_eq!(
367 KindId::new(InputKind::PeerResponseProgress).to_string(),
368 "peer_response_progress"
369 );
370 }
371
372 #[test]
373 fn kind_id_serde_roundtrips_typed_variant() {
374 let id = KindId::new(InputKind::PeerResponseTerminal);
375 let json = serde_json::to_string(&id).unwrap();
376 let parsed: KindId = serde_json::from_str(&json).unwrap();
377 assert_eq!(id, parsed);
378 }
379}