agentic-qe 1.3.3 → 1.3.5

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 (147) hide show
  1. package/.claude/agents/qe-api-contract-validator.md +20 -0
  2. package/.claude/agents/qe-chaos-engineer.md +20 -0
  3. package/.claude/agents/qe-coverage-analyzer.md +21 -0
  4. package/.claude/agents/qe-deployment-readiness.md +20 -0
  5. package/.claude/agents/qe-flaky-test-hunter.md +20 -0
  6. package/.claude/agents/qe-fleet-commander.md +20 -0
  7. package/.claude/agents/qe-performance-tester.md +21 -0
  8. package/.claude/agents/qe-production-intelligence.md +20 -0
  9. package/.claude/agents/qe-quality-analyzer.md +20 -0
  10. package/.claude/agents/qe-quality-gate.md +20 -0
  11. package/.claude/agents/qe-regression-risk-analyzer.md +20 -0
  12. package/.claude/agents/qe-requirements-validator.md +20 -0
  13. package/.claude/agents/qe-security-scanner.md +21 -0
  14. package/.claude/agents/qe-test-data-architect.md +19 -0
  15. package/.claude/agents/qe-test-executor.md +20 -0
  16. package/.claude/agents/qe-test-generator.md +22 -0
  17. package/.claude/agents/qe-visual-tester.md +22 -0
  18. package/CHANGELOG.md +252 -0
  19. package/README.md +325 -1019
  20. package/README.md.backup-20251026 +1366 -0
  21. package/bin/aqe-mcp +1 -1
  22. package/dist/agents/BaseAgent.js +1 -1
  23. package/dist/agents/BaseAgent.js.map +1 -1
  24. package/dist/agents/CoverageAnalyzerAgent.js +16 -16
  25. package/dist/agents/CoverageAnalyzerAgent.js.map +1 -1
  26. package/dist/agents/FlakyTestHunterAgent.js +1 -1
  27. package/dist/agents/FlakyTestHunterAgent.js.map +1 -1
  28. package/dist/cli/commands/init.d.ts.map +1 -1
  29. package/dist/cli/commands/init.js +71 -37
  30. package/dist/cli/commands/init.js.map +1 -1
  31. package/dist/cli/commands/routing/index.d.ts +1 -1
  32. package/dist/cli/commands/routing/index.d.ts.map +1 -1
  33. package/dist/cli/commands/routing/index.js +29 -19
  34. package/dist/cli/commands/routing/index.js.map +1 -1
  35. package/dist/core/memory/EnhancedAgentDBService.d.ts +127 -0
  36. package/dist/core/memory/EnhancedAgentDBService.d.ts.map +1 -0
  37. package/dist/core/memory/EnhancedAgentDBService.js +298 -0
  38. package/dist/core/memory/EnhancedAgentDBService.js.map +1 -0
  39. package/dist/core/neural/NeuralTrainer.js +2 -2
  40. package/dist/core/neural/NeuralTrainer.js.map +1 -1
  41. package/dist/learning/ExperienceReplayBuffer.d.ts +143 -0
  42. package/dist/learning/ExperienceReplayBuffer.d.ts.map +1 -0
  43. package/dist/learning/ExperienceReplayBuffer.js +255 -0
  44. package/dist/learning/ExperienceReplayBuffer.js.map +1 -0
  45. package/dist/learning/FixRecommendationEngine.d.ts +68 -0
  46. package/dist/learning/FixRecommendationEngine.d.ts.map +1 -0
  47. package/dist/learning/FixRecommendationEngine.js +500 -0
  48. package/dist/learning/FixRecommendationEngine.js.map +1 -0
  49. package/dist/learning/FlakyTestDetector.d.ts +19 -0
  50. package/dist/learning/FlakyTestDetector.d.ts.map +1 -1
  51. package/dist/learning/FlakyTestDetector.js +121 -2
  52. package/dist/learning/FlakyTestDetector.js.map +1 -1
  53. package/dist/learning/LearningEngine.d.ts +50 -1
  54. package/dist/learning/LearningEngine.d.ts.map +1 -1
  55. package/dist/learning/LearningEngine.js +140 -0
  56. package/dist/learning/LearningEngine.js.map +1 -1
  57. package/dist/learning/QLearning.d.ts +154 -0
  58. package/dist/learning/QLearning.d.ts.map +1 -0
  59. package/dist/learning/QLearning.js +337 -0
  60. package/dist/learning/QLearning.js.map +1 -0
  61. package/dist/learning/index.d.ts +4 -0
  62. package/dist/learning/index.d.ts.map +1 -1
  63. package/dist/learning/index.js +7 -0
  64. package/dist/learning/index.js.map +1 -1
  65. package/dist/learning/types.d.ts +11 -0
  66. package/dist/learning/types.d.ts.map +1 -1
  67. package/dist/mcp/streaming/CoverageAnalyzeStreamHandler.d.ts +11 -1
  68. package/dist/mcp/streaming/CoverageAnalyzeStreamHandler.d.ts.map +1 -1
  69. package/dist/mcp/streaming/CoverageAnalyzeStreamHandler.js +12 -0
  70. package/dist/mcp/streaming/CoverageAnalyzeStreamHandler.js.map +1 -1
  71. package/dist/mcp/streaming/TestExecuteStreamHandler.d.ts +10 -1
  72. package/dist/mcp/streaming/TestExecuteStreamHandler.d.ts.map +1 -1
  73. package/dist/mcp/streaming/TestExecuteStreamHandler.js +11 -0
  74. package/dist/mcp/streaming/TestExecuteStreamHandler.js.map +1 -1
  75. package/dist/reasoning/PatternQualityScorer.d.ts +134 -0
  76. package/dist/reasoning/PatternQualityScorer.d.ts.map +1 -0
  77. package/dist/reasoning/PatternQualityScorer.js +340 -0
  78. package/dist/reasoning/PatternQualityScorer.js.map +1 -0
  79. package/dist/reasoning/QEReasoningBank.d.ts +138 -4
  80. package/dist/reasoning/QEReasoningBank.d.ts.map +1 -1
  81. package/dist/reasoning/QEReasoningBank.js +560 -12
  82. package/dist/reasoning/QEReasoningBank.js.map +1 -1
  83. package/dist/reasoning/VectorSimilarity.d.ts +131 -0
  84. package/dist/reasoning/VectorSimilarity.d.ts.map +1 -0
  85. package/dist/reasoning/VectorSimilarity.js +250 -0
  86. package/dist/reasoning/VectorSimilarity.js.map +1 -0
  87. package/dist/reasoning/index.d.ts +8 -1
  88. package/dist/reasoning/index.d.ts.map +1 -1
  89. package/dist/reasoning/index.js +13 -2
  90. package/dist/reasoning/index.js.map +1 -1
  91. package/dist/streaming/BaseStreamHandler.d.ts +89 -0
  92. package/dist/streaming/BaseStreamHandler.d.ts.map +1 -0
  93. package/dist/streaming/BaseStreamHandler.js +168 -0
  94. package/dist/streaming/BaseStreamHandler.js.map +1 -0
  95. package/dist/streaming/TestGenerateStreamHandler.d.ts +103 -0
  96. package/dist/streaming/TestGenerateStreamHandler.d.ts.map +1 -0
  97. package/dist/streaming/TestGenerateStreamHandler.js +321 -0
  98. package/dist/streaming/TestGenerateStreamHandler.js.map +1 -0
  99. package/dist/streaming/index.d.ts +16 -0
  100. package/dist/streaming/index.d.ts.map +1 -0
  101. package/dist/streaming/index.js +39 -0
  102. package/dist/streaming/index.js.map +1 -0
  103. package/dist/utils/__mocks__/Logger.d.ts +26 -0
  104. package/dist/utils/__mocks__/Logger.d.ts.map +1 -0
  105. package/dist/utils/__mocks__/Logger.js +42 -0
  106. package/dist/utils/__mocks__/Logger.js.map +1 -0
  107. package/package.json +15 -3
  108. package/dist/agents/mixins/NeuralCapableMixin.d.ts +0 -130
  109. package/dist/agents/mixins/NeuralCapableMixin.d.ts.map +0 -1
  110. package/dist/agents/mixins/NeuralCapableMixin.js +0 -358
  111. package/dist/agents/mixins/NeuralCapableMixin.js.map +0 -1
  112. package/dist/agents/mixins/QUICCapableMixin.d.ts +0 -34
  113. package/dist/agents/mixins/QUICCapableMixin.d.ts.map +0 -1
  114. package/dist/agents/mixins/QUICCapableMixin.js +0 -346
  115. package/dist/agents/mixins/QUICCapableMixin.js.map +0 -1
  116. package/dist/core/security/CertificateValidator.d.ts +0 -130
  117. package/dist/core/security/CertificateValidator.d.ts.map +0 -1
  118. package/dist/core/security/CertificateValidator.js +0 -376
  119. package/dist/core/security/CertificateValidator.js.map +0 -1
  120. package/dist/core/transport/QUICTransport.d.ts +0 -62
  121. package/dist/core/transport/QUICTransport.d.ts.map +0 -1
  122. package/dist/core/transport/QUICTransport.js +0 -381
  123. package/dist/core/transport/QUICTransport.js.map +0 -1
  124. package/dist/core/transport/SecureQUICTransport.d.ts +0 -71
  125. package/dist/core/transport/SecureQUICTransport.d.ts.map +0 -1
  126. package/dist/core/transport/SecureQUICTransport.js +0 -253
  127. package/dist/core/transport/SecureQUICTransport.js.map +0 -1
  128. package/dist/learning/AdvancedFeatureExtractor.d.ts +0 -123
  129. package/dist/learning/AdvancedFeatureExtractor.d.ts.map +0 -1
  130. package/dist/learning/AdvancedFeatureExtractor.js +0 -423
  131. package/dist/learning/AdvancedFeatureExtractor.js.map +0 -1
  132. package/dist/learning/NeuralPatternMatcher.d.ts +0 -184
  133. package/dist/learning/NeuralPatternMatcher.d.ts.map +0 -1
  134. package/dist/learning/NeuralPatternMatcher.js +0 -702
  135. package/dist/learning/NeuralPatternMatcher.js.map +0 -1
  136. package/dist/learning/NeuralTrainer.d.ts +0 -209
  137. package/dist/learning/NeuralTrainer.d.ts.map +0 -1
  138. package/dist/learning/NeuralTrainer.js +0 -478
  139. package/dist/learning/NeuralTrainer.js.map +0 -1
  140. package/dist/transport/QUICTransport.d.ts +0 -340
  141. package/dist/transport/QUICTransport.d.ts.map +0 -1
  142. package/dist/transport/QUICTransport.js +0 -814
  143. package/dist/transport/QUICTransport.js.map +0 -1
  144. package/dist/transport/UDPTransport.d.ts +0 -348
  145. package/dist/transport/UDPTransport.d.ts.map +0 -1
  146. package/dist/transport/UDPTransport.js +0 -820
  147. package/dist/transport/UDPTransport.js.map +0 -1
