systemprompt_identifiers/
client_session.rs1use crate::error::IdValidationError;
17
18const SESSION_SEGMENT: &str = "_session_";
19
20fn validate(value: &str) -> Result<(), IdValidationError> {
21 let parsed = uuid::Uuid::parse_str(value)
22 .map_err(|e| IdValidationError::invalid("ClientSessionId", e.to_string()))?;
23 if parsed.hyphenated().to_string() != value {
24 return Err(IdValidationError::invalid(
25 "ClientSessionId",
26 "must be a lowercase hyphenated UUID",
27 ));
28 }
29 Ok(())
30}
31
32crate::define_id!(ClientSessionId, validated, schema, validate);
33
34impl ClientSessionId {
35 pub fn from_metadata_user_id(value: &str) -> Result<Option<Self>, IdValidationError> {
36 let value = value.trim();
37 let session = if value.starts_with('{') {
38 let metadata: serde_json::Value = serde_json::from_str(value)
39 .map_err(|e| IdValidationError::invalid("ClientSessionId", e.to_string()))?;
40 Some(
41 metadata
42 .get("session_id")
43 .and_then(serde_json::Value::as_str)
44 .ok_or_else(|| {
45 IdValidationError::invalid(
46 "ClientSessionId",
47 "metadata requires a string session_id",
48 )
49 })?
50 .to_owned(),
51 )
52 } else {
53 value
54 .rsplit_once(SESSION_SEGMENT)
55 .map(|(_, suffix)| suffix.to_owned())
56 };
57 session
58 .map(|value| {
59 let parsed = uuid::Uuid::parse_str(value.trim())
60 .map_err(|e| IdValidationError::invalid("ClientSessionId", e.to_string()))?;
61 Self::try_new(parsed.hyphenated().to_string())
62 })
63 .transpose()
64 }
65}