rag-lite-ts 1.0.2 → 2.0.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.
- package/README.md +606 -93
- package/dist/cli/indexer.js +192 -4
- package/dist/cli/search.js +50 -11
- package/dist/cli.js +183 -26
- package/dist/core/abstract-embedder.d.ts +125 -0
- package/dist/core/abstract-embedder.js +264 -0
- package/dist/core/actionable-error-messages.d.ts +60 -0
- package/dist/core/actionable-error-messages.js +397 -0
- package/dist/core/batch-processing-optimizer.d.ts +155 -0
- package/dist/core/batch-processing-optimizer.js +541 -0
- package/dist/core/chunker.d.ts +2 -0
- package/dist/core/cli-database-utils.d.ts +53 -0
- package/dist/core/cli-database-utils.js +239 -0
- package/dist/core/config.js +10 -3
- package/dist/core/content-errors.d.ts +111 -0
- package/dist/core/content-errors.js +362 -0
- package/dist/core/content-manager.d.ts +343 -0
- package/dist/core/content-manager.js +1504 -0
- package/dist/core/content-performance-optimizer.d.ts +150 -0
- package/dist/core/content-performance-optimizer.js +516 -0
- package/dist/core/content-resolver.d.ts +104 -0
- package/dist/core/content-resolver.js +285 -0
- package/dist/core/cross-modal-search.d.ts +164 -0
- package/dist/core/cross-modal-search.js +342 -0
- package/dist/core/database-connection-manager.d.ts +109 -0
- package/dist/core/database-connection-manager.js +304 -0
- package/dist/core/db.d.ts +141 -2
- package/dist/core/db.js +631 -89
- package/dist/core/embedder-factory.d.ts +176 -0
- package/dist/core/embedder-factory.js +338 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.js +4 -1
- package/dist/core/ingestion.d.ts +85 -15
- package/dist/core/ingestion.js +510 -45
- package/dist/core/lazy-dependency-loader.d.ts +152 -0
- package/dist/core/lazy-dependency-loader.js +453 -0
- package/dist/core/mode-detection-service.d.ts +150 -0
- package/dist/core/mode-detection-service.js +565 -0
- package/dist/core/mode-model-validator.d.ts +92 -0
- package/dist/core/mode-model-validator.js +203 -0
- package/dist/core/model-registry.d.ts +120 -0
- package/dist/core/model-registry.js +415 -0
- package/dist/core/model-validator.d.ts +217 -0
- package/dist/core/model-validator.js +782 -0
- package/dist/core/polymorphic-search-factory.d.ts +154 -0
- package/dist/core/polymorphic-search-factory.js +344 -0
- package/dist/core/raglite-paths.d.ts +121 -0
- package/dist/core/raglite-paths.js +145 -0
- package/dist/core/reranking-config.d.ts +42 -0
- package/dist/core/reranking-config.js +156 -0
- package/dist/core/reranking-factory.d.ts +92 -0
- package/dist/core/reranking-factory.js +591 -0
- package/dist/core/reranking-strategies.d.ts +325 -0
- package/dist/core/reranking-strategies.js +720 -0
- package/dist/core/resource-cleanup.d.ts +163 -0
- package/dist/core/resource-cleanup.js +371 -0
- package/dist/core/resource-manager.d.ts +212 -0
- package/dist/core/resource-manager.js +564 -0
- package/dist/core/search.d.ts +28 -1
- package/dist/core/search.js +83 -5
- package/dist/core/streaming-operations.d.ts +145 -0
- package/dist/core/streaming-operations.js +409 -0
- package/dist/core/types.d.ts +3 -0
- package/dist/core/universal-embedder.d.ts +177 -0
- package/dist/core/universal-embedder.js +139 -0
- package/dist/core/validation-messages.d.ts +99 -0
- package/dist/core/validation-messages.js +334 -0
- package/dist/core/vector-index.js +7 -8
- package/dist/factories/index.d.ts +1 -1
- package/dist/factories/text-factory.d.ts +128 -34
- package/dist/factories/text-factory.js +346 -97
- package/dist/file-processor.d.ts +88 -2
- package/dist/file-processor.js +720 -17
- package/dist/index.d.ts +9 -0
- package/dist/index.js +11 -0
- package/dist/ingestion.d.ts +16 -0
- package/dist/ingestion.js +21 -0
- package/dist/mcp-server.d.ts +35 -3
- package/dist/mcp-server.js +1107 -31
- package/dist/multimodal/clip-embedder.d.ts +314 -0
- package/dist/multimodal/clip-embedder.js +945 -0
- package/dist/multimodal/index.d.ts +6 -0
- package/dist/multimodal/index.js +6 -0
- package/dist/run-error-recovery-tests.d.ts +7 -0
- package/dist/run-error-recovery-tests.js +101 -0
- package/dist/search.d.ts +26 -0
- package/dist/search.js +54 -1
- package/dist/test-utils.d.ts +8 -26
- package/dist/text/chunker.d.ts +1 -0
- package/dist/text/embedder.js +15 -8
- package/dist/text/index.d.ts +1 -0
- package/dist/text/index.js +1 -0
- package/dist/text/reranker.d.ts +1 -2
- package/dist/text/reranker.js +17 -47
- package/dist/text/sentence-transformer-embedder.d.ts +96 -0
- package/dist/text/sentence-transformer-embedder.js +340 -0
- package/dist/types.d.ts +39 -0
- package/dist/utils/vector-math.d.ts +31 -0
- package/dist/utils/vector-math.js +70 -0
- package/package.json +15 -3
- package/dist/api-errors.d.ts.map +0 -1
- package/dist/api-errors.js.map +0 -1
- package/dist/cli/indexer.d.ts.map +0 -1
- package/dist/cli/indexer.js.map +0 -1
- package/dist/cli/search.d.ts.map +0 -1
- package/dist/cli/search.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/adapters.d.ts.map +0 -1
- package/dist/core/adapters.js.map +0 -1
- package/dist/core/chunker.d.ts.map +0 -1
- package/dist/core/chunker.js.map +0 -1
- package/dist/core/config.d.ts.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/db.d.ts.map +0 -1
- package/dist/core/db.js.map +0 -1
- package/dist/core/error-handler.d.ts.map +0 -1
- package/dist/core/error-handler.js.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/ingestion.d.ts.map +0 -1
- package/dist/core/ingestion.js.map +0 -1
- package/dist/core/interfaces.d.ts.map +0 -1
- package/dist/core/interfaces.js.map +0 -1
- package/dist/core/path-manager.d.ts.map +0 -1
- package/dist/core/path-manager.js.map +0 -1
- package/dist/core/search-example.d.ts +0 -25
- package/dist/core/search-example.d.ts.map +0 -1
- package/dist/core/search-example.js +0 -138
- package/dist/core/search-example.js.map +0 -1
- package/dist/core/search-pipeline-example.d.ts +0 -21
- package/dist/core/search-pipeline-example.d.ts.map +0 -1
- package/dist/core/search-pipeline-example.js +0 -188
- package/dist/core/search-pipeline-example.js.map +0 -1
- package/dist/core/search-pipeline.d.ts.map +0 -1
- package/dist/core/search-pipeline.js.map +0 -1
- package/dist/core/search.d.ts.map +0 -1
- package/dist/core/search.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/core/vector-index.d.ts.map +0 -1
- package/dist/core/vector-index.js.map +0 -1
- package/dist/dom-polyfills.d.ts.map +0 -1
- package/dist/dom-polyfills.js.map +0 -1
- package/dist/examples/clean-api-examples.d.ts +0 -44
- package/dist/examples/clean-api-examples.d.ts.map +0 -1
- package/dist/examples/clean-api-examples.js +0 -206
- package/dist/examples/clean-api-examples.js.map +0 -1
- package/dist/factories/index.d.ts.map +0 -1
- package/dist/factories/index.js.map +0 -1
- package/dist/factories/text-factory.d.ts.map +0 -1
- package/dist/factories/text-factory.js.map +0 -1
- package/dist/file-processor.d.ts.map +0 -1
- package/dist/file-processor.js.map +0 -1
- package/dist/index-manager.d.ts.map +0 -1
- package/dist/index-manager.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/indexer.d.ts.map +0 -1
- package/dist/indexer.js.map +0 -1
- package/dist/ingestion.d.ts.map +0 -1
- package/dist/ingestion.js.map +0 -1
- package/dist/mcp-server.d.ts.map +0 -1
- package/dist/mcp-server.js.map +0 -1
- package/dist/preprocess.d.ts.map +0 -1
- package/dist/preprocess.js.map +0 -1
- package/dist/preprocessors/index.d.ts.map +0 -1
- package/dist/preprocessors/index.js.map +0 -1
- package/dist/preprocessors/mdx.d.ts.map +0 -1
- package/dist/preprocessors/mdx.js.map +0 -1
- package/dist/preprocessors/mermaid.d.ts.map +0 -1
- package/dist/preprocessors/mermaid.js.map +0 -1
- package/dist/preprocessors/registry.d.ts.map +0 -1
- package/dist/preprocessors/registry.js.map +0 -1
- package/dist/search-standalone.d.ts.map +0 -1
- package/dist/search-standalone.js.map +0 -1
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js.map +0 -1
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js.map +0 -1
- package/dist/text/chunker.d.ts.map +0 -1
- package/dist/text/chunker.js.map +0 -1
- package/dist/text/embedder.d.ts.map +0 -1
- package/dist/text/embedder.js.map +0 -1
- package/dist/text/index.d.ts.map +0 -1
- package/dist/text/index.js.map +0 -1
- package/dist/text/preprocessors/index.d.ts.map +0 -1
- package/dist/text/preprocessors/index.js.map +0 -1
- package/dist/text/preprocessors/mdx.d.ts.map +0 -1
- package/dist/text/preprocessors/mdx.js.map +0 -1
- package/dist/text/preprocessors/mermaid.d.ts.map +0 -1
- package/dist/text/preprocessors/mermaid.js.map +0 -1
- package/dist/text/preprocessors/registry.d.ts.map +0 -1
- package/dist/text/preprocessors/registry.js.map +0 -1
- package/dist/text/reranker.d.ts.map +0 -1
- package/dist/text/reranker.js.map +0 -1
- package/dist/text/tokenizer.d.ts.map +0 -1
- package/dist/text/tokenizer.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORE MODULE — Resource Manager
|
|
3
|
+
* Implements proper cleanup methods for all embedder implementations
|
|
4
|
+
* Adds automatic resource management for image processing operations
|
|
5
|
+
* Creates memory monitoring and garbage collection optimization
|
|
6
|
+
* Ensures proper disposal of transformers.js model resources
|
|
7
|
+
*
|
|
8
|
+
* Requirements: 9.4, 9.6 - Resource cleanup and memory management
|
|
9
|
+
*/
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// RESOURCE MANAGER
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Comprehensive resource manager for embedders and models
|
|
15
|
+
* Handles automatic cleanup, memory monitoring, and garbage collection
|
|
16
|
+
*/
|
|
17
|
+
export class ResourceManager {
|
|
18
|
+
static instance;
|
|
19
|
+
resources = new Map();
|
|
20
|
+
memoryThresholdMB = 512; // Default 512MB threshold
|
|
21
|
+
autoCleanupEnabled = true;
|
|
22
|
+
gcEnabled = true;
|
|
23
|
+
cleanupIntervalMs = 30000; // 30 seconds
|
|
24
|
+
cleanupTimer;
|
|
25
|
+
memoryMonitorTimer;
|
|
26
|
+
peakMemoryMB = 0;
|
|
27
|
+
gcCount = 0;
|
|
28
|
+
lastGcAt;
|
|
29
|
+
constructor() {
|
|
30
|
+
this.startAutoCleanup();
|
|
31
|
+
this.setupMemoryMonitoring();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get singleton instance
|
|
35
|
+
*/
|
|
36
|
+
static getInstance() {
|
|
37
|
+
if (!ResourceManager.instance) {
|
|
38
|
+
ResourceManager.instance = new ResourceManager();
|
|
39
|
+
}
|
|
40
|
+
return ResourceManager.instance;
|
|
41
|
+
}
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// RESOURCE REGISTRATION
|
|
44
|
+
// =============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Register an embedder for resource management
|
|
47
|
+
*/
|
|
48
|
+
registerEmbedder(embedder) {
|
|
49
|
+
const resourceId = this.generateResourceId('embedder', embedder.modelName);
|
|
50
|
+
const resourceInfo = {
|
|
51
|
+
id: resourceId,
|
|
52
|
+
type: 'embedder',
|
|
53
|
+
name: embedder.modelName,
|
|
54
|
+
memoryEstimateMB: this.estimateEmbedderMemory(embedder),
|
|
55
|
+
createdAt: new Date(),
|
|
56
|
+
lastUsedAt: new Date(),
|
|
57
|
+
resource: embedder,
|
|
58
|
+
cleanupFn: async () => {
|
|
59
|
+
// Don't call embedder.cleanup() to avoid circular reference
|
|
60
|
+
// The embedder will handle its own cleanup when explicitly called
|
|
61
|
+
// Just clear the reference here
|
|
62
|
+
console.log(`🧹 Resource manager clearing reference to embedder: ${embedder.modelName}`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
this.resources.set(resourceId, resourceInfo);
|
|
66
|
+
console.log(`📝 Registered embedder: ${embedder.modelName} (ID: ${resourceId}, Est. Memory: ${resourceInfo.memoryEstimateMB}MB)`);
|
|
67
|
+
return resourceId;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Register a transformers.js model for resource management
|
|
71
|
+
*/
|
|
72
|
+
registerModel(model, modelName, modelType) {
|
|
73
|
+
const resourceId = this.generateResourceId('model', `${modelType}:${modelName}`);
|
|
74
|
+
const resourceInfo = {
|
|
75
|
+
id: resourceId,
|
|
76
|
+
type: 'model',
|
|
77
|
+
name: `${modelType}:${modelName}`,
|
|
78
|
+
memoryEstimateMB: this.estimateModelMemory(modelType),
|
|
79
|
+
createdAt: new Date(),
|
|
80
|
+
lastUsedAt: new Date(),
|
|
81
|
+
resource: model,
|
|
82
|
+
cleanupFn: async () => {
|
|
83
|
+
if (typeof model.dispose === 'function') {
|
|
84
|
+
await model.dispose();
|
|
85
|
+
}
|
|
86
|
+
else if (typeof model.destroy === 'function') {
|
|
87
|
+
await model.destroy();
|
|
88
|
+
}
|
|
89
|
+
else if (typeof model.cleanup === 'function') {
|
|
90
|
+
await model.cleanup();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
this.resources.set(resourceId, resourceInfo);
|
|
95
|
+
console.log(`📝 Registered model: ${modelName} (ID: ${resourceId}, Est. Memory: ${resourceInfo.memoryEstimateMB}MB)`);
|
|
96
|
+
return resourceId;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Register an image processor for resource management
|
|
100
|
+
*/
|
|
101
|
+
registerImageProcessor(processor, processorName) {
|
|
102
|
+
const resourceId = this.generateResourceId('processor', processorName);
|
|
103
|
+
const resourceInfo = {
|
|
104
|
+
id: resourceId,
|
|
105
|
+
type: 'processor',
|
|
106
|
+
name: processorName,
|
|
107
|
+
memoryEstimateMB: this.estimateProcessorMemory(processorName),
|
|
108
|
+
createdAt: new Date(),
|
|
109
|
+
lastUsedAt: new Date(),
|
|
110
|
+
resource: processor,
|
|
111
|
+
cleanupFn: async () => {
|
|
112
|
+
if (typeof processor.dispose === 'function') {
|
|
113
|
+
await processor.dispose();
|
|
114
|
+
}
|
|
115
|
+
else if (typeof processor.cleanup === 'function') {
|
|
116
|
+
await processor.cleanup();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
this.resources.set(resourceId, resourceInfo);
|
|
121
|
+
console.log(`📝 Registered processor: ${processorName} (ID: ${resourceId}, Est. Memory: ${resourceInfo.memoryEstimateMB}MB)`);
|
|
122
|
+
return resourceId;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Update last used timestamp for a resource
|
|
126
|
+
*/
|
|
127
|
+
updateResourceUsage(resourceId) {
|
|
128
|
+
const resource = this.resources.get(resourceId);
|
|
129
|
+
if (resource) {
|
|
130
|
+
resource.lastUsedAt = new Date();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// =============================================================================
|
|
134
|
+
// RESOURCE CLEANUP
|
|
135
|
+
// =============================================================================
|
|
136
|
+
/**
|
|
137
|
+
* Clean up a specific resource by ID
|
|
138
|
+
*/
|
|
139
|
+
async cleanupResource(resourceId) {
|
|
140
|
+
const resource = this.resources.get(resourceId);
|
|
141
|
+
if (!resource) {
|
|
142
|
+
console.warn(`Resource not found for cleanup: ${resourceId}`);
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
console.log(`🧹 Cleaning up resource: ${resource.name} (${resource.type})`);
|
|
147
|
+
if (resource.cleanupFn) {
|
|
148
|
+
await resource.cleanupFn();
|
|
149
|
+
}
|
|
150
|
+
this.resources.delete(resourceId);
|
|
151
|
+
console.log(`✅ Resource cleaned up: ${resource.name}`);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error(`❌ Failed to cleanup resource ${resource.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Clean up all resources of a specific type
|
|
161
|
+
*/
|
|
162
|
+
async cleanupResourcesByType(type) {
|
|
163
|
+
const startTime = Date.now();
|
|
164
|
+
const resourcesOfType = Array.from(this.resources.values()).filter(r => r.type === type);
|
|
165
|
+
let cleanedUp = 0;
|
|
166
|
+
let errors = 0;
|
|
167
|
+
let memoryFreed = 0;
|
|
168
|
+
console.log(`🧹 Cleaning up ${resourcesOfType.length} resources of type: ${type}`);
|
|
169
|
+
for (const resource of resourcesOfType) {
|
|
170
|
+
const success = await this.cleanupResource(resource.id);
|
|
171
|
+
if (success) {
|
|
172
|
+
cleanedUp++;
|
|
173
|
+
memoryFreed += resource.memoryEstimateMB;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
errors++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const cleanupTime = Date.now() - startTime;
|
|
180
|
+
const stats = {
|
|
181
|
+
totalResourcesTracked: resourcesOfType.length,
|
|
182
|
+
resourcesCleanedUp: cleanedUp,
|
|
183
|
+
cleanupErrors: errors,
|
|
184
|
+
memoryFreedMB: memoryFreed,
|
|
185
|
+
cleanupTimeMs: cleanupTime
|
|
186
|
+
};
|
|
187
|
+
console.log(`✅ Cleanup complete for ${type}: ${cleanedUp}/${resourcesOfType.length} cleaned, ${memoryFreed}MB freed, ${cleanupTime}ms`);
|
|
188
|
+
return stats;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Clean up all registered resources
|
|
192
|
+
*/
|
|
193
|
+
async cleanupAllResources() {
|
|
194
|
+
const startTime = Date.now();
|
|
195
|
+
const allResources = Array.from(this.resources.values());
|
|
196
|
+
let cleanedUp = 0;
|
|
197
|
+
let errors = 0;
|
|
198
|
+
let memoryFreed = 0;
|
|
199
|
+
console.log(`🧹 Cleaning up all ${allResources.length} registered resources`);
|
|
200
|
+
for (const resource of allResources) {
|
|
201
|
+
const success = await this.cleanupResource(resource.id);
|
|
202
|
+
if (success) {
|
|
203
|
+
cleanedUp++;
|
|
204
|
+
memoryFreed += resource.memoryEstimateMB;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
errors++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const cleanupTime = Date.now() - startTime;
|
|
211
|
+
const stats = {
|
|
212
|
+
totalResourcesTracked: allResources.length,
|
|
213
|
+
resourcesCleanedUp: cleanedUp,
|
|
214
|
+
cleanupErrors: errors,
|
|
215
|
+
memoryFreedMB: memoryFreed,
|
|
216
|
+
cleanupTimeMs: cleanupTime
|
|
217
|
+
};
|
|
218
|
+
console.log(`✅ Full cleanup complete: ${cleanedUp}/${allResources.length} cleaned, ${memoryFreed}MB freed, ${cleanupTime}ms`);
|
|
219
|
+
return stats;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Clean up unused resources (not used recently)
|
|
223
|
+
*/
|
|
224
|
+
async cleanupUnusedResources(maxAgeMinutes = 30) {
|
|
225
|
+
const startTime = Date.now();
|
|
226
|
+
const cutoffTime = new Date(Date.now() - maxAgeMinutes * 60 * 1000);
|
|
227
|
+
const unusedResources = Array.from(this.resources.values()).filter(resource => resource.lastUsedAt < cutoffTime);
|
|
228
|
+
let cleanedUp = 0;
|
|
229
|
+
let errors = 0;
|
|
230
|
+
let memoryFreed = 0;
|
|
231
|
+
console.log(`🧹 Cleaning up ${unusedResources.length} unused resources (older than ${maxAgeMinutes} minutes)`);
|
|
232
|
+
for (const resource of unusedResources) {
|
|
233
|
+
const success = await this.cleanupResource(resource.id);
|
|
234
|
+
if (success) {
|
|
235
|
+
cleanedUp++;
|
|
236
|
+
memoryFreed += resource.memoryEstimateMB;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
errors++;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const cleanupTime = Date.now() - startTime;
|
|
243
|
+
const stats = {
|
|
244
|
+
totalResourcesTracked: unusedResources.length,
|
|
245
|
+
resourcesCleanedUp: cleanedUp,
|
|
246
|
+
cleanupErrors: errors,
|
|
247
|
+
memoryFreedMB: memoryFreed,
|
|
248
|
+
cleanupTimeMs: cleanupTime
|
|
249
|
+
};
|
|
250
|
+
console.log(`✅ Unused resource cleanup complete: ${cleanedUp}/${unusedResources.length} cleaned, ${memoryFreed}MB freed`);
|
|
251
|
+
return stats;
|
|
252
|
+
}
|
|
253
|
+
// =============================================================================
|
|
254
|
+
// MEMORY MANAGEMENT
|
|
255
|
+
// =============================================================================
|
|
256
|
+
/**
|
|
257
|
+
* Get current memory statistics
|
|
258
|
+
*/
|
|
259
|
+
getMemoryStats() {
|
|
260
|
+
const memUsage = process.memoryUsage();
|
|
261
|
+
const currentHeapMB = Math.round(memUsage.heapUsed / 1024 / 1024);
|
|
262
|
+
// Update peak memory
|
|
263
|
+
if (currentHeapMB > this.peakMemoryMB) {
|
|
264
|
+
this.peakMemoryMB = currentHeapMB;
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
heapUsedMB: currentHeapMB,
|
|
268
|
+
heapTotalMB: Math.round(memUsage.heapTotal / 1024 / 1024),
|
|
269
|
+
externalMB: Math.round(memUsage.external / 1024 / 1024),
|
|
270
|
+
rssMemoryMB: Math.round(memUsage.rss / 1024 / 1024),
|
|
271
|
+
peakHeapUsedMB: this.peakMemoryMB,
|
|
272
|
+
gcCount: this.gcCount,
|
|
273
|
+
lastGcAt: this.lastGcAt
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Check if memory usage exceeds threshold
|
|
278
|
+
*/
|
|
279
|
+
isMemoryThresholdExceeded() {
|
|
280
|
+
const stats = this.getMemoryStats();
|
|
281
|
+
return stats.heapUsedMB > this.memoryThresholdMB;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Force garbage collection
|
|
285
|
+
*/
|
|
286
|
+
forceGarbageCollection() {
|
|
287
|
+
if (this.gcEnabled && global.gc) {
|
|
288
|
+
try {
|
|
289
|
+
global.gc();
|
|
290
|
+
this.gcCount++;
|
|
291
|
+
this.lastGcAt = new Date();
|
|
292
|
+
console.log(`🗑️ Forced garbage collection (count: ${this.gcCount})`);
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
console.warn(`Failed to force garbage collection: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Perform memory optimization
|
|
304
|
+
*/
|
|
305
|
+
async optimizeMemory() {
|
|
306
|
+
const initialStats = this.getMemoryStats();
|
|
307
|
+
console.log(`🔧 Starting memory optimization (current: ${initialStats.heapUsedMB}MB, threshold: ${this.memoryThresholdMB}MB)`);
|
|
308
|
+
let resourcesCleanedUp = 0;
|
|
309
|
+
// Clean up unused resources if memory threshold exceeded
|
|
310
|
+
if (this.isMemoryThresholdExceeded()) {
|
|
311
|
+
console.log('💾 Memory threshold exceeded, cleaning up unused resources');
|
|
312
|
+
const cleanupStats = await this.cleanupUnusedResources(15); // Clean resources unused for 15+ minutes
|
|
313
|
+
resourcesCleanedUp = cleanupStats.resourcesCleanedUp;
|
|
314
|
+
}
|
|
315
|
+
// Force garbage collection
|
|
316
|
+
const gcPerformed = this.forceGarbageCollection();
|
|
317
|
+
const finalStats = this.getMemoryStats();
|
|
318
|
+
const memoryFreed = Math.max(0, initialStats.heapUsedMB - finalStats.heapUsedMB);
|
|
319
|
+
console.log(`✅ Memory optimization complete: ${initialStats.heapUsedMB}MB → ${finalStats.heapUsedMB}MB (freed: ${memoryFreed}MB)`);
|
|
320
|
+
return {
|
|
321
|
+
initialMemoryMB: initialStats.heapUsedMB,
|
|
322
|
+
finalMemoryMB: finalStats.heapUsedMB,
|
|
323
|
+
memoryFreedMB: memoryFreed,
|
|
324
|
+
resourcesCleanedUp,
|
|
325
|
+
gcPerformed
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
// =============================================================================
|
|
329
|
+
// CONFIGURATION
|
|
330
|
+
// =============================================================================
|
|
331
|
+
/**
|
|
332
|
+
* Configure memory threshold
|
|
333
|
+
*/
|
|
334
|
+
setMemoryThreshold(thresholdMB) {
|
|
335
|
+
if (thresholdMB < 64) {
|
|
336
|
+
throw new Error('Memory threshold must be at least 64MB');
|
|
337
|
+
}
|
|
338
|
+
this.memoryThresholdMB = thresholdMB;
|
|
339
|
+
console.log(`⚙️ Memory threshold set to ${thresholdMB}MB`);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Enable or disable automatic cleanup
|
|
343
|
+
*/
|
|
344
|
+
setAutoCleanup(enabled) {
|
|
345
|
+
this.autoCleanupEnabled = enabled;
|
|
346
|
+
if (enabled) {
|
|
347
|
+
this.startAutoCleanup();
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
this.stopAutoCleanup();
|
|
351
|
+
}
|
|
352
|
+
console.log(`⚙️ Auto cleanup ${enabled ? 'enabled' : 'disabled'}`);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Enable or disable garbage collection
|
|
356
|
+
*/
|
|
357
|
+
setGarbageCollection(enabled) {
|
|
358
|
+
this.gcEnabled = enabled;
|
|
359
|
+
console.log(`⚙️ Garbage collection ${enabled ? 'enabled' : 'disabled'}`);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Set cleanup interval
|
|
363
|
+
*/
|
|
364
|
+
setCleanupInterval(intervalMs) {
|
|
365
|
+
if (intervalMs < 5000) {
|
|
366
|
+
throw new Error('Cleanup interval must be at least 5 seconds');
|
|
367
|
+
}
|
|
368
|
+
this.cleanupIntervalMs = intervalMs;
|
|
369
|
+
// Restart auto cleanup with new interval
|
|
370
|
+
if (this.autoCleanupEnabled) {
|
|
371
|
+
this.stopAutoCleanup();
|
|
372
|
+
this.startAutoCleanup();
|
|
373
|
+
}
|
|
374
|
+
console.log(`⚙️ Cleanup interval set to ${intervalMs}ms`);
|
|
375
|
+
}
|
|
376
|
+
// =============================================================================
|
|
377
|
+
// RESOURCE STATISTICS
|
|
378
|
+
// =============================================================================
|
|
379
|
+
/**
|
|
380
|
+
* Get comprehensive resource statistics
|
|
381
|
+
*/
|
|
382
|
+
getResourceStats() {
|
|
383
|
+
const resources = Array.from(this.resources.values());
|
|
384
|
+
const now = new Date();
|
|
385
|
+
const resourcesByType = resources.reduce((acc, resource) => {
|
|
386
|
+
acc[resource.type] = (acc[resource.type] || 0) + 1;
|
|
387
|
+
return acc;
|
|
388
|
+
}, {});
|
|
389
|
+
const totalEstimatedMemory = resources.reduce((sum, resource) => sum + resource.memoryEstimateMB, 0);
|
|
390
|
+
let oldestResource = null;
|
|
391
|
+
let newestResource = null;
|
|
392
|
+
if (resources.length > 0) {
|
|
393
|
+
const sortedByAge = resources.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
394
|
+
const oldest = sortedByAge[0];
|
|
395
|
+
const newest = sortedByAge[sortedByAge.length - 1];
|
|
396
|
+
oldestResource = {
|
|
397
|
+
name: oldest.name,
|
|
398
|
+
ageMinutes: Math.round((now.getTime() - oldest.createdAt.getTime()) / 60000)
|
|
399
|
+
};
|
|
400
|
+
newestResource = {
|
|
401
|
+
name: newest.name,
|
|
402
|
+
ageMinutes: Math.round((now.getTime() - newest.createdAt.getTime()) / 60000)
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
totalResources: resources.length,
|
|
407
|
+
resourcesByType,
|
|
408
|
+
totalEstimatedMemoryMB: totalEstimatedMemory,
|
|
409
|
+
oldestResource,
|
|
410
|
+
newestResource,
|
|
411
|
+
memoryStats: this.getMemoryStats()
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
// =============================================================================
|
|
415
|
+
// PRIVATE METHODS
|
|
416
|
+
// =============================================================================
|
|
417
|
+
/**
|
|
418
|
+
* Generate unique resource ID
|
|
419
|
+
*/
|
|
420
|
+
generateResourceId(type, name) {
|
|
421
|
+
const timestamp = Date.now();
|
|
422
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
423
|
+
return `${type}_${name.replace(/[^a-zA-Z0-9]/g, '_')}_${timestamp}_${random}`;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Estimate memory usage for embedder
|
|
427
|
+
*/
|
|
428
|
+
estimateEmbedderMemory(embedder) {
|
|
429
|
+
// Rough estimates based on model type and dimensions
|
|
430
|
+
const dimensions = embedder.dimensions;
|
|
431
|
+
const modelType = embedder.modelType;
|
|
432
|
+
if (modelType === 'clip') {
|
|
433
|
+
// CLIP models are typically larger
|
|
434
|
+
return Math.max(200, dimensions * 0.5); // Minimum 200MB for CLIP
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
// Sentence transformers are typically smaller
|
|
438
|
+
return Math.max(100, dimensions * 0.3); // Minimum 100MB for sentence transformers
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Estimate memory usage for model
|
|
443
|
+
*/
|
|
444
|
+
estimateModelMemory(modelType) {
|
|
445
|
+
const estimates = {
|
|
446
|
+
'clip': 300,
|
|
447
|
+
'sentence-transformer': 150,
|
|
448
|
+
'image-to-text': 250,
|
|
449
|
+
'cross-encoder': 100,
|
|
450
|
+
'default': 100
|
|
451
|
+
};
|
|
452
|
+
return estimates[modelType] || estimates.default;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Estimate memory usage for processor
|
|
456
|
+
*/
|
|
457
|
+
estimateProcessorMemory(processorName) {
|
|
458
|
+
if (processorName.includes('image')) {
|
|
459
|
+
return 50; // Image processors are relatively lightweight
|
|
460
|
+
}
|
|
461
|
+
return 25; // Default for other processors
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Start automatic cleanup timer
|
|
465
|
+
*/
|
|
466
|
+
startAutoCleanup() {
|
|
467
|
+
if (this.cleanupTimer) {
|
|
468
|
+
clearInterval(this.cleanupTimer);
|
|
469
|
+
}
|
|
470
|
+
this.cleanupTimer = setInterval(async () => {
|
|
471
|
+
if (this.autoCleanupEnabled) {
|
|
472
|
+
try {
|
|
473
|
+
// Check memory and clean up if needed
|
|
474
|
+
if (this.isMemoryThresholdExceeded()) {
|
|
475
|
+
await this.optimizeMemory();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
console.warn(`Auto cleanup error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}, this.cleanupIntervalMs);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Stop automatic cleanup timer
|
|
486
|
+
*/
|
|
487
|
+
stopAutoCleanup() {
|
|
488
|
+
if (this.cleanupTimer) {
|
|
489
|
+
clearInterval(this.cleanupTimer);
|
|
490
|
+
this.cleanupTimer = undefined;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Setup memory monitoring
|
|
495
|
+
*/
|
|
496
|
+
setupMemoryMonitoring() {
|
|
497
|
+
// Monitor memory usage periodically
|
|
498
|
+
this.memoryMonitorTimer = setInterval(() => {
|
|
499
|
+
const stats = this.getMemoryStats();
|
|
500
|
+
// Log warning if memory usage is high
|
|
501
|
+
if (stats.heapUsedMB > this.memoryThresholdMB * 0.8) {
|
|
502
|
+
console.warn(`⚠️ High memory usage: ${stats.heapUsedMB}MB (threshold: ${this.memoryThresholdMB}MB)`);
|
|
503
|
+
}
|
|
504
|
+
}, 60000); // Check every minute
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Stop memory monitoring
|
|
508
|
+
*/
|
|
509
|
+
stopMemoryMonitoring() {
|
|
510
|
+
if (this.memoryMonitorTimer) {
|
|
511
|
+
clearInterval(this.memoryMonitorTimer);
|
|
512
|
+
this.memoryMonitorTimer = undefined;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Shutdown resource manager
|
|
517
|
+
*/
|
|
518
|
+
async shutdown() {
|
|
519
|
+
console.log('🔄 Shutting down resource manager...');
|
|
520
|
+
this.stopAutoCleanup();
|
|
521
|
+
this.stopMemoryMonitoring();
|
|
522
|
+
const stats = await this.cleanupAllResources();
|
|
523
|
+
console.log(`✅ Resource manager shutdown complete: ${stats.resourcesCleanedUp} resources cleaned up`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// =============================================================================
|
|
527
|
+
// CONVENIENCE FUNCTIONS
|
|
528
|
+
// =============================================================================
|
|
529
|
+
/**
|
|
530
|
+
* Get the global resource manager instance
|
|
531
|
+
*/
|
|
532
|
+
export function getResourceManager() {
|
|
533
|
+
return ResourceManager.getInstance();
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Register an embedder for automatic resource management
|
|
537
|
+
*/
|
|
538
|
+
export function registerEmbedder(embedder) {
|
|
539
|
+
return getResourceManager().registerEmbedder(embedder);
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Clean up all resources and optimize memory
|
|
543
|
+
*/
|
|
544
|
+
export async function cleanupAndOptimizeMemory() {
|
|
545
|
+
const manager = getResourceManager();
|
|
546
|
+
await manager.optimizeMemory();
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Force garbage collection if available
|
|
550
|
+
*/
|
|
551
|
+
export function forceGarbageCollection() {
|
|
552
|
+
return getResourceManager().forceGarbageCollection();
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Get current memory statistics
|
|
556
|
+
*/
|
|
557
|
+
export function getMemoryStats() {
|
|
558
|
+
return getResourceManager().getMemoryStats();
|
|
559
|
+
}
|
|
560
|
+
// =============================================================================
|
|
561
|
+
// DEFAULT EXPORT
|
|
562
|
+
// =============================================================================
|
|
563
|
+
export default ResourceManager;
|
|
564
|
+
//# sourceMappingURL=resource-manager.js.map
|
package/dist/core/search.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare class SearchEngine {
|
|
|
16
16
|
private indexManager;
|
|
17
17
|
private db;
|
|
18
18
|
private rerankFn?;
|
|
19
|
+
private contentResolver?;
|
|
19
20
|
/**
|
|
20
21
|
* Creates a new SearchEngine with explicit dependency injection
|
|
21
22
|
*
|
|
@@ -70,7 +71,7 @@ export declare class SearchEngine {
|
|
|
70
71
|
* const search = new SearchEngine(customEmbedFn, indexManager, db);
|
|
71
72
|
* ```
|
|
72
73
|
*/
|
|
73
|
-
constructor(embedFn: EmbedFunction, indexManager: IndexManager, db: DatabaseConnection, rerankFn?: RerankFunction | undefined);
|
|
74
|
+
constructor(embedFn: EmbedFunction, indexManager: IndexManager, db: DatabaseConnection, rerankFn?: RerankFunction | undefined, contentResolver?: import('./content-resolver.js').ContentResolver);
|
|
74
75
|
/**
|
|
75
76
|
* Perform semantic search on the indexed documents
|
|
76
77
|
* Implements the core search pipeline: query embedding → vector search → metadata retrieval → optional reranking
|
|
@@ -96,6 +97,32 @@ export declare class SearchEngine {
|
|
|
96
97
|
indexSize: number;
|
|
97
98
|
rerankingEnabled: boolean;
|
|
98
99
|
}>;
|
|
100
|
+
/**
|
|
101
|
+
* Retrieve content by ID in the specified format
|
|
102
|
+
* @param contentId - Content ID to retrieve
|
|
103
|
+
* @param format - Format to return ('file' for CLI clients, 'base64' for MCP clients)
|
|
104
|
+
* @returns Promise that resolves to content in requested format
|
|
105
|
+
*/
|
|
106
|
+
getContent(contentId: string, format?: 'file' | 'base64'): Promise<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Retrieve multiple content items efficiently in batch
|
|
109
|
+
* @param contentIds - Array of content IDs to retrieve
|
|
110
|
+
* @param format - Format to return ('file' for CLI clients, 'base64' for MCP clients)
|
|
111
|
+
* @returns Promise that resolves to array of content in requested format
|
|
112
|
+
*/
|
|
113
|
+
getContentBatch(contentIds: string[], format?: 'file' | 'base64'): Promise<string[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Retrieve content metadata for result enhancement
|
|
116
|
+
* @param contentId - Content ID to get metadata for
|
|
117
|
+
* @returns Promise that resolves to content metadata
|
|
118
|
+
*/
|
|
119
|
+
getContentMetadata(contentId: string): Promise<import('./content-resolver.js').ContentMetadata>;
|
|
120
|
+
/**
|
|
121
|
+
* Verify that content exists and is accessible
|
|
122
|
+
* @param contentId - Content ID to verify
|
|
123
|
+
* @returns Promise that resolves to true if content exists, false otherwise
|
|
124
|
+
*/
|
|
125
|
+
verifyContentExists(contentId: string): Promise<boolean>;
|
|
99
126
|
/**
|
|
100
127
|
* Clean up resources - explicit cleanup method
|
|
101
128
|
*/
|