Skip to main content

context_forge/
config.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5use crate::scrub::ScrubConfig;
6
7/// Default recency half-life in hours (72 hours = 3 days).
8pub const DEFAULT_RECENCY_HALF_LIFE_HOURS: f64 = 72.0;
9
10/// Default recency half-life in seconds (72 hours).
11pub const DEFAULT_RECENCY_HALF_LIFE_SECS: f64 = DEFAULT_RECENCY_HALF_LIFE_HOURS * 3600.0;
12
13/// Default maximum absolute lexicon boost applied to the score multiplier.
14///
15/// Deliberately small. The lexicon enters scoring as a multiplier
16/// `1.0 + boost.clamp(-c, c)`, and fused RRF relevance scores are tightly
17/// compressed (the rank-1-to-rank-2 gap is ~1–2%), so a wide bound lets a
18/// query-*independent* importance signal overwhelm relevance and bury the
19/// evidence. On a pure-relevance benchmark (`LongMemEval`) `0.05` recovered ~87%
20/// of the no-lexicon baseline's Recall@1 while still expressing modest
21/// importance; a larger value trades more relevance for more importance weight.
22pub const DEFAULT_LEXICON_BOOST_CLAMP: f64 = 0.05;
23
24/// Runtime configuration for the context engine.
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[non_exhaustive]
27pub struct Config {
28    /// Maximum number of entries to retain.
29    pub max_entries: usize,
30    /// Total token budget for context injection.
31    pub token_budget: usize,
32    /// Path to the backing database file.
33    ///
34    /// The default (`:memory:`) is an in-memory `SQLite` database that is
35    /// **ephemeral** — all data is lost when the connection pool is
36    /// dropped. Set a real filesystem path for durable persistence.
37    pub db_path: PathBuf,
38    /// Strategy used when the store reaches capacity.
39    pub eviction_policy: EvictionPolicy,
40    /// Recency decay half-life in seconds.
41    ///
42    /// Controls how fast older entries lose relevance. A value of 259200 (72 hours)
43    /// means an entry's score halves every 3 days.
44    pub recency_half_life_secs: f64,
45    /// Maximum absolute lexicon boost, i.e. the relevance↔importance dial.
46    ///
47    /// The lexicon scorer's output enters ranking as a multiplier
48    /// `1.0 + boost.clamp(-c, c)` on the fused relevance score, where `c` is this
49    /// value. `0.0` disables lexicon influence entirely (pure relevance);
50    /// larger values give importance signals more weight at the cost of
51    /// relevance precision. See [`DEFAULT_LEXICON_BOOST_CLAMP`] for the rationale
52    /// behind the conservative default. Negative or non-finite values are
53    /// treated as the default.
54    pub lexicon_boost_clamp: f64,
55    /// Secret-scrubbing configuration applied to entry content at save time.
56    pub scrub: ScrubConfig,
57}
58
59impl Default for Config {
60    /// Defaults: 10,000 max entries, an 8,192-token budget, an in-memory
61    /// database (see [`Self::db_path`] for persistence caveats), LRU
62    /// eviction, the default 72-hour recency half-life, and secret
63    /// scrubbing enabled.
64    fn default() -> Self {
65        Self {
66            max_entries: 10_000,
67            token_budget: 8192,
68            db_path: PathBuf::from(":memory:"),
69            eviction_policy: EvictionPolicy::Lru,
70            recency_half_life_secs: DEFAULT_RECENCY_HALF_LIFE_SECS,
71            lexicon_boost_clamp: DEFAULT_LEXICON_BOOST_CLAMP,
72            scrub: ScrubConfig::default(),
73        }
74    }
75}
76
77/// Strategy for evicting entries when at capacity.
78#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
79#[non_exhaustive]
80pub enum EvictionPolicy {
81    /// Least-recently-used entries are evicted first.
82    Lru,
83}