langmart-gateway-type3 3.0.41 → 3.0.43

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.
@@ -16,25 +16,13 @@ const local_vault_1 = require("./local-vault");
16
16
  const gateway_config_1 = require("./gateway-config");
17
17
  const headless_session_1 = require("./headless-session");
18
18
  const gateway_mode_1 = require("./gateway-mode");
19
- /**
20
- * Type 3 Gateway Server
21
- * Seller-managed gateway deployed on seller's infrastructure
22
- *
23
- * Key Differences from Type 2:
24
- * - Uses local vault for provider credentials (NOT central database)
25
- * - Seller manages their own API keys
26
- * - More privacy and control for sellers
27
- *
28
- * Similarities to Type 2:
29
- * - Same WebSocket communication protocol with Type 1
30
- * - Same request/response format
31
- * - Same registration and heartbeat mechanisms
32
- */
33
19
  class Type3GatewayServer extends events_1.EventEmitter {
34
20
  constructor(config) {
35
21
  super();
36
22
  this.wss = null;
37
- this.marketplaceWs = null;
23
+ this.registryWs = null; // Primary connection (backward compat)
24
+ // Multi-connect: Map of server connections (serverId -> connection)
25
+ this.serverConnections = new Map();
38
26
  this.activeRequests = new Map();
39
27
  this.healthCheckInterval = null;
40
28
  // Version loaded dynamically - works from both source and dist folders
@@ -66,8 +54,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
66
54
  this.isShuttingDown = false;
67
55
  this.headlessSessionManager = null; // For remote automation sessions
68
56
  this.port = config.port;
69
- this.marketplaceUrl = config.marketplaceUrl || 'wss://control.marketplace.ai';
70
- this.marketplaceApiUrl = config.marketplaceUrl?.replace('wss://', 'https://').replace('control.', 'api.') || 'https://api.marketplace.ai';
57
+ this.registryUrl = config.registryUrl || 'wss://control.registry.ai';
58
+ this.registryApiUrl = config.registryUrl?.replace('wss://', 'https://').replace('control.', 'api.') || 'https://api.registry.ai';
71
59
  // Set gateway mode (defaults to FULL for backward compatibility)
72
60
  this.gatewayMode = config.mode ?? gateway_mode_1.GatewayMode.FULL;
73
61
  this.enableRemoteLLMSession = config.enableRemoteLLMSession ?? true;
@@ -142,8 +130,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
142
130
  console.log(`[${this.nodeId}] Starting Type 3 Gateway Server on port ${this.port}`);
143
131
  // 1. Start management REST API server for CLI
144
132
  await this.startManagementServer();
145
- // 2. Connect to marketplace control plane (primary function)
146
- await this.connectToMarketplace();
133
+ // 2. Connect to all inference servers (Multi-Connect architecture)
134
+ // This discovers all Type 0/Type 1 servers and connects to each
135
+ await this.connectToAllServers();
147
136
  // 3. Load credentials from local vault (only if LLM routing is enabled)
148
137
  if (this.enableLLMRouting) {
149
138
  await this.loadCredentials();
@@ -155,11 +144,234 @@ class Type3GatewayServer extends events_1.EventEmitter {
155
144
  }
156
145
  // 5. Start health monitoring
157
146
  this.startHealthMonitoring();
158
- // 6. Register with marketplace (includes tool discovery)
147
+ // 6. Register with registry (includes tool discovery)
159
148
  await this.registerGateway();
160
149
  console.log(`[${this.nodeId}] Type 3 Gateway ready and registered`);
161
150
  console.log(`[${this.nodeId}] Management API: http://localhost:${this.port}`);
162
151
  }
152
+ /**
153
+ * Discover all available inference servers from the registry
154
+ * This enables Type 3 Multi-Connect architecture
155
+ */
156
+ async discoverInferenceServers() {
157
+ try {
158
+ // Convert WebSocket URL to HTTP for API call
159
+ const httpUrl = this.registryUrl
160
+ .replace('ws://', 'http://')
161
+ .replace('wss://', 'https://');
162
+ const discoveryUrl = `${httpUrl}/api/public/inference-servers`;
163
+ console.log(`[${this.nodeId}] Discovering inference servers from ${discoveryUrl}...`);
164
+ const response = await axios_1.default.get(discoveryUrl, {
165
+ timeout: 5000,
166
+ headers: {
167
+ 'Authorization': `Bearer ${this.apiKey}`
168
+ }
169
+ });
170
+ if (response.data?.success && Array.isArray(response.data.servers)) {
171
+ const servers = response.data.servers;
172
+ console.log(`[${this.nodeId}] Discovered ${servers.length} inference servers:`);
173
+ servers.forEach(s => {
174
+ console.log(`[${this.nodeId}] - ${s.name} (${s.serverType}:${s.port}) ${s.isActive ? '[ACTIVE]' : ''}`);
175
+ });
176
+ return servers;
177
+ }
178
+ console.log(`[${this.nodeId}] No servers discovered, falling back to single connection`);
179
+ return [];
180
+ }
181
+ catch (error) {
182
+ console.log(`[${this.nodeId}] Server discovery failed: ${error.message}, using single connection`);
183
+ return [];
184
+ }
185
+ }
186
+ /**
187
+ * Connect to all discovered inference servers (Multi-Connect)
188
+ */
189
+ async connectToAllServers() {
190
+ const servers = await this.discoverInferenceServers();
191
+ if (servers.length === 0) {
192
+ // Fallback to single connection using registryUrl
193
+ console.log(`[${this.nodeId}] No servers discovered, using single connection to ${this.registryUrl}`);
194
+ await this.connectToRegistry();
195
+ return;
196
+ }
197
+ // Connect to ALL servers in parallel
198
+ console.log(`[${this.nodeId}] Connecting to ${servers.length} inference servers...`);
199
+ const connectionPromises = servers.map(async (server) => {
200
+ try {
201
+ await this.connectToServer(server);
202
+ }
203
+ catch (error) {
204
+ console.error(`[${this.nodeId}] Failed to connect to ${server.name}: ${error.message}`);
205
+ }
206
+ });
207
+ await Promise.allSettled(connectionPromises);
208
+ // Check how many connections succeeded
209
+ const connectedCount = Array.from(this.serverConnections.values())
210
+ .filter(c => c.ws?.readyState === ws_1.default.OPEN).length;
211
+ console.log(`[${this.nodeId}] Connected to ${connectedCount}/${servers.length} inference servers`);
212
+ // If no connections succeeded, try the primary registryUrl
213
+ if (connectedCount === 0) {
214
+ console.log(`[${this.nodeId}] No multi-connect succeeded, falling back to ${this.registryUrl}`);
215
+ await this.connectToRegistry();
216
+ }
217
+ }
218
+ /**
219
+ * Connect to a specific inference server
220
+ */
221
+ async connectToServer(server) {
222
+ return new Promise((resolve, reject) => {
223
+ let settled = false;
224
+ console.log(`[${this.nodeId}] Connecting to ${server.name} at ${server.websocketUrl}...`);
225
+ const ws = new ws_1.default(server.websocketUrl, {
226
+ headers: {
227
+ 'X-Gateway-Type': '3',
228
+ 'X-Instance-ID': this.instanceId,
229
+ 'X-Node-ID': this.nodeId,
230
+ 'X-Version': this.currentVersion
231
+ }
232
+ });
233
+ // Preserve reconnect attempts from existing connection (for proper backoff)
234
+ const existingConnection = this.serverConnections.get(server.id);
235
+ const reconnectAttempts = existingConnection?.reconnectAttempts || 0;
236
+ const reconnectInterval = existingConnection?.reconnectInterval || null;
237
+ // Track this connection (preserving reconnect state)
238
+ const connection = {
239
+ serverId: server.id,
240
+ serverType: server.serverType,
241
+ port: server.port,
242
+ ws: ws,
243
+ isAuthenticated: false,
244
+ reconnectAttempts: reconnectAttempts,
245
+ reconnectInterval: reconnectInterval
246
+ };
247
+ this.serverConnections.set(server.id, connection);
248
+ ws.on('open', () => {
249
+ console.log(`[${this.nodeId}] ✅ Connected to ${server.name} (${server.serverType}:${server.port})`);
250
+ // Reset reconnect state on successful connection
251
+ connection.reconnectAttempts = 0;
252
+ if (connection.reconnectInterval) {
253
+ clearTimeout(connection.reconnectInterval);
254
+ connection.reconnectInterval = null;
255
+ }
256
+ // Set as primary if this is the active server or first connection
257
+ if (server.isActive || !this.registryWs) {
258
+ this.registryWs = ws;
259
+ }
260
+ if (!settled) {
261
+ settled = true;
262
+ resolve();
263
+ }
264
+ });
265
+ ws.on('message', (data) => {
266
+ this.handleRegistryMessage(data.toString(), server.id);
267
+ });
268
+ ws.on('error', (error) => {
269
+ console.error(`[${this.nodeId}] ❌ Connection error to ${server.name}:`, error.message);
270
+ if (!settled) {
271
+ settled = true;
272
+ reject(error);
273
+ }
274
+ });
275
+ ws.on('close', (code, reason) => {
276
+ const reasonStr = reason ? (Buffer.isBuffer(reason) ? reason.toString() : String(reason)) : 'unknown';
277
+ console.log(`[${this.nodeId}] 🔌 Disconnected from ${server.name} (code: ${code}, reason: ${reasonStr})`);
278
+ connection.isAuthenticated = false;
279
+ // Handle reconnection for this specific server
280
+ this.handleServerDisconnection(server);
281
+ });
282
+ });
283
+ }
284
+ /**
285
+ * Handle disconnection from a specific server and schedule reconnection
286
+ */
287
+ handleServerDisconnection(server) {
288
+ const connection = this.serverConnections.get(server.id);
289
+ if (!connection || this.isShuttingDown)
290
+ return;
291
+ // Clear existing reconnect interval
292
+ if (connection.reconnectInterval) {
293
+ clearTimeout(connection.reconnectInterval);
294
+ }
295
+ connection.reconnectAttempts++;
296
+ const delay = Math.min(this.reconnectDelay * connection.reconnectAttempts, 60000);
297
+ console.log(`[${this.nodeId}] Scheduling reconnection to ${server.name} in ${delay / 1000}s (attempt ${connection.reconnectAttempts})`);
298
+ connection.reconnectInterval = setTimeout(async () => {
299
+ try {
300
+ await this.connectToServer(server);
301
+ await this.registerWithServer(server.id);
302
+ // Note: reconnectAttempts is reset in the 'open' handler of connectToServer
303
+ }
304
+ catch (error) {
305
+ console.error(`[${this.nodeId}] Reconnection to ${server.name} failed:`, error.message);
306
+ this.handleServerDisconnection(server);
307
+ }
308
+ }, delay);
309
+ }
310
+ /**
311
+ * Register gateway with a specific server
312
+ */
313
+ async registerWithServer(serverId) {
314
+ const connection = this.serverConnections.get(serverId);
315
+ if (!connection?.ws || connection.ws.readyState !== ws_1.default.OPEN) {
316
+ return;
317
+ }
318
+ // Use same registration message format
319
+ const registrationMessage = await this.buildRegistrationMessage();
320
+ connection.ws.send(JSON.stringify(registrationMessage));
321
+ }
322
+ /**
323
+ * Register gateway with all connected servers
324
+ */
325
+ async registerWithAllServers() {
326
+ const registrationMessage = await this.buildRegistrationMessage();
327
+ for (const [serverId, connection] of this.serverConnections) {
328
+ if (connection.ws?.readyState === ws_1.default.OPEN) {
329
+ console.log(`[${this.nodeId}] Registering with server ${serverId}...`);
330
+ connection.ws.send(JSON.stringify(registrationMessage));
331
+ }
332
+ }
333
+ }
334
+ /**
335
+ * Build registration message (extracted for reuse)
336
+ */
337
+ async buildRegistrationMessage() {
338
+ const os = require('os');
339
+ // Detect run mode and container environment
340
+ const isContainer = this.detectContainerEnvironment();
341
+ const runMode = this.detectRunMode();
342
+ const dockerImage = process.env.DOCKER_IMAGE_NAME || null;
343
+ // Discover available MCP tools
344
+ let availableTools = [];
345
+ if (this.enableRemoteLLMSession && this.headlessSessionManager) {
346
+ availableTools = this.headlessSessionManager.discoverAvailableTools?.() || [];
347
+ }
348
+ return {
349
+ type: 'gateway_register',
350
+ gateway_type: 3,
351
+ gateway_id: this.gatewayId,
352
+ instance_id: this.instanceId,
353
+ node_id: this.nodeId,
354
+ version: this.currentVersion,
355
+ api_key: this.apiKey,
356
+ capabilities: {
357
+ maxConcurrent: 10,
358
+ supportsStreaming: true,
359
+ supportsFunctions: true,
360
+ supportedModels: this.vault.listAccessPoints().map((ap) => ap.model_id),
361
+ availableTools: availableTools
362
+ },
363
+ system_info: {
364
+ osPlatform: os.platform(),
365
+ osRelease: os.release(),
366
+ nodeVersion: process.version,
367
+ arch: os.arch(),
368
+ hostname: os.hostname(),
369
+ isContainer: isContainer,
370
+ runMode: runMode,
371
+ dockerImage: dockerImage
372
+ }
373
+ };
374
+ }
163
375
  /**
164
376
  * Initialize the headless session manager for remote automation
165
377
  */
@@ -167,7 +379,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
167
379
  this.headlessSessionManager = new headless_session_1.HeadlessSessionManager({
168
380
  gatewayId: this.instanceId,
169
381
  vault: this.vault,
170
- marketplaceUrl: this.marketplaceUrl,
382
+ registryUrl: this.registryUrl,
171
383
  apiKey: this.apiKey
172
384
  });
173
385
  // Listen for session events
@@ -201,8 +413,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
201
413
  node_id: this.nodeId,
202
414
  uptime_ms: uptime,
203
415
  uptime_human: this.formatUptime(uptime),
204
- marketplace_connected: this.marketplaceWs?.readyState === ws_1.default.OPEN,
205
- marketplace_authenticated: this.isAuthenticated,
416
+ registry_connected: this.registryWs?.readyState === ws_1.default.OPEN,
417
+ registry_authenticated: this.isAuthenticated,
206
418
  mode: {
207
419
  value: this.gatewayMode,
208
420
  name: modeNames[this.gatewayMode],
@@ -336,16 +548,16 @@ class Type3GatewayServer extends events_1.EventEmitter {
336
548
  code: 'vault_error'
337
549
  });
338
550
  }
339
- // Query marketplace for connection details
340
- const marketplaceUrl = this.marketplaceUrl.replace('ws://', 'http://').replace('wss://', 'https://');
341
- const connectionResponse = await axios_1.default.get(`${marketplaceUrl}/api/connections`, {
551
+ // Query registry for connection details
552
+ const registryUrl = this.registryUrl.replace('ws://', 'http://').replace('wss://', 'https://');
553
+ const connectionResponse = await axios_1.default.get(`${registryUrl}/api/connections`, {
342
554
  headers: { 'Authorization': `Bearer ${this.apiKey}` },
343
555
  timeout: 5000
344
556
  });
345
557
  const connection = connectionResponse.data.connections?.find((c) => c.id === connectionId);
346
558
  if (!connection) {
347
559
  return res.status(404).json({
348
- error: 'Connection not found in marketplace',
560
+ error: 'Connection not found in registry',
349
561
  code: 'connection_not_found'
350
562
  });
351
563
  }
@@ -470,7 +682,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
470
682
  // Automatically trigger reconnection after response is sent
471
683
  setTimeout(async () => {
472
684
  console.log(`[${this.nodeId}] Auto-reconnecting with new API key...`);
473
- await this.connectToMarketplace();
685
+ await this.connectToRegistry();
474
686
  await this.registerGateway();
475
687
  }, 500);
476
688
  }
@@ -479,17 +691,17 @@ class Type3GatewayServer extends events_1.EventEmitter {
479
691
  res.status(500).json({ error: error.message });
480
692
  }
481
693
  });
