@mcampa/ai-context-core 0.0.1-beta.05e8984

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