@soulcraft/brainy 2.15.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +249 -152
- package/dist/api/ConfigAPI.d.ts +67 -0
- package/dist/api/ConfigAPI.js +166 -0
- package/dist/api/DataAPI.d.ts +123 -0
- package/dist/api/DataAPI.js +391 -0
- package/dist/api/SecurityAPI.d.ts +50 -0
- package/dist/api/SecurityAPI.js +139 -0
- package/dist/api/UniversalImportAPI.d.ts +134 -0
- package/dist/api/UniversalImportAPI.js +615 -0
- package/dist/augmentationManager.js +12 -7
- package/dist/augmentationPipeline.d.ts +0 -61
- package/dist/augmentationPipeline.js +0 -87
- package/dist/augmentationRegistry.d.ts +1 -1
- package/dist/augmentationRegistry.js +1 -1
- package/dist/augmentations/apiServerAugmentation.d.ts +27 -1
- package/dist/augmentations/apiServerAugmentation.js +288 -7
- package/dist/augmentations/auditLogAugmentation.d.ts +109 -0
- package/dist/augmentations/auditLogAugmentation.js +358 -0
- package/dist/augmentations/batchProcessingAugmentation.d.ts +3 -2
- package/dist/augmentations/batchProcessingAugmentation.js +123 -22
- package/dist/augmentations/brainyAugmentation.d.ts +87 -8
- package/dist/augmentations/brainyAugmentation.js +159 -2
- package/dist/augmentations/cacheAugmentation.d.ts +6 -5
- package/dist/augmentations/cacheAugmentation.js +113 -17
- package/dist/augmentations/conduitAugmentations.d.ts +2 -2
- package/dist/augmentations/conduitAugmentations.js +2 -2
- package/dist/augmentations/configResolver.d.ts +122 -0
- package/dist/augmentations/configResolver.js +440 -0
- package/dist/augmentations/connectionPoolAugmentation.d.ts +3 -1
- package/dist/augmentations/connectionPoolAugmentation.js +37 -12
- package/dist/augmentations/defaultAugmentations.d.ts +9 -11
- package/dist/augmentations/defaultAugmentations.js +4 -11
- package/dist/augmentations/discovery/catalogDiscovery.d.ts +142 -0
- package/dist/augmentations/discovery/catalogDiscovery.js +249 -0
- package/dist/augmentations/discovery/localDiscovery.d.ts +84 -0
- package/dist/augmentations/discovery/localDiscovery.js +246 -0
- package/dist/augmentations/discovery/runtimeLoader.d.ts +97 -0
- package/dist/augmentations/discovery/runtimeLoader.js +337 -0
- package/dist/augmentations/discovery.d.ts +152 -0
- package/dist/augmentations/discovery.js +441 -0
- package/dist/augmentations/display/intelligentComputation.d.ts +1 -1
- package/dist/augmentations/display/intelligentComputation.js +4 -4
- package/dist/augmentations/entityRegistryAugmentation.d.ts +3 -1
- package/dist/augmentations/entityRegistryAugmentation.js +5 -1
- package/dist/augmentations/indexAugmentation.d.ts +3 -3
- package/dist/augmentations/indexAugmentation.js +2 -2
- package/dist/augmentations/intelligentVerbScoringAugmentation.d.ts +22 -6
- package/dist/augmentations/intelligentVerbScoringAugmentation.js +106 -23
- package/dist/augmentations/manifest.d.ts +176 -0
- package/dist/augmentations/manifest.js +8 -0
- package/dist/augmentations/marketplace/AugmentationMarketplace.d.ts +168 -0
- package/dist/augmentations/marketplace/AugmentationMarketplace.js +329 -0
- package/dist/augmentations/marketplace/cli.d.ts +47 -0
- package/dist/augmentations/marketplace/cli.js +265 -0
- package/dist/augmentations/metricsAugmentation.d.ts +3 -3
- package/dist/augmentations/metricsAugmentation.js +2 -2
- package/dist/augmentations/monitoringAugmentation.d.ts +3 -3
- package/dist/augmentations/monitoringAugmentation.js +2 -2
- package/dist/augmentations/neuralImport.d.ts +1 -1
- package/dist/augmentations/rateLimitAugmentation.d.ts +82 -0
- package/dist/augmentations/rateLimitAugmentation.js +321 -0
- package/dist/augmentations/requestDeduplicatorAugmentation.d.ts +2 -2
- package/dist/augmentations/requestDeduplicatorAugmentation.js +1 -1
- package/dist/augmentations/storageAugmentation.d.ts +1 -1
- package/dist/augmentations/storageAugmentation.js +2 -2
- package/dist/augmentations/storageAugmentations.d.ts +37 -8
- package/dist/augmentations/storageAugmentations.js +204 -15
- package/dist/augmentations/synapseAugmentation.d.ts +1 -1
- package/dist/augmentations/synapseAugmentation.js +35 -16
- package/dist/augmentations/typeMatching/intelligentTypeMatcher.d.ts +39 -59
- package/dist/augmentations/typeMatching/intelligentTypeMatcher.js +103 -389
- package/dist/augmentations/universalDisplayAugmentation.d.ts +2 -2
- package/dist/augmentations/universalDisplayAugmentation.js +2 -2
- package/dist/brainy-unified.d.ts +106 -0
- package/dist/brainy-unified.js +327 -0
- package/dist/brainy.d.ts +273 -0
- package/dist/brainy.js +1181 -0
- package/dist/brainyData.d.ts +29 -72
- package/dist/brainyData.js +350 -304
- package/dist/brainyDataV3.d.ts +186 -0
- package/dist/brainyDataV3.js +337 -0
- package/dist/browserFramework.d.ts +6 -6
- package/dist/browserFramework.js +11 -8
- package/dist/browserFramework.minimal.d.ts +5 -5
- package/dist/browserFramework.minimal.js +11 -8
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +3 -3
- package/dist/config/modelAutoConfig.d.ts +6 -7
- package/dist/config/modelAutoConfig.js +17 -76
- package/dist/cortex/backupRestore.d.ts +2 -2
- package/dist/cortex/backupRestore.js +85 -27
- package/dist/cortex/healthCheck.d.ts +2 -2
- package/dist/cortex/neuralImport.d.ts +2 -2
- package/dist/cortex/neuralImport.js +18 -13
- package/dist/cortex/performanceMonitor.d.ts +2 -2
- package/dist/critical/model-guardian.d.ts +4 -0
- package/dist/critical/model-guardian.js +31 -11
- package/dist/demo.d.ts +4 -4
- package/dist/demo.js +7 -7
- package/dist/distributed/cacheSync.d.ts +112 -0
- package/dist/distributed/cacheSync.js +265 -0
- package/dist/distributed/coordinator.d.ts +193 -0
- package/dist/distributed/coordinator.js +548 -0
- package/dist/distributed/httpTransport.d.ts +120 -0
- package/dist/distributed/httpTransport.js +446 -0
- package/dist/distributed/index.d.ts +8 -0
- package/dist/distributed/index.js +5 -0
- package/dist/distributed/networkTransport.d.ts +132 -0
- package/dist/distributed/networkTransport.js +633 -0
- package/dist/distributed/queryPlanner.d.ts +104 -0
- package/dist/distributed/queryPlanner.js +327 -0
- package/dist/distributed/readWriteSeparation.d.ts +134 -0
- package/dist/distributed/readWriteSeparation.js +350 -0
- package/dist/distributed/shardManager.d.ts +114 -0
- package/dist/distributed/shardManager.js +357 -0
- package/dist/distributed/shardMigration.d.ts +110 -0
- package/dist/distributed/shardMigration.js +289 -0
- package/dist/distributed/storageDiscovery.d.ts +160 -0
- package/dist/distributed/storageDiscovery.js +551 -0
- package/dist/embeddings/EmbeddingManager.d.ts +0 -4
- package/dist/embeddings/EmbeddingManager.js +21 -26
- package/dist/errors/brainyError.d.ts +5 -1
- package/dist/errors/brainyError.js +12 -0
- package/dist/examples/basicUsage.js +3 -3
- package/dist/graph/graphAdjacencyIndex.d.ts +96 -0
- package/dist/graph/graphAdjacencyIndex.js +288 -0
- package/dist/graph/pathfinding.js +4 -2
- package/dist/hnsw/scaledHNSWSystem.js +11 -2
- package/dist/importManager.js +6 -3
- package/dist/index.d.ts +12 -21
- package/dist/index.js +14 -22
- package/dist/mcp/brainyMCPAdapter.d.ts +4 -4
- package/dist/mcp/brainyMCPAdapter.js +5 -5
- package/dist/mcp/brainyMCPService.d.ts +3 -3
- package/dist/mcp/brainyMCPService.js +3 -11
- package/dist/mcp/mcpAugmentationToolset.js +20 -30
- package/dist/neural/embeddedPatterns.d.ts +1 -1
- package/dist/neural/embeddedPatterns.js +2 -2
- package/dist/neural/entityExtractor.d.ts +65 -0
- package/dist/neural/entityExtractor.js +316 -0
- package/dist/neural/improvedNeuralAPI.js +90 -79
- package/dist/neural/naturalLanguageProcessor.d.ts +155 -10
- package/dist/neural/naturalLanguageProcessor.js +941 -66
- package/dist/neural/naturalLanguageProcessorStatic.d.ts +2 -2
- package/dist/neural/naturalLanguageProcessorStatic.js +3 -3
- package/dist/neural/neuralAPI.js +8 -2
- package/dist/neural/patternLibrary.d.ts +57 -3
- package/dist/neural/patternLibrary.js +348 -13
- package/dist/neural/staticPatternMatcher.d.ts +2 -2
- package/dist/neural/staticPatternMatcher.js +2 -2
- package/dist/shared/default-augmentations.d.ts +3 -3
- package/dist/shared/default-augmentations.js +5 -5
- package/dist/storage/adapters/fileSystemStorage.d.ts +4 -0
- package/dist/storage/adapters/fileSystemStorage.js +54 -1
- package/dist/storage/adapters/memoryStorage.js +13 -8
- package/dist/storage/backwardCompatibility.d.ts +10 -78
- package/dist/storage/backwardCompatibility.js +17 -132
- package/dist/storage/baseStorage.d.ts +6 -0
- package/dist/storage/baseStorage.js +17 -0
- package/dist/storage/cacheManager.js +2 -2
- package/dist/storage/readOnlyOptimizations.js +8 -3
- package/dist/streaming/pipeline.d.ts +154 -0
- package/dist/streaming/pipeline.js +551 -0
- package/dist/triple/TripleIntelligence.d.ts +25 -110
- package/dist/triple/TripleIntelligence.js +4 -574
- package/dist/triple/TripleIntelligenceSystem.d.ts +159 -0
- package/dist/triple/TripleIntelligenceSystem.js +519 -0
- package/dist/types/apiTypes.d.ts +278 -0
- package/dist/types/apiTypes.js +33 -0
- package/dist/types/brainy.types.d.ts +308 -0
- package/dist/types/brainy.types.js +8 -0
- package/dist/types/brainyDataInterface.d.ts +3 -3
- package/dist/types/brainyDataInterface.js +2 -2
- package/dist/types/graphTypes.js +2 -2
- package/dist/utils/cacheAutoConfig.d.ts +3 -3
- package/dist/utils/embedding.js +8 -14
- package/dist/utils/enhancedLogger.d.ts +104 -0
- package/dist/utils/enhancedLogger.js +232 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/intelligentTypeMapper.d.ts +60 -0
- package/dist/utils/intelligentTypeMapper.js +349 -0
- package/dist/utils/metadataIndex.d.ts +118 -1
- package/dist/utils/metadataIndex.js +539 -16
- package/dist/utils/paramValidation.d.ts +39 -0
- package/dist/utils/paramValidation.js +192 -0
- package/dist/utils/rateLimiter.d.ts +160 -0
- package/dist/utils/rateLimiter.js +271 -0
- package/dist/utils/statistics.d.ts +4 -4
- package/dist/utils/statistics.js +3 -3
- package/dist/utils/structuredLogger.d.ts +146 -0
- package/dist/utils/structuredLogger.js +394 -0
- package/dist/utils/textEncoding.js +2 -1
- package/dist/utils/typeValidation.d.ts +34 -0
- package/dist/utils/typeValidation.js +247 -0
- package/package.json +14 -6
- package/scripts/download-models.cjs +6 -15
- package/dist/augmentations/walAugmentation.d.ts +0 -111
- package/dist/augmentations/walAugmentation.js +0 -519
- package/dist/chat/BrainyChat.d.ts +0 -121
- package/dist/chat/BrainyChat.js +0 -396
- package/dist/chat/ChatCLI.d.ts +0 -61
- package/dist/chat/ChatCLI.js +0 -351
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-Config Parameter Validation
|
|
3
|
+
*
|
|
4
|
+
* Self-configuring validation that adapts to system capabilities
|
|
5
|
+
* Only enforces universal truths, learns everything else
|
|
6
|
+
*/
|
|
7
|
+
import { NounType, VerbType } from '../types/graphTypes.js';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
/**
|
|
10
|
+
* Auto-configured limits based on system resources
|
|
11
|
+
* These adapt to available memory and observed performance
|
|
12
|
+
*/
|
|
13
|
+
class ValidationConfig {
|
|
14
|
+
constructor() {
|
|
15
|
+
// Performance observations
|
|
16
|
+
this.avgQueryTime = 0;
|
|
17
|
+
this.queryCount = 0;
|
|
18
|
+
// Auto-configure based on system resources
|
|
19
|
+
const totalMemory = os.totalmem();
|
|
20
|
+
const availableMemory = os.freemem();
|
|
21
|
+
// Scale limits based on available memory
|
|
22
|
+
// 1GB = 10K limit, 8GB = 80K limit, etc.
|
|
23
|
+
this.maxLimit = Math.min(100000, // Absolute max for safety
|
|
24
|
+
Math.floor(availableMemory / (1024 * 1024 * 100)) * 1000);
|
|
25
|
+
// Query length scales with memory too
|
|
26
|
+
this.maxQueryLength = Math.min(50000, Math.floor(availableMemory / (1024 * 1024 * 10)) * 1000);
|
|
27
|
+
// Vector dimensions (standard for all-MiniLM-L6-v2)
|
|
28
|
+
this.maxVectorDimensions = 384;
|
|
29
|
+
}
|
|
30
|
+
static getInstance() {
|
|
31
|
+
if (!ValidationConfig.instance) {
|
|
32
|
+
ValidationConfig.instance = new ValidationConfig();
|
|
33
|
+
}
|
|
34
|
+
return ValidationConfig.instance;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Learn from actual usage to adjust limits
|
|
38
|
+
*/
|
|
39
|
+
recordQuery(duration, resultCount) {
|
|
40
|
+
this.queryCount++;
|
|
41
|
+
this.avgQueryTime = (this.avgQueryTime * (this.queryCount - 1) + duration) / this.queryCount;
|
|
42
|
+
// If queries are consistently fast with large results, increase limits
|
|
43
|
+
if (this.avgQueryTime < 100 && resultCount > this.maxLimit * 0.8) {
|
|
44
|
+
this.maxLimit = Math.min(this.maxLimit * 1.5, 100000);
|
|
45
|
+
}
|
|
46
|
+
// If queries are slow, reduce limits
|
|
47
|
+
if (this.avgQueryTime > 1000) {
|
|
48
|
+
this.maxLimit = Math.max(this.maxLimit * 0.8, 1000);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Universal validations - things that are always invalid
|
|
54
|
+
* These are mathematical/logical truths, not configuration
|
|
55
|
+
*/
|
|
56
|
+
export function validateFindParams(params) {
|
|
57
|
+
const config = ValidationConfig.getInstance();
|
|
58
|
+
// Universal truth: negative pagination never makes sense
|
|
59
|
+
if (params.limit !== undefined) {
|
|
60
|
+
if (params.limit < 0) {
|
|
61
|
+
throw new Error('limit must be non-negative');
|
|
62
|
+
}
|
|
63
|
+
if (params.limit > config.maxLimit) {
|
|
64
|
+
throw new Error(`limit exceeds auto-configured maximum of ${config.maxLimit} (based on available memory)`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (params.offset !== undefined && params.offset < 0) {
|
|
68
|
+
throw new Error('offset must be non-negative');
|
|
69
|
+
}
|
|
70
|
+
// Universal truth: probability/similarity must be 0-1
|
|
71
|
+
if (params.near?.threshold !== undefined) {
|
|
72
|
+
const t = params.near.threshold;
|
|
73
|
+
if (t < 0 || t > 1) {
|
|
74
|
+
throw new Error('threshold must be between 0 and 1');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Universal truth: can't specify both query and vector (they're alternatives)
|
|
78
|
+
if (params.query !== undefined && params.vector !== undefined) {
|
|
79
|
+
throw new Error('cannot specify both query and vector - they are mutually exclusive');
|
|
80
|
+
}
|
|
81
|
+
// Universal truth: can't use both cursor and offset pagination
|
|
82
|
+
if (params.cursor !== undefined && params.offset !== undefined) {
|
|
83
|
+
throw new Error('cannot use both cursor and offset pagination simultaneously');
|
|
84
|
+
}
|
|
85
|
+
// Auto-limit query length based on memory
|
|
86
|
+
if (params.query && params.query.length > config.maxQueryLength) {
|
|
87
|
+
throw new Error(`query exceeds auto-configured maximum length of ${config.maxQueryLength} characters`);
|
|
88
|
+
}
|
|
89
|
+
// Validate vector dimensions if provided
|
|
90
|
+
if (params.vector && params.vector.length !== config.maxVectorDimensions) {
|
|
91
|
+
throw new Error(`vector must have exactly ${config.maxVectorDimensions} dimensions`);
|
|
92
|
+
}
|
|
93
|
+
// Validate enum types if specified
|
|
94
|
+
if (params.type) {
|
|
95
|
+
const types = Array.isArray(params.type) ? params.type : [params.type];
|
|
96
|
+
for (const type of types) {
|
|
97
|
+
if (!Object.values(NounType).includes(type)) {
|
|
98
|
+
throw new Error(`invalid NounType: ${type}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Validate add parameters
|
|
105
|
+
*/
|
|
106
|
+
export function validateAddParams(params) {
|
|
107
|
+
// Universal truth: must have data or vector
|
|
108
|
+
if (!params.data && !params.vector) {
|
|
109
|
+
throw new Error('must provide either data or vector');
|
|
110
|
+
}
|
|
111
|
+
// Validate noun type
|
|
112
|
+
if (!Object.values(NounType).includes(params.type)) {
|
|
113
|
+
throw new Error(`invalid NounType: ${params.type}`);
|
|
114
|
+
}
|
|
115
|
+
// Validate vector dimensions if provided
|
|
116
|
+
if (params.vector) {
|
|
117
|
+
const config = ValidationConfig.getInstance();
|
|
118
|
+
if (params.vector.length !== config.maxVectorDimensions) {
|
|
119
|
+
throw new Error(`vector must have exactly ${config.maxVectorDimensions} dimensions`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate update parameters
|
|
125
|
+
*/
|
|
126
|
+
export function validateUpdateParams(params) {
|
|
127
|
+
// Universal truth: must have an ID
|
|
128
|
+
if (!params.id) {
|
|
129
|
+
throw new Error('id is required for update');
|
|
130
|
+
}
|
|
131
|
+
// Universal truth: must update something
|
|
132
|
+
if (!params.data && !params.metadata && !params.type && !params.vector) {
|
|
133
|
+
throw new Error('must specify at least one field to update');
|
|
134
|
+
}
|
|
135
|
+
// Validate type if changing
|
|
136
|
+
if (params.type && !Object.values(NounType).includes(params.type)) {
|
|
137
|
+
throw new Error(`invalid NounType: ${params.type}`);
|
|
138
|
+
}
|
|
139
|
+
// Validate vector dimensions if provided
|
|
140
|
+
if (params.vector) {
|
|
141
|
+
const config = ValidationConfig.getInstance();
|
|
142
|
+
if (params.vector.length !== config.maxVectorDimensions) {
|
|
143
|
+
throw new Error(`vector must have exactly ${config.maxVectorDimensions} dimensions`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Validate relate parameters
|
|
149
|
+
*/
|
|
150
|
+
export function validateRelateParams(params) {
|
|
151
|
+
// Universal truths
|
|
152
|
+
if (!params.from) {
|
|
153
|
+
throw new Error('from entity ID is required');
|
|
154
|
+
}
|
|
155
|
+
if (!params.to) {
|
|
156
|
+
throw new Error('to entity ID is required');
|
|
157
|
+
}
|
|
158
|
+
if (params.from === params.to) {
|
|
159
|
+
throw new Error('cannot create self-referential relationship');
|
|
160
|
+
}
|
|
161
|
+
// Validate verb type
|
|
162
|
+
if (!Object.values(VerbType).includes(params.type)) {
|
|
163
|
+
throw new Error(`invalid VerbType: ${params.type}`);
|
|
164
|
+
}
|
|
165
|
+
// Universal truth: weight must be 0-1
|
|
166
|
+
if (params.weight !== undefined) {
|
|
167
|
+
if (params.weight < 0 || params.weight > 1) {
|
|
168
|
+
throw new Error('weight must be between 0 and 1');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get current validation configuration
|
|
174
|
+
* Useful for debugging and monitoring
|
|
175
|
+
*/
|
|
176
|
+
export function getValidationConfig() {
|
|
177
|
+
const config = ValidationConfig.getInstance();
|
|
178
|
+
return {
|
|
179
|
+
maxLimit: config.maxLimit,
|
|
180
|
+
maxQueryLength: config.maxQueryLength,
|
|
181
|
+
maxVectorDimensions: config.maxVectorDimensions,
|
|
182
|
+
systemMemory: os.totalmem(),
|
|
183
|
+
availableMemory: os.freemem()
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Record query performance for auto-tuning
|
|
188
|
+
*/
|
|
189
|
+
export function recordQueryPerformance(duration, resultCount) {
|
|
190
|
+
ValidationConfig.getInstance().recordQuery(duration, resultCount);
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=paramValidation.js.map
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter for Brainy API
|
|
3
|
+
*
|
|
4
|
+
* Provides rate limiting without external dependencies like Redis.
|
|
5
|
+
* - Uses in-memory storage for single instances
|
|
6
|
+
* - Can use S3/R2 for distributed rate limiting
|
|
7
|
+
*
|
|
8
|
+
* @module rateLimiter
|
|
9
|
+
*/
|
|
10
|
+
import { BaseStorageAdapter } from '../storage/adapters/baseStorageAdapter.js';
|
|
11
|
+
export interface RateLimitConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Maximum number of requests allowed
|
|
14
|
+
*/
|
|
15
|
+
maxRequests: number;
|
|
16
|
+
/**
|
|
17
|
+
* Time window in milliseconds
|
|
18
|
+
*/
|
|
19
|
+
windowMs: number;
|
|
20
|
+
/**
|
|
21
|
+
* Optional message to return when rate limit is exceeded
|
|
22
|
+
*/
|
|
23
|
+
message?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to use distributed storage (S3/R2) for rate limiting
|
|
26
|
+
*/
|
|
27
|
+
distributed?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Storage adapter for distributed rate limiting
|
|
30
|
+
*/
|
|
31
|
+
storage?: BaseStorageAdapter;
|
|
32
|
+
/**
|
|
33
|
+
* Key prefix for distributed storage
|
|
34
|
+
*/
|
|
35
|
+
keyPrefix?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface RateLimitResult {
|
|
38
|
+
/**
|
|
39
|
+
* Whether the request is allowed
|
|
40
|
+
*/
|
|
41
|
+
allowed: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Number of requests remaining in the current window
|
|
44
|
+
*/
|
|
45
|
+
remaining: number;
|
|
46
|
+
/**
|
|
47
|
+
* Time when the rate limit window resets (Unix timestamp)
|
|
48
|
+
*/
|
|
49
|
+
resetTime: number;
|
|
50
|
+
/**
|
|
51
|
+
* Total limit for the window
|
|
52
|
+
*/
|
|
53
|
+
limit: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Simple in-memory rate limiter
|
|
57
|
+
*/
|
|
58
|
+
export declare class RateLimiter {
|
|
59
|
+
private config;
|
|
60
|
+
private requests;
|
|
61
|
+
private cleanupInterval;
|
|
62
|
+
constructor(config: RateLimitConfig);
|
|
63
|
+
/**
|
|
64
|
+
* Check if a request is allowed and update the rate limit
|
|
65
|
+
*/
|
|
66
|
+
checkLimit(identifier: string): Promise<RateLimitResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Check rate limit using in-memory storage
|
|
69
|
+
*/
|
|
70
|
+
private checkMemoryLimit;
|
|
71
|
+
/**
|
|
72
|
+
* Check rate limit using distributed storage (S3/R2)
|
|
73
|
+
*/
|
|
74
|
+
private checkDistributedLimit;
|
|
75
|
+
/**
|
|
76
|
+
* Reset rate limit for a specific identifier
|
|
77
|
+
*/
|
|
78
|
+
reset(identifier: string): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Start cleanup interval to remove expired entries
|
|
81
|
+
*/
|
|
82
|
+
private startCleanup;
|
|
83
|
+
/**
|
|
84
|
+
* Stop the rate limiter and cleanup
|
|
85
|
+
*/
|
|
86
|
+
destroy(): void;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Express/Connect middleware for rate limiting
|
|
90
|
+
*/
|
|
91
|
+
export declare function rateLimitMiddleware(config: RateLimitConfig): (req: any, res: any, next: any) => Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Create a rate limiter for use with Brainy
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // For single instance (in-memory)
|
|
98
|
+
* const limiter = createRateLimiter({
|
|
99
|
+
* maxRequests: 100,
|
|
100
|
+
* windowMs: 15 * 60 * 1000 // 15 minutes
|
|
101
|
+
* })
|
|
102
|
+
*
|
|
103
|
+
* // For distributed (using S3/R2)
|
|
104
|
+
* const limiter = createRateLimiter({
|
|
105
|
+
* maxRequests: 100,
|
|
106
|
+
* windowMs: 15 * 60 * 1000,
|
|
107
|
+
* distributed: true,
|
|
108
|
+
* storage: myS3Adapter
|
|
109
|
+
* })
|
|
110
|
+
*
|
|
111
|
+
* // Check rate limit
|
|
112
|
+
* const result = await limiter.checkLimit('user-123')
|
|
113
|
+
* if (!result.allowed) {
|
|
114
|
+
* throw new Error('Rate limit exceeded')
|
|
115
|
+
* }
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare function createRateLimiter(config: RateLimitConfig): RateLimiter;
|
|
119
|
+
/**
|
|
120
|
+
* Preset configurations for common use cases
|
|
121
|
+
*/
|
|
122
|
+
export declare const RateLimitPresets: {
|
|
123
|
+
/**
|
|
124
|
+
* Default API rate limit: 100 requests per 15 minutes
|
|
125
|
+
*/
|
|
126
|
+
default: {
|
|
127
|
+
maxRequests: number;
|
|
128
|
+
windowMs: number;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Strict rate limit: 10 requests per minute
|
|
132
|
+
*/
|
|
133
|
+
strict: {
|
|
134
|
+
maxRequests: number;
|
|
135
|
+
windowMs: number;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Lenient rate limit: 1000 requests per hour
|
|
139
|
+
*/
|
|
140
|
+
lenient: {
|
|
141
|
+
maxRequests: number;
|
|
142
|
+
windowMs: number;
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Search endpoint: 30 requests per minute
|
|
146
|
+
*/
|
|
147
|
+
search: {
|
|
148
|
+
maxRequests: number;
|
|
149
|
+
windowMs: number;
|
|
150
|
+
message: string;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Write operations: 20 requests per minute
|
|
154
|
+
*/
|
|
155
|
+
write: {
|
|
156
|
+
maxRequests: number;
|
|
157
|
+
windowMs: number;
|
|
158
|
+
message: string;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter for Brainy API
|
|
3
|
+
*
|
|
4
|
+
* Provides rate limiting without external dependencies like Redis.
|
|
5
|
+
* - Uses in-memory storage for single instances
|
|
6
|
+
* - Can use S3/R2 for distributed rate limiting
|
|
7
|
+
*
|
|
8
|
+
* @module rateLimiter
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Simple in-memory rate limiter
|
|
12
|
+
*/
|
|
13
|
+
export class RateLimiter {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.requests = new Map();
|
|
17
|
+
this.cleanupInterval = null;
|
|
18
|
+
// Start cleanup interval to remove expired entries
|
|
19
|
+
this.startCleanup();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Check if a request is allowed and update the rate limit
|
|
23
|
+
*/
|
|
24
|
+
async checkLimit(identifier) {
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
if (this.config.distributed && this.config.storage) {
|
|
27
|
+
return this.checkDistributedLimit(identifier, now);
|
|
28
|
+
}
|
|
29
|
+
return this.checkMemoryLimit(identifier, now);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check rate limit using in-memory storage
|
|
33
|
+
*/
|
|
34
|
+
checkMemoryLimit(identifier, now) {
|
|
35
|
+
const entry = this.requests.get(identifier);
|
|
36
|
+
const resetTime = now + this.config.windowMs;
|
|
37
|
+
if (!entry || entry.resetTime <= now) {
|
|
38
|
+
// New window or expired window
|
|
39
|
+
this.requests.set(identifier, {
|
|
40
|
+
count: 1,
|
|
41
|
+
resetTime
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
allowed: true,
|
|
45
|
+
remaining: this.config.maxRequests - 1,
|
|
46
|
+
resetTime,
|
|
47
|
+
limit: this.config.maxRequests
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Existing window
|
|
51
|
+
if (entry.count < this.config.maxRequests) {
|
|
52
|
+
entry.count++;
|
|
53
|
+
return {
|
|
54
|
+
allowed: true,
|
|
55
|
+
remaining: this.config.maxRequests - entry.count,
|
|
56
|
+
resetTime: entry.resetTime,
|
|
57
|
+
limit: this.config.maxRequests
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Rate limit exceeded
|
|
61
|
+
return {
|
|
62
|
+
allowed: false,
|
|
63
|
+
remaining: 0,
|
|
64
|
+
resetTime: entry.resetTime,
|
|
65
|
+
limit: this.config.maxRequests
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check rate limit using distributed storage (S3/R2)
|
|
70
|
+
*/
|
|
71
|
+
async checkDistributedLimit(identifier, now) {
|
|
72
|
+
const storage = this.config.storage;
|
|
73
|
+
const key = `ratelimit_${identifier}`;
|
|
74
|
+
const resetTime = now + this.config.windowMs;
|
|
75
|
+
try {
|
|
76
|
+
// Try to get existing rate limit data from metadata storage
|
|
77
|
+
const existing = await storage.getMetadata(key);
|
|
78
|
+
if (!existing || !existing.resetTime ||
|
|
79
|
+
Number(existing.resetTime) <= now) {
|
|
80
|
+
// New window or expired window
|
|
81
|
+
await storage.saveMetadata(key, {
|
|
82
|
+
count: 1,
|
|
83
|
+
resetTime: resetTime,
|
|
84
|
+
identifier
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
allowed: true,
|
|
88
|
+
remaining: this.config.maxRequests - 1,
|
|
89
|
+
resetTime,
|
|
90
|
+
limit: this.config.maxRequests
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const count = Number(existing.count || 0);
|
|
94
|
+
if (count < this.config.maxRequests) {
|
|
95
|
+
// Update count
|
|
96
|
+
await storage.saveMetadata(key, {
|
|
97
|
+
count: count + 1,
|
|
98
|
+
resetTime: existing.resetTime,
|
|
99
|
+
identifier
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
allowed: true,
|
|
103
|
+
remaining: this.config.maxRequests - count - 1,
|
|
104
|
+
resetTime: Number(existing.resetTime),
|
|
105
|
+
limit: this.config.maxRequests
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Rate limit exceeded
|
|
109
|
+
return {
|
|
110
|
+
allowed: false,
|
|
111
|
+
remaining: 0,
|
|
112
|
+
resetTime: Number(existing.resetTime),
|
|
113
|
+
limit: this.config.maxRequests
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
// On error, fail open (allow the request)
|
|
118
|
+
console.warn('Rate limiter error, failing open:', error);
|
|
119
|
+
return {
|
|
120
|
+
allowed: true,
|
|
121
|
+
remaining: this.config.maxRequests,
|
|
122
|
+
resetTime,
|
|
123
|
+
limit: this.config.maxRequests
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Reset rate limit for a specific identifier
|
|
129
|
+
*/
|
|
130
|
+
async reset(identifier) {
|
|
131
|
+
if (this.config.distributed && this.config.storage) {
|
|
132
|
+
const key = `ratelimit_${identifier}`;
|
|
133
|
+
// Reset by setting count to 0 and expired time
|
|
134
|
+
await this.config.storage.saveMetadata(key, {
|
|
135
|
+
count: 0,
|
|
136
|
+
resetTime: 0,
|
|
137
|
+
identifier
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.requests.delete(identifier);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Start cleanup interval to remove expired entries
|
|
146
|
+
*/
|
|
147
|
+
startCleanup() {
|
|
148
|
+
// Run cleanup every minute
|
|
149
|
+
this.cleanupInterval = setInterval(() => {
|
|
150
|
+
const now = Date.now();
|
|
151
|
+
const expired = [];
|
|
152
|
+
for (const [key, entry] of this.requests) {
|
|
153
|
+
if (entry.resetTime <= now) {
|
|
154
|
+
expired.push(key);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const key of expired) {
|
|
158
|
+
this.requests.delete(key);
|
|
159
|
+
}
|
|
160
|
+
}, 60000); // 1 minute
|
|
161
|
+
// Don't keep Node.js process alive just for cleanup
|
|
162
|
+
if (this.cleanupInterval.unref) {
|
|
163
|
+
this.cleanupInterval.unref();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Stop the rate limiter and cleanup
|
|
168
|
+
*/
|
|
169
|
+
destroy() {
|
|
170
|
+
if (this.cleanupInterval) {
|
|
171
|
+
clearInterval(this.cleanupInterval);
|
|
172
|
+
this.cleanupInterval = null;
|
|
173
|
+
}
|
|
174
|
+
this.requests.clear();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Express/Connect middleware for rate limiting
|
|
179
|
+
*/
|
|
180
|
+
export function rateLimitMiddleware(config) {
|
|
181
|
+
const limiter = new RateLimiter(config);
|
|
182
|
+
return async (req, res, next) => {
|
|
183
|
+
// Use IP address as identifier (can be customized)
|
|
184
|
+
const identifier = req.ip || req.connection?.remoteAddress || 'unknown';
|
|
185
|
+
const result = await limiter.checkLimit(identifier);
|
|
186
|
+
// Set rate limit headers
|
|
187
|
+
res.setHeader('X-RateLimit-Limit', result.limit);
|
|
188
|
+
res.setHeader('X-RateLimit-Remaining', result.remaining);
|
|
189
|
+
res.setHeader('X-RateLimit-Reset', result.resetTime);
|
|
190
|
+
if (!result.allowed) {
|
|
191
|
+
res.status(429).json({
|
|
192
|
+
error: config.message || 'Too many requests, please try again later.',
|
|
193
|
+
retryAfter: Math.ceil((result.resetTime - Date.now()) / 1000)
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
next();
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Create a rate limiter for use with Brainy
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* // For single instance (in-memory)
|
|
206
|
+
* const limiter = createRateLimiter({
|
|
207
|
+
* maxRequests: 100,
|
|
208
|
+
* windowMs: 15 * 60 * 1000 // 15 minutes
|
|
209
|
+
* })
|
|
210
|
+
*
|
|
211
|
+
* // For distributed (using S3/R2)
|
|
212
|
+
* const limiter = createRateLimiter({
|
|
213
|
+
* maxRequests: 100,
|
|
214
|
+
* windowMs: 15 * 60 * 1000,
|
|
215
|
+
* distributed: true,
|
|
216
|
+
* storage: myS3Adapter
|
|
217
|
+
* })
|
|
218
|
+
*
|
|
219
|
+
* // Check rate limit
|
|
220
|
+
* const result = await limiter.checkLimit('user-123')
|
|
221
|
+
* if (!result.allowed) {
|
|
222
|
+
* throw new Error('Rate limit exceeded')
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export function createRateLimiter(config) {
|
|
227
|
+
return new RateLimiter(config);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Preset configurations for common use cases
|
|
231
|
+
*/
|
|
232
|
+
export const RateLimitPresets = {
|
|
233
|
+
/**
|
|
234
|
+
* Default API rate limit: 100 requests per 15 minutes
|
|
235
|
+
*/
|
|
236
|
+
default: {
|
|
237
|
+
maxRequests: 100,
|
|
238
|
+
windowMs: 15 * 60 * 1000
|
|
239
|
+
},
|
|
240
|
+
/**
|
|
241
|
+
* Strict rate limit: 10 requests per minute
|
|
242
|
+
*/
|
|
243
|
+
strict: {
|
|
244
|
+
maxRequests: 10,
|
|
245
|
+
windowMs: 60 * 1000
|
|
246
|
+
},
|
|
247
|
+
/**
|
|
248
|
+
* Lenient rate limit: 1000 requests per hour
|
|
249
|
+
*/
|
|
250
|
+
lenient: {
|
|
251
|
+
maxRequests: 1000,
|
|
252
|
+
windowMs: 60 * 60 * 1000
|
|
253
|
+
},
|
|
254
|
+
/**
|
|
255
|
+
* Search endpoint: 30 requests per minute
|
|
256
|
+
*/
|
|
257
|
+
search: {
|
|
258
|
+
maxRequests: 30,
|
|
259
|
+
windowMs: 60 * 1000,
|
|
260
|
+
message: 'Search rate limit exceeded. Please wait before searching again.'
|
|
261
|
+
},
|
|
262
|
+
/**
|
|
263
|
+
* Write operations: 20 requests per minute
|
|
264
|
+
*/
|
|
265
|
+
write: {
|
|
266
|
+
maxRequests: 20,
|
|
267
|
+
windowMs: 60 * 1000,
|
|
268
|
+
message: 'Write rate limit exceeded. Please slow down your write operations.'
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
//# sourceMappingURL=rateLimiter.js.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility functions for retrieving statistics from Brainy
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { Brainy } from '../brainy.js';
|
|
5
5
|
/**
|
|
6
|
-
* Get statistics about the current state of a
|
|
6
|
+
* Get statistics about the current state of a Brainy instance
|
|
7
7
|
* This function provides access to statistics at the root level of the library
|
|
8
8
|
*
|
|
9
|
-
* @param instance A
|
|
9
|
+
* @param instance A Brainy instance to get statistics from
|
|
10
10
|
* @param options Additional options for retrieving statistics
|
|
11
11
|
* @returns Object containing counts of nouns, verbs, metadata entries, and HNSW index size
|
|
12
12
|
* @throws Error if the instance is not provided or if statistics retrieval fails
|
|
13
13
|
*/
|
|
14
|
-
export declare function getStatistics(instance:
|
|
14
|
+
export declare function getStatistics(instance: Brainy, options?: {
|
|
15
15
|
service?: string | string[];
|
|
16
16
|
}): Promise<{
|
|
17
17
|
nounCount: number;
|
package/dist/utils/statistics.js
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
* Utility functions for retrieving statistics from Brainy
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* Get statistics about the current state of a
|
|
5
|
+
* Get statistics about the current state of a Brainy instance
|
|
6
6
|
* This function provides access to statistics at the root level of the library
|
|
7
7
|
*
|
|
8
|
-
* @param instance A
|
|
8
|
+
* @param instance A Brainy instance to get statistics from
|
|
9
9
|
* @param options Additional options for retrieving statistics
|
|
10
10
|
* @returns Object containing counts of nouns, verbs, metadata entries, and HNSW index size
|
|
11
11
|
* @throws Error if the instance is not provided or if statistics retrieval fails
|
|
12
12
|
*/
|
|
13
13
|
export async function getStatistics(instance, options = {}) {
|
|
14
14
|
if (!instance) {
|
|
15
|
-
throw new Error('
|
|
15
|
+
throw new Error('Brainy instance must be provided to getStatistics');
|
|
16
16
|
}
|
|
17
17
|
try {
|
|
18
18
|
return await instance.getStatistics(options);
|