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