@sparkleideas/embeddings 3.0.0-alpha.12-patch.25 → 3.0.0-alpha.12-patch.27

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 (45) hide show
  1. package/dist/__tests__/embedding-service.test.d.ts +2 -0
  2. package/dist/__tests__/embedding-service.test.d.ts.map +1 -0
  3. package/dist/__tests__/embedding-service.test.js +98 -0
  4. package/dist/__tests__/embedding-service.test.js.map +1 -0
  5. package/dist/chunking.d.ts +68 -0
  6. package/dist/chunking.d.ts.map +1 -0
  7. package/dist/chunking.js +251 -0
  8. package/dist/chunking.js.map +1 -0
  9. package/dist/embedding-service.d.ts +207 -0
  10. package/dist/embedding-service.d.ts.map +1 -0
  11. package/dist/embedding-service.js +965 -0
  12. package/dist/embedding-service.js.map +1 -0
  13. package/dist/hyperbolic.d.ts +103 -0
  14. package/dist/hyperbolic.d.ts.map +1 -0
  15. package/dist/hyperbolic.js +343 -0
  16. package/dist/hyperbolic.js.map +1 -0
  17. package/dist/index.d.ts +31 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +37 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/neural-integration.d.ts +203 -0
  22. package/dist/neural-integration.d.ts.map +1 -0
  23. package/dist/neural-integration.js +213 -0
  24. package/dist/neural-integration.js.map +1 -0
  25. package/dist/normalization.d.ts +73 -0
  26. package/dist/normalization.d.ts.map +1 -0
  27. package/dist/normalization.js +192 -0
  28. package/dist/normalization.js.map +1 -0
  29. package/dist/persistent-cache.d.ts +119 -0
  30. package/dist/persistent-cache.d.ts.map +1 -0
  31. package/dist/persistent-cache.js +337 -0
  32. package/dist/persistent-cache.js.map +1 -0
  33. package/dist/rvf-embedding-cache.d.ts +118 -0
  34. package/dist/rvf-embedding-cache.d.ts.map +1 -0
  35. package/dist/rvf-embedding-cache.js +458 -0
  36. package/dist/rvf-embedding-cache.js.map +1 -0
  37. package/dist/rvf-embedding-service.d.ts +79 -0
  38. package/dist/rvf-embedding-service.d.ts.map +1 -0
  39. package/dist/rvf-embedding-service.js +318 -0
  40. package/dist/rvf-embedding-service.js.map +1 -0
  41. package/dist/types.d.ts +237 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +15 -0
  44. package/dist/types.js.map +1 -0
  45. package/package.json +3 -3
