systemprompt-cli 0.21.1

Unified CLI for systemprompt.io AI governance: agent orchestration, MCP governance, analytics, profiles, cloud deploy, and self-hosted operations.
Documentation
//! Provider API-key collection during profile creation.
//!
//! Copyright (c) systemprompt.io — Business Source License 1.1.
//! See <https://systemprompt.io> for licensing details.

use anyhow::{Result, bail};
use systemprompt_logging::CliService;

use crate::interactive::Prompter;

#[derive(Debug)]
pub struct ApiKeys {
    pub gemini: Option<String>,
    pub anthropic: Option<String>,
    pub openai: Option<String>,
}

impl ApiKeys {
    pub fn from_options(
        gemini: Option<String>,
        anthropic: Option<String>,
        openai: Option<String>,
    ) -> Result<Self> {
        if gemini.is_none() && anthropic.is_none() && openai.is_none() {
            bail!(
                "At least one AI provider API key is required.\nProvide: --anthropic-key, \
                 --openai-key, or --gemini-key"
            );
        }
        Ok(Self {
            gemini,
            anthropic,
            openai,
        })
    }

    pub const fn selected_provider(&self) -> &'static str {
        if self.anthropic.is_some() {
            "anthropic"
        } else if self.openai.is_some() {
            "openai"
        } else if self.gemini.is_some() {
            "gemini"
        } else {
            "anthropic"
        }
    }
}

pub fn collect_api_keys(prompter: &dyn Prompter) -> Result<ApiKeys> {
    CliService::info("At least one AI provider API key is required.");

    let providers = vec![
        "Google AI (Gemini) - https://aistudio.google.com/app/apikey".to_owned(),
        "Anthropic (Claude) - https://console.anthropic.com/api-keys".to_owned(),
        "OpenAI (GPT) - https://platform.openai.com/api-keys".to_owned(),
    ];

    let selection = prompter.select("Select your AI provider", &providers)?;

    match selection {
        0 => {
            let key = prompter.password("Gemini API Key")?;
            if key.is_empty() {
                bail!("API key is required");
            }
            Ok(ApiKeys {
                gemini: Some(key),
                anthropic: None,
                openai: None,
            })
        },
        1 => {
            let key = prompter.password("Anthropic API Key")?;
            if key.is_empty() {
                bail!("API key is required");
            }
            Ok(ApiKeys {
                gemini: None,
                anthropic: Some(key),
                openai: None,
            })
        },
        2 => {
            let key = prompter.password("OpenAI API Key")?;
            if key.is_empty() {
                bail!("API key is required");
            }
            Ok(ApiKeys {
                gemini: None,
                anthropic: None,
                openai: Some(key),
            })
        },
        _ => bail!("Invalid selection"),
    }
}