@rubytech/create-realagent 1.0.673 → 1.0.676

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 (26) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/docs/references/memory-guide.md +1 -1
  3. package/payload/platform/plugins/docs/references/platform.md +9 -5
  4. package/payload/platform/plugins/docs/references/troubleshooting.md +39 -27
  5. package/payload/platform/scripts/vnc.sh +115 -2
  6. package/payload/server/chunk-5YIXIF6C.js +726 -0
  7. package/payload/server/maxy-edge.js +420 -0
  8. package/payload/server/public/assets/admin-DQmUdTBa.js +352 -0
  9. package/payload/server/public/assets/{data-BffoLFjh.js → data-DVlvxbTt.js} +1 -1
  10. package/payload/server/public/assets/{file-CFwYpr7V.js → file-OY_hX2wu.js} +1 -1
  11. package/payload/server/public/assets/{graph-BTqqR6HN.js → graph-BDaM4Qer.js} +13 -13
  12. package/payload/server/public/assets/{house-DL5e4lPb.js → house-CgENfOCP.js} +1 -1
  13. package/payload/server/public/assets/jsx-runtime-Bu4vXoe7.css +1 -0
  14. package/payload/server/public/assets/{public-BJJlVuMu.js → public-Clp4VPwo.js} +1 -1
  15. package/payload/server/public/assets/{share-2-Bcn7Fo6t.js → share-2-RSIR3MmX.js} +1 -1
  16. package/payload/server/public/assets/{useVoiceRecorder-BqzlICMx.js → useVoiceRecorder-B0FI_hts.js} +1 -1
  17. package/payload/server/public/assets/{x-Dv8-a-IC.js → x-DKZ5NR3n.js} +1 -1
  18. package/payload/server/public/data.html +6 -6
  19. package/payload/server/public/graph.html +6 -6
  20. package/payload/server/public/index.html +7 -8
  21. package/payload/server/public/public.html +4 -4
  22. package/payload/server/server.js +660 -1518
  23. package/payload/server/public/assets/admin-CJCz3YFE.js +0 -362
  24. package/payload/server/public/assets/admin-kHJ-D0s7.css +0 -1
  25. package/payload/server/public/assets/jsx-runtime-DsAwO6-r.css +0 -1
  26. /package/payload/server/public/assets/{jsx-runtime-DYU20lw9.js → jsx-runtime-C_VUlXvu.js} +0 -0
