systemprompt_cli/commands/cloud/tenant/
select.rs1use anyhow::{Result, anyhow, bail};
2use systemprompt_cloud::{
3 CloudCredentials, CloudPath, CredentialsBootstrap, StoredTenant, TenantType, get_cloud_paths,
4};
5use systemprompt_config::ProfileBootstrap;
6use systemprompt_identifiers::TenantId;
7
8use crate::interactive::Prompter;
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).map_err(Into::into)
28 } else {
29 bail!("Not logged in. Run 'systemprompt cloud login' first.")
30 }
31}
32
33pub fn select_tenant<'a>(
34 prompter: &dyn Prompter,
35 tenants: &'a [StoredTenant],
36) -> Result<&'a StoredTenant> {
37 let options: Vec<String> = tenants
38 .iter()
39 .map(|t| {
40 let type_str = match t.tenant_type {
41 TenantType::Local => "local",
42 TenantType::Cloud => "cloud",
43 };
44 format!("{} ({})", t.name, type_str)
45 })
46 .collect();
47
48 let selection = prompter.select("Select tenant", &options)?;
49
50 Ok(&tenants[selection])
51}
52
53pub fn resolve_tenant_id(tenant: Option<String>) -> Result<TenantId> {
54 if let Some(id) = tenant {
55 return Ok(TenantId::new(id));
56 }
57
58 ProfileBootstrap::get()
59 .ok()
60 .and_then(|p| p.cloud.as_ref()?.tenant_id.as_ref().map(TenantId::new))
61 .ok_or_else(|| {
62 anyhow!("No tenant specified. Use --tenant or configure a tenant in your profile.")
63 })
64}
65
66trait Pipe: Sized {
67 fn pipe<F, R>(self, f: F) -> R
68 where
69 F: FnOnce(Self) -> R,
70 {
71 f(self)
72 }
73}
74
75impl<T> Pipe for T {}