use serde::{Deserialize, Serialize}; /// An AI agent entry managed through the developer tools. /// /// # Fields /// /// * `id` - Unique agent identifier /// * `name` - Human-readable agent name /// * `description` - What this agent does /// * `status` - Current running status label #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct AgentEntry { pub id: String, pub name: String, pub description: String, pub status: String, } /// A workflow/flow entry from the flow builder. /// /// # Fields /// /// * `id` - Unique flow identifier /// * `name` - Human-readable flow name /// * `node_count` - Number of nodes in the flow graph /// * `last_run` - ISO 8601 timestamp of the last execution #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct FlowEntry { pub id: String, pub name: String, pub node_count: u32, pub last_run: Option, } /// A single analytics metric for the developer dashboard. /// /// # Fields /// /// * `label` - Display name of the metric /// * `value` - Current value as a formatted string /// * `change_pct` - Percentage change from previous period (positive = increase) #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct AnalyticsMetric { pub label: String, pub value: String, pub change_pct: f64, } #[cfg(test)] mod tests { use super::*; use pretty_assertions::assert_eq; #[test] fn agent_entry_serde_round_trip() { let agent = AgentEntry { id: "a1".into(), name: "RAG Agent".into(), description: "Retrieval-augmented generation".into(), status: "running".into(), }; let json = serde_json::to_string(&agent).expect("serialize AgentEntry"); let back: AgentEntry = serde_json::from_str(&json).expect("deserialize AgentEntry"); assert_eq!(agent, back); } #[test] fn flow_entry_serde_round_trip() { let flow = FlowEntry { id: "f1".into(), name: "Data Pipeline".into(), node_count: 5, last_run: Some("2025-06-01T12:00:00Z".into()), }; let json = serde_json::to_string(&flow).expect("serialize FlowEntry"); let back: FlowEntry = serde_json::from_str(&json).expect("deserialize FlowEntry"); assert_eq!(flow, back); } #[test] fn flow_entry_with_none_last_run() { let flow = FlowEntry { id: "f2".into(), name: "New Flow".into(), node_count: 0, last_run: None, }; let json = serde_json::to_string(&flow).expect("serialize"); let back: FlowEntry = serde_json::from_str(&json).expect("deserialize"); assert_eq!(flow, back); assert_eq!(back.last_run, None); } #[test] fn analytics_metric_negative_change_pct() { let metric = AnalyticsMetric { label: "Latency".into(), value: "120ms".into(), change_pct: -15.5, }; let json = serde_json::to_string(&metric).expect("serialize AnalyticsMetric"); let back: AnalyticsMetric = serde_json::from_str(&json).expect("deserialize AnalyticsMetric"); assert_eq!(metric, back); assert!(back.change_pct < 0.0); } }