Skip to main content

systemprompt_cli/commands/cloud/profile/
api_keys.rs

1use anyhow::{Result, bail};
2use systemprompt_logging::CliService;
3
4use crate::interactive::Prompter;
5
6#[derive(Debug)]
7pub struct ApiKeys {
8    pub gemini: Option<String>,
9    pub anthropic: Option<String>,
10    pub openai: Option<String>,
11}
12
13impl ApiKeys {
14    pub fn from_options(
15        gemini: Option<String>,
16        anthropic: Option<String>,
17        openai: Option<String>,
18    ) -> Result<Self> {
19        if gemini.is_none() && anthropic.is_none() && openai.is_none() {
20            bail!(
21                "At least one AI provider API key is required.\nProvide: --anthropic-key, \
22                 --openai-key, or --gemini-key"
23            );
24        }
25        Ok(Self {
26            gemini,
27            anthropic,
28            openai,
29        })
30    }
31
32    pub const fn selected_provider(&self) -> &'static str {
33        if self.anthropic.is_some() {
34            "anthropic"
35        } else if self.openai.is_some() {
36            "openai"
37        } else if self.gemini.is_some() {
38            "gemini"
39        } else {
40            "anthropic"
41        }
42    }
43}
44
45pub fn collect_api_keys(prompter: &dyn Prompter) -> Result<ApiKeys> {
46    CliService::info("At least one AI provider API key is required.");
47
48    let providers = vec![
49        "Google AI (Gemini) - https://aistudio.google.com/app/apikey".to_owned(),
50        "Anthropic (Claude) - https://console.anthropic.com/api-keys".to_owned(),
51        "OpenAI (GPT) - https://platform.openai.com/api-keys".to_owned(),
52    ];
53
54    let selection = prompter.select("Select your AI provider", &providers)?;
55
56    match selection {
57        0 => {
58            let key = prompter.password("Gemini API Key")?;
59            if key.is_empty() {
60                bail!("API key is required");
61            }
62            Ok(ApiKeys {
63                gemini: Some(key),
64                anthropic: None,
65                openai: None,
66            })
67        },
68        1 => {
69            let key = prompter.password("Anthropic API Key")?;
70            if key.is_empty() {
71                bail!("API key is required");
72            }
73            Ok(ApiKeys {
74                gemini: None,
75                anthropic: Some(key),
76                openai: None,
77            })
78        },
79        2 => {
80            let key = prompter.password("OpenAI API Key")?;
81            if key.is_empty() {
82                bail!("API key is required");
83            }
84            Ok(ApiKeys {
85                gemini: None,
86                anthropic: None,
87                openai: Some(key),
88            })
89        },
90        _ => bail!("Invalid selection"),
91    }
92}