@jait/gateway 0.1.529 → 0.1.531

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/routes/chat.d.ts.map +1 -1
  2. package/dist/routes/chat.js +71 -4
  3. package/dist/routes/chat.js.map +1 -1
  4. package/dist/tools/agent-loop.js +1 -1
  5. package/package.json +1 -1
  6. package/web-dist/assets/{_basePickBy-DmZcWCG-.js → _basePickBy-6gbrwdOi.js} +1 -1
  7. package/web-dist/assets/{_baseUniq-CwRdJULm.js → _baseUniq-CLclGSyy.js} +1 -1
  8. package/web-dist/assets/{arc-CkI9iGuh.js → arc-B5r04Gwe.js} +1 -1
  9. package/web-dist/assets/{architectureDiagram-2XIMDMQ5-BC1ssl2b.js → architectureDiagram-2XIMDMQ5-D3MOUVyl.js} +1 -1
  10. package/web-dist/assets/{blockDiagram-WCTKOSBZ-3gRsHnzH.js → blockDiagram-WCTKOSBZ-CHS2og4n.js} +1 -1
  11. package/web-dist/assets/{c4Diagram-IC4MRINW-BfcXGNTs.js → c4Diagram-IC4MRINW-CYOb6MEW.js} +1 -1
  12. package/web-dist/assets/channel-Dw4Zr1sq.js +1 -0
  13. package/web-dist/assets/{chunk-4BX2VUAB-DJpHkeL4.js → chunk-4BX2VUAB-B1jW4Ms3.js} +1 -1
  14. package/web-dist/assets/{chunk-55IACEB6-BNupIEMy.js → chunk-55IACEB6-DzihhO9t.js} +1 -1
  15. package/web-dist/assets/{chunk-FMBD7UC4-C9ngtn2O.js → chunk-FMBD7UC4-D0MnV9fW.js} +1 -1
  16. package/web-dist/assets/{chunk-JSJVCQXG-D1PRvwG7.js → chunk-JSJVCQXG-DrbVcl-5.js} +1 -1
  17. package/web-dist/assets/{chunk-KX2RTZJC-yiEaQCf9.js → chunk-KX2RTZJC-BCc0Yqn4.js} +1 -1
  18. package/web-dist/assets/{chunk-NQ4KR5QH-13PXNlKH.js → chunk-NQ4KR5QH-levMxM4r.js} +1 -1
  19. package/web-dist/assets/{chunk-QZHKN3VN-B1SbuNgF.js → chunk-QZHKN3VN-CXMrHT3y.js} +1 -1
  20. package/web-dist/assets/{chunk-WL4C6EOR-D4PWfANs.js → chunk-WL4C6EOR-CThierD0.js} +1 -1
  21. package/web-dist/assets/classDiagram-VBA2DB6C-BFWKB-8l.js +1 -0
  22. package/web-dist/assets/classDiagram-v2-RAHNMMFH-BFWKB-8l.js +1 -0
  23. package/web-dist/assets/clone-D7D8dEeq.js +1 -0
  24. package/web-dist/assets/{cose-bilkent-S5V4N54A-BgQYmR_e.js → cose-bilkent-S5V4N54A-D15TrLIx.js} +1 -1
  25. package/web-dist/assets/{dagre-KLK3FWXG-DQq4OTGc.js → dagre-KLK3FWXG-D_OfpM6x.js} +1 -1
  26. package/web-dist/assets/{diagram-E7M64L7V-Dg0QCbuR.js → diagram-E7M64L7V-bgsEvM5f.js} +1 -1
  27. package/web-dist/assets/{diagram-IFDJBPK2-CNv1xgxA.js → diagram-IFDJBPK2-K45k96WH.js} +1 -1
  28. package/web-dist/assets/{diagram-P4PSJMXO-D-Dca0sk.js → diagram-P4PSJMXO-6RHgUjio.js} +1 -1
  29. package/web-dist/assets/{erDiagram-INFDFZHY-Dod2pK87.js → erDiagram-INFDFZHY-CcAGrear.js} +1 -1
  30. package/web-dist/assets/{flowDiagram-PKNHOUZH-C-YMgFQ4.js → flowDiagram-PKNHOUZH-BdW2n_gc.js} +1 -1
  31. package/web-dist/assets/{ganttDiagram-A5KZAMGK-C7AlDm2_.js → ganttDiagram-A5KZAMGK-DH6klBBb.js} +2 -2
  32. package/web-dist/assets/{gitGraphDiagram-K3NZZRJ6-BOR4arme.js → gitGraphDiagram-K3NZZRJ6-eIW10pOd.js} +1 -1
  33. package/web-dist/assets/{graph-CSh0XZ0Y.js → graph-C7VaVDoH.js} +1 -1
  34. package/web-dist/assets/index-Bnl8Ohl4.js +1551 -0
  35. package/web-dist/assets/{index-VYQxyqJS.js → index-Cu1IqX1I.js} +1 -1
  36. package/web-dist/assets/index-DB1Lg9G-.css +32 -0
  37. package/web-dist/assets/{index-CoNBsQ9X.js → index-sExQYbX3.js} +1 -1
  38. package/web-dist/assets/{infoDiagram-LFFYTUFH-BTBnA-wy.js → infoDiagram-LFFYTUFH-Dx5DmT1a.js} +1 -1
  39. package/web-dist/assets/{ishikawaDiagram-PHBUUO56-TCNUV9q2.js → ishikawaDiagram-PHBUUO56-DcRTzEhY.js} +1 -1
  40. package/web-dist/assets/{journeyDiagram-4ABVD52K-XPyxDGAA.js → journeyDiagram-4ABVD52K-CrNyi08J.js} +1 -1
  41. package/web-dist/assets/{kanban-definition-K7BYSVSG-ZJKM-OoN.js → kanban-definition-K7BYSVSG-Bs9zazws.js} +1 -1
  42. package/web-dist/assets/{layout-5z9N8PQN.js → layout-Dx0mG9Jz.js} +1 -1
  43. package/web-dist/assets/{linear-D1-6MqIt.js → linear-CdAkZv2Z.js} +1 -1
  44. package/web-dist/assets/{mindmap-definition-YRQLILUH-ByijwJGj.js → mindmap-definition-YRQLILUH-CxOoMdff.js} +1 -1
  45. package/web-dist/assets/{pieDiagram-SKSYHLDU-CXS5bwEQ.js → pieDiagram-SKSYHLDU-BbnqxBRp.js} +1 -1
  46. package/web-dist/assets/{quadrantDiagram-337W2JSQ-BNiTM28o.js → quadrantDiagram-337W2JSQ-Dbh9SOrv.js} +1 -1
  47. package/web-dist/assets/{requirementDiagram-Z7DCOOCP-muKDKUAK.js → requirementDiagram-Z7DCOOCP-BxZr9lWB.js} +1 -1
  48. package/web-dist/assets/{sankeyDiagram-WA2Y5GQK-DgrtvNUm.js → sankeyDiagram-WA2Y5GQK-8CRcxOvo.js} +1 -1
  49. package/web-dist/assets/{sequenceDiagram-2WXFIKYE-Bfl_RYF8.js → sequenceDiagram-2WXFIKYE-DzGGauor.js} +1 -1
  50. package/web-dist/assets/{stateDiagram-RAJIS63D-Cp7FYiSc.js → stateDiagram-RAJIS63D-2fMb93GR.js} +1 -1
  51. package/web-dist/assets/stateDiagram-v2-FVOUBMTO-D2RSBHbB.js +1 -0
  52. package/web-dist/assets/{timeline-definition-YZTLITO2-BHiQfvN6.js → timeline-definition-YZTLITO2-0xN3oPFy.js} +1 -1
  53. package/web-dist/assets/{treemap-KZPCXAKY-luRVSDRQ.js → treemap-KZPCXAKY-aJPlD6Fm.js} +1 -1
  54. package/web-dist/assets/{vennDiagram-LZ73GAT5-CPASq26G.js → vennDiagram-LZ73GAT5-DItPYlTj.js} +1 -1
  55. package/web-dist/assets/{xychartDiagram-JWTSCODW-DUreFySj.js → xychartDiagram-JWTSCODW-CcVMY8dm.js} +1 -1
  56. package/web-dist/index.html +2 -2
  57. package/web-dist/assets/channel-DoXVuwHd.js +0 -1
  58. package/web-dist/assets/classDiagram-VBA2DB6C-DhbnKCEN.js +0 -1
  59. package/web-dist/assets/classDiagram-v2-RAHNMMFH-DhbnKCEN.js +0 -1
  60. package/web-dist/assets/clone-CJ1i-Vxw.js +0 -1
  61. package/web-dist/assets/index-BZrUCLxt.css +0 -32
  62. package/web-dist/assets/index-BdRNueib.js +0 -1546
  63. package/web-dist/assets/stateDiagram-v2-FVOUBMTO-S06SqBtH.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,uBAAuB,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAe,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAgCjE,OAAO,KAAK,EAAS,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAgGvF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBrE;AAyED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE3D;AAqbD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyCtF;AA+hBD,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;IAClD,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KACtD,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa,EACjC,iBAAiB,CAAC,EAAE,cAAc,QAyiEnC"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/routes/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,uBAAuB,CAAC;AACnF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAe,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAgCjE,OAAO,KAAK,EAAS,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAgGvF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBrE;AAyED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE3D;AAscD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyCtF;AA+hBD,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;IAClD,YAAY,CAAC,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,KACtD,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,SAAS,EACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa,EACjC,iBAAiB,CAAC,EAAE,cAAc,QAgmEnC"}
