Skip to main content

systemprompt_cli/
paths.rs

1//! Resolved filesystem paths the CLI operates against.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::path::{Path, PathBuf};
7
8use systemprompt_cloud::ProjectContext;
9use systemprompt_cloud::paths::{CloudPath, get_cloud_paths};
10
11#[derive(Debug)]
12pub struct ResolvedPaths {
13    project_ctx: ProjectContext,
14    has_local_dir: bool,
15}
16
17impl ResolvedPaths {
18    // Why: preferred once a profile is resolved, so the tenant and session stores
19    // depend on the profile rather than on the directory the process started
20    // in.
21    pub fn for_root(root: &Path) -> Self {
22        let project_ctx = ProjectContext::discover_from(root);
23        let has_local_dir = project_ctx.systemprompt_dir().exists();
24        Self {
25            project_ctx,
26            has_local_dir,
27        }
28    }
29
30    pub fn from_profile(profile: &systemprompt_models::Profile) -> Self {
31        Self::for_root(Path::new(&profile.paths.system))
32    }
33
34    // Why: only correct before a profile is resolved; afterwards use
35    // `from_profile`, or the same command answers differently depending on the
36    // caller's cwd.
37    pub fn discover() -> Self {
38        let project_ctx = ProjectContext::discover();
39        let has_local_dir = project_ctx.systemprompt_dir().exists();
40        tracing::debug!(
41            root = %project_ctx.root().display(),
42            has_local_dir,
43            "Resolved project root by walking up from the current directory"
44        );
45        Self {
46            project_ctx,
47            has_local_dir,
48        }
49    }
50
51    pub fn sessions_dir(&self) -> PathBuf {
52        if self.has_local_dir {
53            self.project_ctx.sessions_dir()
54        } else {
55            let cloud_paths = get_cloud_paths();
56            cloud_paths.resolve(CloudPath::SessionsDir)
57        }
58    }
59
60    pub fn tenants_path(&self) -> PathBuf {
61        if self.has_local_dir {
62            self.project_ctx.local_tenants()
63        } else {
64            let cloud_paths = get_cloud_paths();
65            cloud_paths.resolve(CloudPath::Tenants)
66        }
67    }
68
69    pub fn profiles_dir(&self) -> PathBuf {
70        self.project_ctx.profiles_dir()
71    }
72}