@samanhappy/mcphub 0.6.2 → 0.7.1

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 (50) hide show
  1. package/README.md +36 -18
  2. package/README.zh.md +35 -17
  3. package/dist/config/index.js +1 -0
  4. package/dist/config/index.js.map +1 -1
  5. package/dist/controllers/configController.js +28 -0
  6. package/dist/controllers/configController.js.map +1 -0
  7. package/dist/controllers/serverController.js +83 -2
  8. package/dist/controllers/serverController.js.map +1 -1
  9. package/dist/db/connection.js +279 -0
  10. package/dist/db/connection.js.map +1 -0
  11. package/dist/db/entities/VectorEmbedding.js +62 -0
  12. package/dist/db/entities/VectorEmbedding.js.map +1 -0
  13. package/dist/db/entities/index.js +6 -0
  14. package/dist/db/entities/index.js.map +1 -0
  15. package/dist/db/index.js +32 -0
  16. package/dist/db/index.js.map +1 -0
  17. package/dist/db/repositories/BaseRepository.js +58 -0
  18. package/dist/db/repositories/BaseRepository.js.map +1 -0
  19. package/dist/db/repositories/VectorEmbeddingRepository.js +173 -0
  20. package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -0
  21. package/dist/db/repositories/index.js +4 -0
  22. package/dist/db/repositories/index.js.map +1 -0
  23. package/dist/db/subscribers/VectorEmbeddingSubscriber.js +56 -0
  24. package/dist/db/subscribers/VectorEmbeddingSubscriber.js.map +1 -0
  25. package/dist/db/types/postgresVectorType.js +33 -0
  26. package/dist/db/types/postgresVectorType.js.map +1 -0
  27. package/dist/index.js +1 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/middlewares/index.js +18 -8
  30. package/dist/middlewares/index.js.map +1 -1
  31. package/dist/routes/index.js +13 -9
  32. package/dist/routes/index.js.map +1 -1
  33. package/dist/server.js +18 -9
  34. package/dist/server.js.map +1 -1
  35. package/dist/services/mcpService.js +185 -3
  36. package/dist/services/mcpService.js.map +1 -1
  37. package/dist/services/sseService.js +16 -10
  38. package/dist/services/sseService.js.map +1 -1
  39. package/dist/services/vectorSearchService.js +603 -0
  40. package/dist/services/vectorSearchService.js.map +1 -0
  41. package/frontend/dist/assets/favicon-DJnZjsC8.ico +0 -0
  42. package/frontend/dist/assets/index-CO9hZSAL.js +148 -0
  43. package/frontend/dist/assets/index-CO9hZSAL.js.map +1 -0
  44. package/frontend/dist/assets/index-D9p3VMBc.css +1 -0
  45. package/frontend/dist/index.html +3 -3
  46. package/package.json +15 -7
  47. package/frontend/dist/assets/favicon-DKeT5aEu.ico +0 -0
  48. package/frontend/dist/assets/index-B7KNaMJO.js +0 -148
  49. package/frontend/dist/assets/index-B7KNaMJO.js.map +0 -1
  50. package/frontend/dist/assets/index-DDs5RqXX.css +0 -1
