codetether_agent/tui/chat/sync/
config.rs1use super::config_types::*;
4use super::env_helpers::{env_bool, env_non_empty, env_non_placeholder};
5
6fn vault_str(s: &crate::secrets::ProviderSecrets, keys: &[&str]) -> Option<String> {
7 keys.iter().find_map(|k| {
8 s.extra
9 .get(*k)
10 .and_then(|v| v.as_str())
11 .map(|v| v.trim().to_string())
12 .filter(|v| !v.is_empty())
13 })
14}
15
16fn vault_bool_val(s: &crate::secrets::ProviderSecrets, keys: &[&str]) -> Option<bool> {
17 keys.iter().find_map(|k| {
18 s.extra
19 .get(*k)
20 .and_then(|v| v.as_str())
21 .and_then(|v| match v {
22 "true" | "1" | "yes" => Some(true),
23 "false" | "0" | "no" => Some(false),
24 _ => None,
25 })
26 })
27}
28
29pub async fn parse_chat_sync_config(required: bool) -> Result<Option<ChatSyncConfig>, String> {
31 if !env_bool("CODETETHER_CHAT_SYNC_ENABLED").unwrap_or(false) {
32 if required {
33 return Err("CODETETHER_CHAT_SYNC_ENABLED must be true".into());
34 }
35 return Ok(None);
36 }
37 let vault = crate::secrets::get_provider_secrets("chat-sync-minio").await;
38 let ep_raw = env_non_empty("CODETETHER_CHAT_SYNC_MINIO_ENDPOINT")
39 .or_else(|| {
40 vault.as_ref().and_then(|s| {
41 s.base_url
42 .clone()
43 .filter(|v| !v.trim().is_empty())
44 .or_else(|| vault_str(s, &["endpoint", "minio_endpoint"]))
45 })
46 })
47 .ok_or("CODETETHER_CHAT_SYNC_MINIO_ENDPOINT required")?;
48 let endpoint = normalize_minio_endpoint(&ep_raw);
49 let ak = env_non_placeholder("CODETETHER_CHAT_SYNC_MINIO_ACCESS_KEY")
50 .or_else(|| {
51 vault.as_ref().and_then(|s| {
52 vault_str(s, &["access_key", "api_key"]).or_else(|| {
53 s.api_key
54 .as_ref()
55 .map(|v: &String| v.trim().to_string())
56 .filter(|v: &String| !v.is_empty())
57 })
58 })
59 })
60 .ok_or("CODETETHER_CHAT_SYNC_MINIO_ACCESS_KEY required")?;
61 let sk = env_non_placeholder("CODETETHER_CHAT_SYNC_MINIO_SECRET_KEY")
62 .or_else(|| {
63 vault
64 .as_ref()
65 .and_then(|s| vault_str(s, &["secret_key", "password", "secret"]))
66 })
67 .ok_or("CODETETHER_CHAT_SYNC_MINIO_SECRET_KEY required")?;
68 let bucket = env_non_empty("CODETETHER_CHAT_SYNC_MINIO_BUCKET")
69 .or_else(|| vault.as_ref().and_then(|s| vault_str(s, &["bucket"])))
70 .unwrap_or_else(|| CHAT_SYNC_DEFAULT_BUCKET.into());
71 let prefix = env_non_empty("CODETETHER_CHAT_SYNC_MINIO_PREFIX")
72 .or_else(|| vault.as_ref().and_then(|s| vault_str(s, &["prefix"])))
73 .unwrap_or_else(|| CHAT_SYNC_DEFAULT_PREFIX.into())
74 .trim_matches('/')
75 .to_string();
76 let iv = env_non_empty("CODETETHER_CHAT_SYNC_INTERVAL_SECS")
77 .and_then(|v| v.parse::<u64>().ok())
78 .unwrap_or(CHAT_SYNC_DEFAULT_INTERVAL_SECS)
79 .clamp(1, CHAT_SYNC_MAX_INTERVAL_SECS);
80 let tls = env_bool("CODETETHER_CHAT_SYNC_MINIO_INSECURE_SKIP_TLS_VERIFY")
81 .or_else(|| {
82 vault
83 .as_ref()
84 .and_then(|s| vault_bool_val(s, &["insecure_skip_tls_verify"]))
85 })
86 .unwrap_or(false);
87 Ok(Some(ChatSyncConfig {
88 endpoint: endpoint.clone(),
89 fallback_endpoint: minio_fallback_endpoint(&endpoint),
90 access_key: ak,
91 secret_key: sk,
92 bucket,
93 prefix,
94 interval_secs: iv,
95 ignore_cert_check: tls,
96 }))
97}