1use serde::{Deserialize, Serialize};
2use crate::permissions::Permission;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct PluginManifest {
7 pub id: String,
8 pub name: String,
9 pub version: String,
10 pub description: String,
11 #[serde(default)]
12 pub long_description: Option<String>,
13 pub author: String,
14 #[serde(default)]
15 pub author_url: Option<String>,
16 #[serde(default)]
17 pub homepage: Option<String>,
18 #[serde(default)]
19 pub license: Option<String>,
20 #[serde(default)]
21 pub keywords: Vec<String>,
22 #[serde(default)]
23 pub icon: Option<String>,
24
25 pub compatibility: CompatibilitySpec,
26
27 pub capability_levels: Vec<CapabilityLevel>,
29
30 #[serde(default)]
32 pub integration: IntegrationConfig,
33
34 #[serde(default)]
36 pub entry: EntryConfig,
37
38 #[serde(default)]
40 pub dependencies: Vec<PluginDependency>,
41
42 #[serde(default)]
44 pub permissions: Vec<Permission>,
45
46 #[serde(default)]
48 pub settings_schema: Option<serde_json::Value>,
49
50 #[serde(default)]
52 pub commands: Vec<CommandDeclaration>,
53
54 #[serde(default)]
56 pub checksum: Option<String>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct CompatibilitySpec {
61 pub min_app_version: String,
62 #[serde(default)]
63 pub max_app_version: Option<String>,
64 #[serde(default = "all_platforms")]
65 pub platforms: Vec<String>,
66}
67
68fn all_platforms() -> Vec<String> {
69 vec!["windows".into(), "macos".into(), "linux".into()]
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
74#[serde(from = "u8", into = "u8")]
75pub enum CapabilityLevel {
76 Module = 0,
78 ModuleFeature = 1,
80 UiExtension = 2,
82 AiAssistant = 3,
84 Service = 4,
86}
87
88impl From<u8> for CapabilityLevel {
89 fn from(v: u8) -> Self {
90 match v {
91 0 => Self::Module,
92 1 => Self::ModuleFeature,
93 2 => Self::UiExtension,
94 3 => Self::AiAssistant,
95 4 => Self::Service,
96 _ => Self::Service,
97 }
98 }
99}
100
101impl From<CapabilityLevel> for u8 {
102 fn from(l: CapabilityLevel) -> u8 {
103 l as u8
104 }
105}
106
107#[derive(Debug, Clone, Default, Serialize, Deserialize)]
109pub struct IntegrationConfig {
110 #[serde(default)]
111 pub level0: Option<Level0Config>,
112 #[serde(default)]
113 pub level1: Option<Level1Config>,
114 #[serde(default)]
115 pub level2: Option<Level2Config>,
116 #[serde(default)]
117 pub level3: Option<Level3Config>,
118 #[serde(default)]
119 pub level4: Option<Level4Config>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct Level0Config {
125 pub module_id: String,
127 pub module_label: String,
128 pub module_icon: String,
130 #[serde(default = "default_sidebar_position")]
132 pub sidebar_position: String,
133 #[serde(default = "default_sidebar_order")]
135 pub sidebar_order: u32,
136 pub panel_entry: String,
138}
139
140fn default_sidebar_position() -> String { "main".into() }
141fn default_sidebar_order() -> u32 { 100 }
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct Level1Config {
146 pub parent_module: String,
148 pub tab_id: String,
150 pub tab_label: String,
151 pub tab_icon: String,
153 #[serde(default)]
155 pub tab_position: Option<String>,
156 pub panel_entry: String,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct Level2Config {
163 pub slots: Vec<String>,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct Level3Config {
170 pub assistant_id: String,
171 pub assistant_name: String,
172 #[serde(default)]
173 pub assistant_icon: Option<String>,
174 #[serde(default)]
175 pub assistant_description: Option<String>,
176 pub system_prompt_file: String,
178 #[serde(default)]
180 pub preferred_model: Option<String>,
181}
182
183#[derive(Debug, Clone, Default, Serialize, Deserialize)]
185pub struct Level4Config {
186 #[serde(default)]
188 pub workflow_step_types: Vec<String>,
189}
190
191#[derive(Debug, Clone, Default, Serialize, Deserialize)]
193pub struct EntryConfig {
194 #[serde(default)]
195 pub native: Option<NativeEntry>,
196 #[serde(default)]
197 pub frontend: Option<String>,
198 #[serde(default)]
199 pub frontend_styles: Option<String>,
200}
201
202#[derive(Debug, Clone, Default, Serialize, Deserialize)]
203pub struct NativeEntry {
204 #[serde(default)]
205 pub macos_arm64: Option<String>,
206 #[serde(default)]
207 pub macos_x64: Option<String>,
208 #[serde(default)]
209 pub windows_x64: Option<String>,
210 #[serde(default)]
211 pub windows_arm64: Option<String>,
212 #[serde(default)]
213 pub linux_x64: Option<String>,
214 #[serde(default)]
215 pub linux_arm64: Option<String>,
216}
217
218impl NativeEntry {
219 pub fn for_current_platform(&self) -> Option<&str> {
221 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
222 return self.macos_arm64.as_deref();
223
224 #[cfg(all(target_os = "macos", target_arch = "x86_64"))]
225 return self.macos_x64.as_deref();
226
227 #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
228 return self.windows_x64.as_deref();
229
230 #[cfg(all(target_os = "windows", target_arch = "aarch64"))]
231 return self.windows_arm64.as_deref();
232
233 #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
234 return self.linux_x64.as_deref();
235
236 #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
237 return self.linux_arm64.as_deref();
238
239 #[allow(unreachable_code)]
240 None
241 }
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct PluginDependency {
246 pub id: String,
247 pub version: String,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct CommandDeclaration {
253 pub id: String,
254 #[serde(default)]
255 pub description: Option<String>,
256}