systemprompt-models 0.1.18

Shared data models and types for systemprompt.io OS
Documentation
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ExtensionType {
    Mcp,
    Blog,
    Cli,
    #[default]
    Other,
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum BuildType {
    #[default]
    Workspace,
    Submodule,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestRole {
    pub display_name: String,
    pub description: String,
    #[serde(default)]
    pub permissions: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CliCommand {
    pub name: String,
    #[serde(default)]
    pub description: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExtensionManifest {
    pub extension: Extension,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Extension {
    #[serde(rename = "type")]
    pub type_: ExtensionType,

    pub name: String,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub binary: Option<String>,

    #[serde(default)]
    pub description: String,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub port: Option<u16>,

    #[serde(default)]
    pub build_type: BuildType,

    #[serde(default = "default_true")]
    pub enabled: bool,

    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
    pub roles: HashMap<String, ManifestRole>,

    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub commands: Vec<CliCommand>,

    #[serde(default)]
    pub supports_json_output: bool,
}

const fn default_true() -> bool {
    true
}

#[derive(Debug, Clone)]
pub struct DiscoveredExtension {
    pub manifest: ExtensionManifest,
    pub path: PathBuf,
    pub manifest_path: PathBuf,
}

impl DiscoveredExtension {
    pub const fn new(manifest: ExtensionManifest, path: PathBuf, manifest_path: PathBuf) -> Self {
        Self {
            manifest,
            path,
            manifest_path,
        }
    }

    pub const fn extension_type(&self) -> ExtensionType {
        self.manifest.extension.type_
    }

    pub fn binary_name(&self) -> Option<&str> {
        self.manifest.extension.binary.as_deref()
    }

    pub const fn is_enabled(&self) -> bool {
        self.manifest.extension.enabled
    }

    pub fn is_mcp(&self) -> bool {
        self.manifest.extension.type_ == ExtensionType::Mcp
    }

    pub fn is_cli(&self) -> bool {
        self.manifest.extension.type_ == ExtensionType::Cli
    }

    pub fn commands(&self) -> &[CliCommand] {
        &self.manifest.extension.commands
    }

    pub const fn build_type(&self) -> BuildType {
        self.manifest.extension.build_type
    }

    pub const fn supports_json_output(&self) -> bool {
        self.manifest.extension.supports_json_output
    }
}