agent_diva_files/
config.rs1use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5
6pub const DEFAULT_MAX_FILE_SIZE: u64 = 500 * 1024 * 1024;
8
9pub const DEFAULT_MAX_TOTAL_SIZE: u64 = 10 * 1024 * 1024 * 1024;
11
12pub const DEFAULT_CLEANUP_INTERVAL_SECS: u64 = 3600;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct FileConfig {
18 #[serde(default = "default_storage_path")]
20 pub storage_path: PathBuf,
21
22 #[serde(default = "default_max_file_size")]
24 pub max_file_size: u64,
25
26 #[serde(default = "default_max_total_size")]
28 pub max_total_size: u64,
29
30 #[serde(default = "default_true")]
32 pub deduplication: bool,
33
34 #[serde(default)]
36 pub cleanup: CleanupConfig,
37
38 #[serde(default)]
40 pub channels: ChannelConfigs,
41}
42
43impl Default for FileConfig {
44 fn default() -> Self {
45 Self {
46 storage_path: default_storage_path(),
47 max_file_size: DEFAULT_MAX_FILE_SIZE,
48 max_total_size: DEFAULT_MAX_TOTAL_SIZE,
49 deduplication: true,
50 cleanup: CleanupConfig::default(),
51 channels: ChannelConfigs::default(),
52 }
53 }
54}
55
56impl FileConfig {
57 pub fn with_path(path: impl Into<PathBuf>) -> Self {
59 Self {
60 storage_path: path.into(),
61 ..Default::default()
62 }
63 }
64
65 pub fn data_dir(&self) -> PathBuf {
67 self.storage_path.join("data")
68 }
69
70 pub fn index_path(&self) -> PathBuf {
72 self.storage_path.join("index.jsonl")
73 }
74
75 pub fn config_path(&self) -> PathBuf {
77 self.storage_path.join("config.json")
78 }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct CleanupConfig {
84 #[serde(default)]
86 pub strategy: CleanupStrategy,
87
88 #[serde(default = "default_max_age_days")]
90 pub max_age_days: u32,
91
92 #[serde(default)]
94 pub min_ref_count: i32,
95
96 #[serde(default = "default_cleanup_interval")]
98 pub interval_secs: u64,
99}
100
101impl Default for CleanupConfig {
102 fn default() -> Self {
103 Self {
104 strategy: CleanupStrategy::Lazy,
105 max_age_days: 7,
106 min_ref_count: 0,
107 interval_secs: DEFAULT_CLEANUP_INTERVAL_SECS,
108 }
109 }
110}
111
112#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
114#[serde(rename_all = "snake_case")]
115pub enum CleanupStrategy {
116 Immediate,
118 #[default]
120 Lazy,
121 Scheduled,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct ChannelConfigs {
128 #[serde(default)]
129 pub telegram: ChannelConfig,
130 #[serde(default)]
131 pub discord: ChannelConfig,
132 #[serde(default)]
133 pub slack: ChannelConfig,
134 #[serde(default)]
135 pub ui: UiChannelConfig,
136}
137
138impl Default for ChannelConfigs {
139 fn default() -> Self {
140 Self {
141 telegram: ChannelConfig {
142 enabled: true,
143 max_file_size: 10 * 1024 * 1024, auto_download: true,
145 preview_max_size: 100 * 1024, },
147 discord: ChannelConfig {
148 enabled: true,
149 max_file_size: 20 * 1024 * 1024, auto_download: true,
151 preview_max_size: 100 * 1024,
152 },
153 slack: ChannelConfig {
154 enabled: true,
155 max_file_size: 50 * 1024 * 1024, auto_download: true,
157 preview_max_size: 100 * 1024,
158 },
159 ui: UiChannelConfig {
160 enabled: true,
161 max_file_size: 500 * 1024 * 1024, chunk_size: 10 * 1024 * 1024, stream_upload: true,
164 auto_download: true,
165 preview_max_size: 1024 * 1024, },
167 }
168 }
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize, Default)]
173pub struct ChannelConfig {
174 pub enabled: bool,
175 pub max_file_size: u64,
176 pub auto_download: bool,
177 pub preview_max_size: u64,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, Default)]
182pub struct UiChannelConfig {
183 pub enabled: bool,
184 pub max_file_size: u64,
185 pub chunk_size: u64,
186 pub stream_upload: bool,
187 pub auto_download: bool,
188 pub preview_max_size: u64,
189}
190
191fn default_storage_path() -> PathBuf {
193 dirs::home_dir()
194 .map(|h| h.join(".agent-diva").join("files"))
195 .unwrap_or_else(|| PathBuf::from(".agent-diva/files"))
196}
197
198fn default_max_file_size() -> u64 {
199 DEFAULT_MAX_FILE_SIZE
200}
201
202fn default_max_total_size() -> u64 {
203 DEFAULT_MAX_TOTAL_SIZE
204}
205
206fn default_max_age_days() -> u32 {
207 7
208}
209
210fn default_cleanup_interval() -> u64 {
211 DEFAULT_CLEANUP_INTERVAL_SECS
212}
213
214fn default_true() -> bool {
215 true
216}
217
218pub fn default_data_dir() -> Option<PathBuf> {
228 dirs::data_local_dir().map(|base| base.join("agent-diva").join("files"))
229}
230
231pub fn default_data_dir_or_fallback() -> PathBuf {
236 default_data_dir().unwrap_or_else(|| {
237 dirs::home_dir()
238 .map(|h| h.join(".agent-diva").join("files"))
239 .unwrap_or_else(|| PathBuf::from(".agent-diva/files"))
240 })
241}