@@ -414,6 +414,7 @@ function parseQueuedChatMessages(raw) {
414
414
  queue.push({
415
415
  id: typeof record.id === "string" ? record.id : undefined,
416
416
  content: record.content,
417
+ queuedAt: typeof record.queuedAt === "number" ? record.queuedAt : undefined,
417
418
  mode: isValidChatMode(record.mode) ? record.mode : undefined,
418
419
  provider: record.provider === "jait" || record.provider === "codex" || record.provider === "claude-code"
419
420
  ? record.provider
@@ -422,6 +423,21 @@ function parseQueuedChatMessages(raw) {
422
423
  ? record.runtimeMode
423
424
  : undefined,
424
425
  model: typeof record.model === "string" ? record.model : null,
426
+ responseStyle: isResponseStyle(record.responseStyle) ? record.responseStyle : undefined,
427
+ attachments: Array.isArray(record.attachments)
428
+ ? record.attachments.flatMap((attachment) => {
429
+ if (!attachment || typeof attachment !== "object")
430
+ return [];
431
+ const candidate = attachment;
432
+ if (typeof candidate.name !== "string" || typeof candidate.data !== "string")
433
+ return [];
434
+ return [{
435
+ name: candidate.name,
436
+ mimeType: typeof candidate.mimeType === "string" ? candidate.mimeType : "application/octet-stream",
437
+ data: candidate.data,
438
+ }];
439
+ })
440
+ : undefined,
425
441
  displaySegments,
426
442
  });
427
443
  }
@@ -1056,8 +1072,10 @@ export function registerChatRoutes(app, config, depsOrDb, sessionServiceArg) {
1056
1072
  ...(nextMessage.mode ? { mode: nextMessage.mode } : {}),
1057
1073
  ...(nextMessage.provider ? { provider: nextMessage.provider } : {}),
1058
1074
  ...(nextMessage.runtimeMode ? { runtimeMode: nextMessage.runtimeMode } : {}),
1075
+ ...(nextMessage.responseStyle ? { responseStyle: nextMessage.responseStyle } : {}),
1059
1076
  ...(nextMessage.model ? { model: nextMessage.model } : {}),
1060
1077
  ...(nextMessage.displaySegments ? { displaySegments: nextMessage.displaySegments } : {}),
1078
+ ...(nextMessage.attachments?.length ? { attachments: nextMessage.attachments } : {}),
1061
1079
  _queuedDrain: true,
1062
1080
  },
1063
1081
  });
