use serde::{Deserialize, Serialize};
pub const MAX_IMPORTANCE_CEILING: f64 = 100.0;
pub const MIN_SIMILARITY_LENGTH: usize = 10;
pub const SIMILARITY_THRESHOLD: f64 = 0.85;
pub const MERGE_SIMILARITY_THRESHOLD: f64 = 0.7;
pub const MIN_MEMORY_CONTENT_LENGTH: usize = 20;
pub const MAX_DETECTED_ENTRIES: usize = 5;
pub const MAX_MEMORY_CONTENT_LENGTH: usize = 200;
pub const MAX_DISPLAY_LENGTH: usize = 60;
pub const CONFLICT_OVERLAY_THRESHOLD: f64 = 0.5;
pub const CONFLICT_OVERLAY_THRESHOLD_WITH_SIGNAL: f64 = 0.3;
pub const IMPORTANCE_STAR_THRESHOLD: f64 = 80.0;
pub const CONTEXT_RELEVANCE_WEIGHT: f64 = 0.6;
pub const CONTEXT_IMPORTANCE_WEIGHT: f64 = 0.4;
pub const DEFAULT_MEMORY_EXTRACTOR_MODEL: &str = "claude-3-5-haiku-20241022";
pub const MIN_KEYWORDS_FOR_AI_FALLBACK: usize = 2;
pub const DEFAULT_FAST_MODEL: &str = "claude-3-5-haiku-20241022";
pub const DEFAULT_IMPORTANCE_DECISION: f64 = 75.0;
pub const DEFAULT_IMPORTANCE_SOLUTION: f64 = 70.0;
pub const DEFAULT_IMPORTANCE_PREF: f64 = 65.0;
pub const DEFAULT_IMPORTANCE_FINDING: f64 = 55.0;
pub const DEFAULT_IMPORTANCE_TECH: f64 = 45.0;
pub const DEFAULT_IMPORTANCE_STRUCTURE: f64 = 35.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AiKeywordMode {
#[default]
Auto,
Always,
Never,
}
impl AiKeywordMode {
pub fn from_env() -> Self {
match std::env::var("MEMORY_AI_KEYWORDS")
.unwrap_or_default()
.to_lowercase()
.as_str()
{
"always" | "true" | "1" => AiKeywordMode::Always,
"never" | "false" | "0" => AiKeywordMode::Never,
"auto" | "" => AiKeywordMode::Auto,
other => {
log::warn!(
"Unknown MEMORY_AI_KEYWORDS value: '{}', using 'auto'",
other
);
AiKeywordMode::Auto
}
}
}
pub fn should_use_ai(&self, keyword_count: usize) -> bool {
match self {
AiKeywordMode::Always => true,
AiKeywordMode::Never => false,
AiKeywordMode::Auto => keyword_count < MIN_KEYWORDS_FOR_AI_FALLBACK,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AiDetectionMode {
#[default]
Auto,
Always,
Never,
}
impl AiDetectionMode {
pub fn from_env() -> Self {
match std::env::var("MEMORY_AI_DETECTION")
.unwrap_or_default()
.to_lowercase()
.as_str()
{
"always" | "true" | "1" => AiDetectionMode::Always,
"never" | "false" | "0" => AiDetectionMode::Never,
"auto" | "" => AiDetectionMode::Auto,
other => {
log::warn!(
"Unknown MEMORY_AI_DETECTION value: '{}', using 'auto'",
other
);
AiDetectionMode::Auto
}
}
}
pub fn should_use_ai(&self) -> bool {
match self {
AiDetectionMode::Always => true,
AiDetectionMode::Never => false,
AiDetectionMode::Auto => false, }
}
pub fn should_use_ai_for_text(&self, text_len: usize) -> bool {
match self {
AiDetectionMode::Always => true,
AiDetectionMode::Never => false,
AiDetectionMode::Auto => text_len > 500,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryConfig {
pub max_entries: usize,
pub min_importance: f64,
pub enabled: bool,
pub decay_start_days: i64,
pub decay_rate: f64,
pub reference_increment: f64,
pub max_importance_ceiling: f64,
}
impl Default for MemoryConfig {
fn default() -> Self {
Self {
max_entries: 100,
min_importance: 30.0,
enabled: true,
decay_start_days: 30,
decay_rate: 0.5,
reference_increment: 1.0,
max_importance_ceiling: MAX_IMPORTANCE_CEILING,
}
}
}
impl MemoryConfig {
pub fn with_max_entries(max: usize) -> Self {
Self {
max_entries: max,
..Self::default()
}
}
pub fn minimal() -> Self {
Self {
max_entries: 50,
min_importance: 50.0,
enabled: true,
decay_start_days: 14,
decay_rate: 0.6,
reference_increment: 1.0,
max_importance_ceiling: MAX_IMPORTANCE_CEILING,
}
}
pub fn archival() -> Self {
Self {
max_entries: 500,
min_importance: 20.0,
enabled: true,
decay_start_days: 90,
decay_rate: 0.3,
reference_increment: 3.0,
max_importance_ceiling: MAX_IMPORTANCE_CEILING,
}
}
}