@rubytech/create-realagent 1.0.678 → 1.0.681

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 (60) hide show
  1. package/dist/index.js +232 -39
  2. package/package.json +1 -1
  3. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts +2 -0
  4. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.d.ts.map +1 -0
  5. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js +112 -0
  6. package/payload/platform/lib/graph-mcp/dist/__tests__/cypher-validate.test.js.map +1 -0
  7. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts +2 -0
  8. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.d.ts.map +1 -0
  9. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js +163 -0
  10. package/payload/platform/lib/graph-mcp/dist/__tests__/schema-cache.test.js.map +1 -0
  11. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts +38 -0
  12. package/payload/platform/lib/graph-mcp/dist/cypher-validate.d.ts.map +1 -0
  13. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js +130 -0
  14. package/payload/platform/lib/graph-mcp/dist/cypher-validate.js.map +1 -0
  15. package/payload/platform/lib/graph-mcp/dist/index.js +201 -45
  16. package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
  17. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts +78 -0
  18. package/payload/platform/lib/graph-mcp/dist/schema-cache.d.ts.map +1 -0
  19. package/payload/platform/lib/graph-mcp/dist/schema-cache.js +194 -0
  20. package/payload/platform/lib/graph-mcp/dist/schema-cache.js.map +1 -0
  21. package/payload/platform/lib/graph-mcp/src/__tests__/cypher-validate.test.ts +141 -0
  22. package/payload/platform/lib/graph-mcp/src/__tests__/schema-cache.test.ts +169 -0
  23. package/payload/platform/lib/graph-mcp/src/cypher-validate.ts +157 -0
  24. package/payload/platform/lib/graph-mcp/src/index.ts +247 -47
  25. package/payload/platform/lib/graph-mcp/src/schema-cache.ts +212 -0
  26. package/payload/platform/lib/graph-trash/dist/index.d.ts +8 -0
  27. package/payload/platform/lib/graph-trash/dist/index.d.ts.map +1 -1
  28. package/payload/platform/lib/graph-trash/dist/index.js +109 -14
  29. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  30. package/payload/platform/lib/graph-trash/src/index.ts +136 -21
  31. package/payload/platform/plugins/docs/references/deployment.md +4 -2
  32. package/payload/platform/plugins/docs/references/memory-guide.md +5 -1
  33. package/payload/platform/plugins/docs/references/platform.md +1 -1
  34. package/payload/platform/plugins/docs/references/troubleshooting.md +20 -0
  35. package/payload/platform/plugins/memory/PLUGIN.md +1 -0
  36. package/payload/platform/plugins/memory/mcp/dist/index.js +54 -6
  37. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts +36 -0
  39. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.d.ts.map +1 -0
  40. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js +86 -0
  41. package/payload/platform/plugins/memory/mcp/dist/lib/filter-token.js.map +1 -0
  42. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +23 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +47 -1
  45. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +58 -0
  47. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -0
  48. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +125 -0
  49. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -0
  50. package/payload/platform/scripts/vnc.sh +12 -409
  51. package/payload/platform/templates/agents/admin/IDENTITY.md +16 -0
  52. package/payload/platform/templates/dotfiles/.tmux.conf +1 -0
  53. package/payload/platform/templates/systemd/maxy-ttyd.service +25 -0
  54. package/payload/server/chunk-3RBKKDHC.js +783 -0
  55. package/payload/server/maxy-edge.js +377 -8
  56. package/payload/server/public/assets/admin-CIkyOur7.js +362 -0
  57. package/payload/server/public/assets/admin-kHJ-D0s7.css +1 -0
  58. package/payload/server/public/index.html +2 -1
  59. package/payload/server/server.js +391 -412
  60. package/payload/server/public/assets/admin-BBL1no_g.js +0 -352
