langmart-gateway-type3 3.0.40 → 3.0.42

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,31 +784,35 @@ 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) {
591
803
  settled = true;
592
804
  reject(error);
593
805
  }
806
+ // For errors after connection, trigger reconnection
807
+ // (close event should also fire, but just in case)
594
808
  });
595
- this.marketplaceWs.on('close', (code, reason) => {
596
- console.log(`[${this.nodeId}] 🔌 Disconnected from marketplace (code: ${code}, reason: ${reason})`);
809
+ this.registryWs.on('close', (code, reason) => {
810
+ // reason can be Buffer or string depending on ws version - handle both
811
+ const reasonStr = reason ? (Buffer.isBuffer(reason) ? reason.toString() : String(reason)) : 'unknown';
812
+ console.log(`[${this.nodeId}] 🔌 Disconnected from registry (code: ${code}, reason: ${reasonStr})`);
597
813
  this.isAuthenticated = false;
598
814
  this.currentUser = null; // Clear user info on disconnect
599
- this.handleMarketplaceDisconnection();
815
+ this.handleRegistryDisconnection();
600
816
  });
601
817
  });
602
818
  }
@@ -627,7 +843,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
627
843
  }
628
844
  }
629
845
  /**
630
- * Register gateway with marketplace
846
+ * Register gateway with registry
631
847
  * Includes tool discovery for remote automation sessions (if enabled)
632
848
  */
633
849
  async registerGateway() {
@@ -692,14 +908,29 @@ class Type3GatewayServer extends events_1.EventEmitter {
692
908
  if (this.enableLLMRouting) {
693
909
  console.log(`[${this.nodeId}] Registering with ${connections.length} connections for LLM routing`);
694
910
  }
695
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
696
- 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));
697
926
  }
698
927
  }
699
928
  /**
700
- * 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
701
932
  */
