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