Skip to main content

systemprompt_cloud/paths/
context.rs

1use std::path::{Path, PathBuf};
2
3use super::{CloudPath, CloudPaths, DiscoveredProject};
4use crate::constants::{dir_names, file_names};
5
6#[derive(Debug, Clone)]
7pub struct UnifiedContext {
8    project: Option<DiscoveredProject>,
9    cloud_paths: Option<CloudPaths>,
10}
11
12impl UnifiedContext {
13    #[must_use]
14    pub fn discover() -> Self {
15        let project = DiscoveredProject::discover();
16        Self {
17            project,
18            cloud_paths: None,
19        }
20    }
21
22    #[must_use]
23    pub fn discover_from(start: &Path) -> Self {
24        let project = DiscoveredProject::discover_from(start);
25        Self {
26            project,
27            cloud_paths: None,
28        }
29    }
30
31    pub fn with_profile_paths(
32        mut self,
33        profile_dir: &Path,
34        credentials_path: &str,
35        tenants_path: &str,
36    ) -> Self {
37        self.cloud_paths = Some(CloudPaths::from_config(
38            profile_dir,
39            credentials_path,
40            tenants_path,
41        ));
42        self
43    }
44
45    #[must_use]
46    pub const fn has_project(&self) -> bool {
47        self.project.is_some()
48    }
49
50    #[must_use]
51    pub fn project_root(&self) -> Option<&Path> {
52        self.project.as_ref().map(DiscoveredProject::root)
53    }
54
55    #[must_use]
56    pub fn systemprompt_dir(&self) -> Option<PathBuf> {
57        self.project
58            .as_ref()
59            .map(DiscoveredProject::systemprompt_dir)
60            .map(Path::to_path_buf)
61    }
62
63    #[must_use]
64    pub fn credentials_path(&self) -> PathBuf {
65        if let Some(cloud) = &self.cloud_paths {
66            return cloud.resolve(CloudPath::Credentials);
67        }
68        if let Some(project) = &self.project {
69            return project.credentials_path();
70        }
71        PathBuf::from(dir_names::SYSTEMPROMPT).join(file_names::CREDENTIALS)
72    }
73
74    #[must_use]
75    pub fn tenants_path(&self) -> PathBuf {
76        if let Some(cloud) = &self.cloud_paths {
77            return cloud.resolve(CloudPath::Tenants);
78        }
79        if let Some(project) = &self.project {
80            return project.tenants_path();
81        }
82        PathBuf::from(dir_names::SYSTEMPROMPT).join(file_names::TENANTS)
83    }
84
85    #[must_use]
86    pub fn session_path(&self) -> PathBuf {
87        if let Some(cloud) = &self.cloud_paths {
88            return cloud.resolve(CloudPath::CliSession);
89        }
90        if let Some(project) = &self.project {
91            return project.session_path();
92        }
93        PathBuf::from(dir_names::SYSTEMPROMPT).join(file_names::SESSION)
94    }
95
96    #[must_use]
97    pub fn profiles_dir(&self) -> Option<PathBuf> {
98        self.project.as_ref().map(DiscoveredProject::profiles_dir)
99    }
100
101    #[must_use]
102    pub fn profile_dir(&self, name: &str) -> Option<PathBuf> {
103        self.project.as_ref().map(|p| p.profile_dir(name))
104    }
105
106    #[must_use]
107    pub fn docker_dir(&self) -> Option<PathBuf> {
108        self.project.as_ref().map(DiscoveredProject::docker_dir)
109    }
110
111    #[must_use]
112    pub fn storage_dir(&self) -> Option<PathBuf> {
113        self.project.as_ref().map(DiscoveredProject::storage_dir)
114    }
115
116    #[must_use]
117    pub fn has_credentials(&self) -> bool {
118        self.credentials_path().exists()
119    }
120
121    #[must_use]
122    pub fn has_tenants(&self) -> bool {
123        self.tenants_path().exists()
124    }
125
126    #[must_use]
127    pub fn has_session(&self) -> bool {
128        self.session_path().exists()
129    }
130
131    #[must_use]
132    pub fn has_profile(&self, name: &str) -> bool {
133        self.project.as_ref().is_some_and(|p| p.has_profile(name))
134    }
135
136    #[must_use]
137    pub const fn project(&self) -> Option<&DiscoveredProject> {
138        self.project.as_ref()
139    }
140
141    #[must_use]
142    pub const fn cloud_paths(&self) -> Option<&CloudPaths> {
143        self.cloud_paths.as_ref()
144    }
145}
146
147impl Default for UnifiedContext {
148    fn default() -> Self {
149        Self::discover()
150    }
151}