482
- // POST /reconnect - Reconnect to marketplace
694
+ // POST /reconnect - Reconnect to registry
483
695
  this.managementApp.post('/reconnect', async (req, res) => {
484
696
  try {
485
697
  console.log(`[${this.nodeId}] Reconnect requested via management API`);
486
698
  res.json({
487
699
  status: 'reconnecting',
488
- message: 'Disconnecting and reconnecting to marketplace'
700
+ message: 'Disconnecting and reconnecting to registry'
489
701
  });
490
702
  // Reconnect after sending response
491
703
  setTimeout(async () => {
492
- await this.connectToMarketplace();
704
+ await this.connectToRegistry();
493
705
  await this.registerGateway();
494
706
  }, 500);
495
707
  }
@@ -503,7 +715,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
503
715
  res.json({
504
716
  status: 'healthy',
505
717
  timestamp: new Date().toISOString(),
506
- connected: this.marketplaceWs?.readyState === ws_1.default.OPEN,
718
+ connected: this.registryWs?.readyState === ws_1.default.OPEN,
507
719
  authenticated: this.isAuthenticated,
508
720
  current_user: this.currentUser ? {
509
721
  user_id: this.currentUser.id,
@@ -546,9 +758,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
546
758
  return `${seconds}s`;
547
759
  }
548
760
  /**
549
- * Connect to marketplace control plane
761
+ * Connect to registry control plane
550
762
  */
551
- async connectToMarketplace() {
763
+ async connectToRegistry() {
552
764
  return new Promise((resolve, reject) => {
553
765
  // Track if this promise has been settled to prevent double resolve/reject
554
766
  let settled = false;
@@ -556,15 +768,15 @@ class Type3GatewayServer extends events_1.EventEmitter {
556
768
  clearTimeout(this.reconnectInterval);
557
769
  this.reconnectInterval = null;
558
770
  }
559
- if (this.marketplaceWs) {
560
- this.marketplaceWs.removeAllListeners();
561
- if (this.marketplaceWs.readyState === ws_1.default.OPEN) {
562
- this.marketplaceWs.close();
771
+ if (this.registryWs) {
772
+ this.registryWs.removeAllListeners();
773
+ if (this.registryWs.readyState === ws_1.default.OPEN) {
774
+ this.registryWs.close();
563
775
  }
564
- this.marketplaceWs = null;
776
+ this.registryWs = null;
565
777
  }
566
- console.log(`[${this.nodeId}] Connecting to marketplace at ${this.marketplaceUrl}...`);
567
- this.marketplaceWs = new ws_1.default(this.marketplaceUrl, {
778
+ console.log(`[${this.nodeId}] Connecting to registry at ${this.registryUrl}...`);
779
+ this.registryWs = new ws_1.default(this.registryUrl, {
568
780
  headers: {
569
781
  'X-Gateway-Type': '3',
570
782
  'X-Instance-ID': this.instanceId,
@@ -572,19 +784,19 @@ class Type3GatewayServer extends events_1.EventEmitter {
572
784
  'X-Version': this.currentVersion
573
785
  }
574
786
  });
575
- this.marketplaceWs.on('open', () => {
576
- console.log(`[${this.nodeId}] ✅ Connected to marketplace control plane`);
787
+ this.registryWs.on('open', () => {
788
+ console.log(`[${this.nodeId}] ✅ Connected to registry control plane`);
577
789
  this.isAuthenticated = false;
578
790
  if (!settled) {
579
791
  settled = true;
580
792
  resolve();
581
793
  }
582
794
  });
583
- this.marketplaceWs.on('message', (data) => {
584
- this.handleMarketplaceMessage(data.toString());
795
+ this.registryWs.on('message', (data) => {
796
+ this.handleRegistryMessage(data.toString());
585
797
  });
586
- this.marketplaceWs.on('error', (error) => {
587
- console.error(`[${this.nodeId}] ❌ Marketplace connection error:`, error.message);
798
+ this.registryWs.on('error', (error) => {
799
+ console.error(`[${this.nodeId}] ❌ Registry connection error:`, error.message);
588
800
  this.emit('error', error);
589
801
  // Only reject on initial connection attempt (before promise is settled)
590
802
  if (!settled) {
@@ -594,13 +806,13 @@ class Type3GatewayServer extends events_1.EventEmitter {
594
806
  // For errors after connection, trigger reconnection
595
807
  // (close event should also fire, but just in case)
596
808
  });
597
- this.marketplaceWs.on('close', (code, reason) => {
809
+ this.registryWs.on('close', (code, reason) => {
598
810
  // reason can be Buffer or string depending on ws version - handle both
599
811
  const reasonStr = reason ? (Buffer.isBuffer(reason) ? reason.toString() : String(reason)) : 'unknown';
600
- console.log(`[${this.nodeId}] 🔌 Disconnected from marketplace (code: ${code}, reason: ${reasonStr})`);
812
+ console.log(`[${this.nodeId}] 🔌 Disconnected from registry (code: ${code}, reason: ${reasonStr})`);
601
813
  this.isAuthenticated = false;
602
814
  this.currentUser = null; // Clear user info on disconnect
603
- this.handleMarketplaceDisconnection();
815
+ this.handleRegistryDisconnection();
604
816
  });
605
817
  });
606
818
  }
@@ -631,7 +843,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
631
843
  }
632
844
  }
633
845
  /**
634
- * Register gateway with marketplace
846
+ * Register gateway with registry
635
847
  * Includes tool discovery for remote automation sessions (if enabled)
636
848
  */
637
849
  async registerGateway() {
@@ -696,14 +908,29 @@ class Type3GatewayServer extends events_1.EventEmitter {
696
908
  if (this.enableLLMRouting) {
697
909
  console.log(`[${this.nodeId}] Registering with ${connections.length} connections for LLM routing`);
698
910
  }
699
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
700
- this.marketplaceWs.send(JSON.stringify(registration));
911
+ // Multi-connect: Register with ALL connected servers
912
+ if (this.serverConnections.size > 0) {
913
+ let registeredCount = 0;
914
+ for (const [serverId, connection] of this.serverConnections) {
915
+ if (connection.ws?.readyState === ws_1.default.OPEN) {
916
+ console.log(`[${this.nodeId}] Registering with server ${connection.serverType}:${connection.port}...`);
917
+ connection.ws.send(JSON.stringify(registration));
918
+ registeredCount++;
919
+ }
920
+ }
921
+ console.log(`[${this.nodeId}] Registered with ${registeredCount}/${this.serverConnections.size} inference servers`);
922
+ }
923
+ else if (this.registryWs?.readyState === ws_1.default.OPEN) {
924
+ // Fallback: Single connection mode
925
+ this.registryWs.send(JSON.stringify(registration));
701
926
  }
702
927
  }
703
928
  /**
704
- * Handle messages from marketplace control plane
929
+ * Handle messages from registry control plane
930
+ * @param data - Message data as string
931
+ * @param serverId - Optional server ID for multi-connect tracking
705
932
  */
706
- async handleMarketplaceMessage(data) {
933
+ async handleRegistryMessage(data, serverId) {
707
934
  try {
708
935
  const message = JSON.parse(data);
709
936
  // Gateway Type 1 sends both 'event' and 'type' properties for compatibility
@@ -747,8 +974,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
747
974
  console.log(`[${this.nodeId}] Scheduling reconnection with new gateway ID in 2 seconds...`);
748
975
  setTimeout(async () => {
749
976
  try {
750
- console.log(`[${this.nodeId}] Reconnecting to marketplace with fresh identity...`);
751
- await this.connectToMarketplace();
977
+ console.log(`[${this.nodeId}] Reconnecting to registry with fresh identity...`);
978
+ await this.connectToRegistry();
752
979
  await this.registerGateway();
753
980
  console.log(`[${this.nodeId}] ✅ Successfully reconnected with new gateway ID`);
754
981
  }
@@ -761,8 +988,15 @@ class Type3GatewayServer extends events_1.EventEmitter {
761
988
  case 'auth_confirmed':
762
989
  // Gateway Type 1 sends auth_confirmed after successful authentication
763
990
  // It also includes the server-assigned gateway_id and gateway_name
764
- console.log(`[${this.nodeId}] Authentication confirmed by Gateway Type 1`);
991
+ console.log(`[${this.nodeId}] Authentication confirmed by Gateway Type 1${serverId ? ` (server: ${serverId})` : ''}`);
765
992
  this.isAuthenticated = true;
993
+ // Update connection-specific auth status for multi-connect
994
+ if (serverId) {
995
+ const connection = this.serverConnections.get(serverId);
996
+ if (connection) {
997
+ connection.isAuthenticated = true;
998
+ }
999
+ }
766
1000
  // IMPORTANT: Store server-assigned gateway_id for future reconnections
767
1001
  // NOTE: gateway_name is NOT stored locally - it's managed server-side only
768
1002
  const serverGatewayId = message.gatewayId || message.gateway_id;
@@ -806,7 +1040,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
806
1040
  this.sendErrorResponse(message.request_id, 'llm_routing_disabled', 'This gateway is not configured for LLM routing');
807
1041
  break;
808
1042
  }
809
- await this.handleHttpRequest(message);
1043
+ await this.handleHttpRequest(message, serverId);
810
1044
  break;
811
1045
  // ============= REMOTE SESSION EVENTS =============
812
1046
  case 'session_start':
@@ -852,15 +1086,15 @@ class Type3GatewayServer extends events_1.EventEmitter {
852
1086
  await this.handleUpdateAvailable(message);
853
1087
  break;
854
1088
  case 'update_now':
855
- // Mandatory update command from marketplace
1089
+ // Mandatory update command from registry
856
1090
  await this.handleUpdateNow(message);
857
1091
  break;
858
1092
  default:
859
- console.log(`[${this.nodeId}] Unknown marketplace event: ${eventType}`);
1093
+ console.log(`[${this.nodeId}] Unknown registry event: ${eventType}`);
860
1094
  }
861
1095
  }
862
1096
  catch (error) {
863
- console.error(`[${this.nodeId}] Marketplace message error:`, error);
1097
+ console.error(`[${this.nodeId}] Registry message error:`, error);
864
1098
  }
865
1099
  }
866
1100
  /**
@@ -887,6 +1121,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
887
1121
  console.log(`[Type3-${this.nodeId}] Step 2: Extracted parameters:`, {
888
1122
  provider,
889
1123
  endpoint,
1124
+ endpointUrl: endpointUrl || 'NOT PROVIDED',
890
1125
  model,
891
1126
  hasMessages: !!messages,
892
1127
  messageCount: messages?.length || 0,
@@ -954,7 +1189,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
954
1189
  }
955
1190
  if (!stream) {
956
1191
  console.log(`[Type3-${this.nodeId}] Step 7: Received response from provider`);
957
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1192
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
958
1193
  const responseMessage = {
959
1194
  event: 'inference_response',
960
1195
  request_id: requestId,
@@ -965,7 +1200,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
965
1200
  node_id: this.nodeId
966
1201
  }
967
1202
  };
968
- this.marketplaceWs.send(JSON.stringify(responseMessage));
1203
+ this.registryWs.send(JSON.stringify(responseMessage));
969
1204
  console.log(`[Type3-${this.nodeId}] Step 8: Response sent successfully`);
970
1205
  }
971
1206
  }
@@ -978,8 +1213,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
978
1213
  }
979
1214
  catch (error) {
980
1215
  console.error(`[Type3-${this.nodeId}] ERROR in request ${requestId}:`, error.message);
981
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
982
- this.marketplaceWs.send(JSON.stringify({
1216
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1217
+ this.registryWs.send(JSON.stringify({
983
1218
  event: 'inference_error',
984
1219
  request_id: requestId,
985
1220
  error: {
@@ -1081,8 +1316,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1081
1316
  if (line.startsWith('data: ')) {
1082
1317
  const data = line.substring(6);
1083
1318
  if (data === '[DONE]') {
1084
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1085
- this.marketplaceWs.send(JSON.stringify({
1319
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1320
+ this.registryWs.send(JSON.stringify({
1086
1321
  event: 'stream_end',
1087
1322
  request_id: requestId,
1088
1323
  timestamp: new Date().toISOString()
@@ -1092,8 +1327,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1092
1327
  else {
1093
1328
  try {
1094
1329
  const parsed = JSON.parse(data);
1095
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1096
- this.marketplaceWs.send(JSON.stringify({
1330
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1331
+ this.registryWs.send(JSON.stringify({
1097
1332
  event: 'stream_chunk',
1098
1333
  request_id: requestId,
1099
1334
  data: parsed,
@@ -1111,8 +1346,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1111
1346
  return new Promise((resolve, reject) => {
1112
1347
  response.data.on('end', () => {
1113
1348
  console.log(`[${this.nodeId}] Streaming completed for request ${requestId}`);
1114
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1115
- this.marketplaceWs.send(JSON.stringify({
1349
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1350
+ this.registryWs.send(JSON.stringify({
1116
1351
  event: 'stream_complete',
1117
1352
  request_id: requestId,
1118
1353
  stream_completed: true,
@@ -1123,8 +1358,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1123
1358
  });
1124
1359
  response.data.on('error', (error) => {
1125
1360
  console.error(`[${this.nodeId}] Stream error for request ${requestId}:`, error);
1126
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1127
- this.marketplaceWs.send(JSON.stringify({
1361
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1362
+ this.registryWs.send(JSON.stringify({
1128
1363
  event: 'stream_error',
1129
1364
  request_id: requestId,
1130
1365
  error: {
@@ -1194,10 +1429,10 @@ class Type3GatewayServer extends events_1.EventEmitter {
1194
1429
  * body: { ... } (optional)
1195
1430
  * }
1196
1431
  */
1197
- async handleHttpRequest(message) {
1432
+ async handleHttpRequest(message, sourceServerId) {
1198
1433
  const requestId = message.requestId || (0, uuid_1.v4)();
1199
1434
  const { connection_id, method, url, headers = {}, body } = message;
1200
- console.log(`[${this.nodeId}] Forwarding HTTP ${method} request to: ${url}`);
1435
+ console.log(`[${this.nodeId}] Forwarding HTTP ${method} request to: ${url}${sourceServerId ? ` (from server: ${sourceServerId})` : ''}`);
1201
1436
  try {
1202
1437
  // Get API key from local vault if connection_id provided
1203
1438
  let requestHeaders = { ...headers };
@@ -1232,7 +1467,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
1232
1467
  catch {
1233
1468
  responseData = responseText;
1234
1469
  }
1235
- // Send RAW HTTP response back to Type 1
1470
+ // Send RAW HTTP response back to the server that sent the request
1236
1471
  const wsResponse = {
1237
1472
  event: 'http_response',
1238
1473
  requestId: requestId,
@@ -1242,34 +1477,67 @@ class Type3GatewayServer extends events_1.EventEmitter {
1242
1477
  body: responseData, // RAW response body
1243
1478
  timestamp: new Date().toISOString()
1244
1479
  };
1245
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1246
- this.marketplaceWs.send(JSON.stringify(wsResponse));
1247
- console.log(`[${this.nodeId}] Sent HTTP response (${response.status}) to Type 1`);
1480
+ if (this.sendToServer(sourceServerId, wsResponse)) {
1481
+ console.log(`[${this.nodeId}] Sent HTTP response (${response.status}) to server${sourceServerId ? ` ${sourceServerId}` : ''}`);
1482
+ }
1483
+ else {
1484
+ console.error(`[${this.nodeId}] Failed to send HTTP response - no connection available`);
1248
1485
  }
1249
1486
  }
1250
1487
  catch (error) {
1251
1488
  console.error(`[${this.nodeId}] HTTP forwarding error:`, error.message);
1252
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1253
- this.marketplaceWs.send(JSON.stringify({
1254
- event: 'http_response',
1255
- requestId: requestId,
1256
- success: false,
1257
- error: error.message,
1258
- timestamp: new Date().toISOString()
1259
- }));
1260
- }
1489
+ this.sendToServer(sourceServerId, {
1490
+ event: 'http_response',
1491
+ requestId: requestId,
1492
+ success: false,
1493
+ error: error.message,
1494
+ timestamp: new Date().toISOString()
1495
+ });
1261
1496
  }
1262
1497
  }
1263
1498
  /**
1264
- * Send health status to marketplace
1499
+ * Send message to a specific server connection
1500
+ * Falls back to registryWs if serverId not found or not connected
1501
+ * @param serverId - The server ID to send to
1502
+ * @param message - The message object to send
1503
+ * @returns true if message was sent, false otherwise
1504
+ */
1505
+ sendToServer(serverId, message) {
1506
+ // Try to find the specific server connection
1507
+ if (serverId) {
1508
+ const connection = this.serverConnections.get(serverId);
1509
+ if (connection?.ws?.readyState === ws_1.default.OPEN) {
1510
+ connection.ws.send(JSON.stringify(message));
1511
+ return true;
1512
+ }
1513
+ }
1514
+ // Fallback to registryWs (backward compatibility)
1515
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1516
+ this.registryWs.send(JSON.stringify(message));
1517
+ return true;
1518
+ }
1519
+ return false;
1520
+ }
1521
+ /**
1522
+ * Send health status to all connected servers (multi-connect)
1265
1523
  */
1266
1524
  sendHealthStatus() {
1267
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1268
- const heartbeat = {
1269
- type: 'heartbeat',
1270
- timestamp: new Date().toISOString()
1271
- };
1272
- this.marketplaceWs.send(JSON.stringify(heartbeat));
1525
+ const heartbeat = {
1526
+ type: 'heartbeat',
1527
+ timestamp: new Date().toISOString()
1528
+ };
1529
+ const heartbeatStr = JSON.stringify(heartbeat);
1530
+ // Send to all connected servers (multi-connect)
1531
+ let sentCount = 0;
1532
+ for (const [serverId, connection] of this.serverConnections) {
1533
+ if (connection.ws?.readyState === ws_1.default.OPEN) {
1534
+ connection.ws.send(heartbeatStr);
1535
+ sentCount++;
1536
+ }
1537
+ }
1538
+ // Fallback to registryWs if no server connections (legacy mode)
1539
+ if (sentCount === 0 && this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1540
+ this.registryWs.send(heartbeatStr);
1273
1541
  }
1274
1542
  const status = {
1275
1543
  event: 'health_status',
@@ -1288,8 +1556,18 @@ class Type3GatewayServer extends events_1.EventEmitter {
1288
1556
  },
1289
1557
  timestamp: new Date().toISOString()
1290
1558
  };
1291
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1292
- this.marketplaceWs.send(JSON.stringify(status));
1559
+ const statusStr = JSON.stringify(status);
1560
+ // Send health status to all connected servers (multi-connect)
1561
+ let statusSentCount = 0;
1562
+ for (const [, connection] of this.serverConnections) {
1563
+ if (connection.ws?.readyState === ws_1.default.OPEN) {
1564
+ connection.ws.send(statusStr);
1565
+ statusSentCount++;
1566
+ }
1567
+ }
1568
+ // Fallback to registryWs if no server connections (legacy mode)
1569
+ if (statusSentCount === 0 && this.registryWs?.readyState === ws_1.default.OPEN) {
1570
+ this.registryWs.send(statusStr);
1293
1571
  }
1294
1572
  this.metrics.lastHealthCheck = new Date();
1295
1573
  }
@@ -1322,8 +1600,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1322
1600
  },
1323
1601
  timestamp: new Date().toISOString()
1324
1602
  };
1325
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1326
- this.marketplaceWs.send(JSON.stringify(rateLimits));
1603
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1604
+ this.registryWs.send(JSON.stringify(rateLimits));
1327
1605
  }
1328
1606
  }
1329
1607
  /**
@@ -1333,25 +1611,25 @@ class Type3GatewayServer extends events_1.EventEmitter {
1333
1611
  startHealthMonitoring() {
1334
1612
  this.healthCheckInterval = setInterval(() => {
1335
1613
  // Only send health status if connected
1336
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1614
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1337
1615
  this.sendHealthStatus();
1338
1616
  }
1339
1617
  else if (!this.reconnectInterval && !this.isShuttingDown) {
1340
1618
  // Connection lost and no reconnection scheduled - trigger reconnection
1341
- console.warn(`[${this.nodeId}] Health check: Lost connection to marketplace, triggering reconnection...`);
1619
+ console.warn(`[${this.nodeId}] Health check: Lost connection to registry, triggering reconnection...`);
1342
1620
  // Reset reconnect attempts for health-check triggered reconnection
1343
1621
  // This ensures we start fresh when health check detects a problem
1344
1622
  this.reconnectAttempts = 0;
1345
- this.handleMarketplaceDisconnection();
1623
+ this.handleRegistryDisconnection();
1346
1624
  }
1347
1625
  }, 30000);
1348
1626
  }
1349
1627
  /**
1350
- * Handle marketplace disconnection with robust retry logic
1628
+ * Handle registry disconnection with robust retry logic
1351
1629
  * This method schedules reconnection attempts with exponential backoff
1352
1630
  * and ensures registerGateway() is always called after successful reconnection
1353
1631
  */
1354
- handleMarketplaceDisconnection() {
1632
+ handleRegistryDisconnection() {
1355
1633
  if (this.isShuttingDown) {
1356
1634
  console.log(`[${this.nodeId}] Shutdown in progress, skipping reconnection`);
1357
1635
  return;
@@ -1376,9 +1654,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
1376
1654
  this.reconnectInterval = null; // Clear so we can schedule next attempt if needed
1377
1655
  console.log(`[${this.nodeId}] 🔄 Attempting to reconnect (attempt ${this.reconnectAttempts})...`);
1378
1656
  try {
1379
- await this.connectToMarketplace();
1657
+ await this.connectToRegistry();
1380
1658
  // Check if connection was successful
1381
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1659
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1382
1660
  console.log(`[${this.nodeId}] ✅ Reconnected successfully!`);
1383
1661
  console.log(`[${this.nodeId}] 📝 Re-registering after reconnection...`);
1384
1662
  try {
@@ -1390,18 +1668,18 @@ class Type3GatewayServer extends events_1.EventEmitter {
1390
1668
  catch (regError) {
1391
1669
  console.error(`[${this.nodeId}] ❌ Registration failed after reconnect:`, regError.message);
1392
1670
  // Schedule another attempt since registration failed
1393
- this.handleMarketplaceDisconnection();
1671
+ this.handleRegistryDisconnection();
1394
1672
  }
1395
1673
  }
1396
1674
  else {
1397
- console.warn(`[${this.nodeId}] ⚠️ WebSocket not open after connectToMarketplace, scheduling retry...`);
1398
- this.handleMarketplaceDisconnection();
1675
+ console.warn(`[${this.nodeId}] ⚠️ WebSocket not open after connectToRegistry, scheduling retry...`);
1676
+ this.handleRegistryDisconnection();
1399
1677
  }
1400
1678
  }
1401
1679
  catch (error) {
1402
1680
  console.error(`[${this.nodeId}] ❌ Reconnection attempt failed:`, error.message);
1403
1681
  // Schedule another reconnection attempt
1404
- this.handleMarketplaceDisconnection();
1682
+ this.handleRegistryDisconnection();
1405
1683
  }
1406
1684
  }, delay);
1407
1685
  }
@@ -1665,8 +1943,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1665
1943
  // Send acknowledgment to Type 1
1666
1944
  // NOTE: The initialMessage is the assistant's greeting, already added to session history
1667
1945
  // We do NOT call processSessionMessageInternal because the greeting doesn't need an LLM response
1668
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1669
- this.marketplaceWs.send(JSON.stringify({
1946
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1947
+ this.registryWs.send(JSON.stringify({
1670
1948
  event: 'session_started',
1671
1949
  requestId,
1672
1950
  sessionId: session.sessionId,
@@ -1735,8 +2013,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1735
2013
  try {
1736
2014
  // Stream handler to send chunks to Type 1
1737
2015
  const onChunk = (chunk) => {
1738
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1739
- this.marketplaceWs.send(JSON.stringify({
2016
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2017
+ this.registryWs.send(JSON.stringify({
1740
2018
  event: 'session_chunk',
1741
2019
  requestId,
1742
2020
  sessionId,
@@ -1748,8 +2026,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1748
2026
  const response = await this.headlessSessionManager.processMessage(sessionId, userMessage, onChunk, modelId // Pass per-message model ID
1749
2027
  );
1750
2028
  // Send final response to Type 1
1751
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1752
- this.marketplaceWs.send(JSON.stringify({
2029
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2030
+ this.registryWs.send(JSON.stringify({
1753
2031
  event: 'session_response',
1754
2032
  requestId,
1755
2033
  sessionId,
@@ -1789,8 +2067,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1789
2067
  return;
1790
2068
  }
1791
2069
  const success = await this.headlessSessionManager.cancelSession(sessionId);
1792
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1793
- this.marketplaceWs.send(JSON.stringify({
2070
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2071
+ this.registryWs.send(JSON.stringify({
1794
2072
  event: 'session_cancelled',
1795
2073
  requestId,
1796
2074
  sessionId,
@@ -1806,8 +2084,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1806
2084
  const requestId = message.requestId || message.request_id;
1807
2085
  console.log(`[${this.nodeId}] Received get_tools request`);
1808
2086
  const tools = this.headlessSessionManager?.getAvailableTools() || [];
1809
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1810
- this.marketplaceWs.send(JSON.stringify({
2087
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2088
+ this.registryWs.send(JSON.stringify({
1811
2089
  event: 'tools_response',
1812
2090
  requestId,
1813
2091
  gatewayId: this.instanceId,
@@ -1820,8 +2098,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1820
2098
  * Send session error to Type 1
1821
2099
  */
1822
2100
  sendSessionError(requestId, error, sessionId) {
1823
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1824
- this.marketplaceWs.send(JSON.stringify({
2101
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2102
+ this.registryWs.send(JSON.stringify({
1825
2103
  event: 'session_error',
1826
2104
  requestId,
1827
2105
  sessionId,
@@ -1834,8 +2112,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1834
2112
  * Send inference error response to Type 1
1835
2113
  */
1836
2114
  sendErrorResponse(requestId, code, message) {
1837
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1838
- this.marketplaceWs.send(JSON.stringify({
2115
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2116
+ this.registryWs.send(JSON.stringify({
1839
2117
  event: 'inference_error',
1840
2118
  request_id: requestId,
1841
2119
  error: {
@@ -2039,8 +2317,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2039
2317
  });
2040
2318
  console.log(`[${this.nodeId}] Script execution completed: ${result.success ? 'success' : 'failed'} (exit code: ${result.exit_code})`);
2041
2319
  // Send result back to Type 1
2042
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2043
- this.marketplaceWs.send(JSON.stringify({
2320
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2321
+ this.registryWs.send(JSON.stringify({
2044
2322
  event: 'script_result',
2045
2323
  requestId,
2046
2324
  success: true,
@@ -2064,8 +2342,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2064
2342
  * Send script execution error to Type 1
2065
2343
  */
2066
2344
  sendScriptError(requestId, code, message) {
2067
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2068
- this.marketplaceWs.send(JSON.stringify({
2345
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2346
+ this.registryWs.send(JSON.stringify({
2069
2347
  event: 'script_result',
2070
2348
  requestId,
2071
2349
  success: false,
@@ -2097,8 +2375,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2097
2375
  // autoUpdate defaults to true if not explicitly set to false
2098
2376
  const shouldAutoUpdate = mandatory || (autoUpdate !== false);
2099
2377
  // Send acknowledgment to Type 1
2100
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2101
- this.marketplaceWs.send(JSON.stringify({
2378
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2379
+ this.registryWs.send(JSON.stringify({
2102
2380
  event: 'update_acknowledged',
2103
2381
  gatewayId: this.instanceId,
2104
2382
  currentVersion: this.currentVersion,
@@ -2133,8 +2411,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2133
2411
  console.log(`[${this.nodeId}] 🚨 Immediate update requested: v${version}`);
2134
2412
  console.log(`[${this.nodeId}] Reason: ${reason || 'No reason provided'}`);
2135
2413
  // Acknowledge the update command
2136
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2137
- this.marketplaceWs.send(JSON.stringify({
2414
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2415
+ this.registryWs.send(JSON.stringify({
2138
2416
  event: 'update_starting',
2139
2417
  gatewayId: this.instanceId,
2140
2418
  currentVersion: this.currentVersion,
@@ -2245,8 +2523,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2245
2523
  if (resolvedTargetVersion && this.currentVersion === resolvedTargetVersion) {
2246
2524
  console.log(`[${this.nodeId}] ✅ Already at version v${this.currentVersion}, skipping update`);
2247
2525
  // Notify Type 1 that no update is needed
2248
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2249
- this.marketplaceWs.send(JSON.stringify({
2526
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2527
+ this.registryWs.send(JSON.stringify({
2250
2528
  event: 'already_up_to_date',
2251
2529
  gatewayId: this.instanceId,
2252
2530
  currentVersion: this.currentVersion,
@@ -2288,8 +2566,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2288
2566
  }
2289
2567
  console.log(`[${this.nodeId}] ✓ Package installed successfully`);
2290
2568
  // Step 2: Notify Type 1 of successful install
2291
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2292
- this.marketplaceWs.send(JSON.stringify({
2569
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2570
+ this.registryWs.send(JSON.stringify({
2293
2571
  event: 'update_installed',
2294
2572
  gatewayId: this.instanceId,
2295
2573
  previousVersion: this.currentVersion,
@@ -2301,8 +2579,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2301
2579
  // Step 3: Graceful restart
2302
2580
  console.log(`[${this.nodeId}] Step 2: Initiating graceful restart...`);
2303
2581
  // Close WebSocket cleanly
2304
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2305
- this.marketplaceWs.send(JSON.stringify({
2582
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2583
+ this.registryWs.send(JSON.stringify({
2306
2584
  event: 'gateway_restarting',
2307
2585
  gatewayId: this.instanceId,
2308
2586
  reason: 'update',
@@ -2351,8 +2629,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2351
2629
  console.error(`[${this.nodeId}] ❌ Update failed:`, error.message);
2352
2630
  this.isUpdating = false;
2353
2631
  // Notify Type 1 of failure
2354
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2355
- this.marketplaceWs.send(JSON.stringify({
2632
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2633
+ this.registryWs.send(JSON.stringify({
2356
2634
  event: 'update_failed',
2357
2635
  gatewayId: this.instanceId,
2358
2636
  currentVersion: this.currentVersion,
@@ -2402,9 +2680,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
2402
2680
  console.log(`[${this.nodeId}] Waiting for ${this.activeRequests.size} active requests...`);
2403
2681
  await new Promise(resolve => setTimeout(resolve, 1000));
2404
2682
  }
2405
- // Close marketplace WebSocket
2406
- if (this.marketplaceWs) {
2407
- this.marketplaceWs.close();
2683
+ // Close registry WebSocket
2684
+ if (this.registryWs) {
2685
+ this.registryWs.close();
2408
2686
  }
2409
2687
  // Close management API server
2410
2688
  if (this.managementServer) {
@@ -2425,7 +2703,7 @@ exports.Type3GatewayServer = Type3GatewayServer;
2425
2703
  if (require.main === module) {
2426
2704
  const gateway = new Type3GatewayServer({
2427
2705
  port: parseInt(process.env.GATEWAY_PORT || '8083'),
2428
- marketplaceUrl: process.env.MARKETPLACE_URL,
2706
+ registryUrl: process.env.REGISTRY_URL,
2429
2707
  instanceId: process.env.INSTANCE_ID,
2430
2708
  apiKey: process.env.GATEWAY_API_KEY,
2431
2709
  vaultPath: process.env.VAULT_PATH,