Skip to main content

agent_first_http/sdk/profile/
meta.rs

1//! `afhttp-profile.json` metadata file schema (architecture.md §7).
2
3use std::time::SystemTime;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct ProfileMeta {
9    pub schema_version: u32,
10    pub name: String,
11    pub created_at_rfc3339: String,
12    pub last_used_at_rfc3339: String,
13    pub last_host_version: String,
14}
15
16impl ProfileMeta {
17    pub const SCHEMA_VERSION: u32 = 1;
18
19    pub fn new(name: impl Into<String>) -> Self {
20        let now = now_rfc3339();
21        Self {
22            schema_version: Self::SCHEMA_VERSION,
23            name: name.into(),
24            created_at_rfc3339: now.clone(),
25            last_used_at_rfc3339: now,
26            last_host_version: env!("CARGO_PKG_VERSION").to_string(),
27        }
28    }
29}
30
31/// Current UTC time as a second-precision RFC3339 string (`YYYY-MM-DDTHH:MM:SSZ`).
32pub fn now_rfc3339() -> String {
33    humantime::format_rfc3339_seconds(SystemTime::now()).to_string()
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn now_rfc3339_is_second_precision_utc() {
42        let s = now_rfc3339();
43        assert!(s.ends_with('Z'));
44        assert_eq!(s.len(), 20); // YYYY-MM-DDTHH:MM:SSZ
45    }
46
47    #[test]
48    fn meta_round_trips_through_json() {
49        let m = ProfileMeta::new("work");
50        let s = serde_json::to_string(&m).unwrap_or_default();
51        let back: ProfileMeta = serde_json::from_str(&s).unwrap();
52        assert_eq!(back.name, "work");
53        assert_eq!(back.schema_version, ProfileMeta::SCHEMA_VERSION);
54    }
55}