Skip to main content

systemprompt_cli/commands/core/plugins/
show.rs

1use anyhow::{Context, Result, anyhow};
2use clap::Args;
3use std::path::Path;
4
5use crate::CliConfig;
6use crate::shared::CommandOutput;
7
8use super::types::{PluginComponentRef, PluginDetailOutput};
9
10#[derive(Debug, Clone, Args)]
11pub struct ShowArgs {
12    #[arg(help = "Plugin ID (directory name)")]
13    pub id: String,
14}
15
16pub(super) fn execute(args: &ShowArgs, _config: &CliConfig) -> Result<CommandOutput> {
17    let plugins_path = get_plugins_path()?;
18    let plugin_dir = plugins_path.join(&args.id);
19
20    if !plugin_dir.exists() {
21        return Err(anyhow!("Plugin '{}' not found", args.id));
22    }
23
24    let config_path = plugin_dir.join("config.yaml");
25    if !config_path.exists() {
26        return Err(anyhow!("Plugin '{}' has no config.yaml file", args.id));
27    }
28
29    let plugin_file = parse_plugin_config(&config_path)?;
30    let plugin = &plugin_file.plugin;
31
32    let output = PluginDetailOutput {
33        id: systemprompt_identifiers::PluginId::new(plugin.id.clone()),
34        name: plugin.name.clone(),
35        description: plugin.description.clone(),
36        version: plugin.version.clone(),
37        enabled: plugin.enabled,
38        skills: PluginComponentRef {
39            source: plugin.skills.source,
40            filter: plugin.skills.filter,
41            include: plugin.skills.include.clone(),
42            exclude: plugin.skills.exclude.clone(),
43        },
44        agents: PluginComponentRef {
45            source: plugin.agents.source,
46            filter: plugin.agents.filter,
47            include: plugin.agents.include.clone(),
48            exclude: plugin.agents.exclude.clone(),
49        },
50        mcp_servers: plugin.mcp_servers.clone(),
51        scripts: plugin.scripts.iter().map(|s| s.name.clone()).collect(),
52        keywords: plugin.keywords.clone(),
53        category: plugin.category.clone(),
54        author: plugin.author.name.clone(),
55    };
56
57    Ok(CommandOutput::card_value(
58        format!("Plugin: {}", args.id),
59        &output,
60    ))
61}
62
63fn get_plugins_path() -> Result<std::path::PathBuf> {
64    let profile = systemprompt_config::ProfileBootstrap::get().context("Failed to get profile")?;
65    Ok(std::path::PathBuf::from(profile.paths.plugins()))
66}
67
68fn parse_plugin_config(config_path: &Path) -> Result<systemprompt_models::PluginConfigFile> {
69    let content = std::fs::read_to_string(config_path)
70        .with_context(|| format!("Failed to read {}", config_path.display()))?;
71    let plugin_file: systemprompt_models::PluginConfigFile = serde_yaml::from_str(&content)
72        .with_context(|| format!("Failed to parse {}", config_path.display()))?;
73    Ok(plugin_file)
74}