@@ -0,0 +1,603 @@
1
+ import { getRepositoryFactory } from '../db/index.js';
2
+ import { getAppDataSource, initializeDatabase } from '../db/connection.js';
3
+ import { loadSettings } from '../config/index.js';
4
+ import OpenAI from 'openai';
5
+ // Get OpenAI configuration from smartRouting settings or fallback to environment variables
6
+ const getOpenAIConfig = () => {
7
+ try {
8
+ const settings = loadSettings();
9
+ const smartRouting = settings.systemConfig?.smartRouting;
10
+ return {
11
+ apiKey: smartRouting?.openaiApiKey || process.env.OPENAI_API_KEY,
12
+ baseURL: smartRouting?.openaiApiBaseUrl ||
13
+ process.env.OPENAI_API_BASE_URL ||
14
+ 'https://api.openai.com/v1',
15
+ embeddingModel: smartRouting?.openaiApiEmbeddingModel ||
16
+ process.env.OPENAI_API_EMBEDDING_MODEL ||
17
+ 'text-embedding-3-small',
18
+ };
19
+ }
20
+ catch (error) {
21
+ console.warn('Failed to load smartRouting settings, falling back to environment variables:', error);
22
+ return {
23
+ apiKey: '',
24
+ baseURL: 'https://api.openai.com/v1',
25
+ embeddingModel: 'text-embedding-3-small',
26
+ };
27
+ }
28
+ };
29
+ // Environment variables for embedding configuration
30
+ const EMBEDDING_ENV = {
31
+ // The embedding model to use - default to OpenAI but allow BAAI/BGE models
32
+ MODEL: process.env.EMBEDDING_MODEL || getOpenAIConfig().embeddingModel,
33
+ // Detect if using a BGE model from the environment variable
34
+ IS_BGE_MODEL: !!(process.env.EMBEDDING_MODEL && process.env.EMBEDDING_MODEL.includes('bge')),
35
+ };
36
+ // Constants for embedding models
37
+ const EMBEDDING_DIMENSIONS = 1536; // OpenAI's text-embedding-3-small outputs 1536 dimensions
38
+ const BGE_DIMENSIONS = 1024; // BAAI/bge-m3 outputs 1024 dimensions
39
+ const FALLBACK_DIMENSIONS = 100; // Fallback implementation uses 100 dimensions
40
+ // Get dimensions for a model
41
+ const getDimensionsForModel = (model) => {
42
+ if (model.includes('bge-m3')) {
43
+ return BGE_DIMENSIONS;
44
+ }
45
+ else if (model.includes('text-embedding-3')) {
46
+ return EMBEDDING_DIMENSIONS;
47
+ }
48
+ else if (model === 'fallback' || model === 'simple-hash') {
49
+ return FALLBACK_DIMENSIONS;
50
+ }
51
+ // Default to OpenAI dimensions
52
+ return EMBEDDING_DIMENSIONS;
53
+ };
54
+ // Initialize the OpenAI client with smartRouting configuration
55
+ const getOpenAIClient = () => {
56
+ const config = getOpenAIConfig();
57
+ return new OpenAI({
58
+ apiKey: config.apiKey, // Get API key from smartRouting settings or environment variables
59
+ baseURL: config.baseURL, // Get base URL from smartRouting settings or fallback to default
60
+ });
61
+ };
62
+ /**
63
+ * Generate text embedding using OpenAI's embedding model
64
+ *
65
+ * NOTE: embeddings are 1536 dimensions by default.
66
+ * If you previously used the fallback implementation (100 dimensions),
67
+ * you may need to rebuild your vector database indices after switching.
68
+ *
69
+ * @param text Text to generate embeddings for
70
+ * @returns Promise with vector embedding as number array
71
+ */
72
+ async function generateEmbedding(text) {
73
+ try {
74
+ const config = getOpenAIConfig();
75
+ const openai = getOpenAIClient();
76
+ // Check if API key is configured
77
+ if (!openai.apiKey) {
78
+ console.warn('OpenAI API key is not configured. Using fallback embedding method.');
79
+ return generateFallbackEmbedding(text);
80
+ }
81
+ // Truncate text if it's too long (OpenAI has token limits)
82
+ const truncatedText = text.length > 8000 ? text.substring(0, 8000) : text;
83
+ // Call OpenAI's embeddings API
84
+ const response = await openai.embeddings.create({
85
+ model: config.embeddingModel, // Modern model with better performance
86
+ input: truncatedText,
87
+ });
88
+ // Return the embedding
89
+ return response.data[0].embedding;
90
+ }
91
+ catch (error) {
92
+ console.error('Error generating embedding:', error);
93
+ console.warn('Falling back to simple embedding method');
94
+ return generateFallbackEmbedding(text);
95
+ }
96
+ }
97
+ /**
98
+ * Fallback embedding function using a simple approach when OpenAI API is unavailable
99
+ * @param text Text to generate embeddings for
100
+ * @returns Vector embedding as number array
101
+ */
102
+ function generateFallbackEmbedding(text) {
103
+ const words = text.toLowerCase().split(/\s+/);
104
+ const vocabulary = [
105
+ 'search',
106
+ 'find',
107
+ 'get',
108
+ 'fetch',
109
+ 'retrieve',
110
+ 'query',
111
+ 'map',
112
+ 'location',
113
+ 'weather',
114
+ 'file',
115
+ 'directory',
116
+ 'email',
117
+ 'message',
118
+ 'send',
119
+ 'create',
120
+ 'update',
121
+ 'delete',
122
+ 'browser',
123
+ 'web',
124
+ 'page',
125
+ 'click',
126
+ 'navigate',
127
+ 'screenshot',
128
+ 'automation',
129
+ 'database',
130
+ 'table',
131
+ 'record',
132
+ 'insert',
133
+ 'select',
134
+ 'schema',
135
+ 'data',
136
+ 'image',
137
+ 'photo',
138
+ 'video',
139
+ 'media',
140
+ 'upload',
141
+ 'download',
142
+ 'convert',
143
+ 'text',
144
+ 'document',
145
+ 'pdf',
146
+ 'excel',
147
+ 'word',
148
+ 'format',
149
+ 'parse',
150
+ 'api',
151
+ 'rest',
152
+ 'http',
153
+ 'request',
154
+ 'response',
155
+ 'json',
156
+ 'xml',
157
+ 'time',
158
+ 'date',
159
+ 'calendar',
160
+ 'schedule',
161
+ 'reminder',
162
+ 'clock',
163
+ 'math',
164
+ 'calculate',
165
+ 'number',
166
+ 'sum',
167
+ 'average',
168
+ 'statistics',
169
+ 'user',
170
+ 'account',
171
+ 'login',
172
+ 'auth',
173
+ 'permission',
174
+ 'role',
175
+ ];
176
+ // Create vector with fallback dimensions
177
+ const vector = new Array(FALLBACK_DIMENSIONS).fill(0);
178
+ words.forEach((word) => {
179
+ const index = vocabulary.indexOf(word);
180
+ if (index >= 0 && index < vector.length) {
181
+ vector[index] += 1;
182
+ }
183
+ // Add some randomness based on word hash
184
+ const hash = word.split('').reduce((a, b) => a + b.charCodeAt(0), 0);
185
+ vector[hash % vector.length] += 0.1;
186
+ });
187
+ // Normalize the vector
188
+ const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
189
+ if (magnitude > 0) {
190
+ return vector.map((val) => val / magnitude);
191
+ }
192
+ return vector;
193
+ }
194
+ /**
195
+ * Save tool information as vector embeddings
196
+ * @param serverName Server name
197
+ * @param tools Array of tools to save
198
+ */
199
+ export const saveToolsAsVectorEmbeddings = async (serverName, tools) => {
200
+ try {
201
+ const config = getOpenAIConfig();
202
+ const vectorRepository = getRepositoryFactory('vectorEmbeddings')();
203
+ for (const tool of tools) {
204
+ // Create searchable text from tool information
205
+ const searchableText = [
206
+ tool.name,
207
+ tool.description,
208
+ // Include input schema properties if available
209
+ ...(tool.inputSchema && typeof tool.inputSchema === 'object'
210
+ ? Object.keys(tool.inputSchema).filter((key) => key !== 'type' && key !== 'properties')
211
+ : []),
212
+ // Include schema property names if available
213
+ ...(tool.inputSchema &&
214
+ tool.inputSchema.properties &&
215
+ typeof tool.inputSchema.properties === 'object'
216
+ ? Object.keys(tool.inputSchema.properties)
217
+ : []),
218
+ ]
219
+ .filter(Boolean)
220
+ .join(' ');
221
+ try {
222
+ // Generate embedding
223
+ const embedding = await generateEmbedding(searchableText);
224
+ // Check database compatibility before saving
225
+ await checkDatabaseVectorDimensions(embedding.length);
226
+ // Save embedding
227
+ await vectorRepository.saveEmbedding('tool', `${serverName}:${tool.name}`, searchableText, embedding, {
228
+ serverName,
229
+ toolName: tool.name,
230
+ description: tool.description,
231
+ inputSchema: tool.inputSchema,
232
+ }, config.embeddingModel);
233
+ }
234
+ catch (toolError) {
235
+ console.error(`Error processing tool ${tool.name} for server ${serverName}:`, toolError);
236
+ // Continue with the next tool rather than failing the whole batch
237
+ }
238
+ }
239
+ console.log(`Saved ${tools.length} tool embeddings for server: ${serverName}`);
240
+ }
241
+ catch (error) {
242
+ console.error(`Error saving tool embeddings for server ${serverName}:`, error);
243
+ }
244
+ };
245
+ /**
246
+ * Search for tools using vector similarity
247
+ * @param query Search query text
248
+ * @param limit Maximum number of results to return
249
+ * @param threshold Similarity threshold (0-1)
250
+ * @param serverNames Optional array of server names to filter by
251
+ */
252
+ export const searchToolsByVector = async (query, limit = 10, threshold = 0.7, serverNames) => {
253
+ try {
254
+ const vectorRepository = getRepositoryFactory('vectorEmbeddings')();
255
+ // Search by text using vector similarity
256
+ const results = await vectorRepository.searchByText(query, generateEmbedding, limit, threshold, ['tool']);
257
+ // Filter by server names if provided
258
+ let filteredResults = results;
259
+ if (serverNames && serverNames.length > 0) {
260
+ filteredResults = results.filter((result) => {
261
+ if (typeof result.embedding.metadata === 'string') {
262
+ try {
263
+ const parsedMetadata = JSON.parse(result.embedding.metadata);
264
+ return serverNames.includes(parsedMetadata.serverName);
265
+ }
266
+ catch (error) {
267
+ return false;
268
+ }
269
+ }
270
+ return false;
271
+ });
272
+ }
273
+ // Transform results to a more useful format
274
+ return filteredResults.map((result) => {
275
+ // Check if we have metadata as a string that needs to be parsed
276
+ if (result.embedding?.metadata && typeof result.embedding.metadata === 'string') {
277
+ try {
278
+ // Parse the metadata string as JSON
279
+ const parsedMetadata = JSON.parse(result.embedding.metadata);
280
+ if (parsedMetadata.serverName && parsedMetadata.toolName) {
281
+ // We have properly structured metadata
282
+ return {
283
+ serverName: parsedMetadata.serverName,
284
+ toolName: parsedMetadata.toolName,
285
+ description: parsedMetadata.description || '',
286
+ inputSchema: parsedMetadata.inputSchema || {},
287
+ similarity: result.similarity,
288
+ searchableText: result.embedding.text_content,
289
+ };
290
+ }
291
+ }
292
+ catch (error) {
293
+ console.error('Error parsing metadata string:', error);
294
+ // Fall through to the extraction logic below
295
+ }
296
+ }
297
+ // Extract tool info from text_content if metadata is not available or parsing failed
298
+ const textContent = result.embedding?.text_content || '';
299
+ // Extract toolName (first word of text_content)
300
+ const toolNameMatch = textContent.match(/^(\S+)/);
301
+ const toolName = toolNameMatch ? toolNameMatch[1] : '';
302
+ // Extract serverName from toolName if it follows the pattern "serverName_toolPart"
303
+ const serverNameMatch = toolName.match(/^([^_]+)_/);
304
+ const serverName = serverNameMatch ? serverNameMatch[1] : 'unknown';
305
+ // Extract description (everything after the first word)
306
+ const description = textContent.replace(/^\S+\s*/, '').trim();
307
+ return {
308
+ serverName,
309
+ toolName,
310
+ description,
311
+ inputSchema: {},
312
+ similarity: result.similarity,
313
+ searchableText: textContent,
314
+ };
315
+ });
316
+ }
317
+ catch (error) {
318
+ console.error('Error searching tools by vector:', error);
319
+ return [];
320
+ }
321
+ };
322
+ /**
323
+ * Get all available tools in vector database
324
+ * @param serverNames Optional array of server names to filter by
325
+ */
326
+ export const getAllVectorizedTools = async (serverNames) => {
327
+ try {
328
+ const config = getOpenAIConfig();
329
+ const vectorRepository = getRepositoryFactory('vectorEmbeddings')();
330
+ // Try to determine what dimension our database is using
331
+ let dimensionsToUse = getDimensionsForModel(config.embeddingModel); // Default based on the model selected
332
+ try {
333
+ const result = await getAppDataSource().query(`
334
+ SELECT atttypmod as dimensions
335
+ FROM pg_attribute
336
+ WHERE attrelid = 'vector_embeddings'::regclass
337
+ AND attname = 'embedding'
338
+ `);
339
+ if (result && result.length > 0 && result[0].dimensions) {
340
+ const rawValue = result[0].dimensions;
341
+ if (rawValue === -1) {
342
+ // No type modifier specified
343
+ dimensionsToUse = getDimensionsForModel(config.embeddingModel);
344
+ }
345
+ else {
346
+ // For this version of pgvector, atttypmod stores the dimension value directly
347
+ dimensionsToUse = rawValue;
348
+ }
349
+ }
350
+ }
351
+ catch (error) {
352
+ console.warn('Could not determine vector dimensions from database:', error?.message);
353
+ }
354
+ // Get all tool embeddings
355
+ const results = await vectorRepository.searchSimilar(new Array(dimensionsToUse).fill(0), // Zero vector with dimensions matching the database
356
+ 1000, // Large limit
357
+ -1, // No threshold (get all)
358
+ ['tool']);
359
+ // Filter by server names if provided
360
+ let filteredResults = results;
361
+ if (serverNames && serverNames.length > 0) {
362
+ filteredResults = results.filter((result) => {
363
+ if (typeof result.embedding.metadata === 'string') {
364
+ try {
365
+ const parsedMetadata = JSON.parse(result.embedding.metadata);
366
+ return serverNames.includes(parsedMetadata.serverName);
367
+ }
368
+ catch (error) {
369
+ return false;
370
+ }
371
+ }
372
+ return false;
373
+ });
374
+ }
375
+ // Transform results
376
+ return filteredResults.map((result) => {
377
+ if (typeof result.embedding.metadata === 'string') {
378
+ try {
379
+ const parsedMetadata = JSON.parse(result.embedding.metadata);
380
+ return {
381
+ serverName: parsedMetadata.serverName,
382
+ toolName: parsedMetadata.toolName,
383
+ description: parsedMetadata.description,
384
+ inputSchema: parsedMetadata.inputSchema,
385
+ };
386
+ }
387
+ catch (error) {
388
+ console.error('Error parsing metadata string:', error);
389
+ return {
390
+ serverName: 'unknown',
391
+ toolName: 'unknown',
392
+ description: '',
393
+ inputSchema: {},
394
+ };
395
+ }
396
+ }
397
+ return {
398
+ serverName: 'unknown',
399
+ toolName: 'unknown',
400
+ description: '',
401
+ inputSchema: {},
402
+ };
403
+ });
404
+ }
405
+ catch (error) {
406
+ console.error('Error getting all vectorized tools:', error);
407
+ return [];
408
+ }
409
+ };
410
+ /**
411
+ * Remove tool embeddings for a server
412
+ * @param serverName Server name
413
+ */
414
+ export const removeServerToolEmbeddings = async (serverName) => {
415
+ try {
416
+ const vectorRepository = getRepositoryFactory('vectorEmbeddings')();
417
+ // Note: This would require adding a delete method to VectorEmbeddingRepository
418
+ // For now, we'll log that this functionality needs to be implemented
419
+ console.log(`TODO: Remove tool embeddings for server: ${serverName}`);
420
+ }
421
+ catch (error) {
422
+ console.error(`Error removing tool embeddings for server ${serverName}:`, error);
423
+ }
424
+ };
425
+ /**
426
+ * Sync all server tools embeddings when smart routing is first enabled
427
+ * This function will scan all currently connected servers and save their tools as vector embeddings
428
+ */
429
+ export const syncAllServerToolsEmbeddings = async () => {
430
+ try {
431
+ console.log('Starting synchronization of all server tools embeddings...');
432
+ // Import getServersInfo to get all server information
433
+ const { getServersInfo } = await import('./mcpService.js');
434
+ const servers = getServersInfo();
435
+ let totalToolsSynced = 0;
436
+ let serversSynced = 0;
437
+ for (const server of servers) {
438
+ if (server.status === 'connected' && server.tools && server.tools.length > 0) {
439
+ try {
440
+ console.log(`Syncing tools for server: ${server.name} (${server.tools.length} tools)`);
441
+ await saveToolsAsVectorEmbeddings(server.name, server.tools);
442
+ totalToolsSynced += server.tools.length;
443
+ serversSynced++;
444
+ }
445
+ catch (error) {
446
+ console.error(`Failed to sync tools for server ${server.name}:`, error);
447
+ }
448
+ }
449
+ else if (server.status === 'connected' && (!server.tools || server.tools.length === 0)) {
450
+ console.log(`Server ${server.name} is connected but has no tools to sync`);
451
+ }
452
+ else {
453
+ console.log(`Skipping server ${server.name} (status: ${server.status})`);
454
+ }
455
+ }
456
+ console.log(`Smart routing tools sync completed: synced ${totalToolsSynced} tools from ${serversSynced} servers`);
457
+ }
458
+ catch (error) {
459
+ console.error('Error during smart routing tools synchronization:', error);
460
+ throw error;
461
+ }
462
+ };
463
+ /**
464
+ * Check database vector dimensions and ensure compatibility
465
+ * @param dimensionsNeeded The number of dimensions required
466
+ * @returns Promise that resolves when check is complete
467
+ */
468
+ async function checkDatabaseVectorDimensions(dimensionsNeeded) {
469
+ try {
470
+ // First check if database is initialized
471
+ if (!getAppDataSource().isInitialized) {
472
+ console.info('Database not initialized, initializing...');
473
+ await initializeDatabase();
474
+ }
475
+ // Check current vector dimension in the database
476
+ // First try to get vector type info directly
477
+ let vectorTypeInfo;
478
+ try {
479
+ vectorTypeInfo = await getAppDataSource().query(`
480
+ SELECT
481
+ atttypmod,
482
+ format_type(atttypid, atttypmod) as formatted_type
483
+ FROM pg_attribute
484
+ WHERE attrelid = 'vector_embeddings'::regclass
485
+ AND attname = 'embedding'
486
+ `);
487
+ }
488
+ catch (error) {
489
+ console.warn('Could not get vector type info, falling back to atttypmod query');
490
+ }
491
+ // Fallback to original query
492
+ const result = await getAppDataSource().query(`
493
+ SELECT atttypmod as dimensions
494
+ FROM pg_attribute
495
+ WHERE attrelid = 'vector_embeddings'::regclass
496
+ AND attname = 'embedding'
497
+ `);
498
+ let currentDimensions = 0;
499
+ // Parse dimensions from result
500
+ if (result && result.length > 0 && result[0].dimensions) {
501
+ if (vectorTypeInfo && vectorTypeInfo.length > 0) {
502
+ // Try to extract dimensions from formatted type like "vector(1024)"
503
+ const match = vectorTypeInfo[0].formatted_type?.match(/vector\((\d+)\)/);
504
+ if (match) {
505
+ currentDimensions = parseInt(match[1]);
506
+ }
507
+ }
508
+ // If we couldn't extract from formatted type, use the atttypmod value directly
509
+ if (currentDimensions === 0) {
510
+ const rawValue = result[0].dimensions;
511
+ if (rawValue === -1) {
512
+ // No type modifier specified
513
+ currentDimensions = 0;
514
+ }
515
+ else {
516
+ // For this version of pgvector, atttypmod stores the dimension value directly
517
+ currentDimensions = rawValue;
518
+ }
519
+ }
520
+ }
521
+ // Also check the dimensions stored in actual records for validation
522
+ try {
523
+ const recordCheck = await getAppDataSource().query(`
524
+ SELECT dimensions, model, COUNT(*) as count
525
+ FROM vector_embeddings
526
+ GROUP BY dimensions, model
527
+ ORDER BY count DESC
528
+ LIMIT 5
529
+ `);
530
+ if (recordCheck && recordCheck.length > 0) {
531
+ // If we couldn't determine dimensions from schema, use the most common dimension from records
532
+ if (currentDimensions === 0 && recordCheck[0].dimensions) {
533
+ currentDimensions = recordCheck[0].dimensions;
534
+ }
535
+ }
536
+ }
537
+ catch (error) {
538
+ console.warn('Could not check dimensions from actual records:', error);
539
+ }
540
+ // If no dimensions are set or they don't match what we need, handle the mismatch
541
+ if (currentDimensions === 0 || currentDimensions !== dimensionsNeeded) {
542
+ console.log(`Vector dimensions mismatch: database=${currentDimensions}, needed=${dimensionsNeeded}`);
543
+ if (currentDimensions === 0) {
544
+ console.log('Setting up vector dimensions for the first time...');
545
+ }
546
+ else {
547
+ console.log('Dimension mismatch detected. Clearing existing incompatible vector data...');
548
+ // Clear all existing vector embeddings with mismatched dimensions
549
+ await clearMismatchedVectorData(dimensionsNeeded);
550
+ }
551
+ // Drop any existing indices first
552
+ await getAppDataSource().query(`DROP INDEX IF EXISTS idx_vector_embeddings_embedding;`);
553
+ // Alter the column type with the new dimensions
554
+ await getAppDataSource().query(`
555
+ ALTER TABLE vector_embeddings
556
+ ALTER COLUMN embedding TYPE vector(${dimensionsNeeded});
557
+ `);
558
+ // Create a new index with better error handling
559
+ try {
560
+ await getAppDataSource().query(`
561
+ CREATE INDEX idx_vector_embeddings_embedding
562
+ ON vector_embeddings USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
563
+ `);
564
+ }
565
+ catch (indexError) {
566
+ // If the index already exists (code 42P07) or there's a duplicate key constraint (code 23505),
567
+ // it's not a critical error as the index is already there
568
+ if (indexError.code === '42P07' || indexError.code === '23505') {
569
+ console.log('Index already exists, continuing...');
570
+ }
571
+ else {
572
+ console.warn('Warning: Failed to create index, but continuing:', indexError.message);
573
+ }
574
+ }
575
+ console.log(`Successfully configured vector dimensions to ${dimensionsNeeded}`);
576
+ }
577
+ }
578
+ catch (error) {
579
+ console.error('Error checking/updating vector dimensions:', error);
580
+ throw new Error(`Vector dimension check failed: ${error?.message || 'Unknown error'}`);
581
+ }
582
+ }
583
+ /**
584
+ * Clear vector embeddings with mismatched dimensions
585
+ * @param expectedDimensions The expected dimensions
586
+ * @returns Promise that resolves when cleanup is complete
587
+ */
588
+ async function clearMismatchedVectorData(expectedDimensions) {
589
+ try {
590
+ console.log(`Clearing vector embeddings with dimensions different from ${expectedDimensions}...`);
591
+ // Delete all embeddings that don't match the expected dimensions
592
+ await getAppDataSource().query(`
593
+ DELETE FROM vector_embeddings
594
+ WHERE dimensions != $1
595
+ `, [expectedDimensions]);
596
+ console.log('Successfully cleared mismatched vector embeddings');
597
+ }
598
+ catch (error) {
599
+ console.error('Error clearing mismatched vector data:', error);
600
+ throw error;
601
+ }
602
+ }
603
+ //# sourceMappingURL=vectorSearchService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vectorSearchService.js","sourceRoot":"","sources":["../../src/services/vectorSearchService.ts"],"names":[],"mappings":"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"}