Skip to main content

systemprompt_cli/commands/plugins/
validate.rs

1use clap::Args;
2
3use super::discover_registry;
4use super::types::{ExtensionValidationOutput, ValidationError, ValidationWarning};
5use crate::CliConfig;
6use crate::shared::CommandOutput;
7
8#[derive(Debug, Clone, Copy, Args)]
9pub struct ValidateArgs {
10    #[arg(long, help = "Show detailed validation information")]
11    pub verbose: bool,
12}
13
14pub fn execute(args: &ValidateArgs, _config: &CliConfig) -> (CommandOutput, bool) {
15    let registry = discover_registry();
16    let mut errors = Vec::new();
17    let mut warnings = Vec::new();
18
19    if let Err(e) = registry.validate_dependencies() {
20        errors.push(ValidationError {
21            extension_id: None,
22            error_type: "dependency".to_owned(),
23            message: e.to_string(),
24        });
25    }
26
27    for ext in registry.extensions() {
28        if ext.dependencies().is_empty() && args.verbose {
29            continue;
30        }
31
32        for dep in ext.dependencies() {
33            if !registry.has(dep) {
34                errors.push(ValidationError {
35                    extension_id: Some(ext.id().to_owned()),
36                    error_type: "missing_dependency".to_owned(),
37                    message: format!("Missing dependency: {}", dep),
38                });
39            }
40        }
41
42        if ext.config_prefix().is_some()
43            && let Some(schema) = ext.config_schema()
44            && schema.is_null()
45        {
46            warnings.push(ValidationWarning {
47                extension_id: Some(ext.id().to_owned()),
48                warning_type: "config".to_owned(),
49                message: "Config prefix defined but schema is null".to_owned(),
50            });
51        }
52    }
53
54    for ext in registry.asset_extensions() {
55        warnings.push(ValidationWarning {
56            extension_id: Some(ext.id().to_owned()),
57            warning_type: "asset_validation_skipped".to_owned(),
58            message: "Asset validation requires full profile initialization. Use 'systemprompt \
59                      infra db validate'."
60                .to_owned(),
61        });
62    }
63
64    let valid = errors.is_empty();
65    let extension_count = registry.len();
66
67    let output = ExtensionValidationOutput {
68        valid,
69        extension_count,
70        errors,
71        warnings,
72    };
73
74    (
75        CommandOutput::card_value("Extension Validation", &output),
76        valid,
77    )
78}