1use std::collections::HashMap;
2
3use serde::{Deserialize, Deserializer, Serialize};
4
5use super::harness::{Harness, SourceType};
6use super::provider::Provider;
7
8fn null_to_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
13where
14 D: Deserializer<'de>,
15 T: Default + Deserialize<'de>,
16{
17 Ok(Option::<T>::deserialize(deserializer)?.unwrap_or_default())
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
22pub enum AgentType {
23 #[serde(rename = "agent")]
24 Agent,
25}
26
27impl std::fmt::Display for AgentType {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 match self {
30 AgentType::Agent => write!(f, "agent"),
31 }
32 }
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(rename_all = "kebab-case")]
38pub enum ExecutionTier {
39 StaticReview,
40 ReadOnlyRuntime,
41 MutatingRuntime,
42}
43
44impl std::fmt::Display for ExecutionTier {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 match self {
47 ExecutionTier::StaticReview => write!(f, "static-review"),
48 ExecutionTier::ReadOnlyRuntime => write!(f, "read-only-runtime"),
49 ExecutionTier::MutatingRuntime => write!(f, "mutating-runtime"),
50 }
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
56#[serde(rename_all = "kebab-case")]
57pub enum Lifecycle {
58 Experimental,
59 Beta,
60 Stable,
61 Deprecated,
62}
63
64impl std::fmt::Display for Lifecycle {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 Lifecycle::Experimental => write!(f, "experimental"),
68 Lifecycle::Beta => write!(f, "beta"),
69 Lifecycle::Stable => write!(f, "stable"),
70 Lifecycle::Deprecated => write!(f, "deprecated"),
71 }
72 }
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77#[serde(deny_unknown_fields)]
78pub struct Agent {
79 pub id: String,
80 pub name: String,
81 #[serde(rename = "type")]
82 pub entity_type: AgentType,
83 pub provider: Provider,
84 pub harnesses: Vec<Harness>,
85 pub summary: String,
86 pub source_type: SourceType,
87 pub official_docs: Vec<String>,
88 pub security_notes: String,
89 pub last_verified: String,
90 pub path: String,
91 #[serde(default, deserialize_with = "null_to_default")]
92 pub companion_skills: Vec<String>,
93 pub execution_tier: Option<ExecutionTier>,
94 pub lifecycle: Option<Lifecycle>,
95 #[serde(default)]
96 pub harness_variants: HashMap<String, String>,
97 pub author: Option<String>,
98 pub version: Option<String>,
99 #[serde(default)]
100 pub provider_coverage: Option<serde_json::Value>,
101}