Skip to main content

systemprompt_models/extension/
mod.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum ExtensionType {
8    Mcp,
9    Blog,
10    Cli,
11    #[default]
12    Other,
13}
14
15#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
16#[serde(rename_all = "lowercase")]
17pub enum BuildType {
18    #[default]
19    Workspace,
20    Submodule,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ManifestRole {
25    pub display_name: String,
26    pub description: String,
27    #[serde(default)]
28    pub permissions: Vec<String>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct CliCommand {
33    pub name: String,
34    #[serde(default)]
35    pub description: String,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct ExtensionManifest {
40    pub extension: Extension,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct Extension {
45    #[serde(rename = "type")]
46    pub type_: ExtensionType,
47
48    pub name: String,
49
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub binary: Option<String>,
52
53    #[serde(default)]
54    pub description: String,
55
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub port: Option<u16>,
58
59    #[serde(default)]
60    pub build_type: BuildType,
61
62    #[serde(default = "default_true")]
63    pub enabled: bool,
64
65    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
66    pub roles: HashMap<String, ManifestRole>,
67
68    #[serde(default, skip_serializing_if = "Vec::is_empty")]
69    pub commands: Vec<CliCommand>,
70
71    #[serde(default)]
72    pub supports_json_output: bool,
73}
74
75const fn default_true() -> bool {
76    true
77}
78
79#[derive(Debug, Clone)]
80pub struct DiscoveredExtension {
81    pub manifest: ExtensionManifest,
82    pub path: PathBuf,
83    pub manifest_path: PathBuf,
84}
85
86impl DiscoveredExtension {
87    pub const fn new(manifest: ExtensionManifest, path: PathBuf, manifest_path: PathBuf) -> Self {
88        Self {
89            manifest,
90            path,
91            manifest_path,
92        }
93    }
94
95    pub const fn extension_type(&self) -> ExtensionType {
96        self.manifest.extension.type_
97    }
98
99    pub fn binary_name(&self) -> Option<&str> {
100        self.manifest.extension.binary.as_deref()
101    }
102
103    pub const fn is_enabled(&self) -> bool {
104        self.manifest.extension.enabled
105    }
106
107    pub fn is_mcp(&self) -> bool {
108        self.manifest.extension.type_ == ExtensionType::Mcp
109    }
110
111    pub fn is_cli(&self) -> bool {
112        self.manifest.extension.type_ == ExtensionType::Cli
113    }
114
115    pub fn commands(&self) -> &[CliCommand] {
116        &self.manifest.extension.commands
117    }
118
119    pub const fn build_type(&self) -> BuildType {
120        self.manifest.extension.build_type
121    }
122
123    pub const fn supports_json_output(&self) -> bool {
124        self.manifest.extension.supports_json_output
125    }
126}