File size: 3,139 Bytes
35743bd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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<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),
  };
}

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;

  return updates;
}

export function toMemoryRetrievalConfig(settings: MemorySettings): Partial<MemoryConfig> {
  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<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;
}