systemprompt_cli/commands/cloud/profile/
api_keys.rs1use anyhow::{bail, Result};
2use dialoguer::theme::ColorfulTheme;
3use dialoguer::{Password, Select};
4use systemprompt_logging::CliService;
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
33pub fn collect_api_keys() -> Result<ApiKeys> {
34 CliService::info("At least one AI provider API key is required.");
35
36 let providers = vec![
37 "Google AI (Gemini) - https://aistudio.google.com/app/apikey",
38 "Anthropic (Claude) - https://console.anthropic.com/api-keys",
39 "OpenAI (GPT) - https://platform.openai.com/api-keys",
40 ];
41
42 let selection = Select::with_theme(&ColorfulTheme::default())
43 .with_prompt("Select your AI provider")
44 .items(&providers)
45 .default(0)
46 .interact()?;
47
48 match selection {
49 0 => {
50 let key = Password::with_theme(&ColorfulTheme::default())
51 .with_prompt("Gemini API Key")
52 .interact()?;
53 if key.is_empty() {
54 bail!("API key is required");
55 }
56 Ok(ApiKeys {
57 gemini: Some(key),
58 anthropic: None,
59 openai: None,
60 })
61 },
62 1 => {
63 let key = Password::with_theme(&ColorfulTheme::default())
64 .with_prompt("Anthropic API Key")
65 .interact()?;
66 if key.is_empty() {
67 bail!("API key is required");
68 }
69 Ok(ApiKeys {
70 gemini: None,
71 anthropic: Some(key),
72 openai: None,
73 })
74 },
75 2 => {
76 let key = Password::with_theme(&ColorfulTheme::default())
77 .with_prompt("OpenAI API Key")
78 .interact()?;
79 if key.is_empty() {
80 bail!("API key is required");
81 }
82 Ok(ApiKeys {
83 gemini: None,
84 anthropic: None,
85 openai: Some(key),
86 })
87 },
88 _ => bail!("Invalid selection"),
89 }
90}