702
- async handleMarketplaceMessage(data) {
933
+ async handleRegistryMessage(data, serverId) {
703
934
  try {
704
935
  const message = JSON.parse(data);
705
936
  // Gateway Type 1 sends both 'event' and 'type' properties for compatibility
@@ -743,8 +974,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
743
974
  console.log(`[${this.nodeId}] Scheduling reconnection with new gateway ID in 2 seconds...`);
744
975
  setTimeout(async () => {
745
976
  try {
746
- console.log(`[${this.nodeId}] Reconnecting to marketplace with fresh identity...`);
747
- await this.connectToMarketplace();
977
+ console.log(`[${this.nodeId}] Reconnecting to registry with fresh identity...`);
978
+ await this.connectToRegistry();
748
979
  await this.registerGateway();
749
980
  console.log(`[${this.nodeId}] ✅ Successfully reconnected with new gateway ID`);
750
981
  }
@@ -757,8 +988,15 @@ class Type3GatewayServer extends events_1.EventEmitter {
757
988
  case 'auth_confirmed':
758
989
  // Gateway Type 1 sends auth_confirmed after successful authentication
759
990
  // It also includes the server-assigned gateway_id and gateway_name
760
- console.log(`[${this.nodeId}] Authentication confirmed by Gateway Type 1`);
991
+ console.log(`[${this.nodeId}] Authentication confirmed by Gateway Type 1${serverId ? ` (server: ${serverId})` : ''}`);
761
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
+ }
762
1000
  // IMPORTANT: Store server-assigned gateway_id for future reconnections
763
1001
  // NOTE: gateway_name is NOT stored locally - it's managed server-side only
764
1002
  const serverGatewayId = message.gatewayId || message.gateway_id;
@@ -802,7 +1040,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
802
1040
  this.sendErrorResponse(message.request_id, 'llm_routing_disabled', 'This gateway is not configured for LLM routing');
803
1041
  break;
804
1042
  }
805
- await this.handleHttpRequest(message);
1043
+ await this.handleHttpRequest(message, serverId);
806
1044
  break;
807
1045
  // ============= REMOTE SESSION EVENTS =============
808
1046
  case 'session_start':
@@ -848,15 +1086,15 @@ class Type3GatewayServer extends events_1.EventEmitter {
848
1086
  await this.handleUpdateAvailable(message);
849
1087
  break;
850
1088
  case 'update_now':
851
- // Mandatory update command from marketplace
1089
+ // Mandatory update command from registry
852
1090
  await this.handleUpdateNow(message);
853
1091
  break;
854
1092
  default:
855
- console.log(`[${this.nodeId}] Unknown marketplace event: ${eventType}`);
1093
+ console.log(`[${this.nodeId}] Unknown registry event: ${eventType}`);
856
1094
  }
857
1095
  }
858
1096
  catch (error) {
859
- console.error(`[${this.nodeId}] Marketplace message error:`, error);
1097
+ console.error(`[${this.nodeId}] Registry message error:`, error);
860
1098
  }
861
1099
  }
862
1100
  /**
@@ -883,6 +1121,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
883
1121
  console.log(`[Type3-${this.nodeId}] Step 2: Extracted parameters:`, {
884
1122
  provider,
885
1123
  endpoint,
1124
+ endpointUrl: endpointUrl || 'NOT PROVIDED',
886
1125
  model,
887
1126
  hasMessages: !!messages,
888
1127
  messageCount: messages?.length || 0,
@@ -950,7 +1189,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
950
1189
  }
951
1190
  if (!stream) {
952
1191
  console.log(`[Type3-${this.nodeId}] Step 7: Received response from provider`);
953
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1192
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
954
1193
  const responseMessage = {
955
1194
  event: 'inference_response',
956
1195
  request_id: requestId,
@@ -961,7 +1200,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
961
1200
  node_id: this.nodeId
962
1201
  }
963
1202
  };
964
- this.marketplaceWs.send(JSON.stringify(responseMessage));
1203
+ this.registryWs.send(JSON.stringify(responseMessage));
965
1204
  console.log(`[Type3-${this.nodeId}] Step 8: Response sent successfully`);
966
1205
  }
967
1206
  }
@@ -974,8 +1213,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
974
1213
  }
975
1214
  catch (error) {
976
1215
  console.error(`[Type3-${this.nodeId}] ERROR in request ${requestId}:`, error.message);
977
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
978
- this.marketplaceWs.send(JSON.stringify({
1216
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1217
+ this.registryWs.send(JSON.stringify({
979
1218
  event: 'inference_error',
980
1219
  request_id: requestId,
981
1220
  error: {
@@ -1077,8 +1316,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1077
1316
  if (line.startsWith('data: ')) {
1078
1317
  const data = line.substring(6);
1079
1318
  if (data === '[DONE]') {
1080
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1081
- this.marketplaceWs.send(JSON.stringify({
1319
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1320
+ this.registryWs.send(JSON.stringify({
1082
1321
  event: 'stream_end',
1083
1322
  request_id: requestId,
1084
1323
  timestamp: new Date().toISOString()
@@ -1088,8 +1327,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1088
1327
  else {
1089
1328
  try {
1090
1329
  const parsed = JSON.parse(data);
1091
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1092
- this.marketplaceWs.send(JSON.stringify({
1330
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1331
+ this.registryWs.send(JSON.stringify({
1093
1332
  event: 'stream_chunk',
1094
1333
  request_id: requestId,
1095
1334
  data: parsed,
@@ -1107,8 +1346,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1107
1346
  return new Promise((resolve, reject) => {
1108
1347
  response.data.on('end', () => {
1109
1348
  console.log(`[${this.nodeId}] Streaming completed for request ${requestId}`);
1110
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1111
- this.marketplaceWs.send(JSON.stringify({
1349
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1350
+ this.registryWs.send(JSON.stringify({
1112
1351
  event: 'stream_complete',
1113
1352
  request_id: requestId,
1114
1353
  stream_completed: true,
@@ -1119,8 +1358,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1119
1358
  });
1120
1359
  response.data.on('error', (error) => {
1121
1360
  console.error(`[${this.nodeId}] Stream error for request ${requestId}:`, error);
1122
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1123
- this.marketplaceWs.send(JSON.stringify({
1361
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1362
+ this.registryWs.send(JSON.stringify({
1124
1363
  event: 'stream_error',
1125
1364
  request_id: requestId,
1126
1365
  error: {
@@ -1190,10 +1429,10 @@ class Type3GatewayServer extends events_1.EventEmitter {
1190
1429
  * body: { ... } (optional)
1191
1430
  * }
1192
1431
  */
1193
- async handleHttpRequest(message) {
1432
+ async handleHttpRequest(message, sourceServerId) {
1194
1433
  const requestId = message.requestId || (0, uuid_1.v4)();
1195
1434
  const { connection_id, method, url, headers = {}, body } = message;
1196
- 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})` : ''}`);
1197
1436
  try {
1198
1437
  // Get API key from local vault if connection_id provided
1199
1438
  let requestHeaders = { ...headers };
@@ -1228,7 +1467,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
1228
1467
  catch {
1229
1468
  responseData = responseText;
1230
1469
  }
1231
- // Send RAW HTTP response back to Type 1
1470
+ // Send RAW HTTP response back to the server that sent the request
1232
1471
  const wsResponse = {
1233
1472
  event: 'http_response',
1234
1473
  requestId: requestId,
@@ -1238,34 +1477,67 @@ class Type3GatewayServer extends events_1.EventEmitter {
1238
1477
  body: responseData, // RAW response body
1239
1478
  timestamp: new Date().toISOString()
1240
1479
  };
1241
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1242
- this.marketplaceWs.send(JSON.stringify(wsResponse));
1243
- 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`);
1244
1485
  }
1245
1486
  }
1246
1487
  catch (error) {
1247
1488
  console.error(`[${this.nodeId}] HTTP forwarding error:`, error.message);
1248
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1249
- this.marketplaceWs.send(JSON.stringify({
1250
- event: 'http_response',
1251
- requestId: requestId,
1252
- success: false,
1253
- error: error.message,
1254
- timestamp: new Date().toISOString()
1255
- }));
1256
- }
1489
+ this.sendToServer(sourceServerId, {
1490
+ event: 'http_response',
1491
+ requestId: requestId,
1492
+ success: false,
1493
+ error: error.message,
1494
+ timestamp: new Date().toISOString()
1495
+ });
1496
+ }
1497
+ }
1498
+ /**
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;
1257
1518
  }
1519
+ return false;
1258
1520
  }
1259
1521
  /**
1260
- * Send health status to marketplace
1522
+ * Send health status to all connected servers (multi-connect)
1261
1523
  */
1262
1524
  sendHealthStatus() {
1263
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1264
- const heartbeat = {
1265
- type: 'heartbeat',
1266
- timestamp: new Date().toISOString()
1267
- };
1268
- 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);
1269
1541
  }
1270
1542
  const status = {
1271
1543
  event: 'health_status',
@@ -1284,8 +1556,18 @@ class Type3GatewayServer extends events_1.EventEmitter {
1284
1556
  },
1285
1557
  timestamp: new Date().toISOString()
1286
1558
  };
1287
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1288
- 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);
1289
1571
  }
1290
1572
  this.metrics.lastHealthCheck = new Date();
1291
1573
  }
@@ -1318,8 +1600,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1318
1600
  },
1319
1601
  timestamp: new Date().toISOString()
1320
1602
  };
1321
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1322
- this.marketplaceWs.send(JSON.stringify(rateLimits));
1603
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1604
+ this.registryWs.send(JSON.stringify(rateLimits));
1323
1605
  }
1324
1606
  }
1325
1607
  /**
@@ -1329,25 +1611,25 @@ class Type3GatewayServer extends events_1.EventEmitter {
1329
1611
  startHealthMonitoring() {
1330
1612
  this.healthCheckInterval = setInterval(() => {
1331
1613
  // Only send health status if connected
1332
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1614
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1333
1615
  this.sendHealthStatus();
1334
1616
  }
1335
1617
  else if (!this.reconnectInterval && !this.isShuttingDown) {
1336
1618
  // Connection lost and no reconnection scheduled - trigger reconnection
1337
- 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...`);
1338
1620
  // Reset reconnect attempts for health-check triggered reconnection
1339
1621
  // This ensures we start fresh when health check detects a problem
1340
1622
  this.reconnectAttempts = 0;
1341
- this.handleMarketplaceDisconnection();
1623
+ this.handleRegistryDisconnection();
1342
1624
  }
1343
1625
  }, 30000);
