Skip to main content

systemprompt_cli/commands/cloud/profile/
create_tenant.rs

1//! Tenant-type selection (local or cloud) during profile creation.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use anyhow::{Result, bail};
7use systemprompt_cloud::{StoredTenant, TenantStore, TenantType};
8
9use crate::interactive::Prompter;
10
11pub fn select_tenant_type(prompter: &dyn Prompter, store: &TenantStore) -> Result<TenantType> {
12    let local_count = store
13        .tenants
14        .iter()
15        .filter(|t| t.tenant_type == TenantType::Local)
16        .count();
17    let cloud_count = store
18        .tenants
19        .iter()
20        .filter(|t| t.tenant_type == TenantType::Cloud)
21        .count();
22
23    let local_label = match local_count {
24        0 => "Local - no tenants available".to_owned(),
25        1 => "Local - 1 tenant available".to_owned(),
26        n => format!("Local - {} tenants available", n),
27    };
28
29    let cloud_label = match cloud_count {
30        0 => "Cloud - no tenants available".to_owned(),
31        1 => "Cloud - 1 tenant available".to_owned(),
32        n => format!("Cloud - {} tenants available", n),
33    };
34
35    let options = vec![local_label, cloud_label];
36
37    let selection = prompter.select("Profile type", &options)?;
38
39    if selection == 0 {
40        if local_count == 0 {
41            bail!(
42                "No local tenants available.\nRun 'systemprompt cloud tenant create' (or 'just \
43                 tenant') and select 'Local' to create one."
44            );
45        }
46        Ok(TenantType::Local)
47    } else {
48        if cloud_count == 0 {
49            bail!(
50                "No cloud tenants available.\nRun 'systemprompt cloud tenant create' (or 'just \
51                 tenant') and select 'Cloud' to create one."
52            );
53        }
54        Ok(TenantType::Cloud)
55    }
56}
57
58pub(super) fn get_tenants_by_type(
59    store: &TenantStore,
60    tenant_type: TenantType,
61) -> Vec<StoredTenant> {
62    store
63        .tenants
64        .iter()
65        .filter(|t| t.tenant_type == tenant_type)
66        .cloned()
67        .collect()
68}
69
70pub fn select_tenant(prompter: &dyn Prompter, tenants: &[StoredTenant]) -> Result<StoredTenant> {
71    if tenants.is_empty() {
72        bail!("No eligible tenants found.");
73    }
74
75    let options: Vec<String> = tenants
76        .iter()
77        .map(|t| {
78            let db_status = if t.has_database_url() {
79                "✓ db"
80            } else {
81                "✗ db"
82            };
83            format!("{} [{}]", t.name, db_status)
84        })
85        .collect();
86
87    let selection = prompter.select("Select tenant", &options)?;
88
89    Ok(tenants[selection].clone())
90}