lowfat_plugin/
manifest.rs1use serde::Deserialize;
2
3#[derive(Debug, Deserialize)]
5pub struct PluginManifest {
6 pub plugin: PluginMeta,
7 #[serde(default)]
8 pub runtime: RuntimeConfig,
9 pub hooks: Option<HooksConfig>,
10 pub pipeline: Option<PipelineConfig>,
11}
12
13#[derive(Debug, Deserialize)]
14pub struct PluginMeta {
15 pub name: String,
16 pub version: Option<String>,
17 pub description: Option<String>,
18 pub author: Option<String>,
19 pub category: Option<String>,
20 pub commands: Vec<String>,
22 pub subcommands: Option<Vec<String>>,
24}
25
26#[derive(Debug, Deserialize)]
27pub struct RuntimeConfig {
28 #[serde(default = "default_entry")]
30 pub entry: String,
31}
32
33fn default_entry() -> String {
34 "filter.sh".to_string()
35}
36
37impl Default for RuntimeConfig {
38 fn default() -> Self {
39 Self { entry: default_entry() }
40 }
41}
42
43#[derive(Debug, Deserialize)]
44pub struct HooksConfig {
45 pub on_install: Option<String>,
46 pub on_update: Option<String>,
47 pub on_remove: Option<String>,
48}
49
50#[derive(Debug, Deserialize)]
51pub struct PipelineConfig {
52 pub pre: Option<Vec<String>>,
53 pub post: Option<Vec<String>>,
54}
55
56impl PluginManifest {
57 pub fn parse(content: &str) -> anyhow::Result<Self> {
58 Ok(toml::from_str(content)?)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn parse_minimal_manifest() {
68 let toml = r#"
69[plugin]
70name = "git-compact"
71commands = ["git"]
72
73[runtime]
74entry = "filter.sh"
75"#;
76 let manifest = PluginManifest::parse(toml).unwrap();
77 assert_eq!(manifest.plugin.name, "git-compact");
78 assert_eq!(manifest.plugin.commands, vec!["git"]);
79 assert_eq!(manifest.runtime.entry, "filter.sh");
80 }
81
82 #[test]
83 fn parse_minimal_manifest_no_runtime() {
84 let toml = r#"
85[plugin]
86name = "git-compact"
87commands = ["git"]
88"#;
89 let manifest = PluginManifest::parse(toml).unwrap();
90 assert_eq!(manifest.plugin.name, "git-compact");
91 assert_eq!(manifest.runtime.entry, "filter.sh");
92 }
93
94 #[test]
95 fn parse_full_manifest() {
96 let toml = r#"
97[plugin]
98name = "git-compact"
99version = "1.2.0"
100description = "Compact git output for LLM contexts"
101author = "zdk"
102category = "git"
103commands = ["git"]
104subcommands = ["status", "diff", "log", "show"]
105
106[runtime]
107entry = "filter.sh"
108
109[hooks]
110on_install = "chmod +x filter.sh"
111
112[pipeline]
113pre = ["strip-ansi"]
114post = ["truncate"]
115"#;
116 let manifest = PluginManifest::parse(toml).unwrap();
117 assert_eq!(manifest.plugin.name, "git-compact");
118 assert!(manifest.hooks.is_some());
119 assert!(manifest.pipeline.is_some());
120 }
121}