| 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;
|
|
|
| embeddingSource: "remote" | "static" | "transformers" | "auto";
|
| embeddingProviderModel: string | null;
|
| transformersEnabled: boolean;
|
| staticEnabled: boolean;
|
| rerankEnabled: boolean;
|
| rerankProviderModel: string | null;
|
| vectorStore: "sqlite-vec" | "qdrant" | "auto";
|
| }
|
|
|
| export const DEFAULT_MEMORY_SETTINGS: MemorySettings = {
|
| enabled: true,
|
| maxTokens: 2000,
|
| retentionDays: 30,
|
| strategy: "hybrid",
|
| skillsEnabled: true,
|
|
|
| embeddingSource: "auto",
|
| embeddingProviderModel: null,
|
| transformersEnabled: false,
|
| staticEnabled: false,
|
| rerankEnabled: false,
|
| rerankProviderModel: null,
|
| vectorStore: "auto",
|
| };
|
|
|
| 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;
|
| }
|
|
|
| function normalizeEmbeddingSource(value: unknown): MemorySettings["embeddingSource"] {
|
| return value === "remote" || value === "static" || value === "transformers" || value === "auto"
|
| ? value
|
| : DEFAULT_MEMORY_SETTINGS.embeddingSource;
|
| }
|
|
|
| function normalizeVectorStore(value: unknown): MemorySettings["vectorStore"] {
|
| return value === "sqlite-vec" || value === "qdrant" || value === "auto"
|
| ? value
|
| : DEFAULT_MEMORY_SETTINGS.vectorStore;
|
| }
|
|
|
| function normalizeNullableString(value: unknown, fallback: string | null): string | null {
|
| if (value === null || value === undefined) return fallback;
|
| return typeof value === "string" && value.length > 0 ? value : fallback;
|
| }
|
|
|
| export function normalizeMemorySettings(rawSettings: Record<string, unknown> = {}): 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),
|
|
|
| embeddingSource: normalizeEmbeddingSource(rawSettings.memoryEmbeddingSource),
|
| embeddingProviderModel: normalizeNullableString(
|
| rawSettings.memoryEmbeddingProviderModel,
|
| DEFAULT_MEMORY_SETTINGS.embeddingProviderModel
|
| ),
|
| transformersEnabled: toBoolean(
|
| rawSettings.memoryTransformersEnabled,
|
| DEFAULT_MEMORY_SETTINGS.transformersEnabled
|
| ),
|
| staticEnabled: toBoolean(rawSettings.memoryStaticEnabled, DEFAULT_MEMORY_SETTINGS.staticEnabled),
|
| rerankEnabled: toBoolean(rawSettings.memoryRerankEnabled, DEFAULT_MEMORY_SETTINGS.rerankEnabled),
|
| rerankProviderModel: normalizeNullableString(
|
| rawSettings.memoryRerankProviderModel,
|
| DEFAULT_MEMORY_SETTINGS.rerankProviderModel
|
| ),
|
| vectorStore: normalizeVectorStore(rawSettings.memoryVectorStore),
|
| };
|
| }
|
|
|
| export function toMemorySettingsUpdates(
|
| settings: Partial<MemorySettings>
|
| ): Record<string, unknown> {
|
| const updates: Record<string, unknown> = {};
|
|
|
| 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;
|
|
|
| if (settings.embeddingSource !== undefined)
|
| updates.memoryEmbeddingSource = settings.embeddingSource;
|
| if (settings.embeddingProviderModel !== undefined)
|
| updates.memoryEmbeddingProviderModel = settings.embeddingProviderModel;
|
| if (settings.transformersEnabled !== undefined)
|
| updates.memoryTransformersEnabled = settings.transformersEnabled;
|
| if (settings.staticEnabled !== undefined) updates.memoryStaticEnabled = settings.staticEnabled;
|
| if (settings.rerankEnabled !== undefined) updates.memoryRerankEnabled = settings.rerankEnabled;
|
| if (settings.rerankProviderModel !== undefined)
|
| updates.memoryRerankProviderModel = settings.rerankProviderModel;
|
| if (settings.vectorStore !== undefined) updates.memoryVectorStore = settings.vectorStore;
|
|
|
| return updates;
|
| }
|
|
|
| export function toMemoryRetrievalConfig(
|
| settings: MemorySettings,
|
| extra: { query?: string } = {}
|
| ): Partial<MemoryConfig> & { query?: string } {
|
| const enabled = settings.enabled && settings.maxTokens > 0;
|
|
|
| const config: Partial<MemoryConfig> & { query?: string } = {
|
| enabled,
|
| maxTokens: enabled ? settings.maxTokens : 0,
|
| retrievalStrategy: settings.strategy === "recent" ? "exact" : settings.strategy,
|
| autoSummarize: false,
|
| persistAcrossModels: false,
|
| retentionDays: settings.retentionDays,
|
| scope: "apiKey",
|
| };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if (extra.query && extra.query.trim().length > 0 && settings.strategy !== "recent") {
|
| config.query = extra.query.trim();
|
| }
|
|
|
| return config;
|
| }
|
|
|
| export async function getMemorySettings(): Promise<MemorySettings> {
|
| if (cachedMemorySettings !== null) {
|
| return cachedMemorySettings;
|
| }
|
|
|
| const settings = (await getSettings()) as Record<string, unknown>;
|
| cachedMemorySettings = normalizeMemorySettings(settings);
|
| return cachedMemorySettings;
|
| }
|
|
|
| export function invalidateMemorySettingsCache(): void {
|
| cachedMemorySettings = null;
|
| }
|
|
|