agentic-flow 1.10.0 → 1.10.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/dist/utils/adaptive-pool-sizing.js +414 -0
- package/dist/utils/circular-rate-limiter.js +391 -0
- package/dist/utils/dynamic-compression.js +298 -0
- package/dist/utils/http2-multiplexing.js +319 -0
- package/dist/utils/lazy-auth.js +311 -0
- package/dist/utils/server-push.js +251 -0
- package/dist/utils/zero-copy-buffer.js +286 -0
- package/docs/DOCKER-VERIFICATION.md +207 -0
- package/docs/ISSUE-55-VALIDATION.md +25 -6
- package/docs/NPX_AGENTDB_SETUP.md +175 -0
- package/docs/PHASE2-IMPLEMENTATION-SUMMARY.md +275 -0
- package/docs/PHASE2-PHASE3-COMPLETE-SUMMARY.md +453 -0
- package/docs/PHASE3-IMPLEMENTATION-SUMMARY.md +357 -0
- package/docs/PUBLISH_GUIDE.md +438 -0
- package/docs/RELEASE-v1.10.0-COMPLETE.md +382 -0
- package/docs/archive/.agentdb-instructions.md +66 -0
- package/docs/archive/AGENT-BOOSTER-STATUS.md +292 -0
- package/docs/archive/CHANGELOG-v1.3.0.md +120 -0
- package/docs/archive/COMPLETION_REPORT_v1.7.1.md +335 -0
- package/docs/archive/IMPLEMENTATION_SUMMARY_v1.7.1.md +241 -0
- package/docs/archive/SUPABASE-INTEGRATION-COMPLETE.md +357 -0
- package/docs/archive/TESTING_QUICK_START.md +223 -0
- package/docs/archive/TOOL-EMULATION-INTEGRATION-ISSUE.md +669 -0
- package/docs/archive/VALIDATION_v1.7.1.md +234 -0
- package/docs/releases/PUBLISH_CHECKLIST_v1.10.0.md +396 -0
- package/docs/releases/PUBLISH_SUMMARY_v1.7.1.md +198 -0
- package/docs/releases/RELEASE_NOTES_v1.10.0.md +464 -0
- package/docs/releases/RELEASE_NOTES_v1.7.0.md +297 -0
- package/docs/releases/RELEASE_v1.7.1.md +327 -0
- package/package.json +1 -1
- package/validation/docker-npm-validation.sh +170 -0
- package/validation/simple-npm-validation.sh +131 -0
- package/validation/test-gemini-models.ts +200 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Pool Sizing based on Traffic Patterns
|
|
3
|
+
* Automatically adjusts pool sizes for 5-10% better resource utilization
|
|
4
|
+
* Phase 3 Optimization
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Adaptive Pool Sizing Manager
|
|
8
|
+
* Analyzes traffic patterns and automatically adjusts pool sizes
|
|
9
|
+
*/
|
|
10
|
+
export class AdaptivePoolSizingManager {
|
|
11
|
+
config;
|
|
12
|
+
currentSize;
|
|
13
|
+
activeItems = 0;
|
|
14
|
+
stats;
|
|
15
|
+
trafficHistory = [];
|
|
16
|
+
utilizationSamples = [];
|
|
17
|
+
adjustmentTimer;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = {
|
|
20
|
+
enabled: config.enabled,
|
|
21
|
+
minSize: config.minSize || 10,
|
|
22
|
+
maxSize: config.maxSize || 1000,
|
|
23
|
+
initialSize: config.initialSize || 50,
|
|
24
|
+
adjustInterval: config.adjustInterval || 30000, // 30 seconds
|
|
25
|
+
targetUtilization: config.targetUtilization || 70,
|
|
26
|
+
scaleUpThreshold: config.scaleUpThreshold || 80,
|
|
27
|
+
scaleDownThreshold: config.scaleDownThreshold || 40,
|
|
28
|
+
scaleStep: config.scaleStep || 10
|
|
29
|
+
};
|
|
30
|
+
this.currentSize = this.config.initialSize;
|
|
31
|
+
this.stats = {
|
|
32
|
+
currentSize: this.currentSize,
|
|
33
|
+
minSize: this.config.minSize,
|
|
34
|
+
maxSize: this.config.maxSize,
|
|
35
|
+
utilizationPercent: 0,
|
|
36
|
+
activeItems: 0,
|
|
37
|
+
totalAdjustments: 0,
|
|
38
|
+
scaleUps: 0,
|
|
39
|
+
scaleDowns: 0,
|
|
40
|
+
avgUtilization: 0,
|
|
41
|
+
peakUtilization: 0
|
|
42
|
+
};
|
|
43
|
+
if (this.config.enabled) {
|
|
44
|
+
this.startAdjustmentMonitoring();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Record pool usage
|
|
49
|
+
*/
|
|
50
|
+
recordUsage(active, total) {
|
|
51
|
+
this.activeItems = active;
|
|
52
|
+
const poolSize = total || this.currentSize;
|
|
53
|
+
const utilization = (active / poolSize) * 100;
|
|
54
|
+
this.utilizationSamples.push(utilization);
|
|
55
|
+
// Keep last 100 samples
|
|
56
|
+
if (this.utilizationSamples.length > 100) {
|
|
57
|
+
this.utilizationSamples.shift();
|
|
58
|
+
}
|
|
59
|
+
// Update statistics
|
|
60
|
+
this.updateStats(utilization);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Record traffic pattern
|
|
64
|
+
*/
|
|
65
|
+
recordTraffic(pattern) {
|
|
66
|
+
this.trafficHistory.push({
|
|
67
|
+
...pattern,
|
|
68
|
+
timestamp: Date.now()
|
|
69
|
+
});
|
|
70
|
+
// Keep last 1000 patterns (configurable time window)
|
|
71
|
+
if (this.trafficHistory.length > 1000) {
|
|
72
|
+
this.trafficHistory.shift();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get recommended pool size based on traffic analysis
|
|
77
|
+
*/
|
|
78
|
+
getRecommendedSize() {
|
|
79
|
+
if (!this.config.enabled || this.utilizationSamples.length === 0) {
|
|
80
|
+
return this.currentSize;
|
|
81
|
+
}
|
|
82
|
+
const avgUtilization = this.calculateAverageUtilization();
|
|
83
|
+
const trend = this.analyzeTrafficTrend();
|
|
84
|
+
const predictedLoad = this.predictFutureLoad();
|
|
85
|
+
let recommendedSize = this.currentSize;
|
|
86
|
+
// Scale up if high utilization or increasing trend
|
|
87
|
+
if (avgUtilization > this.config.scaleUpThreshold || trend === 'increasing') {
|
|
88
|
+
recommendedSize = this.currentSize + this.config.scaleStep;
|
|
89
|
+
}
|
|
90
|
+
// Scale down if low utilization and stable/decreasing trend
|
|
91
|
+
else if (avgUtilization < this.config.scaleDownThreshold && (trend === 'stable' || trend === 'decreasing')) {
|
|
92
|
+
recommendedSize = this.currentSize - this.config.scaleStep;
|
|
93
|
+
}
|
|
94
|
+
// Adjust for predicted load
|
|
95
|
+
else if (predictedLoad > avgUtilization * 1.2) {
|
|
96
|
+
recommendedSize = Math.ceil(this.currentSize * (predictedLoad / avgUtilization));
|
|
97
|
+
}
|
|
98
|
+
// Ensure within bounds
|
|
99
|
+
return Math.max(this.config.minSize, Math.min(this.config.maxSize, recommendedSize));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Apply recommended pool size adjustment
|
|
103
|
+
*/
|
|
104
|
+
applyAdjustment() {
|
|
105
|
+
const recommended = this.getRecommendedSize();
|
|
106
|
+
const oldSize = this.currentSize;
|
|
107
|
+
if (recommended !== oldSize) {
|
|
108
|
+
this.currentSize = recommended;
|
|
109
|
+
this.stats.currentSize = recommended;
|
|
110
|
+
this.stats.totalAdjustments++;
|
|
111
|
+
if (recommended > oldSize) {
|
|
112
|
+
this.stats.scaleUps++;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.stats.scaleDowns++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return this.currentSize;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Calculate average utilization
|
|
122
|
+
*/
|
|
123
|
+
calculateAverageUtilization() {
|
|
124
|
+
if (this.utilizationSamples.length === 0)
|
|
125
|
+
return 0;
|
|
126
|
+
const sum = this.utilizationSamples.reduce((a, b) => a + b, 0);
|
|
127
|
+
return sum / this.utilizationSamples.length;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Analyze traffic trend (increasing, stable, decreasing)
|
|
131
|
+
*/
|
|
132
|
+
analyzeTrafficTrend() {
|
|
133
|
+
if (this.trafficHistory.length < 10)
|
|
134
|
+
return 'stable';
|
|
135
|
+
const recent = this.trafficHistory.slice(-10);
|
|
136
|
+
const older = this.trafficHistory.slice(-20, -10);
|
|
137
|
+
if (older.length === 0)
|
|
138
|
+
return 'stable';
|
|
139
|
+
const recentAvg = recent.reduce((sum, p) => sum + p.requestRate, 0) / recent.length;
|
|
140
|
+
const olderAvg = older.reduce((sum, p) => sum + p.requestRate, 0) / older.length;
|
|
141
|
+
const change = ((recentAvg - olderAvg) / olderAvg) * 100;
|
|
142
|
+
if (change > 10)
|
|
143
|
+
return 'increasing';
|
|
144
|
+
if (change < -10)
|
|
145
|
+
return 'decreasing';
|
|
146
|
+
return 'stable';
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Predict future load using simple linear regression
|
|
150
|
+
*/
|
|
151
|
+
predictFutureLoad() {
|
|
152
|
+
if (this.utilizationSamples.length < 10) {
|
|
153
|
+
return this.calculateAverageUtilization();
|
|
154
|
+
}
|
|
155
|
+
const samples = this.utilizationSamples.slice(-20);
|
|
156
|
+
const n = samples.length;
|
|
157
|
+
// Simple linear regression
|
|
158
|
+
let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
|
|
159
|
+
for (let i = 0; i < n; i++) {
|
|
160
|
+
sumX += i;
|
|
161
|
+
sumY += samples[i];
|
|
162
|
+
sumXY += i * samples[i];
|
|
163
|
+
sumX2 += i * i;
|
|
164
|
+
}
|
|
165
|
+
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
|
|
166
|
+
const intercept = (sumY - slope * sumX) / n;
|
|
167
|
+
// Predict next value
|
|
168
|
+
const predicted = slope * n + intercept;
|
|
169
|
+
return Math.max(0, Math.min(100, predicted));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Update statistics
|
|
173
|
+
*/
|
|
174
|
+
updateStats(utilization) {
|
|
175
|
+
this.stats.utilizationPercent = utilization;
|
|
176
|
+
this.stats.activeItems = this.activeItems;
|
|
177
|
+
this.stats.avgUtilization = this.calculateAverageUtilization();
|
|
178
|
+
if (utilization > this.stats.peakUtilization) {
|
|
179
|
+
this.stats.peakUtilization = utilization;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Start automatic adjustment monitoring
|
|
184
|
+
*/
|
|
185
|
+
startAdjustmentMonitoring() {
|
|
186
|
+
this.adjustmentTimer = setInterval(() => {
|
|
187
|
+
this.applyAdjustment();
|
|
188
|
+
}, this.config.adjustInterval);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get current pool size
|
|
192
|
+
*/
|
|
193
|
+
getCurrentSize() {
|
|
194
|
+
return this.currentSize;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get statistics
|
|
198
|
+
*/
|
|
199
|
+
getStats() {
|
|
200
|
+
return { ...this.stats };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get traffic analysis
|
|
204
|
+
*/
|
|
205
|
+
getTrafficAnalysis() {
|
|
206
|
+
if (this.trafficHistory.length === 0) {
|
|
207
|
+
return {
|
|
208
|
+
currentRate: 0,
|
|
209
|
+
avgRate: 0,
|
|
210
|
+
peakRate: 0,
|
|
211
|
+
trend: 'stable',
|
|
212
|
+
predictedLoad: 0
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const rates = this.trafficHistory.map(p => p.requestRate);
|
|
216
|
+
const avgRate = rates.reduce((a, b) => a + b, 0) / rates.length;
|
|
217
|
+
const peakRate = Math.max(...rates);
|
|
218
|
+
const currentRate = this.trafficHistory[this.trafficHistory.length - 1]?.requestRate || 0;
|
|
219
|
+
return {
|
|
220
|
+
currentRate,
|
|
221
|
+
avgRate,
|
|
222
|
+
peakRate,
|
|
223
|
+
trend: this.analyzeTrafficTrend(),
|
|
224
|
+
predictedLoad: this.predictFutureLoad()
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get efficiency score (0-100)
|
|
229
|
+
*/
|
|
230
|
+
getEfficiencyScore() {
|
|
231
|
+
const avgUtil = this.stats.avgUtilization;
|
|
232
|
+
const target = this.config.targetUtilization;
|
|
233
|
+
// Perfect score at target utilization
|
|
234
|
+
// Score decreases as utilization deviates from target
|
|
235
|
+
const deviation = Math.abs(avgUtil - target);
|
|
236
|
+
const score = Math.max(0, 100 - (deviation * 2));
|
|
237
|
+
return score;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Reset statistics
|
|
241
|
+
*/
|
|
242
|
+
resetStats() {
|
|
243
|
+
this.stats = {
|
|
244
|
+
currentSize: this.currentSize,
|
|
245
|
+
minSize: this.config.minSize,
|
|
246
|
+
maxSize: this.config.maxSize,
|
|
247
|
+
utilizationPercent: 0,
|
|
248
|
+
activeItems: 0,
|
|
249
|
+
totalAdjustments: 0,
|
|
250
|
+
scaleUps: 0,
|
|
251
|
+
scaleDowns: 0,
|
|
252
|
+
avgUtilization: 0,
|
|
253
|
+
peakUtilization: 0
|
|
254
|
+
};
|
|
255
|
+
this.utilizationSamples = [];
|
|
256
|
+
this.trafficHistory = [];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Manually set pool size
|
|
260
|
+
*/
|
|
261
|
+
setSize(size) {
|
|
262
|
+
if (size < this.config.minSize || size > this.config.maxSize) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
this.currentSize = size;
|
|
266
|
+
this.stats.currentSize = size;
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Destroy manager and cleanup
|
|
271
|
+
*/
|
|
272
|
+
destroy() {
|
|
273
|
+
if (this.adjustmentTimer) {
|
|
274
|
+
clearInterval(this.adjustmentTimer);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Connection Pool with Adaptive Sizing
|
|
280
|
+
*/
|
|
281
|
+
export class AdaptiveConnectionPool {
|
|
282
|
+
pool = [];
|
|
283
|
+
inUse = new Set();
|
|
284
|
+
sizingManager;
|
|
285
|
+
createFn;
|
|
286
|
+
destroyFn;
|
|
287
|
+
constructor(config, createFn, destroyFn) {
|
|
288
|
+
this.sizingManager = new AdaptivePoolSizingManager(config);
|
|
289
|
+
this.createFn = createFn;
|
|
290
|
+
this.destroyFn = destroyFn;
|
|
291
|
+
// Initialize pool to initial size
|
|
292
|
+
this.adjustPoolSize();
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Acquire item from pool
|
|
296
|
+
*/
|
|
297
|
+
acquire() {
|
|
298
|
+
let item = this.pool.pop();
|
|
299
|
+
if (!item) {
|
|
300
|
+
item = this.createFn();
|
|
301
|
+
}
|
|
302
|
+
this.inUse.add(item);
|
|
303
|
+
this.recordUsage();
|
|
304
|
+
return item;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Release item back to pool
|
|
308
|
+
*/
|
|
309
|
+
release(item) {
|
|
310
|
+
this.inUse.delete(item);
|
|
311
|
+
const targetSize = this.sizingManager.getCurrentSize();
|
|
312
|
+
if (this.pool.length + this.inUse.size > targetSize) {
|
|
313
|
+
// Pool too large, destroy item
|
|
314
|
+
this.destroyFn(item);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
// Return to pool
|
|
318
|
+
this.pool.push(item);
|
|
319
|
+
}
|
|
320
|
+
this.recordUsage();
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Record current usage
|
|
324
|
+
*/
|
|
325
|
+
recordUsage() {
|
|
326
|
+
const active = this.inUse.size;
|
|
327
|
+
const total = this.pool.length + active;
|
|
328
|
+
this.sizingManager.recordUsage(active, total);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Adjust pool size based on recommendations
|
|
332
|
+
*/
|
|
333
|
+
adjustPoolSize() {
|
|
334
|
+
const targetSize = this.sizingManager.applyAdjustment();
|
|
335
|
+
const currentTotal = this.pool.length + this.inUse.size;
|
|
336
|
+
if (targetSize > currentTotal) {
|
|
337
|
+
// Scale up - create more items
|
|
338
|
+
const needed = targetSize - currentTotal;
|
|
339
|
+
for (let i = 0; i < needed; i++) {
|
|
340
|
+
this.pool.push(this.createFn());
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
else if (targetSize < currentTotal) {
|
|
344
|
+
// Scale down - remove excess items
|
|
345
|
+
const excess = currentTotal - targetSize;
|
|
346
|
+
const toRemove = Math.min(excess, this.pool.length);
|
|
347
|
+
for (let i = 0; i < toRemove; i++) {
|
|
348
|
+
const item = this.pool.pop();
|
|
349
|
+
if (item) {
|
|
350
|
+
this.destroyFn(item);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Get statistics
|
|
357
|
+
*/
|
|
358
|
+
getStats() {
|
|
359
|
+
return {
|
|
360
|
+
...this.sizingManager.getStats(),
|
|
361
|
+
poolSize: this.pool.length,
|
|
362
|
+
inUseCount: this.inUse.size
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Destroy pool
|
|
367
|
+
*/
|
|
368
|
+
destroy() {
|
|
369
|
+
// Destroy all pooled items
|
|
370
|
+
while (this.pool.length > 0) {
|
|
371
|
+
const item = this.pool.pop();
|
|
372
|
+
if (item) {
|
|
373
|
+
this.destroyFn(item);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
this.sizingManager.destroy();
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Buffer Pool with Adaptive Sizing
|
|
381
|
+
*/
|
|
382
|
+
export class AdaptiveBufferPool {
|
|
383
|
+
pool;
|
|
384
|
+
bufferSize;
|
|
385
|
+
constructor(config, bufferSize = 64 * 1024) {
|
|
386
|
+
this.bufferSize = bufferSize;
|
|
387
|
+
this.pool = new AdaptiveConnectionPool(config, () => Buffer.allocUnsafe(this.bufferSize), (_item) => { });
|
|
388
|
+
}
|
|
389
|
+
acquire() {
|
|
390
|
+
return this.pool.acquire();
|
|
391
|
+
}
|
|
392
|
+
release(buffer) {
|
|
393
|
+
this.pool.release(buffer);
|
|
394
|
+
}
|
|
395
|
+
getStats() {
|
|
396
|
+
return this.pool.getStats();
|
|
397
|
+
}
|
|
398
|
+
destroy() {
|
|
399
|
+
this.pool.destroy();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Calculate resource utilization improvement
|
|
404
|
+
*/
|
|
405
|
+
export function calculatePoolSizingSavings(oldAvgSize, newAvgSize, peakSize) {
|
|
406
|
+
const resourceSavings = oldAvgSize - newAvgSize;
|
|
407
|
+
const savingsPercent = (resourceSavings / oldAvgSize) * 100;
|
|
408
|
+
const efficiencyGain = (1 - (newAvgSize / peakSize)) * 100;
|
|
409
|
+
return {
|
|
410
|
+
resourceSavings,
|
|
411
|
+
savingsPercent,
|
|
412
|
+
efficiencyGain
|
|
413
|
+
};
|
|
414
|
+
}
|