use serde::{Deserialize, Serialize};
use std::path::PathBuf;
pub const DEFAULT_MAX_FILE_SIZE: u64 = 500 * 1024 * 1024;
pub const DEFAULT_MAX_TOTAL_SIZE: u64 = 10 * 1024 * 1024 * 1024;
pub const DEFAULT_CLEANUP_INTERVAL_SECS: u64 = 3600;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileConfig {
#[serde(default = "default_storage_path")]
pub storage_path: PathBuf,
#[serde(default = "default_max_file_size")]
pub max_file_size: u64,
#[serde(default = "default_max_total_size")]
pub max_total_size: u64,
#[serde(default = "default_true")]
pub deduplication: bool,
#[serde(default)]
pub cleanup: CleanupConfig,
#[serde(default)]
pub channels: ChannelConfigs,
}
impl Default for FileConfig {
fn default() -> Self {
Self {
storage_path: default_storage_path(),
max_file_size: DEFAULT_MAX_FILE_SIZE,
max_total_size: DEFAULT_MAX_TOTAL_SIZE,
deduplication: true,
cleanup: CleanupConfig::default(),
channels: ChannelConfigs::default(),
}
}
}
impl FileConfig {
pub fn with_path(path: impl Into<PathBuf>) -> Self {
Self {
storage_path: path.into(),
..Default::default()
}
}
pub fn data_dir(&self) -> PathBuf {
self.storage_path.join("data")
}
pub fn index_path(&self) -> PathBuf {
self.storage_path.join("index.jsonl")
}
pub fn config_path(&self) -> PathBuf {
self.storage_path.join("config.json")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupConfig {
#[serde(default)]
pub strategy: CleanupStrategy,
#[serde(default = "default_max_age_days")]
pub max_age_days: u32,
#[serde(default)]
pub min_ref_count: i32,
#[serde(default = "default_cleanup_interval")]
pub interval_secs: u64,
}
impl Default for CleanupConfig {
fn default() -> Self {
Self {
strategy: CleanupStrategy::Lazy,
max_age_days: 7,
min_ref_count: 0,
interval_secs: DEFAULT_CLEANUP_INTERVAL_SECS,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case")]
pub enum CleanupStrategy {
Immediate,
#[default]
Lazy,
Scheduled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChannelConfigs {
#[serde(default)]
pub telegram: ChannelConfig,
#[serde(default)]
pub discord: ChannelConfig,
#[serde(default)]
pub slack: ChannelConfig,
#[serde(default)]
pub ui: UiChannelConfig,
}
impl Default for ChannelConfigs {
fn default() -> Self {
Self {
telegram: ChannelConfig {
enabled: true,
max_file_size: 10 * 1024 * 1024, auto_download: true,
preview_max_size: 100 * 1024, },
discord: ChannelConfig {
enabled: true,
max_file_size: 20 * 1024 * 1024, auto_download: true,
preview_max_size: 100 * 1024,
},
slack: ChannelConfig {
enabled: true,
max_file_size: 50 * 1024 * 1024, auto_download: true,
preview_max_size: 100 * 1024,
},
ui: UiChannelConfig {
enabled: true,
max_file_size: 500 * 1024 * 1024, chunk_size: 10 * 1024 * 1024, stream_upload: true,
auto_download: true,
preview_max_size: 1024 * 1024, },
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ChannelConfig {
pub enabled: bool,
pub max_file_size: u64,
pub auto_download: bool,
pub preview_max_size: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct UiChannelConfig {
pub enabled: bool,
pub max_file_size: u64,
pub chunk_size: u64,
pub stream_upload: bool,
pub auto_download: bool,
pub preview_max_size: u64,
}
fn default_storage_path() -> PathBuf {
dirs::home_dir()
.map(|h| h.join(".agent-diva").join("files"))
.unwrap_or_else(|| PathBuf::from(".agent-diva/files"))
}
fn default_max_file_size() -> u64 {
DEFAULT_MAX_FILE_SIZE
}
fn default_max_total_size() -> u64 {
DEFAULT_MAX_TOTAL_SIZE
}
fn default_max_age_days() -> u32 {
7
}
fn default_cleanup_interval() -> u64 {
DEFAULT_CLEANUP_INTERVAL_SECS
}
fn default_true() -> bool {
true
}
pub fn default_data_dir() -> Option<PathBuf> {
dirs::data_local_dir().map(|base| base.join("agent-diva").join("files"))
}
pub fn default_data_dir_or_fallback() -> PathBuf {
default_data_dir().unwrap_or_else(|| {
dirs::home_dir()
.map(|h| h.join(".agent-diva").join("files"))
.unwrap_or_else(|| PathBuf::from(".agent-diva/files"))
})
}