@@ -0,0 +1,420 @@
1
+ import {
2
+ canAccessAdmin,
3
+ newCorrId,
4
+ sanitizeClientCorrId,
5
+ vncLog
6
+ } from "./chunk-5YIXIF6C.js";
7
+
8
+ // server/maxy-edge.ts
9
+ import { createServer, request as httpRequest } from "http";
10
+ import { createConnection as createConnection2 } from "net";
11
+ import { readFileSync, existsSync, watchFile } from "fs";
12
+ import { homedir } from "os";
13
+ import { join } from "path";
14
+
15
+ // server/ws-proxy.ts
16
+ import { createConnection } from "net";
17
+ var WS_PATH = "/websockify";
18
+ var UPSTREAM_TIMEOUT_MS = 5e3;
19
+ var HOP_BY_HOP = /* @__PURE__ */ new Set([
20
+ "connection",
21
+ "keep-alive",
22
+ "proxy-authenticate",
23
+ "proxy-authorization",
24
+ "te",
25
+ "trailer",
26
+ "transfer-encoding",
27
+ "upgrade"
28
+ ]);
29
+ function attachVncWsProxy(server2, opts) {
30
+ const upstreamHost = opts.upstreamHost ?? "127.0.0.1";
31
+ const upstreamPort = opts.upstreamPort ?? 6080;
32
+ server2.on("upgrade", (req, clientSocket, head) => {
33
+ try {
34
+ handleUpgrade(req, clientSocket, head, {
35
+ isPublicHost: opts.isPublicHost,
36
+ upstreamHost,
37
+ upstreamPort
38
+ });
39
+ } catch (err) {
40
+ vncLog("ws-upgrade", {
41
+ decision: "rejected",
42
+ reason: "handler-exception",
43
+ err: err.message
44
+ });
45
+ clientSocket.destroy();
46
+ }
47
+ });
48
+ }
49
+ function handleUpgrade(req, clientSocket, head, opts) {
50
+ const url = req.url ?? "";
51
+ const qsIndex = url.indexOf("?");
52
+ const pathname = qsIndex === -1 ? url : url.slice(0, qsIndex);
53
+ if (pathname !== WS_PATH) {
54
+ return;
55
+ }
56
+ const corrId = newCorrId();
57
+ const query = qsIndex === -1 ? "" : url.slice(qsIndex + 1);
58
+ const rawClientCorrId = parseQueryParam(query, "corrId");
59
+ const clientCorrId = sanitizeClientCorrId(rawClientCorrId);
60
+ const hostHeader = (req.headers.host ?? "").split(":")[0];
61
+ const originHeader = headerString(req.headers.origin);
62
+ const remote = req.socket.remoteAddress;
63
+ const xff = headerString(req.headers["x-forwarded-for"]);
64
+ const decision = canAccessAdmin({
65
+ host: hostHeader,
66
+ remoteAddress: remote,
67
+ xForwardedFor: xff,
68
+ cookieHeader: headerString(req.headers.cookie),
69
+ isPublicHost: opts.isPublicHost
70
+ });
71
+ if (!decision.allow) {
72
+ const status = decision.reason === "public-host" ? 404 : 401;
73
+ vncLog("ws-upgrade", {
74
+ corrId,
75
+ clientCorrId: clientCorrId ?? null,
76
+ decision: "rejected",
77
+ reason: decision.reason,
78
+ ip: remote,
79
+ xff: xff ?? null,
80
+ origin: originHeader ?? null,
81
+ host: hostHeader
82
+ });
83
+ writeStatusAndDestroy(clientSocket, status, decision.reason === "public-host" ? "Not Found" : "Unauthorized");
84
+ return;
85
+ }
86
+ const originHost = parseOriginHost(originHeader);
87
+ if (!originHost) {
88
+ vncLog("ws-upgrade", {
89
+ corrId,
90
+ clientCorrId: clientCorrId ?? null,
91
+ decision: "rejected",
92
+ reason: "origin-missing-or-invalid",
93
+ origin: originHeader ?? null,
94
+ host: hostHeader,
95
+ ip: remote
96
+ });
97
+ writeStatusAndDestroy(clientSocket, 403, "Forbidden");
98
+ return;
99
+ }
100
+ if (originHost !== hostHeader) {
101
+ vncLog("ws-upgrade", {
102
+ corrId,
103
+ clientCorrId: clientCorrId ?? null,
104
+ decision: "rejected",
105
+ reason: "origin-mismatch",
106
+ origin_host: originHost,
107
+ host: hostHeader,
108
+ ip: remote
109
+ });
110
+ writeStatusAndDestroy(clientSocket, 403, "Forbidden");
111
+ return;
112
+ }
113
+ if (opts.isPublicHost(originHost)) {
114
+ vncLog("ws-upgrade", {
115
+ corrId,
116
+ clientCorrId: clientCorrId ?? null,
117
+ decision: "rejected",
118
+ reason: "origin-public-host",
119
+ origin_host: originHost,
120
+ host: hostHeader,
121
+ ip: remote
122
+ });
123
+ writeStatusAndDestroy(clientSocket, 403, "Forbidden");
124
+ return;
125
+ }
126
+ vncLog("ws-upgrade", {
127
+ corrId,
128
+ clientCorrId: clientCorrId ?? null,
129
+ decision: "accepted",
130
+ ip: remote,
131
+ xff: xff ?? null,
132
+ origin: originHeader ?? null,
133
+ host: hostHeader,
134
+ sec_ws_version: headerString(req.headers["sec-websocket-version"]) ?? null,
135
+ sec_ws_protocol: headerString(req.headers["sec-websocket-protocol"]) ?? null
136
+ });
137
+ const upstream = createConnection({ host: opts.upstreamHost, port: opts.upstreamPort });
138
+ upstream.setTimeout(UPSTREAM_TIMEOUT_MS);
139
+ let bytesClientToUpstream = 0;
140
+ let bytesUpstreamToClient = 0;
141
+ let closedBy = null;
142
+ let proxyOpened = false;
143
+ const finish = (side, reason) => {
144
+ if (closedBy) return;
145
+ closedBy = side;
146
+ if (proxyOpened) {
147
+ vncLog("proxy-close", {
148
+ corrId,
149
+ closedBy: side,
150
+ reason,
151
+ clientBytes: bytesClientToUpstream,
152
+ upstreamBytes: bytesUpstreamToClient
153
+ });
154
+ }
155
+ clientSocket.destroy();
156
+ upstream.destroy();
157
+ };
158
+ upstream.once("connect", () => {
159
+ upstream.setTimeout(0);
160
+ proxyOpened = true;
161
+ vncLog("proxy-open", {
162
+ corrId,
163
+ upstream: `${opts.upstreamHost}:${opts.upstreamPort}`
164
+ });
165
+ const lines = [];
166
+ lines.push(`${req.method ?? "GET"} ${WS_PATH} HTTP/${req.httpVersion}`);
167
+ lines.push(`host: ${opts.upstreamHost}:${opts.upstreamPort}`);
168
+ for (const [name, value] of Object.entries(req.headers)) {
169
+ if (name === "host") continue;
170
+ if (HOP_BY_HOP.has(name)) continue;
171
+ if (value == null) continue;
172
+ if (Array.isArray(value)) {
173
+ for (const v of value) lines.push(`${name}: ${v}`);
174
+ } else {
175
+ lines.push(`${name}: ${value}`);
176
+ }
177
+ }
178
+ const upgradeHeader = headerString(req.headers.upgrade);
179
+ const connectionHeader = headerString(req.headers.connection);
180
+ if (upgradeHeader) lines.push(`upgrade: ${upgradeHeader}`);
181
+ if (connectionHeader) lines.push(`connection: ${connectionHeader}`);
182
+ upstream.write(lines.join("\r\n") + "\r\n\r\n");
183
+ if (head && head.length > 0) upstream.write(head);
184
+ clientSocket.on("data", (chunk) => {
185
+ bytesClientToUpstream += chunk.length;
186
+ });
187
+ upstream.on("data", (chunk) => {
188
+ bytesUpstreamToClient += chunk.length;
189
+ });
190
+ clientSocket.pipe(upstream);
191
+ upstream.pipe(clientSocket);
192
+ clientSocket.once("close", (hadError) => {
193
+ finish("client", hadError ? "error" : "normal");
194
+ });
195
+ upstream.once("close", (hadError) => {
196
+ finish("upstream", hadError ? "error" : "normal");
197
+ });
198
+ clientSocket.once("error", (err) => {
199
+ vncLog("proxy-error", { corrId, side: "client", err: err.message });
200
+ finish("client", "error");
201
+ });
202
+ upstream.once("error", (err) => {
203
+ vncLog("proxy-error", { corrId, side: "upstream", err: err.message });
204
+ finish("upstream", "error");
205
+ });
206
+ });
207
+ upstream.once("timeout", () => {
208
+ if (proxyOpened) return;
209
+ vncLog("proxy-error", {
210
+ corrId,
211
+ side: "upstream-connect",
212
+ err: "timeout",
213
+ timeout_ms: UPSTREAM_TIMEOUT_MS
214
+ });
215
+ writeStatusAndDestroy(clientSocket, 504, "Gateway Timeout");
216
+ upstream.destroy();
217
+ });
218
+ upstream.once("error", (err) => {
219
+ if (proxyOpened) return;
220
+ vncLog("proxy-error", {
221
+ corrId,
222
+ side: "upstream-connect",
223
+ err: err.message
224
+ });
225
+ writeStatusAndDestroy(clientSocket, 502, "Bad Gateway");
226
+ upstream.destroy();
227
+ });
228
+ }
229
+ function parseQueryParam(query, key) {
230
+ if (!query) return null;
231
+ for (const pair of query.split("&")) {
232
+ const eq = pair.indexOf("=");
233
+ const k = eq === -1 ? pair : pair.slice(0, eq);
234
+ if (k !== key) continue;
235
+ const v = eq === -1 ? "" : pair.slice(eq + 1);
236
+ try {
237
+ return decodeURIComponent(v);
238
+ } catch {
239
+ return null;
240
+ }
241
+ }
242
+ return null;
243
+ }
244
+ function headerString(value) {
245
+ if (value == null) return void 0;
246
+ return Array.isArray(value) ? value[0] : value;
247
+ }
248
+ function parseOriginHost(origin) {
249
+ if (!origin) return null;
250
+ try {
251
+ return new URL(origin).hostname;
252
+ } catch {
253
+ return null;
254
+ }
255
+ }
256
+ function writeStatusAndDestroy(socket, status, statusText) {
257
+ try {
258
+ socket.write(
259
+ `HTTP/1.1 ${status} ${statusText}\r
260
+ Connection: close\r
261
+ Content-Length: 0\r
262
+ \r
263
+ `
264
+ );
265
+ } catch {
266
+ }
267
+ socket.destroy();
268
+ }
269
+
270
+ // server/maxy-edge.ts
271
+ var PLATFORM_ROOT = process.env.MAXY_PLATFORM_ROOT || "";
272
+ var BRAND_JSON_PATH = PLATFORM_ROOT ? join(PLATFORM_ROOT, "config", "brand.json") : "";
273
+ var BRAND = { configDir: ".maxy" };
274
+ if (BRAND_JSON_PATH && existsSync(BRAND_JSON_PATH)) {
275
+ try {
276
+ const parsed = JSON.parse(readFileSync(BRAND_JSON_PATH, "utf-8"));
277
+ if (typeof parsed.configDir === "string") BRAND.configDir = parsed.configDir;
278
+ } catch (err) {
279
+ console.error(`[edge] brand.json parse error: ${err.message}`);
280
+ }
281
+ }
282
+ var ALIAS_DOMAINS_PATH = join(homedir(), BRAND.configDir, "alias-domains.json");
283
+ function loadAliasDomains() {
284
+ try {
285
+ if (!existsSync(ALIAS_DOMAINS_PATH)) return /* @__PURE__ */ new Set();
286
+ const parsed = JSON.parse(readFileSync(ALIAS_DOMAINS_PATH, "utf-8"));
287
+ if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
288
+ return new Set(parsed.filter((h) => typeof h === "string"));
289
+ } catch {
290
+ return /* @__PURE__ */ new Set();
291
+ }
292
+ }
293
+ var aliasDomains = loadAliasDomains();
294
+ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
295
+ aliasDomains = loadAliasDomains();
296
+ console.log(`[edge] alias-domains reloaded (${aliasDomains.size})`);
297
+ });
298
+ function isPublicHost(host) {
299
+ return host.startsWith("public.") || aliasDomains.has(host);
300
+ }
301
+ var EDGE_PORT = parseInt(process.env.EDGE_PORT ?? process.env.PORT ?? "19200", 10);
302
+ var EDGE_HOSTNAME = process.env.EDGE_HOSTNAME ?? "0.0.0.0";
303
+ var UPSTREAM_HOST = process.env.MAXY_UI_HOST ?? "127.0.0.1";
304
+ var UPSTREAM_PORT = parseInt(process.env.MAXY_UI_PORT ?? "19199", 10);
305
+ var WEBSOCKIFY_HOST = process.env.WEBSOCKIFY_HOST ?? "127.0.0.1";
306
+ var WEBSOCKIFY_PORT = parseInt(process.env.WEBSOCKIFY_PORT ?? "6080", 10);
307
+ var HOP_BY_HOP2 = /* @__PURE__ */ new Set([
308
+ "connection",
309
+ "keep-alive",
310
+ "proxy-authenticate",
311
+ "proxy-authorization",
312
+ "te",
313
+ "trailer",
314
+ "transfer-encoding",
315
+ "upgrade"
316
+ ]);
317
+ function forwardHttp(clientReq, clientRes) {
318
+ const headers = {};
319
+ for (const [name, value] of Object.entries(clientReq.headers)) {
320
+ if (value == null) continue;
321
+ if (HOP_BY_HOP2.has(name)) continue;
322
+ headers[name] = value;
323
+ }
324
+ const existingXff = headers["x-forwarded-for"];
325
+ const remote = clientReq.socket.remoteAddress ?? "";
326
+ headers["x-forwarded-for"] = existingXff ? Array.isArray(existingXff) ? [...existingXff, remote].join(", ") : `${existingXff}, ${remote}` : remote;
327
+ const upstream = httpRequest({
328
+ host: UPSTREAM_HOST,
329
+ port: UPSTREAM_PORT,
330
+ method: clientReq.method,
331
+ path: clientReq.url,
332
+ headers
333
+ });
334
+ upstream.on("response", (upstreamRes) => {
335
+ clientRes.writeHead(upstreamRes.statusCode ?? 502, upstreamRes.statusMessage, upstreamRes.headers);
336
+ upstreamRes.pipe(clientRes);
337
+ });
338
+ upstream.on("error", (err) => {
339
+ console.error(`[edge] upstream http error path=${clientReq.url} err=${err.message}`);
340
+ if (!clientRes.headersSent) {
341
+ clientRes.writeHead(502, { "content-type": "text/plain" });
342
+ clientRes.end("Bad Gateway (maxy-ui unavailable)");
343
+ } else {
344
+ clientRes.destroy();
345
+ }
346
+ });
347
+ clientReq.on("aborted", () => upstream.destroy());
348
+ clientReq.pipe(upstream);
349
+ }
350
+ function forwardUpgrade(req, clientSocket, head) {
351
+ const upstream = createConnection2({ host: UPSTREAM_HOST, port: UPSTREAM_PORT });
352
+ upstream.setTimeout(5e3);
353
+ upstream.once("connect", () => {
354
+ upstream.setTimeout(0);
355
+ const lines = [];
356
+ lines.push(`${req.method ?? "GET"} ${req.url} HTTP/${req.httpVersion}`);
357
+ lines.push(`host: ${UPSTREAM_HOST}:${UPSTREAM_PORT}`);
358
+ for (const [name, value] of Object.entries(req.headers)) {
359
+ if (name === "host") continue;
360
+ if (HOP_BY_HOP2.has(name)) continue;
361
+ if (value == null) continue;
362
+ if (Array.isArray(value)) {
363
+ for (const v of value) lines.push(`${name}: ${v}`);
364
+ } else {
365
+ lines.push(`${name}: ${value}`);
366
+ }
367
+ }
368
+ const upgradeHeader = req.headers.upgrade;
369
+ const connectionHeader = req.headers.connection;
370
+ if (typeof upgradeHeader === "string") lines.push(`upgrade: ${upgradeHeader}`);
371
+ if (typeof connectionHeader === "string") lines.push(`connection: ${connectionHeader}`);
372
+ upstream.write(lines.join("\r\n") + "\r\n\r\n");
373
+ if (head && head.length > 0) upstream.write(head);
374
+ clientSocket.pipe(upstream);
375
+ upstream.pipe(clientSocket);
376
+ });
377
+ const teardown = (_reason) => {
378
+ clientSocket.destroy();
379
+ upstream.destroy();
380
+ };
381
+ clientSocket.once("close", () => teardown("client-close"));
382
+ upstream.once("close", () => teardown("upstream-close"));
383
+ clientSocket.once("error", () => teardown("client-error"));
384
+ upstream.once("error", (err) => {
385
+ console.error(`[edge] upstream upgrade error path=${req.url} err=${err.message}`);
386
+ try {
387
+ clientSocket.write("HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
388
+ } catch {
389
+ }
390
+ teardown("upstream-error");
391
+ });
392
+ upstream.once("timeout", () => {
393
+ console.error(`[edge] upstream upgrade timeout path=${req.url}`);
394
+ try {
395
+ clientSocket.write("HTTP/1.1 504 Gateway Timeout\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
396
+ } catch {
397
+ }
398
+ teardown("upstream-timeout");
399
+ });
400
+ }
401
+ var server = createServer((req, res) => {
402
+ forwardHttp(req, res);
403
+ });
404
+ attachVncWsProxy(server, {
405
+ isPublicHost,
406
+ upstreamHost: WEBSOCKIFY_HOST,
407
+ upstreamPort: WEBSOCKIFY_PORT
408
+ });
409
+ server.on("upgrade", (req, socket, head) => {
410
+ const url = req.url ?? "";
411
+ const qsIndex = url.indexOf("?");
412
+ const pathname = qsIndex === -1 ? url : url.slice(0, qsIndex);
413
+ if (pathname === "/websockify") return;
414
+ forwardUpgrade(req, socket, head);
415
+ });
416
+ server.listen(EDGE_PORT, EDGE_HOSTNAME, () => {
417
+ console.log(`[edge] listening on http://${EDGE_HOSTNAME}:${EDGE_PORT}`);
418
+ console.log(`[edge] /websockify \u2192 ${WEBSOCKIFY_HOST}:${WEBSOCKIFY_PORT}`);
419
+ console.log(`[edge] everything else \u2192 ${UPSTREAM_HOST}:${UPSTREAM_PORT}`);
420
+ });