family-ai-agent 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/.letta/settings.local.json +3 -0
  2. package/dist/database/adapters/base-adapter.d.ts +81 -0
  3. package/dist/database/adapters/base-adapter.d.ts.map +1 -0
  4. package/dist/database/adapters/base-adapter.js +105 -0
  5. package/dist/database/adapters/base-adapter.js.map +1 -0
  6. package/dist/database/adapters/index.d.ts +49 -0
  7. package/dist/database/adapters/index.d.ts.map +1 -0
  8. package/dist/database/adapters/index.js +200 -0
  9. package/dist/database/adapters/index.js.map +1 -0
  10. package/dist/database/adapters/postgres-adapter.d.ts +75 -0
  11. package/dist/database/adapters/postgres-adapter.d.ts.map +1 -0
  12. package/dist/database/adapters/postgres-adapter.js +225 -0
  13. package/dist/database/adapters/postgres-adapter.js.map +1 -0
  14. package/dist/database/adapters/sqlite-adapter.d.ts +72 -0
  15. package/dist/database/adapters/sqlite-adapter.d.ts.map +1 -0
  16. package/dist/database/adapters/sqlite-adapter.js +368 -0
  17. package/dist/database/adapters/sqlite-adapter.js.map +1 -0
  18. package/dist/database/cache/cache-keys.d.ts +180 -0
  19. package/dist/database/cache/cache-keys.d.ts.map +1 -0
  20. package/dist/database/cache/cache-keys.js +107 -0
  21. package/dist/database/cache/cache-keys.js.map +1 -0
  22. package/dist/database/cache/index.d.ts +24 -0
  23. package/dist/database/cache/index.d.ts.map +1 -0
  24. package/dist/database/cache/index.js +34 -0
  25. package/dist/database/cache/index.js.map +1 -0
  26. package/dist/database/cache/query-cache.d.ts +67 -0
  27. package/dist/database/cache/query-cache.d.ts.map +1 -0
  28. package/dist/database/cache/query-cache.js +177 -0
  29. package/dist/database/cache/query-cache.js.map +1 -0
  30. package/dist/database/client.d.ts +63 -4
  31. package/dist/database/client.d.ts.map +1 -1
  32. package/dist/database/client.js +147 -59
  33. package/dist/database/client.js.map +1 -1
  34. package/dist/database/db-config.d.ts +104 -0
  35. package/dist/database/db-config.d.ts.map +1 -0
  36. package/dist/database/db-config.js +167 -0
  37. package/dist/database/db-config.js.map +1 -0
  38. package/dist/database/drizzle/index.d.ts +42 -0
  39. package/dist/database/drizzle/index.d.ts.map +1 -0
  40. package/dist/database/drizzle/index.js +48 -0
  41. package/dist/database/drizzle/index.js.map +1 -0
  42. package/dist/database/drizzle/schema/audit.d.ts +533 -0
  43. package/dist/database/drizzle/schema/audit.d.ts.map +1 -0
  44. package/dist/database/drizzle/schema/audit.js +71 -0
  45. package/dist/database/drizzle/schema/audit.js.map +1 -0
  46. package/dist/database/drizzle/schema/checkpoints.d.ts +665 -0
  47. package/dist/database/drizzle/schema/checkpoints.d.ts.map +1 -0
  48. package/dist/database/drizzle/schema/checkpoints.js +110 -0
  49. package/dist/database/drizzle/schema/checkpoints.js.map +1 -0
  50. package/dist/database/drizzle/schema/conversations.d.ts +449 -0
  51. package/dist/database/drizzle/schema/conversations.d.ts.map +1 -0
  52. package/dist/database/drizzle/schema/conversations.js +91 -0
  53. package/dist/database/drizzle/schema/conversations.js.map +1 -0
  54. package/dist/database/drizzle/schema/documents.d.ts +600 -0
  55. package/dist/database/drizzle/schema/documents.d.ts.map +1 -0
  56. package/dist/database/drizzle/schema/documents.js +100 -0
  57. package/dist/database/drizzle/schema/documents.js.map +1 -0
  58. package/dist/database/drizzle/schema/index.d.ts +3084 -0
  59. package/dist/database/drizzle/schema/index.d.ts.map +1 -0
  60. package/dist/database/drizzle/schema/index.js +46 -0
  61. package/dist/database/drizzle/schema/index.js.map +1 -0
  62. package/dist/database/drizzle/schema/memories.d.ts +435 -0
  63. package/dist/database/drizzle/schema/memories.d.ts.map +1 -0
  64. package/dist/database/drizzle/schema/memories.js +73 -0
  65. package/dist/database/drizzle/schema/memories.js.map +1 -0
  66. package/dist/database/drizzle/schema/tasks.d.ts +565 -0
  67. package/dist/database/drizzle/schema/tasks.d.ts.map +1 -0
  68. package/dist/database/drizzle/schema/tasks.js +84 -0
  69. package/dist/database/drizzle/schema/tasks.js.map +1 -0
  70. package/dist/database/health/circuit-breaker.d.ts +81 -0
  71. package/dist/database/health/circuit-breaker.d.ts.map +1 -0
  72. package/dist/database/health/circuit-breaker.js +184 -0
  73. package/dist/database/health/circuit-breaker.js.map +1 -0
  74. package/dist/database/health/health-monitor.d.ts +69 -0
  75. package/dist/database/health/health-monitor.d.ts.map +1 -0
  76. package/dist/database/health/health-monitor.js +174 -0
  77. package/dist/database/health/health-monitor.js.map +1 -0
  78. package/dist/database/health/index.d.ts +27 -0
  79. package/dist/database/health/index.d.ts.map +1 -0
  80. package/dist/database/health/index.js +23 -0
  81. package/dist/database/health/index.js.map +1 -0
  82. package/dist/database/index.d.ts +16 -0
  83. package/dist/database/index.d.ts.map +1 -0
  84. package/dist/database/index.js +41 -0
  85. package/dist/database/index.js.map +1 -0
  86. package/dist/database/migrations/index.d.ts +34 -0
  87. package/dist/database/migrations/index.d.ts.map +1 -0
  88. package/dist/database/migrations/index.js +45 -0
  89. package/dist/database/migrations/index.js.map +1 -0
  90. package/dist/database/migrations/migrator.d.ts +77 -0
  91. package/dist/database/migrations/migrator.d.ts.map +1 -0
  92. package/dist/database/migrations/migrator.js +258 -0
  93. package/dist/database/migrations/migrator.js.map +1 -0
  94. package/dist/database/migrations/versions/001_initial.d.ts +9 -0
  95. package/dist/database/migrations/versions/001_initial.d.ts.map +1 -0
  96. package/dist/database/migrations/versions/001_initial.js +183 -0
  97. package/dist/database/migrations/versions/001_initial.js.map +1 -0
  98. package/dist/database/types.d.ts +255 -0
  99. package/dist/database/types.d.ts.map +1 -0
  100. package/dist/database/types.js +8 -0
  101. package/dist/database/types.js.map +1 -0
  102. package/dist/database/vector/embedding-cache.d.ts +92 -0
  103. package/dist/database/vector/embedding-cache.d.ts.map +1 -0
  104. package/dist/database/vector/embedding-cache.js +185 -0
  105. package/dist/database/vector/embedding-cache.js.map +1 -0
  106. package/dist/database/vector/hnsw-index.d.ts +111 -0
  107. package/dist/database/vector/hnsw-index.d.ts.map +1 -0
  108. package/dist/database/vector/hnsw-index.js +337 -0
  109. package/dist/database/vector/hnsw-index.js.map +1 -0
  110. package/dist/database/vector/index.d.ts +75 -0
  111. package/dist/database/vector/index.d.ts.map +1 -0
  112. package/dist/database/vector/index.js +213 -0
  113. package/dist/database/vector/index.js.map +1 -0
  114. package/dist/database/vector/similarity.d.ts +67 -0
  115. package/dist/database/vector/similarity.d.ts.map +1 -0
  116. package/dist/database/vector/similarity.js +176 -0
  117. package/dist/database/vector/similarity.js.map +1 -0
  118. package/package.json +6 -3
  119. package/src/database/adapters/base-adapter.ts +171 -0
  120. package/src/database/adapters/index.ts +224 -0
  121. package/src/database/adapters/postgres-adapter.ts +285 -0
  122. package/src/database/adapters/sqlite-adapter.ts +420 -0
  123. package/src/database/cache/cache-keys.ts +150 -0
  124. package/src/database/cache/index.ts +44 -0
  125. package/src/database/cache/query-cache.ts +213 -0
  126. package/src/database/client.ts +166 -64
  127. package/src/database/db-config.ts +194 -0
  128. package/src/database/drizzle/index.ts +66 -0
  129. package/src/database/drizzle/schema/audit.ts +127 -0
  130. package/src/database/drizzle/schema/checkpoints.ts +164 -0
  131. package/src/database/drizzle/schema/conversations.ts +138 -0
  132. package/src/database/drizzle/schema/documents.ts +157 -0
  133. package/src/database/drizzle/schema/index.ts +139 -0
  134. package/src/database/drizzle/schema/memories.ts +127 -0
  135. package/src/database/drizzle/schema/tasks.ts +129 -0
  136. package/src/database/health/circuit-breaker.ts +214 -0
  137. package/src/database/health/health-monitor.ts +224 -0
  138. package/src/database/health/index.ts +41 -0
  139. package/src/database/index.ts +157 -0
  140. package/src/database/migrations/index.ts +52 -0
  141. package/src/database/migrations/migrator.ts +325 -0
  142. package/src/database/migrations/versions/001_initial.ts +198 -0
  143. package/src/database/types.ts +324 -0
  144. package/src/database/vector/embedding-cache.ts +234 -0
  145. package/src/database/vector/hnsw-index.ts +452 -0
  146. package/src/database/vector/index.ts +292 -0
  147. package/src/database/vector/similarity.ts +198 -0
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Database Layer Types
3
+ *
4
+ * Shared TypeScript types for the database abstraction layer.
5
+ * Supports both PostgreSQL and SQLite backends.
6
+ */
7
+
8
+ import type { DrizzleConfig } from 'drizzle-orm';
9
+
10
+ /**
11
+ * Supported database types
12
+ */
13
+ export type DatabaseType = 'postgresql' | 'sqlite';
14
+
15
+ /**
16
+ * Database detection modes
17
+ */
18
+ export type DatabaseDetectionMode = 'auto' | 'postgresql' | 'sqlite';
19
+
20
+ /**
21
+ * Query result row constraint (compatible with pg.QueryResultRow)
22
+ */
23
+ export type QueryResultRow = Record<string, any>;
24
+
25
+ /**
26
+ * Query result interface (compatible with pg.QueryResult)
27
+ */
28
+ export interface QueryResult<T extends QueryResultRow = Record<string, any>> {
29
+ rows: T[];
30
+ rowCount: number | null;
31
+ }
32
+
33
+ /**
34
+ * Transaction client interface
35
+ */
36
+ export interface TransactionClient {
37
+ query<T extends QueryResultRow = Record<string, any>>(
38
+ sql: string,
39
+ params?: unknown[]
40
+ ): Promise<QueryResult<T>>;
41
+ }
42
+
43
+ /**
44
+ * Connection pool statistics
45
+ */
46
+ export interface PoolStats {
47
+ total: number;
48
+ idle: number;
49
+ waiting: number;
50
+ }
51
+
52
+ /**
53
+ * Database health status
54
+ */
55
+ export interface DatabaseHealth {
56
+ status: 'healthy' | 'degraded' | 'unhealthy';
57
+ type: DatabaseType;
58
+ latencyMs: number;
59
+ poolStats?: PoolStats;
60
+ circuitState: CircuitBreakerState;
61
+ lastCheck: Date;
62
+ errors: string[];
63
+ }
64
+
65
+ /**
66
+ * Circuit breaker states
67
+ */
68
+ export type CircuitBreakerState = 'closed' | 'open' | 'half-open';
69
+
70
+ /**
71
+ * Migration result
72
+ */
73
+ export interface MigrationResult {
74
+ version: number;
75
+ name: string;
76
+ success: boolean;
77
+ error?: string;
78
+ durationMs: number;
79
+ }
80
+
81
+ /**
82
+ * Cache statistics
83
+ */
84
+ export interface CacheStats {
85
+ size: number;
86
+ maxSize: number;
87
+ hitCount: number;
88
+ missCount: number;
89
+ hitRate: number;
90
+ }
91
+
92
+ /**
93
+ * Vector search options
94
+ */
95
+ export interface VectorSearchOptions {
96
+ userId?: string;
97
+ memoryType?: string;
98
+ limit?: number;
99
+ minSimilarity?: number;
100
+ }
101
+
102
+ /**
103
+ * Vector search result
104
+ */
105
+ export interface VectorSearchResult {
106
+ id: string;
107
+ content: string;
108
+ similarity: number;
109
+ memoryType: string;
110
+ metadata: Record<string, unknown>;
111
+ }
112
+
113
+ /**
114
+ * Embedding entry for vector index
115
+ */
116
+ export interface EmbeddingEntry {
117
+ id: string;
118
+ vector: number[];
119
+ metadata?: Record<string, unknown>;
120
+ }
121
+
122
+ /**
123
+ * Database adapter interface
124
+ */
125
+ export interface DatabaseAdapter {
126
+ /** Database type */
127
+ readonly type: DatabaseType;
128
+
129
+ /** Whether the adapter is initialized */
130
+ readonly isInitialized: boolean;
131
+
132
+ /**
133
+ * Initialize the database connection
134
+ */
135
+ initialize(): Promise<void>;
136
+
137
+ /**
138
+ * Execute a raw SQL query
139
+ */
140
+ query<T extends QueryResultRow = Record<string, any>>(
141
+ sql: string,
142
+ params?: unknown[]
143
+ ): Promise<QueryResult<T>>;
144
+
145
+ /**
146
+ * Execute a transaction
147
+ */
148
+ transaction<T>(
149
+ callback: (client: TransactionClient) => Promise<T>
150
+ ): Promise<T>;
151
+
152
+ /**
153
+ * Check database health
154
+ */
155
+ healthCheck(): Promise<boolean>;
156
+
157
+ /**
158
+ * Get connection pool statistics (PostgreSQL only)
159
+ */
160
+ getPoolStats?(): PoolStats;
161
+
162
+ /**
163
+ * Close all connections
164
+ */
165
+ close(): Promise<void>;
166
+ }
167
+
168
+ /**
169
+ * Vector search engine interface
170
+ */
171
+ export interface VectorSearchEngine {
172
+ /**
173
+ * Initialize the vector index
174
+ */
175
+ initialize(): Promise<void>;
176
+
177
+ /**
178
+ * Store an embedding
179
+ */
180
+ store(
181
+ id: string,
182
+ embedding: number[],
183
+ metadata?: Record<string, unknown>
184
+ ): Promise<void>;
185
+
186
+ /**
187
+ * Search for similar embeddings
188
+ */
189
+ search(
190
+ queryEmbedding: number[],
191
+ options?: VectorSearchOptions
192
+ ): Promise<VectorSearchResult[]>;
193
+
194
+ /**
195
+ * Remove an embedding
196
+ */
197
+ remove(id: string): Promise<void>;
198
+
199
+ /**
200
+ * Rebuild the vector index
201
+ */
202
+ rebuildIndex(): Promise<void>;
203
+
204
+ /**
205
+ * Get index statistics
206
+ */
207
+ getStats(): { size: number; dimension: number };
208
+ }
209
+
210
+ /**
211
+ * Database detection result
212
+ */
213
+ export interface DetectionResult {
214
+ type: DatabaseType;
215
+ connectionString?: string;
216
+ sqlitePath?: string;
217
+ reason: string;
218
+ }
219
+
220
+ /**
221
+ * Migration definition
222
+ */
223
+ export interface Migration {
224
+ version: number;
225
+ name: string;
226
+ up: (adapter: DatabaseAdapter) => Promise<void>;
227
+ down: (adapter: DatabaseAdapter) => Promise<void>;
228
+ }
229
+
230
+ /**
231
+ * Cache entry
232
+ */
233
+ export interface CacheEntry<T> {
234
+ value: T;
235
+ expiresAt: number;
236
+ hits: number;
237
+ }
238
+
239
+ /**
240
+ * Query cache options
241
+ */
242
+ export interface QueryCacheOptions {
243
+ maxSize: number;
244
+ defaultTtlMs: number;
245
+ }
246
+
247
+ /**
248
+ * Circuit breaker options
249
+ */
250
+ export interface CircuitBreakerOptions {
251
+ failureThreshold: number;
252
+ resetTimeoutMs: number;
253
+ halfOpenMaxAttempts: number;
254
+ }
255
+
256
+ /**
257
+ * Health monitor options
258
+ */
259
+ export interface HealthMonitorOptions {
260
+ checkIntervalMs: number;
261
+ errorThreshold: number;
262
+ }
263
+
264
+ /**
265
+ * Database configuration
266
+ */
267
+ export interface DatabaseConfig {
268
+ // Detection mode
269
+ type: DatabaseDetectionMode;
270
+
271
+ // PostgreSQL settings
272
+ postgresUrl?: string;
273
+ postgresHost: string;
274
+ postgresPort: number;
275
+ postgresUser: string;
276
+ postgresPassword: string;
277
+ postgresDatabase: string;
278
+ postgresPoolMax: number;
279
+ postgresIdleTimeoutMs: number;
280
+ postgresConnectionTimeoutMs: number;
281
+
282
+ // SQLite settings
283
+ sqlitePath?: string;
284
+
285
+ // Health monitoring
286
+ healthCheckIntervalMs: number;
287
+ circuitBreakerThreshold: number;
288
+ circuitBreakerTimeoutMs: number;
289
+
290
+ // Cache settings
291
+ cacheMaxSize: number;
292
+ cacheTtlMs: number;
293
+
294
+ // Vector settings
295
+ vectorDimension: number;
296
+ vectorMinSimilarity: number;
297
+ }
298
+
299
+ /**
300
+ * Memory types for vector storage
301
+ */
302
+ export type MemoryType = 'semantic' | 'episodic' | 'procedural';
303
+
304
+ /**
305
+ * Message roles
306
+ */
307
+ export type MessageRole = 'user' | 'assistant' | 'system';
308
+
309
+ /**
310
+ * Task status
311
+ */
312
+ export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
313
+
314
+ /**
315
+ * Audit log action types
316
+ */
317
+ export type AuditActionType =
318
+ | 'chat_message'
319
+ | 'memory_store'
320
+ | 'memory_search'
321
+ | 'document_upload'
322
+ | 'agent_invocation'
323
+ | 'tool_execution'
324
+ | 'safety_block';
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Embedding Cache
3
+ *
4
+ * LRU cache for embeddings to avoid redundant database queries.
5
+ * Improves performance for frequently accessed vectors.
6
+ */
7
+
8
+ import { createLogger } from '../../utils/logger.js';
9
+
10
+ const logger = createLogger('EmbeddingCache');
11
+
12
+ /**
13
+ * Cache entry with metadata
14
+ */
15
+ interface CacheEntry {
16
+ embedding: number[];
17
+ metadata?: Record<string, unknown>;
18
+ accessCount: number;
19
+ lastAccessed: number;
20
+ addedAt: number;
21
+ }
22
+
23
+ /**
24
+ * Cache statistics
25
+ */
26
+ export interface EmbeddingCacheStats {
27
+ size: number;
28
+ maxSize: number;
29
+ hitCount: number;
30
+ missCount: number;
31
+ hitRate: number;
32
+ memoryUsageBytes: number;
33
+ }
34
+
35
+ /**
36
+ * LRU cache for embeddings
37
+ */
38
+ export class EmbeddingCache {
39
+ private cache: Map<string, CacheEntry> = new Map();
40
+ private maxSize: number;
41
+ private hitCount: number = 0;
42
+ private missCount: number = 0;
43
+ private dimension: number;
44
+
45
+ constructor(options: { maxSize?: number; dimension?: number } = {}) {
46
+ this.maxSize = options.maxSize ?? 10000;
47
+ this.dimension = options.dimension ?? 1536;
48
+ }
49
+
50
+ /**
51
+ * Get embedding from cache
52
+ */
53
+ get(id: string): number[] | undefined {
54
+ const entry = this.cache.get(id);
55
+
56
+ if (!entry) {
57
+ this.missCount++;
58
+ return undefined;
59
+ }
60
+
61
+ // Update access metadata
62
+ entry.accessCount++;
63
+ entry.lastAccessed = Date.now();
64
+
65
+ // Move to end for LRU
66
+ this.cache.delete(id);
67
+ this.cache.set(id, entry);
68
+
69
+ this.hitCount++;
70
+ return entry.embedding;
71
+ }
72
+
73
+ /**
74
+ * Set embedding in cache
75
+ */
76
+ set(id: string, embedding: number[], metadata?: Record<string, unknown>): void {
77
+ // Evict if at capacity
78
+ if (this.cache.size >= this.maxSize && !this.cache.has(id)) {
79
+ this.evictLRU();
80
+ }
81
+
82
+ const entry: CacheEntry = {
83
+ embedding,
84
+ metadata,
85
+ accessCount: 1,
86
+ lastAccessed: Date.now(),
87
+ addedAt: Date.now(),
88
+ };
89
+
90
+ // Delete first to ensure it's at the end
91
+ this.cache.delete(id);
92
+ this.cache.set(id, entry);
93
+ }
94
+
95
+ /**
96
+ * Check if ID is in cache
97
+ */
98
+ has(id: string): boolean {
99
+ return this.cache.has(id);
100
+ }
101
+
102
+ /**
103
+ * Remove embedding from cache
104
+ */
105
+ delete(id: string): boolean {
106
+ return this.cache.delete(id);
107
+ }
108
+
109
+ /**
110
+ * Clear the cache
111
+ */
112
+ clear(): void {
113
+ this.cache.clear();
114
+ this.hitCount = 0;
115
+ this.missCount = 0;
116
+ logger.debug('Embedding cache cleared');
117
+ }
118
+
119
+ /**
120
+ * Evict least recently used entry
121
+ */
122
+ private evictLRU(): void {
123
+ // First entry is LRU due to Map ordering
124
+ const firstKey = this.cache.keys().next().value;
125
+ if (firstKey) {
126
+ this.cache.delete(firstKey);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Evict entries matching a pattern
132
+ */
133
+ evictPattern(pattern: (id: string) => boolean): number {
134
+ let count = 0;
135
+ for (const id of this.cache.keys()) {
136
+ if (pattern(id)) {
137
+ this.cache.delete(id);
138
+ count++;
139
+ }
140
+ }
141
+ return count;
142
+ }
143
+
144
+ /**
145
+ * Get multiple embeddings (batch)
146
+ */
147
+ getMany(ids: string[]): Map<string, number[]> {
148
+ const result = new Map<string, number[]>();
149
+ for (const id of ids) {
150
+ const embedding = this.get(id);
151
+ if (embedding) {
152
+ result.set(id, embedding);
153
+ }
154
+ }
155
+ return result;
156
+ }
157
+
158
+ /**
159
+ * Set multiple embeddings (batch)
160
+ */
161
+ setMany(entries: Array<{ id: string; embedding: number[]; metadata?: Record<string, unknown> }>): void {
162
+ for (const { id, embedding, metadata } of entries) {
163
+ this.set(id, embedding, metadata);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Get cache statistics
169
+ */
170
+ getStats(): EmbeddingCacheStats {
171
+ const totalRequests = this.hitCount + this.missCount;
172
+ const memoryUsageBytes = this.cache.size * this.dimension * 4; // 4 bytes per float32
173
+
174
+ return {
175
+ size: this.cache.size,
176
+ maxSize: this.maxSize,
177
+ hitCount: this.hitCount,
178
+ missCount: this.missCount,
179
+ hitRate: totalRequests > 0 ? this.hitCount / totalRequests : 0,
180
+ memoryUsageBytes,
181
+ };
182
+ }
183
+
184
+ /**
185
+ * Get cache size
186
+ */
187
+ get size(): number {
188
+ return this.cache.size;
189
+ }
190
+
191
+ /**
192
+ * Preload embeddings from database records
193
+ */
194
+ preload(records: Array<{ id: string; embedding: number[] | string }>): void {
195
+ for (const record of records) {
196
+ let embedding: number[];
197
+
198
+ if (typeof record.embedding === 'string') {
199
+ try {
200
+ embedding = JSON.parse(record.embedding);
201
+ } catch {
202
+ continue;
203
+ }
204
+ } else {
205
+ embedding = record.embedding;
206
+ }
207
+
208
+ this.set(record.id, embedding);
209
+ }
210
+
211
+ logger.debug('Embeddings preloaded', { count: records.length });
212
+ }
213
+
214
+ /**
215
+ * Trim cache to a smaller size
216
+ */
217
+ trim(newMaxSize: number): void {
218
+ if (newMaxSize >= this.cache.size) return;
219
+
220
+ const toRemove = this.cache.size - newMaxSize;
221
+ let removed = 0;
222
+
223
+ for (const id of this.cache.keys()) {
224
+ if (removed >= toRemove) break;
225
+ this.cache.delete(id);
226
+ removed++;
227
+ }
228
+
229
+ this.maxSize = newMaxSize;
230
+ logger.debug('Cache trimmed', { removed, newSize: this.cache.size });
231
+ }
232
+ }
233
+
234
+ export default EmbeddingCache;