@mcampa/claude-context-core 0.1.3

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 (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +285 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/context.d.ts +276 -0
  5. package/dist/context.d.ts.map +1 -0
  6. package/dist/context.js +1080 -0
  7. package/dist/context.js.map +1 -0
  8. package/dist/embedding/base-embedding.d.ts +51 -0
  9. package/dist/embedding/base-embedding.d.ts.map +1 -0
  10. package/dist/embedding/base-embedding.js +36 -0
  11. package/dist/embedding/base-embedding.js.map +1 -0
  12. package/dist/embedding/gemini-embedding.d.ts +53 -0
  13. package/dist/embedding/gemini-embedding.d.ts.map +1 -0
  14. package/dist/embedding/gemini-embedding.js +152 -0
  15. package/dist/embedding/gemini-embedding.js.map +1 -0
  16. package/dist/embedding/index.d.ts +6 -0
  17. package/dist/embedding/index.d.ts.map +1 -0
  18. package/dist/embedding/index.js +24 -0
  19. package/dist/embedding/index.js.map +1 -0
  20. package/dist/embedding/ollama-embedding.d.ts +55 -0
  21. package/dist/embedding/ollama-embedding.d.ts.map +1 -0
  22. package/dist/embedding/ollama-embedding.js +192 -0
  23. package/dist/embedding/ollama-embedding.js.map +1 -0
  24. package/dist/embedding/openai-embedding.d.ts +36 -0
  25. package/dist/embedding/openai-embedding.d.ts.map +1 -0
  26. package/dist/embedding/openai-embedding.js +159 -0
  27. package/dist/embedding/openai-embedding.js.map +1 -0
  28. package/dist/embedding/voyageai-embedding.d.ts +44 -0
  29. package/dist/embedding/voyageai-embedding.d.ts.map +1 -0
  30. package/dist/embedding/voyageai-embedding.js +227 -0
  31. package/dist/embedding/voyageai-embedding.js.map +1 -0
  32. package/dist/index.d.ts +8 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +24 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/splitter/ast-splitter.d.ts +22 -0
  37. package/dist/splitter/ast-splitter.d.ts.map +1 -0
  38. package/dist/splitter/ast-splitter.js +234 -0
  39. package/dist/splitter/ast-splitter.js.map +1 -0
  40. package/dist/splitter/index.d.ts +41 -0
  41. package/dist/splitter/index.d.ts.map +1 -0
  42. package/dist/splitter/index.js +27 -0
  43. package/dist/splitter/index.js.map +1 -0
  44. package/dist/splitter/langchain-splitter.d.ts +13 -0
  45. package/dist/splitter/langchain-splitter.d.ts.map +1 -0
  46. package/dist/splitter/langchain-splitter.js +118 -0
  47. package/dist/splitter/langchain-splitter.js.map +1 -0
  48. package/dist/sync/merkle.d.ts +26 -0
  49. package/dist/sync/merkle.d.ts.map +1 -0
  50. package/dist/sync/merkle.js +112 -0
  51. package/dist/sync/merkle.js.map +1 -0
  52. package/dist/sync/synchronizer.d.ts +30 -0
  53. package/dist/sync/synchronizer.d.ts.map +1 -0
  54. package/dist/sync/synchronizer.js +339 -0
  55. package/dist/sync/synchronizer.js.map +1 -0
  56. package/dist/types.d.ts +14 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +3 -0
  59. package/dist/types.js.map +1 -0
  60. package/dist/utils/env-manager.d.ts +19 -0
  61. package/dist/utils/env-manager.d.ts.map +1 -0
  62. package/dist/utils/env-manager.js +125 -0
  63. package/dist/utils/env-manager.js.map +1 -0
  64. package/dist/utils/git.d.ts +11 -0
  65. package/dist/utils/git.d.ts.map +1 -0
  66. package/dist/utils/git.js +46 -0
  67. package/dist/utils/git.js.map +1 -0
  68. package/dist/utils/index.d.ts +2 -0
  69. package/dist/utils/index.d.ts.map +1 -0
  70. package/dist/utils/index.js +7 -0
  71. package/dist/utils/index.js.map +1 -0
  72. package/dist/vectordb/index.d.ts +5 -0
  73. package/dist/vectordb/index.d.ts.map +1 -0
  74. package/dist/vectordb/index.js +14 -0
  75. package/dist/vectordb/index.js.map +1 -0
  76. package/dist/vectordb/milvus-restful-vectordb.d.ts +75 -0
  77. package/dist/vectordb/milvus-restful-vectordb.d.ts.map +1 -0
  78. package/dist/vectordb/milvus-restful-vectordb.js +703 -0
  79. package/dist/vectordb/milvus-restful-vectordb.js.map +1 -0
  80. package/dist/vectordb/milvus-vectordb.d.ts +60 -0
  81. package/dist/vectordb/milvus-vectordb.d.ts.map +1 -0
  82. package/dist/vectordb/milvus-vectordb.js +638 -0
  83. package/dist/vectordb/milvus-vectordb.js.map +1 -0
  84. package/dist/vectordb/types.d.ts +120 -0
  85. package/dist/vectordb/types.d.ts.map +1 -0
  86. package/dist/vectordb/types.js +9 -0
  87. package/dist/vectordb/types.js.map +1 -0
  88. package/dist/vectordb/zilliz-utils.d.ts +135 -0
  89. package/dist/vectordb/zilliz-utils.d.ts.map +1 -0
  90. package/dist/vectordb/zilliz-utils.js +192 -0
  91. package/dist/vectordb/zilliz-utils.js.map +1 -0
  92. package/package.json +58 -0
@@ -0,0 +1,703 @@
1
+ "use strict";
2
+ /**
3
+ * Milvus RESTful Vector Database Implementation
4
+ *
5
+ * This RESTful implementation of Milvus vector database is specifically designed for
6
+ * environments with strict dependency constraints, e.g. VSCode Extensions, Chrome Extensions, etc.
7
+ *
8
+ * The standard Milvus gRPC implementation requires some dependencies and modules
9
+ * that are not available or restricted in these constrained environments. This RESTful
10
+ * implementation uses only HTTP requests, making it compatible with them.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.MilvusRestfulVectorDatabase = void 0;
14
+ const types_1 = require("./types");
15
+ const zilliz_utils_1 = require("./zilliz-utils");
16
+ /**
17
+ * TODO: Change this usage to checkCollectionLimit()
18
+ * Wrapper function to handle collection creation with limit detection
19
+ * This is the single point where collection limit errors are detected and handled
20
+ */
21
+ async function createCollectionWithLimitCheck(makeRequestFn, collectionSchema) {
22
+ try {
23
+ await makeRequestFn('/collections/create', 'POST', collectionSchema);
24
+ }
25
+ catch (error) {
26
+ // Check if the error message contains the collection limit exceeded pattern
27
+ const errorMessage = error.message || error.toString() || '';
28
+ if (/exceeded the limit number of collections/i.test(errorMessage)) {
29
+ // Throw the exact message string, not an Error object
30
+ throw types_1.COLLECTION_LIMIT_MESSAGE;
31
+ }
32
+ // Re-throw other errors as-is
33
+ throw error;
34
+ }
35
+ }
36
+ /**
37
+ * Milvus Vector Database implementation using REST API
38
+ * This implementation is designed for environments where gRPC is not available,
39
+ * such as VSCode extensions or browser environments.
40
+ */
41
+ class MilvusRestfulVectorDatabase {
42
+ constructor(config) {
43
+ this.baseUrl = null;
44
+ this.config = config;
45
+ // Start initialization asynchronously without waiting
46
+ this.initializationPromise = this.initialize();
47
+ }
48
+ async initialize() {
49
+ const resolvedAddress = await this.resolveAddress();
50
+ await this.initializeClient(resolvedAddress);
51
+ }
52
+ async initializeClient(address) {
53
+ // Ensure address has protocol prefix
54
+ let processedAddress = address;
55
+ if (!processedAddress.startsWith('http://') && !processedAddress.startsWith('https://')) {
56
+ processedAddress = `http://${processedAddress}`;
57
+ }
58
+ this.baseUrl = processedAddress.replace(/\/$/, '') + '/v2/vectordb';
59
+ console.log(`🔌 Connecting to Milvus REST API at: ${processedAddress}`);
60
+ }
61
+ /**
62
+ * Resolve address from config or token
63
+ * Common logic for both gRPC and REST implementations
64
+ */
65
+ async resolveAddress() {
66
+ let finalConfig = { ...this.config };
67
+ // If address is not provided, get it using token
68
+ if (!finalConfig.address && finalConfig.token) {
69
+ finalConfig.address = await zilliz_utils_1.ClusterManager.getAddressFromToken(finalConfig.token);
70
+ }
71
+ if (!finalConfig.address) {
72
+ throw new Error('Address is required and could not be resolved from token');
73
+ }
74
+ return finalConfig.address;
75
+ }
76
+ /**
77
+ * Ensure initialization is complete before method execution
78
+ */
79
+ async ensureInitialized() {
80
+ await this.initializationPromise;
81
+ if (!this.baseUrl) {
82
+ throw new Error('Base URL not initialized');
83
+ }
84
+ }
85
+ /**
86
+ * Ensure collection is loaded before search/query operations
87
+ */
88
+ async ensureLoaded(collectionName) {
89
+ try {
90
+ const restfulConfig = this.config;
91
+ // Check if collection is loaded
92
+ const response = await this.makeRequest('/collections/get_load_state', 'POST', {
93
+ collectionName,
94
+ dbName: restfulConfig.database
95
+ });
96
+ const loadState = response.data?.loadState;
97
+ if (loadState !== 'LoadStateLoaded') {
98
+ console.log(`[MilvusRestfulDB] 🔄 Loading collection '${collectionName}' to memory...`);
99
+ await this.loadCollection(collectionName);
100
+ }
101
+ }
102
+ catch (error) {
103
+ console.error(`[MilvusRestfulDB] ❌ Failed to ensure collection '${collectionName}' is loaded:`, error);
104
+ throw error;
105
+ }
106
+ }
107
+ /**
108
+ * Make HTTP request to Milvus REST API
109
+ */
110
+ async makeRequest(endpoint, method = 'POST', data) {
111
+ const url = `${this.baseUrl}${endpoint}`;
112
+ const headers = {
113
+ 'Content-Type': 'application/json',
114
+ 'Accept': 'application/json'
115
+ };
116
+ // Handle authentication
117
+ if (this.config.token) {
118
+ headers['Authorization'] = `Bearer ${this.config.token}`;
119
+ }
120
+ else if (this.config.username && this.config.password) {
121
+ headers['Authorization'] = `Bearer ${this.config.username}:${this.config.password}`;
122
+ }
123
+ const requestOptions = {
124
+ method,
125
+ headers,
126
+ };
127
+ if (data && method === 'POST') {
128
+ requestOptions.body = JSON.stringify(data);
129
+ }
130
+ try {
131
+ const response = await fetch(url, requestOptions);
132
+ if (!response.ok) {
133
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
134
+ }
135
+ const result = await response.json();
136
+ if (result.code !== 0 && result.code !== 200) {
137
+ throw new Error(`Milvus API error: ${result.message || 'Unknown error'}`);
138
+ }
139
+ return result;
140
+ }
141
+ catch (error) {
142
+ console.error(`[MilvusRestfulDB] Milvus REST API request failed:`, error);
143
+ throw error;
144
+ }
145
+ }
146
+ async createCollection(collectionName, dimension, description) {
147
+ await this.ensureInitialized();
148
+ try {
149
+ const restfulConfig = this.config;
150
+ // Build collection schema based on the original milvus-vectordb.ts implementation
151
+ // Note: REST API doesn't support description parameter in collection creation
152
+ // Unlike gRPC version, the description parameter is ignored in REST API
153
+ const collectionSchema = {
154
+ collectionName,
155
+ dbName: restfulConfig.database,
156
+ schema: {
157
+ enableDynamicField: false,
158
+ fields: [
159
+ {
160
+ fieldName: "id",
161
+ dataType: "VarChar",
162
+ isPrimary: true,
163
+ elementTypeParams: {
164
+ max_length: 512
165
+ }
166
+ },
167
+ {
168
+ fieldName: "vector",
169
+ dataType: "FloatVector",
170
+ elementTypeParams: {
171
+ dim: dimension
172
+ }
173
+ },
174
+ {
175
+ fieldName: "content",
176
+ dataType: "VarChar",
177
+ elementTypeParams: {
178
+ max_length: 65535
179
+ }
180
+ },
181
+ {
182
+ fieldName: "relativePath",
183
+ dataType: "VarChar",
184
+ elementTypeParams: {
185
+ max_length: 1024
186
+ }
187
+ },
188
+ {
189
+ fieldName: "startLine",
190
+ dataType: "Int64"
191
+ },
192
+ {
193
+ fieldName: "endLine",
194
+ dataType: "Int64"
195
+ },
196
+ {
197
+ fieldName: "fileExtension",
198
+ dataType: "VarChar",
199
+ elementTypeParams: {
200
+ max_length: 32
201
+ }
202
+ },
203
+ {
204
+ fieldName: "metadata",
205
+ dataType: "VarChar",
206
+ elementTypeParams: {
207
+ max_length: 65535
208
+ }
209
+ }
210
+ ]
211
+ }
212
+ };
213
+ // Step 1: Create collection with schema
214
+ await createCollectionWithLimitCheck(this.makeRequest.bind(this), collectionSchema);
215
+ // Step 2: Create index for vector field (separate API call)
216
+ await this.createIndex(collectionName);
217
+ // Step 3: Load collection to memory for searching
218
+ await this.loadCollection(collectionName);
219
+ }
220
+ catch (error) {
221
+ console.error(`[MilvusRestfulDB] ❌ Failed to create collection '${collectionName}':`, error);
222
+ throw error;
223
+ }
224
+ }
225
+ /**
226
+ * Create index for vector field using the Index Create API
227
+ */
228
+ async createIndex(collectionName) {
229
+ try {
230
+ const restfulConfig = this.config;
231
+ const indexParams = {
232
+ collectionName,
233
+ dbName: restfulConfig.database,
234
+ indexParams: [
235
+ {
236
+ fieldName: "vector",
237
+ indexName: "vector_index",
238
+ metricType: "COSINE",
239
+ index_type: "AUTOINDEX"
240
+ }
241
+ ]
242
+ };
243
+ await this.makeRequest('/indexes/create', 'POST', indexParams);
244
+ }
245
+ catch (error) {
246
+ console.error(`[MilvusRestfulDB] ❌ Failed to create index for collection '${collectionName}':`, error);
247
+ throw error;
248
+ }
249
+ }
250
+ /**
251
+ * Load collection to memory for searching
252
+ */
253
+ async loadCollection(collectionName) {
254
+ try {
255
+ const restfulConfig = this.config;
256
+ await this.makeRequest('/collections/load', 'POST', {
257
+ collectionName,
258
+ dbName: restfulConfig.database
259
+ });
260
+ }
261
+ catch (error) {
262
+ console.error(`[MilvusRestfulDB] ❌ Failed to load collection '${collectionName}':`, error);
263
+ throw error;
264
+ }
265
+ }
266
+ async dropCollection(collectionName) {
267
+ await this.ensureInitialized();
268
+ try {
269
+ const restfulConfig = this.config;
270
+ await this.makeRequest('/collections/drop', 'POST', {
271
+ collectionName,
272
+ dbName: restfulConfig.database
273
+ });
274
+ }
275
+ catch (error) {
276
+ console.error(`[MilvusRestfulDB] ❌ Failed to drop collection '${collectionName}':`, error);
277
+ throw error;
278
+ }
279
+ }
280
+ async hasCollection(collectionName) {
281
+ await this.ensureInitialized();
282
+ try {
283
+ const restfulConfig = this.config;
284
+ const response = await this.makeRequest('/collections/has', 'POST', {
285
+ collectionName,
286
+ dbName: restfulConfig.database
287
+ });
288
+ const exists = response.data?.has || false;
289
+ return exists;
290
+ }
291
+ catch (error) {
292
+ console.error(`[MilvusRestfulDB] ❌ Failed to check collection '${collectionName}' existence:`, error);
293
+ throw error;
294
+ }
295
+ }
296
+ async listCollections() {
297
+ await this.ensureInitialized();
298
+ try {
299
+ const restfulConfig = this.config;
300
+ const response = await this.makeRequest('/collections/list', 'POST', {
301
+ dbName: restfulConfig.database
302
+ });
303
+ return response.data || [];
304
+ }
305
+ catch (error) {
306
+ console.error(`[MilvusRestfulDB] ❌ Failed to list collections:`, error);
307
+ throw error;
308
+ }
309
+ }
310
+ async insert(collectionName, documents) {
311
+ await this.ensureInitialized();
312
+ await this.ensureLoaded(collectionName);
313
+ try {
314
+ const restfulConfig = this.config;
315
+ // Transform VectorDocument array to Milvus entity format
316
+ const data = documents.map(doc => ({
317
+ id: doc.id,
318
+ vector: doc.vector,
319
+ content: doc.content,
320
+ relativePath: doc.relativePath,
321
+ startLine: doc.startLine,
322
+ endLine: doc.endLine,
323
+ fileExtension: doc.fileExtension,
324
+ metadata: JSON.stringify(doc.metadata) // Convert metadata object to JSON string
325
+ }));
326
+ const insertRequest = {
327
+ collectionName,
328
+ data,
329
+ dbName: restfulConfig.database
330
+ };
331
+ await this.makeRequest('/entities/insert', 'POST', insertRequest);
332
+ }
333
+ catch (error) {
334
+ console.error(`[MilvusRestfulDB] ❌ Failed to insert documents into collection '${collectionName}':`, error);
335
+ throw error;
336
+ }
337
+ }
338
+ async search(collectionName, queryVector, options) {
339
+ await this.ensureInitialized();
340
+ await this.ensureLoaded(collectionName);
341
+ const topK = options?.topK || 10;
342
+ try {
343
+ const restfulConfig = this.config;
344
+ // Build search request according to Milvus REST API specification
345
+ const searchRequest = {
346
+ collectionName,
347
+ dbName: restfulConfig.database,
348
+ data: [queryVector], // Array of query vectors
349
+ annsField: "vector", // Vector field name
350
+ limit: topK,
351
+ outputFields: [
352
+ "content",
353
+ "relativePath",
354
+ "startLine",
355
+ "endLine",
356
+ "fileExtension",
357
+ "metadata"
358
+ ],
359
+ searchParams: {
360
+ metricType: "COSINE", // Match the index metric type
361
+ params: {}
362
+ }
363
+ };
364
+ // Apply boolean expression filter if provided (e.g., fileExtension in ['.ts','.py'])
365
+ if (options?.filterExpr && options.filterExpr.trim().length > 0) {
366
+ searchRequest.filter = options.filterExpr;
367
+ }
368
+ const response = await this.makeRequest('/entities/search', 'POST', searchRequest);
369
+ // Transform response to VectorSearchResult format
370
+ const results = (response.data || []).map((item) => {
371
+ // Parse metadata from JSON string
372
+ let metadata = {};
373
+ try {
374
+ metadata = JSON.parse(item.metadata || '{}');
375
+ }
376
+ catch (error) {
377
+ console.warn(`[MilvusRestfulDB] Failed to parse metadata for item ${item.id}:`, error);
378
+ metadata = {};
379
+ }
380
+ return {
381
+ document: {
382
+ id: item.id?.toString() || '',
383
+ vector: queryVector, // Vector not returned in search results
384
+ content: item.content || '',
385
+ relativePath: item.relativePath || '',
386
+ startLine: item.startLine || 0,
387
+ endLine: item.endLine || 0,
388
+ fileExtension: item.fileExtension || '',
389
+ metadata: metadata
390
+ },
391
+ score: item.distance || 0
392
+ };
393
+ });
394
+ return results;
395
+ }
396
+ catch (error) {
397
+ console.error(`[MilvusRestfulDB] ❌ Failed to search in collection '${collectionName}':`, error);
398
+ throw error;
399
+ }
400
+ }
401
+ async delete(collectionName, ids) {
402
+ await this.ensureInitialized();
403
+ await this.ensureLoaded(collectionName);
404
+ try {
405
+ const restfulConfig = this.config;
406
+ // Build filter expression for deleting by IDs
407
+ // Format: id in ["id1", "id2", "id3"]
408
+ const filter = `id in [${ids.map(id => `"${id}"`).join(', ')}]`;
409
+ const deleteRequest = {
410
+ collectionName,
411
+ filter,
412
+ dbName: restfulConfig.database
413
+ };
414
+ await this.makeRequest('/entities/delete', 'POST', deleteRequest);
415
+ }
416
+ catch (error) {
417
+ console.error(`[MilvusRestfulDB] ❌ Failed to delete documents from collection '${collectionName}':`, error);
418
+ throw error;
419
+ }
420
+ }
421
+ async query(collectionName, filter, outputFields, limit) {
422
+ await this.ensureInitialized();
423
+ await this.ensureLoaded(collectionName);
424
+ try {
425
+ const restfulConfig = this.config;
426
+ const queryRequest = {
427
+ collectionName,
428
+ dbName: restfulConfig.database,
429
+ filter,
430
+ outputFields,
431
+ limit: limit || 16384, // Use provided limit or default
432
+ offset: 0
433
+ };
434
+ const response = await this.makeRequest('/entities/query', 'POST', queryRequest);
435
+ if (response.code !== 0) {
436
+ throw new Error(`Failed to query Milvus: ${response.message || 'Unknown error'}`);
437
+ }
438
+ return response.data || [];
439
+ }
440
+ catch (error) {
441
+ console.error(`[MilvusRestfulDB] ❌ Failed to query collection '${collectionName}':`, error);
442
+ throw error;
443
+ }
444
+ }
445
+ async createHybridCollection(collectionName, dimension, description) {
446
+ try {
447
+ const restfulConfig = this.config;
448
+ const collectionSchema = {
449
+ collectionName,
450
+ dbName: restfulConfig.database,
451
+ schema: {
452
+ enableDynamicField: false,
453
+ functions: [
454
+ {
455
+ name: "content_bm25_emb",
456
+ description: "content bm25 function",
457
+ type: "BM25",
458
+ inputFieldNames: ["content"],
459
+ outputFieldNames: ["sparse_vector"],
460
+ params: {},
461
+ },
462
+ ],
463
+ fields: [
464
+ {
465
+ fieldName: "id",
466
+ dataType: "VarChar",
467
+ isPrimary: true,
468
+ elementTypeParams: {
469
+ max_length: 512
470
+ }
471
+ },
472
+ {
473
+ fieldName: "content",
474
+ dataType: "VarChar",
475
+ elementTypeParams: {
476
+ max_length: 65535,
477
+ enable_analyzer: true
478
+ }
479
+ },
480
+ {
481
+ fieldName: "vector",
482
+ dataType: "FloatVector",
483
+ elementTypeParams: {
484
+ dim: dimension
485
+ }
486
+ },
487
+ {
488
+ fieldName: "sparse_vector",
489
+ dataType: "SparseFloatVector"
490
+ },
491
+ {
492
+ fieldName: "relativePath",
493
+ dataType: "VarChar",
494
+ elementTypeParams: {
495
+ max_length: 1024
496
+ }
497
+ },
498
+ {
499
+ fieldName: "startLine",
500
+ dataType: "Int64"
501
+ },
502
+ {
503
+ fieldName: "endLine",
504
+ dataType: "Int64"
505
+ },
506
+ {
507
+ fieldName: "fileExtension",
508
+ dataType: "VarChar",
509
+ elementTypeParams: {
510
+ max_length: 32
511
+ }
512
+ },
513
+ {
514
+ fieldName: "metadata",
515
+ dataType: "VarChar",
516
+ elementTypeParams: {
517
+ max_length: 65535
518
+ }
519
+ }
520
+ ]
521
+ }
522
+ };
523
+ // Step 1: Create collection with schema and functions
524
+ await createCollectionWithLimitCheck(this.makeRequest.bind(this), collectionSchema);
525
+ // Step 2: Create indexes for both vector fields
526
+ await this.createHybridIndexes(collectionName);
527
+ // Step 3: Load collection to memory for searching
528
+ await this.loadCollection(collectionName);
529
+ }
530
+ catch (error) {
531
+ console.error(`[MilvusRestfulDB] ❌ Failed to create hybrid collection '${collectionName}':`, error);
532
+ throw error;
533
+ }
534
+ }
535
+ async createHybridIndexes(collectionName) {
536
+ try {
537
+ const restfulConfig = this.config;
538
+ // Create index for dense vector
539
+ const denseIndexParams = {
540
+ collectionName,
541
+ dbName: restfulConfig.database,
542
+ indexParams: [
543
+ {
544
+ fieldName: "vector",
545
+ indexName: "vector_index",
546
+ metricType: "COSINE",
547
+ index_type: "AUTOINDEX"
548
+ }
549
+ ]
550
+ };
551
+ await this.makeRequest('/indexes/create', 'POST', denseIndexParams);
552
+ // Create index for sparse vector
553
+ const sparseIndexParams = {
554
+ collectionName,
555
+ dbName: restfulConfig.database,
556
+ indexParams: [
557
+ {
558
+ fieldName: "sparse_vector",
559
+ indexName: "sparse_vector_index",
560
+ metricType: "BM25",
561
+ index_type: "SPARSE_INVERTED_INDEX"
562
+ }
563
+ ]
564
+ };
565
+ await this.makeRequest('/indexes/create', 'POST', sparseIndexParams);
566
+ }
567
+ catch (error) {
568
+ console.error(`[MilvusRestfulDB] ❌ Failed to create hybrid indexes for collection '${collectionName}':`, error);
569
+ throw error;
570
+ }
571
+ }
572
+ async insertHybrid(collectionName, documents) {
573
+ await this.ensureInitialized();
574
+ await this.ensureLoaded(collectionName);
575
+ try {
576
+ const restfulConfig = this.config;
577
+ const data = documents.map(doc => ({
578
+ id: doc.id,
579
+ content: doc.content,
580
+ vector: doc.vector,
581
+ relativePath: doc.relativePath,
582
+ startLine: doc.startLine,
583
+ endLine: doc.endLine,
584
+ fileExtension: doc.fileExtension,
585
+ metadata: JSON.stringify(doc.metadata),
586
+ }));
587
+ const insertRequest = {
588
+ collectionName,
589
+ dbName: restfulConfig.database,
590
+ data: data
591
+ };
592
+ const response = await this.makeRequest('/entities/insert', 'POST', insertRequest);
593
+ if (response.code !== 0) {
594
+ throw new Error(`Insert failed: ${response.message || 'Unknown error'}`);
595
+ }
596
+ }
597
+ catch (error) {
598
+ console.error(`[MilvusRestfulDB] ❌ Failed to insert hybrid documents to collection '${collectionName}':`, error);
599
+ throw error;
600
+ }
601
+ }
602
+ async hybridSearch(collectionName, searchRequests, options) {
603
+ await this.ensureInitialized();
604
+ await this.ensureLoaded(collectionName);
605
+ try {
606
+ const restfulConfig = this.config;
607
+ console.log(`[MilvusRestfulDB] 🔍 Preparing hybrid search for collection: ${collectionName}`);
608
+ // Prepare search requests according to Milvus REST API hybrid search specification
609
+ // For dense vector search - data must be array of vectors: [[0.1, 0.2, 0.3, ...]]
610
+ const search_param_1 = {
611
+ data: Array.isArray(searchRequests[0].data) ? [searchRequests[0].data] : [[searchRequests[0].data]],
612
+ annsField: searchRequests[0].anns_field, // "vector"
613
+ limit: searchRequests[0].limit,
614
+ outputFields: ["*"],
615
+ searchParams: {
616
+ metricType: "COSINE",
617
+ params: searchRequests[0].param || { "nprobe": 10 }
618
+ }
619
+ };
620
+ // For sparse vector search - data must be array of queries: ["query text"]
621
+ const search_param_2 = {
622
+ data: Array.isArray(searchRequests[1].data) ? searchRequests[1].data : [searchRequests[1].data],
623
+ annsField: searchRequests[1].anns_field, // "sparse_vector"
624
+ limit: searchRequests[1].limit,
625
+ outputFields: ["*"],
626
+ searchParams: {
627
+ metricType: "BM25",
628
+ params: searchRequests[1].param || { "drop_ratio_search": 0.2 }
629
+ }
630
+ };
631
+ // Apply filter to both search parameters if provided
632
+ if (options?.filterExpr && options.filterExpr.trim().length > 0) {
633
+ search_param_1.filter = options.filterExpr;
634
+ search_param_2.filter = options.filterExpr;
635
+ }
636
+ const rerank_strategy = {
637
+ strategy: "rrf",
638
+ params: {
639
+ k: 100
640
+ }
641
+ };
642
+ console.log(`[MilvusRestfulDB] 🔍 Dense search params:`, JSON.stringify({
643
+ annsField: search_param_1.annsField,
644
+ limit: search_param_1.limit,
645
+ data_length: Array.isArray(search_param_1.data[0]) ? search_param_1.data[0].length : 'N/A',
646
+ searchParams: search_param_1.searchParams
647
+ }, null, 2));
648
+ console.log(`[MilvusRestfulDB] 🔍 Sparse search params:`, JSON.stringify({
649
+ annsField: search_param_2.annsField,
650
+ limit: search_param_2.limit,
651
+ query_text: typeof search_param_2.data[0] === 'string' ? search_param_2.data[0].substring(0, 50) + '...' : 'N/A',
652
+ searchParams: search_param_2.searchParams
653
+ }, null, 2));
654
+ const hybridSearchRequest = {
655
+ collectionName,
656
+ dbName: restfulConfig.database,
657
+ search: [search_param_1, search_param_2],
658
+ rerank: rerank_strategy,
659
+ limit: options?.limit || searchRequests[0]?.limit || 10,
660
+ outputFields: ['id', 'content', 'relativePath', 'startLine', 'endLine', 'fileExtension', 'metadata'],
661
+ };
662
+ console.log(`[MilvusRestfulDB] 🔍 Executing REST API hybrid search...`);
663
+ const response = await this.makeRequest('/entities/hybrid_search', 'POST', hybridSearchRequest);
664
+ if (response.code !== 0) {
665
+ throw new Error(`Hybrid search failed: ${response.message || 'Unknown error'}`);
666
+ }
667
+ const results = response.data || [];
668
+ console.log(`[MilvusRestfulDB] ✅ Found ${results.length} results from hybrid search`);
669
+ // Transform response to HybridSearchResult format
670
+ return results.map((result) => ({
671
+ document: {
672
+ id: result.id,
673
+ content: result.content,
674
+ vector: [], // Vector not returned in search results
675
+ sparse_vector: [], // Vector not returned in search results
676
+ relativePath: result.relativePath,
677
+ startLine: result.startLine,
678
+ endLine: result.endLine,
679
+ fileExtension: result.fileExtension,
680
+ metadata: JSON.parse(result.metadata || '{}'),
681
+ },
682
+ score: result.score || result.distance || 0,
683
+ }));
684
+ }
685
+ catch (error) {
686
+ console.error(`[MilvusRestfulDB] ❌ Failed to perform hybrid search on collection '${collectionName}':`, error);
687
+ throw error;
688
+ }
689
+ }
690
+ /**
691
+ * Check collection limit
692
+ * Returns true if collection can be created, false if limit exceeded
693
+ * TODO: Implement proper collection limit checking for REST API
694
+ */
695
+ async checkCollectionLimit() {
696
+ // TODO: Implement REST API version of collection limit checking
697
+ // For now, always return true to maintain compatibility
698
+ console.warn('[MilvusRestfulDB] ⚠️ checkCollectionLimit not implemented for REST API - returning true');
699
+ return true;
700
+ }
701
+ }
702
+ exports.MilvusRestfulVectorDatabase = MilvusRestfulVectorDatabase;
703
+ //# sourceMappingURL=milvus-restful-vectordb.js.map