Skip to main content

oharness_core/
ids.rs

1//! Identifier newtypes (ยง4.1).
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5use uuid::Uuid;
6
7/// Identifies a single agent run. UUIDs are chosen for collision-freedom across concurrent
8/// runs writing to the same output directory.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(transparent)]
11pub struct RunId(pub Uuid);
12
13#[cfg(feature = "schemars-export")]
14impl schemars::JsonSchema for RunId {
15    fn schema_name() -> String {
16        "RunId".into()
17    }
18    fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
19        // UUID v4, rendered as the canonical 36-char hex form.
20        schemars::schema::SchemaObject {
21            instance_type: Some(schemars::schema::InstanceType::String.into()),
22            format: Some("uuid".into()),
23            ..Default::default()
24        }
25        .into()
26    }
27}
28
29impl RunId {
30    pub fn new() -> Self {
31        Self(Uuid::new_v4())
32    }
33}
34
35impl Default for RunId {
36    fn default() -> Self {
37        Self::new()
38    }
39}
40
41impl fmt::Display for RunId {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        self.0.fmt(f)
44    }
45}
46
47/// Identifies a span (open/close event pair). Strings rather than UUIDs because they
48/// are meant to be human-readable: `llm-0`, `tool-3`, `run-0`.
49#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
50#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
51#[cfg_attr(feature = "schemars-export", schemars(transparent))]
52#[serde(transparent)]
53pub struct SpanId(pub String);
54
55impl SpanId {
56    pub fn new(s: impl Into<String>) -> Self {
57        Self(s.into())
58    }
59}
60
61impl fmt::Display for SpanId {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        self.0.fmt(f)
64    }
65}
66
67impl From<&str> for SpanId {
68    fn from(s: &str) -> Self {
69        Self(s.to_string())
70    }
71}
72
73impl From<String> for SpanId {
74    fn from(s: String) -> Self {
75        Self(s)
76    }
77}
78
79impl From<&String> for SpanId {
80    fn from(s: &String) -> Self {
81        Self(s.clone())
82    }
83}
84
85/// Provider-qualified model identifier, e.g. `anthropic/claude-opus-4-7`.
86#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
87#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
88#[cfg_attr(feature = "schemars-export", schemars(transparent))]
89#[serde(transparent)]
90pub struct ModelId(pub String);
91
92impl ModelId {
93    pub fn new(s: impl Into<String>) -> Self {
94        Self(s.into())
95    }
96
97    pub fn as_str(&self) -> &str {
98        &self.0
99    }
100}
101
102impl fmt::Display for ModelId {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        self.0.fmt(f)
105    }
106}
107
108impl From<&str> for ModelId {
109    fn from(s: &str) -> Self {
110        Self(s.to_string())
111    }
112}
113
114impl From<String> for ModelId {
115    fn from(s: String) -> Self {
116        Self(s)
117    }
118}