@rubytech/create-maxy-code 0.1.195 → 0.1.197
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/package.json +1 -1
- package/payload/platform/config/brand.json +3 -1
- package/payload/platform/plugins/admin/PLUGIN.md +3 -0
- package/payload/platform/plugins/admin/skills/investigate/SKILL.md +286 -0
- package/payload/platform/plugins/admin/skills/superpowers-sprint/SKILL.md +361 -0
- package/payload/platform/plugins/admin/skills/task/SKILL.md +283 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -1
- package/payload/platform/plugins/docs/references/internals.md +0 -2
- package/payload/platform/plugins/docs/references/investigate-and-task-skills.md +9 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +0 -3
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +0 -248
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/server/public/assets/AdminShell-DPk5UgEJ.js +1 -0
- package/payload/server/public/assets/{Checkbox-G-kyM1P1.js → Checkbox-Bh3kwzxP.js} +1 -1
- package/payload/server/public/assets/{admin-B-GDNkoN.js → admin-BWzKAudL.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-BGgdXdD2.js → architectureDiagram-Q4EWVU46-Boys2mT1.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DKWoL4Rp.js → blockDiagram-DXYQGD6D-CvHqp46r.js} +1 -1
- package/payload/server/public/assets/{brand-MbpD2Bhr.css → brand-VQtREmts.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Ca6rs6F4.js → c4Diagram-AHTNJAMY-DiNQ95F6.js} +1 -1
- package/payload/server/public/assets/channel-BgwH_qhE.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DcdMZImV.js → chunk-336JU56O-9nS9-05M.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-9FSP-c1z.js → chunk-426QAEUC-B2__9lRY.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-CC1QpEvA.js → chunk-4TB4RGXK-R5F8rS0Z.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-o1b70dEE.js → chunk-5FUZZQ4R-B8HhJce-.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-C7VCYRz9.js → chunk-5PVQY5BW-Bjb08lbL.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-B8d5xj_4.js → chunk-EDXVE4YY-he0qCF3s.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-SSbr4n2X.js → chunk-ENJZ2VHE-BTArFW5l.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-Cgj9YSpX.js → chunk-ICPOFSXX-CoyIL4q_.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DNEEcCqI.js → chunk-OYMX7WX6-DjLEhNFe.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-DuaoK83q.js → chunk-U2HBQHQK-tac2uvW1.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CzMp0dpq.js → chunk-X2U36JSP-DIWD9i88.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-B2wBDwSa.js → chunk-YZCP3GAM-Ac7ogADz.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-DkyF7XKW.js → chunk-ZZ45TVLE-QgqDaY9-.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CwdV1-c8.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CS_jtevB.js +1 -0
- package/payload/server/public/assets/clone-BTishuSs.js +1 -0
- package/payload/server/public/assets/{dagre-AGj1P0p4.js → dagre-D6qN4nkK.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-Cnrxcu6A.js → dagre-KV5264BT-C6TRKOg0.js} +1 -1
- package/payload/server/public/assets/data-CaZbNF-j.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-gyFYSx73.js → diagram-5BDNPKRD-BVk_J8Pt.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DFmZEv5C.js → diagram-G4DWMVQ6-BdV1IgwS.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DA4qbuEW.js → diagram-MMDJMWI5-OsvBkN6u.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-D4n-8gig.js → diagram-TYMM5635-BQmKPyrb.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-CigRMjF1.js → erDiagram-SMLLAGMA-ChEx5_3C.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-ClS27acA.js → flowDiagram-DWJPFMVM-B7sf6AG3.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-Dr1IulXe.js → ganttDiagram-T4ZO3ILL-DbpSraax.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-lwLibdPs.js → gitGraphDiagram-UUTBAWPF-BnxDElDh.js} +1 -1
- package/payload/server/public/assets/{graph-CpozZ74I.js → graph-CBP5yppq.js} +2 -2
- package/payload/server/public/assets/{graph-labels-C2y666R0.js → graph-labels-BsZNScfa.js} +1 -1
- package/payload/server/public/assets/{graphlib-DBvoJMrc.js → graphlib-Dux06enE.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-D4kReEIV.js → infoDiagram-42DDH7IO-BLWb6oKx.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BnteQRQ0.js → ishikawaDiagram-UXIWVN3A-AFiRuE6G.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CXu6hLyJ.js → journeyDiagram-VCZTEJTY-CxHBRGGu.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CGDW2jle.js → kanban-definition-6JOO6SKY-CGugF0N8.js} +1 -1
- package/payload/server/public/assets/{line-pdg5hxC3.js → line-COFloj-X.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-o3lIIK3Z.js → mermaid-parser.core-CxXuCDQf.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-DLR6Q3rV.js → mermaid.core-BRBNvNup.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CH4cB0Dn.js → mindmap-definition-QFDTVHPH-DarW5Wwq.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-Ba4voL_Y.js → pieDiagram-DEJITSTG-CTokFAkN.js} +1 -1
- package/payload/server/public/assets/{public-C8mil9h0.js → public-Bq-eOUu9.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Cqn2xehe.js → quadrantDiagram-34T5L4WZ-BNawkg3I.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DLfNx99l.js → requirementDiagram-MS252O5E-CWnO56oR.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-uck_V-cb.js → sankeyDiagram-XADWPNL6-D9c-EZfV.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmQalqud.js → sequenceDiagram-FGHM5R23-In5lxCT5.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DUdWeVRa.js → stateDiagram-FHFEXIEX-CYb5js-u.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-z-TVJfRt.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BgL1wM5n.js → timeline-definition-GMOUNBTQ-Cje-BY9v.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-BLpVlOgm.js → useSelectionMode-B_2EQ2CC.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-7FHjIqPi.js → vennDiagram-DHZGUBPP-BqeuoPr1.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BHzo4V1J.js → wardleyDiagram-NUSXRM2D-DE7xAnoq.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DtuWhqwh.js → xychartDiagram-5P7HB3ND-JE4x8YEZ.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +6 -6
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +325 -332
- package/payload/server/public/assets/AdminShell-BoJbnn6d.js +0 -1
- package/payload/server/public/assets/channel-BwsV7WTV.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CEWNfHVo.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BBjzRxux.js +0 -1
- package/payload/server/public/assets/clone-CXtSonnn.js +0 -1
- package/payload/server/public/assets/data-Bg0Frxt3.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DNTpFwdy.js +0 -1
- /package/payload/server/public/assets/{brand-CYcGHhlS.js → brand-CzeO4m4J.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -817,7 +817,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
817
817
|
|
|
818
818
|
// server/index.ts
|
|
819
819
|
import { readFileSync as readFileSync21, existsSync as existsSync21, watchFile } from "fs";
|
|
820
|
-
import { resolve as
|
|
820
|
+
import { resolve as resolve22, join as join16, basename as basename6 } from "path";
|
|
821
821
|
import { homedir as homedir2 } from "os";
|
|
822
822
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
823
823
|
|
|
@@ -1275,7 +1275,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1275
1275
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1276
1276
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
1277
1277
|
const timer2 = new Promise(
|
|
1278
|
-
(
|
|
1278
|
+
(resolve23) => setTimeout(() => resolve23("timeout"), timeoutMs)
|
|
1279
1279
|
);
|
|
1280
1280
|
const result = await Promise.race([
|
|
1281
1281
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1403,11 +1403,11 @@ async function createWaSocket(opts) {
|
|
|
1403
1403
|
return sock;
|
|
1404
1404
|
}
|
|
1405
1405
|
async function waitForConnection(sock) {
|
|
1406
|
-
return new Promise((
|
|
1406
|
+
return new Promise((resolve23, reject) => {
|
|
1407
1407
|
const handler = (update) => {
|
|
1408
1408
|
if (update.connection === "open") {
|
|
1409
1409
|
sock.ev.off("connection.update", handler);
|
|
1410
|
-
|
|
1410
|
+
resolve23();
|
|
1411
1411
|
}
|
|
1412
1412
|
if (update.connection === "close") {
|
|
1413
1413
|
sock.ev.off("connection.update", handler);
|
|
@@ -1521,14 +1521,14 @@ ${inspected}`;
|
|
|
1521
1521
|
return inspect2(err, INSPECT_OPTS2);
|
|
1522
1522
|
}
|
|
1523
1523
|
function withTimeout(label, promise, timeoutMs) {
|
|
1524
|
-
return new Promise((
|
|
1524
|
+
return new Promise((resolve23, reject) => {
|
|
1525
1525
|
const timer2 = setTimeout(() => {
|
|
1526
1526
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
1527
1527
|
}, timeoutMs);
|
|
1528
1528
|
promise.then(
|
|
1529
1529
|
(value) => {
|
|
1530
1530
|
clearTimeout(timer2);
|
|
1531
|
-
|
|
1531
|
+
resolve23(value);
|
|
1532
1532
|
},
|
|
1533
1533
|
(err) => {
|
|
1534
1534
|
clearTimeout(timer2);
|
|
@@ -2063,8 +2063,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2063
2063
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2064
2064
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2065
2065
|
let release;
|
|
2066
|
-
const mine = new Promise((
|
|
2067
|
-
release =
|
|
2066
|
+
const mine = new Promise((resolve23) => {
|
|
2067
|
+
release = resolve23;
|
|
2068
2068
|
});
|
|
2069
2069
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2070
2070
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -3100,11 +3100,11 @@ async function connectWithReconnect(conn) {
|
|
|
3100
3100
|
console.error(
|
|
3101
3101
|
`${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3102
3102
|
);
|
|
3103
|
-
await new Promise((
|
|
3104
|
-
const timer2 = setTimeout(
|
|
3103
|
+
await new Promise((resolve23) => {
|
|
3104
|
+
const timer2 = setTimeout(resolve23, delay);
|
|
3105
3105
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3106
3106
|
clearTimeout(timer2);
|
|
3107
|
-
|
|
3107
|
+
resolve23();
|
|
3108
3108
|
}, { once: true });
|
|
3109
3109
|
});
|
|
3110
3110
|
}
|
|
@@ -3112,16 +3112,16 @@ async function connectWithReconnect(conn) {
|
|
|
3112
3112
|
}
|
|
3113
3113
|
}
|
|
3114
3114
|
function waitForDisconnectEvent(conn) {
|
|
3115
|
-
return new Promise((
|
|
3115
|
+
return new Promise((resolve23) => {
|
|
3116
3116
|
if (!conn.sock) {
|
|
3117
|
-
|
|
3117
|
+
resolve23();
|
|
3118
3118
|
return;
|
|
3119
3119
|
}
|
|
3120
3120
|
const sock = conn.sock;
|
|
3121
3121
|
const handler = (update) => {
|
|
3122
3122
|
if (update.connection === "close") {
|
|
3123
3123
|
sock.ev.off("connection.update", handler);
|
|
3124
|
-
|
|
3124
|
+
resolve23();
|
|
3125
3125
|
}
|
|
3126
3126
|
};
|
|
3127
3127
|
sock.ev.on("connection.update", handler);
|
|
@@ -3383,8 +3383,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3383
3383
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
3384
3384
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
3385
3385
|
let resolvePending;
|
|
3386
|
-
const sttPending = new Promise((
|
|
3387
|
-
resolvePending =
|
|
3386
|
+
const sttPending = new Promise((resolve23) => {
|
|
3387
|
+
resolvePending = resolve23;
|
|
3388
3388
|
});
|
|
3389
3389
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
3390
3390
|
try {
|
|
@@ -3788,20 +3788,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
3788
3788
|
|
|
3789
3789
|
// server/routes/health.ts
|
|
3790
3790
|
function checkPort(port2, timeoutMs = 500) {
|
|
3791
|
-
return new Promise((
|
|
3791
|
+
return new Promise((resolve23) => {
|
|
3792
3792
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
3793
3793
|
socket.setTimeout(timeoutMs);
|
|
3794
3794
|
socket.once("connect", () => {
|
|
3795
3795
|
socket.destroy();
|
|
3796
|
-
|
|
3796
|
+
resolve23(true);
|
|
3797
3797
|
});
|
|
3798
3798
|
socket.once("error", () => {
|
|
3799
3799
|
socket.destroy();
|
|
3800
|
-
|
|
3800
|
+
resolve23(false);
|
|
3801
3801
|
});
|
|
3802
3802
|
socket.once("timeout", () => {
|
|
3803
3803
|
socket.destroy();
|
|
3804
|
-
|
|
3804
|
+
resolve23(false);
|
|
3805
3805
|
});
|
|
3806
3806
|
});
|
|
3807
3807
|
}
|
|
@@ -4537,12 +4537,12 @@ async function dispatchOnce(input) {
|
|
|
4537
4537
|
});
|
|
4538
4538
|
if (!entry) return { error: "spawn-failed" };
|
|
4539
4539
|
entry.lastInboundAt = Date.now();
|
|
4540
|
-
let
|
|
4540
|
+
let resolve23;
|
|
4541
4541
|
const turnPromise = new Promise((r) => {
|
|
4542
|
-
|
|
4542
|
+
resolve23 = r;
|
|
4543
4543
|
});
|
|
4544
4544
|
const listener = (text) => {
|
|
4545
|
-
|
|
4545
|
+
resolve23(text);
|
|
4546
4546
|
};
|
|
4547
4547
|
entry.subscribers.add(listener);
|
|
4548
4548
|
const writeOk = await writeInput(entry, input.text);
|
|
@@ -4984,8 +4984,8 @@ async function startLogin(opts) {
|
|
|
4984
4984
|
resetActiveLogin(accountId);
|
|
4985
4985
|
let resolveQr = null;
|
|
4986
4986
|
let rejectQr = null;
|
|
4987
|
-
const qrPromise = new Promise((
|
|
4988
|
-
resolveQr =
|
|
4987
|
+
const qrPromise = new Promise((resolve23, reject) => {
|
|
4988
|
+
resolveQr = resolve23;
|
|
4989
4989
|
rejectQr = reject;
|
|
4990
4990
|
});
|
|
4991
4991
|
const qrTimer = setTimeout(
|
|
@@ -7966,13 +7966,13 @@ ${fm}
|
|
|
7966
7966
|
}
|
|
7967
7967
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
7968
7968
|
const skills = [];
|
|
7969
|
-
for (const
|
|
7970
|
-
const skillPath = join10(dir,
|
|
7969
|
+
for (const relPath of skillPaths) {
|
|
7970
|
+
const skillPath = join10(dir, relPath);
|
|
7971
7971
|
const skillFm = readFrontmatter(skillPath);
|
|
7972
7972
|
if (!skillFm) continue;
|
|
7973
7973
|
const skillName = frontmatterField(`---
|
|
7974
7974
|
${skillFm}
|
|
7975
|
-
---`, "name") ??
|
|
7975
|
+
---`, "name") ?? relPath;
|
|
7976
7976
|
const skillDesc = frontmatterField(`---
|
|
7977
7977
|
${skillFm}
|
|
7978
7978
|
---`, "description");
|
|
@@ -8391,8 +8391,8 @@ var DATA_ROOT = resolve12(PLATFORM_ROOT5, "..", "data");
|
|
|
8391
8391
|
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve12(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
8392
8392
|
var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
|
|
8393
8393
|
var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8394
|
-
function crossesForeignAccountPartition(
|
|
8395
|
-
const segs =
|
|
8394
|
+
function crossesForeignAccountPartition(relPath, accountId) {
|
|
8395
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
8396
8396
|
if (segs.length < 2) return false;
|
|
8397
8397
|
if (!ACCOUNT_PARTITION_DIRS.has(segs[0])) return false;
|
|
8398
8398
|
const owner = segs[1];
|
|
@@ -8432,8 +8432,8 @@ function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
|
8432
8432
|
if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep2)) {
|
|
8433
8433
|
return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: resolvedReal };
|
|
8434
8434
|
}
|
|
8435
|
-
const
|
|
8436
|
-
return { ok: true, absolute: resolvedReal, dataRootReal: rootReal, relative:
|
|
8435
|
+
const relPath = relative(rootReal, resolvedReal) || ".";
|
|
8436
|
+
return { ok: true, absolute: resolvedReal, dataRootReal: rootReal, relative: relPath };
|
|
8437
8437
|
}
|
|
8438
8438
|
function resolveDataPath(raw) {
|
|
8439
8439
|
return resolveUnderRoot(raw, DATA_ROOT, "DATA_ROOT");
|
|
@@ -8680,8 +8680,8 @@ async function restoreNode(params) {
|
|
|
8680
8680
|
|
|
8681
8681
|
// app/lib/file-delete-cascade.ts
|
|
8682
8682
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8683
|
-
function parseAttachmentPath(
|
|
8684
|
-
const segments =
|
|
8683
|
+
function parseAttachmentPath(relPath) {
|
|
8684
|
+
const segments = relPath.split("/").filter(Boolean);
|
|
8685
8685
|
if (segments.length !== 4) return null;
|
|
8686
8686
|
if (segments[0] !== "uploads") return null;
|
|
8687
8687
|
const accountId = segments[1];
|
|
@@ -9246,9 +9246,9 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
9246
9246
|
}
|
|
9247
9247
|
}
|
|
9248
9248
|
}
|
|
9249
|
-
function buildDisplayPath(
|
|
9250
|
-
if (
|
|
9251
|
-
return
|
|
9249
|
+
function buildDisplayPath(relPath, accountNames) {
|
|
9250
|
+
if (relPath === "." || relPath === "") return [];
|
|
9251
|
+
return relPath.split("/").filter(Boolean).map((seg) => {
|
|
9252
9252
|
const dn = UUID_RE3.test(seg) ? accountNames.get(seg) : void 0;
|
|
9253
9253
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
9254
9254
|
});
|
|
@@ -9286,9 +9286,9 @@ app15.get("/", requireAdminSession, async (c) => {
|
|
|
9286
9286
|
}
|
|
9287
9287
|
return c.json({ error: resolution.error }, resolution.status);
|
|
9288
9288
|
}
|
|
9289
|
-
const { absolute, relative:
|
|
9290
|
-
if (crossesForeignAccountPartition(
|
|
9291
|
-
console.error(`[data] account-scope-blocked endpoint="/api/admin/files" path="${
|
|
9289
|
+
const { absolute, relative: relPath } = resolution;
|
|
9290
|
+
if (crossesForeignAccountPartition(relPath, accountId)) {
|
|
9291
|
+
console.error(`[data] account-scope-blocked endpoint="/api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
9292
9292
|
return c.json({ error: "Not found" }, 404);
|
|
9293
9293
|
}
|
|
9294
9294
|
try {
|
|
@@ -9297,7 +9297,7 @@ app15.get("/", requireAdminSession, async (c) => {
|
|
|
9297
9297
|
return c.json({ error: "Path is not a directory \u2014 use /api/admin/files/download for files" }, 400);
|
|
9298
9298
|
}
|
|
9299
9299
|
const names = await readdir3(absolute);
|
|
9300
|
-
const segs =
|
|
9300
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
9301
9301
|
const isAccountParent = segs.length === 1 && (segs[0] === "accounts" || segs[0] === "uploads");
|
|
9302
9302
|
const entries = [];
|
|
9303
9303
|
for (const name of names) {
|
|
@@ -9328,17 +9328,17 @@ app15.get("/", requireAdminSession, async (c) => {
|
|
|
9328
9328
|
const bKey = b.displayName ?? b.name;
|
|
9329
9329
|
return aKey.localeCompare(bKey);
|
|
9330
9330
|
});
|
|
9331
|
-
const displayPath = buildDisplayPath(
|
|
9332
|
-
console.error(`[data] file-list path="${
|
|
9333
|
-
return c.json({ path:
|
|
9331
|
+
const displayPath = buildDisplayPath(relPath, accountNames);
|
|
9332
|
+
console.error(`[data] file-list path="${relPath}" entries=${entries.length}`);
|
|
9333
|
+
return c.json({ path: relPath, displayPath, entries });
|
|
9334
9334
|
} catch (err) {
|
|
9335
9335
|
const code = err.code;
|
|
9336
9336
|
if (code === "ENOENT") {
|
|
9337
|
-
console.error(`[data] file-list not-found path="${
|
|
9337
|
+
console.error(`[data] file-list not-found path="${relPath}"`);
|
|
9338
9338
|
return c.json({ error: "Not found" }, 404);
|
|
9339
9339
|
}
|
|
9340
9340
|
const message = err instanceof Error ? err.message : String(err);
|
|
9341
|
-
console.error(`[data] file-list error path="${
|
|
9341
|
+
console.error(`[data] file-list error path="${relPath}" err="${message}"`);
|
|
9342
9342
|
return c.json({ error: message }, 500);
|
|
9343
9343
|
}
|
|
9344
9344
|
});
|
|
@@ -9362,16 +9362,16 @@ app15.get("/download", requireAdminSession, async (c) => {
|
|
|
9362
9362
|
}
|
|
9363
9363
|
return c.json({ error: resolution.error }, resolution.status);
|
|
9364
9364
|
}
|
|
9365
|
-
const { absolute, relative:
|
|
9365
|
+
const { absolute, relative: relPath } = resolution;
|
|
9366
9366
|
if (root === "claude-uploads") {
|
|
9367
|
-
const attachmentId =
|
|
9367
|
+
const attachmentId = relPath.split("/").filter(Boolean)[0] ?? "";
|
|
9368
9368
|
const owned = await knowledgeDocOwnedByAccount(accountId, attachmentId);
|
|
9369
9369
|
if (!owned) {
|
|
9370
9370
|
console.error(`[data] account-scope-blocked root="claude-uploads" attachmentId="${attachmentId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
9371
9371
|
return c.json({ error: "Not found" }, 404);
|
|
9372
9372
|
}
|
|
9373
|
-
} else if (crossesForeignAccountPartition(
|
|
9374
|
-
console.error(`[data] account-scope-blocked endpoint="/api/admin/files/download" path="${
|
|
9373
|
+
} else if (crossesForeignAccountPartition(relPath, accountId)) {
|
|
9374
|
+
console.error(`[data] account-scope-blocked endpoint="/api/admin/files/download" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
9375
9375
|
return c.json({ error: "Not found" }, 404);
|
|
9376
9376
|
}
|
|
9377
9377
|
try {
|
|
@@ -9383,7 +9383,7 @@ app15.get("/download", requireAdminSession, async (c) => {
|
|
|
9383
9383
|
const mimeType = detectMimeType(absolute);
|
|
9384
9384
|
const nodeStream = createReadStream2(absolute);
|
|
9385
9385
|
const webStream = Readable2.toWeb(nodeStream);
|
|
9386
|
-
console.error(`[data] file-download root="${root}" path="${
|
|
9386
|
+
console.error(`[data] file-download root="${root}" path="${relPath}" size=${info.size}`);
|
|
9387
9387
|
const safeQuotedName = filename.replace(/[\r\n"\\]/g, "_");
|
|
9388
9388
|
const encodedName = encodeURIComponent(filename);
|
|
9389
9389
|
return new Response(webStream, {
|
|
@@ -9398,11 +9398,11 @@ app15.get("/download", requireAdminSession, async (c) => {
|
|
|
9398
9398
|
} catch (err) {
|
|
9399
9399
|
const code = err.code;
|
|
9400
9400
|
if (code === "ENOENT") {
|
|
9401
|
-
console.error(`[data] file-download not-found path="${
|
|
9401
|
+
console.error(`[data] file-download not-found path="${relPath}"`);
|
|
9402
9402
|
return c.json({ error: "Not found" }, 404);
|
|
9403
9403
|
}
|
|
9404
9404
|
const message = err instanceof Error ? err.message : String(err);
|
|
9405
|
-
console.error(`[data] file-download error path="${
|
|
9405
|
+
console.error(`[data] file-download error path="${relPath}" err="${message}"`);
|
|
9406
9406
|
return c.json({ error: message }, 500);
|
|
9407
9407
|
}
|
|
9408
9408
|
});
|
|
@@ -9483,15 +9483,15 @@ app15.delete("/", requireAdminSession, async (c) => {
|
|
|
9483
9483
|
}
|
|
9484
9484
|
return c.json({ error: resolution.error }, resolution.status);
|
|
9485
9485
|
}
|
|
9486
|
-
const { absolute, relative:
|
|
9487
|
-
if (crossesForeignAccountPartition(
|
|
9488
|
-
console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${
|
|
9486
|
+
const { absolute, relative: relPath } = resolution;
|
|
9487
|
+
if (crossesForeignAccountPartition(relPath, accountId)) {
|
|
9488
|
+
console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
9489
9489
|
return c.json({ error: "Not found" }, 404);
|
|
9490
9490
|
}
|
|
9491
9491
|
const base = basename4(absolute);
|
|
9492
|
-
const segments =
|
|
9492
|
+
const segments = relPath.split("/").filter(Boolean);
|
|
9493
9493
|
if (base === "account.json" || segments.includes(".git")) {
|
|
9494
|
-
console.error(`[data] file-delete blocked path="${
|
|
9494
|
+
console.error(`[data] file-delete blocked path="${relPath}" reason="protected"`);
|
|
9495
9495
|
return c.json({ error: "Protected file \u2014 refusing to delete" }, 403);
|
|
9496
9496
|
}
|
|
9497
9497
|
try {
|
|
@@ -9512,34 +9512,34 @@ app15.delete("/", requireAdminSession, async (c) => {
|
|
|
9512
9512
|
} catch {
|
|
9513
9513
|
}
|
|
9514
9514
|
}
|
|
9515
|
-
console.error(`[data] file-delete path="${
|
|
9515
|
+
console.error(`[data] file-delete path="${relPath}" bytes=${info.size}`);
|
|
9516
9516
|
try {
|
|
9517
|
-
await dropFileIndex(accountId,
|
|
9517
|
+
await dropFileIndex(accountId, relPath);
|
|
9518
9518
|
} catch (err) {
|
|
9519
|
-
console.error(`[data] file-delete index-drop-failed path="${
|
|
9519
|
+
console.error(`[data] file-delete index-drop-failed path="${relPath}" err="${err instanceof Error ? err.message : String(err)}"`);
|
|
9520
9520
|
}
|
|
9521
|
-
const parsed = parseAttachmentPath(
|
|
9521
|
+
const parsed = parseAttachmentPath(relPath);
|
|
9522
9522
|
if (parsed) {
|
|
9523
9523
|
try {
|
|
9524
9524
|
const { nodes } = await cascadeDeleteDocument({
|
|
9525
9525
|
accountId,
|
|
9526
9526
|
attachmentId: parsed.attachmentId
|
|
9527
9527
|
});
|
|
9528
|
-
console.error(`[data] file-delete graph-cascade path="${
|
|
9528
|
+
console.error(`[data] file-delete graph-cascade path="${relPath}" nodes=${nodes}`);
|
|
9529
9529
|
} catch (err) {
|
|
9530
9530
|
const message = err instanceof Error ? err.message : String(err);
|
|
9531
|
-
console.error(`[data] file-delete graph-cascade-failed path="${
|
|
9531
|
+
console.error(`[data] file-delete graph-cascade-failed path="${relPath}" err="${message}"`);
|
|
9532
9532
|
}
|
|
9533
9533
|
}
|
|
9534
9534
|
return c.json({ ok: true });
|
|
9535
9535
|
} catch (err) {
|
|
9536
9536
|
const code = err.code;
|
|
9537
9537
|
if (code === "ENOENT") {
|
|
9538
|
-
console.error(`[data] file-delete not-found path="${
|
|
9538
|
+
console.error(`[data] file-delete not-found path="${relPath}"`);
|
|
9539
9539
|
return c.json({ error: "Not found" }, 404);
|
|
9540
9540
|
}
|
|
9541
9541
|
const message = err instanceof Error ? err.message : String(err);
|
|
9542
|
-
console.error(`[data] file-delete error path="${
|
|
9542
|
+
console.error(`[data] file-delete error path="${relPath}" err="${message}"`);
|
|
9543
9543
|
return c.json({ error: message }, 500);
|
|
9544
9544
|
}
|
|
9545
9545
|
});
|
|
@@ -11601,7 +11601,6 @@ async function fetchOutputArtefacts(accountId) {
|
|
|
11601
11601
|
name: displayName ?? basename5(relativePath),
|
|
11602
11602
|
kind: "output-file",
|
|
11603
11603
|
updatedAt: modifiedAt,
|
|
11604
|
-
editable: false,
|
|
11605
11604
|
mimeType,
|
|
11606
11605
|
downloadPath: relativePath,
|
|
11607
11606
|
downloadRoot: "data"
|
|
@@ -11628,8 +11627,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
11628
11627
|
overridePath,
|
|
11629
11628
|
overrideRoot: accountDir,
|
|
11630
11629
|
bundledPath,
|
|
11631
|
-
bundledRoot: PLATFORM_ROOT
|
|
11632
|
-
editable: true
|
|
11630
|
+
bundledRoot: PLATFORM_ROOT
|
|
11633
11631
|
});
|
|
11634
11632
|
if (row) rows.push(row);
|
|
11635
11633
|
}
|
|
@@ -11646,8 +11644,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
11646
11644
|
overridePath,
|
|
11647
11645
|
overrideRoot: accountDir,
|
|
11648
11646
|
bundledPath,
|
|
11649
|
-
bundledRoot: PLATFORM_ROOT
|
|
11650
|
-
editable: false
|
|
11647
|
+
bundledRoot: PLATFORM_ROOT
|
|
11651
11648
|
});
|
|
11652
11649
|
if (row) rows.push(row);
|
|
11653
11650
|
}
|
|
@@ -11700,7 +11697,6 @@ async function readAgentTemplateRow(inp) {
|
|
|
11700
11697
|
name: inp.displayName,
|
|
11701
11698
|
kind: "agent-template",
|
|
11702
11699
|
updatedAt: st.mtime.toISOString(),
|
|
11703
|
-
editable: inp.editable,
|
|
11704
11700
|
mimeType: "text/markdown",
|
|
11705
11701
|
// Override paths live under <accountDir> (inside DATA_ROOT) and are
|
|
11706
11702
|
// downloadable; bundled-fallback templates live under PLATFORM_ROOT
|
|
@@ -11724,89 +11720,86 @@ function isWithin(target, root) {
|
|
|
11724
11720
|
}
|
|
11725
11721
|
var sidebar_artefacts_default = app22;
|
|
11726
11722
|
|
|
11727
|
-
// server/routes/admin/sidebar-
|
|
11728
|
-
import {
|
|
11729
|
-
import {
|
|
11730
|
-
var
|
|
11723
|
+
// server/routes/admin/sidebar-sessions.ts
|
|
11724
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
11725
|
+
import { join as join13 } from "path";
|
|
11726
|
+
var RC_URL_RE = /https:\/\/claude\.ai\/code\/session_[A-Za-z0-9_-]+/;
|
|
11727
|
+
var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
|
|
11728
|
+
var TITLE_MAX = 80;
|
|
11731
11729
|
var app23 = new Hono();
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
const
|
|
11737
|
-
|
|
11738
|
-
return c.json({ error: "id and content required" }, 400);
|
|
11739
|
-
}
|
|
11740
|
-
const accountDir = resolve16(ACCOUNTS_DIR, accountId);
|
|
11741
|
-
const resolved = await resolveSavePath(body.id, accountDir);
|
|
11742
|
-
if (resolved.kind === "reject") {
|
|
11743
|
-
console.error(
|
|
11744
|
-
`[admin/sidebar-artefact-save] auth-rejected reason=${resolved.reason} path=${body.id}`
|
|
11745
|
-
);
|
|
11746
|
-
return c.json({ error: resolved.reason }, resolved.status);
|
|
11747
|
-
}
|
|
11748
|
-
const start = Date.now();
|
|
11730
|
+
function claudeConfigDir() {
|
|
11731
|
+
return process.env.CLAUDE_CONFIG_DIR ?? null;
|
|
11732
|
+
}
|
|
11733
|
+
function enumerateJsonls(projectsRoot) {
|
|
11734
|
+
const out = [];
|
|
11735
|
+
let slugs;
|
|
11749
11736
|
try {
|
|
11750
|
-
|
|
11737
|
+
slugs = readdirSync8(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
11751
11738
|
} catch (err) {
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
`[admin/sidebar-artefact-save] write-failed path=${relPath(resolved.path, accountDir)} error="${message}"`
|
|
11755
|
-
);
|
|
11756
|
-
return c.json({ error: "Write failed" }, 500);
|
|
11757
|
-
}
|
|
11758
|
-
let updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11759
|
-
try {
|
|
11760
|
-
const st = await stat6(resolved.path);
|
|
11761
|
-
updatedAt = st.mtime.toISOString();
|
|
11762
|
-
} catch {
|
|
11763
|
-
}
|
|
11764
|
-
const ms = Date.now() - start;
|
|
11765
|
-
console.log(
|
|
11766
|
-
`[admin/sidebar-artefact-save] account=${accountId} path=${relPath(resolved.path, accountDir)} bytes=${body.content.length} ms=${ms}`
|
|
11767
|
-
);
|
|
11768
|
-
return c.json({ updatedAt });
|
|
11769
|
-
});
|
|
11770
|
-
async function resolveSavePath(id, accountDir) {
|
|
11771
|
-
if (!id.startsWith("agent-template:")) {
|
|
11772
|
-
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11773
|
-
}
|
|
11774
|
-
const parts = id.split(":");
|
|
11775
|
-
if (parts.length !== 3) return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11776
|
-
const [, role, filename] = parts;
|
|
11777
|
-
if (role === "specialist") {
|
|
11778
|
-
return { kind: "reject", status: 403, reason: "specialist-write-blocked" };
|
|
11739
|
+
if (err.code === "ENOENT") return out;
|
|
11740
|
+
throw err;
|
|
11779
11741
|
}
|
|
11780
|
-
|
|
11781
|
-
|
|
11742
|
+
for (const slug of slugs) {
|
|
11743
|
+
const slugDir = join13(projectsRoot, slug);
|
|
11744
|
+
let entries;
|
|
11745
|
+
try {
|
|
11746
|
+
entries = readdirSync8(slugDir, { withFileTypes: true });
|
|
11747
|
+
} catch (err) {
|
|
11748
|
+
const code = err.code ?? "unknown";
|
|
11749
|
+
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
11750
|
+
continue;
|
|
11751
|
+
}
|
|
11752
|
+
for (const entry of entries) {
|
|
11753
|
+
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
11754
|
+
out.push({ path: join13(slugDir, entry.name), isSubagent: false });
|
|
11755
|
+
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
11756
|
+
const subDir = join13(slugDir, entry.name);
|
|
11757
|
+
let subEntries;
|
|
11758
|
+
try {
|
|
11759
|
+
subEntries = readdirSync8(subDir, { withFileTypes: true });
|
|
11760
|
+
} catch (err) {
|
|
11761
|
+
const code = err.code ?? "unknown";
|
|
11762
|
+
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
11763
|
+
continue;
|
|
11764
|
+
}
|
|
11765
|
+
for (const sub of subEntries) {
|
|
11766
|
+
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
11767
|
+
out.push({ path: join13(subDir, sub.name), isSubagent: true });
|
|
11768
|
+
}
|
|
11769
|
+
}
|
|
11770
|
+
}
|
|
11771
|
+
}
|
|
11782
11772
|
}
|
|
11783
|
-
|
|
11784
|
-
|
|
11773
|
+
return out;
|
|
11774
|
+
}
|
|
11775
|
+
function liveSessionIdSet(configDir2) {
|
|
11776
|
+
const out = /* @__PURE__ */ new Set();
|
|
11777
|
+
const sessionsDir = join13(configDir2, "sessions");
|
|
11778
|
+
let entries;
|
|
11785
11779
|
try {
|
|
11786
|
-
|
|
11780
|
+
entries = readdirSync8(sessionsDir, { withFileTypes: true });
|
|
11787
11781
|
} catch {
|
|
11788
|
-
return
|
|
11782
|
+
return out;
|
|
11789
11783
|
}
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
return join13(configDir2, "projects", slug);
|
|
11784
|
+
for (const entry of entries) {
|
|
11785
|
+
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
11786
|
+
let body;
|
|
11787
|
+
try {
|
|
11788
|
+
body = readFileSync14(join13(sessionsDir, entry.name), "utf8");
|
|
11789
|
+
} catch {
|
|
11790
|
+
continue;
|
|
11791
|
+
}
|
|
11792
|
+
let parsed;
|
|
11793
|
+
try {
|
|
11794
|
+
parsed = JSON.parse(body);
|
|
11795
|
+
} catch {
|
|
11796
|
+
continue;
|
|
11797
|
+
}
|
|
11798
|
+
if (!parsed || typeof parsed !== "object") continue;
|
|
11799
|
+
const sid = parsed.sessionId;
|
|
11800
|
+
if (typeof sid === "string" && sid.length > 0) out.add(sid);
|
|
11801
|
+
}
|
|
11802
|
+
return out;
|
|
11810
11803
|
}
|
|
11811
11804
|
function firstUserMessage(body) {
|
|
11812
11805
|
for (const line of body.split("\n")) {
|
|
@@ -11828,35 +11821,28 @@ function firstUserMessage(body) {
|
|
|
11828
11821
|
}
|
|
11829
11822
|
return null;
|
|
11830
11823
|
}
|
|
11831
|
-
|
|
11832
|
-
const
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
return c.json({ error: "Account not found for session" }, 401);
|
|
11836
|
-
}
|
|
11837
|
-
const projectsDir = projectsDirForAccount(accountId);
|
|
11838
|
-
if (!projectsDir) {
|
|
11839
|
-
console.error(`[admin-sessions-list] account=${accountId} no-claude-config-dir`);
|
|
11824
|
+
app23.get("/", requireAdminSession, async (c) => {
|
|
11825
|
+
const configDir2 = claudeConfigDir();
|
|
11826
|
+
if (!configDir2) {
|
|
11827
|
+
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
11840
11828
|
return c.json({ sessions: [] });
|
|
11841
11829
|
}
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
} catch (err) {
|
|
11846
|
-
const code = err.code;
|
|
11847
|
-
if (code === "ENOENT") {
|
|
11848
|
-
console.log(`[admin-sessions-list] account=${accountId} rows=0 reason=no-projects-dir`);
|
|
11849
|
-
return c.json({ sessions: [] });
|
|
11850
|
-
}
|
|
11851
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
11852
|
-
console.error(`[admin-sessions-list] account=${accountId} readdir-failed error="${message}"`);
|
|
11853
|
-
return c.json({ error: "projects-dir-unreadable" }, 500);
|
|
11854
|
-
}
|
|
11830
|
+
const projectsRoot = join13(configDir2, "projects");
|
|
11831
|
+
const jsonls = enumerateJsonls(projectsRoot);
|
|
11832
|
+
const liveIds = liveSessionIdSet(configDir2);
|
|
11855
11833
|
const rows = [];
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11834
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
11835
|
+
let liveCount = 0;
|
|
11836
|
+
let rcCount = 0;
|
|
11837
|
+
let subagentCount = 0;
|
|
11838
|
+
for (const { path: path2, isSubagent } of jsonls) {
|
|
11839
|
+
const base = path2.slice(path2.lastIndexOf("/") + 1);
|
|
11840
|
+
const sessionId = base.slice(0, -".jsonl".length);
|
|
11841
|
+
if (seenIds.has(sessionId)) {
|
|
11842
|
+
console.error(`[admin-sessions-list] duplicate-sessionId sessionId=${sessionId} path=${path2}`);
|
|
11843
|
+
continue;
|
|
11844
|
+
}
|
|
11845
|
+
seenIds.add(sessionId);
|
|
11860
11846
|
let body;
|
|
11861
11847
|
let mtimeMs;
|
|
11862
11848
|
try {
|
|
@@ -11866,20 +11852,28 @@ app24.get("/", requireAdminSession, async (c) => {
|
|
|
11866
11852
|
continue;
|
|
11867
11853
|
}
|
|
11868
11854
|
const urlMatch = body.match(RC_URL_RE);
|
|
11869
|
-
|
|
11855
|
+
const live = liveIds.has(sessionId);
|
|
11870
11856
|
const title = firstUserMessage(body) ?? sessionId.slice(0, 8);
|
|
11871
|
-
|
|
11857
|
+
const row = {
|
|
11872
11858
|
sessionId,
|
|
11873
11859
|
title,
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11860
|
+
startedAt: new Date(mtimeMs).toISOString(),
|
|
11861
|
+
live,
|
|
11862
|
+
isSubagent
|
|
11863
|
+
};
|
|
11864
|
+
if (urlMatch) row.rcUrl = urlMatch[0];
|
|
11865
|
+
rows.push(row);
|
|
11866
|
+
if (live) liveCount += 1;
|
|
11867
|
+
if (urlMatch) rcCount += 1;
|
|
11868
|
+
if (isSubagent) subagentCount += 1;
|
|
11877
11869
|
}
|
|
11878
|
-
rows.sort((a, b) => a.
|
|
11879
|
-
console.log(
|
|
11870
|
+
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
11871
|
+
console.log(
|
|
11872
|
+
`[admin-sessions-list] rows=${rows.length} live=${liveCount} rc=${rcCount} subagents=${subagentCount}`
|
|
11873
|
+
);
|
|
11880
11874
|
return c.json({ sessions: rows });
|
|
11881
11875
|
});
|
|
11882
|
-
var sidebar_sessions_default =
|
|
11876
|
+
var sidebar_sessions_default = app23;
|
|
11883
11877
|
|
|
11884
11878
|
// server/routes/admin/system-stats.ts
|
|
11885
11879
|
import { readFile as readFile5 } from "fs/promises";
|
|
@@ -11976,8 +11970,8 @@ async function sample() {
|
|
|
11976
11970
|
if (process.platform === "linux") return sampleLinux();
|
|
11977
11971
|
return sampleOsFallback();
|
|
11978
11972
|
}
|
|
11979
|
-
var
|
|
11980
|
-
|
|
11973
|
+
var app24 = new Hono();
|
|
11974
|
+
app24.get("/", async (c) => {
|
|
11981
11975
|
const started = Date.now();
|
|
11982
11976
|
if (!inflight) {
|
|
11983
11977
|
inflight = sample().finally(() => {
|
|
@@ -12000,12 +11994,12 @@ app25.get("/", async (c) => {
|
|
|
12000
11994
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
12001
11995
|
}
|
|
12002
11996
|
});
|
|
12003
|
-
var system_stats_default =
|
|
11997
|
+
var system_stats_default = app24;
|
|
12004
11998
|
|
|
12005
11999
|
// server/routes/admin/health.ts
|
|
12006
12000
|
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
|
|
12007
|
-
import { resolve as
|
|
12008
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
12001
|
+
import { resolve as resolve16, join as join14 } from "path";
|
|
12002
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
12009
12003
|
var brandHostname = "maxy";
|
|
12010
12004
|
var brandJsonPath = join14(PLATFORM_ROOT6, "config", "brand.json");
|
|
12011
12005
|
if (existsSync17(brandJsonPath)) {
|
|
@@ -12015,7 +12009,7 @@ if (existsSync17(brandJsonPath)) {
|
|
|
12015
12009
|
} catch {
|
|
12016
12010
|
}
|
|
12017
12011
|
}
|
|
12018
|
-
var VERSION_FILE =
|
|
12012
|
+
var VERSION_FILE = resolve16(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
12019
12013
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
12020
12014
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
12021
12015
|
function readVersion() {
|
|
@@ -12045,8 +12039,8 @@ async function probeConversationDb() {
|
|
|
12045
12039
|
});
|
|
12046
12040
|
}
|
|
12047
12041
|
}
|
|
12048
|
-
var
|
|
12049
|
-
|
|
12042
|
+
var app25 = new Hono();
|
|
12043
|
+
app25.get("/", async (c) => {
|
|
12050
12044
|
const version = readVersion();
|
|
12051
12045
|
const probe = await probeConversationDb();
|
|
12052
12046
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -12068,7 +12062,7 @@ app26.get("/", async (c) => {
|
|
|
12068
12062
|
uptimeMs
|
|
12069
12063
|
});
|
|
12070
12064
|
});
|
|
12071
|
-
var health_default2 =
|
|
12065
|
+
var health_default2 = app25;
|
|
12072
12066
|
|
|
12073
12067
|
// server/routes/admin/linkedin-ingest.ts
|
|
12074
12068
|
var TAG20 = "[linkedin-ingest-route]";
|
|
@@ -12164,8 +12158,8 @@ function buildInitialMessage(env) {
|
|
|
12164
12158
|
}
|
|
12165
12159
|
return header;
|
|
12166
12160
|
}
|
|
12167
|
-
var
|
|
12168
|
-
|
|
12161
|
+
var app26 = new Hono();
|
|
12162
|
+
app26.post("/", requireAdminSession, async (c) => {
|
|
12169
12163
|
let body;
|
|
12170
12164
|
try {
|
|
12171
12165
|
body = await c.req.json();
|
|
@@ -12219,7 +12213,7 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
12219
12213
|
);
|
|
12220
12214
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: claudeSessionId }, 202);
|
|
12221
12215
|
});
|
|
12222
|
-
var linkedin_ingest_default =
|
|
12216
|
+
var linkedin_ingest_default = app26;
|
|
12223
12217
|
|
|
12224
12218
|
// server/routes/admin/post-turn-context.ts
|
|
12225
12219
|
import neo4j2 from "neo4j-driver";
|
|
@@ -12261,8 +12255,8 @@ function pruneProperties(raw) {
|
|
|
12261
12255
|
}
|
|
12262
12256
|
return out;
|
|
12263
12257
|
}
|
|
12264
|
-
var
|
|
12265
|
-
|
|
12258
|
+
var app27 = new Hono();
|
|
12259
|
+
app27.get("/", async (c) => {
|
|
12266
12260
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12267
12261
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
12268
12262
|
console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12322,7 +12316,7 @@ app28.get("/", async (c) => {
|
|
|
12322
12316
|
await session.close();
|
|
12323
12317
|
}
|
|
12324
12318
|
});
|
|
12325
|
-
var post_turn_context_default =
|
|
12319
|
+
var post_turn_context_default = app27;
|
|
12326
12320
|
|
|
12327
12321
|
// server/routes/admin/public-session-context.ts
|
|
12328
12322
|
import neo4j3 from "neo4j-driver";
|
|
@@ -12364,8 +12358,8 @@ function pruneProperties2(raw) {
|
|
|
12364
12358
|
}
|
|
12365
12359
|
return out;
|
|
12366
12360
|
}
|
|
12367
|
-
var
|
|
12368
|
-
|
|
12361
|
+
var app28 = new Hono();
|
|
12362
|
+
app28.get("/", async (c) => {
|
|
12369
12363
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12370
12364
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
12371
12365
|
console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12424,15 +12418,15 @@ app29.get("/", async (c) => {
|
|
|
12424
12418
|
await session.close();
|
|
12425
12419
|
}
|
|
12426
12420
|
});
|
|
12427
|
-
var public_session_context_default =
|
|
12421
|
+
var public_session_context_default = app28;
|
|
12428
12422
|
|
|
12429
12423
|
// server/routes/admin/public-session-exit.ts
|
|
12430
12424
|
var TAG23 = "[public-session-exit-route]";
|
|
12431
12425
|
function isLoopbackAddr4(addr) {
|
|
12432
12426
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
12433
12427
|
}
|
|
12434
|
-
var
|
|
12435
|
-
|
|
12428
|
+
var app29 = new Hono();
|
|
12429
|
+
app29.post("/", async (c) => {
|
|
12436
12430
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12437
12431
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
12438
12432
|
console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12459,15 +12453,15 @@ app30.post("/", async (c) => {
|
|
|
12459
12453
|
handlePublicSessionExit(sessionId);
|
|
12460
12454
|
return c.json({ ok: true });
|
|
12461
12455
|
});
|
|
12462
|
-
var public_session_exit_default =
|
|
12456
|
+
var public_session_exit_default = app29;
|
|
12463
12457
|
|
|
12464
12458
|
// server/routes/admin/access-session-evict.ts
|
|
12465
12459
|
var TAG24 = "[access-session-evict]";
|
|
12466
12460
|
function isLoopbackAddr5(addr) {
|
|
12467
12461
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
12468
12462
|
}
|
|
12469
|
-
var
|
|
12470
|
-
|
|
12463
|
+
var app30 = new Hono();
|
|
12464
|
+
app30.post("/", async (c) => {
|
|
12471
12465
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12472
12466
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
12473
12467
|
console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12495,48 +12489,47 @@ app31.post("/", async (c) => {
|
|
|
12495
12489
|
console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
|
|
12496
12490
|
return c.json({ ok: true, dropped });
|
|
12497
12491
|
});
|
|
12498
|
-
var access_session_evict_default =
|
|
12492
|
+
var access_session_evict_default = app30;
|
|
12499
12493
|
|
|
12500
12494
|
// server/routes/admin/index.ts
|
|
12501
|
-
var
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
var admin_default = app32;
|
|
12495
|
+
var app31 = new Hono();
|
|
12496
|
+
app31.route("/session", session_default);
|
|
12497
|
+
app31.route("/logs", logs_default);
|
|
12498
|
+
app31.route("/claude-info", claude_info_default);
|
|
12499
|
+
app31.route("/attachment", attachment_default);
|
|
12500
|
+
app31.route("/agents", agents_default);
|
|
12501
|
+
app31.route("/sessions", sessions_default);
|
|
12502
|
+
app31.route("/claude-sessions", claude_sessions_default);
|
|
12503
|
+
app31.route("/log-ingest", log_ingest_default);
|
|
12504
|
+
app31.route("/events", events_default);
|
|
12505
|
+
app31.route("/files", files_default);
|
|
12506
|
+
app31.route("/graph-search", graph_search_default);
|
|
12507
|
+
app31.route("/graph-subgraph", graph_subgraph_default);
|
|
12508
|
+
app31.route("/graph-delete", graph_delete_default);
|
|
12509
|
+
app31.route("/graph-restore", graph_restore_default);
|
|
12510
|
+
app31.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
12511
|
+
app31.route("/graph-default-view", graph_default_view_default);
|
|
12512
|
+
app31.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
12513
|
+
app31.route("/sidebar-sessions", sidebar_sessions_default);
|
|
12514
|
+
app31.route("/system-stats", system_stats_default);
|
|
12515
|
+
app31.route("/health-brand", health_default2);
|
|
12516
|
+
app31.route("/linkedin-ingest", linkedin_ingest_default);
|
|
12517
|
+
app31.route("/post-turn-context", post_turn_context_default);
|
|
12518
|
+
app31.route("/public-session-context", public_session_context_default);
|
|
12519
|
+
app31.route("/public-session-exit", public_session_exit_default);
|
|
12520
|
+
app31.route("/access-session-evict", access_session_evict_default);
|
|
12521
|
+
var admin_default = app31;
|
|
12529
12522
|
|
|
12530
12523
|
// app/lib/access-gate.ts
|
|
12531
12524
|
import neo4j4 from "neo4j-driver";
|
|
12532
12525
|
import { readFileSync as readFileSync16 } from "fs";
|
|
12533
|
-
import { resolve as
|
|
12526
|
+
import { resolve as resolve17 } from "path";
|
|
12534
12527
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
12535
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
12528
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
12536
12529
|
var driver = null;
|
|
12537
12530
|
function readPassword() {
|
|
12538
12531
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
12539
|
-
const passwordFile =
|
|
12532
|
+
const passwordFile = resolve17(PLATFORM_ROOT7, "config/.neo4j-password");
|
|
12540
12533
|
try {
|
|
12541
12534
|
return readFileSync16(passwordFile, "utf-8").trim();
|
|
12542
12535
|
} catch {
|
|
@@ -12739,8 +12732,8 @@ async function generateNewMagicToken(grantId) {
|
|
|
12739
12732
|
var TAG25 = "[access-verify]";
|
|
12740
12733
|
var MINT_TAG = "[access-session-mint]";
|
|
12741
12734
|
var COOKIE_NAME = "__access_session";
|
|
12742
|
-
var
|
|
12743
|
-
|
|
12735
|
+
var app32 = new Hono();
|
|
12736
|
+
app32.post("/", async (c) => {
|
|
12744
12737
|
const ip = c.var.clientIp || "unknown";
|
|
12745
12738
|
let body;
|
|
12746
12739
|
try {
|
|
@@ -12822,13 +12815,13 @@ app33.post("/", async (c) => {
|
|
|
12822
12815
|
displayName: grant.displayName
|
|
12823
12816
|
});
|
|
12824
12817
|
});
|
|
12825
|
-
var verify_token_default =
|
|
12818
|
+
var verify_token_default = app32;
|
|
12826
12819
|
|
|
12827
12820
|
// app/lib/access-email.ts
|
|
12828
12821
|
import { spawn as spawn2 } from "child_process";
|
|
12829
|
-
import { resolve as
|
|
12830
|
-
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ??
|
|
12831
|
-
var SEND_SCRIPT =
|
|
12822
|
+
import { resolve as resolve18 } from "path";
|
|
12823
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
|
|
12824
|
+
var SEND_SCRIPT = resolve18(
|
|
12832
12825
|
PLATFORM_ROOT8,
|
|
12833
12826
|
"plugins",
|
|
12834
12827
|
"email",
|
|
@@ -12885,9 +12878,9 @@ async function sendMagicLinkEmail(payload) {
|
|
|
12885
12878
|
|
|
12886
12879
|
// server/routes/access/request-magic-link.ts
|
|
12887
12880
|
var TAG26 = "[access-request-link]";
|
|
12888
|
-
var
|
|
12881
|
+
var app33 = new Hono();
|
|
12889
12882
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
12890
|
-
|
|
12883
|
+
app33.post("/", async (c) => {
|
|
12891
12884
|
let body;
|
|
12892
12885
|
try {
|
|
12893
12886
|
body = await c.req.json();
|
|
@@ -12961,17 +12954,17 @@ app34.post("/", async (c) => {
|
|
|
12961
12954
|
);
|
|
12962
12955
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
12963
12956
|
});
|
|
12964
|
-
var request_magic_link_default =
|
|
12957
|
+
var request_magic_link_default = app33;
|
|
12965
12958
|
|
|
12966
12959
|
// server/routes/access/index.ts
|
|
12967
|
-
var
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
var access_default =
|
|
12960
|
+
var app34 = new Hono();
|
|
12961
|
+
app34.route("/verify-token", verify_token_default);
|
|
12962
|
+
app34.route("/request-magic-link", request_magic_link_default);
|
|
12963
|
+
var access_default = app34;
|
|
12971
12964
|
|
|
12972
12965
|
// server/routes/sites.ts
|
|
12973
12966
|
import { existsSync as existsSync18, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
|
|
12974
|
-
import { resolve as
|
|
12967
|
+
import { resolve as resolve19 } from "path";
|
|
12975
12968
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12976
12969
|
var MIME = {
|
|
12977
12970
|
".html": "text/html; charset=utf-8",
|
|
@@ -13002,8 +12995,8 @@ function getExt(p) {
|
|
|
13002
12995
|
if (idx < p.lastIndexOf("/")) return "";
|
|
13003
12996
|
return p.slice(idx).toLowerCase();
|
|
13004
12997
|
}
|
|
13005
|
-
var
|
|
13006
|
-
|
|
12998
|
+
var app35 = new Hono();
|
|
12999
|
+
app35.get("/:rel{.*}", (c) => {
|
|
13007
13000
|
const reqPath = c.req.path;
|
|
13008
13001
|
const rawRel = c.req.param("rel") ?? "";
|
|
13009
13002
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -13028,19 +13021,19 @@ app36.get("/:rel{.*}", (c) => {
|
|
|
13028
13021
|
}
|
|
13029
13022
|
segments.push(seg);
|
|
13030
13023
|
}
|
|
13031
|
-
const rootDir =
|
|
13032
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
13024
|
+
const rootDir = resolve19(account.accountDir, "sites");
|
|
13025
|
+
let filePath = segments.length === 0 ? rootDir : resolve19(rootDir, ...segments);
|
|
13033
13026
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
13034
13027
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
13035
13028
|
return c.text("Forbidden", 403);
|
|
13036
13029
|
}
|
|
13037
|
-
let
|
|
13030
|
+
let stat7;
|
|
13038
13031
|
try {
|
|
13039
|
-
|
|
13032
|
+
stat7 = existsSync18(filePath) ? statSync8(filePath) : null;
|
|
13040
13033
|
} catch {
|
|
13041
|
-
|
|
13034
|
+
stat7 = null;
|
|
13042
13035
|
}
|
|
13043
|
-
if (
|
|
13036
|
+
if (stat7?.isDirectory() && !reqPath.endsWith("/")) {
|
|
13044
13037
|
const search = new URL(c.req.url).search;
|
|
13045
13038
|
const target = `${reqPath}/${search}`;
|
|
13046
13039
|
console.log(
|
|
@@ -13048,8 +13041,8 @@ app36.get("/:rel{.*}", (c) => {
|
|
|
13048
13041
|
);
|
|
13049
13042
|
return c.redirect(target, 301);
|
|
13050
13043
|
}
|
|
13051
|
-
if (
|
|
13052
|
-
filePath =
|
|
13044
|
+
if (stat7?.isDirectory()) {
|
|
13045
|
+
filePath = resolve19(filePath, "index.html");
|
|
13053
13046
|
}
|
|
13054
13047
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
13055
13048
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
@@ -13106,7 +13099,7 @@ app36.get("/:rel{.*}", (c) => {
|
|
|
13106
13099
|
"X-Content-Type-Options": "nosniff"
|
|
13107
13100
|
});
|
|
13108
13101
|
});
|
|
13109
|
-
var sites_default =
|
|
13102
|
+
var sites_default = app35;
|
|
13110
13103
|
|
|
13111
13104
|
// app/lib/visitor-token.ts
|
|
13112
13105
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -13206,7 +13199,7 @@ function readBrandConfig() {
|
|
|
13206
13199
|
}
|
|
13207
13200
|
|
|
13208
13201
|
// server/routes/visitor-consent.ts
|
|
13209
|
-
var
|
|
13202
|
+
var app36 = new Hono();
|
|
13210
13203
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
13211
13204
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
13212
13205
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -13251,17 +13244,17 @@ function siteSlugFromReferer(referer) {
|
|
|
13251
13244
|
return "";
|
|
13252
13245
|
}
|
|
13253
13246
|
}
|
|
13254
|
-
|
|
13247
|
+
app36.options("/consent", (c) => {
|
|
13255
13248
|
const origin = getOrigin(c);
|
|
13256
13249
|
setCorsHeaders(c, origin);
|
|
13257
13250
|
return c.body(null, 204);
|
|
13258
13251
|
});
|
|
13259
|
-
|
|
13252
|
+
app36.options("/brand-config", (c) => {
|
|
13260
13253
|
const origin = getOrigin(c);
|
|
13261
13254
|
setCorsHeaders(c, origin);
|
|
13262
13255
|
return c.body(null, 204);
|
|
13263
13256
|
});
|
|
13264
|
-
|
|
13257
|
+
app36.post("/consent", async (c) => {
|
|
13265
13258
|
const origin = getOrigin(c);
|
|
13266
13259
|
setCorsHeaders(c, origin);
|
|
13267
13260
|
let raw;
|
|
@@ -13301,7 +13294,7 @@ app37.post("/consent", async (c) => {
|
|
|
13301
13294
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
13302
13295
|
return c.body(null, 204);
|
|
13303
13296
|
});
|
|
13304
|
-
|
|
13297
|
+
app36.get("/brand-config", (c) => {
|
|
13305
13298
|
const origin = getOrigin(c);
|
|
13306
13299
|
setCorsHeaders(c, origin);
|
|
13307
13300
|
const brand = readBrandConfig();
|
|
@@ -13311,7 +13304,7 @@ app37.get("/brand-config", (c) => {
|
|
|
13311
13304
|
c.header("Cache-Control", "public, max-age=300");
|
|
13312
13305
|
return c.json({ consent: { copy, palette } });
|
|
13313
13306
|
});
|
|
13314
|
-
var visitor_consent_default =
|
|
13307
|
+
var visitor_consent_default = app36;
|
|
13315
13308
|
|
|
13316
13309
|
// server/routes/listings.ts
|
|
13317
13310
|
function getCookie(headerValue, name) {
|
|
@@ -13338,8 +13331,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
13338
13331
|
}
|
|
13339
13332
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
13340
13333
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
13341
|
-
var
|
|
13342
|
-
|
|
13334
|
+
var app37 = new Hono();
|
|
13335
|
+
app37.get("/:slug/click", async (c) => {
|
|
13343
13336
|
const slug = c.req.param("slug") ?? "";
|
|
13344
13337
|
const rawSession = c.req.query("session") ?? "";
|
|
13345
13338
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -13403,10 +13396,10 @@ app38.get("/:slug/click", async (c) => {
|
|
|
13403
13396
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
13404
13397
|
return c.redirect(redirectUrl, 302);
|
|
13405
13398
|
});
|
|
13406
|
-
var listings_default =
|
|
13399
|
+
var listings_default = app37;
|
|
13407
13400
|
|
|
13408
13401
|
// server/routes/visitor-event.ts
|
|
13409
|
-
var
|
|
13402
|
+
var app38 = new Hono();
|
|
13410
13403
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
13411
13404
|
var buckets = /* @__PURE__ */ new Map();
|
|
13412
13405
|
var RATE_LIMIT = 60;
|
|
@@ -13473,12 +13466,12 @@ function originAllowed(origin, allowlist) {
|
|
|
13473
13466
|
return false;
|
|
13474
13467
|
}
|
|
13475
13468
|
}
|
|
13476
|
-
|
|
13469
|
+
app38.options("/event", (c) => {
|
|
13477
13470
|
const origin = getOrigin2(c);
|
|
13478
13471
|
setCorsHeaders2(c, origin);
|
|
13479
13472
|
return c.body(null, 204);
|
|
13480
13473
|
});
|
|
13481
|
-
|
|
13474
|
+
app38.post("/event", async (c) => {
|
|
13482
13475
|
const origin = getOrigin2(c);
|
|
13483
13476
|
setCorsHeaders2(c, origin);
|
|
13484
13477
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -13683,7 +13676,7 @@ async function writeEvent(opts) {
|
|
|
13683
13676
|
);
|
|
13684
13677
|
}
|
|
13685
13678
|
}
|
|
13686
|
-
var visitor_event_default =
|
|
13679
|
+
var visitor_event_default = app38;
|
|
13687
13680
|
|
|
13688
13681
|
// app/lib/graph-health.ts
|
|
13689
13682
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
@@ -13768,7 +13761,7 @@ function startGraphHealthTimer() {
|
|
|
13768
13761
|
|
|
13769
13762
|
// app/lib/file-watcher.ts
|
|
13770
13763
|
import * as fsp2 from "fs/promises";
|
|
13771
|
-
import { resolve as
|
|
13764
|
+
import { resolve as resolve20, sep as sep6 } from "path";
|
|
13772
13765
|
var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13773
13766
|
var DEFAULT_COALESCE_MS = 500;
|
|
13774
13767
|
var ROOTS = ["uploads", "accounts"];
|
|
@@ -13787,7 +13780,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
13787
13780
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
13788
13781
|
for (const r of ROOTS) {
|
|
13789
13782
|
try {
|
|
13790
|
-
await fsp2.mkdir(
|
|
13783
|
+
await fsp2.mkdir(resolve20(dataRoot, r), { recursive: true });
|
|
13791
13784
|
} catch (err) {
|
|
13792
13785
|
console.error(
|
|
13793
13786
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -13808,7 +13801,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
13808
13801
|
timers.set(relativePath, t);
|
|
13809
13802
|
}
|
|
13810
13803
|
async function runHook(relativePath, accountId) {
|
|
13811
|
-
const absolute =
|
|
13804
|
+
const absolute = resolve20(dataRoot, relativePath);
|
|
13812
13805
|
let exists = false;
|
|
13813
13806
|
try {
|
|
13814
13807
|
const st = await fsp2.stat(absolute);
|
|
@@ -13832,7 +13825,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
13832
13825
|
}
|
|
13833
13826
|
}
|
|
13834
13827
|
async function watchRoot(rootName) {
|
|
13835
|
-
const absRoot =
|
|
13828
|
+
const absRoot = resolve20(dataRoot, rootName);
|
|
13836
13829
|
try {
|
|
13837
13830
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
13838
13831
|
for await (const event of iter) {
|
|
@@ -13931,7 +13924,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
13931
13924
|
// ../lib/entitlement/src/index.ts
|
|
13932
13925
|
import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
|
|
13933
13926
|
import { existsSync as existsSync20, readFileSync as readFileSync20, statSync as statSync9 } from "fs";
|
|
13934
|
-
import { resolve as
|
|
13927
|
+
import { resolve as resolve21 } from "path";
|
|
13935
13928
|
|
|
13936
13929
|
// ../lib/entitlement/src/canonicalize.ts
|
|
13937
13930
|
function canonicalize(value) {
|
|
@@ -13966,7 +13959,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
13966
13959
|
var GRACE_DAYS = 7;
|
|
13967
13960
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
13968
13961
|
function pubkeyPath(brand) {
|
|
13969
|
-
return
|
|
13962
|
+
return resolve21(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
13970
13963
|
}
|
|
13971
13964
|
var memo = null;
|
|
13972
13965
|
function memoKey(mtimeMs, account) {
|
|
@@ -13978,12 +13971,12 @@ function resolveEntitlement(brand, account) {
|
|
|
13978
13971
|
if (brand.commercialMode !== true) {
|
|
13979
13972
|
return logResolved(implicitTrust(account), null);
|
|
13980
13973
|
}
|
|
13981
|
-
const entitlementPath =
|
|
13974
|
+
const entitlementPath = resolve21(brand.configDir, "entitlement.json");
|
|
13982
13975
|
if (!existsSync20(entitlementPath)) {
|
|
13983
13976
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
13984
13977
|
}
|
|
13985
|
-
const
|
|
13986
|
-
const key = memoKey(
|
|
13978
|
+
const stat7 = statSync9(entitlementPath);
|
|
13979
|
+
const key = memoKey(stat7.mtimeMs, account);
|
|
13987
13980
|
if (memo && memo.key === key) {
|
|
13988
13981
|
return memo.result;
|
|
13989
13982
|
}
|
|
@@ -14223,9 +14216,9 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
14223
14216
|
function isPublicHost(host) {
|
|
14224
14217
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
14225
14218
|
}
|
|
14226
|
-
var
|
|
14227
|
-
|
|
14228
|
-
|
|
14219
|
+
var app39 = new Hono();
|
|
14220
|
+
app39.use("*", clientIpMiddleware);
|
|
14221
|
+
app39.use("*", async (c, next) => {
|
|
14229
14222
|
await next();
|
|
14230
14223
|
c.header("X-Content-Type-Options", "nosniff");
|
|
14231
14224
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -14235,7 +14228,7 @@ app40.use("*", async (c, next) => {
|
|
|
14235
14228
|
);
|
|
14236
14229
|
});
|
|
14237
14230
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
14238
|
-
|
|
14231
|
+
app39.use("*", async (c, next) => {
|
|
14239
14232
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
14240
14233
|
await next();
|
|
14241
14234
|
return;
|
|
@@ -14268,7 +14261,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
14268
14261
|
"/sites/"
|
|
14269
14262
|
];
|
|
14270
14263
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
14271
|
-
|
|
14264
|
+
app39.use("*", async (c, next) => {
|
|
14272
14265
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14273
14266
|
if (!isPublicHost(host)) {
|
|
14274
14267
|
await next();
|
|
@@ -14308,7 +14301,7 @@ function resolveRemoteAuthOpts() {
|
|
|
14308
14301
|
return brandLoginOpts;
|
|
14309
14302
|
}
|
|
14310
14303
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
14311
|
-
|
|
14304
|
+
app39.post("/__remote-auth/login", async (c) => {
|
|
14312
14305
|
const client = clientFrom(c);
|
|
14313
14306
|
const clientIp = client.ip || "unknown";
|
|
14314
14307
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -14353,7 +14346,7 @@ app40.post("/__remote-auth/login", async (c) => {
|
|
|
14353
14346
|
}
|
|
14354
14347
|
});
|
|
14355
14348
|
});
|
|
14356
|
-
|
|
14349
|
+
app39.get("/__remote-auth/logout", (c) => {
|
|
14357
14350
|
const client = clientFrom(c);
|
|
14358
14351
|
const clientIp = client.ip || "unknown";
|
|
14359
14352
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -14366,7 +14359,7 @@ app40.get("/__remote-auth/logout", (c) => {
|
|
|
14366
14359
|
}
|
|
14367
14360
|
});
|
|
14368
14361
|
});
|
|
14369
|
-
|
|
14362
|
+
app39.post("/__remote-auth/change-password", async (c) => {
|
|
14370
14363
|
const client = clientFrom(c);
|
|
14371
14364
|
const clientIp = client.ip || "unknown";
|
|
14372
14365
|
const rateLimited = checkRateLimit(client);
|
|
@@ -14417,13 +14410,13 @@ app40.post("/__remote-auth/change-password", async (c) => {
|
|
|
14417
14410
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
14418
14411
|
}
|
|
14419
14412
|
});
|
|
14420
|
-
|
|
14413
|
+
app39.get("/__remote-auth/setup", (c) => {
|
|
14421
14414
|
if (isRemoteAuthConfigured()) {
|
|
14422
14415
|
return c.redirect("/");
|
|
14423
14416
|
}
|
|
14424
14417
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
14425
14418
|
});
|
|
14426
|
-
|
|
14419
|
+
app39.post("/__remote-auth/set-initial-password", async (c) => {
|
|
14427
14420
|
if (isRemoteAuthConfigured()) {
|
|
14428
14421
|
return c.redirect("/");
|
|
14429
14422
|
}
|
|
@@ -14461,10 +14454,10 @@ app40.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
14461
14454
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
14462
14455
|
}
|
|
14463
14456
|
});
|
|
14464
|
-
|
|
14457
|
+
app39.get("/api/remote-auth/status", (c) => {
|
|
14465
14458
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
14466
14459
|
});
|
|
14467
|
-
|
|
14460
|
+
app39.post("/api/remote-auth/set-password", async (c) => {
|
|
14468
14461
|
let body;
|
|
14469
14462
|
try {
|
|
14470
14463
|
body = await c.req.json();
|
|
@@ -14495,9 +14488,9 @@ app40.post("/api/remote-auth/set-password", async (c) => {
|
|
|
14495
14488
|
return c.json({ error: "Failed to save password" }, 500);
|
|
14496
14489
|
}
|
|
14497
14490
|
});
|
|
14498
|
-
|
|
14491
|
+
app39.route("/api/_client-error", client_error_default);
|
|
14499
14492
|
console.log("[client-error-route] mounted");
|
|
14500
|
-
|
|
14493
|
+
app39.use("*", async (c, next) => {
|
|
14501
14494
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14502
14495
|
const path2 = c.req.path;
|
|
14503
14496
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -14530,12 +14523,12 @@ app40.use("*", async (c, next) => {
|
|
|
14530
14523
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
14531
14524
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
14532
14525
|
});
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14526
|
+
app39.route("/api/health", health_default);
|
|
14527
|
+
app39.route("/api/chat", chat_default);
|
|
14528
|
+
app39.route("/api/whatsapp", whatsapp_default);
|
|
14529
|
+
app39.route("/api/onboarding", onboarding_default);
|
|
14530
|
+
app39.route("/api/admin", admin_default);
|
|
14531
|
+
app39.route("/api/access", access_default);
|
|
14539
14532
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
14540
14533
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
14541
14534
|
var IMAGE_MIME = {
|
|
@@ -14547,7 +14540,7 @@ var IMAGE_MIME = {
|
|
|
14547
14540
|
".svg": "image/svg+xml",
|
|
14548
14541
|
".ico": "image/x-icon"
|
|
14549
14542
|
};
|
|
14550
|
-
|
|
14543
|
+
app39.get("/agent-assets/:slug/:filename", (c) => {
|
|
14551
14544
|
const slug = c.req.param("slug");
|
|
14552
14545
|
const filename = c.req.param("filename");
|
|
14553
14546
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -14563,8 +14556,8 @@ app40.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
14563
14556
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
14564
14557
|
return c.text("Not found", 404);
|
|
14565
14558
|
}
|
|
14566
|
-
const filePath =
|
|
14567
|
-
const expectedDir =
|
|
14559
|
+
const filePath = resolve22(account.accountDir, "agents", slug, "assets", filename);
|
|
14560
|
+
const expectedDir = resolve22(account.accountDir, "agents", slug, "assets");
|
|
14568
14561
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
14569
14562
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
14570
14563
|
return c.text("Forbidden", 403);
|
|
@@ -14582,7 +14575,7 @@ app40.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
14582
14575
|
"Cache-Control": "public, max-age=3600"
|
|
14583
14576
|
});
|
|
14584
14577
|
});
|
|
14585
|
-
|
|
14578
|
+
app39.get("/generated/:filename", (c) => {
|
|
14586
14579
|
const filename = c.req.param("filename");
|
|
14587
14580
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
14588
14581
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -14593,8 +14586,8 @@ app40.get("/generated/:filename", (c) => {
|
|
|
14593
14586
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
14594
14587
|
return c.text("Not found", 404);
|
|
14595
14588
|
}
|
|
14596
|
-
const filePath =
|
|
14597
|
-
const expectedDir =
|
|
14589
|
+
const filePath = resolve22(account.accountDir, "generated", filename);
|
|
14590
|
+
const expectedDir = resolve22(account.accountDir, "generated");
|
|
14598
14591
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
14599
14592
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
14600
14593
|
return c.text("Forbidden", 403);
|
|
@@ -14612,10 +14605,10 @@ app40.get("/generated/:filename", (c) => {
|
|
|
14612
14605
|
"Cache-Control": "public, max-age=86400"
|
|
14613
14606
|
});
|
|
14614
14607
|
});
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
|
|
14608
|
+
app39.route("/sites", sites_default);
|
|
14609
|
+
app39.route("/listings", listings_default);
|
|
14610
|
+
app39.route("/v", visitor_event_default);
|
|
14611
|
+
app39.route("/v", visitor_consent_default);
|
|
14619
14612
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
14620
14613
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
14621
14614
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
@@ -14681,7 +14674,7 @@ var clientErrorReporterScript = `<script>
|
|
|
14681
14674
|
function cachedHtml(file) {
|
|
14682
14675
|
let html = htmlCache.get(file);
|
|
14683
14676
|
if (!html) {
|
|
14684
|
-
html = readFileSync21(
|
|
14677
|
+
html = readFileSync21(resolve22(process.cwd(), "public", file), "utf-8");
|
|
14685
14678
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
14686
14679
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
14687
14680
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -14752,7 +14745,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
14752
14745
|
function escapeHtml(s) {
|
|
14753
14746
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
14754
14747
|
}
|
|
14755
|
-
|
|
14748
|
+
app39.get("/", (c) => {
|
|
14756
14749
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14757
14750
|
if (isPublicHost(host)) {
|
|
14758
14751
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -14760,12 +14753,12 @@ app40.get("/", (c) => {
|
|
|
14760
14753
|
}
|
|
14761
14754
|
return c.html(cachedHtml("index.html"));
|
|
14762
14755
|
});
|
|
14763
|
-
|
|
14756
|
+
app39.get("/public", (c) => {
|
|
14764
14757
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14765
14758
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14766
14759
|
return c.html(cachedHtml("public.html"));
|
|
14767
14760
|
});
|
|
14768
|
-
|
|
14761
|
+
app39.get("/chat", (c) => {
|
|
14769
14762
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14770
14763
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14771
14764
|
return c.html(cachedHtml("public.html"));
|
|
@@ -14784,12 +14777,12 @@ async function logViewerFetch(c, next) {
|
|
|
14784
14777
|
duration_ms: Date.now() - start
|
|
14785
14778
|
});
|
|
14786
14779
|
}
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14780
|
+
app39.use("/vnc-viewer.html", logViewerFetch);
|
|
14781
|
+
app39.use("/vnc-popout.html", logViewerFetch);
|
|
14782
|
+
app39.get("/vnc-popout.html", (c) => {
|
|
14790
14783
|
let html = htmlCache.get("vnc-popout.html");
|
|
14791
14784
|
if (!html) {
|
|
14792
|
-
html = readFileSync21(
|
|
14785
|
+
html = readFileSync21(resolve22(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
14793
14786
|
const name = escapeHtml(BRAND.productName);
|
|
14794
14787
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
14795
14788
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -14799,7 +14792,7 @@ app40.get("/vnc-popout.html", (c) => {
|
|
|
14799
14792
|
}
|
|
14800
14793
|
return c.html(html);
|
|
14801
14794
|
});
|
|
14802
|
-
|
|
14795
|
+
app39.post("/api/vnc/client-event", async (c) => {
|
|
14803
14796
|
let body;
|
|
14804
14797
|
try {
|
|
14805
14798
|
body = await c.req.json();
|
|
@@ -14820,25 +14813,25 @@ app40.post("/api/vnc/client-event", async (c) => {
|
|
|
14820
14813
|
});
|
|
14821
14814
|
return c.json({ ok: true });
|
|
14822
14815
|
});
|
|
14823
|
-
|
|
14816
|
+
app39.get("/g/:slug", (c) => {
|
|
14824
14817
|
return c.html(brandedPublicHtml());
|
|
14825
14818
|
});
|
|
14826
|
-
|
|
14819
|
+
app39.get("/graph", (c) => {
|
|
14827
14820
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14828
14821
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14829
14822
|
return c.html(cachedHtml("graph.html"));
|
|
14830
14823
|
});
|
|
14831
|
-
|
|
14824
|
+
app39.get("/sessions", (c) => {
|
|
14832
14825
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14833
14826
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14834
14827
|
return c.html(cachedHtml("sessions.html"));
|
|
14835
14828
|
});
|
|
14836
|
-
|
|
14829
|
+
app39.get("/data", (c) => {
|
|
14837
14830
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14838
14831
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14839
14832
|
return c.html(cachedHtml("data.html"));
|
|
14840
14833
|
});
|
|
14841
|
-
|
|
14834
|
+
app39.get("/:slug", async (c, next) => {
|
|
14842
14835
|
const slug = c.req.param("slug");
|
|
14843
14836
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
14844
14837
|
const branding = loadBrandingCache(slug);
|
|
@@ -14848,15 +14841,15 @@ app40.get("/:slug", async (c, next) => {
|
|
|
14848
14841
|
await next();
|
|
14849
14842
|
});
|
|
14850
14843
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
14851
|
-
|
|
14844
|
+
app39.get("/favicon.ico", (c) => {
|
|
14852
14845
|
c.header("Cache-Control", "public, max-age=300");
|
|
14853
14846
|
return c.redirect(brandFaviconPath, 302);
|
|
14854
14847
|
});
|
|
14855
14848
|
}
|
|
14856
|
-
|
|
14849
|
+
app39.use("/*", serveStatic({ root: "./public" }));
|
|
14857
14850
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
14858
14851
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
14859
|
-
var httpServer = serve({ fetch:
|
|
14852
|
+
var httpServer = serve({ fetch: app39.fetch, port, hostname });
|
|
14860
14853
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
14861
14854
|
{
|
|
14862
14855
|
const loopHist = monitorEventLoopDelay({ resolution: 50 });
|
|
@@ -14892,7 +14885,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
14892
14885
|
}
|
|
14893
14886
|
try {
|
|
14894
14887
|
const registered = [];
|
|
14895
|
-
for (const r of
|
|
14888
|
+
for (const r of app39.routes ?? []) {
|
|
14896
14889
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
14897
14890
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
14898
14891
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -15010,7 +15003,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
15010
15003
|
}
|
|
15011
15004
|
init({
|
|
15012
15005
|
configDir: configDirForWhatsApp,
|
|
15013
|
-
platformRoot:
|
|
15006
|
+
platformRoot: resolve22(process.env.MAXY_PLATFORM_ROOT ?? join16(__dirname, "..")),
|
|
15014
15007
|
accountConfig: bootAccountConfig,
|
|
15015
15008
|
onMessage: async (msg) => {
|
|
15016
15009
|
if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {
|