systemprompt_config/paths/
system.rs1use std::path::{Path, PathBuf};
7
8use super::PathError;
9use systemprompt_manifest::paths::PathResolution;
10use systemprompt_manifest::profile::PathsConfig;
11
12#[derive(Debug, Clone)]
13pub struct SystemPaths {
14 root: PathBuf,
15 services: PathBuf,
16 skills: PathBuf,
17 settings: PathBuf,
18 content_config: PathBuf,
19 geoip_database: Option<PathBuf>,
20 defaults: PathBuf,
21}
22
23impl SystemPaths {
24 const LOGS_DIR: &'static str = "logs";
25
26 pub fn from_profile(
27 paths: &PathsConfig,
28 resolution: PathResolution,
29 ) -> Result<Self, PathError> {
30 let root = match resolution {
31 PathResolution::Canonicalize => Self::canonicalize(&paths.system, "system")?,
32 PathResolution::Lexical => Self::lexical(&paths.system, "system")?,
33 };
34 let defaults = Self::resolve_defaults_dir(&root);
35
36 Ok(Self {
37 root,
38 services: PathBuf::from(&paths.services),
39 skills: PathBuf::from(paths.skills()),
40 settings: PathBuf::from(paths.config()),
41 content_config: PathBuf::from(paths.content_config()),
42 geoip_database: paths.geoip_database.as_ref().map(PathBuf::from),
43 defaults,
44 })
45 }
46
47 fn canonicalize(path: &str, field: &'static str) -> Result<PathBuf, PathError> {
48 std::fs::canonicalize(path).map_err(|source| PathError::CanonicalizeFailed {
49 path: PathBuf::from(path),
50 field,
51 source,
52 })
53 }
54
55 fn lexical(path: &str, field: &'static str) -> Result<PathBuf, PathError> {
56 let path = PathBuf::from(path);
57 if path.is_absolute() {
58 Ok(path)
59 } else {
60 Err(PathError::NotAbsolute { path, field })
61 }
62 }
63
64 fn resolve_defaults_dir(root: &Path) -> PathBuf {
65 root.join("defaults")
66 }
67
68 pub fn root(&self) -> &Path {
69 &self.root
70 }
71
72 pub fn services(&self) -> &Path {
73 &self.services
74 }
75
76 pub fn skills(&self) -> &Path {
77 &self.skills
78 }
79
80 pub fn settings(&self) -> &Path {
81 &self.settings
82 }
83
84 pub fn content_config(&self) -> &Path {
85 &self.content_config
86 }
87
88 pub fn geoip_database(&self) -> Option<&Path> {
89 self.geoip_database.as_deref()
90 }
91
92 pub fn logs(&self) -> PathBuf {
93 self.root.join(Self::LOGS_DIR)
94 }
95
96 pub fn defaults(&self) -> &Path {
97 &self.defaults
98 }
99}