Skip to main content

systemprompt_cli/commands/admin/config/
paths.rs

1use anyhow::Result;
2use clap::Subcommand;
3use std::path::Path;
4use systemprompt_logging::CliService;
5use systemprompt_models::ProfileBootstrap;
6
7use super::types::{PathInfo, PathValidation, PathsConfigOutput, PathsValidateOutput};
8use crate::cli_settings::OutputFormat;
9use crate::shared::{render_result, CommandResult};
10use crate::CliConfig;
11
12#[derive(Debug, Clone, Copy, Subcommand)]
13pub enum PathsCommands {
14    #[command(about = "Show paths configuration")]
15    Show,
16
17    #[command(about = "Validate that all configured paths exist")]
18    Validate,
19}
20
21pub fn execute(command: PathsCommands, config: &CliConfig) -> Result<()> {
22    match command {
23        PathsCommands::Show => execute_show(),
24        PathsCommands::Validate => execute_validate(config),
25    }
26}
27
28fn execute_show() -> Result<()> {
29    let profile = ProfileBootstrap::get()?;
30
31    let output = PathsConfigOutput {
32        system: PathInfo {
33            path: profile.paths.system.clone(),
34            exists: Path::new(&profile.paths.system).exists(),
35        },
36        services: PathInfo {
37            path: profile.paths.services.clone(),
38            exists: Path::new(&profile.paths.services).exists(),
39        },
40        bin: PathInfo {
41            path: profile.paths.bin.clone(),
42            exists: Path::new(&profile.paths.bin).exists(),
43        },
44        web_path: profile.paths.web_path.as_ref().map(|p| PathInfo {
45            path: p.clone(),
46            exists: Path::new(p).exists(),
47        }),
48        storage: profile.paths.storage.as_ref().map(|p| PathInfo {
49            path: p.clone(),
50            exists: Path::new(p).exists(),
51        }),
52        geoip_database: profile.paths.geoip_database.as_ref().map(|p| PathInfo {
53            path: p.clone(),
54            exists: Path::new(p).exists(),
55        }),
56    };
57
58    render_result(&CommandResult::card(output).with_title("Paths Configuration"));
59
60    Ok(())
61}
62
63fn execute_validate(config: &CliConfig) -> Result<()> {
64    let profile = ProfileBootstrap::get()?;
65
66    let mut validations: Vec<PathValidation> = Vec::new();
67
68    validations.push(PathValidation {
69        name: "system".to_string(),
70        path: profile.paths.system.clone(),
71        exists: Path::new(&profile.paths.system).exists(),
72        required: true,
73    });
74
75    validations.push(PathValidation {
76        name: "services".to_string(),
77        path: profile.paths.services.clone(),
78        exists: Path::new(&profile.paths.services).exists(),
79        required: true,
80    });
81
82    validations.push(PathValidation {
83        name: "bin".to_string(),
84        path: profile.paths.bin.clone(),
85        exists: Path::new(&profile.paths.bin).exists(),
86        required: true,
87    });
88
89    if let Some(web_path) = &profile.paths.web_path {
90        validations.push(PathValidation {
91            name: "web_path".to_string(),
92            path: web_path.clone(),
93            exists: Path::new(web_path).exists(),
94            required: false,
95        });
96    }
97
98    if let Some(storage) = &profile.paths.storage {
99        validations.push(PathValidation {
100            name: "storage".to_string(),
101            path: storage.clone(),
102            exists: Path::new(storage).exists(),
103            required: false,
104        });
105    }
106
107    if let Some(geoip) = &profile.paths.geoip_database {
108        validations.push(PathValidation {
109            name: "geoip_database".to_string(),
110            path: geoip.clone(),
111            exists: Path::new(geoip).exists(),
112            required: false,
113        });
114    }
115
116    let config_path = profile.paths.config();
117    validations.push(PathValidation {
118        name: "config".to_string(),
119        path: config_path.clone(),
120        exists: Path::new(&config_path).exists(),
121        required: false,
122    });
123
124    let ai_config_path = profile.paths.ai_config();
125    validations.push(PathValidation {
126        name: "ai_config".to_string(),
127        path: ai_config_path.clone(),
128        exists: Path::new(&ai_config_path).exists(),
129        required: false,
130    });
131
132    let content_config_path = profile.paths.content_config();
133    validations.push(PathValidation {
134        name: "content_config".to_string(),
135        path: content_config_path.clone(),
136        exists: Path::new(&content_config_path).exists(),
137        required: false,
138    });
139
140    let valid = validations.iter().filter(|v| v.required).all(|v| v.exists);
141
142    let output = PathsValidateOutput {
143        valid,
144        paths: validations,
145    };
146
147    render_result(&CommandResult::table(output).with_title("Paths Validation"));
148
149    if config.output_format() == OutputFormat::Table {
150        if valid {
151            CliService::success("All required paths exist");
152        } else {
153            CliService::error("Some required paths are missing");
154        }
155    }
156
157    Ok(())
158}