@opensaas/stack-rag 0.1.6

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 (149) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +10 -0
  3. package/CLAUDE.md +565 -0
  4. package/LICENSE +21 -0
  5. package/README.md +406 -0
  6. package/dist/config/index.d.ts +63 -0
  7. package/dist/config/index.d.ts.map +1 -0
  8. package/dist/config/index.js +94 -0
  9. package/dist/config/index.js.map +1 -0
  10. package/dist/config/plugin.d.ts +38 -0
  11. package/dist/config/plugin.d.ts.map +1 -0
  12. package/dist/config/plugin.js +215 -0
  13. package/dist/config/plugin.js.map +1 -0
  14. package/dist/config/plugin.test.d.ts +2 -0
  15. package/dist/config/plugin.test.d.ts.map +1 -0
  16. package/dist/config/plugin.test.js +554 -0
  17. package/dist/config/plugin.test.js.map +1 -0
  18. package/dist/config/types.d.ts +249 -0
  19. package/dist/config/types.d.ts.map +1 -0
  20. package/dist/config/types.js +5 -0
  21. package/dist/config/types.js.map +1 -0
  22. package/dist/fields/embedding.d.ts +85 -0
  23. package/dist/fields/embedding.d.ts.map +1 -0
  24. package/dist/fields/embedding.js +81 -0
  25. package/dist/fields/embedding.js.map +1 -0
  26. package/dist/fields/embedding.test.d.ts +2 -0
  27. package/dist/fields/embedding.test.d.ts.map +1 -0
  28. package/dist/fields/embedding.test.js +323 -0
  29. package/dist/fields/embedding.test.js.map +1 -0
  30. package/dist/fields/index.d.ts +6 -0
  31. package/dist/fields/index.d.ts.map +1 -0
  32. package/dist/fields/index.js +5 -0
  33. package/dist/fields/index.js.map +1 -0
  34. package/dist/index.d.ts +8 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +9 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/mcp/index.d.ts +19 -0
  39. package/dist/mcp/index.d.ts.map +1 -0
  40. package/dist/mcp/index.js +18 -0
  41. package/dist/mcp/index.js.map +1 -0
  42. package/dist/providers/index.d.ts +38 -0
  43. package/dist/providers/index.d.ts.map +1 -0
  44. package/dist/providers/index.js +68 -0
  45. package/dist/providers/index.js.map +1 -0
  46. package/dist/providers/ollama.d.ts +49 -0
  47. package/dist/providers/ollama.d.ts.map +1 -0
  48. package/dist/providers/ollama.js +151 -0
  49. package/dist/providers/ollama.js.map +1 -0
  50. package/dist/providers/openai.d.ts +41 -0
  51. package/dist/providers/openai.d.ts.map +1 -0
  52. package/dist/providers/openai.js +126 -0
  53. package/dist/providers/openai.js.map +1 -0
  54. package/dist/providers/providers.test.d.ts +2 -0
  55. package/dist/providers/providers.test.d.ts.map +1 -0
  56. package/dist/providers/providers.test.js +224 -0
  57. package/dist/providers/providers.test.js.map +1 -0
  58. package/dist/providers/types.d.ts +88 -0
  59. package/dist/providers/types.d.ts.map +1 -0
  60. package/dist/providers/types.js +2 -0
  61. package/dist/providers/types.js.map +1 -0
  62. package/dist/runtime/batch.d.ts +183 -0
  63. package/dist/runtime/batch.d.ts.map +1 -0
  64. package/dist/runtime/batch.js +240 -0
  65. package/dist/runtime/batch.js.map +1 -0
  66. package/dist/runtime/batch.test.d.ts +2 -0
  67. package/dist/runtime/batch.test.d.ts.map +1 -0
  68. package/dist/runtime/batch.test.js +251 -0
  69. package/dist/runtime/batch.test.js.map +1 -0
  70. package/dist/runtime/chunking.d.ts +42 -0
  71. package/dist/runtime/chunking.d.ts.map +1 -0
  72. package/dist/runtime/chunking.js +264 -0
  73. package/dist/runtime/chunking.js.map +1 -0
  74. package/dist/runtime/chunking.test.d.ts +2 -0
  75. package/dist/runtime/chunking.test.d.ts.map +1 -0
  76. package/dist/runtime/chunking.test.js +212 -0
  77. package/dist/runtime/chunking.test.js.map +1 -0
  78. package/dist/runtime/embeddings.d.ts +147 -0
  79. package/dist/runtime/embeddings.d.ts.map +1 -0
  80. package/dist/runtime/embeddings.js +201 -0
  81. package/dist/runtime/embeddings.js.map +1 -0
  82. package/dist/runtime/embeddings.test.d.ts +2 -0
  83. package/dist/runtime/embeddings.test.d.ts.map +1 -0
  84. package/dist/runtime/embeddings.test.js +366 -0
  85. package/dist/runtime/embeddings.test.js.map +1 -0
  86. package/dist/runtime/index.d.ts +14 -0
  87. package/dist/runtime/index.d.ts.map +1 -0
  88. package/dist/runtime/index.js +18 -0
  89. package/dist/runtime/index.js.map +1 -0
  90. package/dist/runtime/search.d.ts +135 -0
  91. package/dist/runtime/search.d.ts.map +1 -0
  92. package/dist/runtime/search.js +101 -0
  93. package/dist/runtime/search.js.map +1 -0
  94. package/dist/storage/index.d.ts +41 -0
  95. package/dist/storage/index.d.ts.map +1 -0
  96. package/dist/storage/index.js +73 -0
  97. package/dist/storage/index.js.map +1 -0
  98. package/dist/storage/json.d.ts +34 -0
  99. package/dist/storage/json.d.ts.map +1 -0
  100. package/dist/storage/json.js +82 -0
  101. package/dist/storage/json.js.map +1 -0
  102. package/dist/storage/pgvector.d.ts +53 -0
  103. package/dist/storage/pgvector.d.ts.map +1 -0
  104. package/dist/storage/pgvector.js +168 -0
  105. package/dist/storage/pgvector.js.map +1 -0
  106. package/dist/storage/sqlite-vss.d.ts +49 -0
  107. package/dist/storage/sqlite-vss.d.ts.map +1 -0
  108. package/dist/storage/sqlite-vss.js +148 -0
  109. package/dist/storage/sqlite-vss.js.map +1 -0
  110. package/dist/storage/storage.test.d.ts +2 -0
  111. package/dist/storage/storage.test.d.ts.map +1 -0
  112. package/dist/storage/storage.test.js +440 -0
  113. package/dist/storage/storage.test.js.map +1 -0
  114. package/dist/storage/types.d.ts +79 -0
  115. package/dist/storage/types.d.ts.map +1 -0
  116. package/dist/storage/types.js +49 -0
  117. package/dist/storage/types.js.map +1 -0
  118. package/package.json +82 -0
  119. package/src/config/index.ts +116 -0
  120. package/src/config/plugin.test.ts +664 -0
  121. package/src/config/plugin.ts +257 -0
  122. package/src/config/types.ts +283 -0
  123. package/src/fields/embedding.test.ts +408 -0
  124. package/src/fields/embedding.ts +150 -0
  125. package/src/fields/index.ts +6 -0
  126. package/src/index.ts +33 -0
  127. package/src/mcp/index.ts +21 -0
  128. package/src/providers/index.ts +81 -0
  129. package/src/providers/ollama.ts +186 -0
  130. package/src/providers/openai.ts +161 -0
  131. package/src/providers/providers.test.ts +275 -0
  132. package/src/providers/types.ts +100 -0
  133. package/src/runtime/batch.test.ts +332 -0
  134. package/src/runtime/batch.ts +424 -0
  135. package/src/runtime/chunking.test.ts +258 -0
  136. package/src/runtime/chunking.ts +334 -0
  137. package/src/runtime/embeddings.test.ts +441 -0
  138. package/src/runtime/embeddings.ts +380 -0
  139. package/src/runtime/index.ts +51 -0
  140. package/src/runtime/search.ts +243 -0
  141. package/src/storage/index.ts +86 -0
  142. package/src/storage/json.ts +106 -0
  143. package/src/storage/pgvector.ts +206 -0
  144. package/src/storage/sqlite-vss.ts +193 -0
  145. package/src/storage/storage.test.ts +521 -0
  146. package/src/storage/types.ts +126 -0
  147. package/tsconfig.json +13 -0
  148. package/tsconfig.tsbuildinfo +1 -0
  149. package/vitest.config.ts +18 -0
