doum_cli/core/
secret.rs

1use crate::llm::{AnthropicSecret, OpenAISecret, Provider};
2use crate::system::SecretManager;
3use anyhow::Result;
4use std::collections::HashMap;
5
6pub struct SecretField {
7    pub name: String,
8    pub label: String,
9    pub required: bool,
10    pub is_password: bool,
11}
12
13pub struct SecretConfigData {
14    pub provider: String,
15    pub fields: Vec<SecretField>,
16}
17
18/// Get secret configuration for a provider
19pub fn get_provider_config(provider: &Provider) -> Result<SecretConfigData> {
20    match provider {
21        Provider::OpenAI => Ok(SecretConfigData {
22            provider: provider.as_str().to_string(),
23            fields: vec![
24                SecretField {
25                    name: "api_key".to_string(),
26                    label: "OpenAI API Key (required)".to_string(),
27                    required: true,
28                    is_password: true,
29                },
30                SecretField {
31                    name: "organization".to_string(),
32                    label: "Organization ID (optional, press Enter to skip)".to_string(),
33                    required: false,
34                    is_password: false,
35                },
36                SecretField {
37                    name: "project".to_string(),
38                    label: "Project ID (optional, press Enter to skip)".to_string(),
39                    required: false,
40                    is_password: false,
41                },
42            ],
43        }),
44        Provider::Anthropic => Ok(SecretConfigData {
45            provider: provider.as_str().to_string(),
46            fields: vec![SecretField {
47                name: "api_key".to_string(),
48                label: "Anthropic API Key (required)".to_string(),
49                required: true,
50                is_password: true,
51            }],
52        }),
53    }
54}
55
56/// Save secrets for a provider
57pub fn save_secrets(provider: &Provider, values: HashMap<String, String>) -> Result<()> {
58    match provider {
59        Provider::OpenAI => {
60            let secret = OpenAISecret {
61                api_key: values
62                    .get("api_key")
63                    .ok_or_else(|| anyhow::anyhow!("API key is required"))?
64                    .clone(),
65                organization: values
66                    .get("organization")
67                    .cloned()
68                    .filter(|s| !s.is_empty()),
69                project: values.get("project").cloned().filter(|s| !s.is_empty()),
70            };
71            SecretManager::save(provider.as_str(), &secret)
72        }
73        Provider::Anthropic => {
74            let secret = AnthropicSecret {
75                api_key: values
76                    .get("api_key")
77                    .ok_or_else(|| anyhow::anyhow!("API key is required"))?
78                    .clone(),
79            };
80            SecretManager::save(provider.as_str(), &secret)
81        }
82    }
83}