syncable_cli/config/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4/// Main configuration structure
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Config {
7    pub analysis: AnalysisConfig,
8    pub generation: GenerationConfig,
9    pub output: OutputConfig,
10    pub telemetry: TelemetryConfig,
11    #[serde(default)]
12    pub agent: AgentConfig,
13}
14
15/// Analysis configuration
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct AnalysisConfig {
18    pub include_dev_dependencies: bool,
19    pub deep_analysis: bool,
20    pub ignore_patterns: Vec<String>,
21    pub max_file_size: usize,
22}
23
24/// Generation configuration
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct GenerationConfig {
27    pub dockerfile: DockerfileConfig,
28    pub compose: ComposeConfig,
29    pub terraform: TerraformConfig,
30}
31
32/// Dockerfile generation configuration
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct DockerfileConfig {
35    pub base_image_override: Option<String>,
36    pub use_multi_stage: bool,
37    pub optimize_for_size: bool,
38    pub include_health_check: bool,
39}
40
41/// Docker Compose generation configuration
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct ComposeConfig {
44    pub version: String,
45    pub include_database: bool,
46    pub include_redis: bool,
47}
48
49/// Terraform generation configuration
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct TerraformConfig {
52    pub provider: String,
53    pub include_networking: bool,
54    pub include_monitoring: bool,
55}
56
57/// Output configuration
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct OutputConfig {
60    pub format: OutputFormat,
61    pub overwrite_existing: bool,
62    pub create_backup: bool,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub enum OutputFormat {
67    Files,
68    Stdout,
69    Json,
70}
71
72// Telemetry configuration
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct TelemetryConfig {
75    pub enabled: bool,
76}
77
78/// Agent/Chat configuration
79#[derive(Debug, Clone, Serialize, Deserialize, Default)]
80pub struct AgentConfig {
81    /// OpenAI API key (legacy, use profiles instead)
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub openai_api_key: Option<String>,
84    /// Anthropic API key (legacy, use profiles instead)
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub anthropic_api_key: Option<String>,
87    /// AWS Bedrock configuration (legacy, use profiles instead)
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub bedrock: Option<BedrockConfig>,
90    /// AWS Bedrock configured flag (legacy)
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub bedrock_configured: Option<bool>,
93    /// Default provider (openai, anthropic, or bedrock)
94    #[serde(default = "default_provider")]
95    pub default_provider: String,
96    /// Default model
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub default_model: Option<String>,
99
100    // --- Global Profile support ---
101    /// Named profiles containing all provider settings
102    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
103    pub profiles: HashMap<String, Profile>,
104    /// Currently active profile name
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub active_profile: Option<String>,
107
108    // --- Legacy per-provider profiles (deprecated, kept for migration) ---
109    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
110    pub openai_profiles: HashMap<String, OpenAIProfile>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub openai_active_profile: Option<String>,
113    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
114    pub anthropic_profiles: HashMap<String, AnthropicProfile>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub anthropic_active_profile: Option<String>,
117    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
118    pub bedrock_profiles: HashMap<String, BedrockConfig>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub bedrock_active_profile: Option<String>,
121}
122
123/// A global profile containing settings for all providers
124#[derive(Debug, Clone, Serialize, Deserialize, Default)]
125pub struct Profile {
126    /// Description of this profile (e.g., "Work", "Personal")
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub description: Option<String>,
129    /// Default provider for this profile
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub default_provider: Option<String>,
132    /// Default model for this profile
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub default_model: Option<String>,
135    /// OpenAI settings for this profile
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub openai: Option<OpenAIProfile>,
138    /// Anthropic settings for this profile
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub anthropic: Option<AnthropicProfile>,
141    /// Bedrock settings for this profile
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub bedrock: Option<BedrockConfig>,
144}
145
146/// OpenAI profile configuration
147#[derive(Debug, Clone, Serialize, Deserialize, Default)]
148pub struct OpenAIProfile {
149    /// API key for this profile
150    pub api_key: String,
151    /// Optional description/label
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub description: Option<String>,
154    /// Preferred model for this profile
155    #[serde(skip_serializing_if = "Option::is_none")]
156    pub default_model: Option<String>,
157}
158
159/// Anthropic profile configuration
160#[derive(Debug, Clone, Serialize, Deserialize, Default)]
161pub struct AnthropicProfile {
162    /// API key for this profile
163    pub api_key: String,
164    /// Optional description/label
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub description: Option<String>,
167    /// Preferred model for this profile
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub default_model: Option<String>,
170}
171
172/// AWS Bedrock configuration
173#[derive(Debug, Clone, Serialize, Deserialize, Default)]
174pub struct BedrockConfig {
175    /// AWS region (e.g., us-east-1, us-west-2)
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub region: Option<String>,
178    /// AWS profile name from ~/.aws/credentials
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub profile: Option<String>,
181    /// AWS Access Key ID (alternative to profile)
182    #[serde(skip_serializing_if = "Option::is_none")]
183    pub access_key_id: Option<String>,
184    /// AWS Secret Access Key (alternative to profile)
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub secret_access_key: Option<String>,
187    /// AWS Bearer Token for Bedrock (used by Bedrock API Gateway)
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub bearer_token: Option<String>,
190    /// Preferred model ID
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub default_model: Option<String>,
193}
194
195fn default_provider() -> String {
196    "openai".to_string()
197}
198
199impl Default for Config {
200    fn default() -> Self {
201        Self {
202            analysis: AnalysisConfig {
203                include_dev_dependencies: false,
204                deep_analysis: true,
205                ignore_patterns: vec![
206                    "node_modules".to_string(),
207                    ".git".to_string(),
208                    "target".to_string(),
209                    "build".to_string(),
210                ],
211                max_file_size: 1024 * 1024, // 1MB
212            },
213            generation: GenerationConfig {
214                dockerfile: DockerfileConfig {
215                    base_image_override: None,
216                    use_multi_stage: true,
217                    optimize_for_size: true,
218                    include_health_check: true,
219                },
220                compose: ComposeConfig {
221                    version: "3.8".to_string(),
222                    include_database: false,
223                    include_redis: false,
224                },
225                terraform: TerraformConfig {
226                    provider: "docker".to_string(),
227                    include_networking: true,
228                    include_monitoring: false,
229                },
230            },
231            output: OutputConfig {
232                format: OutputFormat::Files,
233                overwrite_existing: false,
234                create_backup: true,
235            },
236            telemetry: TelemetryConfig { enabled: true },
237            agent: AgentConfig::default(),
238        }
239    }
240}