@@ -1,814 +0,0 @@
1
- "use strict";
2
- /**
3
- * QUICTransport - High-performance QUIC transport layer for distributed QE fleet coordination
4
- *
5
- * Provides 50-70% latency reduction vs TCP through:
6
- * - 0-RTT connection establishment
7
- * - Multiplexed bidirectional streams
8
- * - Built-in congestion control
9
- * - Automatic TCP fallback for compatibility
10
- *
11
- * @module transport/QUICTransport
12
- * @version 1.0.0
13
- * @since 2025-10-20
14
- */
15
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
- if (k2 === undefined) k2 = k;
17
- var desc = Object.getOwnPropertyDescriptor(m, k);
18
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
- desc = { enumerable: true, get: function() { return m[k]; } };
20
- }
21
- Object.defineProperty(o, k2, desc);
22
- }) : (function(o, m, k, k2) {
23
- if (k2 === undefined) k2 = k;
24
- o[k2] = m[k];
25
- }));
26
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
- Object.defineProperty(o, "default", { enumerable: true, value: v });
28
- }) : function(o, v) {
29
- o["default"] = v;
30
- });
31
- var __importStar = (this && this.__importStar) || (function () {
32
- var ownKeys = function(o) {
33
- ownKeys = Object.getOwnPropertyNames || function (o) {
34
- var ar = [];
35
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
- return ar;
37
- };
38
- return ownKeys(o);
39
- };
40
- return function (mod) {
41
- if (mod && mod.__esModule) return mod;
42
- var result = {};
43
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
- __setModuleDefault(result, mod);
45
- return result;
46
- };
47
- })();
48
- Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.QUICTransport = exports.ConnectionState = exports.TransportMode = void 0;
50
- exports.createQUICTransport = createQUICTransport;
51
- const events_1 = require("events");
52
- const dgram = __importStar(require("dgram"));
53
- const tls = __importStar(require("tls"));
54
- const fs = __importStar(require("fs/promises"));
55
- const crypto = __importStar(require("crypto"));
56
- /**
57
- * Transport mode - QUIC or TCP fallback
58
- */
59
- var TransportMode;
60
- (function (TransportMode) {
61
- TransportMode["QUIC"] = "QUIC";
62
- TransportMode["TCP"] = "TCP";
63
- TransportMode["UNKNOWN"] = "UNKNOWN";
64
- })(TransportMode || (exports.TransportMode = TransportMode = {}));
65
- /**
66
- * Connection state
67
- */
68
- var ConnectionState;
69
- (function (ConnectionState) {
70
- ConnectionState["DISCONNECTED"] = "DISCONNECTED";
71
- ConnectionState["CONNECTING"] = "CONNECTING";
72
- ConnectionState["CONNECTED"] = "CONNECTED";
73
- ConnectionState["RECONNECTING"] = "RECONNECTING";
74
- ConnectionState["FAILED"] = "FAILED";
75
- })(ConnectionState || (exports.ConnectionState = ConnectionState = {}));
76
- /**
77
- * QUICTransport - Production-ready QUIC/TCP transport layer
78
- *
79
- * Features:
80
- * - QUIC protocol with 0-RTT support
81
- * - Automatic TCP fallback
82
- * - Channel-based message routing
83
- * - Bidirectional streaming
84
- * - Connection pooling and multiplexing
85
- * - Comprehensive error handling
86
- * - Performance monitoring
87
- *
88
- * @example
89
- * ```typescript
90
- * const transport = new QUICTransport();
91
- * await transport.initialize({
92
- * host: 'fleet.example.com',
93
- * port: 4433,
94
- * enable0RTT: true
95
- * });
96
- *
97
- * await transport.receive('coordination', (data) => {
98
- * console.log('Received:', data);
99
- * });
100
- *
101
- * await transport.send('coordination', { action: 'sync', agentId: 'qe-01' });
102
- * ```
103
- */
104
- class QUICTransport extends events_1.EventEmitter {
105
- constructor() {
106
- super();
107
- this.mode = TransportMode.UNKNOWN;
108
- this.state = ConnectionState.DISCONNECTED;
109
- // QUIC/UDP socket
110
- this.quicSocket = null;
111
- // TCP fallback socket
112
- this.tcpSocket = null;
113
- // TLS credentials
114
- this.tlsCert = null;
115
- this.tlsKey = null;
116
- // Channel subscriptions
117
- this.channelCallbacks = new Map();
118
- // Active streams
119
- this.streams = new Map();
120
- // Performance metrics
121
- this.metrics = {
122
- mode: TransportMode.UNKNOWN,
123
- state: ConnectionState.DISCONNECTED,
124
- messagessent: 0,
125
- messagesReceived: 0,
126
- bytesTransferred: 0,
127
- averageLatency: 0,
128
- connectionUptime: 0,
129
- activeStreams: 0,
130
- failedAttempts: 0
131
- };
132
- // Latency tracking
133
- this.latencySamples = [];
134
- this.connectionStartTime = 0;
135
- // Keep-alive timer
136
- this.keepAliveTimer = null;
137
- // Retry state
138
- this.retryCount = 0;
139
- this.isReconnecting = false;
140
- this.config = this.getDefaultConfig();
141
- }
142
- /**
143
- * Get default configuration with sensible defaults
144
- * @private
145
- */
146
- getDefaultConfig() {
147
- return {
148
- host: 'localhost',
149
- port: 4433,
150
- certPath: '',
151
- keyPath: '',
152
- enable0RTT: true,
153
- enableTCPFallback: true,
154
- connectionTimeout: 5000,
155
- maxRetries: 3,
156
- retryDelay: 1000,
157
- keepAlive: true,
158
- keepAliveInterval: 30000,
159
- maxConcurrentStreams: 100,
160
- debug: false
161
- };
162
- }
163
- /**
164
- * Initialize QUIC transport with configuration
165
- *
166
- * Attempts QUIC connection first, falls back to TCP if:
167
- * - QUIC not supported by network
168
- * - Connection fails after retries
169
- * - UDP blocked by firewall
170
- *
171
- * @param config - Transport configuration options
172
- * @throws {Error} If both QUIC and TCP connections fail
173
- *
174
- * @example
175
- * ```typescript
176
- * await transport.initialize({
177
- * host: 'fleet.example.com',
178
- * port: 4433,
179
- * certPath: '/path/to/cert.pem',
180
- * keyPath: '/path/to/key.pem',
181
- * enable0RTT: true
182
- * });
183
- * ```
184
- */
185
- async initialize(config) {
186
- this.config = { ...this.getDefaultConfig(), ...config };
187
- this.state = ConnectionState.CONNECTING;
188
- this.emit('stateChange', this.state);
189
- this.log('Initializing QUIC transport', { config: this.config });
190
- try {
191
- // Load or generate TLS credentials
192
- await this.loadTLSCredentials();
193
- // Try QUIC first
194
- try {
195
- await this.connectQUIC();
196
- this.mode = TransportMode.QUIC;
197
- this.state = ConnectionState.CONNECTED;
198
- this.connectionStartTime = Date.now();
199
- this.log('QUIC connection established successfully');
200
- this.emit('connected', { mode: TransportMode.QUIC });
201
- // Start keep-alive if enabled
202
- if (this.config.keepAlive) {
203
- this.startKeepAlive();
204
- }
205
- return;
206
- }
207
- catch (quicError) {
208
- this.log('QUIC connection failed', { error: quicError });
209
- this.metrics.failedAttempts++;
210
- // Try TCP fallback if enabled
211
- if (this.config.enableTCPFallback) {
212
- this.log('Attempting TCP fallback');
213
- await this.connectTCP();
214
- this.mode = TransportMode.TCP;
215
- this.state = ConnectionState.CONNECTED;
216
- this.connectionStartTime = Date.now();
217
- this.log('TCP fallback connection established');
218
- this.emit('connected', { mode: TransportMode.TCP });
219
- if (this.config.keepAlive) {
220
- this.startKeepAlive();
221
- }
222
- return;
223
- }
224
- throw quicError;
225
- }
226
- }
227
- catch (error) {
228
- this.state = ConnectionState.FAILED;
229
- this.metrics.lastError = error instanceof Error ? error.message : String(error);
230
- this.emit('stateChange', this.state);
231
- throw new Error(`Transport initialization failed: ${error instanceof Error ? error.message : String(error)}`);
232
- }
233
- }
234
- /**
235
- * Load TLS credentials from files or generate self-signed
236
- * @private
237
- */
238
- async loadTLSCredentials() {
239
- try {
240
- if (this.config.certPath && this.config.keyPath) {
241
- // Load from files
242
- this.tlsCert = await fs.readFile(this.config.certPath);
243
- this.tlsKey = await fs.readFile(this.config.keyPath);
244
- this.log('Loaded TLS credentials from files');
245
- }
246
- else {
247
- // Generate self-signed certificate for development
248
- const { cert, key } = await this.generateSelfSignedCert();
249
- this.tlsCert = Buffer.from(cert);
250
- this.tlsKey = Buffer.from(key);
251
- this.log('Generated self-signed TLS certificate');
252
- }
253
- }
254
- catch (error) {
255
- throw new Error(`Failed to load TLS credentials: ${error instanceof Error ? error.message : String(error)}`);
256
- }
257
- }
258
- /**
259
- * Generate self-signed certificate for development
260
- * @private
261
- */
262
- async generateSelfSignedCert() {
263
- // Note: In production, use proper certificate authority
264
- // This is a simplified implementation for development
265
- const { generateKeyPairSync } = crypto;
266
- const { publicKey, privateKey } = generateKeyPairSync('rsa', {
267
- modulusLength: 2048,
268
- publicKeyEncoding: { type: 'spki', format: 'pem' },
269
- privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
270
- });
271
- // Create a basic self-signed certificate
272
- // In production, use proper X.509 certificate generation
273
- const cert = publicKey;
274
- const key = privateKey;
275
- return { cert, key };
276
- }
277
- /**
278
- * Establish QUIC connection over UDP
279
- * @private
280
- */
281
- async connectQUIC() {
282
- return new Promise((resolve, reject) => {
283
- const timeout = setTimeout(() => {
284
- reject(new Error('QUIC connection timeout'));
285
- }, this.config.connectionTimeout);
286
- try {
287
- // Create UDP socket for QUIC
288
- this.quicSocket = dgram.createSocket('udp4');
289
- // Handle socket errors
290
- this.quicSocket.on('error', (error) => {
291
- clearTimeout(timeout);
292
- this.log('QUIC socket error', { error });
293
- reject(error);
294
- });
295
- // Handle incoming messages
296
- this.quicSocket.on('message', (msg, rinfo) => {
297
- this.handleQUICMessage(msg, rinfo);
298
- });
299
- // Bind socket
300
- this.quicSocket.bind(() => {
301
- this.log('QUIC socket bound', {
302
- address: this.quicSocket.address()
303
- });
304
- // Send connection handshake
305
- this.sendQUICHandshake()
306
- .then(() => {
307
- clearTimeout(timeout);
308
- resolve();
309
- })
310
- .catch((error) => {
311
- clearTimeout(timeout);
312
- reject(error);
313
- });
314
- });
315
- }
316
- catch (error) {
317
- clearTimeout(timeout);
318
- reject(error);
319
- }
320
- });
321
- }
322
- /**
323
- * Send QUIC handshake packet with 0-RTT support
324
- * @private
325
- */
326
- async sendQUICHandshake() {
327
- if (!this.quicSocket) {
328
- throw new Error('QUIC socket not initialized');
329
- }
330
- // Simplified QUIC handshake (in production, use proper QUIC library)
331
- const handshake = {
332
- type: 'HANDSHAKE',
333
- version: '1.0',
334
- enable0RTT: this.config.enable0RTT,
335
- timestamp: Date.now()
336
- };
337
- const packet = Buffer.from(JSON.stringify(handshake));
338
- return new Promise((resolve, reject) => {
339
- this.quicSocket.send(packet, 0, packet.length, this.config.port, this.config.host, (error) => {
340
- if (error) {
341
- reject(error);
342
- }
343
- else {
344
- this.log('QUIC handshake sent');
345
- resolve();
346
- }
347
- });
348
- });
349
- }
350
- /**
351
- * Handle incoming QUIC message
352
- * @private
353
- */
354
- handleQUICMessage(msg, rinfo) {
355
- try {
356
- const startTime = Date.now();
357
- const envelope = JSON.parse(msg.toString());
358
- // Update metrics
359
- this.metrics.messagesReceived++;
360
- this.metrics.bytesTransferred += msg.length;
361
- // Calculate latency
362
- const latency = Date.now() - envelope.timestamp;
363
- this.latencySamples.push(latency);
364
- if (this.latencySamples.length > 100) {
365
- this.latencySamples.shift();
366
- }
367
- this.metrics.averageLatency =
368
- this.latencySamples.reduce((a, b) => a + b, 0) / this.latencySamples.length;
369
- // Route to channel callbacks
370
- this.routeMessage(envelope);
371
- this.log('QUIC message received', {
372
- channel: envelope.channel,
373
- latency: `${latency}ms`,
374
- from: rinfo
375
- });
376
- }
377
- catch (error) {
378
- this.log('Error handling QUIC message', { error });
379
- this.emit('error', error);
380
- }
381
- }
382
- /**
383
- * Establish TCP fallback connection
384
- * @private
385
- */
386
- async connectTCP() {
387
- return new Promise((resolve, reject) => {
388
- const timeout = setTimeout(() => {
389
- reject(new Error('TCP connection timeout'));
390
- }, this.config.connectionTimeout);
391
- try {
392
- // Create TCP socket with TLS
393
- this.tcpSocket = tls.connect({
394
- host: this.config.host,
395
- port: this.config.port,
396
- cert: this.tlsCert,
397
- key: this.tlsKey,
398
- rejectUnauthorized: false // For self-signed certs in development
399
- });
400
- // Handle connection events
401
- this.tcpSocket.on('secureConnect', () => {
402
- clearTimeout(timeout);
403
- this.log('TCP connection established');
404
- resolve();
405
- });
406
- this.tcpSocket.on('error', (error) => {
407
- clearTimeout(timeout);
408
- this.log('TCP socket error', { error });
409
- reject(error);
410
- });
411
- this.tcpSocket.on('data', (data) => {
412
- this.handleTCPMessage(data);
413
- });
414
- this.tcpSocket.on('close', () => {
415
- this.log('TCP connection closed');
416
- this.handleDisconnect();
417
- });
418
- }
419
- catch (error) {
420
- clearTimeout(timeout);
421
- reject(error);
422
- }
423
- });
424
- }
425
- /**
426
- * Handle incoming TCP message
427
- * @private
428
- */
429
- handleTCPMessage(data) {
430
- try {
431
- const envelope = JSON.parse(data.toString());
432
- // Update metrics
433
- this.metrics.messagesReceived++;
434
- this.metrics.bytesTransferred += data.length;
435
- // Calculate latency
436
- const latency = Date.now() - envelope.timestamp;
437
- this.latencySamples.push(latency);
438
- if (this.latencySamples.length > 100) {
439
- this.latencySamples.shift();
440
- }
441
- this.metrics.averageLatency =
442
- this.latencySamples.reduce((a, b) => a + b, 0) / this.latencySamples.length;
443
- // Route to channel callbacks
444
- this.routeMessage(envelope);
445
- this.log('TCP message received', {
446
- channel: envelope.channel,
447
- latency: `${latency}ms`
448
- });
449
- }
450
- catch (error) {
451
- this.log('Error handling TCP message', { error });
452
- this.emit('error', error);
453
- }
454
- }
455
- /**
456
- * Route message to channel callbacks
457
- * @private
458
- */
459
- routeMessage(envelope) {
460
- const callbacks = this.channelCallbacks.get(envelope.channel);
461
- if (callbacks && callbacks.size > 0) {
462
- callbacks.forEach((callback) => {
463
- try {
464
- callback(envelope.data);
465
- }
466
- catch (error) {
467
- this.log('Error in channel callback', { channel: envelope.channel, error });
468
- this.emit('error', error);
469
- }
470
- });
471
- }
472
- }
473
- /**
474
- * Send message on specified channel
475
- *
476
- * Automatically routes message through active transport (QUIC or TCP).
477
- * Includes retry logic and error handling.
478
- *
479
- * @param channel - Channel name for routing
480
- * @param data - Message data (any JSON-serializable object)
481
- * @throws {Error} If transport not connected or send fails
482
- *
483
- * @example
484
- * ```typescript
485
- * await transport.send('coordination', {
486
- * action: 'sync',
487
- * agentId: 'qe-01',
488
- * timestamp: Date.now()
489
- * });
490
- * ```
491
- */
492
- async send(channel, data) {
493
- if (this.state !== ConnectionState.CONNECTED) {
494
- throw new Error(`Cannot send: transport not connected (state: ${this.state})`);
495
- }
496
- const envelope = {
497
- channel,
498
- data,
499
- timestamp: Date.now(),
500
- messageId: this.generateMessageId()
501
- };
502
- const message = Buffer.from(JSON.stringify(envelope));
503
- try {
504
- if (this.mode === TransportMode.QUIC && this.quicSocket) {
505
- await this.sendQUICMessage(message);
506
- }
507
- else if (this.mode === TransportMode.TCP && this.tcpSocket) {
508
- await this.sendTCPMessage(message);
509
- }
510
- else {
511
- throw new Error('No active transport connection');
512
- }
513
- // Update metrics
514
- this.metrics.messagessent++;
515
- this.metrics.bytesTransferred += message.length;
516
- this.log('Message sent', { channel, mode: this.mode });
517
- }
518
- catch (error) {
519
- this.log('Error sending message', { channel, error });
520
- // Attempt retry with exponential backoff
521
- if (this.retryCount < this.config.maxRetries) {
522
- this.retryCount++;
523
- const delay = this.config.retryDelay * Math.pow(2, this.retryCount - 1);
524
- this.log('Retrying send', { attempt: this.retryCount, delay });
525
- await new Promise(resolve => setTimeout(resolve, delay));
526
- return this.send(channel, data);
527
- }
528
- throw new Error(`Failed to send message after ${this.config.maxRetries} retries: ${error instanceof Error ? error.message : String(error)}`);
529
- }
530
- }
531
- /**
532
- * Send message via QUIC
533
- * @private
534
- */
535
- async sendQUICMessage(message) {
536
- if (!this.quicSocket) {
537
- throw new Error('QUIC socket not available');
538
- }
539
- return new Promise((resolve, reject) => {
540
- this.quicSocket.send(message, 0, message.length, this.config.port, this.config.host, (error) => {
541
- if (error) {
542
- reject(error);
543
- }
544
- else {
545
- resolve();
546
- }
547
- });
548
- });
549
- }
550
- /**
551
- * Send message via TCP
552
- * @private
553
- */
554
- async sendTCPMessage(message) {
555
- if (!this.tcpSocket || this.tcpSocket.destroyed) {
556
- throw new Error('TCP socket not available');
557
- }
558
- return new Promise((resolve, reject) => {
559
- this.tcpSocket.write(message, (error) => {
560
- if (error) {
561
- reject(error);
562
- }
563
- else {
564
- resolve();
565
- }
566
- });
567
- });
568
- }
569
- /**
570
- * Register callback for channel messages
571
- *
572
- * Supports multiple callbacks per channel for pub/sub pattern.
573
- *
574
- * @param channel - Channel name to subscribe to
575
- * @param callback - Function to call when message received
576
- *
577
- * @example
578
- * ```typescript
579
- * await transport.receive('coordination', (data) => {
580
- * console.log('Coordination event:', data);
581
- * });
582
- *
583
- * await transport.receive('metrics', (data) => {
584
- * console.log('Performance metrics:', data);
585
- * });
586
- * ```
587
- */
588
- async receive(channel, callback) {
589
- if (!this.channelCallbacks.has(channel)) {
590
- this.channelCallbacks.set(channel, new Set());
591
- }
592
- this.channelCallbacks.get(channel).add(callback);
593
- // Update stream metadata
594
- const streamId = this.generateStreamId(channel);
595
- if (!this.streams.has(streamId)) {
596
- this.streams.set(streamId, {
597
- streamId,
598
- channel,
599
- created: Date.now(),
600
- lastActivity: Date.now(),
601
- messageCount: 0
602
- });
603
- this.metrics.activeStreams = this.streams.size;
604
- }
605
- this.log('Registered channel callback', { channel, totalCallbacks: this.channelCallbacks.get(channel).size });
606
- }
607
- /**
608
- * Unregister callback from channel
609
- *
610
- * @param channel - Channel name
611
- * @param callback - Callback function to remove
612
- */
613
- unsubscribe(channel, callback) {
614
- const callbacks = this.channelCallbacks.get(channel);
615
- if (callbacks) {
616
- callbacks.delete(callback);
617
- if (callbacks.size === 0) {
618
- this.channelCallbacks.delete(channel);
619
- // Clean up stream metadata
620
- const streamId = this.generateStreamId(channel);
621
- this.streams.delete(streamId);
622
- this.metrics.activeStreams = this.streams.size;
623
- }
624
- this.log('Unregistered channel callback', { channel });
625
- }
626
- }
627
- /**
628
- * Close transport connection gracefully
629
- *
630
- * Cleanup includes:
631
- * - Closing active sockets
632
- * - Clearing subscriptions
633
- * - Stopping keep-alive timer
634
- * - Emitting disconnect event
635
- *
636
- * @example
637
- * ```typescript
638
- * await transport.close();
639
- * console.log('Transport closed successfully');
640
- * ```
641
- */
642
- async close() {
643
- this.log('Closing transport connection');
644
- try {
645
- // Stop keep-alive
646
- if (this.keepAliveTimer) {
647
- clearInterval(this.keepAliveTimer);
648
- this.keepAliveTimer = null;
649
- }
650
- // Close QUIC socket
651
- if (this.quicSocket) {
652
- this.quicSocket.close();
653
- this.quicSocket = null;
654
- }
655
- // Close TCP socket
656
- if (this.tcpSocket) {
657
- this.tcpSocket.destroy();
658
- this.tcpSocket = null;
659
- }
660
- // Clear subscriptions
661
- this.channelCallbacks.clear();
662
- this.streams.clear();
663
- // Update state
664
- this.state = ConnectionState.DISCONNECTED;
665
- this.mode = TransportMode.UNKNOWN;
666
- this.metrics.activeStreams = 0;
667
- this.emit('disconnected');
668
- this.log('Transport closed successfully');
669
- }
670
- catch (error) {
671
- this.log('Error closing transport', { error });
672
- throw error;
673
- }
674
- }
675
- /**
676
- * Check if transport is connected
677
- *
678
- * @returns true if connected via QUIC or TCP, false otherwise
679
- */
680
- isConnected() {
681
- return this.state === ConnectionState.CONNECTED;
682
- }
683
- /**
684
- * Get current transport mode
685
- *
686
- * @returns Current transport mode (QUIC, TCP, or UNKNOWN)
687
- */
688
- getMode() {
689
- return this.mode;
690
- }
691
- /**
692
- * Get connection state
693
- *
694
- * @returns Current connection state
695
- */
696
- getState() {
697
- return this.state;
698
- }
699
- /**
700
- * Get performance metrics
701
- *
702
- * Includes:
703
- * - Messages sent/received
704
- * - Average latency
705
- * - Connection uptime
706
- * - Active streams
707
- * - Failed attempts
708
- *
709
- * @returns Current transport metrics
710
- */
711
- getMetrics() {
712
- return {
713
- ...this.metrics,
714
- mode: this.mode,
715
- state: this.state,
716
- connectionUptime: this.connectionStartTime
717
- ? Date.now() - this.connectionStartTime
718
- : 0
719
- };
720
- }
721
- /**
722
- * Handle disconnection and attempt reconnect
723
- * @private
724
- */
725
- async handleDisconnect() {
726
- if (this.isReconnecting) {
727
- return;
728
- }
729
- this.log('Connection lost, attempting reconnect');
730
- this.state = ConnectionState.RECONNECTING;
731
- this.isReconnecting = true;
732
- this.emit('stateChange', this.state);
733
- try {
734
- await this.initialize(this.config);
735
- this.isReconnecting = false;
736
- this.retryCount = 0;
737
- this.emit('reconnected');
738
- }
739
- catch (error) {
740
- this.log('Reconnection failed', { error });
741
- this.isReconnecting = false;
742
- this.state = ConnectionState.FAILED;
743
- this.emit('stateChange', this.state);
744
- }
745
- }
746
- /**
747
- * Start keep-alive timer
748
- * @private
749
- */
750
- startKeepAlive() {
751
- if (this.keepAliveTimer) {
752
- clearInterval(this.keepAliveTimer);
753
- }
754
- this.keepAliveTimer = setInterval(async () => {
755
- try {
756
- await this.send('__keepalive__', { timestamp: Date.now() });
757
- this.log('Keep-alive sent');
758
- }
759
- catch (error) {
760
- this.log('Keep-alive failed', { error });
761
- this.handleDisconnect();
762
- }
763
- }, this.config.keepAliveInterval);
764
- }
765
- /**
766
- * Generate unique message ID
767
- * @private
768
- */
769
- generateMessageId() {
770
- return `${Date.now()}-${crypto.randomBytes(8).toString('hex')}`;
771
- }
772
- /**
773
- * Generate stream ID from channel
774
- * @private
775
- */
776
- generateStreamId(channel) {
777
- return crypto.createHash('sha256').update(channel).digest('hex').substring(0, 16);
778
- }
779
- /**
780
- * Debug logging
781
- * @private
782
- */
783
- log(message, data) {
784
- if (this.config.debug) {
785
- const timestamp = new Date().toISOString();
786
- console.log(`[QUICTransport ${timestamp}] ${message}`, data || '');
787
- }
788
- this.emit('log', { message, data, timestamp: Date.now() });
789
- }
790
- }
791
- exports.QUICTransport = QUICTransport;
792
- /**
793
- * Create and initialize QUIC transport
794
- *
795
- * Convenience factory function for quick setup.
796
- *
797
- * @param config - Transport configuration
798
- * @returns Initialized QUICTransport instance
799
- *
800
- * @example
801
- * ```typescript
802
- * const transport = await createQUICTransport({
803
- * host: 'fleet.example.com',
804
- * port: 4433,
805
- * enable0RTT: true
806
- * });
807
- * ```
808
- */
809
- async function createQUICTransport(config) {
810
- const transport = new QUICTransport();
811
- await transport.initialize(config);
812
- return transport;
813
- }
814
- //# sourceMappingURL=QUICTransport.js.map