Skip to main content

vtcode_core/utils/session_archive/
settings.rs

1use std::env;
2#[cfg(test)]
3use std::path::Path;
4use std::sync::{Mutex, OnceLock};
5
6use crate::config::{HistoryPersistence, VTCodeConfig};
7
8pub const SESSION_DIR_ENV: &str = "VT_SESSION_DIR";
9pub const SESSION_MAX_FILES_ENV: &str = "VT_SESSION_MAX_FILES";
10pub const SESSION_MAX_AGE_DAYS_ENV: &str = "VT_SESSION_MAX_AGE_DAYS";
11pub const SESSION_MAX_SIZE_MB_ENV: &str = "VT_SESSION_MAX_SIZE_MB";
12
13#[derive(Debug, Clone, Copy)]
14pub(crate) struct SessionHistorySettings {
15    pub(crate) persistence: HistoryPersistence,
16    pub(crate) max_bytes: Option<usize>,
17}
18
19impl Default for SessionHistorySettings {
20    fn default() -> Self {
21        Self {
22            persistence: HistoryPersistence::File,
23            max_bytes: None,
24        }
25    }
26}
27
28static SESSION_HISTORY_SETTINGS: OnceLock<Mutex<SessionHistorySettings>> = OnceLock::new();
29
30pub(crate) fn session_history_settings() -> SessionHistorySettings {
31    SESSION_HISTORY_SETTINGS
32        .get()
33        .map(|settings| *settings.lock().unwrap_or_else(|e| e.into_inner()))
34        .unwrap_or_default()
35}
36
37pub fn apply_session_history_config_from_vtcode(config: &VTCodeConfig) {
38    let settings = SessionHistorySettings {
39        persistence: config.history.persistence,
40        max_bytes: config.history.max_bytes,
41    };
42    let cell = SESSION_HISTORY_SETTINGS.get_or_init(|| Mutex::new(SessionHistorySettings::default()));
43    if let Ok(mut guard) = cell.lock() {
44        *guard = settings;
45    }
46}
47
48pub fn history_persistence_enabled() -> bool {
49    matches!(session_history_settings().persistence, HistoryPersistence::File)
50}
51
52pub(crate) fn read_env_var_os(key: &str) -> Option<std::ffi::OsString> {
53    #[cfg(test)]
54    if let Some(override_value) = test_env_overrides::get(key) {
55        return override_value;
56    }
57
58    env::var_os(key)
59}
60
61pub(crate) fn read_env_var(key: &str) -> Option<String> {
62    #[cfg(test)]
63    if let Some(override_value) = test_env_overrides::get(key) {
64        return override_value.map(|value| value.to_string_lossy().to_string());
65    }
66
67    env::var(key).ok()
68}
69
70#[cfg(test)]
71pub(crate) fn set_test_env_override_path(key: &str, value: &Path) {
72    test_env_overrides::set(key, Some(value.as_os_str().to_os_string()));
73}
74
75#[cfg(test)]
76pub(crate) fn clear_test_env_override(key: &str) {
77    test_env_overrides::clear(key);
78}
79
80#[cfg(test)]
81pub(crate) fn override_sessions_dir_for_tests(path: &Path) {
82    set_test_env_override_path(SESSION_DIR_ENV, path);
83}
84
85#[cfg(test)]
86pub(crate) fn clear_sessions_dir_override_for_tests() {
87    clear_test_env_override(SESSION_DIR_ENV);
88}
89
90#[cfg(test)]
91mod test_env_overrides {
92    use hashbrown::HashMap;
93    use std::ffi::OsString;
94    use std::sync::{LazyLock, Mutex};
95
96    static OVERRIDES: LazyLock<Mutex<HashMap<String, Option<OsString>>>> = LazyLock::new(|| Mutex::new(HashMap::new()));
97
98    pub(super) fn get(key: &str) -> Option<Option<OsString>> {
99        OVERRIDES.lock().ok().and_then(|map| map.get(key).cloned())
100    }
101
102    pub(super) fn set(key: &str, value: Option<OsString>) {
103        if let Ok(mut map) = OVERRIDES.lock() {
104            map.insert(key.to_owned(), value);
105        }
106    }
107
108    pub(super) fn clear(key: &str) {
109        if let Ok(mut map) = OVERRIDES.lock() {
110            map.remove(key);
111        }
112    }
113}