systemprompt_models/bridge/
plugin_bundle.rs1use serde::{Deserialize, Serialize};
23
24pub const PLUGIN_MANIFEST_RELPATH: &str = ".claude-plugin/plugin.json";
25
26pub const PLUGIN_MANIFEST_DIRS: &[&str] = &[".claude-plugin", "claude-plugin"];
27
28pub const PLUGIN_MANIFEST_FILE: &str = "plugin.json";
29
30#[derive(Debug, Clone, Default, Serialize, Deserialize)]
31pub struct PluginManifest {
32 pub name: String,
33 #[serde(default)]
34 pub description: String,
35 #[serde(default)]
36 pub version: String,
37 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub author: Option<ManifestAuthor>,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub hooks: Option<String>,
41 #[serde(default, skip_serializing_if = "Vec::is_empty")]
42 pub keywords: Vec<String>,
43 #[serde(
44 default,
45 rename = "installationPreference",
46 skip_serializing_if = "Option::is_none"
47 )]
48 pub installation_preference: Option<String>,
49
50 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub skills: Option<serde_json::Value>,
52
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 pub agents: Option<serde_json::Value>,
55
56 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub commands: Option<serde_json::Value>,
58
59 #[serde(
60 default,
61 rename = "mcpServers",
62 alias = "mcp_servers",
63 skip_serializing_if = "Option::is_none"
64 )]
65 pub mcp_servers: Option<serde_json::Value>,
66
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub homepage: Option<String>,
69
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub repository: Option<String>,
72
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 pub license: Option<String>,
75
76 #[serde(default, skip_serializing_if = "Option::is_none")]
77 pub category: Option<String>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct ManifestAuthor {
82 pub name: String,
83 #[serde(default, skip_serializing_if = "String::is_empty")]
84 pub email: String,
85}
86
87pub fn bundle_has_manifest<S: AsRef<str>>(paths: impl IntoIterator<Item = S>) -> bool {
88 paths
89 .into_iter()
90 .any(|path| path.as_ref() == PLUGIN_MANIFEST_RELPATH)
91}