use serde::{Deserialize, Serialize}; use serde_json::Value; use time::OffsetDateTime; use crate::ids::{AgentId, OperationId, WorkspaceId}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AgentStatus { Draft, Published, Archived, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Agent { pub id: AgentId, pub workspace_id: WorkspaceId, pub slug: String, pub display_name: String, pub description: String, pub status: AgentStatus, pub current_draft_version: u32, pub latest_published_version: Option, #[serde(with = "time::serde::rfc3339")] pub created_at: OffsetDateTime, #[serde(with = "time::serde::rfc3339")] pub updated_at: OffsetDateTime, #[serde(default, with = "time::serde::rfc3339::option")] pub published_at: Option, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct AgentVersion { pub agent_id: AgentId, pub version: u32, pub status: AgentStatus, pub instructions: Value, pub tool_selection_policy: Value, #[serde(with = "time::serde::rfc3339")] pub created_at: OffsetDateTime, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct AgentOperationBinding { pub operation_id: OperationId, pub operation_version: u32, pub tool_name: String, pub tool_title: String, pub tool_description_override: Option, pub enabled: bool, } #[cfg(test)] mod tests { use serde_json::json; use time::{OffsetDateTime, format_description::well_known::Rfc3339}; use super::{Agent, AgentStatus, AgentVersion}; use crate::ids::{AgentId, WorkspaceId}; #[test] fn agent_serializes_timestamps_as_rfc3339() { let agent = Agent { id: AgentId::new("agent_01"), workspace_id: WorkspaceId::new("ws_01"), slug: "triage".to_owned(), display_name: "Triage".to_owned(), description: "Triage agent".to_owned(), status: AgentStatus::Published, current_draft_version: 2, latest_published_version: Some(2), created_at: OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap(), updated_at: OffsetDateTime::parse("2026-03-25T12:05:00Z", &Rfc3339).unwrap(), published_at: Some(OffsetDateTime::parse("2026-03-25T12:10:00Z", &Rfc3339).unwrap()), }; let value = serde_json::to_value(&agent).unwrap(); assert_eq!(value["created_at"], json!("2026-03-25T12:00:00Z")); assert_eq!(value["updated_at"], json!("2026-03-25T12:05:00Z")); assert_eq!(value["published_at"], json!("2026-03-25T12:10:00Z")); } #[test] fn agent_version_deserializes_created_at_from_rfc3339() { let version: AgentVersion = serde_json::from_value(json!({ "agent_id": "agent_01", "version": 1, "status": "draft", "instructions": {"system": "triage"}, "tool_selection_policy": {"mode": "allow_list"}, "created_at": "2026-03-25T12:00:00Z" })) .unwrap(); assert_eq!( version.created_at, OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap() ); } }