import { getSettings } from "@/lib/db/settings"; import type { MemoryConfig } from "./types"; export interface MemorySettings { enabled: boolean; maxTokens: number; retentionDays: number; strategy: "recent" | "semantic" | "hybrid"; skillsEnabled: boolean; } export const DEFAULT_MEMORY_SETTINGS: MemorySettings = { enabled: true, maxTokens: 2000, retentionDays: 30, strategy: "hybrid", skillsEnabled: false, }; let cachedMemorySettings: MemorySettings | null = null; function toBoolean(value: unknown, fallback: boolean): boolean { return typeof value === "boolean" ? value : fallback; } function clampInteger(value: unknown, fallback: number, min: number, max: number): number { if (typeof value !== "number" || !Number.isFinite(value)) return fallback; return Math.min(Math.max(Math.round(value), min), max); } function normalizeStrategy(value: unknown): MemorySettings["strategy"] { return value === "recent" || value === "semantic" || value === "hybrid" ? value : DEFAULT_MEMORY_SETTINGS.strategy; } export function normalizeMemorySettings(rawSettings: Record = {}): MemorySettings { return { enabled: toBoolean(rawSettings.memoryEnabled, DEFAULT_MEMORY_SETTINGS.enabled), maxTokens: clampInteger( rawSettings.memoryMaxTokens, DEFAULT_MEMORY_SETTINGS.maxTokens, 0, 16000 ), retentionDays: clampInteger( rawSettings.memoryRetentionDays, DEFAULT_MEMORY_SETTINGS.retentionDays, 1, 365 ), strategy: normalizeStrategy(rawSettings.memoryStrategy), skillsEnabled: toBoolean(rawSettings.skillsEnabled, DEFAULT_MEMORY_SETTINGS.skillsEnabled), }; } export function toMemorySettingsUpdates( settings: Partial ): Record { const updates: Record = {}; if (settings.enabled !== undefined) updates.memoryEnabled = settings.enabled; if (settings.maxTokens !== undefined) updates.memoryMaxTokens = settings.maxTokens; if (settings.retentionDays !== undefined) updates.memoryRetentionDays = settings.retentionDays; if (settings.strategy !== undefined) updates.memoryStrategy = settings.strategy; if (settings.skillsEnabled !== undefined) updates.skillsEnabled = settings.skillsEnabled; return updates; } export function toMemoryRetrievalConfig(settings: MemorySettings): Partial { const enabled = settings.enabled && settings.maxTokens > 0; return { enabled, maxTokens: enabled ? settings.maxTokens : 0, retrievalStrategy: settings.strategy === "recent" ? "exact" : settings.strategy, autoSummarize: false, persistAcrossModels: false, retentionDays: settings.retentionDays, scope: "apiKey", }; } export async function getMemorySettings(): Promise { if (cachedMemorySettings !== null) { return cachedMemorySettings; } const settings = (await getSettings()) as Record; cachedMemorySettings = normalizeMemorySettings(settings); return cachedMemorySettings; } export function invalidateMemorySettingsCache(): void { cachedMemorySettings = null; }