doum_cli/core/
secret.rs

1use crate::llm::{AnthropicSecret, OpenAISecret};
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
18pub struct SecretService;
19
20impl SecretService {
21    /// Get secret configuration for a provider
22    pub fn get_provider_config(provider: &str) -> Result<SecretConfigData> {
23        match provider {
24            "openai" => Ok(SecretConfigData {
25                provider: "openai".to_string(),
26                fields: vec![
27                    SecretField {
28                        name: "api_key".to_string(),
29                        label: "OpenAI API Key (required)".to_string(),
30                        required: true,
31                        is_password: true,
32                    },
33                    SecretField {
34                        name: "organization".to_string(),
35                        label: "Organization ID (optional, press Enter to skip)".to_string(),
36                        required: false,
37                        is_password: false,
38                    },
39                    SecretField {
40                        name: "project".to_string(),
41                        label: "Project ID (optional, press Enter to skip)".to_string(),
42                        required: false,
43                        is_password: false,
44                    },
45                ],
46            }),
47            "anthropic" => Ok(SecretConfigData {
48                provider: "anthropic".to_string(),
49                fields: vec![SecretField {
50                    name: "api_key".to_string(),
51                    label: "Anthropic API Key (required)".to_string(),
52                    required: true,
53                    is_password: true,
54                }],
55            }),
56            _ => anyhow::bail!("Unknown provider: {}", provider),
57        }
58    }
59
60    /// Save secrets for a provider
61    pub fn save_secrets(provider: &str, values: HashMap<String, String>) -> Result<()> {
62        match provider {
63            "openai" => {
64                let secret = OpenAISecret {
65                    api_key: values
66                        .get("api_key")
67                        .ok_or_else(|| anyhow::anyhow!("API key is required"))?
68                        .clone(),
69                    organization: values
70                        .get("organization")
71                        .cloned()
72                        .filter(|s| !s.is_empty()),
73                    project: values.get("project").cloned().filter(|s| !s.is_empty()),
74                };
75                SecretManager::save("openai", &secret)
76            }
77            "anthropic" => {
78                let secret = AnthropicSecret {
79                    api_key: values
80                        .get("api_key")
81                        .ok_or_else(|| anyhow::anyhow!("API key is required"))?
82                        .clone(),
83                };
84                SecretManager::save("anthropic", &secret)
85            }
86            _ => anyhow::bail!("Unknown provider: {}", provider),
87        }
88    }
89
90    /// List all available providers
91    pub fn list_providers() -> Vec<String> {
92        vec!["openai".to_string(), "anthropic".to_string()]
93    }
94}