@rubytech/create-realagent-code 0.1.192 → 0.1.193
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/plugins/docs/references/projects-guide.md +21 -0
- package/payload/platform/plugins/work/PLUGIN.md +2 -0
- package/payload/platform/plugins/work/skills/execute-task/SKILL.md +101 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +12 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/server/public/assets/AdminShell-BoJbnn6d.js +1 -0
- package/payload/server/public/assets/{Checkbox-DsHqjzGj.js → Checkbox-G-kyM1P1.js} +1 -1
- package/payload/server/public/assets/{admin-CWOprOdW.js → admin-B-GDNkoN.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DROzw8rH.js → architectureDiagram-Q4EWVU46-BGgdXdD2.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Dw9sieJu.js → blockDiagram-DXYQGD6D-DKWoL4Rp.js} +1 -1
- package/payload/server/public/assets/{brand-BQW2DYy_.css → brand-MbpD2Bhr.css} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-fnwntjFK.js → c4Diagram-AHTNJAMY-Ca6rs6F4.js} +1 -1
- package/payload/server/public/assets/channel-BwsV7WTV.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DVpyamlA.js → chunk-336JU56O-DcdMZImV.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-yiGugjCx.js → chunk-426QAEUC-9FSP-c1z.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BAPL_MqI.js → chunk-4TB4RGXK-CC1QpEvA.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-Ba-5D35r.js → chunk-5FUZZQ4R-o1b70dEE.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-BtDS8-t9.js → chunk-5PVQY5BW-C7VCYRz9.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CqcdpDg_.js → chunk-EDXVE4YY-B8d5xj_4.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CaBy9U1e.js → chunk-ENJZ2VHE-SSbr4n2X.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BdPjOce4.js → chunk-ICPOFSXX-Cgj9YSpX.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-CK6wx_FD.js → chunk-OYMX7WX6-DNEEcCqI.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-DyZFy43o.js → chunk-U2HBQHQK-DuaoK83q.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CMTofLbX.js → chunk-X2U36JSP-CzMp0dpq.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-YfFrkYbQ.js → chunk-YZCP3GAM-B2wBDwSa.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BVfvS5n3.js → chunk-ZZ45TVLE-DkyF7XKW.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CEWNfHVo.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BBjzRxux.js +1 -0
- package/payload/server/public/assets/clone-CXtSonnn.js +1 -0
- package/payload/server/public/assets/{dagre-ComHkUs6.js → dagre-AGj1P0p4.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BB-QqzpF.js → dagre-KV5264BT-Cnrxcu6A.js} +1 -1
- package/payload/server/public/assets/data-Bg0Frxt3.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-CpQQszhw.js → diagram-5BDNPKRD-gyFYSx73.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DLdElVzs.js → diagram-G4DWMVQ6-DFmZEv5C.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-JQ3ceLSO.js → diagram-MMDJMWI5-DA4qbuEW.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-D_-AtVPR.js → diagram-TYMM5635-D4n-8gig.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-Dq50MKD-.js → erDiagram-SMLLAGMA-CigRMjF1.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CEdKm-zL.js → flowDiagram-DWJPFMVM-ClS27acA.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CpTomdNN.js → ganttDiagram-T4ZO3ILL-Dr1IulXe.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-VU-gjbee.js → gitGraphDiagram-UUTBAWPF-lwLibdPs.js} +1 -1
- package/payload/server/public/assets/{graph-BXaY_xoS.js → graph-CpozZ74I.js} +2 -2
- package/payload/server/public/assets/{graph-labels-EqZyoU25.js → graph-labels-C2y666R0.js} +1 -1
- package/payload/server/public/assets/{graphlib-nLzyerxi.js → graphlib-DBvoJMrc.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-ThwX5Xgr.js → infoDiagram-42DDH7IO-D4kReEIV.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DaKxxHLW.js → ishikawaDiagram-UXIWVN3A-BnteQRQ0.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DtMAHpWz.js → journeyDiagram-VCZTEJTY-CXu6hLyJ.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-s898dJRu.js → kanban-definition-6JOO6SKY-CGDW2jle.js} +1 -1
- package/payload/server/public/assets/{line-D96q2CLD.js → line-pdg5hxC3.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CqFLtzz8.js → mermaid-parser.core-o3lIIK3Z.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-o9rmBTu-.js → mermaid.core-DLR6Q3rV.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BM8KKsaM.js → mindmap-definition-QFDTVHPH-CH4cB0Dn.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-B66Y-dcU.js → pieDiagram-DEJITSTG-Ba4voL_Y.js} +1 -1
- package/payload/server/public/assets/{public-ClAaV52O.js → public-C8mil9h0.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Bv4mojq8.js → quadrantDiagram-34T5L4WZ-Cqn2xehe.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-BNYdfEKS.js → requirementDiagram-MS252O5E-DLfNx99l.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Do8BgX92.js → sankeyDiagram-XADWPNL6-uck_V-cb.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-VN57FKth.js → sequenceDiagram-FGHM5R23-DmQalqud.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CCtRfCg0.js → stateDiagram-FHFEXIEX-DUdWeVRa.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DNTpFwdy.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-ja01S9Wd.js → timeline-definition-GMOUNBTQ-BgL1wM5n.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-ejMSaa52.js → useSelectionMode-BLpVlOgm.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-wWbiL1f6.js → vennDiagram-DHZGUBPP-7FHjIqPi.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BZgue-PK.js → wardleyDiagram-NUSXRM2D-BHzo4V1J.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-B_ynYRnW.js → xychartDiagram-5P7HB3ND-DtuWhqwh.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 +283 -268
- package/payload/server/public/assets/AdminShell-CdgotOLV.js +0 -1
- package/payload/server/public/assets/channel-DEl-UCEn.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BZ9e1dmR.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B1_4kXdN.js +0 -1
- package/payload/server/public/assets/clone-CNXfxCnl.js +0 -1
- package/payload/server/public/assets/data-DEsRsfI1.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Cz319KBI.js +0 -1
- /package/payload/server/public/assets/{brand-DKUA91KU.js → brand-CYcGHhlS.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -815,8 +815,8 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
815
815
|
};
|
|
816
816
|
|
|
817
817
|
// server/index.ts
|
|
818
|
-
import { readFileSync as
|
|
819
|
-
import { resolve as resolve23, join as
|
|
818
|
+
import { readFileSync as readFileSync21, existsSync as existsSync21, watchFile } from "fs";
|
|
819
|
+
import { resolve as resolve23, join as join16, basename as basename6 } from "path";
|
|
820
820
|
import { homedir as homedir2 } from "os";
|
|
821
821
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
822
822
|
|
|
@@ -7245,24 +7245,6 @@ function openResumeStreamLog(accountId, sessionId) {
|
|
|
7245
7245
|
}
|
|
7246
7246
|
return createWriteStream(resolvePath(dir, `${sessionId}.log`), { flags: "a" });
|
|
7247
7247
|
}
|
|
7248
|
-
var healPending = /* @__PURE__ */ new Map();
|
|
7249
|
-
function markHealPending(accountId, attachmentId) {
|
|
7250
|
-
let set = healPending.get(accountId);
|
|
7251
|
-
if (!set) {
|
|
7252
|
-
set = /* @__PURE__ */ new Set();
|
|
7253
|
-
healPending.set(accountId, set);
|
|
7254
|
-
}
|
|
7255
|
-
set.add(attachmentId);
|
|
7256
|
-
}
|
|
7257
|
-
function clearHealPending(accountId, attachmentId) {
|
|
7258
|
-
const set = healPending.get(accountId);
|
|
7259
|
-
if (!set) return;
|
|
7260
|
-
set.delete(attachmentId);
|
|
7261
|
-
if (set.size === 0) healPending.delete(accountId);
|
|
7262
|
-
}
|
|
7263
|
-
function isHealPending(accountId, attachmentId) {
|
|
7264
|
-
return healPending.get(accountId)?.has(attachmentId) ?? false;
|
|
7265
|
-
}
|
|
7266
7248
|
function validateAndShapeAttachments(raws, conversationAccountId, sessionId, messageId, streamLogPath) {
|
|
7267
7249
|
const chips = [];
|
|
7268
7250
|
let valid = 0;
|
|
@@ -7640,17 +7622,14 @@ app11.post("/:id/resume", async (c) => {
|
|
|
7640
7622
|
textOffset: c2.textOffset
|
|
7641
7623
|
};
|
|
7642
7624
|
if (!c2.artefactAttachmentId || !c2.artefactMimeType || !c2.artefactTitle) return base;
|
|
7643
|
-
markHealPending(accountId, c2.artefactAttachmentId);
|
|
7644
7625
|
try {
|
|
7645
7626
|
const dataObj = JSON.parse(c2.data);
|
|
7646
7627
|
const bytesPick = pickComponentBytes(dataObj);
|
|
7647
7628
|
if (!bytesPick) {
|
|
7648
|
-
clearHealPending(accountId, c2.artefactAttachmentId);
|
|
7649
7629
|
return base;
|
|
7650
7630
|
}
|
|
7651
7631
|
const filename = bytesPick.mimeType === "text/html" ? `${c2.artefactTitle}.html` : `${c2.artefactTitle}.md`;
|
|
7652
7632
|
await storeComponentArtefact(accountId, c2.artefactAttachmentId, bytesPick.mimeType, bytesPick.content, filename);
|
|
7653
|
-
clearHealPending(accountId, c2.artefactAttachmentId);
|
|
7654
7633
|
streamLogPath.write(
|
|
7655
7634
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] [component-persist] heal componentName=${c2.name} attachmentId=${c2.artefactAttachmentId.slice(0, 8)} mimeType=${bytesPick.mimeType} bytes=${bytesPick.content.length} outcome=ok
|
|
7656
7635
|
`
|
|
@@ -7662,7 +7641,6 @@ app11.post("/:id/resume", async (c) => {
|
|
|
7662
7641
|
artefactTitle: c2.artefactTitle
|
|
7663
7642
|
};
|
|
7664
7643
|
} catch (writeErr) {
|
|
7665
|
-
clearHealPending(accountId, c2.artefactAttachmentId);
|
|
7666
7644
|
const reason2 = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
7667
7645
|
streamLogPath.write(
|
|
7668
7646
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] [component-persist] heal componentName=${c2.name} attachmentId=${c2.artefactAttachmentId.slice(0, 8)} outcome=disk-fail reason=${JSON.stringify(reason2.slice(0, 200))}
|
|
@@ -11733,11 +11711,9 @@ function isWithin(target, root) {
|
|
|
11733
11711
|
var sidebar_artefacts_default = app22;
|
|
11734
11712
|
|
|
11735
11713
|
// server/routes/admin/sidebar-artefact-save.ts
|
|
11736
|
-
import { mkdir as mkdir4,
|
|
11714
|
+
import { mkdir as mkdir4, stat as stat6, writeFile as writeFile5 } from "fs/promises";
|
|
11737
11715
|
import { resolve as resolve16 } from "path";
|
|
11738
|
-
import { existsSync as existsSync17 } from "fs";
|
|
11739
11716
|
var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
|
|
11740
|
-
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
11741
11717
|
var app23 = new Hono();
|
|
11742
11718
|
app23.post("/", requireAdminSession, async (c) => {
|
|
11743
11719
|
const cacheKey = c.var.cacheKey;
|
|
@@ -11748,11 +11724,7 @@ app23.post("/", requireAdminSession, async (c) => {
|
|
|
11748
11724
|
return c.json({ error: "id and content required" }, 400);
|
|
11749
11725
|
}
|
|
11750
11726
|
const accountDir = resolve16(ACCOUNTS_DIR, accountId);
|
|
11751
|
-
const resolved = await resolveSavePath(body.id,
|
|
11752
|
-
if (resolved.kind === "heal-race") {
|
|
11753
|
-
c.header("Retry-After", "2");
|
|
11754
|
-
return c.json({ error: "heal-race", reason: resolved.reason }, 503);
|
|
11755
|
-
}
|
|
11727
|
+
const resolved = await resolveSavePath(body.id, accountDir);
|
|
11756
11728
|
if (resolved.kind === "reject") {
|
|
11757
11729
|
console.error(
|
|
11758
11730
|
`[admin/sidebar-artefact-save] auth-rejected reason=${resolved.reason} path=${body.id}`
|
|
@@ -11781,77 +11753,119 @@ app23.post("/", requireAdminSession, async (c) => {
|
|
|
11781
11753
|
);
|
|
11782
11754
|
return c.json({ updatedAt });
|
|
11783
11755
|
});
|
|
11784
|
-
async function resolveSavePath(id,
|
|
11785
|
-
if (id.startsWith("agent-template:")) {
|
|
11786
|
-
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
|
|
11796
|
-
|
|
11756
|
+
async function resolveSavePath(id, accountDir) {
|
|
11757
|
+
if (!id.startsWith("agent-template:")) {
|
|
11758
|
+
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11759
|
+
}
|
|
11760
|
+
const parts = id.split(":");
|
|
11761
|
+
if (parts.length !== 3) return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11762
|
+
const [, role, filename] = parts;
|
|
11763
|
+
if (role === "specialist") {
|
|
11764
|
+
return { kind: "reject", status: 403, reason: "specialist-write-blocked" };
|
|
11765
|
+
}
|
|
11766
|
+
if (role !== "admin" || !ADMIN_AGENT_FILES2.has(filename)) {
|
|
11767
|
+
return { kind: "reject", status: 400, reason: "invalid-id" };
|
|
11768
|
+
}
|
|
11769
|
+
const parent = resolve16(accountDir, "agents", "admin");
|
|
11770
|
+
await mkdir4(parent, { recursive: true });
|
|
11771
|
+
try {
|
|
11772
|
+
validateFilePathInAccount(parent, accountDir);
|
|
11773
|
+
} catch {
|
|
11774
|
+
return { kind: "reject", status: 400, reason: "containment-rejected" };
|
|
11775
|
+
}
|
|
11776
|
+
return { kind: "admin-template", path: resolve16(parent, filename) };
|
|
11777
|
+
}
|
|
11778
|
+
function relPath(absPath, root) {
|
|
11779
|
+
return absPath.startsWith(root) ? absPath.slice(root.length + 1) : absPath;
|
|
11780
|
+
}
|
|
11781
|
+
var sidebar_artefact_save_default = app23;
|
|
11782
|
+
|
|
11783
|
+
// server/routes/admin/sidebar-sessions.ts
|
|
11784
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
11785
|
+
import { join as join13 } from "path";
|
|
11786
|
+
var RC_URL_RE = /https:\/\/claude\.ai\/code\/session_[A-Za-z0-9_-]+/;
|
|
11787
|
+
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;
|
|
11788
|
+
var TITLE_MAX = 80;
|
|
11789
|
+
var app24 = new Hono();
|
|
11790
|
+
function projectsDirForAccount(accountId) {
|
|
11791
|
+
const configDir2 = process.env.CLAUDE_CONFIG_DIR;
|
|
11792
|
+
if (!configDir2) return null;
|
|
11793
|
+
const accountCwd = join13(DATA_ROOT, "accounts", accountId);
|
|
11794
|
+
const slug = accountCwd.replace(/\//g, "-");
|
|
11795
|
+
return join13(configDir2, "projects", slug);
|
|
11796
|
+
}
|
|
11797
|
+
function firstUserMessage(body) {
|
|
11798
|
+
for (const line of body.split("\n")) {
|
|
11799
|
+
if (!line || line[0] !== "{") continue;
|
|
11800
|
+
let parsed;
|
|
11797
11801
|
try {
|
|
11798
|
-
|
|
11802
|
+
parsed = JSON.parse(line);
|
|
11799
11803
|
} catch {
|
|
11800
|
-
|
|
11804
|
+
continue;
|
|
11801
11805
|
}
|
|
11802
|
-
|
|
11806
|
+
if (!parsed || typeof parsed !== "object") continue;
|
|
11807
|
+
const row = parsed;
|
|
11808
|
+
if (row.type !== "user" || !row.message || row.message.role !== "user") continue;
|
|
11809
|
+
const content = row.message.content;
|
|
11810
|
+
if (typeof content !== "string") continue;
|
|
11811
|
+
const trimmed = content.trim().replace(/\s+/g, " ");
|
|
11812
|
+
if (!trimmed) continue;
|
|
11813
|
+
return trimmed.length > TITLE_MAX ? trimmed.slice(0, TITLE_MAX - 1) + "\u2026" : trimmed;
|
|
11803
11814
|
}
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
return { kind: "reject", status: 400, reason: "not-found" };
|
|
11826
|
-
} catch (neoErr) {
|
|
11827
|
-
const reason = neoErr instanceof Error ? neoErr.message.slice(0, 120) : String(neoErr).slice(0, 120);
|
|
11828
|
-
console.error(`[admin/sidebar-artefact-save] heal-race attachmentId=${attShort} outcome=neo4j-fail reason="${reason}"`);
|
|
11829
|
-
return { kind: "heal-race", reason: "neo4j-fail" };
|
|
11830
|
-
} finally {
|
|
11831
|
-
try {
|
|
11832
|
-
await session.close();
|
|
11833
|
-
} catch {
|
|
11834
|
-
}
|
|
11835
|
-
}
|
|
11815
|
+
return null;
|
|
11816
|
+
}
|
|
11817
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
11818
|
+
const cacheKey = c.var.cacheKey;
|
|
11819
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11820
|
+
if (!accountId) {
|
|
11821
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
11822
|
+
}
|
|
11823
|
+
const projectsDir = projectsDirForAccount(accountId);
|
|
11824
|
+
if (!projectsDir) {
|
|
11825
|
+
console.error(`[admin-sessions-list] account=${accountId} no-claude-config-dir`);
|
|
11826
|
+
return c.json({ sessions: [] });
|
|
11827
|
+
}
|
|
11828
|
+
let entries;
|
|
11829
|
+
try {
|
|
11830
|
+
entries = readdirSync8(projectsDir);
|
|
11831
|
+
} catch (err) {
|
|
11832
|
+
const code = err.code;
|
|
11833
|
+
if (code === "ENOENT") {
|
|
11834
|
+
console.log(`[admin-sessions-list] account=${accountId} rows=0 reason=no-projects-dir`);
|
|
11835
|
+
return c.json({ sessions: [] });
|
|
11836
11836
|
}
|
|
11837
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11838
|
+
console.error(`[admin-sessions-list] account=${accountId} readdir-failed error="${message}"`);
|
|
11839
|
+
return c.json({ error: "projects-dir-unreadable" }, 500);
|
|
11840
|
+
}
|
|
11841
|
+
const rows = [];
|
|
11842
|
+
for (const name of entries) {
|
|
11843
|
+
if (!SESSION_ID_RE.test(name)) continue;
|
|
11844
|
+
const sessionId = name.slice(0, -".jsonl".length);
|
|
11845
|
+
const path2 = join13(projectsDir, name);
|
|
11846
|
+
let body;
|
|
11847
|
+
let mtimeMs;
|
|
11837
11848
|
try {
|
|
11838
|
-
|
|
11849
|
+
body = readFileSync14(path2, "utf8");
|
|
11850
|
+
mtimeMs = statSync7(path2).mtimeMs;
|
|
11839
11851
|
} catch {
|
|
11840
|
-
|
|
11841
|
-
}
|
|
11842
|
-
const entries = await readdir5(dir);
|
|
11843
|
-
const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
|
|
11844
|
-
if (!dataFile) {
|
|
11845
|
-
return { kind: "reject", status: 400, reason: "not-found" };
|
|
11852
|
+
continue;
|
|
11846
11853
|
}
|
|
11847
|
-
|
|
11854
|
+
const urlMatch = body.match(RC_URL_RE);
|
|
11855
|
+
if (!urlMatch) continue;
|
|
11856
|
+
const title = firstUserMessage(body) ?? sessionId.slice(0, 8);
|
|
11857
|
+
rows.push({
|
|
11858
|
+
sessionId,
|
|
11859
|
+
title,
|
|
11860
|
+
url: urlMatch[0],
|
|
11861
|
+
capturedAt: new Date(mtimeMs).toISOString()
|
|
11862
|
+
});
|
|
11848
11863
|
}
|
|
11849
|
-
|
|
11850
|
-
}
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
|
|
11854
|
-
var sidebar_artefact_save_default = app23;
|
|
11864
|
+
rows.sort((a, b) => a.capturedAt < b.capturedAt ? 1 : -1);
|
|
11865
|
+
console.log(`[admin-sessions-list] account=${accountId} rows=${rows.length}`);
|
|
11866
|
+
return c.json({ sessions: rows });
|
|
11867
|
+
});
|
|
11868
|
+
var sidebar_sessions_default = app24;
|
|
11855
11869
|
|
|
11856
11870
|
// server/routes/admin/system-stats.ts
|
|
11857
11871
|
import { readFile as readFile5 } from "fs/promises";
|
|
@@ -11948,8 +11962,8 @@ async function sample() {
|
|
|
11948
11962
|
if (process.platform === "linux") return sampleLinux();
|
|
11949
11963
|
return sampleOsFallback();
|
|
11950
11964
|
}
|
|
11951
|
-
var
|
|
11952
|
-
|
|
11965
|
+
var app25 = new Hono();
|
|
11966
|
+
app25.get("/", async (c) => {
|
|
11953
11967
|
const started = Date.now();
|
|
11954
11968
|
if (!inflight) {
|
|
11955
11969
|
inflight = sample().finally(() => {
|
|
@@ -11972,17 +11986,17 @@ app24.get("/", async (c) => {
|
|
|
11972
11986
|
return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
|
|
11973
11987
|
}
|
|
11974
11988
|
});
|
|
11975
|
-
var system_stats_default =
|
|
11989
|
+
var system_stats_default = app25;
|
|
11976
11990
|
|
|
11977
11991
|
// server/routes/admin/health.ts
|
|
11978
|
-
import { existsSync as
|
|
11979
|
-
import { resolve as resolve17, join as
|
|
11992
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
|
|
11993
|
+
import { resolve as resolve17, join as join14 } from "path";
|
|
11980
11994
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
11981
11995
|
var brandHostname = "maxy";
|
|
11982
|
-
var brandJsonPath =
|
|
11983
|
-
if (
|
|
11996
|
+
var brandJsonPath = join14(PLATFORM_ROOT6, "config", "brand.json");
|
|
11997
|
+
if (existsSync17(brandJsonPath)) {
|
|
11984
11998
|
try {
|
|
11985
|
-
const brand = JSON.parse(
|
|
11999
|
+
const brand = JSON.parse(readFileSync15(brandJsonPath, "utf-8"));
|
|
11986
12000
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
11987
12001
|
} catch {
|
|
11988
12002
|
}
|
|
@@ -11991,8 +12005,8 @@ var VERSION_FILE = resolve17(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
11991
12005
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
11992
12006
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
11993
12007
|
function readVersion() {
|
|
11994
|
-
if (!
|
|
11995
|
-
return
|
|
12008
|
+
if (!existsSync17(VERSION_FILE)) return "unknown";
|
|
12009
|
+
return readFileSync15(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
11996
12010
|
}
|
|
11997
12011
|
async function probeConversationDb() {
|
|
11998
12012
|
let session;
|
|
@@ -12017,8 +12031,8 @@ async function probeConversationDb() {
|
|
|
12017
12031
|
});
|
|
12018
12032
|
}
|
|
12019
12033
|
}
|
|
12020
|
-
var
|
|
12021
|
-
|
|
12034
|
+
var app26 = new Hono();
|
|
12035
|
+
app26.get("/", async (c) => {
|
|
12022
12036
|
const version = readVersion();
|
|
12023
12037
|
const probe = await probeConversationDb();
|
|
12024
12038
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -12040,7 +12054,7 @@ app25.get("/", async (c) => {
|
|
|
12040
12054
|
uptimeMs
|
|
12041
12055
|
});
|
|
12042
12056
|
});
|
|
12043
|
-
var health_default2 =
|
|
12057
|
+
var health_default2 = app26;
|
|
12044
12058
|
|
|
12045
12059
|
// server/routes/admin/linkedin-ingest.ts
|
|
12046
12060
|
var TAG20 = "[linkedin-ingest-route]";
|
|
@@ -12136,8 +12150,8 @@ function buildInitialMessage(env) {
|
|
|
12136
12150
|
}
|
|
12137
12151
|
return header;
|
|
12138
12152
|
}
|
|
12139
|
-
var
|
|
12140
|
-
|
|
12153
|
+
var app27 = new Hono();
|
|
12154
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
12141
12155
|
let body;
|
|
12142
12156
|
try {
|
|
12143
12157
|
body = await c.req.json();
|
|
@@ -12191,7 +12205,7 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
12191
12205
|
);
|
|
12192
12206
|
return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: claudeSessionId }, 202);
|
|
12193
12207
|
});
|
|
12194
|
-
var linkedin_ingest_default =
|
|
12208
|
+
var linkedin_ingest_default = app27;
|
|
12195
12209
|
|
|
12196
12210
|
// server/routes/admin/post-turn-context.ts
|
|
12197
12211
|
import neo4j2 from "neo4j-driver";
|
|
@@ -12233,8 +12247,8 @@ function pruneProperties(raw) {
|
|
|
12233
12247
|
}
|
|
12234
12248
|
return out;
|
|
12235
12249
|
}
|
|
12236
|
-
var
|
|
12237
|
-
|
|
12250
|
+
var app28 = new Hono();
|
|
12251
|
+
app28.get("/", async (c) => {
|
|
12238
12252
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12239
12253
|
if (!isLoopbackAddr2(remoteAddr)) {
|
|
12240
12254
|
console.error(`${TAG21} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12294,7 +12308,7 @@ app27.get("/", async (c) => {
|
|
|
12294
12308
|
await session.close();
|
|
12295
12309
|
}
|
|
12296
12310
|
});
|
|
12297
|
-
var post_turn_context_default =
|
|
12311
|
+
var post_turn_context_default = app28;
|
|
12298
12312
|
|
|
12299
12313
|
// server/routes/admin/public-session-context.ts
|
|
12300
12314
|
import neo4j3 from "neo4j-driver";
|
|
@@ -12336,8 +12350,8 @@ function pruneProperties2(raw) {
|
|
|
12336
12350
|
}
|
|
12337
12351
|
return out;
|
|
12338
12352
|
}
|
|
12339
|
-
var
|
|
12340
|
-
|
|
12353
|
+
var app29 = new Hono();
|
|
12354
|
+
app29.get("/", async (c) => {
|
|
12341
12355
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12342
12356
|
if (!isLoopbackAddr3(remoteAddr)) {
|
|
12343
12357
|
console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12396,15 +12410,15 @@ app28.get("/", async (c) => {
|
|
|
12396
12410
|
await session.close();
|
|
12397
12411
|
}
|
|
12398
12412
|
});
|
|
12399
|
-
var public_session_context_default =
|
|
12413
|
+
var public_session_context_default = app29;
|
|
12400
12414
|
|
|
12401
12415
|
// server/routes/admin/public-session-exit.ts
|
|
12402
12416
|
var TAG23 = "[public-session-exit-route]";
|
|
12403
12417
|
function isLoopbackAddr4(addr) {
|
|
12404
12418
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
12405
12419
|
}
|
|
12406
|
-
var
|
|
12407
|
-
|
|
12420
|
+
var app30 = new Hono();
|
|
12421
|
+
app30.post("/", async (c) => {
|
|
12408
12422
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12409
12423
|
if (!isLoopbackAddr4(remoteAddr)) {
|
|
12410
12424
|
console.error(`${TAG23} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12431,15 +12445,15 @@ app29.post("/", async (c) => {
|
|
|
12431
12445
|
handlePublicSessionExit(sessionId);
|
|
12432
12446
|
return c.json({ ok: true });
|
|
12433
12447
|
});
|
|
12434
|
-
var public_session_exit_default =
|
|
12448
|
+
var public_session_exit_default = app30;
|
|
12435
12449
|
|
|
12436
12450
|
// server/routes/admin/access-session-evict.ts
|
|
12437
12451
|
var TAG24 = "[access-session-evict]";
|
|
12438
12452
|
function isLoopbackAddr5(addr) {
|
|
12439
12453
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
12440
12454
|
}
|
|
12441
|
-
var
|
|
12442
|
-
|
|
12455
|
+
var app31 = new Hono();
|
|
12456
|
+
app31.post("/", async (c) => {
|
|
12443
12457
|
const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
|
|
12444
12458
|
if (!isLoopbackAddr5(remoteAddr)) {
|
|
12445
12459
|
console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
|
|
@@ -12467,40 +12481,41 @@ app30.post("/", async (c) => {
|
|
|
12467
12481
|
console.log(`${TAG24} grantId=${grantId} dropped=${dropped}`);
|
|
12468
12482
|
return c.json({ ok: true, dropped });
|
|
12469
12483
|
});
|
|
12470
|
-
var access_session_evict_default =
|
|
12484
|
+
var access_session_evict_default = app31;
|
|
12471
12485
|
|
|
12472
12486
|
// server/routes/admin/index.ts
|
|
12473
|
-
var
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12487
|
+
var app32 = new Hono();
|
|
12488
|
+
app32.route("/session", session_default);
|
|
12489
|
+
app32.route("/logs", logs_default);
|
|
12490
|
+
app32.route("/claude-info", claude_info_default);
|
|
12491
|
+
app32.route("/attachment", attachment_default);
|
|
12492
|
+
app32.route("/agents", agents_default);
|
|
12493
|
+
app32.route("/sessions", sessions_default);
|
|
12494
|
+
app32.route("/claude-sessions", claude_sessions_default);
|
|
12495
|
+
app32.route("/log-ingest", log_ingest_default);
|
|
12496
|
+
app32.route("/events", events_default);
|
|
12497
|
+
app32.route("/files", files_default);
|
|
12498
|
+
app32.route("/graph-search", graph_search_default);
|
|
12499
|
+
app32.route("/graph-subgraph", graph_subgraph_default);
|
|
12500
|
+
app32.route("/graph-delete", graph_delete_default);
|
|
12501
|
+
app32.route("/graph-restore", graph_restore_default);
|
|
12502
|
+
app32.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
12503
|
+
app32.route("/graph-default-view", graph_default_view_default);
|
|
12504
|
+
app32.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
12505
|
+
app32.route("/sidebar-artefact-save", sidebar_artefact_save_default);
|
|
12506
|
+
app32.route("/sidebar-sessions", sidebar_sessions_default);
|
|
12507
|
+
app32.route("/system-stats", system_stats_default);
|
|
12508
|
+
app32.route("/health-brand", health_default2);
|
|
12509
|
+
app32.route("/linkedin-ingest", linkedin_ingest_default);
|
|
12510
|
+
app32.route("/post-turn-context", post_turn_context_default);
|
|
12511
|
+
app32.route("/public-session-context", public_session_context_default);
|
|
12512
|
+
app32.route("/public-session-exit", public_session_exit_default);
|
|
12513
|
+
app32.route("/access-session-evict", access_session_evict_default);
|
|
12514
|
+
var admin_default = app32;
|
|
12500
12515
|
|
|
12501
12516
|
// app/lib/access-gate.ts
|
|
12502
12517
|
import neo4j4 from "neo4j-driver";
|
|
12503
|
-
import { readFileSync as
|
|
12518
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
12504
12519
|
import { resolve as resolve18 } from "path";
|
|
12505
12520
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
12506
12521
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "..");
|
|
@@ -12509,7 +12524,7 @@ function readPassword() {
|
|
|
12509
12524
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
12510
12525
|
const passwordFile = resolve18(PLATFORM_ROOT7, "config/.neo4j-password");
|
|
12511
12526
|
try {
|
|
12512
|
-
return
|
|
12527
|
+
return readFileSync16(passwordFile, "utf-8").trim();
|
|
12513
12528
|
} catch {
|
|
12514
12529
|
throw new Error(
|
|
12515
12530
|
`Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
|
|
@@ -12710,8 +12725,8 @@ async function generateNewMagicToken(grantId) {
|
|
|
12710
12725
|
var TAG25 = "[access-verify]";
|
|
12711
12726
|
var MINT_TAG = "[access-session-mint]";
|
|
12712
12727
|
var COOKIE_NAME = "__access_session";
|
|
12713
|
-
var
|
|
12714
|
-
|
|
12728
|
+
var app33 = new Hono();
|
|
12729
|
+
app33.post("/", async (c) => {
|
|
12715
12730
|
const ip = c.var.clientIp || "unknown";
|
|
12716
12731
|
let body;
|
|
12717
12732
|
try {
|
|
@@ -12793,7 +12808,7 @@ app32.post("/", async (c) => {
|
|
|
12793
12808
|
displayName: grant.displayName
|
|
12794
12809
|
});
|
|
12795
12810
|
});
|
|
12796
|
-
var verify_token_default =
|
|
12811
|
+
var verify_token_default = app33;
|
|
12797
12812
|
|
|
12798
12813
|
// app/lib/access-email.ts
|
|
12799
12814
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -12856,9 +12871,9 @@ async function sendMagicLinkEmail(payload) {
|
|
|
12856
12871
|
|
|
12857
12872
|
// server/routes/access/request-magic-link.ts
|
|
12858
12873
|
var TAG26 = "[access-request-link]";
|
|
12859
|
-
var
|
|
12874
|
+
var app34 = new Hono();
|
|
12860
12875
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
12861
|
-
|
|
12876
|
+
app34.post("/", async (c) => {
|
|
12862
12877
|
let body;
|
|
12863
12878
|
try {
|
|
12864
12879
|
body = await c.req.json();
|
|
@@ -12932,16 +12947,16 @@ app33.post("/", async (c) => {
|
|
|
12932
12947
|
);
|
|
12933
12948
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
12934
12949
|
});
|
|
12935
|
-
var request_magic_link_default =
|
|
12950
|
+
var request_magic_link_default = app34;
|
|
12936
12951
|
|
|
12937
12952
|
// server/routes/access/index.ts
|
|
12938
|
-
var
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
var access_default =
|
|
12953
|
+
var app35 = new Hono();
|
|
12954
|
+
app35.route("/verify-token", verify_token_default);
|
|
12955
|
+
app35.route("/request-magic-link", request_magic_link_default);
|
|
12956
|
+
var access_default = app35;
|
|
12942
12957
|
|
|
12943
12958
|
// server/routes/sites.ts
|
|
12944
|
-
import { existsSync as
|
|
12959
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
|
|
12945
12960
|
import { resolve as resolve20 } from "path";
|
|
12946
12961
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
12947
12962
|
var MIME = {
|
|
@@ -12973,8 +12988,8 @@ function getExt(p) {
|
|
|
12973
12988
|
if (idx < p.lastIndexOf("/")) return "";
|
|
12974
12989
|
return p.slice(idx).toLowerCase();
|
|
12975
12990
|
}
|
|
12976
|
-
var
|
|
12977
|
-
|
|
12991
|
+
var app36 = new Hono();
|
|
12992
|
+
app36.get("/:rel{.*}", (c) => {
|
|
12978
12993
|
const reqPath = c.req.path;
|
|
12979
12994
|
const rawRel = c.req.param("rel") ?? "";
|
|
12980
12995
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -13007,7 +13022,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
13007
13022
|
}
|
|
13008
13023
|
let stat8;
|
|
13009
13024
|
try {
|
|
13010
|
-
stat8 =
|
|
13025
|
+
stat8 = existsSync18(filePath) ? statSync8(filePath) : null;
|
|
13011
13026
|
} catch {
|
|
13012
13027
|
stat8 = null;
|
|
13013
13028
|
}
|
|
@@ -13026,7 +13041,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
13026
13041
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
13027
13042
|
return c.text("Forbidden", 403);
|
|
13028
13043
|
}
|
|
13029
|
-
if (!
|
|
13044
|
+
if (!existsSync18(filePath)) {
|
|
13030
13045
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
13031
13046
|
return c.text("Not found", 404);
|
|
13032
13047
|
}
|
|
@@ -13045,7 +13060,7 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
13045
13060
|
}
|
|
13046
13061
|
let body;
|
|
13047
13062
|
try {
|
|
13048
|
-
body =
|
|
13063
|
+
body = readFileSync17(realPath);
|
|
13049
13064
|
} catch (err) {
|
|
13050
13065
|
const code = err?.code;
|
|
13051
13066
|
if (code === "EISDIR") {
|
|
@@ -13077,11 +13092,11 @@ app35.get("/:rel{.*}", (c) => {
|
|
|
13077
13092
|
"X-Content-Type-Options": "nosniff"
|
|
13078
13093
|
});
|
|
13079
13094
|
});
|
|
13080
|
-
var sites_default =
|
|
13095
|
+
var sites_default = app36;
|
|
13081
13096
|
|
|
13082
13097
|
// app/lib/visitor-token.ts
|
|
13083
13098
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
13084
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
13099
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "fs";
|
|
13085
13100
|
import { dirname as dirname4 } from "path";
|
|
13086
13101
|
var TOKEN_PREFIX = "v1.";
|
|
13087
13102
|
var SECRET_BYTES = 32;
|
|
@@ -13090,7 +13105,7 @@ var cachedSecret = null;
|
|
|
13090
13105
|
function getSecret() {
|
|
13091
13106
|
if (cachedSecret) return cachedSecret;
|
|
13092
13107
|
try {
|
|
13093
|
-
const hex2 =
|
|
13108
|
+
const hex2 = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
13094
13109
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
13095
13110
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
13096
13111
|
return cachedSecret;
|
|
@@ -13104,7 +13119,7 @@ function getSecret() {
|
|
|
13104
13119
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
13105
13120
|
} catch {
|
|
13106
13121
|
}
|
|
13107
|
-
const hex =
|
|
13122
|
+
const hex = readFileSync18(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
13108
13123
|
cachedSecret = Buffer.from(hex, "hex");
|
|
13109
13124
|
return cachedSecret;
|
|
13110
13125
|
}
|
|
@@ -13157,8 +13172,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
13157
13172
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
13158
13173
|
|
|
13159
13174
|
// app/lib/brand-config.ts
|
|
13160
|
-
import { existsSync as
|
|
13161
|
-
import { join as
|
|
13175
|
+
import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
|
|
13176
|
+
import { join as join15 } from "path";
|
|
13162
13177
|
var cached2 = null;
|
|
13163
13178
|
var cachedAttempted = false;
|
|
13164
13179
|
function readBrandConfig() {
|
|
@@ -13166,10 +13181,10 @@ function readBrandConfig() {
|
|
|
13166
13181
|
cachedAttempted = true;
|
|
13167
13182
|
const platformRoot = process.env.MAXY_PLATFORM_ROOT;
|
|
13168
13183
|
if (!platformRoot) return null;
|
|
13169
|
-
const brandPath =
|
|
13170
|
-
if (!
|
|
13184
|
+
const brandPath = join15(platformRoot, "config", "brand.json");
|
|
13185
|
+
if (!existsSync19(brandPath)) return null;
|
|
13171
13186
|
try {
|
|
13172
|
-
cached2 = JSON.parse(
|
|
13187
|
+
cached2 = JSON.parse(readFileSync19(brandPath, "utf-8"));
|
|
13173
13188
|
return cached2;
|
|
13174
13189
|
} catch {
|
|
13175
13190
|
return null;
|
|
@@ -13177,7 +13192,7 @@ function readBrandConfig() {
|
|
|
13177
13192
|
}
|
|
13178
13193
|
|
|
13179
13194
|
// server/routes/visitor-consent.ts
|
|
13180
|
-
var
|
|
13195
|
+
var app37 = new Hono();
|
|
13181
13196
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
13182
13197
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
13183
13198
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -13222,17 +13237,17 @@ function siteSlugFromReferer(referer) {
|
|
|
13222
13237
|
return "";
|
|
13223
13238
|
}
|
|
13224
13239
|
}
|
|
13225
|
-
|
|
13240
|
+
app37.options("/consent", (c) => {
|
|
13226
13241
|
const origin = getOrigin(c);
|
|
13227
13242
|
setCorsHeaders(c, origin);
|
|
13228
13243
|
return c.body(null, 204);
|
|
13229
13244
|
});
|
|
13230
|
-
|
|
13245
|
+
app37.options("/brand-config", (c) => {
|
|
13231
13246
|
const origin = getOrigin(c);
|
|
13232
13247
|
setCorsHeaders(c, origin);
|
|
13233
13248
|
return c.body(null, 204);
|
|
13234
13249
|
});
|
|
13235
|
-
|
|
13250
|
+
app37.post("/consent", async (c) => {
|
|
13236
13251
|
const origin = getOrigin(c);
|
|
13237
13252
|
setCorsHeaders(c, origin);
|
|
13238
13253
|
let raw;
|
|
@@ -13272,7 +13287,7 @@ app36.post("/consent", async (c) => {
|
|
|
13272
13287
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
13273
13288
|
return c.body(null, 204);
|
|
13274
13289
|
});
|
|
13275
|
-
|
|
13290
|
+
app37.get("/brand-config", (c) => {
|
|
13276
13291
|
const origin = getOrigin(c);
|
|
13277
13292
|
setCorsHeaders(c, origin);
|
|
13278
13293
|
const brand = readBrandConfig();
|
|
@@ -13282,7 +13297,7 @@ app36.get("/brand-config", (c) => {
|
|
|
13282
13297
|
c.header("Cache-Control", "public, max-age=300");
|
|
13283
13298
|
return c.json({ consent: { copy, palette } });
|
|
13284
13299
|
});
|
|
13285
|
-
var visitor_consent_default =
|
|
13300
|
+
var visitor_consent_default = app37;
|
|
13286
13301
|
|
|
13287
13302
|
// server/routes/listings.ts
|
|
13288
13303
|
function getCookie(headerValue, name) {
|
|
@@ -13309,8 +13324,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
13309
13324
|
}
|
|
13310
13325
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
13311
13326
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
13312
|
-
var
|
|
13313
|
-
|
|
13327
|
+
var app38 = new Hono();
|
|
13328
|
+
app38.get("/:slug/click", async (c) => {
|
|
13314
13329
|
const slug = c.req.param("slug") ?? "";
|
|
13315
13330
|
const rawSession = c.req.query("session") ?? "";
|
|
13316
13331
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -13374,10 +13389,10 @@ app37.get("/:slug/click", async (c) => {
|
|
|
13374
13389
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
13375
13390
|
return c.redirect(redirectUrl, 302);
|
|
13376
13391
|
});
|
|
13377
|
-
var listings_default =
|
|
13392
|
+
var listings_default = app38;
|
|
13378
13393
|
|
|
13379
13394
|
// server/routes/visitor-event.ts
|
|
13380
|
-
var
|
|
13395
|
+
var app39 = new Hono();
|
|
13381
13396
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
13382
13397
|
var buckets = /* @__PURE__ */ new Map();
|
|
13383
13398
|
var RATE_LIMIT = 60;
|
|
@@ -13444,12 +13459,12 @@ function originAllowed(origin, allowlist) {
|
|
|
13444
13459
|
return false;
|
|
13445
13460
|
}
|
|
13446
13461
|
}
|
|
13447
|
-
|
|
13462
|
+
app39.options("/event", (c) => {
|
|
13448
13463
|
const origin = getOrigin2(c);
|
|
13449
13464
|
setCorsHeaders2(c, origin);
|
|
13450
13465
|
return c.body(null, 204);
|
|
13451
13466
|
});
|
|
13452
|
-
|
|
13467
|
+
app39.post("/event", async (c) => {
|
|
13453
13468
|
const origin = getOrigin2(c);
|
|
13454
13469
|
setCorsHeaders2(c, origin);
|
|
13455
13470
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -13654,7 +13669,7 @@ async function writeEvent(opts) {
|
|
|
13654
13669
|
);
|
|
13655
13670
|
}
|
|
13656
13671
|
}
|
|
13657
|
-
var visitor_event_default =
|
|
13672
|
+
var visitor_event_default = app39;
|
|
13658
13673
|
|
|
13659
13674
|
// app/lib/graph-health.ts
|
|
13660
13675
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
@@ -13901,7 +13916,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
13901
13916
|
|
|
13902
13917
|
// ../lib/entitlement/src/index.ts
|
|
13903
13918
|
import { createPublicKey, createHash as createHash4, verify as cryptoVerify } from "crypto";
|
|
13904
|
-
import { existsSync as
|
|
13919
|
+
import { existsSync as existsSync20, readFileSync as readFileSync20, statSync as statSync9 } from "fs";
|
|
13905
13920
|
import { resolve as resolve22 } from "path";
|
|
13906
13921
|
|
|
13907
13922
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -13950,10 +13965,10 @@ function resolveEntitlement(brand, account) {
|
|
|
13950
13965
|
return logResolved(implicitTrust(account), null);
|
|
13951
13966
|
}
|
|
13952
13967
|
const entitlementPath = resolve22(brand.configDir, "entitlement.json");
|
|
13953
|
-
if (!
|
|
13968
|
+
if (!existsSync20(entitlementPath)) {
|
|
13954
13969
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
13955
13970
|
}
|
|
13956
|
-
const stat8 =
|
|
13971
|
+
const stat8 = statSync9(entitlementPath);
|
|
13957
13972
|
const key = memoKey(stat8.mtimeMs, account);
|
|
13958
13973
|
if (memo && memo.key === key) {
|
|
13959
13974
|
return memo.result;
|
|
@@ -13965,7 +13980,7 @@ function resolveEntitlement(brand, account) {
|
|
|
13965
13980
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
13966
13981
|
let pubkeyPem;
|
|
13967
13982
|
try {
|
|
13968
|
-
pubkeyPem =
|
|
13983
|
+
pubkeyPem = readFileSync20(pubkeyPath(brand), "utf-8");
|
|
13969
13984
|
} catch (err) {
|
|
13970
13985
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
13971
13986
|
reason: "pubkey-missing"
|
|
@@ -13979,7 +13994,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
13979
13994
|
}
|
|
13980
13995
|
let envelope;
|
|
13981
13996
|
try {
|
|
13982
|
-
envelope = JSON.parse(
|
|
13997
|
+
envelope = JSON.parse(readFileSync20(entitlementPath, "utf-8"));
|
|
13983
13998
|
} catch {
|
|
13984
13999
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
13985
14000
|
}
|
|
@@ -14140,14 +14155,14 @@ function clientFrom(c) {
|
|
|
14140
14155
|
);
|
|
14141
14156
|
}
|
|
14142
14157
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
14143
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT9 ?
|
|
14158
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join16(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
14144
14159
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
14145
|
-
if (BRAND_JSON_PATH && !
|
|
14160
|
+
if (BRAND_JSON_PATH && !existsSync21(BRAND_JSON_PATH)) {
|
|
14146
14161
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
14147
14162
|
}
|
|
14148
|
-
if (BRAND_JSON_PATH &&
|
|
14163
|
+
if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
|
|
14149
14164
|
try {
|
|
14150
|
-
const parsed = JSON.parse(
|
|
14165
|
+
const parsed = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
|
|
14151
14166
|
BRAND = { ...BRAND, ...parsed };
|
|
14152
14167
|
} catch (err) {
|
|
14153
14168
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -14166,11 +14181,11 @@ var brandLoginOpts = {
|
|
|
14166
14181
|
bodyFont: BRAND.defaultFonts?.body,
|
|
14167
14182
|
logoContainsName: !!BRAND.logoContainsName
|
|
14168
14183
|
};
|
|
14169
|
-
var ALIAS_DOMAINS_PATH =
|
|
14184
|
+
var ALIAS_DOMAINS_PATH = join16(homedir2(), BRAND.configDir, "alias-domains.json");
|
|
14170
14185
|
function loadAliasDomains() {
|
|
14171
14186
|
try {
|
|
14172
|
-
if (!
|
|
14173
|
-
const parsed = JSON.parse(
|
|
14187
|
+
if (!existsSync21(ALIAS_DOMAINS_PATH)) return null;
|
|
14188
|
+
const parsed = JSON.parse(readFileSync21(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
14174
14189
|
if (!Array.isArray(parsed)) {
|
|
14175
14190
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
14176
14191
|
return null;
|
|
@@ -14194,9 +14209,9 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
14194
14209
|
function isPublicHost(host) {
|
|
14195
14210
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
14196
14211
|
}
|
|
14197
|
-
var
|
|
14198
|
-
|
|
14199
|
-
|
|
14212
|
+
var app40 = new Hono();
|
|
14213
|
+
app40.use("*", clientIpMiddleware);
|
|
14214
|
+
app40.use("*", async (c, next) => {
|
|
14200
14215
|
await next();
|
|
14201
14216
|
c.header("X-Content-Type-Options", "nosniff");
|
|
14202
14217
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -14206,7 +14221,7 @@ app39.use("*", async (c, next) => {
|
|
|
14206
14221
|
);
|
|
14207
14222
|
});
|
|
14208
14223
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
14209
|
-
|
|
14224
|
+
app40.use("*", async (c, next) => {
|
|
14210
14225
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
14211
14226
|
await next();
|
|
14212
14227
|
return;
|
|
@@ -14239,7 +14254,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
14239
14254
|
"/sites/"
|
|
14240
14255
|
];
|
|
14241
14256
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
14242
|
-
|
|
14257
|
+
app40.use("*", async (c, next) => {
|
|
14243
14258
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14244
14259
|
if (!isPublicHost(host)) {
|
|
14245
14260
|
await next();
|
|
@@ -14279,7 +14294,7 @@ function resolveRemoteAuthOpts() {
|
|
|
14279
14294
|
return brandLoginOpts;
|
|
14280
14295
|
}
|
|
14281
14296
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
14282
|
-
|
|
14297
|
+
app40.post("/__remote-auth/login", async (c) => {
|
|
14283
14298
|
const client = clientFrom(c);
|
|
14284
14299
|
const clientIp = client.ip || "unknown";
|
|
14285
14300
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -14324,7 +14339,7 @@ app39.post("/__remote-auth/login", async (c) => {
|
|
|
14324
14339
|
}
|
|
14325
14340
|
});
|
|
14326
14341
|
});
|
|
14327
|
-
|
|
14342
|
+
app40.get("/__remote-auth/logout", (c) => {
|
|
14328
14343
|
const client = clientFrom(c);
|
|
14329
14344
|
const clientIp = client.ip || "unknown";
|
|
14330
14345
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -14337,7 +14352,7 @@ app39.get("/__remote-auth/logout", (c) => {
|
|
|
14337
14352
|
}
|
|
14338
14353
|
});
|
|
14339
14354
|
});
|
|
14340
|
-
|
|
14355
|
+
app40.post("/__remote-auth/change-password", async (c) => {
|
|
14341
14356
|
const client = clientFrom(c);
|
|
14342
14357
|
const clientIp = client.ip || "unknown";
|
|
14343
14358
|
const rateLimited = checkRateLimit(client);
|
|
@@ -14388,13 +14403,13 @@ app39.post("/__remote-auth/change-password", async (c) => {
|
|
|
14388
14403
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
14389
14404
|
}
|
|
14390
14405
|
});
|
|
14391
|
-
|
|
14406
|
+
app40.get("/__remote-auth/setup", (c) => {
|
|
14392
14407
|
if (isRemoteAuthConfigured()) {
|
|
14393
14408
|
return c.redirect("/");
|
|
14394
14409
|
}
|
|
14395
14410
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
14396
14411
|
});
|
|
14397
|
-
|
|
14412
|
+
app40.post("/__remote-auth/set-initial-password", async (c) => {
|
|
14398
14413
|
if (isRemoteAuthConfigured()) {
|
|
14399
14414
|
return c.redirect("/");
|
|
14400
14415
|
}
|
|
@@ -14432,10 +14447,10 @@ app39.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
14432
14447
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
14433
14448
|
}
|
|
14434
14449
|
});
|
|
14435
|
-
|
|
14450
|
+
app40.get("/api/remote-auth/status", (c) => {
|
|
14436
14451
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
14437
14452
|
});
|
|
14438
|
-
|
|
14453
|
+
app40.post("/api/remote-auth/set-password", async (c) => {
|
|
14439
14454
|
let body;
|
|
14440
14455
|
try {
|
|
14441
14456
|
body = await c.req.json();
|
|
@@ -14466,9 +14481,9 @@ app39.post("/api/remote-auth/set-password", async (c) => {
|
|
|
14466
14481
|
return c.json({ error: "Failed to save password" }, 500);
|
|
14467
14482
|
}
|
|
14468
14483
|
});
|
|
14469
|
-
|
|
14484
|
+
app40.route("/api/_client-error", client_error_default);
|
|
14470
14485
|
console.log("[client-error-route] mounted");
|
|
14471
|
-
|
|
14486
|
+
app40.use("*", async (c, next) => {
|
|
14472
14487
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14473
14488
|
const path2 = c.req.path;
|
|
14474
14489
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -14501,12 +14516,12 @@ app39.use("*", async (c, next) => {
|
|
|
14501
14516
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
14502
14517
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
14503
14518
|
});
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14519
|
+
app40.route("/api/health", health_default);
|
|
14520
|
+
app40.route("/api/chat", chat_default);
|
|
14521
|
+
app40.route("/api/whatsapp", whatsapp_default);
|
|
14522
|
+
app40.route("/api/onboarding", onboarding_default);
|
|
14523
|
+
app40.route("/api/admin", admin_default);
|
|
14524
|
+
app40.route("/api/access", access_default);
|
|
14510
14525
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
14511
14526
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
14512
14527
|
var IMAGE_MIME = {
|
|
@@ -14518,7 +14533,7 @@ var IMAGE_MIME = {
|
|
|
14518
14533
|
".svg": "image/svg+xml",
|
|
14519
14534
|
".ico": "image/x-icon"
|
|
14520
14535
|
};
|
|
14521
|
-
|
|
14536
|
+
app40.get("/agent-assets/:slug/:filename", (c) => {
|
|
14522
14537
|
const slug = c.req.param("slug");
|
|
14523
14538
|
const filename = c.req.param("filename");
|
|
14524
14539
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -14540,20 +14555,20 @@ app39.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
14540
14555
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
14541
14556
|
return c.text("Forbidden", 403);
|
|
14542
14557
|
}
|
|
14543
|
-
if (!
|
|
14558
|
+
if (!existsSync21(filePath)) {
|
|
14544
14559
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
14545
14560
|
return c.text("Not found", 404);
|
|
14546
14561
|
}
|
|
14547
14562
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
14548
14563
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
14549
14564
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
14550
|
-
const body =
|
|
14565
|
+
const body = readFileSync21(filePath);
|
|
14551
14566
|
return c.body(body, 200, {
|
|
14552
14567
|
"Content-Type": contentType,
|
|
14553
14568
|
"Cache-Control": "public, max-age=3600"
|
|
14554
14569
|
});
|
|
14555
14570
|
});
|
|
14556
|
-
|
|
14571
|
+
app40.get("/generated/:filename", (c) => {
|
|
14557
14572
|
const filename = c.req.param("filename");
|
|
14558
14573
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
14559
14574
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -14570,29 +14585,29 @@ app39.get("/generated/:filename", (c) => {
|
|
|
14570
14585
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
14571
14586
|
return c.text("Forbidden", 403);
|
|
14572
14587
|
}
|
|
14573
|
-
if (!
|
|
14588
|
+
if (!existsSync21(filePath)) {
|
|
14574
14589
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
14575
14590
|
return c.text("Not found", 404);
|
|
14576
14591
|
}
|
|
14577
14592
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
14578
14593
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
14579
14594
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
14580
|
-
const body =
|
|
14595
|
+
const body = readFileSync21(filePath);
|
|
14581
14596
|
return c.body(body, 200, {
|
|
14582
14597
|
"Content-Type": contentType,
|
|
14583
14598
|
"Cache-Control": "public, max-age=86400"
|
|
14584
14599
|
});
|
|
14585
14600
|
});
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14601
|
+
app40.route("/sites", sites_default);
|
|
14602
|
+
app40.route("/listings", listings_default);
|
|
14603
|
+
app40.route("/v", visitor_event_default);
|
|
14604
|
+
app40.route("/v", visitor_consent_default);
|
|
14590
14605
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
14591
14606
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
14592
14607
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
14593
|
-
if (BRAND_JSON_PATH &&
|
|
14608
|
+
if (BRAND_JSON_PATH && existsSync21(BRAND_JSON_PATH)) {
|
|
14594
14609
|
try {
|
|
14595
|
-
const fullBrand = JSON.parse(
|
|
14610
|
+
const fullBrand = JSON.parse(readFileSync21(BRAND_JSON_PATH, "utf-8"));
|
|
14596
14611
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
14597
14612
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
14598
14613
|
} catch {
|
|
@@ -14609,9 +14624,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
14609
14624
|
function readInstalledVersion() {
|
|
14610
14625
|
try {
|
|
14611
14626
|
if (!PLATFORM_ROOT9) return "unknown";
|
|
14612
|
-
const versionFile =
|
|
14613
|
-
if (!
|
|
14614
|
-
const content =
|
|
14627
|
+
const versionFile = join16(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
|
|
14628
|
+
if (!existsSync21(versionFile)) return "unknown";
|
|
14629
|
+
const content = readFileSync21(versionFile, "utf-8").trim();
|
|
14615
14630
|
return content || "unknown";
|
|
14616
14631
|
} catch {
|
|
14617
14632
|
return "unknown";
|
|
@@ -14652,7 +14667,7 @@ var clientErrorReporterScript = `<script>
|
|
|
14652
14667
|
function cachedHtml(file) {
|
|
14653
14668
|
let html = htmlCache.get(file);
|
|
14654
14669
|
if (!html) {
|
|
14655
|
-
html =
|
|
14670
|
+
html = readFileSync21(resolve23(process.cwd(), "public", file), "utf-8");
|
|
14656
14671
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
14657
14672
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
14658
14673
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -14668,26 +14683,26 @@ ${clientErrorReporterScript}
|
|
|
14668
14683
|
}
|
|
14669
14684
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
14670
14685
|
function loadBrandingCache(agentSlug) {
|
|
14671
|
-
const configDir2 =
|
|
14686
|
+
const configDir2 = join16(homedir2(), BRAND.configDir);
|
|
14672
14687
|
try {
|
|
14673
|
-
const accountJsonPath =
|
|
14674
|
-
if (!
|
|
14675
|
-
const account = JSON.parse(
|
|
14688
|
+
const accountJsonPath = join16(configDir2, "account.json");
|
|
14689
|
+
if (!existsSync21(accountJsonPath)) return null;
|
|
14690
|
+
const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
|
|
14676
14691
|
const accountId = account.accountId;
|
|
14677
14692
|
if (!accountId) return null;
|
|
14678
|
-
const cachePath =
|
|
14679
|
-
if (!
|
|
14680
|
-
return JSON.parse(
|
|
14693
|
+
const cachePath = join16(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
14694
|
+
if (!existsSync21(cachePath)) return null;
|
|
14695
|
+
return JSON.parse(readFileSync21(cachePath, "utf-8"));
|
|
14681
14696
|
} catch {
|
|
14682
14697
|
return null;
|
|
14683
14698
|
}
|
|
14684
14699
|
}
|
|
14685
14700
|
function resolveDefaultSlug() {
|
|
14686
14701
|
try {
|
|
14687
|
-
const configDir2 =
|
|
14688
|
-
const accountJsonPath =
|
|
14689
|
-
if (!
|
|
14690
|
-
const account = JSON.parse(
|
|
14702
|
+
const configDir2 = join16(homedir2(), BRAND.configDir);
|
|
14703
|
+
const accountJsonPath = join16(configDir2, "account.json");
|
|
14704
|
+
if (!existsSync21(accountJsonPath)) return null;
|
|
14705
|
+
const account = JSON.parse(readFileSync21(accountJsonPath, "utf-8"));
|
|
14691
14706
|
return account.defaultAgent || null;
|
|
14692
14707
|
} catch {
|
|
14693
14708
|
return null;
|
|
@@ -14723,7 +14738,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
14723
14738
|
function escapeHtml(s) {
|
|
14724
14739
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
14725
14740
|
}
|
|
14726
|
-
|
|
14741
|
+
app40.get("/", (c) => {
|
|
14727
14742
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14728
14743
|
if (isPublicHost(host)) {
|
|
14729
14744
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -14731,12 +14746,12 @@ app39.get("/", (c) => {
|
|
|
14731
14746
|
}
|
|
14732
14747
|
return c.html(cachedHtml("index.html"));
|
|
14733
14748
|
});
|
|
14734
|
-
|
|
14749
|
+
app40.get("/public", (c) => {
|
|
14735
14750
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14736
14751
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14737
14752
|
return c.html(cachedHtml("public.html"));
|
|
14738
14753
|
});
|
|
14739
|
-
|
|
14754
|
+
app40.get("/chat", (c) => {
|
|
14740
14755
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14741
14756
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14742
14757
|
return c.html(cachedHtml("public.html"));
|
|
@@ -14755,12 +14770,12 @@ async function logViewerFetch(c, next) {
|
|
|
14755
14770
|
duration_ms: Date.now() - start
|
|
14756
14771
|
});
|
|
14757
14772
|
}
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14773
|
+
app40.use("/vnc-viewer.html", logViewerFetch);
|
|
14774
|
+
app40.use("/vnc-popout.html", logViewerFetch);
|
|
14775
|
+
app40.get("/vnc-popout.html", (c) => {
|
|
14761
14776
|
let html = htmlCache.get("vnc-popout.html");
|
|
14762
14777
|
if (!html) {
|
|
14763
|
-
html =
|
|
14778
|
+
html = readFileSync21(resolve23(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
14764
14779
|
const name = escapeHtml(BRAND.productName);
|
|
14765
14780
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
14766
14781
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -14770,7 +14785,7 @@ app39.get("/vnc-popout.html", (c) => {
|
|
|
14770
14785
|
}
|
|
14771
14786
|
return c.html(html);
|
|
14772
14787
|
});
|
|
14773
|
-
|
|
14788
|
+
app40.post("/api/vnc/client-event", async (c) => {
|
|
14774
14789
|
let body;
|
|
14775
14790
|
try {
|
|
14776
14791
|
body = await c.req.json();
|
|
@@ -14791,25 +14806,25 @@ app39.post("/api/vnc/client-event", async (c) => {
|
|
|
14791
14806
|
});
|
|
14792
14807
|
return c.json({ ok: true });
|
|
14793
14808
|
});
|
|
14794
|
-
|
|
14809
|
+
app40.get("/g/:slug", (c) => {
|
|
14795
14810
|
return c.html(brandedPublicHtml());
|
|
14796
14811
|
});
|
|
14797
|
-
|
|
14812
|
+
app40.get("/graph", (c) => {
|
|
14798
14813
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14799
14814
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14800
14815
|
return c.html(cachedHtml("graph.html"));
|
|
14801
14816
|
});
|
|
14802
|
-
|
|
14817
|
+
app40.get("/sessions", (c) => {
|
|
14803
14818
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14804
14819
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14805
14820
|
return c.html(cachedHtml("sessions.html"));
|
|
14806
14821
|
});
|
|
14807
|
-
|
|
14822
|
+
app40.get("/data", (c) => {
|
|
14808
14823
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
14809
14824
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
14810
14825
|
return c.html(cachedHtml("data.html"));
|
|
14811
14826
|
});
|
|
14812
|
-
|
|
14827
|
+
app40.get("/:slug", async (c, next) => {
|
|
14813
14828
|
const slug = c.req.param("slug");
|
|
14814
14829
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
14815
14830
|
const branding = loadBrandingCache(slug);
|
|
@@ -14819,15 +14834,15 @@ app39.get("/:slug", async (c, next) => {
|
|
|
14819
14834
|
await next();
|
|
14820
14835
|
});
|
|
14821
14836
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
14822
|
-
|
|
14837
|
+
app40.get("/favicon.ico", (c) => {
|
|
14823
14838
|
c.header("Cache-Control", "public, max-age=300");
|
|
14824
14839
|
return c.redirect(brandFaviconPath, 302);
|
|
14825
14840
|
});
|
|
14826
14841
|
}
|
|
14827
|
-
|
|
14842
|
+
app40.use("/*", serveStatic({ root: "./public" }));
|
|
14828
14843
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
14829
14844
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
14830
|
-
var httpServer = serve({ fetch:
|
|
14845
|
+
var httpServer = serve({ fetch: app40.fetch, port, hostname });
|
|
14831
14846
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
14832
14847
|
{
|
|
14833
14848
|
const loopHist = monitorEventLoopDelay({ resolution: 50 });
|
|
@@ -14863,7 +14878,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
14863
14878
|
}
|
|
14864
14879
|
try {
|
|
14865
14880
|
const registered = [];
|
|
14866
|
-
for (const r of
|
|
14881
|
+
for (const r of app40.routes ?? []) {
|
|
14867
14882
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
14868
14883
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
14869
14884
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -14885,8 +14900,8 @@ try {
|
|
|
14885
14900
|
}
|
|
14886
14901
|
(async () => {
|
|
14887
14902
|
try {
|
|
14888
|
-
if (!
|
|
14889
|
-
const usersRaw =
|
|
14903
|
+
if (!existsSync21(USERS_FILE)) return;
|
|
14904
|
+
const usersRaw = readFileSync21(USERS_FILE, "utf-8").trim();
|
|
14890
14905
|
if (!usersRaw) return;
|
|
14891
14906
|
const users = JSON.parse(usersRaw);
|
|
14892
14907
|
const userId = users[0]?.userId;
|
|
@@ -14981,7 +14996,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
14981
14996
|
}
|
|
14982
14997
|
init({
|
|
14983
14998
|
configDir: configDirForWhatsApp,
|
|
14984
|
-
platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ??
|
|
14999
|
+
platformRoot: resolve23(process.env.MAXY_PLATFORM_ROOT ?? join16(__dirname, "..")),
|
|
14985
15000
|
accountConfig: bootAccountConfig,
|
|
14986
15001
|
onMessage: async (msg) => {
|
|
14987
15002
|
if (process.env.WHATSAPP_PTY_BRIDGE_ENABLED === "true" && msg.text && !msg.isOwnerMirror) {
|