@@ -1280,6 +1298,7 @@ export function registerChatRoutes(app, config, depsOrDb, sessionServiceArg) {
1280
1298
  : randomUUID();
1281
1299
  const chatMode = isValidChatMode(body["mode"]) ? body["mode"] : "agent";
1282
1300
  const responseStyle = isResponseStyle(body["responseStyle"]) ? body["responseStyle"] : "normal";
1301
+ const requestBodyModel = typeof body["model"] === "string" ? body["model"].trim() : "";
1283
1302
  let requestProvider = typeof body["provider"] === "string"
1284
1303
  ? body["provider"]
1285
1304
  : undefined;
@@ -1316,9 +1335,49 @@ export function registerChatRoutes(app, config, depsOrDb, sessionServiceArg) {
1316
1335
  sessionService.update(sessionId, { name: deriveSessionTitle(content) }, authUser.id);
1317
1336
  }
1318
1337
  }
1338
+ if (!isQueuedDrainRequest && activeStreams.has(sessionId)) {
1339
+ if (!sessionStateService) {
1340
+ return reply.status(409).send({ error: "CONFLICT", details: "Session is already streaming" });
1341
+ }
1342
+ const existingState = sessionStateService.get(sessionId, ["queued_messages"]);
1343
+ const queue = parseQueuedChatMessages(existingState["queued_messages"]);
1344
+ const queuedMessage = {
1345
+ id: `q-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1346
+ content,
1347
+ queuedAt: Date.now(),
1348
+ mode: chatMode,
1349
+ ...(requestProvider ? { provider: requestProvider } : {}),
1350
+ ...(requestRuntimeMode ? { runtimeMode: requestRuntimeMode } : {}),
1351
+ ...(responseStyle !== "normal" ? { responseStyle } : {}),
1352
+ ...(requestBodyModel ? { model: requestBodyModel } : {}),
1353
+ ...(displaySegments ? { displaySegments } : {}),
1354
+ ...(attachments.length ? { attachments } : {}),
1355
+ };
1356
+ const nextQueue = [...queue, queuedMessage];
1357
+ sessionStateService.set(sessionId, { queued_messages: nextQueue });
1358
+ broadcastQueuedMessagesState(sessionId, nextQueue);
1359
+ const reqOrigin = request.headers.origin ?? "*";
1360
+ reply.raw.writeHead(202, {
1361
+ "Content-Type": "text/event-stream",
1362
+ "Cache-Control": "no-cache",
1363
+ Connection: "keep-alive",
1364
+ "X-Accel-Buffering": "no",
1365
+ "Access-Control-Allow-Origin": reqOrigin,
1366
+ "Access-Control-Allow-Credentials": "true",
1367
+ });
1368
+ const queuedEvent = {
1369
+ type: "queued",
1370
+ session_id: sessionId,
1371
+ message: queuedMessage,
1372
+ queue_length: nextQueue.length,
1373
+ };
1374
+ reply.raw.write(`data: ${JSON.stringify(queuedEvent)}\n\n`);
1375
+ reply.raw.write(`data: ${JSON.stringify({ type: "done", session_id: sessionId, prompt_count: null, remaining_prompts: null })}\n\n`);
1376
+ reply.raw.end();
1377
+ return;
1378
+ }
1319
1379
  const userSettings = userService?.getSettings(authUser.id);
1320
1380
  const userApiKeys = userSettings?.apiKeys ?? {};
1321
- const requestBodyModel = typeof body["model"] === "string" ? body["model"].trim() : "";
1322
1381
  const jaitCoordinatorModel = swarmWorkerProvider ? "" : requestBodyModel;
1323
1382
  // Use the user's preferred backend, but fall back to the server-level config
1324
1383
  // when the user still has the initial default ("openai") and the server is
@@ -1545,13 +1604,21 @@ export function registerChatRoutes(app, config, depsOrDb, sessionServiceArg) {
1545
1604
  let isRemote = false;
1546
1605
  let remoteNodeInfo = null;
1547
1606
  if (!pathExistsLocally && ws) {
1548
- // Match path platform to connected FsNodes
1607
+ const remoteSurfaceNodeId = surfaceRegistry?.getBySession(sessionId)
1608
+ .map((surface) => surface.snapshot().metadata)
1609
+ .find((metadata) => metadata?.remote === true && typeof metadata.nodeId === "string")
1610
+ ?.nodeId;
1611
+ // Prefer the node that owns the active remote filesystem surface. If
1612
+ // no surface is available, fall back to matching by path platform.
1549
1613
  const isWindowsPath = /^[A-Za-z]:[\\/]/.test(cliWsRoot);
1550
1614
  const expectedPlatform = isWindowsPath ? "windows" : null;
1551
- for (const node of ws.getFsNodes()) {
1615
+ const candidateNodes = remoteSurfaceNodeId
1616
+ ? ws.getFsNodes().filter((node) => node.id === remoteSurfaceNodeId)
1617
+ : ws.getFsNodes();
1618
+ for (const node of candidateNodes) {
1552
1619
  if (node.isGateway)
1553
1620
  continue;
1554
- if (expectedPlatform && node.platform !== expectedPlatform)
1621
+ if (!remoteSurfaceNodeId && expectedPlatform && node.platform !== expectedPlatform)
1555
1622
  continue;
1556
1623
  if (!node.providers?.includes(requestProvider))
1557
1624
  continue;