@@ -0,0 +1,148 @@
1
+ import { cosineSimilarity as calculateCosineSimilarity } from './types.js';
2
+ import { getDbKey } from '@opensaas/stack-core';
3
+ /**
4
+ * SQLite VSS storage backend
5
+ * Uses sqlite-vss extension for vector similarity search
6
+ * Requires: sqlite-vss extension to be loaded
7
+ */
8
+ export class SqliteVssStorage {
9
+ type = 'sqlite-vss';
10
+ distanceFunction;
11
+ constructor(config) {
12
+ this.distanceFunction = config.distanceFunction || 'cosine';
13
+ }
14
+ /**
15
+ * Convert distance to similarity score (0-1, higher is more similar)
16
+ */
17
+ distanceToScore(distance) {
18
+ if (this.distanceFunction === 'cosine') {
19
+ // Cosine distance is 1 - similarity
20
+ return 1 - distance;
21
+ }
22
+ else {
23
+ // L2 distance: convert to similarity using 1 / (1 + distance)
24
+ return 1 / (1 + distance);
25
+ }
26
+ }
27
+ /**
28
+ * Search for similar vectors using sqlite-vss
29
+ */
30
+ async search(listKey, fieldName, queryVector, options) {
31
+ const { limit = 10, minScore = 0.0, context, where = {} } = options;
32
+ const dbKey = getDbKey(listKey);
33
+ const model = context.db[dbKey];
34
+ if (!model) {
35
+ throw new Error(`List '${listKey}' not found in context.db`);
36
+ }
37
+ try {
38
+ // Get the underlying Prisma client
39
+ const prisma = context.prisma;
40
+ if (!prisma) {
41
+ // Fallback: if we can't access Prisma directly, use JSON storage approach
42
+ console.warn('sqlite-vss: Could not access Prisma client directly. ' +
43
+ 'Falling back to JSON-based search. ' +
44
+ 'For full sqlite-vss support, ensure the context exposes _prisma.');
45
+ return this.fallbackSearch(listKey, fieldName, queryVector, options);
46
+ }
47
+ // Build JSON array string for the vector
48
+ // Note: vectorString would be used for native sqlite-vss queries
49
+ // Currently using fallback JS-based search
50
+ // const vectorString = JSON.stringify(queryVector)
51
+ // Table name (Prisma uses PascalCase in schema but lowercases in DB)
52
+ // Note: tableName would be used for native sqlite-vss queries
53
+ // const tableName = listKey
54
+ // SQLite VSS query
55
+ // We need to create a virtual table for VSS search
56
+ // For now, we'll use a simpler approach: extract vectors and compute in JS
57
+ // Full sqlite-vss integration would require creating virtual tables at schema generation time
58
+ // Query to get all items with embeddings
59
+ const items = await model.findMany({
60
+ where: {
61
+ ...where,
62
+ [fieldName]: {
63
+ not: null,
64
+ },
65
+ },
66
+ });
67
+ // Calculate similarity for each item (JavaScript fallback)
68
+ const results = [];
69
+ for (const item of items) {
70
+ const embeddingData = item[fieldName];
71
+ if (!embeddingData || !embeddingData.vector) {
72
+ continue;
73
+ }
74
+ const storedVector = embeddingData.vector;
75
+ // Validate vector dimensions
76
+ if (storedVector.length !== queryVector.length) {
77
+ console.warn(`Vector dimension mismatch for ${listKey}.${item.id}.${fieldName}: ` +
78
+ `expected ${queryVector.length}, got ${storedVector.length}. Skipping.`);
79
+ continue;
80
+ }
81
+ // Calculate similarity
82
+ let distance;
83
+ if (this.distanceFunction === 'cosine') {
84
+ const similarity = this.cosineSimilarity(queryVector, storedVector);
85
+ distance = 1 - similarity;
86
+ }
87
+ else {
88
+ // L2 distance
89
+ distance = Math.sqrt(storedVector.reduce((sum, val, i) => {
90
+ const diff = val - queryVector[i];
91
+ return sum + diff * diff;
92
+ }, 0));
93
+ }
94
+ const score = this.distanceToScore(distance);
95
+ if (score >= minScore) {
96
+ results.push({
97
+ item: item,
98
+ score,
99
+ distance,
100
+ });
101
+ }
102
+ }
103
+ // Sort by score (descending) and limit results
104
+ results.sort((a, b) => b.score - a.score);
105
+ return results.slice(0, limit);
106
+ }
107
+ catch (error) {
108
+ throw new Error(`sqlite-vss search failed: ${error.message}\n` +
109
+ 'Ensure sqlite-vss extension is loaded in your SQLite connection.');
110
+ }
111
+ }
112
+ /**
113
+ * Fallback to JSON-based search if we can't access Prisma directly
114
+ */
115
+ async fallbackSearch(listKey, fieldName, queryVector, options) {
116
+ const { JsonVectorStorage } = await import('./json.js');
117
+ const jsonStorage = new JsonVectorStorage();
118
+ return jsonStorage.search(listKey, fieldName, queryVector, options);
119
+ }
120
+ /**
121
+ * Calculate cosine similarity between two vectors
122
+ */
123
+ cosineSimilarity(a, b) {
124
+ return calculateCosineSimilarity(a, b);
125
+ }
126
+ }
127
+ /**
128
+ * Create a SQLite VSS storage instance
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * import { createSqliteVssStorage } from '@opensaas/stack-rag/storage'
133
+ *
134
+ * const storage = createSqliteVssStorage({
135
+ * type: 'sqlite-vss',
136
+ * distanceFunction: 'cosine'
137
+ * })
138
+ *
139
+ * const results = await storage.search('Article', 'contentEmbedding', queryVector, {
140
+ * limit: 10,
141
+ * context
142
+ * })
143
+ * ```
144
+ */
145
+ export function createSqliteVssStorage(config) {
146
+ return new SqliteVssStorage(config);
147
+ }
148
+ //# sourceMappingURL=sqlite-vss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-vss.js","sourceRoot":"","sources":["../../src/storage/sqlite-vss.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../src/storage/storage.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,440 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ import { JsonVectorStorage } from './json.js';
3
+ import { createVectorStorage } from './index.js';
4
+ import { cosineSimilarity, dotProduct, l2Distance } from './types.js';
5
+ // Helper to create mock context
6
+ function createMockContext(dbOverrides = {}) {
7
+ return {
8
+ db: dbOverrides,
9
+ session: null,
10
+ sudo: vi.fn(),
11
+ prisma: {},
12
+ storage: {},
13
+ };
14
+ }
15
+ describe('Vector Storage', () => {
16
+ describe('JsonVectorStorage', () => {
17
+ let storage;
18
+ beforeEach(() => {
19
+ storage = new JsonVectorStorage();
20
+ });
21
+ describe('constructor', () => {
22
+ it('should initialize with correct type', () => {
23
+ expect(storage.type).toBe('json');
24
+ });
25
+ });
26
+ describe('search', () => {
27
+ it('should throw error for non-existent list', async () => {
28
+ const mockContext = createMockContext({});
29
+ const queryVector = [0.1, 0.2, 0.3];
30
+ await expect(storage.search('NonExistentList', 'embedding', queryVector, {
31
+ context: mockContext,
32
+ })).rejects.toThrow(/List 'NonExistentList' not found/);
33
+ });
34
+ it('should return empty results when no items match', async () => {
35
+ const mockContext = createMockContext({
36
+ article: {
37
+ findMany: vi.fn().mockResolvedValue([]),
38
+ },
39
+ });
40
+ const queryVector = [0.1, 0.2, 0.3];
41
+ const results = await storage.search('Article', 'embedding', queryVector, {
42
+ context: mockContext,
43
+ });
44
+ expect(results).toEqual([]);
45
+ });
46
+ it('should filter items with null embeddings', async () => {
47
+ const mockItems = [
48
+ {
49
+ id: '1',
50
+ title: 'Article 1',
51
+ embedding: null,
52
+ },
53
+ {
54
+ id: '2',
55
+ title: 'Article 2',
56
+ embedding: {
57
+ vector: [0.1, 0.2, 0.3],
58
+ metadata: {
59
+ model: 'test',
60
+ provider: 'test',
61
+ dimensions: 3,
62
+ generatedAt: new Date().toISOString(),
63
+ },
64
+ },
65
+ },
66
+ ];
67
+ const mockContext = createMockContext({
68
+ article: {
69
+ findMany: vi.fn().mockResolvedValue(mockItems),
70
+ },
71
+ });
72
+ const queryVector = [0.1, 0.2, 0.3];
73
+ const results = await storage.search('Article', 'embedding', queryVector, {
74
+ context: mockContext,
75
+ });
76
+ expect(results).toHaveLength(1);
77
+ expect(results[0].item.id).toBe('2');
78
+ });
79
+ it('should calculate cosine similarity correctly', async () => {
80
+ const embedding1 = {
81
+ vector: [1.0, 0.0, 0.0],
82
+ metadata: {
83
+ model: 'test',
84
+ provider: 'test',
85
+ dimensions: 3,
86
+ generatedAt: new Date().toISOString(),
87
+ },
88
+ };
89
+ const embedding2 = {
90
+ vector: [0.0, 1.0, 0.0],
91
+ metadata: {
92
+ model: 'test',
93
+ provider: 'test',
94
+ dimensions: 3,
95
+ generatedAt: new Date().toISOString(),
96
+ },
97
+ };
98
+ const embedding3 = {
99
+ vector: [1.0, 0.0, 0.0],
100
+ metadata: {
101
+ model: 'test',
102
+ provider: 'test',
103
+ dimensions: 3,
104
+ generatedAt: new Date().toISOString(),
105
+ },
106
+ };
107
+ const mockItems = [
108
+ { id: '1', embedding: embedding1 },
109
+ { id: '2', embedding: embedding2 },
110
+ { id: '3', embedding: embedding3 },
111
+ ];
112
+ const mockContext = createMockContext({
113
+ article: {
114
+ findMany: vi.fn().mockResolvedValue(mockItems),
115
+ },
116
+ });
117
+ const queryVector = [1.0, 0.0, 0.0]; // Same as embedding1 and embedding3
118
+ const results = await storage.search('Article', 'embedding', queryVector, {
119
+ context: mockContext,
120
+ limit: 10,
121
+ });
122
+ expect(results).toHaveLength(3);
123
+ // Items 1 and 3 should have perfect similarity (score = 1.0)
124
+ expect(results[0].score).toBeCloseTo(1.0, 5);
125
+ expect(results[1].score).toBeCloseTo(1.0, 5);
126
+ // Item 2 should have perpendicular vectors (cosine similarity normalized to 0.5)
127
+ expect(results[2].score).toBeCloseTo(0.5, 5);
128
+ });
129
+ it('should respect limit parameter', async () => {
130
+ const mockItems = Array.from({ length: 20 }, (_, i) => ({
131
+ id: String(i + 1),
132
+ embedding: {
133
+ vector: [Math.random(), Math.random(), Math.random()],
134
+ metadata: {
135
+ model: 'test',
136
+ provider: 'test',
137
+ dimensions: 3,
138
+ generatedAt: new Date().toISOString(),
139
+ },
140
+ },
141
+ }));
142
+ const mockContext = createMockContext({
143
+ article: {
144
+ findMany: vi.fn().mockResolvedValue(mockItems),
145
+ },
146
+ });
147
+ const queryVector = [0.5, 0.5, 0.5];
148
+ const results = await storage.search('Article', 'embedding', queryVector, {
149
+ context: mockContext,
150
+ limit: 5,
151
+ });
152
+ expect(results).toHaveLength(5);
153
+ });
154
+ it('should respect minScore parameter', async () => {
155
+ const mockItems = [
156
+ {
157
+ id: '1',
158
+ embedding: {
159
+ vector: [1.0, 0.0, 0.0], // Perfect match
160
+ metadata: {
161
+ model: 'test',
162
+ provider: 'test',
163
+ dimensions: 3,
164
+ generatedAt: new Date().toISOString(),
165
+ },
166
+ },
167
+ },
168
+ {
169
+ id: '2',
170
+ embedding: {
171
+ vector: [0.0, 1.0, 0.0], // No match (perpendicular)
172
+ metadata: {
173
+ model: 'test',
174
+ provider: 'test',
175
+ dimensions: 3,
176
+ generatedAt: new Date().toISOString(),
177
+ },
178
+ },
179
+ },
180
+ ];
181
+ const mockContext = createMockContext({
182
+ article: {
183
+ findMany: vi.fn().mockResolvedValue(mockItems),
184
+ },
185
+ });
186
+ const queryVector = [1.0, 0.0, 0.0];
187
+ const results = await storage.search('Article', 'embedding', queryVector, {
188
+ context: mockContext,
189
+ minScore: 0.9, // Only items with >90% similarity
190
+ });
191
+ expect(results).toHaveLength(1);
192
+ expect(results[0].item.id).toBe('1');
193
+ });
194
+ it('should sort results by score descending', async () => {
195
+ const mockItems = [
196
+ {
197
+ id: '1',
198
+ score: 0.5,
199
+ embedding: {
200
+ vector: [0.5, 0.5, 0.5],
201
+ metadata: {
202
+ model: 'test',
203
+ provider: 'test',
204
+ dimensions: 3,
205
+ generatedAt: new Date().toISOString(),
206
+ },
207
+ },
208
+ },
209
+ {
210
+ id: '2',
211
+ score: 0.9,
212
+ embedding: {
213
+ vector: [0.9, 0.9, 0.9],
214
+ metadata: {
215
+ model: 'test',
216
+ provider: 'test',
217
+ dimensions: 3,
218
+ generatedAt: new Date().toISOString(),
219
+ },
220
+ },
221
+ },
222
+ {
223
+ id: '3',
224
+ score: 0.7,
225
+ embedding: {
226
+ vector: [0.7, 0.7, 0.7],
227
+ metadata: {
228
+ model: 'test',
229
+ provider: 'test',
230
+ dimensions: 3,
231
+ generatedAt: new Date().toISOString(),
232
+ },
233
+ },
234
+ },
235
+ ];
236
+ const mockContext = createMockContext({
237
+ article: {
238
+ findMany: vi.fn().mockResolvedValue(mockItems),
239
+ },
240
+ });
241
+ const queryVector = [1.0, 1.0, 1.0];
242
+ const results = await storage.search('Article', 'embedding', queryVector, {
243
+ context: mockContext,
244
+ });
245
+ // Results should be sorted by similarity score descending
246
+ expect(results[0].score).toBeGreaterThanOrEqual(results[1].score);
247
+ expect(results[1].score).toBeGreaterThanOrEqual(results[2].score);
248
+ });
249
+ it('should skip items with dimension mismatch', async () => {
250
+ const mockItems = [
251
+ {
252
+ id: '1',
253
+ embedding: {
254
+ vector: [0.1, 0.2], // 2 dimensions
255
+ metadata: {
256
+ model: 'test',
257
+ provider: 'test',
258
+ dimensions: 2,
259
+ generatedAt: new Date().toISOString(),
260
+ },
261
+ },
262
+ },
263
+ {
264
+ id: '2',
265
+ embedding: {
266
+ vector: [0.1, 0.2, 0.3], // 3 dimensions - correct
267
+ metadata: {
268
+ model: 'test',
269
+ provider: 'test',
270
+ dimensions: 3,
271
+ generatedAt: new Date().toISOString(),
272
+ },
273
+ },
274
+ },
275
+ ];
276
+ const mockContext = createMockContext({
277
+ article: {
278
+ findMany: vi.fn().mockResolvedValue(mockItems),
279
+ },
280
+ });
281
+ const queryVector = [0.1, 0.2, 0.3]; // 3 dimensions
282
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
283
+ const results = await storage.search('Article', 'embedding', queryVector, {
284
+ context: mockContext,
285
+ });
286
+ expect(results).toHaveLength(1);
287
+ expect(results[0].item.id).toBe('2');
288
+ expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('Vector dimension mismatch'));
289
+ consoleWarnSpy.mockRestore();
290
+ });
291
+ it('should pass through where clause to Prisma', async () => {
292
+ const mockContext = createMockContext({
293
+ article: {
294
+ findMany: vi.fn().mockResolvedValue([]),
295
+ },
296
+ });
297
+ const queryVector = [0.1, 0.2, 0.3];
298
+ const whereClause = { published: true };
299
+ await storage.search('Article', 'embedding', queryVector, {
300
+ context: mockContext,
301
+ where: whereClause,
302
+ });
303
+ expect(mockContext.db.article
304
+ .findMany).toHaveBeenCalledWith({
305
+ where: {
306
+ published: true,
307
+ embedding: { not: null },
308
+ },
309
+ });
310
+ });
311
+ it('should include distance in results', async () => {
312
+ const mockItems = [
313
+ {
314
+ id: '1',
315
+ embedding: {
316
+ vector: [1.0, 0.0, 0.0],
317
+ metadata: {
318
+ model: 'test',
319
+ provider: 'test',
320
+ dimensions: 3,
321
+ generatedAt: new Date().toISOString(),
322
+ },
323
+ },
324
+ },
325
+ ];
326
+ const mockContext = createMockContext({
327
+ article: {
328
+ findMany: vi.fn().mockResolvedValue(mockItems),
329
+ },
330
+ });
331
+ const queryVector = [1.0, 0.0, 0.0];
332
+ const results = await storage.search('Article', 'embedding', queryVector, {
333
+ context: mockContext,
334
+ });
335
+ expect(results[0]).toHaveProperty('distance');
336
+ expect(results[0].distance).toBeCloseTo(0.0, 5); // distance = 1 - score, perfect match = 0 distance
337
+ });
338
+ });
339
+ describe('cosineSimilarity', () => {
340
+ it('should calculate similarity for identical vectors', () => {
341
+ const vec1 = [1.0, 2.0, 3.0];
342
+ const vec2 = [1.0, 2.0, 3.0];
343
+ const similarity = storage.cosineSimilarity(vec1, vec2);
344
+ expect(similarity).toBeCloseTo(1.0, 5);
345
+ });
346
+ it('should calculate similarity for perpendicular vectors', () => {
347
+ const vec1 = [1.0, 0.0, 0.0];
348
+ const vec2 = [0.0, 1.0, 0.0];
349
+ const similarity = storage.cosineSimilarity(vec1, vec2);
350
+ // Cosine similarity is normalized to 0-1 range in the implementation
351
+ // Perpendicular vectors have cosine 0, which becomes 0.5 after normalization
352
+ expect(similarity).toBeCloseTo(0.5, 5);
353
+ });
354
+ it('should calculate similarity for opposite vectors', () => {
355
+ const vec1 = [1.0, 0.0, 0.0];
356
+ const vec2 = [-1.0, 0.0, 0.0];
357
+ const similarity = storage.cosineSimilarity(vec1, vec2);
358
+ // Cosine similarity is normalized to 0-1 range in the implementation
359
+ // Opposite vectors have cosine -1, which becomes 0.0 after normalization
360
+ expect(similarity).toBeCloseTo(0.0, 5);
361
+ });
362
+ });
363
+ });
364
+ describe('Similarity utility functions', () => {
365
+ describe('cosineSimilarity', () => {
366
+ it('should calculate cosine similarity correctly', () => {
367
+ const vec1 = [1.0, 0.0, 0.0];
368
+ const vec2 = [1.0, 0.0, 0.0];
369
+ expect(cosineSimilarity(vec1, vec2)).toBeCloseTo(1.0, 5);
370
+ });
371
+ it('should handle zero vectors', () => {
372
+ const vec1 = [0.0, 0.0, 0.0];
373
+ const vec2 = [1.0, 0.0, 0.0];
374
+ expect(cosineSimilarity(vec1, vec2)).toBe(0);
375
+ });
376
+ it('should throw for mismatched dimensions', () => {
377
+ const vec1 = [1.0, 0.0];
378
+ const vec2 = [1.0, 0.0, 0.0];
379
+ expect(() => cosineSimilarity(vec1, vec2)).toThrow('Vector dimension mismatch');
380
+ });
381
+ });
382
+ describe('dotProduct', () => {
383
+ it('should calculate dot product correctly', () => {
384
+ const vec1 = [1.0, 2.0, 3.0];
385
+ const vec2 = [4.0, 5.0, 6.0];
386
+ // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
387
+ expect(dotProduct(vec1, vec2)).toBe(32);
388
+ });
389
+ it('should return 0 for perpendicular vectors', () => {
390
+ const vec1 = [1.0, 0.0, 0.0];
391
+ const vec2 = [0.0, 1.0, 0.0];
392
+ expect(dotProduct(vec1, vec2)).toBe(0);
393
+ });
394
+ it('should throw for mismatched dimensions', () => {
395
+ const vec1 = [1.0, 0.0];
396
+ const vec2 = [1.0, 0.0, 0.0];
397
+ expect(() => dotProduct(vec1, vec2)).toThrow('Vector dimension mismatch');
398
+ });
399
+ });
400
+ describe('l2Distance', () => {
401
+ it('should calculate L2 distance correctly', () => {
402
+ const vec1 = [0.0, 0.0, 0.0];
403
+ const vec2 = [3.0, 4.0, 0.0];
404
+ // sqrt((3-0)^2 + (4-0)^2 + (0-0)^2) = sqrt(9 + 16) = 5
405
+ expect(l2Distance(vec1, vec2)).toBe(5);
406
+ });
407
+ it('should return 0 for identical vectors', () => {
408
+ const vec1 = [1.0, 2.0, 3.0];
409
+ const vec2 = [1.0, 2.0, 3.0];
410
+ expect(l2Distance(vec1, vec2)).toBe(0);
411
+ });
412
+ it('should throw for mismatched dimensions', () => {
413
+ const vec1 = [1.0, 0.0];
414
+ const vec2 = [1.0, 0.0, 0.0];
415
+ expect(() => l2Distance(vec1, vec2)).toThrow('Vector dimension mismatch');
416
+ });
417
+ });
418
+ });
419
+ describe('createVectorStorage factory', () => {
420
+ it('should create JSON storage', () => {
421
+ const storage = createVectorStorage({ type: 'json' });
422
+ expect(storage).toBeInstanceOf(JsonVectorStorage);
423
+ expect(storage.type).toBe('json');
424
+ });
425
+ it('should throw error for unknown storage type', () => {
426
+ expect(() => {
427
+ createVectorStorage({ type: 'unknown' });
428
+ }).toThrow(/Unknown vector storage type/);
429
+ });
430
+ });
431
+ describe('Storage interface compliance', () => {
432
+ it('JSON storage should implement VectorStorage interface', () => {
433
+ const storage = new JsonVectorStorage();
434
+ expect(storage).toHaveProperty('type');
435
+ expect(storage).toHaveProperty('search');
436
+ expect(typeof storage.search).toBe('function');
437
+ });
438
+ });
439
+ });
440
+ //# sourceMappingURL=storage.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../src/storage/storage.test.ts"],"names":[],"mappings":"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"}