use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramMeta {
pub name: String,
pub version: String,
pub description: String,
pub author: String,
pub tools: Vec<ToolDef>,
pub dependencies: Vec<String>,
pub host_requirements: ProgramHostRequirements,
#[serde(default)]
pub mcp_servers: Vec<McpServerConfig>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProgramHostRequirements {
pub required: Vec<String>,
pub optional: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpServerConfig {
pub name: String,
pub command: String,
#[serde(default)]
pub args: Vec<String>,
#[serde(default)]
pub env: HashMap<String, String>,
#[serde(default = "default_enabled")]
pub enabled: bool,
}
fn default_enabled() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDef {
pub name: String,
pub description: String,
pub arguments: Vec<ArgumentDef>,
#[serde(default)]
pub command: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArgumentDef {
pub name: String,
pub description: String,
pub required: bool,
pub default: Option<String>,
}
#[derive(Debug, Clone)]
pub struct Program {
pub meta: ProgramMeta,
pub path: std::path::PathBuf,
pub skill_content: String,
pub enabled: bool,
}
pub enum InstallSource {
Local(std::path::PathBuf),
Git {
url: String,
branch: Option<String>,
},
Tarball {
url: String,
},
}
#[derive(Debug, Clone, Serialize)]
pub struct HostRequirementsCheck {
pub program_name: String,
pub missing_required: Vec<String>,
pub optional_available: HashMap<String, bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgramState {
pub enabled: bool,
pub installed_at: String,
pub last_modified: String,
}
impl Default for ProgramState {
fn default() -> Self {
let now = chrono::Utc::now().to_rfc3339();
Self {
enabled: true,
installed_at: now.clone(),
last_modified: now,
}
}
}
impl ProgramState {
pub fn new() -> Self {
Self::default()
}
pub fn with_enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self.last_modified = chrono::Utc::now().to_rfc3339();
self
}
}