@@ -0,0 +1,118 @@
1
+ /**
2
+ * RVF Embedding Cache - Pure TypeScript Binary File Cache
3
+ *
4
+ * Replaces the sql.js-based PersistentEmbeddingCache with a lightweight
5
+ * pure-TS binary file format. No native dependencies required.
6
+ *
7
+ * Features:
8
+ * - Map-based in-memory cache with periodic flush to binary file
9
+ * - LRU eviction tracked via access timestamps
10
+ * - TTL support for cache entries
11
+ * - Deterministic FNV-1a text hashing for keys
12
+ * - Binary format: RVEC magic + entry records
13
+ *
14
+ * Binary entry format:
15
+ * [4-byte key-hash][4-byte dims][dims*4 bytes float32][8-byte timestamp][8-byte access-count]
16
+ *
17
+ * @module @sparkleideas/embeddings
18
+ */
19
+ /**
20
+ * Configuration for RVF embedding cache
21
+ */
22
+ export interface RvfEmbeddingCacheConfig {
23
+ /** Path to the binary cache file */
24
+ cachePath: string;
25
+ /** Maximum number of entries (default: 10000) */
26
+ maxSize?: number;
27
+ /** TTL in milliseconds (default: 7 days) */
28
+ ttlMs?: number;
29
+ /** Embedding dimensions (used for validation) */
30
+ dimensions?: number;
31
+ }
32
+ /**
33
+ * Pure-TS binary file embedding cache with LRU eviction and TTL support.
34
+ *
35
+ * Stores embeddings as raw Float32Array bytes keyed by FNV-1a text hashes.
36
+ * Uses an in-memory Map with periodic flush to a compact binary file.
37
+ */
38
+ export declare class RvfEmbeddingCache {
39
+ private readonly cachePath;
40
+ private readonly maxSize;
41
+ private readonly ttlMs;
42
+ private readonly dimensions;
43
+ private entries;
44
+ private textToHash;
45
+ private dirty;
46
+ private flushTimer;
47
+ private initialized;
48
+ constructor(config: RvfEmbeddingCacheConfig);
49
+ /**
50
+ * Lazily initialize the cache: load from disk if file exists, start auto-flush.
51
+ */
52
+ private ensureInitialized;
53
+ /**
54
+ * Get an embedding from the cache by text.
55
+ * Returns null if not found or expired.
56
+ */
57
+ get(text: string): Promise<Float32Array | null>;
58
+ /**
59
+ * Store an embedding in the cache.
60
+ * Triggers LRU eviction if the cache exceeds maxSize.
61
+ */
62
+ set(text: string, embedding: Float32Array): Promise<void>;
63
+ /**
64
+ * Check whether the cache contains an embedding for the given text.
65
+ */
66
+ has(text: string): Promise<boolean>;
67
+ /**
68
+ * Delete a specific entry from the cache.
69
+ * Returns true if the entry existed and was deleted.
70
+ */
71
+ delete(text: string): Promise<boolean>;
72
+ /**
73
+ * Clear all entries from the cache and persist the empty state.
74
+ */
75
+ clear(): Promise<void>;
76
+ /**
77
+ * Return the number of entries currently in the cache.
78
+ */
79
+ size(): Promise<number>;
80
+ /**
81
+ * Flush pending changes to disk and stop the auto-flush timer.
82
+ */
83
+ close(): Promise<void>;
84
+ /**
85
+ * FNV-1a 32-bit hash of the input text.
86
+ * Deterministic: same input always produces the same hash.
87
+ */
88
+ private hashText;
89
+ /**
90
+ * If the cache exceeds maxSize, evict the least-recently-accessed entries
91
+ * until we are back at 90% capacity.
92
+ */
93
+ private evictIfNeeded;
94
+ /**
95
+ * Remove all entries whose createdAt timestamp is older than TTL.
96
+ */
97
+ private cleanExpired;
98
+ private startAutoFlush;
99
+ private stopAutoFlush;
100
+ /**
101
+ * Write all entries to the binary cache file.
102
+ *
103
+ * Format:
104
+ * [4-byte magic "RVEC"]
105
+ * For each entry:
106
+ * [4-byte key-hash (uint32)]
107
+ * [4-byte dims (uint32)]
108
+ * [dims * 4 bytes float32 data]
109
+ * [8-byte createdAt (float64, used as timestamp)]
110
+ * [8-byte accessCount (float64)]
111
+ */
112
+ private flushToFile;
113
+ /**
114
+ * Load entries from the binary cache file.
115
+ */
116
+ private loadFromFile;
117
+ }
118
+ //# sourceMappingURL=rvf-embedding-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rvf-embedding-cache.d.ts","sourceRoot":"","sources":["../src/rvf-embedding-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAuCD;;;;;GAKG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAEhD,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,uBAAuB;IAY3C;;OAEG;YACW,iBAAiB;IA2B/B;;;OAGG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IA2BrD;;;OAGG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC/D;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBzC;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc5C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAK7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAahB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,YAAY;IA+BpB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,aAAa;IAWrB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,WAAW;IAsEnB;;OAEG;IACH,OAAO,CAAC,YAAY;CA0FrB"}
@@ -0,0 +1,458 @@
1
+ /**
2
+ * RVF Embedding Cache - Pure TypeScript Binary File Cache
3
+ *
4
+ * Replaces the sql.js-based PersistentEmbeddingCache with a lightweight
5
+ * pure-TS binary file format. No native dependencies required.
6
+ *
7
+ * Features:
8
+ * - Map-based in-memory cache with periodic flush to binary file
9
+ * - LRU eviction tracked via access timestamps
10
+ * - TTL support for cache entries
11
+ * - Deterministic FNV-1a text hashing for keys
12
+ * - Binary format: RVEC magic + entry records
13
+ *
14
+ * Binary entry format:
15
+ * [4-byte key-hash][4-byte dims][dims*4 bytes float32][8-byte timestamp][8-byte access-count]
16
+ *
17
+ * @module @sparkleideas/embeddings
18
+ */
19
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from 'fs';
20
+ import { dirname } from 'path';
21
+ /** Validate a file path is safe */
22
+ function validatePath(p) {
23
+ if (p.includes('\0'))
24
+ throw new Error('Cache path contains null bytes');
25
+ }
26
+ // ============================================================================
27
+ // Constants
28
+ // ============================================================================
29
+ /** Binary file magic bytes: "RVEC" */
30
+ const MAGIC = new Uint8Array([0x52, 0x56, 0x45, 0x43]); // R V E C
31
+ /** Default TTL: 7 days in milliseconds */
32
+ const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000;
33
+ /** Default max entries */
34
+ const DEFAULT_MAX_SIZE = 10000;
35
+ /** Auto-flush interval: 30 seconds */
36
+ const AUTO_FLUSH_INTERVAL_MS = 30000;
37
+ /** FNV-1a offset basis (32-bit) */
38
+ const FNV_OFFSET_BASIS = 0x811c9dc5;
39
+ /** FNV-1a prime (32-bit) */
40
+ const FNV_PRIME = 0x01000193;
41
+ // ============================================================================
42
+ // RVF Embedding Cache
43
+ // ============================================================================
44
+ /**
45
+ * Pure-TS binary file embedding cache with LRU eviction and TTL support.
46
+ *
47
+ * Stores embeddings as raw Float32Array bytes keyed by FNV-1a text hashes.
48
+ * Uses an in-memory Map with periodic flush to a compact binary file.
49
+ */
50
+ export class RvfEmbeddingCache {
51
+ cachePath;
52
+ maxSize;
53
+ ttlMs;
54
+ dimensions;
55
+ entries = new Map();
56
+ textToHash = new Map();
57
+ dirty = false;
58
+ flushTimer = null;
59
+ initialized = false;
60
+ constructor(config) {
61
+ this.cachePath = config.cachePath;
62
+ this.maxSize = config.maxSize ?? DEFAULT_MAX_SIZE;
63
+ this.ttlMs = config.ttlMs ?? DEFAULT_TTL_MS;
64
+ this.dimensions = config.dimensions;
65
+ validatePath(this.cachePath);
66
+ }
67
+ // --------------------------------------------------------------------------
68
+ // Initialization
69
+ // --------------------------------------------------------------------------
70
+ /**
71
+ * Lazily initialize the cache: load from disk if file exists, start auto-flush.
72
+ */
73
+ async ensureInitialized() {
74
+ if (this.initialized)
75
+ return;
76
+ // Ensure parent directory exists
77
+ const dir = dirname(this.cachePath);
78
+ if (!existsSync(dir)) {
79
+ mkdirSync(dir, { recursive: true });
80
+ }
81
+ // Load existing cache file
82
+ if (existsSync(this.cachePath)) {
83
+ this.loadFromFile();
84
+ }
85
+ // Clean expired entries on startup
86
+ this.cleanExpired();
87
+ // Start auto-flush timer
88
+ this.startAutoFlush();
89
+ this.initialized = true;
90
+ }
91
+ // --------------------------------------------------------------------------
92
+ // Public API (matches PersistentEmbeddingCache)
93
+ // --------------------------------------------------------------------------
94
+ /**
95
+ * Get an embedding from the cache by text.
96
+ * Returns null if not found or expired.
97
+ */
98
+ async get(text) {
99
+ await this.ensureInitialized();
100
+ const hash = this.hashText(text);
101
+ const entry = this.entries.get(hash);
102
+ if (!entry) {
103
+ return null;
104
+ }
105
+ // Check TTL
106
+ const now = Date.now();
107
+ if (now - entry.createdAt > this.ttlMs) {
108
+ this.entries.delete(hash);
109
+ this.textToHash.delete(text);
110
+ this.dirty = true;
111
+ return null;
112
+ }
113
+ // Update LRU tracking
114
+ entry.accessedAt = now;
115
+ entry.accessCount++;
116
+ this.dirty = true;
117
+ return entry.embedding;
118
+ }
119
+ /**
120
+ * Store an embedding in the cache.
121
+ * Triggers LRU eviction if the cache exceeds maxSize.
122
+ */
123
+ async set(text, embedding) {
124
+ await this.ensureInitialized();
125
+ // Validate dimensions if configured
126
+ if (this.dimensions !== undefined && embedding.length !== this.dimensions) {
127
+ throw new Error(`Dimension mismatch: expected ${this.dimensions}, got ${embedding.length}`);
128
+ }
129
+ const hash = this.hashText(text);
130
+ const now = Date.now();
131
+ // Copy the embedding to avoid external mutation
132
+ const copy = new Float32Array(embedding.length);
133
+ copy.set(embedding);
134
+ const existing = this.entries.get(hash);
135
+ if (existing) {
136
+ existing.embedding = copy;
137
+ existing.accessedAt = now;
138
+ existing.accessCount++;
139
+ }
140
+ else {
141
+ this.entries.set(hash, {
142
+ embedding: copy,
143
+ createdAt: now,
144
+ accessedAt: now,
145
+ accessCount: 1,
146
+ });
147
+ this.textToHash.set(text, hash);
148
+ }
149
+ this.dirty = true;
150
+ // Evict if over capacity
151
+ this.evictIfNeeded();
152
+ }
153
+ /**
154
+ * Check whether the cache contains an embedding for the given text.
155
+ */
156
+ async has(text) {
157
+ await this.ensureInitialized();
158
+ const hash = this.hashText(text);
159
+ const entry = this.entries.get(hash);
160
+ if (!entry)
161
+ return false;
162
+ // Check TTL
163
+ if (Date.now() - entry.createdAt > this.ttlMs) {
164
+ this.entries.delete(hash);
165
+ this.textToHash.delete(text);
166
+ this.dirty = true;
167
+ return false;
168
+ }
169
+ return true;
170
+ }
171
+ /**
172
+ * Delete a specific entry from the cache.
173
+ * Returns true if the entry existed and was deleted.
174
+ */
175
+ async delete(text) {
176
+ await this.ensureInitialized();
177
+ const hash = this.hashText(text);
178
+ const existed = this.entries.delete(hash);
179
+ this.textToHash.delete(text);
180
+ if (existed) {
181
+ this.dirty = true;
182
+ }
183
+ return existed;
184
+ }
185
+ /**
186
+ * Clear all entries from the cache and persist the empty state.
187
+ */
188
+ async clear() {
189
+ await this.ensureInitialized();
190
+ this.entries.clear();
191
+ this.textToHash.clear();
192
+ this.dirty = true;
193
+ this.flushToFile();
194
+ }
195
+ /**
196
+ * Return the number of entries currently in the cache.
197
+ */
198
+ async size() {
199
+ await this.ensureInitialized();
200
+ return this.entries.size;
201
+ }
202
+ /**
203
+ * Flush pending changes to disk and stop the auto-flush timer.
204
+ */
205
+ async close() {
206
+ this.stopAutoFlush();
207
+ if (this.dirty) {
208
+ this.flushToFile();
209
+ }
210
+ this.entries.clear();
211
+ this.textToHash.clear();
212
+ this.initialized = false;
213
+ }
214
+ // --------------------------------------------------------------------------
215
+ // Hashing
216
+ // --------------------------------------------------------------------------
217
+ /**
218
+ * FNV-1a 32-bit hash of the input text.
219
+ * Deterministic: same input always produces the same hash.
220
+ */
221
+ hashText(text) {
222
+ let hash = FNV_OFFSET_BASIS;
223
+ for (let i = 0; i < text.length; i++) {
224
+ hash ^= text.charCodeAt(i);
225
+ hash = Math.imul(hash, FNV_PRIME) >>> 0;
226
+ }
227
+ return hash;
228
+ }
229
+ // --------------------------------------------------------------------------
230
+ // LRU Eviction
231
+ // --------------------------------------------------------------------------
232
+ /**
233
+ * If the cache exceeds maxSize, evict the least-recently-accessed entries
234
+ * until we are back at 90% capacity.
235
+ */
236
+ evictIfNeeded() {
237
+ if (this.entries.size <= this.maxSize)
238
+ return;
239
+ const targetSize = Math.floor(this.maxSize * 0.9);
240
+ const toEvict = this.entries.size - targetSize;
241
+ // Sort entries by accessedAt ascending (oldest first)
242
+ const sorted = [...this.entries.entries()].sort((a, b) => a[1].accessedAt - b[1].accessedAt);
243
+ // Build reverse map for O(1) lookup (hash → text)
244
+ const hashToText = new Map();
245
+ for (const [text, hash] of this.textToHash) {
246
+ hashToText.set(hash, text);
247
+ }
248
+ for (let i = 0; i < toEvict && i < sorted.length; i++) {
249
+ const [hash] = sorted[i];
250
+ this.entries.delete(hash);
251
+ const text = hashToText.get(hash);
252
+ if (text !== undefined)
253
+ this.textToHash.delete(text);
254
+ }
255
+ this.dirty = true;
256
+ }
257
+ // --------------------------------------------------------------------------
258
+ // TTL Cleanup
259
+ // --------------------------------------------------------------------------
260
+ /**
261
+ * Remove all entries whose createdAt timestamp is older than TTL.
262
+ */
263
+ cleanExpired() {
264
+ const cutoff = Date.now() - this.ttlMs;
265
+ const toDelete = [];
266
+ for (const [hash, entry] of this.entries) {
267
+ if (entry.createdAt < cutoff) {
268
+ toDelete.push(hash);
269
+ }
270
+ }
271
+ // Build reverse map for O(1) lookup
272
+ const hashToText = new Map();
273
+ for (const [text, h] of this.textToHash) {
274
+ hashToText.set(h, text);
275
+ }
276
+ for (const hash of toDelete) {
277
+ this.entries.delete(hash);
278
+ const text = hashToText.get(hash);
279
+ if (text !== undefined)
280
+ this.textToHash.delete(text);
281
+ }
282
+ if (toDelete.length > 0) {
283
+ this.dirty = true;
284
+ }
285
+ }
286
+ // --------------------------------------------------------------------------
287
+ // Auto-Flush Timer
288
+ // --------------------------------------------------------------------------
289
+ startAutoFlush() {
290
+ if (this.flushTimer)
291
+ return;
292
+ this.flushTimer = setInterval(() => {
293
+ if (this.dirty) {
294
+ this.flushToFile();
295
+ }
296
+ }, AUTO_FLUSH_INTERVAL_MS);
297
+ if (this.flushTimer.unref)
298
+ this.flushTimer.unref();
299
+ }
300
+ stopAutoFlush() {
301
+ if (this.flushTimer) {
302
+ clearInterval(this.flushTimer);
303
+ this.flushTimer = null;
304
+ }
305
+ }
306
+ // --------------------------------------------------------------------------
307
+ // Binary Serialization
308
+ // --------------------------------------------------------------------------
309
+ /**
310
+ * Write all entries to the binary cache file.
311
+ *
312
+ * Format:
313
+ * [4-byte magic "RVEC"]
314
+ * For each entry:
315
+ * [4-byte key-hash (uint32)]
316
+ * [4-byte dims (uint32)]
317
+ * [dims * 4 bytes float32 data]
318
+ * [8-byte createdAt (float64, used as timestamp)]
319
+ * [8-byte accessCount (float64)]
320
+ */
321
+ flushToFile() {
322
+ try {
323
+ // Version 2 format: magic(4) + version(4) + entries...
324
+ // Entry: hash(4) + dims(4) + embedding(dims*4) + createdAt(8) + accessedAt(8) + accessCount(8)
325
+ let totalSize = MAGIC.length + 4; // magic + version uint32
326
+ for (const [, entry] of this.entries) {
327
+ totalSize += 4 + 4 + entry.embedding.length * 4 + 8 + 8 + 8;
328
+ }
329
+ const buffer = new ArrayBuffer(totalSize);
330
+ const view = new DataView(buffer);
331
+ const bytes = new Uint8Array(buffer);
332
+ let offset = 0;
333
+ // Write magic
334
+ bytes.set(MAGIC, 0);
335
+ offset += MAGIC.length;
336
+ // Write format version
337
+ view.setUint32(offset, 2, true);
338
+ offset += 4;
339
+ // Write entries
340
+ for (const [hash, entry] of this.entries) {
341
+ // Key hash (uint32, little-endian)
342
+ view.setUint32(offset, hash, true);
343
+ offset += 4;
344
+ // Dimensions (uint32, little-endian)
345
+ view.setUint32(offset, entry.embedding.length, true);
346
+ offset += 4;
347
+ // Embedding data (float32 array, little-endian)
348
+ for (let i = 0; i < entry.embedding.length; i++) {
349
+ view.setFloat32(offset, entry.embedding[i], true);
350
+ offset += 4;
351
+ }
352
+ // createdAt as float64 (little-endian) - v2: separate from accessedAt
353
+ view.setFloat64(offset, entry.createdAt, true);
354
+ offset += 8;
355
+ // accessedAt as float64 (little-endian)
356
+ view.setFloat64(offset, entry.accessedAt, true);
357
+ offset += 8;
358
+ // Access count as float64 (little-endian)
359
+ view.setFloat64(offset, entry.accessCount, true);
360
+ offset += 8;
361
+ }
362
+ // Ensure parent directory exists
363
+ const dir = dirname(this.cachePath);
364
+ if (!existsSync(dir)) {
365
+ mkdirSync(dir, { recursive: true });
366
+ }
367
+ const tmpSuffix = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
368
+ const tmpPath = this.cachePath + '.tmp.' + tmpSuffix;
369
+ writeFileSync(tmpPath, Buffer.from(buffer));
370
+ renameSync(tmpPath, this.cachePath);
371
+ this.dirty = false;
372
+ }
373
+ catch (error) {
374
+ console.error('[rvf-embedding-cache] Flush error:', error instanceof Error ? error.message : error);
375
+ }
376
+ }
377
+ /**
378
+ * Load entries from the binary cache file.
379
+ */
380
+ loadFromFile() {
381
+ try {
382
+ const fileBuffer = readFileSync(this.cachePath);
383
+ if (fileBuffer.length < MAGIC.length)
384
+ return;
385
+ const buffer = fileBuffer.buffer.slice(fileBuffer.byteOffset, fileBuffer.byteOffset + fileBuffer.byteLength);
386
+ const view = new DataView(buffer);
387
+ const bytes = new Uint8Array(buffer);
388
+ let offset = 0;
389
+ // Verify magic
390
+ for (let i = 0; i < MAGIC.length; i++) {
391
+ if (bytes[offset + i] !== MAGIC[i]) {
392
+ console.warn('[rvf-embedding-cache] Invalid magic bytes, skipping load');
393
+ return;
394
+ }
395
+ }
396
+ offset += MAGIC.length;
397
+ // Check for version header (v2+)
398
+ let formatVersion = 1;
399
+ if (offset + 4 <= buffer.byteLength) {
400
+ const possibleVersion = view.getUint32(offset, true);
401
+ if (possibleVersion === 2) {
402
+ formatVersion = possibleVersion;
403
+ offset += 4;
404
+ }
405
+ }
406
+ // Read entries
407
+ while (offset + 8 <= buffer.byteLength) {
408
+ // Need at least 4 (hash) + 4 (dims) = 8 bytes for the header
409
+ const hash = view.getUint32(offset, true);
410
+ offset += 4;
411
+ const dims = view.getUint32(offset, true);
412
+ offset += 4;
413
+ const entryDataSize = formatVersion === 2
414
+ ? dims * 4 + 8 + 8 + 8 // v2: embedding + createdAt + accessedAt + accessCount
415
+ : dims * 4 + 8 + 8; // v1: embedding + accessedAt + accessCount
416
+ if (offset + entryDataSize > buffer.byteLength) {
417
+ console.warn('[rvf-embedding-cache] Truncated entry, stopping load');
418
+ break;
419
+ }
420
+ // Read embedding
421
+ const embedding = new Float32Array(dims);
422
+ for (let i = 0; i < dims; i++) {
423
+ embedding[i] = view.getFloat32(offset, true);
424
+ offset += 4;
425
+ }
426
+ let createdAt;
427
+ let accessedAt;
428
+ let accessCount;
429
+ if (formatVersion >= 2) {
430
+ createdAt = view.getFloat64(offset, true);
431
+ offset += 8;
432
+ accessedAt = view.getFloat64(offset, true);
433
+ offset += 8;
434
+ accessCount = view.getFloat64(offset, true);
435
+ offset += 8;
436
+ }
437
+ else {
438
+ // v1: only accessedAt was stored, use it as createdAt too
439
+ accessedAt = view.getFloat64(offset, true);
440
+ offset += 8;
441
+ accessCount = view.getFloat64(offset, true);
442
+ offset += 8;
443
+ createdAt = accessedAt;
444
+ }
445
+ this.entries.set(hash, {
446
+ embedding,
447
+ createdAt,
448
+ accessedAt,
449
+ accessCount,
450
+ });
451
+ }
452
+ }
453
+ catch (error) {
454
+ console.warn('[rvf-embedding-cache] Load error:', error instanceof Error ? error.message : error);
455
+ }
456
+ }
457
+ }
458
+ //# sourceMappingURL=rvf-embedding-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rvf-embedding-cache.js","sourceRoot":"","sources":["../src/rvf-embedding-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * RVF Embedding Service - Lightweight Hash-Based Embeddings
3
+ *
4
+ * Provides deterministic, sub-millisecond embedding generation using
5
+ * FNV-1a hash-based vectors. No neural model or external API required.
6
+ *
7
+ * Features:
8
+ * - Deterministic: same input always produces the same embedding
9
+ * - FNV-1a hash seeding with multi-round mixing
10
+ * - L2-normalized output vectors
11
+ * - Sub-millisecond generation (<0.1ms typical)
12
+ * - RvfEmbeddingCache for binary file persistence
13
+ * - Zero external dependencies
14
+ *
15
+ * Use cases:
16
+ * - Fast similarity search where relative distances matter more than semantics
17
+ * - Development and testing without API keys
18
+ * - Offline environments without neural model access
19
+ * - Bootstrapping before heavier providers are available
20
+ *
21
+ * @module @sparkleideas/embeddings
22
+ */
23
+ import { EventEmitter } from 'events';
24
+ import type { EmbeddingProvider, EmbeddingResult, BatchEmbeddingResult, IEmbeddingService, EmbeddingEventListener, RvfEmbeddingConfig } from './types.js';
25
+ /**
26
+ * Lightweight hash-based embedding service.
27
+ *
28
+ * Generates deterministic embeddings from text using FNV-1a hashing
29
+ * with multi-round mixing and L2 normalization. The output is a unit
30
+ * vector in R^n where n = configured dimensions (default 384).
31
+ *
32
+ * Extends EventEmitter and implements IEmbeddingService for drop-in
33
+ * compatibility with other providers.
34
+ */
35
+ export declare class RvfEmbeddingService extends EventEmitter implements IEmbeddingService {
36
+ readonly provider: EmbeddingProvider;
37
+ private readonly dimensions;
38
+ private readonly cache;
39
+ private readonly normalizationType;
40
+ private readonly embeddingListeners;
41
+ private persistentCache;
42
+ constructor(config: RvfEmbeddingConfig);
43
+ /**
44
+ * Generate an embedding for a single text string.
45
+ */
46
+ embed(text: string): Promise<EmbeddingResult>;
47
+ /**
48
+ * Generate embeddings for multiple text strings.
49
+ */
50
+ embedBatch(texts: string[]): Promise<BatchEmbeddingResult>;
51
+ clearCache(): void;
52
+ getCacheStats(): {
53
+ size: number;
54
+ maxSize: number;
55
+ hitRate: number;
56
+ };
57
+ shutdown(): Promise<void>;
58
+ addEventListener(listener: EmbeddingEventListener): void;
59
+ removeEventListener(listener: EmbeddingEventListener): void;
60
+ private emitEvent;
61
+ /**
62
+ * Generate a deterministic embedding from text using FNV-1a hashing.
63
+ *
64
+ * Algorithm:
65
+ * 1. Compute a base FNV-1a hash of the full text.
66
+ * 2. For each dimension, derive a unique seed by mixing the base hash
67
+ * with the dimension index using the golden ratio constant.
68
+ * 3. Apply a sine-based pseudo-random transform to spread values.
69
+ * 4. L2-normalize the result to produce a unit vector.
70
+ *
71
+ * This is deterministic: the same text always yields the same vector.
72
+ */
73
+ private generateHashEmbedding;
74
+ /**
75
+ * Apply user-configured normalization if set.
76
+ */
77
+ private applyNormalization;
78
+ }
79
+ //# sourceMappingURL=rvf-embedding-service.d.ts.map