Skip to main content

systemprompt_cli/commands/cloud/tenant/
select.rs

1use anyhow::{Result, anyhow, bail};
2use dialoguer::Select;
3use dialoguer::theme::ColorfulTheme;
4use systemprompt_cloud::{
5    CloudCredentials, CloudPath, CredentialsBootstrap, StoredTenant, TenantType, get_cloud_paths,
6};
7use systemprompt_identifiers::TenantId;
8use systemprompt_models::profile_bootstrap::ProfileBootstrap;
9
10pub fn get_credentials() -> Result<CloudCredentials> {
11    if CredentialsBootstrap::is_initialized() {
12        return CredentialsBootstrap::require()
13            .map_err(|e| {
14                anyhow!(
15                    "Credentials required. Run 'systemprompt cloud login': {}",
16                    e
17                )
18            })?
19            .clone()
20            .pipe(Ok);
21    }
22
23    let cloud_paths = get_cloud_paths();
24    let creds_path = cloud_paths.resolve(CloudPath::Credentials);
25
26    if creds_path.exists() {
27        CloudCredentials::load_from_path(&creds_path)
28    } else {
29        bail!("Not logged in. Run 'systemprompt cloud login' first.")
30    }
31}
32
33pub fn select_tenant(tenants: &[StoredTenant]) -> Result<&StoredTenant> {
34    let options: Vec<String> = tenants
35        .iter()
36        .map(|t| {
37            let type_str = match t.tenant_type {
38                TenantType::Local => "local",
39                TenantType::Cloud => "cloud",
40            };
41            format!("{} ({})", t.name, type_str)
42        })
43        .collect();
44
45    let selection = Select::with_theme(&ColorfulTheme::default())
46        .with_prompt("Select tenant")
47        .items(&options)
48        .default(0)
49        .interact()?;
50
51    Ok(&tenants[selection])
52}
53
54pub fn resolve_tenant_id(tenant: Option<String>) -> Result<TenantId> {
55    if let Some(id) = tenant {
56        return Ok(TenantId::new(id));
57    }
58
59    ProfileBootstrap::get()
60        .ok()
61        .and_then(|p| p.cloud.as_ref()?.tenant_id.as_ref().map(TenantId::new))
62        .ok_or_else(|| {
63            anyhow!("No tenant specified. Use --tenant or configure a tenant in your profile.")
64        })
65}
66
67trait Pipe: Sized {
68    fn pipe<F, R>(self, f: F) -> R
69    where
70        F: FnOnce(Self) -> R,
71    {
72        f(self)
73    }
74}
75
76impl<T> Pipe for T {}