use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use kyma_core::tenant::TenantId;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct MemorySettings {
pub extraction_enabled: bool,
pub min_events: i64,
pub default_limit: usize,
pub default_expand_hops: u8,
pub ann_threshold: f64,
pub w_rrf: f64,
pub w_semantic: f64,
pub w_keyword: f64,
pub w_graph: f64,
pub w_importance: f64,
pub w_recency: f64,
pub half_life_days: f64,
pub rrf_k: f64,
}
impl Default for MemorySettings {
fn default() -> Self {
Self {
extraction_enabled: true,
min_events: 1,
default_limit: 8,
default_expand_hops: 1,
ann_threshold: 0.0,
w_rrf: kyma_memory::W_RRF,
w_semantic: kyma_memory::W_SEMANTIC,
w_keyword: kyma_memory::W_KEYWORD,
w_graph: kyma_memory::W_GRAPH,
w_importance: kyma_memory::W_IMPORTANCE,
w_recency: kyma_memory::W_RECENCY,
half_life_days: kyma_memory::HALF_LIFE_DAYS,
rrf_k: kyma_memory::RRF_K,
}
}
}
pub async fn load(pool: Option<&PgPool>, tenant: TenantId) -> MemorySettings {
let Some(pool) = pool else {
return MemorySettings::default();
};
let row: Option<(serde_json::Value,)> =
sqlx::query_as("SELECT settings FROM memory_settings WHERE tenant_id = $1")
.bind(tenant.as_uuid())
.fetch_optional(pool)
.await
.ok()
.flatten();
match row {
Some((v,)) => serde_json::from_value(v).unwrap_or_default(),
None => MemorySettings::default(),
}
}
pub async fn save(pool: &PgPool, tenant: TenantId, s: &MemorySettings) -> anyhow::Result<()> {
let json = serde_json::to_value(s)?;
sqlx::query(
"INSERT INTO memory_settings (tenant_id, settings, updated_at) \
VALUES ($1, $2, now()) \
ON CONFLICT (tenant_id) DO UPDATE SET settings = $2, updated_at = now()",
)
.bind(tenant.as_uuid())
.bind(json)
.execute(pool)
.await?;
Ok(())
}