use serde::{Deserialize, Serialize};
use uuid::Uuid;
macro_rules! define_id {
($name:ident) => {
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct $name(pub String);
impl $name {
pub fn generate() -> Self {
Self(Uuid::new_v4().to_string())
}
}
impl From<&str> for $name {
fn from(value: &str) -> Self {
Self(value.to_string())
}
}
impl From<String> for $name {
fn from(value: String) -> Self {
Self(value)
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
};
}
define_id!(SessionId);
define_id!(BranchId);
define_id!(RunId);
define_id!(TurnId);
define_id!(EntryId);
define_id!(ToolCallId);
define_id!(ProviderId);
define_id!(ModelId);
impl ProviderId {
pub const OPENAI: &'static str = "openai";
pub const OPENAI_COMPATIBLE: &'static str = "openai-compatible";
pub const ANTHROPIC: &'static str = "anthropic";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn generated_ids_are_unique() {
assert_ne!(SessionId::generate(), SessionId::generate());
}
#[test]
fn ids_roundtrip_through_serde() {
let id = RunId::from("run-123");
let json = serde_json::to_string(&id).unwrap();
assert_eq!(json, "\"run-123\"");
let back: RunId = serde_json::from_str(&json).unwrap();
assert_eq!(back, id);
}
#[test]
fn ids_convert_from_str_and_string() {
let a: BranchId = "b1".into();
let b: BranchId = String::from("b2").into();
assert_eq!(a.as_ref(), "b1");
assert_eq!(b.to_string(), "b2");
}
#[test]
fn provider_constants_match_spec() {
assert_eq!(ProviderId::OPENAI, "openai");
assert_eq!(ProviderId::OPENAI_COMPATIBLE, "openai-compatible");
assert_eq!(ProviderId::ANTHROPIC, "anthropic");
}
}