agentic-qe 2.3.1 → 2.3.3

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 (128) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +1 -1
  3. package/dist/agents/CoverageAnalyzerAgent.d.ts.map +1 -1
  4. package/dist/agents/CoverageAnalyzerAgent.js +53 -27
  5. package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
  6. package/dist/agents/FlakyTestHunterAgent.d.ts +5 -0
  7. package/dist/agents/FlakyTestHunterAgent.d.ts.map +1 -1
  8. package/dist/agents/FlakyTestHunterAgent.js +20 -5
  9. package/dist/agents/FlakyTestHunterAgent.js.map +1 -1
  10. package/dist/agents/QualityGateAgent.js +44 -6
  11. package/dist/agents/QualityGateAgent.js.map +1 -1
  12. package/dist/cli/index.js +0 -0
  13. package/dist/cli/init/database-init.js +5 -0
  14. package/dist/cli/init/database-init.js.map +1 -1
  15. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  16. package/dist/learning/PerformanceTracker.d.ts +9 -0
  17. package/dist/learning/PerformanceTracker.d.ts.map +1 -1
  18. package/dist/learning/PerformanceTracker.js +26 -2
  19. package/dist/learning/PerformanceTracker.js.map +1 -1
  20. package/dist/mcp/server-instructions.d.ts +1 -1
  21. package/dist/mcp/server-instructions.js +1 -1
  22. package/package.json +4 -2
  23. package/scripts/README.md +352 -0
  24. package/scripts/hooks/capture-task-learning.js +191 -0
  25. package/scripts/hooks/emit-task-complete.sh +35 -0
  26. package/scripts/hooks/emit-task-spawn.sh +27 -0
  27. package/.claude/agents/failing-agent.json +0 -9
  28. package/.claude/agents/test-agent.json +0 -9
  29. package/dist/App.d.ts +0 -5
  30. package/dist/App.d.ts.map +0 -1
  31. package/dist/App.js +0 -15
  32. package/dist/App.js.map +0 -1
  33. package/dist/cli/init/utils.d.ts +0 -183
  34. package/dist/cli/init/utils.d.ts.map +0 -1
  35. package/dist/cli/init/utils.js +0 -354
  36. package/dist/cli/init/utils.js.map +0 -1
  37. package/dist/components/Dashboard/Dashboard.d.ts +0 -4
  38. package/dist/components/Dashboard/Dashboard.d.ts.map +0 -1
  39. package/dist/components/Dashboard/Dashboard.js +0 -148
  40. package/dist/components/Dashboard/Dashboard.js.map +0 -1
  41. package/dist/components/Dashboard/DashboardHeader.d.ts +0 -4
  42. package/dist/components/Dashboard/DashboardHeader.d.ts.map +0 -1
  43. package/dist/components/Dashboard/DashboardHeader.js +0 -138
  44. package/dist/components/Dashboard/DashboardHeader.js.map +0 -1
  45. package/dist/contexts/DashboardContext.d.ts +0 -41
  46. package/dist/contexts/DashboardContext.d.ts.map +0 -1
  47. package/dist/contexts/DashboardContext.js +0 -187
  48. package/dist/contexts/DashboardContext.js.map +0 -1
  49. package/dist/core/transport/QUICTransport.d.ts +0 -320
  50. package/dist/core/transport/QUICTransport.d.ts.map +0 -1
  51. package/dist/core/transport/QUICTransport.js +0 -711
  52. package/dist/core/transport/QUICTransport.js.map +0 -1
  53. package/dist/learning/LearningPersistenceAdapter.d.ts +0 -84
  54. package/dist/learning/LearningPersistenceAdapter.d.ts.map +0 -1
  55. package/dist/learning/LearningPersistenceAdapter.js +0 -202
  56. package/dist/learning/LearningPersistenceAdapter.js.map +0 -1
  57. package/dist/learning/algorithms/QLearning.d.ts +0 -68
  58. package/dist/learning/algorithms/QLearning.d.ts.map +0 -1
  59. package/dist/learning/algorithms/QLearning.js +0 -116
  60. package/dist/learning/algorithms/QLearning.js.map +0 -1
  61. package/dist/mcp/handlers/advanced/requirements-generate-bdd.d.ts +0 -7
  62. package/dist/mcp/handlers/advanced/requirements-generate-bdd.d.ts.map +0 -1
  63. package/dist/mcp/handlers/advanced/requirements-generate-bdd.js +0 -267
  64. package/dist/mcp/handlers/advanced/requirements-generate-bdd.js.map +0 -1
  65. package/dist/mcp/handlers/advanced/requirements-validate.d.ts +0 -7
  66. package/dist/mcp/handlers/advanced/requirements-validate.d.ts.map +0 -1
  67. package/dist/mcp/handlers/advanced/requirements-validate.js +0 -175
  68. package/dist/mcp/handlers/advanced/requirements-validate.js.map +0 -1
  69. package/dist/mcp/handlers/analysis/performance-benchmark-run-handler.d.ts +0 -15
  70. package/dist/mcp/handlers/analysis/performance-benchmark-run-handler.d.ts.map +0 -1
  71. package/dist/mcp/handlers/analysis/performance-benchmark-run-handler.js +0 -43
  72. package/dist/mcp/handlers/analysis/performance-benchmark-run-handler.js.map +0 -1
  73. package/dist/mcp/handlers/analysis/performanceBenchmarkRun.d.ts +0 -58
  74. package/dist/mcp/handlers/analysis/performanceBenchmarkRun.d.ts.map +0 -1
  75. package/dist/mcp/handlers/analysis/performanceBenchmarkRun.js +0 -188
  76. package/dist/mcp/handlers/analysis/performanceBenchmarkRun.js.map +0 -1
  77. package/dist/mcp/handlers/optimize-tests.d.ts +0 -219
  78. package/dist/mcp/handlers/optimize-tests.d.ts.map +0 -1
  79. package/dist/mcp/handlers/optimize-tests.js +0 -533
  80. package/dist/mcp/handlers/optimize-tests.js.map +0 -1
  81. package/dist/mcp/handlers/predict-defects.d.ts +0 -194
  82. package/dist/mcp/handlers/predict-defects.d.ts.map +0 -1
  83. package/dist/mcp/handlers/predict-defects.js +0 -722
  84. package/dist/mcp/handlers/predict-defects.js.map +0 -1
  85. package/dist/mcp/handlers/prediction/regression-risk-analyze.d.ts +0 -199
  86. package/dist/mcp/handlers/prediction/regression-risk-analyze.d.ts.map +0 -1
  87. package/dist/mcp/handlers/prediction/regression-risk-analyze.js +0 -471
  88. package/dist/mcp/handlers/prediction/regression-risk-analyze.js.map +0 -1
  89. package/dist/mcp/handlers/quality/quality-decision-make.d.ts +0 -104
  90. package/dist/mcp/handlers/quality/quality-decision-make.d.ts.map +0 -1
  91. package/dist/mcp/handlers/quality/quality-decision-make.js +0 -408
  92. package/dist/mcp/handlers/quality/quality-decision-make.js.map +0 -1
  93. package/dist/mcp/handlers/quality/quality-gate-execute.d.ts +0 -160
  94. package/dist/mcp/handlers/quality/quality-gate-execute.d.ts.map +0 -1
  95. package/dist/mcp/handlers/quality/quality-gate-execute.js +0 -412
  96. package/dist/mcp/handlers/quality/quality-gate-execute.js.map +0 -1
  97. package/dist/mcp/handlers/quality/quality-policy-check.d.ts +0 -163
  98. package/dist/mcp/handlers/quality/quality-policy-check.d.ts.map +0 -1
  99. package/dist/mcp/handlers/quality/quality-policy-check.js +0 -455
  100. package/dist/mcp/handlers/quality/quality-policy-check.js.map +0 -1
  101. package/dist/mcp/handlers/quality/quality-risk-assess.d.ts +0 -123
  102. package/dist/mcp/handlers/quality/quality-risk-assess.d.ts.map +0 -1
  103. package/dist/mcp/handlers/quality/quality-risk-assess.js +0 -522
  104. package/dist/mcp/handlers/quality/quality-risk-assess.js.map +0 -1
  105. package/dist/mcp/handlers/quality/quality-validate-metrics.d.ts +0 -117
  106. package/dist/mcp/handlers/quality/quality-validate-metrics.d.ts.map +0 -1
  107. package/dist/mcp/handlers/quality/quality-validate-metrics.js +0 -288
  108. package/dist/mcp/handlers/quality/quality-validate-metrics.js.map +0 -1
  109. package/dist/mcp/handlers/quality-analyze.d.ts +0 -279
  110. package/dist/mcp/handlers/quality-analyze.d.ts.map +0 -1
  111. package/dist/mcp/handlers/quality-analyze.js +0 -720
  112. package/dist/mcp/handlers/quality-analyze.js.map +0 -1
  113. package/dist/mcp/handlers/security/check-authz.d.ts +0 -152
  114. package/dist/mcp/handlers/security/check-authz.d.ts.map +0 -1
  115. package/dist/mcp/handlers/security/check-authz.js +0 -434
  116. package/dist/mcp/handlers/security/check-authz.js.map +0 -1
  117. package/dist/mcp/handlers/security/scan-dependencies.d.ts +0 -148
  118. package/dist/mcp/handlers/security/scan-dependencies.d.ts.map +0 -1
  119. package/dist/mcp/handlers/security/scan-dependencies.js +0 -354
  120. package/dist/mcp/handlers/security/scan-dependencies.js.map +0 -1
  121. package/dist/mcp/handlers/security/validate-auth.d.ts +0 -128
  122. package/dist/mcp/handlers/security/validate-auth.d.ts.map +0 -1
  123. package/dist/mcp/handlers/security/validate-auth.js +0 -294
  124. package/dist/mcp/handlers/security/validate-auth.js.map +0 -1
  125. package/dist/mcp/handlers/test-generate.d.ts +0 -107
  126. package/dist/mcp/handlers/test-generate.d.ts.map +0 -1
  127. package/dist/mcp/handlers/test-generate.js +0 -454
  128. package/dist/mcp/handlers/test-generate.js.map +0 -1
