1use std::fmt;
7
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
24pub struct CollectiveId(pub Uuid);
25
26impl CollectiveId {
27 #[inline]
29 pub fn new() -> Self {
30 Self(Uuid::now_v7())
31 }
32
33 #[inline]
36 pub fn nil() -> Self {
37 Self(Uuid::nil())
38 }
39
40 #[inline]
42 pub fn as_bytes(&self) -> &[u8; 16] {
43 self.0.as_bytes()
44 }
45
46 #[inline]
48 pub fn from_bytes(bytes: [u8; 16]) -> Self {
49 Self(Uuid::from_bytes(bytes))
50 }
51}
52
53impl Default for CollectiveId {
54 fn default() -> Self {
58 Self::nil()
59 }
60}
61
62impl fmt::Display for CollectiveId {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "{}", self.0)
65 }
66}
67
68#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
73pub struct ExperienceId(pub Uuid);
74
75impl ExperienceId {
76 #[inline]
78 pub fn new() -> Self {
79 Self(Uuid::now_v7())
80 }
81
82 #[inline]
84 pub fn nil() -> Self {
85 Self(Uuid::nil())
86 }
87
88 #[inline]
90 pub fn as_bytes(&self) -> &[u8; 16] {
91 self.0.as_bytes()
92 }
93
94 #[inline]
96 pub fn from_bytes(bytes: [u8; 16]) -> Self {
97 Self(Uuid::from_bytes(bytes))
98 }
99}
100
101impl Default for ExperienceId {
102 fn default() -> Self {
106 Self::nil()
107 }
108}
109
110impl fmt::Display for ExperienceId {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "{}", self.0)
113 }
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
122pub struct InstanceId(pub Uuid);
123
124impl InstanceId {
125 #[inline]
127 pub fn new() -> Self {
128 Self(Uuid::now_v7())
129 }
130
131 #[inline]
135 pub fn nil() -> Self {
136 Self(Uuid::nil())
137 }
138
139 #[inline]
141 pub fn as_bytes(&self) -> &[u8; 16] {
142 self.0.as_bytes()
143 }
144
145 #[inline]
147 pub fn from_bytes(bytes: [u8; 16]) -> Self {
148 Self(Uuid::from_bytes(bytes))
149 }
150}
151
152impl Default for InstanceId {
153 fn default() -> Self {
157 Self::nil()
158 }
159}
160
161impl fmt::Display for InstanceId {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 write!(f, "{}", self.0)
164 }
165}
166
167#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
172pub struct Timestamp(pub i64);
173
174impl Timestamp {
175 #[inline]
180 pub fn now() -> Self {
181 use std::time::{SystemTime, UNIX_EPOCH};
182 let duration = SystemTime::now()
183 .duration_since(UNIX_EPOCH)
184 .unwrap_or_default();
185 Self(duration.as_millis() as i64)
186 }
187
188 #[inline]
190 pub const fn from_millis(millis: i64) -> Self {
191 Self(millis)
192 }
193
194 #[inline]
196 pub const fn as_millis(&self) -> i64 {
197 self.0
198 }
199
200 #[inline]
202 pub fn to_be_bytes(&self) -> [u8; 8] {
203 self.0.to_be_bytes()
204 }
205}
206
207impl fmt::Display for Timestamp {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 write!(f, "{}", self.0)
210 }
211}
212
213#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
218pub struct RelationId(pub Uuid);
219
220impl RelationId {
221 #[inline]
223 pub fn new() -> Self {
224 Self(Uuid::now_v7())
225 }
226
227 #[inline]
229 pub fn nil() -> Self {
230 Self(Uuid::nil())
231 }
232
233 #[inline]
235 pub fn as_bytes(&self) -> &[u8; 16] {
236 self.0.as_bytes()
237 }
238
239 #[inline]
241 pub fn from_bytes(bytes: [u8; 16]) -> Self {
242 Self(Uuid::from_bytes(bytes))
243 }
244}
245
246impl Default for RelationId {
247 fn default() -> Self {
251 Self::nil()
252 }
253}
254
255impl fmt::Display for RelationId {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 write!(f, "{}", self.0)
258 }
259}
260
261#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
274pub struct InsightId(pub Uuid);
275
276impl InsightId {
277 #[inline]
279 pub fn new() -> Self {
280 Self(Uuid::now_v7())
281 }
282
283 #[inline]
285 pub fn nil() -> Self {
286 Self(Uuid::nil())
287 }
288
289 #[inline]
291 pub fn as_bytes(&self) -> &[u8; 16] {
292 self.0.as_bytes()
293 }
294
295 #[inline]
297 pub fn from_bytes(bytes: [u8; 16]) -> Self {
298 Self(Uuid::from_bytes(bytes))
299 }
300}
301
302impl Default for InsightId {
303 fn default() -> Self {
307 Self::nil()
308 }
309}
310
311impl fmt::Display for InsightId {
312 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 write!(f, "{}", self.0)
314 }
315}
316
317#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
322pub struct UserId(pub String);
323
324impl UserId {
325 pub fn new(id: impl Into<String>) -> Self {
327 Self(id.into())
328 }
329
330 pub fn as_str(&self) -> &str {
332 &self.0
333 }
334}
335
336impl fmt::Display for UserId {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 write!(f, "{}", self.0)
339 }
340}
341
342#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
347pub struct AgentId(pub String);
348
349impl AgentId {
350 pub fn new(id: impl Into<String>) -> Self {
352 Self(id.into())
353 }
354
355 pub fn as_str(&self) -> &str {
357 &self.0
358 }
359}
360
361impl fmt::Display for AgentId {
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 write!(f, "{}", self.0)
364 }
365}
366
367#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
372pub struct TaskId(pub String);
373
374impl TaskId {
375 pub fn new(id: impl Into<String>) -> Self {
377 Self(id.into())
378 }
379
380 pub fn as_str(&self) -> &str {
382 &self.0
383 }
384}
385
386impl fmt::Display for TaskId {
387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
388 write!(f, "{}", self.0)
389 }
390}
391
392pub type Embedding = Vec<f32>;
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_collective_id_new_is_unique() {
403 let id1 = CollectiveId::new();
404 let id2 = CollectiveId::new();
405 assert_ne!(id1, id2);
406 }
407
408 #[test]
409 fn test_collective_id_nil() {
410 let id = CollectiveId::nil();
411 assert_eq!(id.0, Uuid::nil());
412 }
413
414 #[test]
415 fn test_collective_id_bytes_roundtrip() {
416 let id = CollectiveId::new();
417 let bytes = *id.as_bytes();
418 let restored = CollectiveId::from_bytes(bytes);
419 assert_eq!(id, restored);
420 }
421
422 #[test]
423 fn test_collective_id_serialization() {
424 let id = CollectiveId::new();
425 let bytes = postcard::to_stdvec(&id).unwrap();
426 let restored: CollectiveId = postcard::from_bytes(&bytes).unwrap();
427 assert_eq!(id, restored);
428 }
429
430 #[test]
431 fn test_experience_id_new_is_unique() {
432 let id1 = ExperienceId::new();
433 let id2 = ExperienceId::new();
434 assert_ne!(id1, id2);
435 }
436
437 #[test]
438 fn test_experience_id_serialization() {
439 let id = ExperienceId::new();
440 let bytes = postcard::to_stdvec(&id).unwrap();
441 let restored: ExperienceId = postcard::from_bytes(&bytes).unwrap();
442 assert_eq!(id, restored);
443 }
444
445 #[test]
446 fn test_relation_id_new_is_unique() {
447 let id1 = RelationId::new();
448 let id2 = RelationId::new();
449 assert_ne!(id1, id2);
450 }
451
452 #[test]
453 fn test_relation_id_nil() {
454 let id = RelationId::nil();
455 assert_eq!(id.0, Uuid::nil());
456 }
457
458 #[test]
459 fn test_relation_id_bytes_roundtrip() {
460 let id = RelationId::new();
461 let bytes = *id.as_bytes();
462 let restored = RelationId::from_bytes(bytes);
463 assert_eq!(id, restored);
464 }
465
466 #[test]
467 fn test_relation_id_serialization() {
468 let id = RelationId::new();
469 let bytes = postcard::to_stdvec(&id).unwrap();
470 let restored: RelationId = postcard::from_bytes(&bytes).unwrap();
471 assert_eq!(id, restored);
472 }
473
474 #[test]
475 fn test_insight_id_new_is_unique() {
476 let id1 = InsightId::new();
477 let id2 = InsightId::new();
478 assert_ne!(id1, id2);
479 }
480
481 #[test]
482 fn test_insight_id_nil() {
483 let id = InsightId::nil();
484 assert_eq!(id.0, Uuid::nil());
485 }
486
487 #[test]
488 fn test_insight_id_bytes_roundtrip() {
489 let id = InsightId::new();
490 let bytes = *id.as_bytes();
491 let restored = InsightId::from_bytes(bytes);
492 assert_eq!(id, restored);
493 }
494
495 #[test]
496 fn test_insight_id_serialization() {
497 let id = InsightId::new();
498 let bytes = postcard::to_stdvec(&id).unwrap();
499 let restored: InsightId = postcard::from_bytes(&bytes).unwrap();
500 assert_eq!(id, restored);
501 }
502
503 #[test]
504 fn test_timestamp_now() {
505 let t1 = Timestamp::now();
506 std::thread::sleep(std::time::Duration::from_millis(1));
507 let t2 = Timestamp::now();
508 assert!(t1 < t2, "Timestamps should be ordered");
509 }
510
511 #[test]
512 fn test_timestamp_ordering() {
513 let t1 = Timestamp::from_millis(1000);
514 let t2 = Timestamp::from_millis(2000);
515 assert!(t1 < t2);
516 }
517
518 #[test]
519 fn test_timestamp_be_bytes() {
520 let t1 = Timestamp::from_millis(100);
522 let t2 = Timestamp::from_millis(200);
523 assert!(t1.to_be_bytes() < t2.to_be_bytes());
524 }
525
526 #[test]
527 fn test_user_id() {
528 let id = UserId::new("user-123");
529 assert_eq!(id.as_str(), "user-123");
530 assert_eq!(format!("{}", id), "user-123");
531 }
532
533 #[test]
534 fn test_agent_id() {
535 let id = AgentId::new("claude-opus");
536 assert_eq!(id.as_str(), "claude-opus");
537 }
538
539 #[test]
540 fn test_task_id() {
541 let id = TaskId::new("task-456");
542 assert_eq!(id.as_str(), "task-456");
543 }
544}