systemprompt_cli/commands/admin/config/
validate.rs1use anyhow::Result;
2use clap::Args;
3
4use super::types::{read_yaml_file, ConfigFileInfo, ConfigSection, ConfigValidateOutput};
5use crate::shared::CommandResult;
6use crate::CliConfig;
7
8#[derive(Debug, Clone, Args)]
9pub struct ValidateArgs {
10 #[arg(value_name = "PATH_OR_SECTION")]
11 pub target: Option<String>,
12
13 #[arg(long)]
14 pub strict: bool,
15}
16
17pub fn execute(
18 args: &ValidateArgs,
19 _config: &CliConfig,
20) -> Result<CommandResult<ConfigValidateOutput>> {
21 let files_to_validate = if let Some(target) = &args.target {
22 if let Ok(section) = target.parse::<ConfigSection>() {
23 section.all_files()?
24 } else {
25 vec![std::path::PathBuf::from(target)]
26 }
27 } else {
28 let mut all_files = Vec::new();
29 for section in ConfigSection::all() {
30 if let Ok(files) = section.all_files() {
31 all_files.extend(files);
32 }
33 }
34 all_files
35 };
36
37 let mut results = Vec::new();
38 let mut all_valid = true;
39
40 for file_path in files_to_validate {
41 let section = detect_section(&file_path);
42 let exists = file_path.exists();
43
44 let (valid, error) = if exists {
45 match validate_file(&file_path, args.strict) {
46 Ok(()) => (true, None),
47 Err(e) => {
48 all_valid = false;
49 (false, Some(e.to_string()))
50 },
51 }
52 } else {
53 all_valid = false;
54 (false, Some("File not found".to_string()))
55 };
56
57 results.push(ConfigFileInfo {
58 path: file_path.display().to_string(),
59 section,
60 exists,
61 valid,
62 error,
63 });
64 }
65
66 let output = ConfigValidateOutput {
67 files: results,
68 all_valid,
69 };
70
71 let title = if all_valid {
72 "Validation Passed"
73 } else {
74 "Validation Failed"
75 };
76
77 Ok(CommandResult::table(output).with_title(title))
78}
79
80fn validate_file(path: &std::path::Path, _strict: bool) -> Result<()> {
81 let _content = read_yaml_file(path)?;
82 Ok(())
83}
84
85fn detect_section(path: &std::path::Path) -> String {
86 let path_str = path.display().to_string();
87
88 if path_str.contains("/ai/") {
89 "ai".to_string()
90 } else if path_str.contains("/content/") {
91 "content".to_string()
92 } else if path_str.contains("/web/") {
93 "web".to_string()
94 } else if path_str.contains("/scheduler/") {
95 "scheduler".to_string()
96 } else if path_str.contains("/agents/") {
97 "agents".to_string()
98 } else if path_str.contains("/mcp/") {
99 "mcp".to_string()
100 } else if path_str.contains("/skills/") {
101 "skills".to_string()
102 } else if path_str.contains("profile.yaml") {
103 "profile".to_string()
104 } else if path_str.contains("/config/config.yaml") {
105 "services".to_string()
106 } else {
107 "unknown".to_string()
108 }
109}