@pleaseai/context-please-core 0.1.0

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