use semver::Version;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Frontmatter {
pub name: String,
pub version: Version,
pub description: String,
#[serde(default)]
pub authors: Vec<String>,
#[serde(default = "default_license")]
pub license: String,
#[serde(default)]
pub runtime: RuntimeRequirement,
#[serde(default)]
pub inputs: Vec<InputSpec>,
#[serde(default)]
pub outputs: Option<OutputSpec>,
#[serde(default)]
pub dependencies: Dependencies,
#[serde(default)]
pub permissions: Permissions,
#[serde(default)]
pub tags: Vec<String>,
#[serde(flatten)]
pub extra: BTreeMap<String, serde_yaml::Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RuntimeRequirement {
#[serde(rename = "type", default = "default_runtime_type")]
pub kind: String,
#[serde(default)]
pub min_version: Option<Version>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputSpec {
pub name: String,
#[serde(rename = "type")]
pub kind: InputKind,
#[serde(default)]
pub required: bool,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub default: Option<serde_yaml::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum InputKind {
String,
Number,
Boolean,
File,
Url,
Json,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OutputSpec {
#[serde(rename = "type")]
pub kind: OutputKind,
#[serde(default)]
pub schema: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OutputKind {
Text,
Json,
File,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Dependencies {
#[serde(default, rename = "mcp-servers")]
pub mcp_servers: Vec<String>,
#[serde(default)]
pub skills: Vec<String>,
#[serde(default)]
pub tools: Vec<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Permissions {
#[serde(default)]
pub network: Vec<String>,
#[serde(default)]
pub filesystem: Vec<String>,
#[serde(default)]
pub env: Vec<String>,
}
fn default_license() -> String {
"UNLICENSED".to_string()
}
fn default_runtime_type() -> String {
"markdown-skill".to_string()
}