@rubytech/create-maxy 1.0.680 → 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.
- package/dist/index.js +209 -39
- package/package.json +1 -1
- package/payload/platform/plugins/docs/references/deployment.md +4 -2
- package/payload/platform/plugins/docs/references/troubleshooting.md +2 -0
- package/payload/platform/scripts/vnc.sh +12 -409
- package/payload/platform/templates/dotfiles/.tmux.conf +1 -0
- package/payload/platform/templates/systemd/maxy-ttyd.service +25 -0
- package/payload/server/maxy-edge.js +366 -5
- package/payload/server/public/assets/admin-CIkyOur7.js +362 -0
- package/payload/server/public/assets/admin-kHJ-D0s7.css +1 -0
- package/payload/server/public/index.html +2 -1
- package/payload/server/server.js +108 -301
- package/payload/server/public/assets/admin-BBL1no_g.js +0 -352
package/payload/server/server.js
CHANGED
|
@@ -1203,14 +1203,14 @@ var Hono = class _Hono {
|
|
|
1203
1203
|
* app.route("/api", app2) // GET /api/user
|
|
1204
1204
|
* ```
|
|
1205
1205
|
*/
|
|
1206
|
-
route(path2,
|
|
1206
|
+
route(path2, app35) {
|
|
1207
1207
|
const subApp = this.basePath(path2);
|
|
1208
|
-
|
|
1208
|
+
app35.routes.map((r) => {
|
|
1209
1209
|
let handler;
|
|
1210
|
-
if (
|
|
1210
|
+
if (app35.errorHandler === errorHandler) {
|
|
1211
1211
|
handler = r.handler;
|
|
1212
1212
|
} else {
|
|
1213
|
-
handler = async (c, next) => (await compose([],
|
|
1213
|
+
handler = async (c, next) => (await compose([], app35.errorHandler)(c, () => r.handler(c, next))).res;
|
|
1214
1214
|
handler[COMPOSED_HANDLER] = r.handler;
|
|
1215
1215
|
}
|
|
1216
1216
|
subApp.#addRoute(r.method, r.path, handler);
|
|
@@ -3264,7 +3264,6 @@ function resolveBrowserTransport(req, remoteAddress) {
|
|
|
3264
3264
|
return transport;
|
|
3265
3265
|
}
|
|
3266
3266
|
var currentCdpDisplay = null;
|
|
3267
|
-
var currentTerminalDisplay = null;
|
|
3268
3267
|
function discoverNativeDisplay() {
|
|
3269
3268
|
const fallback = { sessionType: "x11", display: ":0", waylandDisplay: "" };
|
|
3270
3269
|
try {
|
|
@@ -3435,137 +3434,6 @@ async function ensureCdp(transport = "vnc") {
|
|
|
3435
3434
|
function killChromium() {
|
|
3436
3435
|
spawnSync("pkill", ["-f", "chromium"], { stdio: "pipe" });
|
|
3437
3436
|
}
|
|
3438
|
-
function terminalAlive() {
|
|
3439
|
-
const result = spawnSync("bash", [VNC_SCRIPT, "status-terminal"], {
|
|
3440
|
-
stdio: "pipe",
|
|
3441
|
-
timeout: 2e3
|
|
3442
|
-
});
|
|
3443
|
-
return result.status === 0;
|
|
3444
|
-
}
|
|
3445
|
-
function extractFailureLine(stderr, signal) {
|
|
3446
|
-
if (signal === "SIGTERM") {
|
|
3447
|
-
return '[terminal-launch] failed err="vnc.sh timed out after 10s \u2014 X server on :99 may be wedged (check Xtigervnc + websockify in vnc-boot.log)"';
|
|
3448
|
-
}
|
|
3449
|
-
const raw2 = (stderr ?? "").trim();
|
|
3450
|
-
if (!raw2) return "Terminal failed to start (no diagnostic captured)";
|
|
3451
|
-
const lines = raw2.split("\n").filter((l) => l.trim().length > 0);
|
|
3452
|
-
const lastFailed = [...lines].reverse().find((l) => l.includes("[terminal-launch] failed"));
|
|
3453
|
-
return (lastFailed ?? lines[lines.length - 1]).trim();
|
|
3454
|
-
}
|
|
3455
|
-
async function ensureTerminal(transport = "vnc") {
|
|
3456
|
-
const targetSentinel = transport === "native" ? "native" : ":99";
|
|
3457
|
-
if (terminalAlive()) {
|
|
3458
|
-
if (currentTerminalDisplay !== null && currentTerminalDisplay !== targetSentinel) {
|
|
3459
|
-
console.error(`[ensureTerminal] Display switch: ${currentTerminalDisplay} \u2192 ${targetSentinel}`);
|
|
3460
|
-
vncLog("ensure-terminal", {
|
|
3461
|
-
action: "display-switch",
|
|
3462
|
-
transport,
|
|
3463
|
-
from_display: currentTerminalDisplay,
|
|
3464
|
-
to_display: targetSentinel
|
|
3465
|
-
});
|
|
3466
|
-
killTerminal();
|
|
3467
|
-
await sleep(500);
|
|
3468
|
-
} else {
|
|
3469
|
-
if (currentTerminalDisplay === null) {
|
|
3470
|
-
currentTerminalDisplay = targetSentinel;
|
|
3471
|
-
}
|
|
3472
|
-
const check = spawnSync("bash", [VNC_SCRIPT, transport === "native" ? "start-terminal-native" : "start-terminal"], {
|
|
3473
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3474
|
-
timeout: 1e4
|
|
3475
|
-
});
|
|
3476
|
-
if (check.status !== 0) {
|
|
3477
|
-
const errorLine = extractFailureLine(check.stderr?.toString(), check.signal);
|
|
3478
|
-
vncLog("ensure-terminal", { action: "already-running-self-heal-failed", transport, windowPresent: false, err: errorLine });
|
|
3479
|
-
return { ok: false, error: errorLine };
|
|
3480
|
-
}
|
|
3481
|
-
vncLog("ensure-terminal", { action: "already-running", transport, windowPresent: true });
|
|
3482
|
-
return { ok: true };
|
|
3483
|
-
}
|
|
3484
|
-
}
|
|
3485
|
-
const vncCommand = transport === "native" ? "start-terminal-native" : "start-terminal";
|
|
3486
|
-
if (transport === "vnc") {
|
|
3487
|
-
const xAlive = await waitForPort(5900, 1e3);
|
|
3488
|
-
if (!xAlive) {
|
|
3489
|
-
console.error("[ensureTerminal] X server down on :5900 \u2014 escalating to full VNC restart");
|
|
3490
|
-
vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport });
|
|
3491
|
-
const vncOk = await ensureVnc();
|
|
3492
|
-
if (!vncOk) {
|
|
3493
|
-
console.error("[ensureTerminal] Full VNC restart failed \u2014 terminal degraded");
|
|
3494
|
-
vncLog("ensure-terminal", { action: "degraded", reason: "vnc-restart-failed", transport });
|
|
3495
|
-
return { ok: false, error: "VNC failed to start after recovery attempt" };
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
}
|
|
3499
|
-
if (transport === "native") {
|
|
3500
|
-
const nativeInfo = discoverNativeDisplay();
|
|
3501
|
-
vncLog("ensure-terminal", {
|
|
3502
|
-
action: "native-display-resolved",
|
|
3503
|
-
transport,
|
|
3504
|
-
session_type: nativeInfo.sessionType,
|
|
3505
|
-
display: nativeInfo.display
|
|
3506
|
-
});
|
|
3507
|
-
}
|
|
3508
|
-
console.error(`[ensureTerminal] Launching terminal (${vncCommand}) for transport=${transport}`);
|
|
3509
|
-
vncLog("ensure-terminal", { action: `launch-${vncCommand}`, transport });
|
|
3510
|
-
const result = spawnSync("bash", [VNC_SCRIPT, vncCommand], {
|
|
3511
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3512
|
-
timeout: 1e4
|
|
3513
|
-
});
|
|
3514
|
-
if (result.status !== 0) {
|
|
3515
|
-
const errorLine = extractFailureLine(result.stderr?.toString(), result.signal);
|
|
3516
|
-
vncLog("ensure-terminal", { action: "launch-failed", transport, windowPresent: false, err: errorLine });
|
|
3517
|
-
return { ok: false, error: errorLine };
|
|
3518
|
-
}
|
|
3519
|
-
currentTerminalDisplay = targetSentinel;
|
|
3520
|
-
vncLog("ensure-terminal", { action: "launch-complete", transport, sentinel: targetSentinel, windowPresent: true });
|
|
3521
|
-
return { ok: true };
|
|
3522
|
-
}
|
|
3523
|
-
function killTerminal() {
|
|
3524
|
-
spawnSync("bash", [VNC_SCRIPT, "kill-terminal"], { stdio: "pipe", timeout: 5e3 });
|
|
3525
|
-
currentTerminalDisplay = null;
|
|
3526
|
-
}
|
|
3527
|
-
async function ensureTerminalUpgrade(transport = "vnc") {
|
|
3528
|
-
const targetSentinel = ":99";
|
|
3529
|
-
vncLog("ensure-terminal", {
|
|
3530
|
-
action: "launch-upgrade",
|
|
3531
|
-
transport,
|
|
3532
|
-
cmd: "npx -y @rubytech/create-maxy@latest"
|
|
3533
|
-
});
|
|
3534
|
-
killTerminal();
|
|
3535
|
-
await sleep(500);
|
|
3536
|
-
if (transport === "vnc") {
|
|
3537
|
-
const xAlive = await waitForPort(5900, 1e3);
|
|
3538
|
-
if (!xAlive) {
|
|
3539
|
-
console.error("[ensureTerminalUpgrade] X server down on :5900 \u2014 escalating to full VNC restart");
|
|
3540
|
-
vncLog("ensure-terminal", { action: "escalate-vnc-restart", reason: "x-down", transport, upgrade: true });
|
|
3541
|
-
const vncOk = await ensureVnc();
|
|
3542
|
-
if (!vncOk) {
|
|
3543
|
-
console.error("[ensureTerminalUpgrade] Full VNC restart failed \u2014 upgrade degraded");
|
|
3544
|
-
vncLog("ensure-terminal", { action: "launch-upgrade-failed", transport, windowPresent: false, err: "VNC failed to start after recovery attempt" });
|
|
3545
|
-
return { ok: false, error: "VNC failed to start after recovery attempt" };
|
|
3546
|
-
}
|
|
3547
|
-
}
|
|
3548
|
-
}
|
|
3549
|
-
console.error(`[ensureTerminalUpgrade] Launching upgrade terminal transport=${transport}`);
|
|
3550
|
-
const result = spawnSync("bash", [VNC_SCRIPT, "start-terminal-upgrade"], {
|
|
3551
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
3552
|
-
timeout: 1e4
|
|
3553
|
-
});
|
|
3554
|
-
if (result.status !== 0) {
|
|
3555
|
-
const errorLine = extractFailureLine(result.stderr?.toString(), result.signal);
|
|
3556
|
-
vncLog("ensure-terminal", { action: "launch-upgrade-failed", transport, windowPresent: false, err: errorLine });
|
|
3557
|
-
return { ok: false, error: errorLine };
|
|
3558
|
-
}
|
|
3559
|
-
currentTerminalDisplay = targetSentinel;
|
|
3560
|
-
vncLog("ensure-terminal", {
|
|
3561
|
-
action: "launch-upgrade-complete",
|
|
3562
|
-
transport,
|
|
3563
|
-
sentinel: targetSentinel,
|
|
3564
|
-
windowPresent: true,
|
|
3565
|
-
cmd: "npx -y @rubytech/create-maxy@latest"
|
|
3566
|
-
});
|
|
3567
|
-
return { ok: true };
|
|
3568
|
-
}
|
|
3569
3437
|
function writeChromiumWrapper() {
|
|
3570
3438
|
mkdirSync2(BIN_DIR, { recursive: true });
|
|
3571
3439
|
const wrapperPath = resolve2(BIN_DIR, "chromium");
|
|
@@ -18910,66 +18778,6 @@ app20.post("/launch", async (c) => {
|
|
|
18910
18778
|
});
|
|
18911
18779
|
var browser_default = app20;
|
|
18912
18780
|
|
|
18913
|
-
// server/routes/admin/terminal.ts
|
|
18914
|
-
var app21 = new Hono2();
|
|
18915
|
-
app21.post("/launch", async (c) => {
|
|
18916
|
-
try {
|
|
18917
|
-
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
18918
|
-
if (transport === "vnc") {
|
|
18919
|
-
const vncOk = await ensureVnc();
|
|
18920
|
-
if (!vncOk) {
|
|
18921
|
-
return c.json({ ok: false, error: "VNC failed to start" }, 502);
|
|
18922
|
-
}
|
|
18923
|
-
}
|
|
18924
|
-
const terminalResult = await ensureTerminal(transport);
|
|
18925
|
-
if (!terminalResult.ok) {
|
|
18926
|
-
return c.json({ ok: false, error: terminalResult.error ?? "Terminal failed to start" }, 502);
|
|
18927
|
-
}
|
|
18928
|
-
return c.json({ ok: true, transport });
|
|
18929
|
-
} catch (err) {
|
|
18930
|
-
console.error("[admin/terminal/launch] Failed to start terminal:", err);
|
|
18931
|
-
return c.json(
|
|
18932
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18933
|
-
500
|
|
18934
|
-
);
|
|
18935
|
-
}
|
|
18936
|
-
});
|
|
18937
|
-
app21.post("/launch-upgrade", async (c) => {
|
|
18938
|
-
try {
|
|
18939
|
-
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
18940
|
-
if (transport === "vnc") {
|
|
18941
|
-
const vncOk = await ensureVnc();
|
|
18942
|
-
if (!vncOk) {
|
|
18943
|
-
return c.json({ ok: false, error: "VNC failed to start" }, 502);
|
|
18944
|
-
}
|
|
18945
|
-
}
|
|
18946
|
-
const result = await ensureTerminalUpgrade(transport);
|
|
18947
|
-
if (!result.ok) {
|
|
18948
|
-
return c.json({ ok: false, error: result.error ?? "Upgrade terminal failed to start" }, 502);
|
|
18949
|
-
}
|
|
18950
|
-
return c.json({ ok: true, transport });
|
|
18951
|
-
} catch (err) {
|
|
18952
|
-
console.error("[admin/terminal/launch-upgrade] Failed to start upgrade terminal:", err);
|
|
18953
|
-
return c.json(
|
|
18954
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18955
|
-
500
|
|
18956
|
-
);
|
|
18957
|
-
}
|
|
18958
|
-
});
|
|
18959
|
-
app21.post("/close", (c) => {
|
|
18960
|
-
try {
|
|
18961
|
-
killTerminal();
|
|
18962
|
-
return c.json({ ok: true });
|
|
18963
|
-
} catch (err) {
|
|
18964
|
-
console.error("[admin/terminal/close] kill failed:", err);
|
|
18965
|
-
return c.json(
|
|
18966
|
-
{ ok: false, error: err instanceof Error ? err.message : "Unknown error" },
|
|
18967
|
-
500
|
|
18968
|
-
);
|
|
18969
|
-
}
|
|
18970
|
-
});
|
|
18971
|
-
var terminal_default = app21;
|
|
18972
|
-
|
|
18973
18781
|
// app/lib/cdp-client.ts
|
|
18974
18782
|
var CDP_HOST = "127.0.0.1";
|
|
18975
18783
|
var CDP_PORT = 9222;
|
|
@@ -19011,8 +18819,8 @@ async function cdpNavigateNewTab(url, opts = {}) {
|
|
|
19011
18819
|
}
|
|
19012
18820
|
|
|
19013
18821
|
// server/routes/admin/device-browser.ts
|
|
19014
|
-
var
|
|
19015
|
-
|
|
18822
|
+
var app21 = new Hono2();
|
|
18823
|
+
app21.post("/navigate", async (c) => {
|
|
19016
18824
|
const TAG19 = "[device-url:click]";
|
|
19017
18825
|
let body;
|
|
19018
18826
|
try {
|
|
@@ -19099,7 +18907,7 @@ app22.post("/navigate", async (c) => {
|
|
|
19099
18907
|
targetId: outcome.targetId
|
|
19100
18908
|
});
|
|
19101
18909
|
});
|
|
19102
|
-
var device_browser_default =
|
|
18910
|
+
var device_browser_default = app21;
|
|
19103
18911
|
|
|
19104
18912
|
// server/routes/admin/events.ts
|
|
19105
18913
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -19108,8 +18916,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
19108
18916
|
"device-url:vnc-surface-shown",
|
|
19109
18917
|
"device-url:malformed"
|
|
19110
18918
|
]);
|
|
19111
|
-
var
|
|
19112
|
-
|
|
18919
|
+
var app22 = new Hono2();
|
|
18920
|
+
app22.post("/", async (c) => {
|
|
19113
18921
|
const TAG19 = "[admin:events]";
|
|
19114
18922
|
let body;
|
|
19115
18923
|
try {
|
|
@@ -19140,7 +18948,7 @@ app23.post("/", async (c) => {
|
|
|
19140
18948
|
console.error(`[${event}] ${formatted}`);
|
|
19141
18949
|
return c.json({ ok: true });
|
|
19142
18950
|
});
|
|
19143
|
-
var events_default =
|
|
18951
|
+
var events_default = app22;
|
|
19144
18952
|
|
|
19145
18953
|
// server/routes/admin/cloudflare.ts
|
|
19146
18954
|
import { homedir as homedir3 } from "os";
|
|
@@ -19233,7 +19041,7 @@ function validateBody(body) {
|
|
|
19233
19041
|
}
|
|
19234
19042
|
return null;
|
|
19235
19043
|
}
|
|
19236
|
-
var
|
|
19044
|
+
var app23 = new Hono2();
|
|
19237
19045
|
function fieldFromReason(reason) {
|
|
19238
19046
|
switch (reason) {
|
|
19239
19047
|
case "not-signed-in":
|
|
@@ -19250,7 +19058,7 @@ function fieldFromReason(reason) {
|
|
|
19250
19058
|
return "script";
|
|
19251
19059
|
}
|
|
19252
19060
|
}
|
|
19253
|
-
|
|
19061
|
+
app23.get("/domains", requireAdminSession, async (c) => {
|
|
19254
19062
|
const started = Date.now();
|
|
19255
19063
|
const sessionKey = c.var.sessionKey;
|
|
19256
19064
|
let correlationId;
|
|
@@ -19343,7 +19151,7 @@ ${result.stderr}` : ""}`;
|
|
|
19343
19151
|
);
|
|
19344
19152
|
return c.json(success, 200);
|
|
19345
19153
|
});
|
|
19346
|
-
|
|
19154
|
+
app23.post("/setup", requireAdminSession, async (c) => {
|
|
19347
19155
|
const started = Date.now();
|
|
19348
19156
|
const sessionKey = c.var.sessionKey;
|
|
19349
19157
|
let correlationId;
|
|
@@ -19481,7 +19289,7 @@ ${result.stderr}` : ""}`;
|
|
|
19481
19289
|
log2(`phase=response-sent`);
|
|
19482
19290
|
return resp;
|
|
19483
19291
|
});
|
|
19484
|
-
var cloudflare_default =
|
|
19292
|
+
var cloudflare_default = app23;
|
|
19485
19293
|
|
|
19486
19294
|
// server/routes/admin/files.ts
|
|
19487
19295
|
import { createReadStream as createReadStream3 } from "fs";
|
|
@@ -19914,8 +19722,8 @@ function buildDisplayPath(relPath, accountNames) {
|
|
|
19914
19722
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
19915
19723
|
});
|
|
19916
19724
|
}
|
|
19917
|
-
var
|
|
19918
|
-
|
|
19725
|
+
var app24 = new Hono2();
|
|
19726
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
19919
19727
|
const sessionKey = c.var.sessionKey;
|
|
19920
19728
|
if (!getAccountIdForSession(sessionKey)) {
|
|
19921
19729
|
console.error(`[data] auth-rejected endpoint="/api/admin/files" reason="no account for session"`);
|
|
@@ -19976,7 +19784,7 @@ app25.get("/", requireAdminSession, async (c) => {
|
|
|
19976
19784
|
return c.json({ error: message }, 500);
|
|
19977
19785
|
}
|
|
19978
19786
|
});
|
|
19979
|
-
|
|
19787
|
+
app24.get("/download", requireAdminSession, async (c) => {
|
|
19980
19788
|
const sessionKey = c.var.sessionKey;
|
|
19981
19789
|
if (!getAccountIdForSession(sessionKey)) {
|
|
19982
19790
|
console.error(`[data] auth-rejected endpoint="/api/admin/files/download" reason="no account for session"`);
|
|
@@ -20024,7 +19832,7 @@ app25.get("/download", requireAdminSession, async (c) => {
|
|
|
20024
19832
|
return c.json({ error: message }, 500);
|
|
20025
19833
|
}
|
|
20026
19834
|
});
|
|
20027
|
-
|
|
19835
|
+
app24.post("/upload", requireAdminSession, async (c) => {
|
|
20028
19836
|
const sessionKey = c.var.sessionKey;
|
|
20029
19837
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20030
19838
|
if (!accountId) {
|
|
@@ -20082,7 +19890,7 @@ app25.post("/upload", requireAdminSession, async (c) => {
|
|
|
20082
19890
|
mimeType: file.type
|
|
20083
19891
|
});
|
|
20084
19892
|
});
|
|
20085
|
-
|
|
19893
|
+
app24.delete("/", requireAdminSession, async (c) => {
|
|
20086
19894
|
const sessionKey = c.var.sessionKey;
|
|
20087
19895
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20088
19896
|
if (!accountId) {
|
|
@@ -20149,13 +19957,13 @@ app25.delete("/", requireAdminSession, async (c) => {
|
|
|
20149
19957
|
return c.json({ error: message }, 500);
|
|
20150
19958
|
}
|
|
20151
19959
|
});
|
|
20152
|
-
var files_default =
|
|
19960
|
+
var files_default = app24;
|
|
20153
19961
|
|
|
20154
19962
|
// server/routes/admin/graph-search.ts
|
|
20155
19963
|
var DEFAULT_LIMIT = 20;
|
|
20156
19964
|
var MAX_LIMIT = 100;
|
|
20157
|
-
var
|
|
20158
|
-
|
|
19965
|
+
var app25 = new Hono2();
|
|
19966
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
20159
19967
|
const sessionKey = c.var.sessionKey;
|
|
20160
19968
|
const q = (c.req.query("q") ?? "").trim();
|
|
20161
19969
|
const rawLimit = c.req.query("limit");
|
|
@@ -20180,7 +19988,7 @@ app26.get("/", requireAdminSession, async (c) => {
|
|
|
20180
19988
|
return c.json({ error: `Graph search unavailable: ${message}` }, 503);
|
|
20181
19989
|
}
|
|
20182
19990
|
});
|
|
20183
|
-
var graph_search_default =
|
|
19991
|
+
var graph_search_default = app25;
|
|
20184
19992
|
|
|
20185
19993
|
// server/routes/admin/graph-subgraph.ts
|
|
20186
19994
|
import neo4j3 from "neo4j-driver";
|
|
@@ -20309,8 +20117,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
20309
20117
|
"otpCode",
|
|
20310
20118
|
"sessionKey"
|
|
20311
20119
|
]);
|
|
20312
|
-
var
|
|
20313
|
-
|
|
20120
|
+
var app26 = new Hono2();
|
|
20121
|
+
app26.get("/", requireAdminSession, async (c) => {
|
|
20314
20122
|
const sessionKey = c.var.sessionKey;
|
|
20315
20123
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20316
20124
|
if (!accountId) {
|
|
@@ -20586,12 +20394,12 @@ function pruneNode(node, warnedClasses) {
|
|
|
20586
20394
|
const labels = (node.labels ?? []).filter((l) => l !== "Trashed");
|
|
20587
20395
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
20588
20396
|
}
|
|
20589
|
-
var graph_subgraph_default =
|
|
20397
|
+
var graph_subgraph_default = app26;
|
|
20590
20398
|
|
|
20591
20399
|
// server/routes/admin/graph-delete.ts
|
|
20592
20400
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
|
|
20593
|
-
var
|
|
20594
|
-
|
|
20401
|
+
var app27 = new Hono2();
|
|
20402
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
20595
20403
|
const sessionKey = c.var.sessionKey;
|
|
20596
20404
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20597
20405
|
if (!accountId) {
|
|
@@ -20662,11 +20470,11 @@ app28.post("/", requireAdminSession, async (c) => {
|
|
|
20662
20470
|
}
|
|
20663
20471
|
}
|
|
20664
20472
|
});
|
|
20665
|
-
var graph_delete_default =
|
|
20473
|
+
var graph_delete_default = app27;
|
|
20666
20474
|
|
|
20667
20475
|
// server/routes/admin/graph-restore.ts
|
|
20668
|
-
var
|
|
20669
|
-
|
|
20476
|
+
var app28 = new Hono2();
|
|
20477
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
20670
20478
|
const sessionKey = c.var.sessionKey;
|
|
20671
20479
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20672
20480
|
if (!accountId) {
|
|
@@ -20730,11 +20538,11 @@ app29.post("/", requireAdminSession, async (c) => {
|
|
|
20730
20538
|
}
|
|
20731
20539
|
}
|
|
20732
20540
|
});
|
|
20733
|
-
var graph_restore_default =
|
|
20541
|
+
var graph_restore_default = app28;
|
|
20734
20542
|
|
|
20735
20543
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
20736
|
-
var
|
|
20737
|
-
|
|
20544
|
+
var app29 = new Hono2();
|
|
20545
|
+
app29.get("/", requireAdminSession, async (c) => {
|
|
20738
20546
|
const sessionKey = c.var.sessionKey;
|
|
20739
20547
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20740
20548
|
if (!accountId) {
|
|
@@ -20795,11 +20603,11 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
20795
20603
|
sum(halfEdges) AS relDegree
|
|
20796
20604
|
RETURN label, nodeCount, relDegree
|
|
20797
20605
|
`;
|
|
20798
|
-
var graph_labels_in_graph_default =
|
|
20606
|
+
var graph_labels_in_graph_default = app29;
|
|
20799
20607
|
|
|
20800
20608
|
// server/routes/admin/graph-default-view.ts
|
|
20801
|
-
var
|
|
20802
|
-
|
|
20609
|
+
var app30 = new Hono2();
|
|
20610
|
+
app30.get("/", requireAdminSession, async (c) => {
|
|
20803
20611
|
const sessionKey = c.var.sessionKey;
|
|
20804
20612
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20805
20613
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -20837,7 +20645,7 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
20837
20645
|
}
|
|
20838
20646
|
}
|
|
20839
20647
|
});
|
|
20840
|
-
|
|
20648
|
+
app30.put("/", requireAdminSession, async (c) => {
|
|
20841
20649
|
const sessionKey = c.var.sessionKey;
|
|
20842
20650
|
const accountId = getAccountIdForSession(sessionKey);
|
|
20843
20651
|
const userId = getUserIdForSession(sessionKey);
|
|
@@ -20919,11 +20727,11 @@ var WRITE_CYPHER = `
|
|
|
20919
20727
|
p.updatedAt = $updatedAt
|
|
20920
20728
|
RETURN p.labels AS labels
|
|
20921
20729
|
`;
|
|
20922
|
-
var graph_default_view_default =
|
|
20730
|
+
var graph_default_view_default = app30;
|
|
20923
20731
|
|
|
20924
20732
|
// server/routes/admin/file-attach.ts
|
|
20925
|
-
var
|
|
20926
|
-
|
|
20733
|
+
var app31 = new Hono2();
|
|
20734
|
+
app31.post("/", async (c) => {
|
|
20927
20735
|
try {
|
|
20928
20736
|
const body = await c.req.json();
|
|
20929
20737
|
const { filePath, accountId } = body;
|
|
@@ -20946,11 +20754,11 @@ app32.post("/", async (c) => {
|
|
|
20946
20754
|
return c.json({ error: message }, 500);
|
|
20947
20755
|
}
|
|
20948
20756
|
});
|
|
20949
|
-
var file_attach_default =
|
|
20757
|
+
var file_attach_default = app31;
|
|
20950
20758
|
|
|
20951
20759
|
// server/routes/admin/adherence.ts
|
|
20952
|
-
var
|
|
20953
|
-
|
|
20760
|
+
var app32 = new Hono2();
|
|
20761
|
+
app32.get("/", requireAdminSession, async (c) => {
|
|
20954
20762
|
const agent = c.req.query("agent") ?? "admin";
|
|
20955
20763
|
const includeBlock = c.req.query("block") === "1";
|
|
20956
20764
|
const account = resolveAccount();
|
|
@@ -20971,35 +20779,34 @@ app33.get("/", requireAdminSession, async (c) => {
|
|
|
20971
20779
|
return c.json({ error: "Failed to read adherence ledger", agent }, 500);
|
|
20972
20780
|
}
|
|
20973
20781
|
});
|
|
20974
|
-
var adherence_default =
|
|
20782
|
+
var adherence_default = app32;
|
|
20975
20783
|
|
|
20976
20784
|
// server/routes/admin/index.ts
|
|
20977
|
-
var
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20989
|
-
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
var admin_default = app34;
|
|
20785
|
+
var app33 = new Hono2();
|
|
20786
|
+
app33.route("/session", session_default2);
|
|
20787
|
+
app33.route("/chat", chat_default2);
|
|
20788
|
+
app33.route("/compact", compact_default);
|
|
20789
|
+
app33.route("/logs", logs_default);
|
|
20790
|
+
app33.route("/claude-info", claude_info_default);
|
|
20791
|
+
app33.route("/attachment", attachment_default);
|
|
20792
|
+
app33.route("/account", account_default);
|
|
20793
|
+
app33.route("/agents", agents_default);
|
|
20794
|
+
app33.route("/version", version_default);
|
|
20795
|
+
app33.route("/sessions", sessions_default);
|
|
20796
|
+
app33.route("/browser", browser_default);
|
|
20797
|
+
app33.route("/device-browser", device_browser_default);
|
|
20798
|
+
app33.route("/events", events_default);
|
|
20799
|
+
app33.route("/cloudflare", cloudflare_default);
|
|
20800
|
+
app33.route("/files", files_default);
|
|
20801
|
+
app33.route("/graph-search", graph_search_default);
|
|
20802
|
+
app33.route("/graph-subgraph", graph_subgraph_default);
|
|
20803
|
+
app33.route("/graph-delete", graph_delete_default);
|
|
20804
|
+
app33.route("/graph-restore", graph_restore_default);
|
|
20805
|
+
app33.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
20806
|
+
app33.route("/graph-default-view", graph_default_view_default);
|
|
20807
|
+
app33.route("/file-attach", file_attach_default);
|
|
20808
|
+
app33.route("/adherence", adherence_default);
|
|
20809
|
+
var admin_default = app33;
|
|
21003
20810
|
|
|
21004
20811
|
// server/index.ts
|
|
21005
20812
|
var PLATFORM_ROOT10 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
@@ -21057,9 +20864,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
21057
20864
|
function isPublicHost(host) {
|
|
21058
20865
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
21059
20866
|
}
|
|
21060
|
-
var
|
|
21061
|
-
|
|
21062
|
-
|
|
20867
|
+
var app34 = new Hono2();
|
|
20868
|
+
app34.use("*", clientIpMiddleware);
|
|
20869
|
+
app34.use("*", async (c, next) => {
|
|
21063
20870
|
await next();
|
|
21064
20871
|
c.header("X-Content-Type-Options", "nosniff");
|
|
21065
20872
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -21082,7 +20889,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
21082
20889
|
"/g/"
|
|
21083
20890
|
];
|
|
21084
20891
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
21085
|
-
|
|
20892
|
+
app34.use("*", async (c, next) => {
|
|
21086
20893
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21087
20894
|
if (!isPublicHost(host)) {
|
|
21088
20895
|
await next();
|
|
@@ -21122,7 +20929,7 @@ function resolveRemoteAuthOpts() {
|
|
|
21122
20929
|
return brandLoginOpts;
|
|
21123
20930
|
}
|
|
21124
20931
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
21125
|
-
|
|
20932
|
+
app34.post("/__remote-auth/login", async (c) => {
|
|
21126
20933
|
const clientIp = c.var.clientIp || "unknown";
|
|
21127
20934
|
const rateLimited = checkRateLimit(clientIp);
|
|
21128
20935
|
if (rateLimited) {
|
|
@@ -21158,7 +20965,7 @@ app35.post("/__remote-auth/login", async (c) => {
|
|
|
21158
20965
|
}
|
|
21159
20966
|
});
|
|
21160
20967
|
});
|
|
21161
|
-
|
|
20968
|
+
app34.get("/__remote-auth/logout", () => {
|
|
21162
20969
|
return new Response(null, {
|
|
21163
20970
|
status: 302,
|
|
21164
20971
|
headers: {
|
|
@@ -21168,7 +20975,7 @@ app35.get("/__remote-auth/logout", () => {
|
|
|
21168
20975
|
}
|
|
21169
20976
|
});
|
|
21170
20977
|
});
|
|
21171
|
-
|
|
20978
|
+
app34.post("/__remote-auth/change-password", async (c) => {
|
|
21172
20979
|
const clientIp = c.var.clientIp || "unknown";
|
|
21173
20980
|
const rateLimited = checkRateLimit(clientIp);
|
|
21174
20981
|
if (rateLimited) {
|
|
@@ -21217,13 +21024,13 @@ app35.post("/__remote-auth/change-password", async (c) => {
|
|
|
21217
21024
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
21218
21025
|
}
|
|
21219
21026
|
});
|
|
21220
|
-
|
|
21027
|
+
app34.get("/__remote-auth/setup", (c) => {
|
|
21221
21028
|
if (isRemoteAuthConfigured()) {
|
|
21222
21029
|
return c.redirect("/");
|
|
21223
21030
|
}
|
|
21224
21031
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
21225
21032
|
});
|
|
21226
|
-
|
|
21033
|
+
app34.post("/__remote-auth/set-initial-password", async (c) => {
|
|
21227
21034
|
if (isRemoteAuthConfigured()) {
|
|
21228
21035
|
return c.redirect("/");
|
|
21229
21036
|
}
|
|
@@ -21259,10 +21066,10 @@ app35.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
21259
21066
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
21260
21067
|
}
|
|
21261
21068
|
});
|
|
21262
|
-
|
|
21069
|
+
app34.get("/api/remote-auth/status", (c) => {
|
|
21263
21070
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
21264
21071
|
});
|
|
21265
|
-
|
|
21072
|
+
app34.post("/api/remote-auth/set-password", async (c) => {
|
|
21266
21073
|
let body;
|
|
21267
21074
|
try {
|
|
21268
21075
|
body = await c.req.json();
|
|
@@ -21292,9 +21099,9 @@ app35.post("/api/remote-auth/set-password", async (c) => {
|
|
|
21292
21099
|
return c.json({ error: "Failed to save password" }, 500);
|
|
21293
21100
|
}
|
|
21294
21101
|
});
|
|
21295
|
-
|
|
21102
|
+
app34.route("/api/_client-error", client_error_default);
|
|
21296
21103
|
console.log("[client-error-route] mounted");
|
|
21297
|
-
|
|
21104
|
+
app34.use("*", async (c, next) => {
|
|
21298
21105
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21299
21106
|
const path2 = c.req.path;
|
|
21300
21107
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -21324,15 +21131,15 @@ app35.use("*", async (c, next) => {
|
|
|
21324
21131
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2}`);
|
|
21325
21132
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
21326
21133
|
});
|
|
21327
|
-
|
|
21328
|
-
|
|
21329
|
-
|
|
21330
|
-
|
|
21331
|
-
|
|
21332
|
-
|
|
21333
|
-
|
|
21334
|
-
|
|
21335
|
-
|
|
21134
|
+
app34.route("/api/health", health_default);
|
|
21135
|
+
app34.route("/api/session", session_default);
|
|
21136
|
+
app34.route("/api/chat", chat_default);
|
|
21137
|
+
app34.route("/api/group", group_default);
|
|
21138
|
+
app34.route("/api/access", access_default);
|
|
21139
|
+
app34.route("/api/telegram", telegram_default);
|
|
21140
|
+
app34.route("/api/whatsapp", whatsapp_default);
|
|
21141
|
+
app34.route("/api/onboarding", onboarding_default);
|
|
21142
|
+
app34.route("/api/admin", admin_default);
|
|
21336
21143
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
21337
21144
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
21338
21145
|
var IMAGE_MIME = {
|
|
@@ -21344,7 +21151,7 @@ var IMAGE_MIME = {
|
|
|
21344
21151
|
".svg": "image/svg+xml",
|
|
21345
21152
|
".ico": "image/x-icon"
|
|
21346
21153
|
};
|
|
21347
|
-
|
|
21154
|
+
app34.get("/agent-assets/:slug/:filename", (c) => {
|
|
21348
21155
|
const slug = c.req.param("slug");
|
|
21349
21156
|
const filename = c.req.param("filename");
|
|
21350
21157
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -21379,7 +21186,7 @@ app35.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
21379
21186
|
"Cache-Control": "public, max-age=3600"
|
|
21380
21187
|
});
|
|
21381
21188
|
});
|
|
21382
|
-
|
|
21189
|
+
app34.get("/generated/:filename", (c) => {
|
|
21383
21190
|
const filename = c.req.param("filename");
|
|
21384
21191
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
21385
21192
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -21544,7 +21351,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
21544
21351
|
function escapeHtml(s) {
|
|
21545
21352
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
21546
21353
|
}
|
|
21547
|
-
|
|
21354
|
+
app34.get("/", (c) => {
|
|
21548
21355
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21549
21356
|
if (isPublicHost(host)) {
|
|
21550
21357
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -21552,12 +21359,12 @@ app35.get("/", (c) => {
|
|
|
21552
21359
|
}
|
|
21553
21360
|
return c.html(cachedHtml("index.html"));
|
|
21554
21361
|
});
|
|
21555
|
-
|
|
21362
|
+
app34.get("/public", (c) => {
|
|
21556
21363
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21557
21364
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21558
21365
|
return c.html(cachedHtml("public.html"));
|
|
21559
21366
|
});
|
|
21560
|
-
|
|
21367
|
+
app34.get("/chat", (c) => {
|
|
21561
21368
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21562
21369
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21563
21370
|
return c.html(cachedHtml("public.html"));
|
|
@@ -21576,9 +21383,9 @@ async function logViewerFetch(c, next) {
|
|
|
21576
21383
|
duration_ms: Date.now() - start
|
|
21577
21384
|
});
|
|
21578
21385
|
}
|
|
21579
|
-
|
|
21580
|
-
|
|
21581
|
-
|
|
21386
|
+
app34.use("/vnc-viewer.html", logViewerFetch);
|
|
21387
|
+
app34.use("/vnc-popout.html", logViewerFetch);
|
|
21388
|
+
app34.get("/vnc-popout.html", (c) => {
|
|
21582
21389
|
let html = htmlCache.get("vnc-popout.html");
|
|
21583
21390
|
if (!html) {
|
|
21584
21391
|
html = readFileSync25(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -21591,7 +21398,7 @@ app35.get("/vnc-popout.html", (c) => {
|
|
|
21591
21398
|
}
|
|
21592
21399
|
return c.html(html);
|
|
21593
21400
|
});
|
|
21594
|
-
|
|
21401
|
+
app34.post("/api/vnc/client-event", async (c) => {
|
|
21595
21402
|
let body;
|
|
21596
21403
|
try {
|
|
21597
21404
|
body = await c.req.json();
|
|
@@ -21612,20 +21419,20 @@ app35.post("/api/vnc/client-event", async (c) => {
|
|
|
21612
21419
|
});
|
|
21613
21420
|
return c.json({ ok: true });
|
|
21614
21421
|
});
|
|
21615
|
-
|
|
21422
|
+
app34.get("/g/:slug", (c) => {
|
|
21616
21423
|
return c.html(brandedPublicHtml());
|
|
21617
21424
|
});
|
|
21618
|
-
|
|
21425
|
+
app34.get("/graph", (c) => {
|
|
21619
21426
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21620
21427
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21621
21428
|
return c.html(cachedHtml("graph.html"));
|
|
21622
21429
|
});
|
|
21623
|
-
|
|
21430
|
+
app34.get("/data", (c) => {
|
|
21624
21431
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21625
21432
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21626
21433
|
return c.html(cachedHtml("data.html"));
|
|
21627
21434
|
});
|
|
21628
|
-
|
|
21435
|
+
app34.get("/:slug", async (c, next) => {
|
|
21629
21436
|
const slug = c.req.param("slug");
|
|
21630
21437
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
21631
21438
|
const branding = loadBrandingCache(slug);
|
|
@@ -21634,10 +21441,10 @@ app35.get("/:slug", async (c, next) => {
|
|
|
21634
21441
|
}
|
|
21635
21442
|
await next();
|
|
21636
21443
|
});
|
|
21637
|
-
|
|
21444
|
+
app34.use("/*", serveStatic({ root: "./public" }));
|
|
21638
21445
|
var port = parseInt(process.env.PORT ?? "19199", 10);
|
|
21639
21446
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
21640
|
-
var httpServer = serve({ fetch:
|
|
21447
|
+
var httpServer = serve({ fetch: app34.fetch, port, hostname });
|
|
21641
21448
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
21642
21449
|
var SUBAPP_MANIFEST = [
|
|
21643
21450
|
{ prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
|
|
@@ -21657,7 +21464,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
21657
21464
|
}
|
|
21658
21465
|
try {
|
|
21659
21466
|
const registered = [];
|
|
21660
|
-
for (const r of
|
|
21467
|
+
for (const r of app34.routes ?? []) {
|
|
21661
21468
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
21662
21469
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
21663
21470
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|