use std::fmt;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct CollectiveId(pub Uuid);
impl CollectiveId {
#[inline]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
#[inline]
pub fn nil() -> Self {
Self(Uuid::nil())
}
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
}
impl Default for CollectiveId {
fn default() -> Self {
Self::nil()
}
}
impl fmt::Display for CollectiveId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ExperienceId(pub Uuid);
impl ExperienceId {
#[inline]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
#[inline]
pub fn nil() -> Self {
Self(Uuid::nil())
}
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
}
impl Default for ExperienceId {
fn default() -> Self {
Self::nil()
}
}
impl fmt::Display for ExperienceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct InstanceId(pub Uuid);
impl InstanceId {
#[inline]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
#[inline]
pub fn nil() -> Self {
Self(Uuid::nil())
}
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
}
impl Default for InstanceId {
fn default() -> Self {
Self::nil()
}
}
impl fmt::Display for InstanceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Timestamp(pub i64);
impl Timestamp {
#[inline]
pub fn now() -> Self {
use std::time::{SystemTime, UNIX_EPOCH};
let duration = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
Self(duration.as_millis() as i64)
}
#[inline]
pub const fn from_millis(millis: i64) -> Self {
Self(millis)
}
#[inline]
pub const fn as_millis(&self) -> i64 {
self.0
}
#[inline]
pub fn to_be_bytes(&self) -> [u8; 8] {
self.0.to_be_bytes()
}
}
impl fmt::Display for Timestamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct RelationId(pub Uuid);
impl RelationId {
#[inline]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
#[inline]
pub fn nil() -> Self {
Self(Uuid::nil())
}
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
}
impl Default for RelationId {
fn default() -> Self {
Self::nil()
}
}
impl fmt::Display for RelationId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct InsightId(pub Uuid);
impl InsightId {
#[inline]
pub fn new() -> Self {
Self(Uuid::now_v7())
}
#[inline]
pub fn nil() -> Self {
Self(Uuid::nil())
}
#[inline]
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
}
impl Default for InsightId {
fn default() -> Self {
Self::nil()
}
}
impl fmt::Display for InsightId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct UserId(pub String);
impl UserId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for UserId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct AgentId(pub String);
impl AgentId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for AgentId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TaskId(pub String);
impl TaskId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for TaskId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
pub type Embedding = Vec<f32>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_collective_id_new_is_unique() {
let id1 = CollectiveId::new();
let id2 = CollectiveId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_collective_id_nil() {
let id = CollectiveId::nil();
assert_eq!(id.0, Uuid::nil());
}
#[test]
fn test_collective_id_bytes_roundtrip() {
let id = CollectiveId::new();
let bytes = *id.as_bytes();
let restored = CollectiveId::from_bytes(bytes);
assert_eq!(id, restored);
}
#[test]
fn test_collective_id_serialization() {
let id = CollectiveId::new();
let bytes = postcard::to_stdvec(&id).unwrap();
let restored: CollectiveId = postcard::from_bytes(&bytes).unwrap();
assert_eq!(id, restored);
}
#[test]
fn test_experience_id_new_is_unique() {
let id1 = ExperienceId::new();
let id2 = ExperienceId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_experience_id_serialization() {
let id = ExperienceId::new();
let bytes = postcard::to_stdvec(&id).unwrap();
let restored: ExperienceId = postcard::from_bytes(&bytes).unwrap();
assert_eq!(id, restored);
}
#[test]
fn test_relation_id_new_is_unique() {
let id1 = RelationId::new();
let id2 = RelationId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_relation_id_nil() {
let id = RelationId::nil();
assert_eq!(id.0, Uuid::nil());
}
#[test]
fn test_relation_id_bytes_roundtrip() {
let id = RelationId::new();
let bytes = *id.as_bytes();
let restored = RelationId::from_bytes(bytes);
assert_eq!(id, restored);
}
#[test]
fn test_relation_id_serialization() {
let id = RelationId::new();
let bytes = postcard::to_stdvec(&id).unwrap();
let restored: RelationId = postcard::from_bytes(&bytes).unwrap();
assert_eq!(id, restored);
}
#[test]
fn test_insight_id_new_is_unique() {
let id1 = InsightId::new();
let id2 = InsightId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_insight_id_nil() {
let id = InsightId::nil();
assert_eq!(id.0, Uuid::nil());
}
#[test]
fn test_insight_id_bytes_roundtrip() {
let id = InsightId::new();
let bytes = *id.as_bytes();
let restored = InsightId::from_bytes(bytes);
assert_eq!(id, restored);
}
#[test]
fn test_insight_id_serialization() {
let id = InsightId::new();
let bytes = postcard::to_stdvec(&id).unwrap();
let restored: InsightId = postcard::from_bytes(&bytes).unwrap();
assert_eq!(id, restored);
}
#[test]
fn test_timestamp_now() {
let t1 = Timestamp::now();
std::thread::sleep(std::time::Duration::from_millis(1));
let t2 = Timestamp::now();
assert!(t1 < t2, "Timestamps should be ordered");
}
#[test]
fn test_timestamp_ordering() {
let t1 = Timestamp::from_millis(1000);
let t2 = Timestamp::from_millis(2000);
assert!(t1 < t2);
}
#[test]
fn test_timestamp_be_bytes() {
let t1 = Timestamp::from_millis(100);
let t2 = Timestamp::from_millis(200);
assert!(t1.to_be_bytes() < t2.to_be_bytes());
}
#[test]
fn test_user_id() {
let id = UserId::new("user-123");
assert_eq!(id.as_str(), "user-123");
assert_eq!(format!("{}", id), "user-123");
}
#[test]
fn test_agent_id() {
let id = AgentId::new("claude-opus");
assert_eq!(id.as_str(), "claude-opus");
}
#[test]
fn test_task_id() {
let id = TaskId::new("task-456");
assert_eq!(id.as_str(), "task-456");
}
}