systemprompt_cloud/paths/
discovery.rs1use std::path::{Path, PathBuf};
2
3use crate::constants::{dir_names, file_names};
4
5#[derive(Debug, Clone)]
6pub struct DiscoveredProject {
7 root: PathBuf,
8 systemprompt_dir: PathBuf,
9}
10
11impl DiscoveredProject {
12 #[must_use]
13 pub fn discover() -> Option<Self> {
14 let cwd = match std::env::current_dir() {
15 Ok(dir) => dir,
16 Err(e) => {
17 tracing::debug!(error = %e, "Failed to get current directory for project discovery");
18 return None;
19 },
20 };
21 Self::discover_from(&cwd)
22 }
23
24 #[must_use]
25 pub fn discover_from(start: &Path) -> Option<Self> {
26 let mut current = start.to_path_buf();
27 loop {
28 let systemprompt_dir = current.join(dir_names::SYSTEMPROMPT);
29 if systemprompt_dir.is_dir() {
30 return Some(Self {
31 root: current,
32 systemprompt_dir,
33 });
34 }
35 if !current.pop() {
36 break;
37 }
38 }
39 None
40 }
41
42 #[must_use]
43 pub fn from_root(root: PathBuf) -> Self {
44 let systemprompt_dir = root.join(dir_names::SYSTEMPROMPT);
45 Self {
46 root,
47 systemprompt_dir,
48 }
49 }
50
51 #[must_use]
52 pub fn root(&self) -> &Path {
53 &self.root
54 }
55
56 #[must_use]
57 pub fn systemprompt_dir(&self) -> &Path {
58 &self.systemprompt_dir
59 }
60
61 #[must_use]
62 pub fn credentials_path(&self) -> PathBuf {
63 self.systemprompt_dir.join(file_names::CREDENTIALS)
64 }
65
66 #[must_use]
67 pub fn tenants_path(&self) -> PathBuf {
68 self.systemprompt_dir.join(file_names::TENANTS)
69 }
70
71 #[must_use]
72 pub fn session_path(&self) -> PathBuf {
73 self.systemprompt_dir.join(file_names::SESSION)
74 }
75
76 #[must_use]
77 pub fn sessions_dir(&self) -> PathBuf {
78 self.systemprompt_dir.join(dir_names::SESSIONS)
79 }
80
81 #[must_use]
82 pub fn profiles_dir(&self) -> PathBuf {
83 self.systemprompt_dir.join(dir_names::PROFILES)
84 }
85
86 #[must_use]
87 pub fn profile_dir(&self, name: &str) -> PathBuf {
88 self.profiles_dir().join(name)
89 }
90
91 #[must_use]
92 pub fn profile_config(&self, name: &str) -> PathBuf {
93 self.profile_dir(name).join(file_names::PROFILE_CONFIG)
94 }
95
96 #[must_use]
97 pub fn profile_secrets(&self, name: &str) -> PathBuf {
98 self.profile_dir(name).join(file_names::PROFILE_SECRETS)
99 }
100
101 #[must_use]
102 pub fn docker_dir(&self) -> PathBuf {
103 self.systemprompt_dir.join(dir_names::DOCKER)
104 }
105
106 #[must_use]
107 pub fn storage_dir(&self) -> PathBuf {
108 self.systemprompt_dir.join(dir_names::STORAGE)
109 }
110
111 #[must_use]
112 pub fn is_initialized(&self) -> bool {
113 self.systemprompt_dir.is_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.profile_dir(name).is_dir()
134 }
135}