@@ -1,13 +1,16 @@
1
1
  import {
2
+ LOG_DIR,
2
3
  canAccessAdmin,
4
+ describeRemoteSession,
3
5
  newCorrId,
6
+ parseCookieValue,
4
7
  sanitizeClientCorrId,
5
8
  vncLog
6
- } from "./chunk-5YIXIF6C.js";
9
+ } from "./chunk-3RBKKDHC.js";
7
10
 
8
11
  // server/maxy-edge.ts
9
12
  import { createServer, request as httpRequest } from "http";
10
- import { createConnection as createConnection2 } from "net";
13
+ import { createConnection as createConnection3 } from "net";
11
14
  import { readFileSync, existsSync, watchFile } from "fs";
12
15
  import { homedir } from "os";
13
16
  import { join } from "path";
@@ -61,15 +64,18 @@ function handleUpgrade(req, clientSocket, head, opts) {
61
64
  const originHeader = headerString(req.headers.origin);
62
65
  const remote = req.socket.remoteAddress;
63
66
  const xff = headerString(req.headers["x-forwarded-for"]);
67
+ const cookieHeader = headerString(req.headers.cookie);
64
68
  const decision = canAccessAdmin({
65
69
  host: hostHeader,
66
70
  remoteAddress: remote,
67
71
  xForwardedFor: xff,
68
- cookieHeader: headerString(req.headers.cookie),
72
+ cookieHeader,
69
73
  isPublicHost: opts.isPublicHost
70
74
  });
71
75
  if (!decision.allow) {
72
76
  const status = decision.reason === "public-host" ? 404 : 401;
77
+ const rawToken = parseCookieValue(cookieHeader, "__remote_session");
78
+ const tokenInfo = describeRemoteSession(rawToken);
73
79
  vncLog("ws-upgrade", {
74
80
  corrId,
75
81
  clientCorrId: clientCorrId ?? null,
@@ -78,7 +84,10 @@ function handleUpgrade(req, clientSocket, head, opts) {
78
84
  ip: remote,
79
85
  xff: xff ?? null,
80
86
  origin: originHeader ?? null,
81
- host: hostHeader
87
+ host: hostHeader,
88
+ cookieHeaderPresent: cookieHeader != null && cookieHeader.length > 0,
89
+ tokenPresent: tokenInfo.present,
90
+ tokenExpired: tokenInfo.expired
82
91
  });
83
92
  writeStatusAndDestroy(clientSocket, status, decision.reason === "public-host" ? "Not Found" : "Unauthorized");
84
93
  return;
@@ -267,6 +276,357 @@ Content-Length: 0\r
267
276
  socket.destroy();
268
277
  }
269
278
 
279
+ // server/ws-proxy-ttyd.ts
280
+ import { createConnection as createConnection2 } from "net";
281
+
282
+ // app/lib/ttyd-logger.ts
283
+ import { appendFileSync, mkdirSync } from "fs";
284
+ import { resolve } from "path";
285
+ var EDGE_LOG_FILE = resolve(LOG_DIR, "edge-boot.log");
286
+ try {
287
+ mkdirSync(LOG_DIR, { recursive: true });
288
+ } catch (err) {
289
+ console.error(`[ttyd-log-fail] mkdir ${LOG_DIR} failed: ${err.message}`);
290
+ }
291
+ function ttydLog(phase, fields = {}) {
292
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
293
+ const kv = Object.entries(fields).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(" ");
294
+ const line = kv.length > 0 ? `[${ts}] [${phase}] ${kv}
295
+ ` : `[${ts}] [${phase}]
296
+ `;
297
+ try {
298
+ appendFileSync(EDGE_LOG_FILE, line);
299
+ } catch (err) {
300
+ console.error(`[ttyd-log-fail] ${err.message} \u2014 dropped: ${line.slice(0, 300).trim()}`);
301
+ }
302
+ }
303
+
304
+ // server/ws-proxy-ttyd.ts
305
+ var WS_PATH2 = "/ttyd";
306
+ var UPSTREAM_TIMEOUT_MS2 = 5e3;
307
+ var FLOW_ACTIVE_INTERVAL_MS = 5e3;
308
+ var FLOW_IDLE_INTERVAL_MS = 3e4;
309
+ var CHUNK_THROTTLE_MS = 1e3;
310
+ var CHUNK_UNTHROTTLED_COUNT = 5;
311
+ var HOP_BY_HOP2 = /* @__PURE__ */ new Set([
312
+ "connection",
313
+ "keep-alive",
314
+ "proxy-authenticate",
315
+ "proxy-authorization",
316
+ "te",
317
+ "trailer",
318
+ "transfer-encoding",
319
+ "upgrade"
320
+ ]);
321
+ function attachTtydWsProxy(server2, opts) {
322
+ const upstreamHost = opts.upstreamHost ?? "127.0.0.1";
323
+ const upstreamPort = opts.upstreamPort ?? 7681;
324
+ const now = opts.now ?? (() => Date.now());
325
+ server2.on("upgrade", (req, clientSocket, head) => {
326
+ try {
327
+ handleUpgrade2(req, clientSocket, head, {
328
+ isPublicHost: opts.isPublicHost,
329
+ upstreamHost,
330
+ upstreamPort,
331
+ now
332
+ });
333
+ } catch (err) {
334
+ ttydLog("ttyd-ws-upgrade", {
335
+ decision: "rejected",
336
+ reason: "handler-exception",
337
+ err: err.message
338
+ });
339
+ clientSocket.destroy();
340
+ }
341
+ });
342
+ }
343
+ function handleUpgrade2(req, clientSocket, head, opts) {
344
+ const url = req.url ?? "";
345
+ const qsIndex = url.indexOf("?");
346
+ const pathname = qsIndex === -1 ? url : url.slice(0, qsIndex);
347
+ if (pathname !== WS_PATH2) return;
348
+ const corrId = newCorrId();
349
+ const query = qsIndex === -1 ? "" : url.slice(qsIndex + 1);
350
+ const clientCorrId = sanitizeClientCorrId(parseQueryParam2(query, "corrId"));
351
+ const hostHeader = (req.headers.host ?? "").split(":")[0];
352
+ const originHeader = headerString2(req.headers.origin);
353
+ const remote = req.socket.remoteAddress;
354
+ const xff = headerString2(req.headers["x-forwarded-for"]);
355
+ const cookieHeader = headerString2(req.headers.cookie);
356
+ const decision = canAccessAdmin({
357
+ host: hostHeader,
358
+ remoteAddress: remote,
359
+ xForwardedFor: xff,
360
+ cookieHeader,
361
+ isPublicHost: opts.isPublicHost
362
+ });
363
+ if (!decision.allow) {
364
+ const status = decision.reason === "public-host" ? 404 : 401;
365
+ const rawToken = parseCookieValue(cookieHeader, "__remote_session");
366
+ const tokenInfo = describeRemoteSession(rawToken);
367
+ ttydLog("ttyd-ws-upgrade", {
368
+ corrId,
369
+ clientCorrId: clientCorrId ?? null,
370
+ decision: "rejected",
371
+ reason: decision.reason,
372
+ ip: remote,
373
+ xff: xff ?? null,
374
+ origin: originHeader ?? null,
375
+ host: hostHeader,
376
+ cookieHeaderPresent: cookieHeader != null && cookieHeader.length > 0,
377
+ tokenPresent: tokenInfo.present,
378
+ tokenExpired: tokenInfo.expired
379
+ });
380
+ writeStatusAndDestroy2(clientSocket, status, decision.reason === "public-host" ? "Not Found" : "Unauthorized");
381
+ return;
382
+ }
383
+ const originHost = parseOriginHost2(originHeader);
384
+ if (!originHost) {
385
+ ttydLog("ttyd-ws-upgrade", {
386
+ corrId,
387
+ clientCorrId: clientCorrId ?? null,
388
+ decision: "rejected",
389
+ reason: "origin-missing-or-invalid",
390
+ origin: originHeader ?? null,
391
+ host: hostHeader,
392
+ ip: remote
393
+ });
394
+ writeStatusAndDestroy2(clientSocket, 403, "Forbidden");
395
+ return;
396
+ }
397
+ if (originHost !== hostHeader) {
398
+ ttydLog("ttyd-ws-upgrade", {
399
+ corrId,
400
+ clientCorrId: clientCorrId ?? null,
401
+ decision: "rejected",
402
+ reason: "origin-mismatch",
403
+ origin_host: originHost,
404
+ host: hostHeader,
405
+ ip: remote
406
+ });
407
+ writeStatusAndDestroy2(clientSocket, 403, "Forbidden");
408
+ return;
409
+ }
410
+ if (opts.isPublicHost(originHost)) {
411
+ ttydLog("ttyd-ws-upgrade", {
412
+ corrId,
413
+ clientCorrId: clientCorrId ?? null,
414
+ decision: "rejected",
415
+ reason: "origin-public-host",
416
+ origin_host: originHost,
417
+ host: hostHeader,
418
+ ip: remote
419
+ });
420
+ writeStatusAndDestroy2(clientSocket, 403, "Forbidden");
421
+ return;
422
+ }
423
+ ttydLog("ttyd-ws-upgrade", {
424
+ corrId,
425
+ clientCorrId: clientCorrId ?? null,
426
+ decision: "accepted",
427
+ ip: remote,
428
+ xff: xff ?? null,
429
+ origin: originHeader ?? null,
430
+ host: hostHeader,
431
+ sec_ws_version: headerString2(req.headers["sec-websocket-version"]) ?? null,
432
+ sec_ws_protocol: headerString2(req.headers["sec-websocket-protocol"]) ?? null
433
+ });
434
+ const connectStart = opts.now();
435
+ const upstream = createConnection2({ host: opts.upstreamHost, port: opts.upstreamPort });
436
+ upstream.setTimeout(UPSTREAM_TIMEOUT_MS2);
437
+ let bytesClientToUpstream = 0;
438
+ let bytesUpstreamToClient = 0;
439
+ let lastFlowBytesClient = 0;
440
+ let lastFlowBytesUpstream = 0;
441
+ let lastActivityAt = opts.now();
442
+ let lastChunkLogAtClient = 0;
443
+ let lastChunkLogAtUpstream = 0;
444
+ let chunkCountClient = 0;
445
+ let chunkCountUpstream = 0;
446
+ let closedBy = null;
447
+ let proxyOpened = false;
448
+ const sessionStart = opts.now();
449
+ let flowHandle = null;
450
+ let currentFlowInterval = FLOW_ACTIVE_INTERVAL_MS;
451
+ const scheduleFlow = (intervalMs) => {
452
+ if (flowHandle) clearInterval(flowHandle);
453
+ currentFlowInterval = intervalMs;
454
+ flowHandle = setInterval(emitFlow, intervalMs);
455
+ };
456
+ const emitFlow = () => {
457
+ if (!proxyOpened || closedBy) return;
458
+ const deltaClient = bytesClientToUpstream - lastFlowBytesClient;
459
+ const deltaUpstream = bytesUpstreamToClient - lastFlowBytesUpstream;
460
+ lastFlowBytesClient = bytesClientToUpstream;
461
+ lastFlowBytesUpstream = bytesUpstreamToClient;
462
+ const idleMs = opts.now() - lastActivityAt;
463
+ ttydLog("ttyd-proxy-flow", {
464
+ corrId,
465
+ clientBytes: bytesClientToUpstream,
466
+ upstreamBytes: bytesUpstreamToClient,
467
+ clientBytesDelta: deltaClient,
468
+ upstreamBytesDelta: deltaUpstream,
469
+ idleMs
470
+ });
471
+ const active = deltaClient > 0 || deltaUpstream > 0;
472
+ const desiredInterval = active ? FLOW_ACTIVE_INTERVAL_MS : FLOW_IDLE_INTERVAL_MS;
473
+ if (desiredInterval !== currentFlowInterval) scheduleFlow(desiredInterval);
474
+ };
475
+ const finish = (side, reason) => {
476
+ if (closedBy) return;
477
+ closedBy = side;
478
+ if (flowHandle) {
479
+ clearInterval(flowHandle);
480
+ flowHandle = null;
481
+ }
482
+ if (proxyOpened) {
483
+ ttydLog("ttyd-proxy-close", {
484
+ corrId,
485
+ closedBy: side,
486
+ reason,
487
+ clientBytes: bytesClientToUpstream,
488
+ upstreamBytes: bytesUpstreamToClient,
489
+ durationMs: opts.now() - sessionStart
490
+ });
491
+ }
492
+ clientSocket.destroy();
493
+ upstream.destroy();
494
+ };
495
+ upstream.once("connect", () => {
496
+ upstream.setTimeout(0);
497
+ proxyOpened = true;
498
+ ttydLog("ttyd-proxy-open", {
499
+ corrId,
500
+ upstream: `${opts.upstreamHost}:${opts.upstreamPort}`,
501
+ connect_ms: opts.now() - connectStart
502
+ });
503
+ const lines = [];
504
+ lines.push(`${req.method ?? "GET"} ${WS_PATH2} HTTP/${req.httpVersion}`);
505
+ lines.push(`host: ${opts.upstreamHost}:${opts.upstreamPort}`);
506
+ for (const [name, value] of Object.entries(req.headers)) {
507
+ if (name === "host") continue;
508
+ if (HOP_BY_HOP2.has(name)) continue;
509
+ if (value == null) continue;
510
+ if (Array.isArray(value)) {
511
+ for (const v of value) lines.push(`${name}: ${v}`);
512
+ } else {
513
+ lines.push(`${name}: ${value}`);
514
+ }
515
+ }
516
+ const upgradeHeader = headerString2(req.headers.upgrade);
517
+ const connectionHeader = headerString2(req.headers.connection);
518
+ if (upgradeHeader) lines.push(`upgrade: ${upgradeHeader}`);
519
+ if (connectionHeader) lines.push(`connection: ${connectionHeader}`);
520
+ upstream.write(lines.join("\r\n") + "\r\n\r\n");
521
+ if (head && head.length > 0) upstream.write(head);
522
+ const logChunk = (dir, bytes) => {
523
+ const now = opts.now();
524
+ if (dir === "client\u2192upstream") {
525
+ chunkCountClient += 1;
526
+ const sinceLastMs = lastChunkLogAtClient === 0 ? 0 : now - lastChunkLogAtClient;
527
+ if (chunkCountClient <= CHUNK_UNTHROTTLED_COUNT || sinceLastMs >= CHUNK_THROTTLE_MS) {
528
+ ttydLog("ttyd-proxy-chunk", { corrId, dir, bytes, sinceLastMs });
529
+ lastChunkLogAtClient = now;
530
+ }
531
+ } else {
532
+ chunkCountUpstream += 1;
533
+ const sinceLastMs = lastChunkLogAtUpstream === 0 ? 0 : now - lastChunkLogAtUpstream;
534
+ if (chunkCountUpstream <= CHUNK_UNTHROTTLED_COUNT || sinceLastMs >= CHUNK_THROTTLE_MS) {
535
+ ttydLog("ttyd-proxy-chunk", { corrId, dir, bytes, sinceLastMs });
536
+ lastChunkLogAtUpstream = now;
537
+ }
538
+ }
539
+ lastActivityAt = now;
540
+ };
541
+ clientSocket.on("data", (chunk) => {
542
+ bytesClientToUpstream += chunk.length;
543
+ logChunk("client\u2192upstream", chunk.length);
544
+ });
545
+ upstream.on("data", (chunk) => {
546
+ bytesUpstreamToClient += chunk.length;
547
+ logChunk("upstream\u2192client", chunk.length);
548
+ });
549
+ clientSocket.pipe(upstream);
550
+ upstream.pipe(clientSocket);
551
+ scheduleFlow(FLOW_ACTIVE_INTERVAL_MS);
552
+ clientSocket.once("close", (hadError) => {
553
+ finish("client", hadError ? "error" : "normal");
554
+ });
555
+ upstream.once("close", (hadError) => {
556
+ finish("upstream", hadError ? "error" : "normal");
557
+ });
558
+ clientSocket.once("error", (err) => {
559
+ ttydLog("ttyd-proxy-error", { corrId, side: "client", err: err.message });
560
+ finish("client", "error");
561
+ });
562
+ upstream.once("error", (err) => {
563
+ ttydLog("ttyd-proxy-error", { corrId, side: "upstream", err: err.message });
564
+ finish("upstream", "error");
565
+ });
566
+ });
567
+ upstream.once("timeout", () => {
568
+ if (proxyOpened) return;
569
+ ttydLog("ttyd-proxy-error", {
570
+ corrId,
571
+ side: "upstream-connect",
572
+ err: "timeout",
573
+ timeout_ms: UPSTREAM_TIMEOUT_MS2
574
+ });
575
+ writeStatusAndDestroy2(clientSocket, 504, "Gateway Timeout");
576
+ upstream.destroy();
577
+ });
578
+ upstream.once("error", (err) => {
579
+ if (proxyOpened) return;
580
+ ttydLog("ttyd-proxy-error", {
581
+ corrId,
582
+ side: "upstream-connect",
583
+ err: err.message
584
+ });
585
+ writeStatusAndDestroy2(clientSocket, 502, "Bad Gateway");
586
+ upstream.destroy();
587
+ });
588
+ }
589
+ function parseQueryParam2(query, key) {
590
+ if (!query) return null;
591
+ for (const pair of query.split("&")) {
592
+ const eq = pair.indexOf("=");
593
+ const k = eq === -1 ? pair : pair.slice(0, eq);
594
+ if (k !== key) continue;
595
+ const v = eq === -1 ? "" : pair.slice(eq + 1);
596
+ try {
597
+ return decodeURIComponent(v);
598
+ } catch {
599
+ return null;
600
+ }
601
+ }
602
+ return null;
603
+ }
604
+ function headerString2(value) {
605
+ if (value == null) return void 0;
606
+ return Array.isArray(value) ? value[0] : value;
607
+ }
608
+ function parseOriginHost2(origin) {
609
+ if (!origin) return null;
610
+ try {
611
+ return new URL(origin).hostname;
612
+ } catch {
613
+ return null;
614
+ }
615
+ }
616
+ function writeStatusAndDestroy2(socket, status, statusText) {
617
+ try {
618
+ socket.write(
619
+ `HTTP/1.1 ${status} ${statusText}\r
620
+ Connection: close\r
621
+ Content-Length: 0\r
622
+ \r
623
+ `
624
+ );
625
+ } catch {
626
+ }
627
+ socket.destroy();
628
+ }
629
+
270
630
  // server/maxy-edge.ts
271
631
  var PLATFORM_ROOT = process.env.MAXY_PLATFORM_ROOT || "";
272
632
  var BRAND_JSON_PATH = PLATFORM_ROOT ? join(PLATFORM_ROOT, "config", "brand.json") : "";
@@ -304,7 +664,9 @@ var UPSTREAM_HOST = process.env.MAXY_UI_HOST ?? "127.0.0.1";
304
664
  var UPSTREAM_PORT = parseInt(process.env.MAXY_UI_PORT ?? "19199", 10);
305
665
  var WEBSOCKIFY_HOST = process.env.WEBSOCKIFY_HOST ?? "127.0.0.1";
306
666
  var WEBSOCKIFY_PORT = parseInt(process.env.WEBSOCKIFY_PORT ?? "6080", 10);
307
- var HOP_BY_HOP2 = /* @__PURE__ */ new Set([
667
+ var TTYD_HOST = process.env.TTYD_HOST ?? "127.0.0.1";
668
+ var TTYD_PORT = parseInt(process.env.TTYD_PORT ?? "7681", 10);
669
+ var HOP_BY_HOP3 = /* @__PURE__ */ new Set([
308
670
  "connection",
309
671
  "keep-alive",
310
672
  "proxy-authenticate",
@@ -318,7 +680,7 @@ function forwardHttp(clientReq, clientRes) {
318
680
  const headers = {};
319
681
  for (const [name, value] of Object.entries(clientReq.headers)) {
320
682
  if (value == null) continue;
321
- if (HOP_BY_HOP2.has(name)) continue;
683
+ if (HOP_BY_HOP3.has(name)) continue;
322
684
  headers[name] = value;
323
685
  }
324
686
  const existingXff = headers["x-forwarded-for"];
@@ -348,7 +710,7 @@ function forwardHttp(clientReq, clientRes) {
348
710
  clientReq.pipe(upstream);
349
711
  }
350
712
  function forwardUpgrade(req, clientSocket, head) {
351
- const upstream = createConnection2({ host: UPSTREAM_HOST, port: UPSTREAM_PORT });
713
+ const upstream = createConnection3({ host: UPSTREAM_HOST, port: UPSTREAM_PORT });
352
714
  upstream.setTimeout(5e3);
353
715
  upstream.once("connect", () => {
354
716
  upstream.setTimeout(0);
@@ -357,7 +719,7 @@ function forwardUpgrade(req, clientSocket, head) {
357
719
  lines.push(`host: ${UPSTREAM_HOST}:${UPSTREAM_PORT}`);
358
720
  for (const [name, value] of Object.entries(req.headers)) {
359
721
  if (name === "host") continue;
360
- if (HOP_BY_HOP2.has(name)) continue;
722
+ if (HOP_BY_HOP3.has(name)) continue;
361
723
  if (value == null) continue;
362
724
  if (Array.isArray(value)) {
363
725
  for (const v of value) lines.push(`${name}: ${v}`);
@@ -408,15 +770,22 @@ attachVncWsProxy(server, {
408
770
  upstreamHost: WEBSOCKIFY_HOST,
409
771
  upstreamPort: WEBSOCKIFY_PORT
410
772
  });
773
+ attachTtydWsProxy(server, {
774
+ isPublicHost,
775
+ upstreamHost: TTYD_HOST,
776
+ upstreamPort: TTYD_PORT
777
+ });
411
778
  server.on("upgrade", (req, socket, head) => {
412
779
  const url = req.url ?? "";
413
780
  const qsIndex = url.indexOf("?");
414
781
  const pathname = qsIndex === -1 ? url : url.slice(0, qsIndex);
415
782
  if (pathname === "/websockify") return;
783
+ if (pathname === "/ttyd") return;
416
784
  forwardUpgrade(req, socket, head);
417
785
  });
418
786
  server.listen(EDGE_PORT, EDGE_HOSTNAME, () => {
419
787
  console.log(`[edge] listening on http://${EDGE_HOSTNAME}:${EDGE_PORT}`);
420
788
  console.log(`[edge] /websockify \u2192 ${WEBSOCKIFY_HOST}:${WEBSOCKIFY_PORT}`);
789
+ console.log(`[edge] /ttyd \u2192 ${TTYD_HOST}:${TTYD_PORT}`);
421
790
  console.log(`[edge] everything else \u2192 ${UPSTREAM_HOST}:${UPSTREAM_PORT}`);
422
791
  });