@@ -1,711 +0,0 @@
1
- "use strict";
2
- /**
3
- * QUIC Transport Layer for AgentDB
4
- * Provides low-latency, multiplexed connections with HTTP/2 fallback
5
- *
6
- * Since QUIC is experimental in Node.js, this implementation uses HTTP/2 as primary
7
- * transport with the QUIC interface ready for future integration.
8
- *
9
- * Features:
10
- * - Connection pooling with automatic scaling
11
- * - Circuit breaker pattern for fault tolerance
12
- * - Exponential backoff retry logic
13
- * - Health monitoring and metrics
14
- * - Automatic fallback from HTTP/2 to HTTP/1.1
15
- * - Low-latency multiplexed streams
16
- *
17
- * @version 1.0.0
18
- */
19
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
- if (k2 === undefined) k2 = k;
21
- var desc = Object.getOwnPropertyDescriptor(m, k);
22
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
23
- desc = { enumerable: true, get: function() { return m[k]; } };
24
- }
25
- Object.defineProperty(o, k2, desc);
26
- }) : (function(o, m, k, k2) {
27
- if (k2 === undefined) k2 = k;
28
- o[k2] = m[k];
29
- }));
30
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
31
- Object.defineProperty(o, "default", { enumerable: true, value: v });
32
- }) : function(o, v) {
33
- o["default"] = v;
34
- });
35
- var __importStar = (this && this.__importStar) || (function () {
36
- var ownKeys = function(o) {
37
- ownKeys = Object.getOwnPropertyNames || function (o) {
38
- var ar = [];
39
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
40
- return ar;
41
- };
42
- return ownKeys(o);
43
- };
44
- return function (mod) {
45
- if (mod && mod.__esModule) return mod;
46
- var result = {};
47
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
48
- __setModuleDefault(result, mod);
49
- return result;
50
- };
51
- })();
52
- Object.defineProperty(exports, "__esModule", { value: true });
53
- exports.DEFAULT_QUIC_CONFIG = exports.QUICTransport = exports.ConnectionPool = exports.CircuitBreaker = void 0;
54
- exports.createQUICTransport = createQUICTransport;
55
- const http2 = __importStar(require("http2"));
56
- const http = __importStar(require("http"));
57
- const https = __importStar(require("https"));
58
- const events_1 = require("events");
59
- /**
60
- * Circuit Breaker Implementation
61
- * Prevents cascading failures by stopping requests to unhealthy services
62
- */
63
- class CircuitBreaker {
64
- constructor(options) {
65
- this.state = 'closed';
66
- this.failureCount = 0;
67
- this.successCount = 0;
68
- this.lastFailure = null;
69
- this.nextRetryTime = null;
70
- this.failureThreshold = options.failureThreshold;
71
- this.successThreshold = options.successThreshold;
72
- this.timeout = options.timeout;
73
- }
74
- /**
75
- * Execute operation with circuit breaker protection
76
- */
77
- async execute(operation) {
78
- // Check if circuit is open
79
- if (this.state === 'open') {
80
- const now = Date.now();
81
- if (this.nextRetryTime && now < this.nextRetryTime.getTime()) {
82
- throw new Error('Circuit breaker is OPEN - requests blocked');
83
- }
84
- // Try half-open state
85
- this.state = 'half-open';
86
- this.successCount = 0;
87
- }
88
- try {
89
- const result = await operation();
90
- this.recordSuccess();
91
- return result;
92
- }
93
- catch (error) {
94
- this.recordFailure();
95
- throw error;
96
- }
97
- }
98
- /**
99
- * Record successful operation
100
- */
101
- recordSuccess() {
102
- this.failureCount = 0;
103
- if (this.state === 'half-open') {
104
- this.successCount++;
105
- if (this.successCount >= this.successThreshold) {
106
- this.state = 'closed';
107
- this.successCount = 0;
108
- }
109
- }
110
- }
111
- /**
112
- * Record failed operation
113
- */
114
- recordFailure() {
115
- this.failureCount++;
116
- this.lastFailure = new Date();
117
- if (this.failureCount >= this.failureThreshold) {
118
- this.state = 'open';
119
- this.nextRetryTime = new Date(Date.now() + this.timeout);
120
- }
121
- }
122
- /**
123
- * Get current circuit breaker state
124
- */
125
- getState() {
126
- return {
127
- state: this.state,
128
- failureCount: this.failureCount,
129
- successCount: this.successCount,
130
- lastFailure: this.lastFailure,
131
- nextRetryTime: this.nextRetryTime
132
- };
133
- }
134
- /**
135
- * Reset circuit breaker
136
- */
137
- reset() {
138
- this.state = 'closed';
139
- this.failureCount = 0;
140
- this.successCount = 0;
141
- this.lastFailure = null;
142
- this.nextRetryTime = null;
143
- }
144
- }
145
- exports.CircuitBreaker = CircuitBreaker;
146
- /**
147
- * Connection Pool Management
148
- * Manages a pool of reusable connections
149
- */
150
- class ConnectionPool {
151
- constructor(options) {
152
- this.connections = [];
153
- this.cleanupInterval = null;
154
- this.minSize = options.minSize;
155
- this.maxSize = options.maxSize;
156
- this.idleTimeout = options.idleTimeout;
157
- // Start cleanup interval
158
- this.cleanupInterval = setInterval(() => {
159
- this.cleanup();
160
- }, 30000); // Clean up every 30 seconds
161
- }
162
- /**
163
- * Acquire a connection from the pool
164
- */
165
- async acquire() {
166
- // Try to find an available healthy connection
167
- const available = this.connections.find(conn => conn.isHealthy && conn.streams.size < 100);
168
- if (available) {
169
- available.lastUsed = new Date();
170
- available.requestCount++;
171
- return available;
172
- }
173
- // Create new connection if pool not full
174
- if (this.connections.length < this.maxSize) {
175
- const conn = await this.createConnection();
176
- this.connections.push(conn);
177
- return conn;
178
- }
179
- // Pool is full, wait and retry
180
- await this.sleep(100);
181
- return this.acquire();
182
- }
183
- /**
184
- * Release a connection back to the pool
185
- */
186
- release(conn) {
187
- conn.lastUsed = new Date();
188
- }
189
- /**
190
- * Mark connection as unhealthy
191
- */
192
- markUnhealthy(conn) {
193
- conn.isHealthy = false;
194
- }
195
- /**
196
- * Get pool statistics
197
- */
198
- getStats() {
199
- const healthy = this.connections.filter(c => c.isHealthy).length;
200
- return {
201
- size: this.connections.length,
202
- healthy,
203
- utilization: this.connections.length / this.maxSize
204
- };
205
- }
206
- /**
207
- * Drain and close all connections
208
- */
209
- async drain() {
210
- if (this.cleanupInterval) {
211
- clearInterval(this.cleanupInterval);
212
- this.cleanupInterval = null;
213
- }
214
- const closePromises = this.connections.map(conn => this.closeConnection(conn));
215
- await Promise.all(closePromises);
216
- this.connections = [];
217
- }
218
- /**
219
- * Cleanup idle connections
220
- */
221
- cleanup() {
222
- const now = Date.now();
223
- const toRemove = [];
224
- for (const conn of this.connections) {
225
- const idle = now - conn.lastUsed.getTime();
226
- if (idle > this.idleTimeout && this.connections.length > this.minSize) {
227
- toRemove.push(conn);
228
- }
229
- }
230
- // Remove idle connections
231
- toRemove.forEach(conn => {
232
- const index = this.connections.indexOf(conn);
233
- if (index > -1) {
234
- this.connections.splice(index, 1);
235
- this.closeConnection(conn);
236
- }
237
- });
238
- }
239
- /**
240
- * Create a new connection (placeholder - implemented in QUICTransport)
241
- */
242
- async createConnection() {
243
- return {
244
- id: `conn-${Date.now()}-${Math.random()}`,
245
- session: new http.Agent({ keepAlive: true }),
246
- endpoint: '',
247
- protocol: 'http1',
248
- createdAt: new Date(),
249
- lastUsed: new Date(),
250
- requestCount: 0,
251
- isHealthy: true,
252
- streams: new Set()
253
- };
254
- }
255
- /**
256
- * Close a connection
257
- */
258
- async closeConnection(conn) {
259
- try {
260
- if (conn.protocol === 'http2') {
261
- // HTTP/2 session
262
- if (conn.session && typeof conn.session.close === 'function') {
263
- conn.session.close();
264
- }
265
- }
266
- else {
267
- // HTTP/1.1 agent
268
- if (conn.session && typeof conn.session.destroy === 'function') {
269
- conn.session.destroy();
270
- }
271
- }
272
- }
273
- catch (error) {
274
- // Ignore errors during cleanup
275
- }
276
- }
277
- sleep(ms) {
278
- return new Promise(resolve => setTimeout(resolve, ms));
279
- }
280
- }
281
- exports.ConnectionPool = ConnectionPool;
282
- /**
283
- * QUIC Transport Layer
284
- * Main transport implementation with HTTP/2 fallback
285
- */
286
- class QUICTransport extends events_1.EventEmitter {
287
- constructor(config) {
288
- super();
289
- this.pools = new Map();
290
- this.requests = [];
291
- this.latencyBuffer = [];
292
- this.config = {
293
- ...config,
294
- poolSize: config.poolSize || { min: 2, max: 10 },
295
- circuitBreaker: config.circuitBreaker || {
296
- failureThreshold: 5,
297
- successThreshold: 2,
298
- timeout: 60000
299
- }
300
- };
301
- this.circuitBreaker = new CircuitBreaker(this.config.circuitBreaker);
302
- this.metrics = {
303
- totalRequests: 0,
304
- successfulRequests: 0,
305
- failedRequests: 0,
306
- avgLatency: 0,
307
- p50Latency: 0,
308
- p95Latency: 0,
309
- p99Latency: 0,
310
- bytesSent: 0,
311
- bytesReceived: 0,
312
- circuitBreakerState: 'closed',
313
- activeConnections: 0,
314
- poolUtilization: 0
315
- };
316
- }
317
- /**
318
- * Connect to an endpoint
319
- */
320
- async connect(endpoint) {
321
- const pool = this.getOrCreatePool(endpoint);
322
- const conn = await pool.acquire();
323
- // Create actual connection if needed
324
- if (!conn.endpoint) {
325
- const url = new URL(endpoint);
326
- const protocol = await this.detectBestProtocol(url);
327
- try {
328
- if (protocol === 'http2') {
329
- conn.session = await this.createHTTP2Connection(url);
330
- conn.protocol = 'http2';
331
- }
332
- else {
333
- conn.session = this.createHTTP1Connection(url);
334
- conn.protocol = 'http1';
335
- }
336
- conn.endpoint = endpoint;
337
- }
338
- catch (error) {
339
- pool.markUnhealthy(conn);
340
- throw error;
341
- }
342
- }
343
- return conn;
344
- }
345
- /**
346
- * Disconnect from an endpoint
347
- */
348
- async disconnect(endpoint) {
349
- const pool = this.pools.get(endpoint);
350
- if (pool) {
351
- await pool.drain();
352
- this.pools.delete(endpoint);
353
- }
354
- }
355
- /**
356
- * Send data to endpoint
357
- */
358
- async send(endpoint, data) {
359
- return this.withCircuitBreaker(async () => {
360
- return this.withRetry(async () => {
361
- const conn = await this.connect(endpoint);
362
- const startTime = Date.now();
363
- try {
364
- let response;
365
- if (conn.protocol === 'http2') {
366
- response = await this.sendHTTP2(conn, data);
367
- }
368
- else {
369
- response = await this.sendHTTP1(conn, endpoint, data);
370
- }
371
- this.recordRequest(startTime, true);
372
- this.emit('request:success', { endpoint, latency: Date.now() - startTime });
373
- return response;
374
- }
375
- catch (error) {
376
- this.recordRequest(startTime, false);
377
- this.emit('request:failure', { endpoint, error });
378
- throw error;
379
- }
380
- finally {
381
- const pool = this.pools.get(endpoint);
382
- if (pool) {
383
- pool.release(conn);
384
- }
385
- }
386
- }, this.config.retryAttempts);
387
- });
388
- }
389
- /**
390
- * Check connection health
391
- */
392
- async healthCheck(endpoint) {
393
- const pool = this.pools.get(endpoint);
394
- if (!pool) {
395
- return {
396
- latency: Infinity,
397
- packetLoss: 1,
398
- throughput: 0,
399
- activeStreams: 0,
400
- lastHealthCheck: new Date(),
401
- state: 'unhealthy',
402
- protocol: 'http1'
403
- };
404
- }
405
- const stats = pool.getStats();
406
- const recentLatencies = this.latencyBuffer.slice(-100);
407
- const avgLatency = recentLatencies.length > 0
408
- ? recentLatencies.reduce((a, b) => a + b, 0) / recentLatencies.length
409
- : 0;
410
- const successRate = this.metrics.totalRequests > 0
411
- ? this.metrics.successfulRequests / this.metrics.totalRequests
412
- : 0;
413
- let state = 'healthy';
414
- if (successRate < 0.5 || avgLatency > 5000) {
415
- state = 'unhealthy';
416
- }
417
- else if (successRate < 0.9 || avgLatency > 1000) {
418
- state = 'degraded';
419
- }
420
- return {
421
- latency: avgLatency,
422
- packetLoss: 1 - successRate,
423
- throughput: this.calculateThroughput(),
424
- activeStreams: stats.size,
425
- lastHealthCheck: new Date(),
426
- state,
427
- protocol: 'http2' // Assume http2 for now
428
- };
429
- }
430
- /**
431
- * Get transport metrics
432
- */
433
- getMetrics() {
434
- const cbState = this.circuitBreaker.getState();
435
- this.metrics.circuitBreakerState = cbState.state;
436
- let totalConnections = 0;
437
- let totalUtilization = 0;
438
- this.pools.forEach(pool => {
439
- const stats = pool.getStats();
440
- totalConnections += stats.size;
441
- totalUtilization += stats.utilization;
442
- });
443
- this.metrics.activeConnections = totalConnections;
444
- this.metrics.poolUtilization = this.pools.size > 0
445
- ? totalUtilization / this.pools.size
446
- : 0;
447
- // Calculate latency percentiles
448
- if (this.latencyBuffer.length > 0) {
449
- const sorted = [...this.latencyBuffer].sort((a, b) => a - b);
450
- this.metrics.p50Latency = sorted[Math.floor(sorted.length * 0.5)];
451
- this.metrics.p95Latency = sorted[Math.floor(sorted.length * 0.95)];
452
- this.metrics.p99Latency = sorted[Math.floor(sorted.length * 0.99)];
453
- }
454
- return { ...this.metrics };
455
- }
456
- /**
457
- * Execute operation with circuit breaker
458
- */
459
- async withCircuitBreaker(operation) {
460
- return this.circuitBreaker.execute(operation);
461
- }
462
- /**
463
- * Execute operation with retry logic
464
- */
465
- async withRetry(operation, attempts = 3) {
466
- let lastError = null;
467
- for (let i = 0; i < attempts; i++) {
468
- try {
469
- return await operation();
470
- }
471
- catch (error) {
472
- lastError = error;
473
- if (i < attempts - 1) {
474
- // Exponential backoff
475
- const delay = this.config.retryDelay * Math.pow(2, i);
476
- await this.sleep(delay);
477
- this.emit('retry', { attempt: i + 1, delay });
478
- }
479
- }
480
- }
481
- throw lastError || new Error('Operation failed after retries');
482
- }
483
- /**
484
- * Close all connections and cleanup
485
- */
486
- async close() {
487
- const drainPromises = Array.from(this.pools.values()).map(pool => pool.drain());
488
- await Promise.all(drainPromises);
489
- this.pools.clear();
490
- this.removeAllListeners();
491
- }
492
- // ============================================================================
493
- // Private Methods
494
- // ============================================================================
495
- /**
496
- * Get or create connection pool for endpoint
497
- */
498
- getOrCreatePool(endpoint) {
499
- let pool = this.pools.get(endpoint);
500
- if (!pool) {
501
- pool = new ConnectionPool({
502
- minSize: this.config.poolSize.min,
503
- maxSize: this.config.poolSize.max,
504
- idleTimeout: this.config.idleTimeout
505
- });
506
- this.pools.set(endpoint, pool);
507
- }
508
- return pool;
509
- }
510
- /**
511
- * Detect best protocol for endpoint
512
- */
513
- async detectBestProtocol(url) {
514
- // For now, prefer HTTP/2 if available
515
- if (this.config.enableFallback) {
516
- try {
517
- // Quick ALPN check would go here
518
- return 'http2';
519
- }
520
- catch {
521
- return 'http1';
522
- }
523
- }
524
- return 'http2';
525
- }
526
- /**
527
- * Create HTTP/2 connection
528
- */
529
- async createHTTP2Connection(url) {
530
- return new Promise((resolve, reject) => {
531
- const session = http2.connect(url.origin, {
532
- maxOutstandingPings: 10,
533
- maxSessionMemory: 10,
534
- ...this.config.tls
535
- });
536
- session.on('connect', () => resolve(session));
537
- session.on('error', reject);
538
- setTimeout(() => reject(new Error('Connection timeout')), 5000);
539
- });
540
- }
541
- /**
542
- * Create HTTP/1.1 connection
543
- */
544
- createHTTP1Connection(url) {
545
- const options = {
546
- keepAlive: true,
547
- maxSockets: this.config.maxStreams,
548
- ...this.config.tls
549
- };
550
- return url.protocol === 'https:'
551
- ? new https.Agent(options)
552
- : new http.Agent(options);
553
- }
554
- /**
555
- * Send data via HTTP/2
556
- */
557
- async sendHTTP2(conn, data) {
558
- return new Promise((resolve, reject) => {
559
- const session = conn.session;
560
- const req = session.request({
561
- ':method': 'POST',
562
- ':path': '/',
563
- 'content-type': 'application/octet-stream',
564
- 'content-length': data.length
565
- });
566
- const chunks = [];
567
- req.on('response', (headers) => {
568
- const status = headers[':status'];
569
- if (status && status >= 400) {
570
- reject(new Error(`HTTP ${status}`));
571
- }
572
- });
573
- req.on('data', (chunk) => chunks.push(chunk));
574
- req.on('end', () => resolve(Buffer.concat(chunks)));
575
- req.on('error', reject);
576
- req.write(data);
577
- req.end();
578
- // Track stream ID if available
579
- const streamId = req.stream?.id;
580
- if (streamId !== undefined) {
581
- conn.streams.add(streamId);
582
- req.on('close', () => conn.streams.delete(streamId));
583
- }
584
- });
585
- }
586
- /**
587
- * Send data via HTTP/1.1
588
- */
589
- async sendHTTP1(conn, endpoint, data) {
590
- return new Promise((resolve, reject) => {
591
- const url = new URL(endpoint);
592
- const options = {
593
- hostname: url.hostname,
594
- port: url.port,
595
- path: url.pathname,
596
- method: 'POST',
597
- headers: {
598
- 'Content-Type': 'application/octet-stream',
599
- 'Content-Length': data.length
600
- },
601
- agent: conn.session
602
- };
603
- const reqFn = url.protocol === 'https:' ? https.request : http.request;
604
- const req = reqFn(options, (res) => {
605
- const chunks = [];
606
- res.on('data', (chunk) => chunks.push(chunk));
607
- res.on('end', () => {
608
- if (res.statusCode && res.statusCode >= 400) {
609
- reject(new Error(`HTTP ${res.statusCode}`));
610
- }
611
- else {
612
- resolve(Buffer.concat(chunks));
613
- }
614
- });
615
- });
616
- req.on('error', reject);
617
- req.write(data);
618
- req.end();
619
- });
620
- }
621
- /**
622
- * Record request timing
623
- */
624
- recordRequest(startTime, success) {
625
- const latency = Date.now() - startTime;
626
- this.metrics.totalRequests++;
627
- if (success) {
628
- this.metrics.successfulRequests++;
629
- }
630
- else {
631
- this.metrics.failedRequests++;
632
- }
633
- this.latencyBuffer.push(latency);
634
- if (this.latencyBuffer.length > 1000) {
635
- this.latencyBuffer.shift();
636
- }
637
- // Update average latency
638
- this.metrics.avgLatency = this.latencyBuffer.reduce((a, b) => a + b, 0) / this.latencyBuffer.length;
639
- }
640
- /**
641
- * Calculate throughput
642
- */
643
- calculateThroughput() {
644
- const windowMs = 60000; // 1 minute window
645
- const now = Date.now();
646
- const recentRequests = this.requests.filter(r => r.endTime && (now - r.endTime) < windowMs);
647
- if (recentRequests.length === 0)
648
- return 0;
649
- const totalBytes = this.metrics.bytesSent + this.metrics.bytesReceived;
650
- return totalBytes / (windowMs / 1000); // bytes per second
651
- }
652
- /**
653
- * Sleep utility
654
- */
655
- sleep(ms) {
656
- return new Promise(resolve => setTimeout(resolve, ms));
657
- }
658
- /**
659
- * Fallback to HTTP/2 (already implemented as primary)
660
- */
661
- async fallbackToHTTP2(endpoint) {
662
- return this.connect(endpoint);
663
- }
664
- /**
665
- * Fallback to HTTP/1.1
666
- */
667
- async fallbackToHTTP1(endpoint) {
668
- const pool = this.getOrCreatePool(endpoint);
669
- const conn = await pool.acquire();
670
- if (!conn.endpoint) {
671
- const url = new URL(endpoint);
672
- conn.session = this.createHTTP1Connection(url);
673
- conn.protocol = 'http1';
674
- conn.endpoint = endpoint;
675
- }
676
- return conn;
677
- }
678
- }
679
- exports.QUICTransport = QUICTransport;
680
- /**
681
- * Default QUIC configuration
682
- */
683
- exports.DEFAULT_QUIC_CONFIG = {
684
- host: 'localhost',
685
- port: 4433,
686
- maxStreams: 100,
687
- idleTimeout: 30000,
688
- enableFallback: true,
689
- retryAttempts: 3,
690
- retryDelay: 1000,
691
- poolSize: {
692
- min: 2,
693
- max: 10
694
- },
695
- circuitBreaker: {
696
- failureThreshold: 5,
697
- successThreshold: 2,
698
- timeout: 60000
699
- },
700
- enableTLS: false
701
- };
702
- /**
703
- * Create QUIC transport with default configuration
704
- */
705
- function createQUICTransport(config) {
706
- return new QUICTransport({
707
- ...exports.DEFAULT_QUIC_CONFIG,
708
- ...config
709
- });
710
- }
711
- //# sourceMappingURL=QUICTransport.js.map