agentic-flow 2.0.1-alpha.4 → 2.0.1-alpha.8

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 (197) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentdb/controllers/EmbeddingService.d.ts +37 -0
  4. package/dist/agentdb/controllers/EmbeddingService.d.ts.map +1 -0
  5. package/dist/agentdb/controllers/EmbeddingService.js +1 -0
  6. package/dist/agentdb/controllers/EmbeddingService.js.map +1 -0
  7. package/dist/billing/mcp/tools.d.ts.map +1 -1
  8. package/dist/billing/mcp/tools.js +2 -0
  9. package/dist/billing/mcp/tools.js.map +1 -1
  10. package/dist/cli/commands/hooks.d.ts +18 -0
  11. package/dist/cli/commands/hooks.d.ts.map +1 -0
  12. package/dist/cli/commands/hooks.js +750 -0
  13. package/dist/cli/commands/hooks.js.map +1 -0
  14. package/dist/cli-proxy.js +26 -1
  15. package/dist/cli-proxy.js.map +1 -1
  16. package/dist/core/agentdb-fast.js +3 -3
  17. package/dist/core/agentdb-fast.js.map +1 -1
  18. package/dist/core/agentdb-wrapper-enhanced.d.ts.map +1 -1
  19. package/dist/core/agentdb-wrapper-enhanced.js +32 -17
  20. package/dist/core/agentdb-wrapper-enhanced.js.map +1 -1
  21. package/dist/core/attention-native.d.ts +1 -0
  22. package/dist/core/attention-native.d.ts.map +1 -1
  23. package/dist/core/attention-native.js +6 -1
  24. package/dist/core/attention-native.js.map +1 -1
  25. package/dist/federation/integrations/supabase-adapter-debug.js +3 -3
  26. package/dist/federation/integrations/supabase-adapter-debug.js.map +1 -1
  27. package/dist/intelligence/RuVectorIntelligence.d.ts +362 -0
  28. package/dist/intelligence/RuVectorIntelligence.d.ts.map +1 -0
  29. package/dist/intelligence/RuVectorIntelligence.js +852 -0
  30. package/dist/intelligence/RuVectorIntelligence.js.map +1 -0
  31. package/dist/intelligence/index.d.ts +14 -0
  32. package/dist/intelligence/index.d.ts.map +1 -0
  33. package/dist/intelligence/index.js +14 -0
  34. package/dist/intelligence/index.js.map +1 -0
  35. package/dist/llm/RuvLLMOrchestrator.d.ts +184 -0
  36. package/dist/llm/RuvLLMOrchestrator.d.ts.map +1 -0
  37. package/dist/llm/RuvLLMOrchestrator.js +442 -0
  38. package/dist/llm/RuvLLMOrchestrator.js.map +1 -0
  39. package/dist/llm/index.d.ts +9 -0
  40. package/dist/llm/index.d.ts.map +1 -0
  41. package/dist/llm/index.js +8 -0
  42. package/dist/llm/index.js.map +1 -0
  43. package/dist/mcp/claudeFlowSdkServer.d.ts.map +1 -1
  44. package/dist/mcp/claudeFlowSdkServer.js +86 -21
  45. package/dist/mcp/claudeFlowSdkServer.js.map +1 -1
  46. package/dist/mcp/fastmcp/servers/hooks-server.d.ts +15 -0
  47. package/dist/mcp/fastmcp/servers/hooks-server.d.ts.map +1 -0
  48. package/dist/mcp/fastmcp/servers/hooks-server.js +63 -0
  49. package/dist/mcp/fastmcp/servers/hooks-server.js.map +1 -0
  50. package/dist/mcp/fastmcp/tools/hooks/benchmark.d.ts +20 -0
  51. package/dist/mcp/fastmcp/tools/hooks/benchmark.d.ts.map +1 -0
  52. package/dist/mcp/fastmcp/tools/hooks/benchmark.js +110 -0
  53. package/dist/mcp/fastmcp/tools/hooks/benchmark.js.map +1 -0
  54. package/dist/mcp/fastmcp/tools/hooks/build-agents.d.ts +7 -0
  55. package/dist/mcp/fastmcp/tools/hooks/build-agents.d.ts.map +1 -0
  56. package/dist/mcp/fastmcp/tools/hooks/build-agents.js +276 -0
  57. package/dist/mcp/fastmcp/tools/hooks/build-agents.js.map +1 -0
  58. package/dist/mcp/fastmcp/tools/hooks/explain.d.ts +6 -0
  59. package/dist/mcp/fastmcp/tools/hooks/explain.d.ts.map +1 -0
  60. package/dist/mcp/fastmcp/tools/hooks/explain.js +164 -0
  61. package/dist/mcp/fastmcp/tools/hooks/explain.js.map +1 -0
  62. package/dist/mcp/fastmcp/tools/hooks/index.d.ts +28 -0
  63. package/dist/mcp/fastmcp/tools/hooks/index.d.ts.map +1 -0
  64. package/dist/mcp/fastmcp/tools/hooks/index.js +59 -0
  65. package/dist/mcp/fastmcp/tools/hooks/index.js.map +1 -0
  66. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.d.ts +91 -0
  67. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.d.ts.map +1 -0
  68. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js +269 -0
  69. package/dist/mcp/fastmcp/tools/hooks/intelligence-bridge.js.map +1 -0
  70. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.d.ts +58 -0
  71. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.d.ts.map +1 -0
  72. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.js +416 -0
  73. package/dist/mcp/fastmcp/tools/hooks/intelligence-tools.js.map +1 -0
  74. package/dist/mcp/fastmcp/tools/hooks/metrics.d.ts +6 -0
  75. package/dist/mcp/fastmcp/tools/hooks/metrics.d.ts.map +1 -0
  76. package/dist/mcp/fastmcp/tools/hooks/metrics.js +137 -0
  77. package/dist/mcp/fastmcp/tools/hooks/metrics.js.map +1 -0
  78. package/dist/mcp/fastmcp/tools/hooks/post-command.d.ts +7 -0
  79. package/dist/mcp/fastmcp/tools/hooks/post-command.d.ts.map +1 -0
  80. package/dist/mcp/fastmcp/tools/hooks/post-command.js +91 -0
  81. package/dist/mcp/fastmcp/tools/hooks/post-command.js.map +1 -0
  82. package/dist/mcp/fastmcp/tools/hooks/post-edit.d.ts +12 -0
  83. package/dist/mcp/fastmcp/tools/hooks/post-edit.d.ts.map +1 -0
  84. package/dist/mcp/fastmcp/tools/hooks/post-edit.js +146 -0
  85. package/dist/mcp/fastmcp/tools/hooks/post-edit.js.map +1 -0
  86. package/dist/mcp/fastmcp/tools/hooks/pre-command.d.ts +7 -0
  87. package/dist/mcp/fastmcp/tools/hooks/pre-command.d.ts.map +1 -0
  88. package/dist/mcp/fastmcp/tools/hooks/pre-command.js +70 -0
  89. package/dist/mcp/fastmcp/tools/hooks/pre-command.js.map +1 -0
  90. package/dist/mcp/fastmcp/tools/hooks/pre-edit.d.ts +14 -0
  91. package/dist/mcp/fastmcp/tools/hooks/pre-edit.d.ts.map +1 -0
  92. package/dist/mcp/fastmcp/tools/hooks/pre-edit.js +121 -0
  93. package/dist/mcp/fastmcp/tools/hooks/pre-edit.js.map +1 -0
  94. package/dist/mcp/fastmcp/tools/hooks/pretrain.d.ts +7 -0
  95. package/dist/mcp/fastmcp/tools/hooks/pretrain.d.ts.map +1 -0
  96. package/dist/mcp/fastmcp/tools/hooks/pretrain.js +171 -0
  97. package/dist/mcp/fastmcp/tools/hooks/pretrain.js.map +1 -0
  98. package/dist/mcp/fastmcp/tools/hooks/route.d.ts +12 -0
  99. package/dist/mcp/fastmcp/tools/hooks/route.d.ts.map +1 -0
  100. package/dist/mcp/fastmcp/tools/hooks/route.js +267 -0
  101. package/dist/mcp/fastmcp/tools/hooks/route.js.map +1 -0
  102. package/dist/mcp/fastmcp/tools/hooks/shared.d.ts +46 -0
  103. package/dist/mcp/fastmcp/tools/hooks/shared.d.ts.map +1 -0
  104. package/dist/mcp/fastmcp/tools/hooks/shared.js +159 -0
  105. package/dist/mcp/fastmcp/tools/hooks/shared.js.map +1 -0
  106. package/dist/mcp/fastmcp/tools/hooks/transfer.d.ts +7 -0
  107. package/dist/mcp/fastmcp/tools/hooks/transfer.d.ts.map +1 -0
  108. package/dist/mcp/fastmcp/tools/hooks/transfer.js +151 -0
  109. package/dist/mcp/fastmcp/tools/hooks/transfer.js.map +1 -0
  110. package/dist/mcp/tools/agent-booster-tools.d.ts +10 -1
  111. package/dist/mcp/tools/agent-booster-tools.d.ts.map +1 -1
  112. package/dist/mcp/tools/agent-booster-tools.js.map +1 -1
  113. package/dist/mcp/tools/sona-tools.d.ts.map +1 -1
  114. package/dist/mcp/tools/sona-tools.js +15 -3
  115. package/dist/mcp/tools/sona-tools.js.map +1 -1
  116. package/dist/memory/SharedMemoryPool.d.ts +16 -3
  117. package/dist/memory/SharedMemoryPool.d.ts.map +1 -1
  118. package/dist/memory/SharedMemoryPool.js +33 -1
  119. package/dist/memory/SharedMemoryPool.js.map +1 -1
  120. package/dist/middleware/auth.middleware.d.ts +114 -0
  121. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  122. package/dist/middleware/auth.middleware.js +222 -0
  123. package/dist/middleware/auth.middleware.js.map +1 -0
  124. package/dist/optimizations/agent-booster-migration.d.ts.map +1 -1
  125. package/dist/optimizations/agent-booster-migration.js.map +1 -1
  126. package/dist/proxy/anthropic-to-gemini.d.ts.map +1 -1
  127. package/dist/proxy/anthropic-to-gemini.js.map +1 -1
  128. package/dist/proxy/anthropic-to-openrouter.d.ts.map +1 -1
  129. package/dist/proxy/anthropic-to-openrouter.js.map +1 -1
  130. package/dist/proxy/anthropic-to-requesty.d.ts.map +1 -1
  131. package/dist/proxy/anthropic-to-requesty.js.map +1 -1
  132. package/dist/proxy/quic-proxy.d.ts +0 -1
  133. package/dist/proxy/quic-proxy.d.ts.map +1 -1
  134. package/dist/proxy/quic-proxy.js +2 -1
  135. package/dist/proxy/quic-proxy.js.map +1 -1
  136. package/dist/reasoningbank/AdvancedMemory.d.ts.map +1 -1
  137. package/dist/reasoningbank/AdvancedMemory.js +12 -1
  138. package/dist/reasoningbank/AdvancedMemory.js.map +1 -1
  139. package/dist/reasoningbank/HybridBackend.d.ts +9 -0
  140. package/dist/reasoningbank/HybridBackend.d.ts.map +1 -1
  141. package/dist/reasoningbank/HybridBackend.js +48 -4
  142. package/dist/reasoningbank/HybridBackend.js.map +1 -1
  143. package/dist/reasoningbank/backend-selector.d.ts +1 -1
  144. package/dist/reasoningbank/backend-selector.d.ts.map +1 -1
  145. package/dist/reasoningbank/backend-selector.js.map +1 -1
  146. package/dist/reasoningbank/index-new.d.ts +0 -6
  147. package/dist/reasoningbank/index-new.d.ts.map +1 -1
  148. package/dist/reasoningbank/index-new.js +9 -7
  149. package/dist/reasoningbank/index-new.js.map +1 -1
  150. package/dist/reasoningbank/index.d.ts +1 -6
  151. package/dist/reasoningbank/index.d.ts.map +1 -1
  152. package/dist/reasoningbank/index.js +10 -7
  153. package/dist/reasoningbank/index.js.map +1 -1
  154. package/dist/router/providers/onnx-local.d.ts.map +1 -1
  155. package/dist/router/providers/onnx-local.js +3 -1
  156. package/dist/router/providers/onnx-local.js.map +1 -1
  157. package/dist/routing/CircuitBreakerRouter.d.ts +187 -0
  158. package/dist/routing/CircuitBreakerRouter.d.ts.map +1 -0
  159. package/dist/routing/CircuitBreakerRouter.js +460 -0
  160. package/dist/routing/CircuitBreakerRouter.js.map +1 -0
  161. package/dist/routing/SemanticRouter.d.ts +164 -0
  162. package/dist/routing/SemanticRouter.d.ts.map +1 -0
  163. package/dist/routing/SemanticRouter.js +291 -0
  164. package/dist/routing/SemanticRouter.js.map +1 -0
  165. package/dist/routing/index.d.ts +12 -0
  166. package/dist/routing/index.d.ts.map +1 -0
  167. package/dist/routing/index.js +10 -0
  168. package/dist/routing/index.js.map +1 -0
  169. package/dist/services/embedding-service.d.ts.map +1 -1
  170. package/dist/services/embedding-service.js +5 -2
  171. package/dist/services/embedding-service.js.map +1 -1
  172. package/dist/services/sona-agent-training.js +1 -1
  173. package/dist/services/sona-agent-training.js.map +1 -1
  174. package/dist/services/sona-agentdb-integration.d.ts.map +1 -1
  175. package/dist/services/sona-agentdb-integration.js +10 -5
  176. package/dist/services/sona-agentdb-integration.js.map +1 -1
  177. package/dist/services/sona-service.d.ts +6 -6
  178. package/dist/services/sona-service.d.ts.map +1 -1
  179. package/dist/services/sona-service.js +3 -1
  180. package/dist/services/sona-service.js.map +1 -1
  181. package/dist/utils/audit-logger.d.ts +115 -0
  182. package/dist/utils/audit-logger.d.ts.map +1 -0
  183. package/dist/utils/audit-logger.js +228 -0
  184. package/dist/utils/audit-logger.js.map +1 -0
  185. package/dist/utils/cli.d.ts +1 -1
  186. package/dist/utils/cli.d.ts.map +1 -1
  187. package/dist/utils/cli.js +5 -0
  188. package/dist/utils/cli.js.map +1 -1
  189. package/dist/utils/input-validator.d.ts +116 -0
  190. package/dist/utils/input-validator.d.ts.map +1 -0
  191. package/dist/utils/input-validator.js +299 -0
  192. package/dist/utils/input-validator.js.map +1 -0
  193. package/dist/utils/rate-limiter.js +2 -2
  194. package/dist/utils/rate-limiter.js.map +1 -1
  195. package/package.json +5 -2
  196. package/wasm/reasoningbank/reasoningbank_wasm_bg.js +2 -2
  197. package/wasm/reasoningbank/reasoningbank_wasm_bg.wasm +0 -0
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Input Validation Utilities
3
+ *
4
+ * Provides secure input validation for RuVector integration:
5
+ * - Task description validation
6
+ * - Configuration validation
7
+ * - Injection attack prevention
8
+ * - Resource exhaustion prevention
9
+ */
10
+ export class ValidationError extends Error {
11
+ field;
12
+ constructor(message, field) {
13
+ super(message);
14
+ this.field = field;
15
+ this.name = 'ValidationError';
16
+ }
17
+ }
18
+ /**
19
+ * Input Validator
20
+ *
21
+ * Validates all external inputs to prevent:
22
+ * - Injection attacks (XSS, SQL injection, prompt injection)
23
+ * - Resource exhaustion (excessive length, recursion)
24
+ * - Malicious content (scripts, control characters)
25
+ */
26
+ export class InputValidator {
27
+ // Suspicious patterns that could indicate attacks
28
+ static SUSPICIOUS_PATTERNS = [
29
+ /<script/i, // XSS attempt
30
+ /javascript:/i, // JavaScript protocol
31
+ /data:text\/html/i, // Data URI XSS
32
+ /on\w+\s*=/i, // Event handlers
33
+ /\beval\s*\(/i, // eval() calls
34
+ /\bFunction\s*\(/i, // Function constructor
35
+ /__proto__/, // Prototype pollution
36
+ /\.\.\//, // Path traversal
37
+ /[;\x00]/, // SQL injection chars
38
+ ];
39
+ // Control characters that should be removed
40
+ static CONTROL_CHARS_REGEX = /[\x00-\x1F\x7F]/g;
41
+ /**
42
+ * Validate task description
43
+ *
44
+ * @param taskDescription - User-provided task description
45
+ * @param options - Validation options
46
+ * @returns Sanitized task description
47
+ * @throws ValidationError if invalid
48
+ */
49
+ static validateTaskDescription(taskDescription, options) {
50
+ const opts = {
51
+ maxLength: options?.maxLength ?? 10000,
52
+ minLength: options?.minLength ?? 1,
53
+ allowEmpty: options?.allowEmpty ?? false,
54
+ sanitize: options?.sanitize ?? true,
55
+ };
56
+ // Check for null/undefined
57
+ if (taskDescription === null || taskDescription === undefined) {
58
+ throw new ValidationError('Task description is required', 'taskDescription');
59
+ }
60
+ // Check type
61
+ if (typeof taskDescription !== 'string') {
62
+ throw new ValidationError(`Task description must be a string, got ${typeof taskDescription}`, 'taskDescription');
63
+ }
64
+ // Check empty
65
+ if (!opts.allowEmpty && taskDescription.trim().length === 0) {
66
+ throw new ValidationError('Task description cannot be empty', 'taskDescription');
67
+ }
68
+ // Check length
69
+ if (taskDescription.length < opts.minLength) {
70
+ throw new ValidationError(`Task description too short (min ${opts.minLength} chars)`, 'taskDescription');
71
+ }
72
+ if (taskDescription.length > opts.maxLength) {
73
+ throw new ValidationError(`Task description too long (max ${opts.maxLength} chars)`, 'taskDescription');
74
+ }
75
+ // Sanitize if requested
76
+ let sanitized = taskDescription;
77
+ if (opts.sanitize) {
78
+ // Remove control characters
79
+ sanitized = sanitized.replace(InputValidator.CONTROL_CHARS_REGEX, '');
80
+ // Check for suspicious patterns
81
+ for (const pattern of InputValidator.SUSPICIOUS_PATTERNS) {
82
+ if (pattern.test(sanitized)) {
83
+ throw new ValidationError('Task description contains suspicious content', 'taskDescription');
84
+ }
85
+ }
86
+ }
87
+ return sanitized.trim();
88
+ }
89
+ /**
90
+ * Validate agent name
91
+ *
92
+ * @param agentName - Agent identifier
93
+ * @returns Sanitized agent name
94
+ * @throws ValidationError if invalid
95
+ */
96
+ static validateAgentName(agentName) {
97
+ if (!agentName || typeof agentName !== 'string') {
98
+ throw new ValidationError('Agent name is required', 'agentName');
99
+ }
100
+ if (agentName.length < 1 || agentName.length > 100) {
101
+ throw new ValidationError('Agent name must be between 1-100 characters', 'agentName');
102
+ }
103
+ // Only allow alphanumeric, dash, underscore
104
+ if (!/^[a-zA-Z0-9_-]+$/.test(agentName)) {
105
+ throw new ValidationError('Agent name can only contain letters, numbers, dash, and underscore', 'agentName');
106
+ }
107
+ return agentName.toLowerCase();
108
+ }
109
+ /**
110
+ * Validate confidence score
111
+ *
112
+ * @param confidence - Confidence score (0-1)
113
+ * @returns Validated confidence
114
+ * @throws ValidationError if invalid
115
+ */
116
+ static validateConfidence(confidence) {
117
+ if (typeof confidence !== 'number') {
118
+ throw new ValidationError(`Confidence must be a number, got ${typeof confidence}`, 'confidence');
119
+ }
120
+ if (Number.isNaN(confidence) || !Number.isFinite(confidence)) {
121
+ throw new ValidationError('Confidence must be a valid number', 'confidence');
122
+ }
123
+ if (confidence < 0 || confidence > 1) {
124
+ throw new ValidationError('Confidence must be between 0 and 1', 'confidence');
125
+ }
126
+ return confidence;
127
+ }
128
+ /**
129
+ * Validate timeout value
130
+ *
131
+ * @param timeout - Timeout in milliseconds
132
+ * @param min - Minimum allowed timeout (default: 100ms)
133
+ * @param max - Maximum allowed timeout (default: 5 minutes)
134
+ * @returns Validated timeout
135
+ * @throws ValidationError if invalid
136
+ */
137
+ static validateTimeout(timeout, min = 100, max = 300000) {
138
+ if (typeof timeout !== 'number') {
139
+ throw new ValidationError(`Timeout must be a number, got ${typeof timeout}`, 'timeout');
140
+ }
141
+ if (Number.isNaN(timeout) || !Number.isFinite(timeout)) {
142
+ throw new ValidationError('Timeout must be a valid number', 'timeout');
143
+ }
144
+ if (timeout < min) {
145
+ throw new ValidationError(`Timeout too short (min ${min}ms)`, 'timeout');
146
+ }
147
+ if (timeout > max) {
148
+ throw new ValidationError(`Timeout too long (max ${max}ms)`, 'timeout');
149
+ }
150
+ return Math.floor(timeout);
151
+ }
152
+ /**
153
+ * Validate array of strings
154
+ *
155
+ * @param array - Array to validate
156
+ * @param fieldName - Field name for error messages
157
+ * @param maxItems - Maximum number of items
158
+ * @param maxLength - Maximum length per item
159
+ * @returns Validated array
160
+ * @throws ValidationError if invalid
161
+ */
162
+ static validateStringArray(array, fieldName, maxItems = 100, maxLength = 1000) {
163
+ if (!Array.isArray(array)) {
164
+ throw new ValidationError(`${fieldName} must be an array`, fieldName);
165
+ }
166
+ if (array.length > maxItems) {
167
+ throw new ValidationError(`${fieldName} has too many items (max ${maxItems})`, fieldName);
168
+ }
169
+ const validated = [];
170
+ for (let i = 0; i < array.length; i++) {
171
+ const item = array[i];
172
+ if (typeof item !== 'string') {
173
+ throw new ValidationError(`${fieldName}[${i}] must be a string`, fieldName);
174
+ }
175
+ if (item.length > maxLength) {
176
+ throw new ValidationError(`${fieldName}[${i}] too long (max ${maxLength} chars)`, fieldName);
177
+ }
178
+ validated.push(item);
179
+ }
180
+ return validated;
181
+ }
182
+ /**
183
+ * Validate configuration object
184
+ *
185
+ * @param config - Configuration to validate
186
+ * @param schema - Validation schema
187
+ * @returns Validated configuration
188
+ * @throws ValidationError if invalid
189
+ */
190
+ static validateConfig(config, schema) {
191
+ if (!config || typeof config !== 'object') {
192
+ throw new ValidationError('Configuration must be an object', 'config');
193
+ }
194
+ const validated = {};
195
+ const configObj = config;
196
+ for (const [key, rules] of Object.entries(schema)) {
197
+ const value = configObj[key];
198
+ // Check required
199
+ if (rules.required && (value === undefined || value === null)) {
200
+ throw new ValidationError(`Configuration field '${key}' is required`, key);
201
+ }
202
+ // Skip if optional and not provided
203
+ if (!rules.required && (value === undefined || value === null)) {
204
+ continue;
205
+ }
206
+ // Check type
207
+ if (typeof value !== rules.type) {
208
+ throw new ValidationError(`Configuration field '${key}' must be ${rules.type}, got ${typeof value}`, key);
209
+ }
210
+ // Validate numbers
211
+ if (rules.type === 'number') {
212
+ if (Number.isNaN(value) || !Number.isFinite(value)) {
213
+ throw new ValidationError(`Configuration field '${key}' must be a valid number`, key);
214
+ }
215
+ if (rules.min !== undefined && value < rules.min) {
216
+ throw new ValidationError(`Configuration field '${key}' must be >= ${rules.min}`, key);
217
+ }
218
+ if (rules.max !== undefined && value > rules.max) {
219
+ throw new ValidationError(`Configuration field '${key}' must be <= ${rules.max}`, key);
220
+ }
221
+ }
222
+ // Custom validator
223
+ if (rules.validator && !rules.validator(value)) {
224
+ throw new ValidationError(`Configuration field '${key}' failed validation`, key);
225
+ }
226
+ validated[key] = value;
227
+ }
228
+ return validated;
229
+ }
230
+ /**
231
+ * Sanitize HTML to prevent XSS
232
+ *
233
+ * @param html - HTML string to sanitize
234
+ * @returns Sanitized HTML (text only)
235
+ */
236
+ static sanitizeHtml(html) {
237
+ if (typeof html !== 'string') {
238
+ return '';
239
+ }
240
+ // Strip all HTML tags, keep text only
241
+ return html
242
+ .replace(/<[^>]*>/g, '')
243
+ .replace(/&lt;/g, '<')
244
+ .replace(/&gt;/g, '>')
245
+ .replace(/&amp;/g, '&')
246
+ .replace(/&quot;/g, '"')
247
+ .replace(/&#x27;/g, "'");
248
+ }
249
+ /**
250
+ * Validate email address
251
+ *
252
+ * @param email - Email to validate
253
+ * @returns Normalized email
254
+ * @throws ValidationError if invalid
255
+ */
256
+ static validateEmail(email) {
257
+ if (!email || typeof email !== 'string') {
258
+ throw new ValidationError('Email is required', 'email');
259
+ }
260
+ // Basic email regex
261
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
262
+ if (!emailRegex.test(email)) {
263
+ throw new ValidationError('Invalid email format', 'email');
264
+ }
265
+ if (email.length > 254) {
266
+ throw new ValidationError('Email too long (max 254 chars)', 'email');
267
+ }
268
+ return email.toLowerCase().trim();
269
+ }
270
+ }
271
+ /**
272
+ * Validation middleware factory
273
+ *
274
+ * Creates validation middleware for Express/Fastify routes
275
+ */
276
+ export function createValidationMiddleware(validator) {
277
+ return async (req, res, next) => {
278
+ try {
279
+ await validator(req);
280
+ next();
281
+ }
282
+ catch (error) {
283
+ if (error instanceof ValidationError) {
284
+ res.status(400).json({
285
+ error: 'Validation Error',
286
+ message: error.message,
287
+ field: error.field,
288
+ });
289
+ }
290
+ else {
291
+ res.status(500).json({
292
+ error: 'Internal Server Error',
293
+ message: 'Validation failed',
294
+ });
295
+ }
296
+ }
297
+ };
298
+ }
299
+ //# sourceMappingURL=input-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/utils/input-validator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Input Validation Utilities\n *\n * Provides secure input validation for RuVector integration:\n * - Task description validation\n * - Configuration validation\n * - Injection attack prevention\n * - Resource exhaustion prevention\n */\n\nexport interface ValidationOptions {\n maxLength?: number;\n minLength?: number;\n allowEmpty?: boolean;\n sanitize?: boolean;\n}\n\nexport class ValidationError extends Error {\n constructor(message: string, public field?: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Input Validator\n *\n * Validates all external inputs to prevent:\n * - Injection attacks (XSS, SQL injection, prompt injection)\n * - Resource exhaustion (excessive length, recursion)\n * - Malicious content (scripts, control characters)\n */\nexport class InputValidator {\n // Suspicious patterns that could indicate attacks\n private static readonly SUSPICIOUS_PATTERNS = [\n /<script/i, // XSS attempt\n /javascript:/i, // JavaScript protocol\n /data:text\\/html/i, // Data URI XSS\n /on\\w+\\s*=/i, // Event handlers\n /\\beval\\s*\\(/i, // eval() calls\n /\\bFunction\\s*\\(/i, // Function constructor\n /__proto__/, // Prototype pollution\n /\\.\\.\\//, // Path traversal\n /[;\\x00]/, // SQL injection chars\n ];\n\n // Control characters that should be removed\n private static readonly CONTROL_CHARS_REGEX = /[\\x00-\\x1F\\x7F]/g;\n\n /**\n * Validate task description\n *\n * @param taskDescription - User-provided task description\n * @param options - Validation options\n * @returns Sanitized task description\n * @throws ValidationError if invalid\n */\n static validateTaskDescription(\n taskDescription: string,\n options?: ValidationOptions\n ): string {\n const opts = {\n maxLength: options?.maxLength ?? 10000,\n minLength: options?.minLength ?? 1,\n allowEmpty: options?.allowEmpty ?? false,\n sanitize: options?.sanitize ?? true,\n };\n\n // Check for null/undefined\n if (taskDescription === null || taskDescription === undefined) {\n throw new ValidationError('Task description is required', 'taskDescription');\n }\n\n // Check type\n if (typeof taskDescription !== 'string') {\n throw new ValidationError(\n `Task description must be a string, got ${typeof taskDescription}`,\n 'taskDescription'\n );\n }\n\n // Check empty\n if (!opts.allowEmpty && taskDescription.trim().length === 0) {\n throw new ValidationError('Task description cannot be empty', 'taskDescription');\n }\n\n // Check length\n if (taskDescription.length < opts.minLength) {\n throw new ValidationError(\n `Task description too short (min ${opts.minLength} chars)`,\n 'taskDescription'\n );\n }\n\n if (taskDescription.length > opts.maxLength) {\n throw new ValidationError(\n `Task description too long (max ${opts.maxLength} chars)`,\n 'taskDescription'\n );\n }\n\n // Sanitize if requested\n let sanitized = taskDescription;\n if (opts.sanitize) {\n // Remove control characters\n sanitized = sanitized.replace(InputValidator.CONTROL_CHARS_REGEX, '');\n\n // Check for suspicious patterns\n for (const pattern of InputValidator.SUSPICIOUS_PATTERNS) {\n if (pattern.test(sanitized)) {\n throw new ValidationError(\n 'Task description contains suspicious content',\n 'taskDescription'\n );\n }\n }\n }\n\n return sanitized.trim();\n }\n\n /**\n * Validate agent name\n *\n * @param agentName - Agent identifier\n * @returns Sanitized agent name\n * @throws ValidationError if invalid\n */\n static validateAgentName(agentName: string): string {\n if (!agentName || typeof agentName !== 'string') {\n throw new ValidationError('Agent name is required', 'agentName');\n }\n\n if (agentName.length < 1 || agentName.length > 100) {\n throw new ValidationError(\n 'Agent name must be between 1-100 characters',\n 'agentName'\n );\n }\n\n // Only allow alphanumeric, dash, underscore\n if (!/^[a-zA-Z0-9_-]+$/.test(agentName)) {\n throw new ValidationError(\n 'Agent name can only contain letters, numbers, dash, and underscore',\n 'agentName'\n );\n }\n\n return agentName.toLowerCase();\n }\n\n /**\n * Validate confidence score\n *\n * @param confidence - Confidence score (0-1)\n * @returns Validated confidence\n * @throws ValidationError if invalid\n */\n static validateConfidence(confidence: number): number {\n if (typeof confidence !== 'number') {\n throw new ValidationError(\n `Confidence must be a number, got ${typeof confidence}`,\n 'confidence'\n );\n }\n\n if (Number.isNaN(confidence) || !Number.isFinite(confidence)) {\n throw new ValidationError('Confidence must be a valid number', 'confidence');\n }\n\n if (confidence < 0 || confidence > 1) {\n throw new ValidationError('Confidence must be between 0 and 1', 'confidence');\n }\n\n return confidence;\n }\n\n /**\n * Validate timeout value\n *\n * @param timeout - Timeout in milliseconds\n * @param min - Minimum allowed timeout (default: 100ms)\n * @param max - Maximum allowed timeout (default: 5 minutes)\n * @returns Validated timeout\n * @throws ValidationError if invalid\n */\n static validateTimeout(\n timeout: number,\n min: number = 100,\n max: number = 300000\n ): number {\n if (typeof timeout !== 'number') {\n throw new ValidationError(\n `Timeout must be a number, got ${typeof timeout}`,\n 'timeout'\n );\n }\n\n if (Number.isNaN(timeout) || !Number.isFinite(timeout)) {\n throw new ValidationError('Timeout must be a valid number', 'timeout');\n }\n\n if (timeout < min) {\n throw new ValidationError(`Timeout too short (min ${min}ms)`, 'timeout');\n }\n\n if (timeout > max) {\n throw new ValidationError(`Timeout too long (max ${max}ms)`, 'timeout');\n }\n\n return Math.floor(timeout);\n }\n\n /**\n * Validate array of strings\n *\n * @param array - Array to validate\n * @param fieldName - Field name for error messages\n * @param maxItems - Maximum number of items\n * @param maxLength - Maximum length per item\n * @returns Validated array\n * @throws ValidationError if invalid\n */\n static validateStringArray(\n array: unknown,\n fieldName: string,\n maxItems: number = 100,\n maxLength: number = 1000\n ): string[] {\n if (!Array.isArray(array)) {\n throw new ValidationError(`${fieldName} must be an array`, fieldName);\n }\n\n if (array.length > maxItems) {\n throw new ValidationError(\n `${fieldName} has too many items (max ${maxItems})`,\n fieldName\n );\n }\n\n const validated: string[] = [];\n for (let i = 0; i < array.length; i++) {\n const item = array[i];\n\n if (typeof item !== 'string') {\n throw new ValidationError(\n `${fieldName}[${i}] must be a string`,\n fieldName\n );\n }\n\n if (item.length > maxLength) {\n throw new ValidationError(\n `${fieldName}[${i}] too long (max ${maxLength} chars)`,\n fieldName\n );\n }\n\n validated.push(item);\n }\n\n return validated;\n }\n\n /**\n * Validate configuration object\n *\n * @param config - Configuration to validate\n * @param schema - Validation schema\n * @returns Validated configuration\n * @throws ValidationError if invalid\n */\n static validateConfig<T extends Record<string, any>>(\n config: unknown,\n schema: {\n [K in keyof T]: {\n type: 'string' | 'number' | 'boolean' | 'object';\n required?: boolean;\n min?: number;\n max?: number;\n validator?: (value: any) => boolean;\n };\n }\n ): T {\n if (!config || typeof config !== 'object') {\n throw new ValidationError('Configuration must be an object', 'config');\n }\n\n const validated: any = {};\n const configObj = config as Record<string, any>;\n\n for (const [key, rules] of Object.entries(schema)) {\n const value = configObj[key];\n\n // Check required\n if (rules.required && (value === undefined || value === null)) {\n throw new ValidationError(`Configuration field '${key}' is required`, key);\n }\n\n // Skip if optional and not provided\n if (!rules.required && (value === undefined || value === null)) {\n continue;\n }\n\n // Check type\n if (typeof value !== rules.type) {\n throw new ValidationError(\n `Configuration field '${key}' must be ${rules.type}, got ${typeof value}`,\n key\n );\n }\n\n // Validate numbers\n if (rules.type === 'number') {\n if (Number.isNaN(value) || !Number.isFinite(value)) {\n throw new ValidationError(\n `Configuration field '${key}' must be a valid number`,\n key\n );\n }\n\n if (rules.min !== undefined && value < rules.min) {\n throw new ValidationError(\n `Configuration field '${key}' must be >= ${rules.min}`,\n key\n );\n }\n\n if (rules.max !== undefined && value > rules.max) {\n throw new ValidationError(\n `Configuration field '${key}' must be <= ${rules.max}`,\n key\n );\n }\n }\n\n // Custom validator\n if (rules.validator && !rules.validator(value)) {\n throw new ValidationError(\n `Configuration field '${key}' failed validation`,\n key\n );\n }\n\n validated[key] = value;\n }\n\n return validated as T;\n }\n\n /**\n * Sanitize HTML to prevent XSS\n *\n * @param html - HTML string to sanitize\n * @returns Sanitized HTML (text only)\n */\n static sanitizeHtml(html: string): string {\n if (typeof html !== 'string') {\n return '';\n }\n\n // Strip all HTML tags, keep text only\n return html\n .replace(/<[^>]*>/g, '')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&')\n .replace(/&quot;/g, '\"')\n .replace(/&#x27;/g, \"'\");\n }\n\n /**\n * Validate email address\n *\n * @param email - Email to validate\n * @returns Normalized email\n * @throws ValidationError if invalid\n */\n static validateEmail(email: string): string {\n if (!email || typeof email !== 'string') {\n throw new ValidationError('Email is required', 'email');\n }\n\n // Basic email regex\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n throw new ValidationError('Invalid email format', 'email');\n }\n\n if (email.length > 254) {\n throw new ValidationError('Email too long (max 254 chars)', 'email');\n }\n\n return email.toLowerCase().trim();\n }\n}\n\n/**\n * Validation middleware factory\n *\n * Creates validation middleware for Express/Fastify routes\n */\nexport function createValidationMiddleware(\n validator: (req: any) => void | Promise<void>\n) {\n return async (req: any, res: any, next: any) => {\n try {\n await validator(req);\n next();\n } catch (error) {\n if (error instanceof ValidationError) {\n res.status(400).json({\n error: 'Validation Error',\n message: error.message,\n field: error.field,\n });\n } else {\n res.status(500).json({\n error: 'Internal Server Error',\n message: 'Validation failed',\n });\n }\n }\n };\n}\n"]}
@@ -10,11 +10,11 @@ export class RateLimiter {
10
10
  // Cleanup expired entries every minute
11
11
  this.cleanupInterval = setInterval(() => {
12
12
  const now = Date.now();
13
- for (const [key, record] of this.clients.entries()) {
13
+ this.clients.forEach((record, key) => {
14
14
  if (record.resetTime < now && (!record.blockedUntil || record.blockedUntil < now)) {
15
15
  this.clients.delete(key);
16
16
  }
17
- }
17
+ });
18
18
  }, 60000);
19
19
  }
20
20
  async consume(key) {
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,MAAM,OAAO,WAAW;IACd,MAAM,CAAoB;IAC1B,OAAO,GAA8B,IAAI,GAAG,EAAE,CAAC;IAC/C,eAAe,CAAiB;IAExC,YAAY,MAAyB;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,uCAAuC;QACvC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;gBACnD,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC;oBAClF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAErC,6BAA6B;QAC7B,IAAI,MAAM,EAAE,YAAY,IAAI,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;YACtD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAChG,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;gBACpB,KAAK,EAAE,CAAC;gBACR,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI;aAC7C,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,kBAAkB;QAClB,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,0BAA0B;QAC1B,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,MAAM,CAAC,MAAM,iBAAiB,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF","sourcesContent":["/**\n * Simple in-memory rate limiter for proxy protection\n */\n\nexport interface RateLimiterConfig {\n points: number; // Number of requests\n duration: number; // Time window in seconds\n blockDuration: number; // Block duration in seconds when exceeded\n}\n\ninterface ClientRecord {\n count: number;\n resetTime: number;\n blockedUntil?: number;\n}\n\nexport class RateLimiter {\n private config: RateLimiterConfig;\n private clients: Map<string, ClientRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor(config: RateLimiterConfig) {\n this.config = config;\n\n // Cleanup expired entries every minute\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [key, record] of this.clients.entries()) {\n if (record.resetTime < now && (!record.blockedUntil || record.blockedUntil < now)) {\n this.clients.delete(key);\n }\n }\n }, 60000);\n }\n\n async consume(key: string): Promise<void> {\n const now = Date.now();\n const record = this.clients.get(key);\n\n // Check if client is blocked\n if (record?.blockedUntil && record.blockedUntil > now) {\n const remainingMs = record.blockedUntil - now;\n throw new Error(`Rate limit exceeded. Try again in ${Math.ceil(remainingMs / 1000)} seconds`);\n }\n\n // Initialize or reset record\n if (!record || record.resetTime < now) {\n this.clients.set(key, {\n count: 1,\n resetTime: now + this.config.duration * 1000\n });\n return;\n }\n\n // Increment count\n record.count++;\n\n // Check if limit exceeded\n if (record.count > this.config.points) {\n record.blockedUntil = now + this.config.blockDuration * 1000;\n throw new Error(`Rate limit exceeded (${this.config.points} requests per ${this.config.duration}s)`);\n }\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n this.clients.clear();\n }\n}\n"]}
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,MAAM,OAAO,WAAW;IACd,MAAM,CAAoB;IAC1B,OAAO,GAA8B,IAAI,GAAG,EAAE,CAAC;IAC/C,eAAe,CAAiB;IAExC,YAAY,MAAyB;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,uCAAuC;QACvC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;gBACnC,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC;oBAClF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAErC,6BAA6B;QAC7B,IAAI,MAAM,EAAE,YAAY,IAAI,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;YACtD,MAAM,WAAW,GAAG,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAChG,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;gBACpB,KAAK,EAAE,CAAC;gBACR,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI;aAC7C,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,kBAAkB;QAClB,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,0BAA0B;QAC1B,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;YAC7D,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,MAAM,CAAC,MAAM,iBAAiB,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IAED,OAAO;QACL,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF","sourcesContent":["/**\n * Simple in-memory rate limiter for proxy protection\n */\n\nexport interface RateLimiterConfig {\n points: number; // Number of requests\n duration: number; // Time window in seconds\n blockDuration: number; // Block duration in seconds when exceeded\n}\n\ninterface ClientRecord {\n count: number;\n resetTime: number;\n blockedUntil?: number;\n}\n\nexport class RateLimiter {\n private config: RateLimiterConfig;\n private clients: Map<string, ClientRecord> = new Map();\n private cleanupInterval: NodeJS.Timeout;\n\n constructor(config: RateLimiterConfig) {\n this.config = config;\n\n // Cleanup expired entries every minute\n this.cleanupInterval = setInterval(() => {\n const now = Date.now();\n this.clients.forEach((record, key) => {\n if (record.resetTime < now && (!record.blockedUntil || record.blockedUntil < now)) {\n this.clients.delete(key);\n }\n });\n }, 60000);\n }\n\n async consume(key: string): Promise<void> {\n const now = Date.now();\n const record = this.clients.get(key);\n\n // Check if client is blocked\n if (record?.blockedUntil && record.blockedUntil > now) {\n const remainingMs = record.blockedUntil - now;\n throw new Error(`Rate limit exceeded. Try again in ${Math.ceil(remainingMs / 1000)} seconds`);\n }\n\n // Initialize or reset record\n if (!record || record.resetTime < now) {\n this.clients.set(key, {\n count: 1,\n resetTime: now + this.config.duration * 1000\n });\n return;\n }\n\n // Increment count\n record.count++;\n\n // Check if limit exceeded\n if (record.count > this.config.points) {\n record.blockedUntil = now + this.config.blockDuration * 1000;\n throw new Error(`Rate limit exceeded (${this.config.points} requests per ${this.config.duration}s)`);\n }\n }\n\n destroy(): void {\n clearInterval(this.cleanupInterval);\n this.clients.clear();\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-flow",
3
- "version": "2.0.1-alpha.4",
3
+ "version": "2.0.1-alpha.8",
4
4
  "description": "Production-ready AI agent orchestration platform with 66 specialized agents, 213 MCP tools, ReasoningBank learning memory, and autonomous multi-agent swarms. Built by @ruvnet with Claude Agent SDK, neural networks, memory persistence, GitHub integration, and distributed consensus protocols.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -143,10 +143,13 @@
143
143
  "@anthropic-ai/claude-agent-sdk": "^0.1.5",
144
144
  "@anthropic-ai/sdk": "^0.65.0",
145
145
  "@google/genai": "^1.22.0",
146
+ "@ruvector/router": "^0.1.25",
147
+ "@ruvector/ruvllm": "^0.2.3",
148
+ "@ruvector/tiny-dancer": "^0.1.15",
146
149
  "@supabase/supabase-js": "^2.78.0",
147
150
  "@xenova/transformers": "^2.17.2",
148
151
  "agent-booster": "file:../packages/agent-booster",
149
- "agentdb": "^1.4.3",
152
+ "agentdb": "^2.0.0-alpha.2.20",
150
153
  "axios": "^1.12.2",
151
154
  "better-sqlite3": "^11.10.0",
152
155
  "dotenv": "^16.4.5",
@@ -258,7 +258,7 @@ export function log(message) {
258
258
  wasm.log(ptr0, len0);
259
259
  }
260
260
 
261
- function __wbg_adapter_4(arg0, arg1, arg2) {
261
+ function __wbg_adapter_6(arg0, arg1, arg2) {
262
262
  wasm.__wbindgen_export_5(arg0, arg1, addHeapObject(arg2));
263
263
  }
264
264
 
@@ -540,7 +540,7 @@ export function __wbindgen_cast_2241b6af4c4b2941(arg0, arg1) {
540
540
 
541
541
  export function __wbindgen_cast_8eb6fd44e7238d11(arg0, arg1) {
542
542
  // Cast intrinsic for `Closure(Closure { dtor_idx: 62, function: Function { arguments: [Externref], shim_idx: 63, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
543
- const ret = makeMutClosure(arg0, arg1, 62, __wbg_adapter_4);
543
+ const ret = makeMutClosure(arg0, arg1, 62, __wbg_adapter_6);
544
544
  return addHeapObject(ret);
545
545
  };
546
546