1use std::fmt;
8use std::str::FromStr;
9
10use crate::KitError;
11
12pub use crate::agent::AgentInfo;
13
14#[derive(Clone, Copy)]
15enum IdentityKind {
16 Agent,
17 Workspace,
18 Conversation,
19 Notification,
20}
21
22impl IdentityKind {
23 fn prefix(self) -> &'static str {
24 match self {
25 Self::Agent => "agent_",
26 Self::Workspace => "workspace_",
27 Self::Conversation => "conversation_",
28 Self::Notification => "notification_",
29 }
30 }
31}
32
33#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
34struct Identity {
35 canonical: String,
36}
37
38impl Identity {
39 fn new(kind: IdentityKind) -> Self {
40 Self {
41 canonical: format!("{}{}", kind.prefix(), uuid::Uuid::new_v4().simple()),
42 }
43 }
44
45 fn parse(kind: IdentityKind, value: String) -> Result<Self, KitError> {
46 let payload = value
47 .strip_prefix(kind.prefix())
48 .ok_or_else(|| KitError::invalid_input("Kit identity category is invalid"))?;
49 if payload.len() != 32
50 || !payload
51 .bytes()
52 .all(|byte| byte.is_ascii_digit() || matches!(byte, b'a'..=b'f'))
53 {
54 return Err(KitError::invalid_input(
55 "Kit identity canonical form is invalid",
56 ));
57 }
58 let parsed = uuid::Uuid::parse_str(payload)
59 .map_err(|_| KitError::invalid_input("Kit identity canonical form is invalid"))?;
60 if parsed.simple().to_string() != payload {
61 return Err(KitError::invalid_input(
62 "Kit identity canonical form is invalid",
63 ));
64 }
65 Ok(Self { canonical: value })
66 }
67
68 fn as_str(&self) -> &str {
69 &self.canonical
70 }
71}
72
73#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
84pub struct AgentId(Identity);
85
86impl AgentId {
87 pub(crate) fn new() -> Self {
88 Self(Identity::new(IdentityKind::Agent))
89 }
90
91 pub fn as_str(&self) -> &str {
102 self.0.as_str()
103 }
104}
105
106impl fmt::Display for AgentId {
107 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
108 formatter.write_str(self.as_str())
109 }
110}
111
112impl FromStr for AgentId {
113 type Err = KitError;
114
115 fn from_str(value: &str) -> Result<Self, Self::Err> {
116 Identity::parse(IdentityKind::Agent, value.to_owned()).map(Self)
117 }
118}
119
120impl serde::Serialize for AgentId {
121 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122 where
123 S: serde::Serializer,
124 {
125 serializer.serialize_str(self.as_str())
126 }
127}
128
129impl<'de> serde::Deserialize<'de> for AgentId {
130 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131 where
132 D: serde::Deserializer<'de>,
133 {
134 let value = <String as serde::Deserialize>::deserialize(deserializer)?;
135 Self::from_str(&value).map_err(serde::de::Error::custom)
136 }
137}
138
139#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
150pub struct WorkspaceId(Identity);
151
152impl WorkspaceId {
153 pub(crate) fn new() -> Self {
154 Self(Identity::new(IdentityKind::Workspace))
155 }
156
157 pub fn as_str(&self) -> &str {
168 self.0.as_str()
169 }
170}
171
172impl fmt::Display for WorkspaceId {
173 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
174 formatter.write_str(self.as_str())
175 }
176}
177
178impl FromStr for WorkspaceId {
179 type Err = KitError;
180
181 fn from_str(value: &str) -> Result<Self, Self::Err> {
182 Identity::parse(IdentityKind::Workspace, value.to_owned()).map(Self)
183 }
184}
185
186impl serde::Serialize for WorkspaceId {
187 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
188 where
189 S: serde::Serializer,
190 {
191 serializer.serialize_str(self.as_str())
192 }
193}
194
195impl<'de> serde::Deserialize<'de> for WorkspaceId {
196 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
197 where
198 D: serde::Deserializer<'de>,
199 {
200 let value = <String as serde::Deserialize>::deserialize(deserializer)?;
201 Self::from_str(&value).map_err(serde::de::Error::custom)
202 }
203}
204
205#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
216pub struct ConversationId(Identity);
217
218impl ConversationId {
219 pub(crate) fn new() -> Self {
220 Self(Identity::new(IdentityKind::Conversation))
221 }
222
223 pub fn as_str(&self) -> &str {
234 self.0.as_str()
235 }
236}
237
238impl fmt::Display for ConversationId {
239 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
240 formatter.write_str(self.as_str())
241 }
242}
243
244impl FromStr for ConversationId {
245 type Err = KitError;
246
247 fn from_str(value: &str) -> Result<Self, Self::Err> {
248 Identity::parse(IdentityKind::Conversation, value.to_owned()).map(Self)
249 }
250}
251
252impl serde::Serialize for ConversationId {
253 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
254 where
255 S: serde::Serializer,
256 {
257 serializer.serialize_str(self.as_str())
258 }
259}
260
261impl<'de> serde::Deserialize<'de> for ConversationId {
262 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
263 where
264 D: serde::Deserializer<'de>,
265 {
266 let value = <String as serde::Deserialize>::deserialize(deserializer)?;
267 Self::from_str(&value).map_err(serde::de::Error::custom)
268 }
269}
270
271#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
282pub struct NotificationId(Identity);
283
284impl NotificationId {
285 pub(crate) fn new() -> Self {
286 Self(Identity::new(IdentityKind::Notification))
287 }
288
289 pub fn as_str(&self) -> &str {
300 self.0.as_str()
301 }
302}
303
304impl fmt::Display for NotificationId {
305 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
306 formatter.write_str(self.as_str())
307 }
308}
309
310impl FromStr for NotificationId {
311 type Err = KitError;
312
313 fn from_str(value: &str) -> Result<Self, Self::Err> {
314 Identity::parse(IdentityKind::Notification, value.to_owned()).map(Self)
315 }
316}
317
318impl serde::Serialize for NotificationId {
319 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
320 where
321 S: serde::Serializer,
322 {
323 serializer.serialize_str(self.as_str())
324 }
325}
326
327impl<'de> serde::Deserialize<'de> for NotificationId {
328 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
329 where
330 D: serde::Deserializer<'de>,
331 {
332 let value = <String as serde::Deserialize>::deserialize(deserializer)?;
333 Self::from_str(&value).map_err(serde::de::Error::custom)
334 }
335}