1344
1626
  }
1345
1627
  /**
1346
- * Handle marketplace disconnection with robust retry logic
1628
+ * Handle registry disconnection with robust retry logic
1347
1629
  * This method schedules reconnection attempts with exponential backoff
1348
1630
  * and ensures registerGateway() is always called after successful reconnection
1349
1631
  */
1350
- handleMarketplaceDisconnection() {
1632
+ handleRegistryDisconnection() {
1351
1633
  if (this.isShuttingDown) {
1352
1634
  console.log(`[${this.nodeId}] Shutdown in progress, skipping reconnection`);
1353
1635
  return;
@@ -1372,9 +1654,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
1372
1654
  this.reconnectInterval = null; // Clear so we can schedule next attempt if needed
1373
1655
  console.log(`[${this.nodeId}] 🔄 Attempting to reconnect (attempt ${this.reconnectAttempts})...`);
1374
1656
  try {
1375
- await this.connectToMarketplace();
1657
+ await this.connectToRegistry();
1376
1658
  // Check if connection was successful
1377
- if (this.marketplaceWs && this.marketplaceWs.readyState === ws_1.default.OPEN) {
1659
+ if (this.registryWs && this.registryWs.readyState === ws_1.default.OPEN) {
1378
1660
  console.log(`[${this.nodeId}] ✅ Reconnected successfully!`);
1379
1661
  console.log(`[${this.nodeId}] 📝 Re-registering after reconnection...`);
1380
1662
  try {
@@ -1386,18 +1668,18 @@ class Type3GatewayServer extends events_1.EventEmitter {
1386
1668
  catch (regError) {
1387
1669
  console.error(`[${this.nodeId}] ❌ Registration failed after reconnect:`, regError.message);
1388
1670
  // Schedule another attempt since registration failed
1389
- this.handleMarketplaceDisconnection();
1671
+ this.handleRegistryDisconnection();
1390
1672
  }
1391
1673
  }
1392
1674
  else {
1393
- console.warn(`[${this.nodeId}] ⚠️ WebSocket not open after connectToMarketplace, scheduling retry...`);
1394
- this.handleMarketplaceDisconnection();
1675
+ console.warn(`[${this.nodeId}] ⚠️ WebSocket not open after connectToRegistry, scheduling retry...`);
1676
+ this.handleRegistryDisconnection();
1395
1677
  }
1396
1678
  }
1397
1679
  catch (error) {
1398
1680
  console.error(`[${this.nodeId}] ❌ Reconnection attempt failed:`, error.message);
1399
1681
  // Schedule another reconnection attempt
1400
- this.handleMarketplaceDisconnection();
1682
+ this.handleRegistryDisconnection();
1401
1683
  }
1402
1684
  }, delay);
1403
1685
  }
@@ -1636,6 +1918,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
1636
1918
  async handleSessionStart(message) {
1637
1919
  const requestId = message.requestId || message.request_id;
1638
1920
  console.log(`[${this.nodeId}] Received session_start request: ${requestId}`);
1921
+ console.log(`[${this.nodeId}] session_start received includeEnvironmentInfo: ${message.includeEnvironmentInfo}, systemPrompt defined: ${message.systemPrompt !== undefined}, systemPrompt length: ${message.systemPrompt?.length || 0}`);
1639
1922
  if (!this.headlessSessionManager) {
1640
1923
  this.sendSessionError(requestId, 'Headless session manager not initialized');
1641
1924
  return;
@@ -1647,6 +1930,7 @@ class Type3GatewayServer extends events_1.EventEmitter {
1647
1930
  organizationId: message.organizationId,
1648
1931
  templateId: message.templateId,
1649
1932
  systemPrompt: message.systemPrompt,
1933
+ includeEnvironmentInfo: message.includeEnvironmentInfo !== false, // Default to true
1650
1934
  initialMessage: message.initialMessage,
1651
1935
  modelId: message.modelId,
1652
1936
  connectionId: message.connectionId,
@@ -1659,8 +1943,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1659
1943
  // Send acknowledgment to Type 1
1660
1944
  // NOTE: The initialMessage is the assistant's greeting, already added to session history
1661
1945
  // We do NOT call processSessionMessageInternal because the greeting doesn't need an LLM response
1662
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1663
- this.marketplaceWs.send(JSON.stringify({
1946
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
1947
+ this.registryWs.send(JSON.stringify({
1664
1948
  event: 'session_started',
1665
1949
  requestId,
1666
1950
  sessionId: session.sessionId,
@@ -1699,13 +1983,17 @@ class Type3GatewayServer extends events_1.EventEmitter {
1699
1983
  if (needsRestore && sessionRestore) {
1700
1984
  const reason = !existingSession ? 'not found in memory' : `in ${existingSession.status} state`;
1701
1985
  console.log(`[${this.nodeId}] Session ${sessionId} ${reason}, auto-restoring from Type 1 data`);
1986
+ console.log(`[${this.nodeId}] Session restore data - systemPrompt: ${sessionRestore.systemPrompt ? 'provided' : 'not provided'}, includeEnvironmentInfo: ${sessionRestore.includeEnvironmentInfo}`);
1702
1987
  try {
1703
1988
  await this.headlessSessionManager.restoreSession(sessionId, {
1704
1989
  userId: sessionRestore.userId,
1705
1990
  organizationId: sessionRestore.organizationId,
1706
1991
  sessionType: sessionRestore.sessionType,
1707
1992
  modelId: modelId,
1708
- messages: sessionRestore.messages || []
1993
+ messages: sessionRestore.messages || [],
1994
+ // Pass system prompt configuration from session metadata for proper restore
1995
+ systemPrompt: sessionRestore.systemPrompt,
1996
+ includeEnvironmentInfo: sessionRestore.includeEnvironmentInfo
1709
1997
  });
1710
1998
  console.log(`[${this.nodeId}] Session ${sessionId} restored/reactivated successfully`);
1711
1999
  }
@@ -1725,8 +2013,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1725
2013
  try {
1726
2014
  // Stream handler to send chunks to Type 1
1727
2015
  const onChunk = (chunk) => {
1728
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1729
- this.marketplaceWs.send(JSON.stringify({
2016
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2017
+ this.registryWs.send(JSON.stringify({
1730
2018
  event: 'session_chunk',
1731
2019
  requestId,
1732
2020
  sessionId,
@@ -1738,18 +2026,26 @@ class Type3GatewayServer extends events_1.EventEmitter {
1738
2026
  const response = await this.headlessSessionManager.processMessage(sessionId, userMessage, onChunk, modelId // Pass per-message model ID
1739
2027
  );
1740
2028
  // Send final response to Type 1
1741
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1742
- this.marketplaceWs.send(JSON.stringify({
2029
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2030
+ this.registryWs.send(JSON.stringify({
1743
2031
  event: 'session_response',
1744
2032
  requestId,
1745
2033
  sessionId,
1746
2034
  status: response.status,
1747
- message: response.message,
1748
- toolResults: response.toolResults,
1749
2035
  isComplete: response.isComplete,
1750
2036
  error: response.error,
1751
- requestIds: response.requestIds, // LLM request IDs for request log linking
1752
- usage: response.usage, // Token usage for display
2037
+ // New structured fields for Type 1
2038
+ assistant_message: response.assistant_message,
2039
+ tool_calls: response.tool_calls,
2040
+ tools_available: response.tools_available,
2041
+ tools_enabled: response.tools_enabled,
2042
+ llm_iterations: response.llm_iterations,
2043
+ request_log_ids: response.request_log_ids,
2044
+ usage: response.usage,
2045
+ // Legacy fields for backward compatibility
2046
+ message: response.message,
2047
+ toolResults: response.toolResults,
2048
+ requestIds: response.requestIds || response.request_log_ids,
1753
2049
  timestamp: new Date().toISOString()
1754
2050
  }));
1755
2051
  }
@@ -1771,8 +2067,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1771
2067
  return;
1772
2068
  }
1773
2069
  const success = await this.headlessSessionManager.cancelSession(sessionId);
1774
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1775
- this.marketplaceWs.send(JSON.stringify({
2070
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2071
+ this.registryWs.send(JSON.stringify({
1776
2072
  event: 'session_cancelled',
1777
2073
  requestId,
1778
2074
  sessionId,
@@ -1788,8 +2084,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1788
2084
  const requestId = message.requestId || message.request_id;
1789
2085
  console.log(`[${this.nodeId}] Received get_tools request`);
1790
2086
  const tools = this.headlessSessionManager?.getAvailableTools() || [];
1791
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1792
- this.marketplaceWs.send(JSON.stringify({
2087
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2088
+ this.registryWs.send(JSON.stringify({
1793
2089
  event: 'tools_response',
1794
2090
  requestId,
1795
2091
  gatewayId: this.instanceId,
@@ -1802,8 +2098,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1802
2098
  * Send session error to Type 1
1803
2099
  */
1804
2100
  sendSessionError(requestId, error, sessionId) {
1805
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1806
- this.marketplaceWs.send(JSON.stringify({
2101
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2102
+ this.registryWs.send(JSON.stringify({
1807
2103
  event: 'session_error',
1808
2104
  requestId,
1809
2105
  sessionId,
@@ -1816,8 +2112,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
1816
2112
  * Send inference error response to Type 1
1817
2113
  */
1818
2114
  sendErrorResponse(requestId, code, message) {
1819
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
1820
- this.marketplaceWs.send(JSON.stringify({
2115
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2116
+ this.registryWs.send(JSON.stringify({
1821
2117
  event: 'inference_error',
1822
2118
  request_id: requestId,
1823
2119
  error: {
@@ -2021,8 +2317,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2021
2317
  });
2022
2318
  console.log(`[${this.nodeId}] Script execution completed: ${result.success ? 'success' : 'failed'} (exit code: ${result.exit_code})`);
2023
2319
  // Send result back to Type 1
2024
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2025
- this.marketplaceWs.send(JSON.stringify({
2320
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2321
+ this.registryWs.send(JSON.stringify({
2026
2322
  event: 'script_result',
2027
2323
  requestId,
2028
2324
  success: true,
@@ -2046,8 +2342,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2046
2342
  * Send script execution error to Type 1
2047
2343
  */
2048
2344
  sendScriptError(requestId, code, message) {
2049
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2050
- this.marketplaceWs.send(JSON.stringify({
2345
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2346
+ this.registryWs.send(JSON.stringify({
2051
2347
  event: 'script_result',
2052
2348
  requestId,
2053
2349
  success: false,
@@ -2079,8 +2375,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2079
2375
  // autoUpdate defaults to true if not explicitly set to false
2080
2376
  const shouldAutoUpdate = mandatory || (autoUpdate !== false);
2081
2377
  // Send acknowledgment to Type 1
2082
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2083
- this.marketplaceWs.send(JSON.stringify({
2378
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2379
+ this.registryWs.send(JSON.stringify({
2084
2380
  event: 'update_acknowledged',
2085
2381
  gatewayId: this.instanceId,
2086
2382
  currentVersion: this.currentVersion,
@@ -2115,8 +2411,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2115
2411
  console.log(`[${this.nodeId}] 🚨 Immediate update requested: v${version}`);
2116
2412
  console.log(`[${this.nodeId}] Reason: ${reason || 'No reason provided'}`);
2117
2413
  // Acknowledge the update command
2118
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2119
- this.marketplaceWs.send(JSON.stringify({
2414
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2415
+ this.registryWs.send(JSON.stringify({
2120
2416
  event: 'update_starting',
2121
2417
  gatewayId: this.instanceId,
2122
2418
  currentVersion: this.currentVersion,
@@ -2227,8 +2523,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2227
2523
  if (resolvedTargetVersion && this.currentVersion === resolvedTargetVersion) {
2228
2524
  console.log(`[${this.nodeId}] ✅ Already at version v${this.currentVersion}, skipping update`);
2229
2525
  // Notify Type 1 that no update is needed
2230
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2231
- this.marketplaceWs.send(JSON.stringify({
2526
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2527
+ this.registryWs.send(JSON.stringify({
2232
2528
  event: 'already_up_to_date',
2233
2529
  gatewayId: this.instanceId,
2234
2530
  currentVersion: this.currentVersion,
@@ -2270,8 +2566,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2270
2566
  }
2271
2567
  console.log(`[${this.nodeId}] ✓ Package installed successfully`);
2272
2568
  // Step 2: Notify Type 1 of successful install
2273
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2274
- this.marketplaceWs.send(JSON.stringify({
2569
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2570
+ this.registryWs.send(JSON.stringify({
2275
2571
  event: 'update_installed',
2276
2572
  gatewayId: this.instanceId,
2277
2573
  previousVersion: this.currentVersion,
@@ -2283,8 +2579,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2283
2579
  // Step 3: Graceful restart
2284
2580
  console.log(`[${this.nodeId}] Step 2: Initiating graceful restart...`);
2285
2581
  // Close WebSocket cleanly
2286
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2287
- this.marketplaceWs.send(JSON.stringify({
2582
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2583
+ this.registryWs.send(JSON.stringify({
2288
2584
  event: 'gateway_restarting',
2289
2585
  gatewayId: this.instanceId,
2290
2586
  reason: 'update',
@@ -2333,8 +2629,8 @@ class Type3GatewayServer extends events_1.EventEmitter {
2333
2629
  console.error(`[${this.nodeId}] ❌ Update failed:`, error.message);
2334
2630
  this.isUpdating = false;
2335
2631
  // Notify Type 1 of failure
2336
- if (this.marketplaceWs?.readyState === ws_1.default.OPEN) {
2337
- this.marketplaceWs.send(JSON.stringify({
2632
+ if (this.registryWs?.readyState === ws_1.default.OPEN) {
2633
+ this.registryWs.send(JSON.stringify({
2338
2634
  event: 'update_failed',
2339
2635
  gatewayId: this.instanceId,
2340
2636
  currentVersion: this.currentVersion,
@@ -2384,9 +2680,9 @@ class Type3GatewayServer extends events_1.EventEmitter {
2384
2680
  console.log(`[${this.nodeId}] Waiting for ${this.activeRequests.size} active requests...`);
2385
2681
  await new Promise(resolve => setTimeout(resolve, 1000));
2386
2682
  }
2387
- // Close marketplace WebSocket
2388
- if (this.marketplaceWs) {
2389
- this.marketplaceWs.close();
2683
+ // Close registry WebSocket
2684
+ if (this.registryWs) {
2685
+ this.registryWs.close();
2390
2686
  }
2391
2687
  // Close management API server
2392
2688
  if (this.managementServer) {
@@ -2407,7 +2703,7 @@ exports.Type3GatewayServer = Type3GatewayServer;
2407
2703
  if (require.main === module) {
2408
2704
  const gateway = new Type3GatewayServer({
2409
2705
  port: parseInt(process.env.GATEWAY_PORT || '8083'),
2410
- marketplaceUrl: process.env.MARKETPLACE_URL,
2706
+ registryUrl: process.env.REGISTRY_URL,
2411
2707
  instanceId: process.env.INSTANCE_ID,
2412
2708
  apiKey: process.env.GATEWAY_API_KEY,
2413
2709
  vaultPath: process.env.VAULT_PATH,