use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PluginSource {
Git { url: String, branch: String },
Local { path: PathBuf },
Marketplace { marketplace: String },
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PluginStatus {
Installed,
Disabled,
Error(String),
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum PluginScope {
User,
Project,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolDefinition {
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub parameters: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PromptTemplate {
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub template: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PluginManifest {
pub name: String,
pub version: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub author: Option<String>,
#[serde(default)]
pub tools: Vec<ToolDefinition>,
#[serde(default)]
pub prompts: Vec<PromptTemplate>,
#[serde(default)]
pub dependencies: Vec<String>,
#[serde(default)]
pub skills: Vec<String>,
#[serde(default)]
pub repository: Option<String>,
#[serde(default)]
pub license: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginConfig {
pub name: String,
pub version: String,
pub source: PluginSource,
pub status: PluginStatus,
pub scope: PluginScope,
pub enabled: bool,
pub path: PathBuf,
pub installed_at: DateTime<Utc>,
#[serde(default)]
pub marketplace: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketplaceInfo {
pub name: String,
pub url: String,
#[serde(default = "default_branch")]
pub branch: String,
pub added_at: DateTime<Utc>,
#[serde(default)]
pub last_updated: Option<DateTime<Utc>>,
}
fn default_branch() -> String {
"main".to_string()
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct KnownMarketplaces {
#[serde(default)]
pub marketplaces: HashMap<String, MarketplaceInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct InstalledPlugins {
#[serde(default)]
pub plugins: HashMap<String, PluginConfig>,
}
impl InstalledPlugins {
pub fn make_key(marketplace: &str, plugin: &str) -> String {
format!("{}:{}", marketplace, plugin)
}
pub fn add(&mut self, plugin: PluginConfig) {
let key = Self::make_key(
plugin.marketplace.as_deref().unwrap_or("local"),
&plugin.name,
);
self.plugins.insert(key, plugin);
}
pub fn remove(&mut self, marketplace: &str, plugin: &str) -> Option<PluginConfig> {
let key = Self::make_key(marketplace, plugin);
self.plugins.remove(&key)
}
pub fn get(&self, marketplace: &str, plugin: &str) -> Option<&PluginConfig> {
let key = Self::make_key(marketplace, plugin);
self.plugins.get(&key)
}
pub fn get_mut(&mut self, marketplace: &str, plugin: &str) -> Option<&mut PluginConfig> {
let key = Self::make_key(marketplace, plugin);
self.plugins.get_mut(&key)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MarketplaceCatalog {
#[serde(default)]
pub plugins: Vec<String>,
#[serde(default)]
pub auto_discovered: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginMetadata {
pub name: String,
pub version: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub author: Option<String>,
#[serde(default)]
pub skills: Vec<String>,
#[serde(default)]
pub repository: Option<String>,
#[serde(default)]
pub license: Option<String>,
}