@rubytech/create-maxy-code 0.1.298 → 0.1.299
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/cloudflare/references/manual-setup.md +33 -0
- package/payload/server/public/assets/AdminShell-Eo1RXZxq.js +1 -0
- package/payload/server/public/assets/{Checkbox-CVPUf_7I.js → Checkbox-DHnspkuk.js} +1 -1
- package/payload/server/public/assets/{Transcript-FYmq-mL1.js → Transcript-9FlneAzM.js} +1 -1
- package/payload/server/public/assets/admin-ORJGvOqo.js +1 -0
- package/payload/server/public/assets/{arc-DmR-LPIx.js → arc-CPOhuw1V.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-CQHotPO2.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-IVt2X8Dk.js → architectureDiagram-Q4EWVU46-BaR37f-j.js} +1 -1
- package/payload/server/public/assets/{audio-attachment-mime-DaInZ9sa.js → audio-attachment-mime-CFRERhV0.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CQDngnsc.js → blockDiagram-DXYQGD6D-Du7NMQfQ.js} +1 -1
- package/payload/server/public/assets/{browser-D_hZgtfv.js → browser--bCCzvRh.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BjV_YA-L.js → c4Diagram-AHTNJAMY-F3GnFLbs.js} +1 -1
- package/payload/server/public/assets/channel-DfO_IgSU.js +1 -0
- package/payload/server/public/assets/{chat-COcrNTJi.js → chat-DIrzZjdO.js} +1 -1
- package/payload/server/public/assets/{chunk-2KRD3SAO-BYqpHDvA.js → chunk-2KRD3SAO-SUv9UlAA.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-B0yBhSVq.js → chunk-336JU56O-DHUrM3QG.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-CBo-Lx7X.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-BeDVr5Tb.js → chunk-4BX2VUAB-D5iKMyHO.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BImQYhPF.js → chunk-4TB4RGXK-BahbQ7-Z.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-DB18cH4S.js → chunk-55IACEB6-DfF9myIx.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-DrDSHQZv.js → chunk-5FUZZQ4R-jF6a9UVe.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-CKX_LIok.js → chunk-5PVQY5BW-BOCI-roy.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-Ca9KwdQm.js → chunk-67CJDMHE-E5wGK0dP.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-BDpzHOmv.js → chunk-7N4EOEYR-CtT0GsUT.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-DXo9fZho.js → chunk-AA7GKIK3-CGUj8eo-.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-CTqmM6qI.js → chunk-BSJP7CBP-OPAIjvSk.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-NufEId2j.js → chunk-CIAEETIT-S_D8FhIT.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-D1zHB217.js → chunk-EDXVE4YY-CkD4AyZi.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-SFpdtszU.js → chunk-ENJZ2VHE-CmoK-c5f.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-_4wtKsfc.js → chunk-FMBD7UC4-DcyogdNf.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-565zaYb3.js → chunk-FOC6F5B3-8iNobZdv.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-cYdq7RKF.js → chunk-ICPOFSXX-DeGZE9pw.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-CTZnA5fq.js → chunk-K5T4RW27-CkoKFdgU.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-CeuKp7uR.js → chunk-KGLVRYIC-DyNP1efP.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-DXkzlh3_.js → chunk-LIHQZDEY-WZPpo5Dd.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-DcZUCmgM.js → chunk-ORNJ4GCN-Cr7E0-Df.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-B7JLCext.js → chunk-OYMX7WX6-BPjxo1Oc.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CNlL2tiW.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-DWCeFwem.js → chunk-U2HBQHQK-CuDS7yVX.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-DGnHsoJ3.js → chunk-X2U36JSP-DEkde3xe.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-CnU6DVpC.js → chunk-XPW4576I-BwRCuKyu.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-sg4lGGJV.js → chunk-YZCP3GAM-DD9nUp-w.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-DtUoGmKE.js → chunk-ZZ45TVLE-BDH9b11G.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Bo-iLGpk.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Bz7DNpvQ.js +1 -0
- package/payload/server/public/assets/clone-Bh_bM_44.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-C04wkJr7.js → cose-bilkent-S5V4N54A-CfeophtW.js} +1 -1
- package/payload/server/public/assets/{dagre-Dfj_jbTe.js → dagre-CVxEmku2.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-Bd1VlhUJ.js → dagre-KV5264BT-TOuVLdjq.js} +1 -1
- package/payload/server/public/assets/{data-DkbQI40a.js → data-B8Waqy4Q.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-Dqqyk8GE.js → diagram-5BDNPKRD-BJQnfJjx.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-Xk3WKR_U.js → diagram-G4DWMVQ6-CqK94J29.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-CAdGL9U7.js → diagram-MMDJMWI5-BCnATv2X.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-DY1iYQVY.js → diagram-TYMM5635-Cl3BUrVs.js} +1 -1
- package/payload/server/public/assets/{dist-Pgmncqde.js → dist-BXJR8AkG.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-BJ5HYKeb.js → erDiagram-SMLLAGMA--Uw0kvib.js} +1 -1
- package/payload/server/public/assets/{file-download-BYJN3Kgm.js → file-download-Pk6cNtuB.js} +1 -1
- package/payload/server/public/assets/{flatten-DeFkSYLU.js → flatten-DtM0XAMt.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B-q6x5Q_.js → flowDiagram-DWJPFMVM-B_VGZIbJ.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DbjwY_bG.js → ganttDiagram-T4ZO3ILL-D-vdf1dC.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-Ds2hoRX4.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C3bLrOmb.js → gitGraphDiagram-UUTBAWPF-CpyAlvu3.js} +1 -1
- package/payload/server/public/assets/{graph-DmikPM4A.js → graph-D-VQpkaS.js} +1 -1
- package/payload/server/public/assets/{graph-labels-CtG6ckdG.js → graph-labels-cJvlyVxD.js} +1 -1
- package/payload/server/public/assets/{graphlib-BlOjhixq.js → graphlib-DaV4XyBp.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BuX4gDTt.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-pcFw8-8F.js +2 -0
- package/payload/server/public/assets/{isEmpty-Bn-Se8yT.js → isEmpty-D__iH1WQ.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B_DzwK8l.js → ishikawaDiagram-UXIWVN3A-_4NvfwwU.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-COzTF-qc.js → journeyDiagram-VCZTEJTY-PJQ-tPWv.js} +1 -1
- package/payload/server/public/assets/{jsx-runtime-UQ0Z6nwN.js → jsx-runtime-B54kfC3e.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-C2cOIZU6.js → kanban-definition-6JOO6SKY-asCNlyH4.js} +1 -1
- package/payload/server/public/assets/{line-Bwa6aUYZ.js → line-BSXr2IPU.js} +1 -1
- package/payload/server/public/assets/{linear-CgbkJiu6.js → linear-CSAKvvko.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-BFAF0BAk.js → mermaid-parser.core-DFxv-h16.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-CMOXmawT.js → mermaid.core-Be34BFtA.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-bu0QLO17.js → mindmap-definition-QFDTVHPH-IxwnMT2Q.js} +1 -1
- package/payload/server/public/assets/operator-DyLRFmNE.js +1 -0
- package/payload/server/public/assets/{ordinal-C-EimP2j.js → ordinal-BRQ5CzZY.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-9qQ2zAJ3.js +1 -0
- package/payload/server/public/assets/page-CFgywgGE.js +1 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-aDbmozld.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-DQUe6W2Z.js → pieDiagram-DEJITSTG-DFqSnPPB.js} +1 -1
- package/payload/server/public/assets/{public-CSEIGhb4.js → public-_pD6yEQ6.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-ChhcwVRA.js → quadrantDiagram-34T5L4WZ-1AB3hlEb.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-CEm-iLey.js +1 -0
- package/payload/server/public/assets/{reduce-B0wq8DtH.js → reduce-CkcXOmmJ.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DwQXqTA9.js → requirementDiagram-MS252O5E-C2Zpzq3l.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-zYqdptBM.js → sankeyDiagram-XADWPNL6-DkmhPhwS.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-x2g84gb4.js → sequenceDiagram-FGHM5R23-1hQLpeZ1.js} +1 -1
- package/payload/server/public/assets/{src-CozP7LCe.js → src-CPkr6SrY.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CeUrqs2P.js → stateDiagram-FHFEXIEX-CBHIwm3f.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DHGLsXgi.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CL-c9XN5.js → timeline-definition-GMOUNBTQ-CLRWWipW.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-DYa2gPJa.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-D816ED1y.js +1 -0
- package/payload/server/public/assets/{useSelectionMode-C1_ky4B6.js → useSelectionMode-6fff2UIV.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-By2HBDYr.js → vennDiagram-DHZGUBPP-ByFoQMek.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-BniDWDlr.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-iahvFvIS.js → wardleyDiagram-NUSXRM2D-DIkXRSha.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-33qqdRhI.js → xychartDiagram-5P7HB3ND-BNdEcN73.js} +1 -1
- package/payload/server/public/browser.html +6 -6
- package/payload/server/public/chat.html +8 -8
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +8 -8
- package/payload/server/public/index.html +10 -9
- package/payload/server/public/operator.html +24 -0
- package/payload/server/public/public.html +6 -6
- package/payload/server/server.js +289 -222
- package/payload/server/public/assets/AdminShell-BnhxfX97.js +0 -1
- package/payload/server/public/assets/admin-CF8K3hqE.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-CjF2k79a.js +0 -1
- package/payload/server/public/assets/channel-gFnUr8f4.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-BCmWl6vi.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CBWmDBHe.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-C_wlfUTz.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Ltv5s3OY.js +0 -1
- package/payload/server/public/assets/clone-D0XoXc_v.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-DsUTwRUb.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-BV9FyUXQ.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-BpaHbiXO.js +0 -2
- package/payload/server/public/assets/packet-4T2RLAQJ-SXjQ83Vr.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-q7TXebDD.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-CXKUHVMS.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B27DBP9X.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CWuFgUeJ.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-gKO4rbgo.js +0 -1
- package/payload/server/public/assets/wardley-RL74JXVD-hDEw8pJN.js +0 -1
- /package/payload/server/public/assets/{_baseFor-BV-TyLWt.js → _baseFor-SRtUHe7G.js} +0 -0
- /package/payload/server/public/assets/{array-lqrvkwy7.js → array-BpsnM-Py.js} +0 -0
- /package/payload/server/public/assets/{chunk-CWOGyPgy.js → chunk-Pqm5yXtL.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-SmEOayFS.js → cytoscape.esm-D4Rl1H5h.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-Dl3Sud5K.js → defaultLocale-C7sQPl-O.js} +0 -0
- /package/payload/server/public/assets/{init-BukMwkmL.js → init-BydxaDEV.js} +0 -0
- /package/payload/server/public/assets/{katex-jl-BtNZi.js → katex-B0fVeDx4.js} +0 -0
- /package/payload/server/public/assets/{admin-CWMpccrR.css → page-CWMpccrR.css} +0 -0
- /package/payload/server/public/assets/{path-DPTRcLku.js → path-jlWYQ2i9.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-VLpapkIG.js → rough.esm-c4PR5shF.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1215,7 +1215,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1215
1215
|
|
|
1216
1216
|
// server/index.ts
|
|
1217
1217
|
import { readFileSync as readFileSync26, existsSync as existsSync26, watchFile } from "fs";
|
|
1218
|
-
import { resolve as
|
|
1218
|
+
import { resolve as resolve29, join as join22, basename as basename8 } from "path";
|
|
1219
1219
|
import { homedir as homedir3 } from "os";
|
|
1220
1220
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1221
1221
|
|
|
@@ -1244,6 +1244,21 @@ function isPublicPathAllowed(path2) {
|
|
|
1244
1244
|
if (PUBLIC_ALLOWED_PREFIXES.some((prefix) => path2.startsWith(prefix))) return true;
|
|
1245
1245
|
return AGENT_SLUG_PATTERN.test(path2);
|
|
1246
1246
|
}
|
|
1247
|
+
function isOperatorHost(host) {
|
|
1248
|
+
return host.startsWith("operator.");
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// server/webchat-descriptor.ts
|
|
1252
|
+
import { resolve, join as join2 } from "path";
|
|
1253
|
+
function webchatGatewayUrl() {
|
|
1254
|
+
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
1255
|
+
}
|
|
1256
|
+
function webchatServerPath() {
|
|
1257
|
+
return process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve(process.env.MAXY_PLATFORM_ROOT ?? join2(__dirname, ".."), "services/webchat-channel/dist/server.js");
|
|
1258
|
+
}
|
|
1259
|
+
function webchatChannelDescriptor(key) {
|
|
1260
|
+
return { key, gatewayUrl: webchatGatewayUrl(), serverPath: webchatServerPath() };
|
|
1261
|
+
}
|
|
1247
1262
|
|
|
1248
1263
|
// app/lib/claude-auth.ts
|
|
1249
1264
|
import { readFileSync, writeFileSync } from "fs";
|
|
@@ -1794,7 +1809,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
1794
1809
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
1795
1810
|
console.error(`${TAG2} draining credential save queue\u2026`);
|
|
1796
1811
|
const timer2 = new Promise(
|
|
1797
|
-
(
|
|
1812
|
+
(resolve30) => setTimeout(() => resolve30("timeout"), timeoutMs)
|
|
1798
1813
|
);
|
|
1799
1814
|
const result = await Promise.race([
|
|
1800
1815
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -1922,11 +1937,11 @@ async function createWaSocket(opts) {
|
|
|
1922
1937
|
return sock;
|
|
1923
1938
|
}
|
|
1924
1939
|
async function waitForConnection(sock) {
|
|
1925
|
-
return new Promise((
|
|
1940
|
+
return new Promise((resolve30, reject) => {
|
|
1926
1941
|
const handler = (update) => {
|
|
1927
1942
|
if (update.connection === "open") {
|
|
1928
1943
|
sock.ev.off("connection.update", handler);
|
|
1929
|
-
|
|
1944
|
+
resolve30();
|
|
1930
1945
|
}
|
|
1931
1946
|
if (update.connection === "close") {
|
|
1932
1947
|
sock.ev.off("connection.update", handler);
|
|
@@ -2040,14 +2055,14 @@ ${inspected}`;
|
|
|
2040
2055
|
return inspect2(err, INSPECT_OPTS2);
|
|
2041
2056
|
}
|
|
2042
2057
|
function withTimeout(label, promise, timeoutMs) {
|
|
2043
|
-
return new Promise((
|
|
2058
|
+
return new Promise((resolve30, reject) => {
|
|
2044
2059
|
const timer2 = setTimeout(() => {
|
|
2045
2060
|
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
2046
2061
|
}, timeoutMs);
|
|
2047
2062
|
promise.then(
|
|
2048
2063
|
(value) => {
|
|
2049
2064
|
clearTimeout(timer2);
|
|
2050
|
-
|
|
2065
|
+
resolve30(value);
|
|
2051
2066
|
},
|
|
2052
2067
|
(err) => {
|
|
2053
2068
|
clearTimeout(timer2);
|
|
@@ -2646,8 +2661,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
2646
2661
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2647
2662
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2648
2663
|
let release;
|
|
2649
|
-
const mine = new Promise((
|
|
2650
|
-
release =
|
|
2664
|
+
const mine = new Promise((resolve30) => {
|
|
2665
|
+
release = resolve30;
|
|
2651
2666
|
});
|
|
2652
2667
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2653
2668
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -2833,7 +2848,7 @@ async function ensureWhatsAppConversation(input) {
|
|
|
2833
2848
|
|
|
2834
2849
|
// ../lib/account-enumeration/src/index.ts
|
|
2835
2850
|
import { readdirSync, readFileSync as readFileSync3 } from "fs";
|
|
2836
|
-
import { resolve } from "path";
|
|
2851
|
+
import { resolve as resolve2 } from "path";
|
|
2837
2852
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2838
2853
|
var cache = /* @__PURE__ */ new Map();
|
|
2839
2854
|
function enumerateValidAccountIds(accountsDir) {
|
|
@@ -2852,7 +2867,7 @@ function enumerateValidAccountIds(accountsDir) {
|
|
|
2852
2867
|
const valid = [];
|
|
2853
2868
|
for (const name of names) {
|
|
2854
2869
|
if (!UUID_RE.test(name)) continue;
|
|
2855
|
-
const configPath2 =
|
|
2870
|
+
const configPath2 = resolve2(accountsDir, name, "account.json");
|
|
2856
2871
|
try {
|
|
2857
2872
|
JSON.parse(readFileSync3(configPath2, "utf-8"));
|
|
2858
2873
|
valid.push(name);
|
|
@@ -2871,7 +2886,7 @@ function getAccountsDirFromEnv() {
|
|
|
2871
2886
|
"[graph-write] MAXY_PLATFORM_ROOT not set \u2014 cannot enforce accountId gate. Set MAXY_PLATFORM_ROOT in the spawning process or pass `accountsDir` explicitly."
|
|
2872
2887
|
);
|
|
2873
2888
|
}
|
|
2874
|
-
return
|
|
2889
|
+
return resolve2(root, "..", "data/accounts");
|
|
2875
2890
|
}
|
|
2876
2891
|
function validateAccountIdEnv(envValue, diskIds) {
|
|
2877
2892
|
if (!envValue) {
|
|
@@ -2910,7 +2925,7 @@ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
|
|
|
2910
2925
|
// app/lib/whatsapp/inbound/media.ts
|
|
2911
2926
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2912
2927
|
import { writeFile, mkdir } from "fs/promises";
|
|
2913
|
-
import { join as
|
|
2928
|
+
import { join as join3 } from "path";
|
|
2914
2929
|
import {
|
|
2915
2930
|
downloadMediaMessage,
|
|
2916
2931
|
downloadContentFromMessage,
|
|
@@ -2996,7 +3011,7 @@ async function downloadInboundMedia(msg, sock, opts) {
|
|
|
2996
3011
|
await mkdir(MEDIA_DIR, { recursive: true });
|
|
2997
3012
|
const ext = mimeToExt(mimetype ?? "application/octet-stream");
|
|
2998
3013
|
const filename = `${randomUUID2()}.${ext}`;
|
|
2999
|
-
const filePath =
|
|
3014
|
+
const filePath = join3(MEDIA_DIR, filename);
|
|
3000
3015
|
await writeFile(filePath, buffer);
|
|
3001
3016
|
const sizeKB = (buffer.length / 1024).toFixed(0);
|
|
3002
3017
|
console.error(`${TAG9} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
|
|
@@ -3727,11 +3742,11 @@ async function connectWithReconnect(conn) {
|
|
|
3727
3742
|
console.error(
|
|
3728
3743
|
`${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
3729
3744
|
);
|
|
3730
|
-
await new Promise((
|
|
3731
|
-
const timer2 = setTimeout(
|
|
3745
|
+
await new Promise((resolve30) => {
|
|
3746
|
+
const timer2 = setTimeout(resolve30, delay);
|
|
3732
3747
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
3733
3748
|
clearTimeout(timer2);
|
|
3734
|
-
|
|
3749
|
+
resolve30();
|
|
3735
3750
|
}, { once: true });
|
|
3736
3751
|
});
|
|
3737
3752
|
}
|
|
@@ -3739,16 +3754,16 @@ async function connectWithReconnect(conn) {
|
|
|
3739
3754
|
}
|
|
3740
3755
|
}
|
|
3741
3756
|
function waitForDisconnectEvent(conn) {
|
|
3742
|
-
return new Promise((
|
|
3757
|
+
return new Promise((resolve30) => {
|
|
3743
3758
|
if (!conn.sock) {
|
|
3744
|
-
|
|
3759
|
+
resolve30();
|
|
3745
3760
|
return;
|
|
3746
3761
|
}
|
|
3747
3762
|
const sock = conn.sock;
|
|
3748
3763
|
const handler = (update) => {
|
|
3749
3764
|
if (update.connection === "close") {
|
|
3750
3765
|
sock.ev.off("connection.update", handler);
|
|
3751
|
-
|
|
3766
|
+
resolve30();
|
|
3752
3767
|
}
|
|
3753
3768
|
};
|
|
3754
3769
|
sock.ev.on("connection.update", handler);
|
|
@@ -4008,8 +4023,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4008
4023
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
4009
4024
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
4010
4025
|
let resolvePending;
|
|
4011
|
-
const sttPending = new Promise((
|
|
4012
|
-
resolvePending =
|
|
4026
|
+
const sttPending = new Promise((resolve30) => {
|
|
4027
|
+
resolvePending = resolve30;
|
|
4013
4028
|
});
|
|
4014
4029
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
4015
4030
|
try {
|
|
@@ -4106,9 +4121,9 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4106
4121
|
import { spawnSync, execFileSync } from "child_process";
|
|
4107
4122
|
import { createConnection } from "net";
|
|
4108
4123
|
import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
4109
|
-
import { resolve as
|
|
4110
|
-
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ??
|
|
4111
|
-
var VNC_SCRIPT =
|
|
4124
|
+
import { resolve as resolve3 } from "path";
|
|
4125
|
+
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve3(process.cwd(), "..");
|
|
4126
|
+
var VNC_SCRIPT = resolve3(PLATFORM_ROOT2, "scripts/vnc.sh");
|
|
4112
4127
|
var displayMode = process.env.DISPLAY_MODE ?? "virtual";
|
|
4113
4128
|
if (displayMode === "native") {
|
|
4114
4129
|
console.log(`[vnc] DISPLAY_MODE=native \u2014 local requests use desktop display, remote requests use VNC`);
|
|
@@ -4221,7 +4236,7 @@ function ensureLogDir() {
|
|
|
4221
4236
|
mkdirSync(LOG_DIR, { recursive: true });
|
|
4222
4237
|
}
|
|
4223
4238
|
function logPath(name) {
|
|
4224
|
-
return
|
|
4239
|
+
return resolve3(LOG_DIR, `${name}.log`);
|
|
4225
4240
|
}
|
|
4226
4241
|
async function ensureVnc() {
|
|
4227
4242
|
const up = await waitForPort(RFB_PORT, 1e3);
|
|
@@ -4300,7 +4315,7 @@ function killChromium() {
|
|
|
4300
4315
|
}
|
|
4301
4316
|
function writeChromiumWrapper() {
|
|
4302
4317
|
mkdirSync(BIN_DIR, { recursive: true });
|
|
4303
|
-
const wrapperPath =
|
|
4318
|
+
const wrapperPath = resolve3(BIN_DIR, "chromium");
|
|
4304
4319
|
writeFileSync3(wrapperPath, `#!/bin/bash
|
|
4305
4320
|
LOG="${LOG_DIR}/chromium.log"
|
|
4306
4321
|
echo "==== [$(date)] chromium wrapper ====" >> "$LOG"
|
|
@@ -4400,20 +4415,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
4400
4415
|
|
|
4401
4416
|
// server/routes/health.ts
|
|
4402
4417
|
function checkPort(port2, timeoutMs = 500) {
|
|
4403
|
-
return new Promise((
|
|
4418
|
+
return new Promise((resolve30) => {
|
|
4404
4419
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
4405
4420
|
socket.setTimeout(timeoutMs);
|
|
4406
4421
|
socket.once("connect", () => {
|
|
4407
4422
|
socket.destroy();
|
|
4408
|
-
|
|
4423
|
+
resolve30(true);
|
|
4409
4424
|
});
|
|
4410
4425
|
socket.once("error", () => {
|
|
4411
4426
|
socket.destroy();
|
|
4412
|
-
|
|
4427
|
+
resolve30(false);
|
|
4413
4428
|
});
|
|
4414
4429
|
socket.once("timeout", () => {
|
|
4415
4430
|
socket.destroy();
|
|
4416
|
-
|
|
4431
|
+
resolve30(false);
|
|
4417
4432
|
});
|
|
4418
4433
|
});
|
|
4419
4434
|
}
|
|
@@ -4483,9 +4498,9 @@ var health_default = app;
|
|
|
4483
4498
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
4484
4499
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
4485
4500
|
import { realpathSync } from "fs";
|
|
4486
|
-
import { resolve as
|
|
4487
|
-
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ??
|
|
4488
|
-
var ATTACHMENTS_ROOT =
|
|
4501
|
+
import { resolve as resolve4, extname } from "path";
|
|
4502
|
+
var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve4(process.cwd(), "../platform");
|
|
4503
|
+
var ATTACHMENTS_ROOT = resolve4(PLATFORM_ROOT3, "..", "data/uploads");
|
|
4489
4504
|
var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
4490
4505
|
"image/jpeg",
|
|
4491
4506
|
"image/png",
|
|
@@ -4512,11 +4527,11 @@ function assertSupportedMime(mimeType) {
|
|
|
4512
4527
|
}
|
|
4513
4528
|
async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
|
|
4514
4529
|
const attachmentId = randomUUID3();
|
|
4515
|
-
const dir =
|
|
4530
|
+
const dir = resolve4(ATTACHMENTS_ROOT, scope, attachmentId);
|
|
4516
4531
|
await mkdir2(dir, { recursive: true });
|
|
4517
4532
|
const ext = extname(filename) || "";
|
|
4518
|
-
const storagePath =
|
|
4519
|
-
const metaPath =
|
|
4533
|
+
const storagePath = resolve4(dir, `${attachmentId}${ext}`);
|
|
4534
|
+
const metaPath = resolve4(dir, `${attachmentId}.meta.json`);
|
|
4520
4535
|
const meta = {
|
|
4521
4536
|
attachmentId,
|
|
4522
4537
|
scope,
|
|
@@ -4590,11 +4605,11 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
|
|
|
4590
4605
|
`Component artefact exceeds the 50 MB limit (${(buffer.byteLength / 1024 / 1024).toFixed(1)} MB).`
|
|
4591
4606
|
);
|
|
4592
4607
|
}
|
|
4593
|
-
const dir =
|
|
4608
|
+
const dir = resolve4(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
4594
4609
|
await mkdir2(dir, { recursive: true });
|
|
4595
4610
|
const ext = extname(filename) || (mimeType === "text/html" ? ".html" : ".md");
|
|
4596
|
-
const storagePath =
|
|
4597
|
-
const metaPath =
|
|
4611
|
+
const storagePath = resolve4(dir, `${attachmentId}${ext}`);
|
|
4612
|
+
const metaPath = resolve4(dir, `${attachmentId}.meta.json`);
|
|
4598
4613
|
const meta = {
|
|
4599
4614
|
attachmentId,
|
|
4600
4615
|
scope: accountId,
|
|
@@ -4611,7 +4626,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
|
|
|
4611
4626
|
// app/lib/stt/voice-note.ts
|
|
4612
4627
|
import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
|
|
4613
4628
|
import { tmpdir } from "os";
|
|
4614
|
-
import { join as
|
|
4629
|
+
import { join as join4 } from "path";
|
|
4615
4630
|
var TAG14 = "[voice]";
|
|
4616
4631
|
var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
4617
4632
|
"audio/ogg",
|
|
@@ -4655,9 +4670,9 @@ async function transcribeVoiceNote(file, source) {
|
|
|
4655
4670
|
let tempDir;
|
|
4656
4671
|
let tempPath;
|
|
4657
4672
|
try {
|
|
4658
|
-
tempDir = await mkdtemp(
|
|
4673
|
+
tempDir = await mkdtemp(join4(tmpdir(), "voice-"));
|
|
4659
4674
|
const ext = audioExtension(mimeType);
|
|
4660
|
-
tempPath =
|
|
4675
|
+
tempPath = join4(tempDir, `recording${ext}`);
|
|
4661
4676
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
4662
4677
|
await writeFile3(tempPath, buffer);
|
|
4663
4678
|
} catch (err) {
|
|
@@ -4698,7 +4713,7 @@ async function transcribeVoiceNote(file, source) {
|
|
|
4698
4713
|
}
|
|
4699
4714
|
|
|
4700
4715
|
// app/lib/channel-pty-bridge/bridge.ts
|
|
4701
|
-
import { resolve as
|
|
4716
|
+
import { resolve as resolve6 } from "path";
|
|
4702
4717
|
|
|
4703
4718
|
// app/lib/channel-pty-bridge/manager-client.ts
|
|
4704
4719
|
function managerBase() {
|
|
@@ -5150,7 +5165,7 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
5150
5165
|
// app/lib/whatsapp/outbound/send-document.ts
|
|
5151
5166
|
import { realpathSync as realpathSync2 } from "fs";
|
|
5152
5167
|
import { readFile, stat as stat2 } from "fs/promises";
|
|
5153
|
-
import { resolve as
|
|
5168
|
+
import { resolve as resolve5, basename } from "path";
|
|
5154
5169
|
var TAG16 = "[whatsapp:outbound]";
|
|
5155
5170
|
var WHATSAPP_DOCUMENT_MAX_BYTES = 100 * 1024 * 1024;
|
|
5156
5171
|
var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
|
|
@@ -5181,7 +5196,7 @@ async function sendWhatsAppDocument(input) {
|
|
|
5181
5196
|
if (!maxyAccountId || !platformRoot2) {
|
|
5182
5197
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
5183
5198
|
}
|
|
5184
|
-
const accountDir =
|
|
5199
|
+
const accountDir = resolve5(platformRoot2, "..", "data/accounts", maxyAccountId);
|
|
5185
5200
|
let resolvedPath;
|
|
5186
5201
|
try {
|
|
5187
5202
|
resolvedPath = realpathSync2(filePath);
|
|
@@ -5388,7 +5403,7 @@ async function ensureEntry(input) {
|
|
|
5388
5403
|
});
|
|
5389
5404
|
} else {
|
|
5390
5405
|
console.error(`${tag} route role=${input.role} target=public-spawn senderId=${input.senderId}`);
|
|
5391
|
-
const attachmentDir =
|
|
5406
|
+
const attachmentDir = resolve6(ATTACHMENTS_ROOT, "public", input.senderId);
|
|
5392
5407
|
spawned = await managerSpawn({
|
|
5393
5408
|
senderId: input.senderId,
|
|
5394
5409
|
role: input.role,
|
|
@@ -5520,12 +5535,12 @@ async function dispatchOnce(input) {
|
|
|
5520
5535
|
});
|
|
5521
5536
|
if (!entry) return { error: "spawn-failed" };
|
|
5522
5537
|
entry.lastInboundAt = Date.now();
|
|
5523
|
-
let
|
|
5538
|
+
let resolve30;
|
|
5524
5539
|
const turnPromise = new Promise((r) => {
|
|
5525
|
-
|
|
5540
|
+
resolve30 = r;
|
|
5526
5541
|
});
|
|
5527
5542
|
const listener = (text) => {
|
|
5528
|
-
|
|
5543
|
+
resolve30(text);
|
|
5529
5544
|
};
|
|
5530
5545
|
entry.subscribers.add(listener);
|
|
5531
5546
|
const writeAtMs = Date.now();
|
|
@@ -5895,7 +5910,7 @@ ${result.result.text}` : result.result.text;
|
|
|
5895
5910
|
var chat_default = app2;
|
|
5896
5911
|
|
|
5897
5912
|
// server/routes/whatsapp.ts
|
|
5898
|
-
import { join as
|
|
5913
|
+
import { join as join7, resolve as resolve8 } from "path";
|
|
5899
5914
|
import { readdirSync as readdirSync3, readFileSync as readFileSync7, existsSync as existsSync5 } from "fs";
|
|
5900
5915
|
|
|
5901
5916
|
// app/lib/whatsapp/login.ts
|
|
@@ -5903,10 +5918,10 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
5903
5918
|
|
|
5904
5919
|
// app/lib/whatsapp/config-persist.ts
|
|
5905
5920
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
|
|
5906
|
-
import { resolve as
|
|
5921
|
+
import { resolve as resolve7, join as join5 } from "path";
|
|
5907
5922
|
var TAG18 = "[whatsapp:config]";
|
|
5908
5923
|
function configPath(accountDir) {
|
|
5909
|
-
return
|
|
5924
|
+
return resolve7(accountDir, "account.json");
|
|
5910
5925
|
}
|
|
5911
5926
|
function readConfig(accountDir) {
|
|
5912
5927
|
const path2 = configPath(accountDir);
|
|
@@ -6055,7 +6070,7 @@ function setPublicAgent(accountDir, slug) {
|
|
|
6055
6070
|
if (!trimmed) {
|
|
6056
6071
|
return { ok: false, error: "Agent slug cannot be empty." };
|
|
6057
6072
|
}
|
|
6058
|
-
const agentConfigPath =
|
|
6073
|
+
const agentConfigPath = join5(accountDir, "agents", trimmed, "config.json");
|
|
6059
6074
|
if (!existsSync4(agentConfigPath)) {
|
|
6060
6075
|
return { ok: false, error: `Agent "${trimmed}" not found \u2014 no config.json at ${agentConfigPath}. Check the agent slug and try again.` };
|
|
6061
6076
|
}
|
|
@@ -6313,8 +6328,8 @@ async function startLogin(opts) {
|
|
|
6313
6328
|
await clearAuth(authDir);
|
|
6314
6329
|
let resolveCode = null;
|
|
6315
6330
|
let rejectCode = null;
|
|
6316
|
-
const codePromise = new Promise((
|
|
6317
|
-
resolveCode =
|
|
6331
|
+
const codePromise = new Promise((resolve30, reject) => {
|
|
6332
|
+
resolveCode = resolve30;
|
|
6318
6333
|
rejectCode = reject;
|
|
6319
6334
|
});
|
|
6320
6335
|
const codeTimer = setTimeout(
|
|
@@ -6546,11 +6561,11 @@ function serializeWhatsAppSchema() {
|
|
|
6546
6561
|
|
|
6547
6562
|
// app/lib/whatsapp/status-reconcile.ts
|
|
6548
6563
|
import { readdirSync as readdirSync2 } from "fs";
|
|
6549
|
-
import { join as
|
|
6564
|
+
import { join as join6 } from "path";
|
|
6550
6565
|
var TAG20 = "[whatsapp:reconcile]";
|
|
6551
6566
|
function listCredsAccountIds(credsRoot) {
|
|
6552
6567
|
try {
|
|
6553
|
-
return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(
|
|
6568
|
+
return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join6(credsRoot, e.name))).map((e) => e.name);
|
|
6554
6569
|
} catch {
|
|
6555
6570
|
return [];
|
|
6556
6571
|
}
|
|
@@ -6565,7 +6580,7 @@ function reconcileCredsOnDisk(opts) {
|
|
|
6565
6580
|
const entries = [];
|
|
6566
6581
|
for (const accountId of listCredsAccountIds(credsRoot)) {
|
|
6567
6582
|
if (liveAccountIds.has(accountId)) continue;
|
|
6568
|
-
const authDir =
|
|
6583
|
+
const authDir = join6(credsRoot, accountId);
|
|
6569
6584
|
const selfPhone = readSelfId(authDir).e164 ?? void 0;
|
|
6570
6585
|
const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
|
|
6571
6586
|
console.error(
|
|
@@ -6592,7 +6607,7 @@ app3.get("/status", (c) => {
|
|
|
6592
6607
|
try {
|
|
6593
6608
|
const live = getStatus();
|
|
6594
6609
|
const liveIds = new Set(live.map((a) => a.accountId));
|
|
6595
|
-
const credsRoot =
|
|
6610
|
+
const credsRoot = join7(MAXY_DIR, "credentials", "whatsapp");
|
|
6596
6611
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
6597
6612
|
const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
|
|
6598
6613
|
const accounts = [...live, ...reconciled];
|
|
@@ -6613,7 +6628,7 @@ app3.post("/login/start", async (c) => {
|
|
|
6613
6628
|
if (!phone) {
|
|
6614
6629
|
return c.json({ error: 'Missing required field "phone" (E.164, e.g. +441234567890).' }, 400);
|
|
6615
6630
|
}
|
|
6616
|
-
const authDir =
|
|
6631
|
+
const authDir = join7(MAXY_DIR, "credentials", "whatsapp", accountId);
|
|
6617
6632
|
const accountDir = resolveAccount()?.accountDir ?? null;
|
|
6618
6633
|
const result = await startLogin({ accountId, authDir, phone, accountDir, force });
|
|
6619
6634
|
console.error(`${TAG21} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
|
|
@@ -6711,14 +6726,14 @@ app3.post("/config", async (c) => {
|
|
|
6711
6726
|
return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
|
|
6712
6727
|
}
|
|
6713
6728
|
case "list-public-agents": {
|
|
6714
|
-
const agentsDir =
|
|
6729
|
+
const agentsDir = resolve8(account.accountDir, "agents");
|
|
6715
6730
|
const agents = [];
|
|
6716
6731
|
if (existsSync5(agentsDir)) {
|
|
6717
6732
|
try {
|
|
6718
6733
|
const entries = readdirSync3(agentsDir, { withFileTypes: true });
|
|
6719
6734
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6720
6735
|
if (!entry.isDirectory() || entry.name === "admin") continue;
|
|
6721
|
-
const configPath2 =
|
|
6736
|
+
const configPath2 = resolve8(agentsDir, entry.name, "config.json");
|
|
6722
6737
|
if (!existsSync5(configPath2)) continue;
|
|
6723
6738
|
try {
|
|
6724
6739
|
const config = JSON.parse(readFileSync7(configPath2, "utf-8"));
|
|
@@ -6991,11 +7006,11 @@ var whatsapp_default = app3;
|
|
|
6991
7006
|
|
|
6992
7007
|
// server/routes/whatsapp-reader.ts
|
|
6993
7008
|
import { readFileSync as readFileSync10, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync6 } from "fs";
|
|
6994
|
-
import { basename as basename2, dirname, join as
|
|
7009
|
+
import { basename as basename2, dirname, join as join10, resolve as resolve10, sep as sep2 } from "path";
|
|
6995
7010
|
|
|
6996
7011
|
// server/routes/admin/sidebar-sessions.ts
|
|
6997
7012
|
import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
6998
|
-
import { join as
|
|
7013
|
+
import { join as join8, resolve as resolve9 } from "path";
|
|
6999
7014
|
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;
|
|
7000
7015
|
var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
|
|
7001
7016
|
var PUBLIC_ROLE = "public";
|
|
@@ -7014,7 +7029,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
7014
7029
|
throw err;
|
|
7015
7030
|
}
|
|
7016
7031
|
for (const slug of slugs) {
|
|
7017
|
-
const slugDir =
|
|
7032
|
+
const slugDir = join8(projectsRoot, slug);
|
|
7018
7033
|
let entries;
|
|
7019
7034
|
try {
|
|
7020
7035
|
entries = readdirSync4(slugDir, { withFileTypes: true });
|
|
@@ -7025,9 +7040,9 @@ function enumerateJsonls(projectsRoot) {
|
|
|
7025
7040
|
}
|
|
7026
7041
|
for (const entry of entries) {
|
|
7027
7042
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
7028
|
-
out.push({ path:
|
|
7043
|
+
out.push({ path: join8(slugDir, entry.name), isSubagent: false, archived: false });
|
|
7029
7044
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
7030
|
-
const subDir =
|
|
7045
|
+
const subDir = join8(slugDir, entry.name);
|
|
7031
7046
|
let subEntries;
|
|
7032
7047
|
try {
|
|
7033
7048
|
subEntries = readdirSync4(subDir, { withFileTypes: true });
|
|
@@ -7038,11 +7053,11 @@ function enumerateJsonls(projectsRoot) {
|
|
|
7038
7053
|
}
|
|
7039
7054
|
for (const sub of subEntries) {
|
|
7040
7055
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
7041
|
-
out.push({ path:
|
|
7056
|
+
out.push({ path: join8(subDir, sub.name), isSubagent: true, archived: false });
|
|
7042
7057
|
}
|
|
7043
7058
|
}
|
|
7044
7059
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
7045
|
-
const archiveDir =
|
|
7060
|
+
const archiveDir = join8(slugDir, entry.name);
|
|
7046
7061
|
let archiveEntries;
|
|
7047
7062
|
try {
|
|
7048
7063
|
archiveEntries = readdirSync4(archiveDir, { withFileTypes: true });
|
|
@@ -7053,7 +7068,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
7053
7068
|
}
|
|
7054
7069
|
for (const arc of archiveEntries) {
|
|
7055
7070
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
7056
|
-
out.push({ path:
|
|
7071
|
+
out.push({ path: join8(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
7057
7072
|
}
|
|
7058
7073
|
}
|
|
7059
7074
|
}
|
|
@@ -7086,7 +7101,7 @@ async function fetchLiveSessions() {
|
|
|
7086
7101
|
function loadUserTitles(accountDir) {
|
|
7087
7102
|
const out = /* @__PURE__ */ new Map();
|
|
7088
7103
|
if (!accountDir) return out;
|
|
7089
|
-
const path2 =
|
|
7104
|
+
const path2 = join8(accountDir, "session-titles.json");
|
|
7090
7105
|
let raw;
|
|
7091
7106
|
try {
|
|
7092
7107
|
raw = readFileSync8(path2, "utf8");
|
|
@@ -7183,10 +7198,10 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
7183
7198
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
7184
7199
|
return c.json({ sessions: [], accountId });
|
|
7185
7200
|
}
|
|
7186
|
-
const projectsRoot =
|
|
7201
|
+
const projectsRoot = join8(configDir2, "projects");
|
|
7187
7202
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
7188
7203
|
const liveSessions = await fetchLiveSessions();
|
|
7189
|
-
const accountDir = accountId ?
|
|
7204
|
+
const accountDir = accountId ? resolve9(ACCOUNTS_DIR, accountId) : null;
|
|
7190
7205
|
const userTitles = loadUserTitles(accountDir);
|
|
7191
7206
|
const rows = [];
|
|
7192
7207
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -7217,7 +7232,7 @@ app4.get("/", requireAdminSession, async (c) => {
|
|
|
7217
7232
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
7218
7233
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
7219
7234
|
titleSourceCounts[resolved.source] += 1;
|
|
7220
|
-
const metaPath =
|
|
7235
|
+
const metaPath = join8(projectDir, `${sessionId}.meta.json`);
|
|
7221
7236
|
const { bridgeIds, role, channel } = readSidecarMeta(metaPath);
|
|
7222
7237
|
const resumable = !(role === PUBLIC_ROLE && channel === WEBCHAT_CHANNEL);
|
|
7223
7238
|
rows.push({
|
|
@@ -7264,7 +7279,7 @@ function selectAdminChannelSessions(rows) {
|
|
|
7264
7279
|
// app/lib/admin-identity/pin-validator.ts
|
|
7265
7280
|
import { createHash as createHash2 } from "crypto";
|
|
7266
7281
|
import { existsSync as existsSync6, readFileSync as readFileSync9, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
7267
|
-
import { join as
|
|
7282
|
+
import { join as join9 } from "path";
|
|
7268
7283
|
function hashPin(pin) {
|
|
7269
7284
|
return createHash2("sha256").update(pin).digest("hex");
|
|
7270
7285
|
}
|
|
@@ -7298,13 +7313,13 @@ function scanForOrphanedAccountAdmins(users, accountsDir) {
|
|
|
7298
7313
|
}
|
|
7299
7314
|
for (const entry of entries) {
|
|
7300
7315
|
if (entry.startsWith(".")) continue;
|
|
7301
|
-
const accountDir =
|
|
7316
|
+
const accountDir = join9(accountsDir, entry);
|
|
7302
7317
|
try {
|
|
7303
7318
|
if (!statSync3(accountDir).isDirectory()) continue;
|
|
7304
7319
|
} catch {
|
|
7305
7320
|
continue;
|
|
7306
7321
|
}
|
|
7307
|
-
const accountJsonPath =
|
|
7322
|
+
const accountJsonPath = join9(accountDir, "account.json");
|
|
7308
7323
|
if (!existsSync6(accountJsonPath)) continue;
|
|
7309
7324
|
try {
|
|
7310
7325
|
const config = JSON.parse(readFileSync9(accountJsonPath, "utf-8"));
|
|
@@ -7484,13 +7499,13 @@ var app5 = new Hono();
|
|
|
7484
7499
|
app5.get("/conversations", requireAdminSession, async (c) => {
|
|
7485
7500
|
const cfg = claudeConfigDir();
|
|
7486
7501
|
if (!cfg) return c.json({ conversations: [] });
|
|
7487
|
-
const projectsRoot =
|
|
7502
|
+
const projectsRoot = join10(cfg, "projects");
|
|
7488
7503
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
7489
7504
|
const rows = [];
|
|
7490
7505
|
for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
|
|
7491
7506
|
const sessionId = basename2(path2).replace(/\.jsonl$/, "");
|
|
7492
7507
|
const projectDir = dirname(path2);
|
|
7493
|
-
const meta = readSidecarMeta(
|
|
7508
|
+
const meta = readSidecarMeta(join10(projectDir, `${sessionId}.meta.json`));
|
|
7494
7509
|
if (meta.role !== "admin" || meta.channel !== "whatsapp" && meta.channel !== "telegram") continue;
|
|
7495
7510
|
let body = "";
|
|
7496
7511
|
try {
|
|
@@ -7577,11 +7592,11 @@ app5.get("/stream", requireAdminSession, (c) => {
|
|
|
7577
7592
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
7578
7593
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
7579
7594
|
const cfg = claudeConfigDir();
|
|
7580
|
-
const projectsRoot = cfg ?
|
|
7595
|
+
const projectsRoot = cfg ? resolve10(join10(cfg, "projects")) : null;
|
|
7581
7596
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
7582
7597
|
return c.json({ error: "bad session reference" }, 400);
|
|
7583
7598
|
}
|
|
7584
|
-
const jsonlPath =
|
|
7599
|
+
const jsonlPath = resolve10(join10(projectDir, `${sessionId}.jsonl`));
|
|
7585
7600
|
if (!jsonlPath.startsWith(projectsRoot + sep2)) {
|
|
7586
7601
|
return c.json({ error: "bad session reference" }, 400);
|
|
7587
7602
|
}
|
|
@@ -7668,7 +7683,7 @@ var DIRECTIVE_NAME_RE = /^\d+-\d+\.txt$/;
|
|
|
7668
7683
|
function directiveStoreDir(sessionId) {
|
|
7669
7684
|
const account = resolveAccount();
|
|
7670
7685
|
if (!account) return null;
|
|
7671
|
-
return
|
|
7686
|
+
return resolve10(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
|
|
7672
7687
|
}
|
|
7673
7688
|
app5.get("/directives", requireAdminSession, (c) => {
|
|
7674
7689
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
@@ -7687,7 +7702,7 @@ app5.get("/directives", requireAdminSession, (c) => {
|
|
|
7687
7702
|
const pid = Number(pidPart);
|
|
7688
7703
|
let len = 0;
|
|
7689
7704
|
try {
|
|
7690
|
-
len = statSync4(
|
|
7705
|
+
len = statSync4(join10(dir, name)).size;
|
|
7691
7706
|
} catch {
|
|
7692
7707
|
}
|
|
7693
7708
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -7702,7 +7717,7 @@ app5.get("/directive", requireAdminSession, (c) => {
|
|
|
7702
7717
|
}
|
|
7703
7718
|
const dir = directiveStoreDir(sessionId);
|
|
7704
7719
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
7705
|
-
const path2 =
|
|
7720
|
+
const path2 = resolve10(join10(dir, name));
|
|
7706
7721
|
if (!path2.startsWith(dir + sep2)) return c.json({ error: "bad reference" }, 400);
|
|
7707
7722
|
let body;
|
|
7708
7723
|
try {
|
|
@@ -7716,17 +7731,17 @@ var whatsapp_reader_default = app5;
|
|
|
7716
7731
|
|
|
7717
7732
|
// server/routes/webchat.ts
|
|
7718
7733
|
import { basename as basename3, dirname as dirname2 } from "path";
|
|
7719
|
-
import { join as
|
|
7734
|
+
import { join as join11 } from "path";
|
|
7720
7735
|
import { readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync5 } from "fs";
|
|
7721
7736
|
var WEBCHAT_ADMIN_KEY = "webchat-admin";
|
|
7722
7737
|
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
7723
7738
|
function locateSession(sessionId) {
|
|
7724
7739
|
const cfg = claudeConfigDir();
|
|
7725
7740
|
if (!cfg) return { projectDir: null, channel: null };
|
|
7726
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
7741
|
+
for (const { path: path2 } of enumerateJsonls(join11(cfg, "projects"))) {
|
|
7727
7742
|
if (basename3(path2) === `${sessionId}.jsonl`) {
|
|
7728
7743
|
const dir = dirname2(path2);
|
|
7729
|
-
const meta = readSidecarMeta(
|
|
7744
|
+
const meta = readSidecarMeta(join11(dir, `${sessionId}.meta.json`));
|
|
7730
7745
|
return { projectDir: dir, channel: meta.channel };
|
|
7731
7746
|
}
|
|
7732
7747
|
}
|
|
@@ -7958,7 +7973,7 @@ ${note}` : note;
|
|
|
7958
7973
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
7959
7974
|
return c.json({ error: "account unresolved" }, 503);
|
|
7960
7975
|
}
|
|
7961
|
-
const accountJsonPath =
|
|
7976
|
+
const accountJsonPath = join11(account.accountDir, "account.json");
|
|
7962
7977
|
try {
|
|
7963
7978
|
const parsed = JSON.parse(readFileSync11(accountJsonPath, "utf8"));
|
|
7964
7979
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -7998,7 +8013,7 @@ ${note}` : note;
|
|
|
7998
8013
|
const cfg = claudeConfigDir();
|
|
7999
8014
|
let projectDir = null;
|
|
8000
8015
|
if (cfg) {
|
|
8001
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
8016
|
+
for (const { path: path2 } of enumerateJsonls(join11(cfg, "projects"))) {
|
|
8002
8017
|
if (basename3(path2) === `${sessionId}.jsonl`) {
|
|
8003
8018
|
projectDir = dirname2(path2);
|
|
8004
8019
|
break;
|
|
@@ -8012,11 +8027,11 @@ ${note}` : note;
|
|
|
8012
8027
|
}
|
|
8013
8028
|
|
|
8014
8029
|
// server/routes/webchat-greeting.ts
|
|
8015
|
-
import { resolve as
|
|
8030
|
+
import { resolve as resolve11 } from "path";
|
|
8016
8031
|
|
|
8017
8032
|
// app/lib/claude-agent/specialist-roster.ts
|
|
8018
8033
|
import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
|
|
8019
|
-
import { join as
|
|
8034
|
+
import { join as join12 } from "path";
|
|
8020
8035
|
function field(fm, name) {
|
|
8021
8036
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
8022
8037
|
if (!m) return null;
|
|
@@ -8035,7 +8050,7 @@ function readSpecialistRoster(specialistsDir) {
|
|
|
8035
8050
|
if (!file.endsWith(".md")) continue;
|
|
8036
8051
|
let raw;
|
|
8037
8052
|
try {
|
|
8038
|
-
raw = readFileSync12(
|
|
8053
|
+
raw = readFileSync12(join12(specialistsDir, file), "utf-8");
|
|
8039
8054
|
} catch (err) {
|
|
8040
8055
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
8041
8056
|
continue;
|
|
@@ -8117,7 +8132,7 @@ app6.get("/", requireAdminSession, async (c) => {
|
|
|
8117
8132
|
let specialists = [];
|
|
8118
8133
|
try {
|
|
8119
8134
|
const roster = readSpecialistRoster(
|
|
8120
|
-
|
|
8135
|
+
resolve11(ACCOUNTS_DIR, accountId, "specialists", "agents")
|
|
8121
8136
|
);
|
|
8122
8137
|
specialists = roster.specialists;
|
|
8123
8138
|
for (const s of roster.skipped) {
|
|
@@ -8152,7 +8167,7 @@ var webchat_greeting_default = app6;
|
|
|
8152
8167
|
|
|
8153
8168
|
// server/routes/telegram.ts
|
|
8154
8169
|
import { homedir } from "os";
|
|
8155
|
-
import { resolve as
|
|
8170
|
+
import { resolve as resolve12, join as join13 } from "path";
|
|
8156
8171
|
import { existsSync as existsSync9, readFileSync as readFileSync13 } from "fs";
|
|
8157
8172
|
|
|
8158
8173
|
// app/lib/telegram/access-control.ts
|
|
@@ -8203,8 +8218,8 @@ function routeTelegramUpdate(input) {
|
|
|
8203
8218
|
var TAG22 = "[telegram-inbound]";
|
|
8204
8219
|
var DISPATCH_TIMEOUT_MS = 12e4;
|
|
8205
8220
|
function configDirName() {
|
|
8206
|
-
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ??
|
|
8207
|
-
const brandPath =
|
|
8221
|
+
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
|
|
8222
|
+
const brandPath = join13(platformRoot2, "config", "brand.json");
|
|
8208
8223
|
if (existsSync9(brandPath)) {
|
|
8209
8224
|
try {
|
|
8210
8225
|
return JSON.parse(readFileSync13(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
@@ -8215,7 +8230,7 @@ function configDirName() {
|
|
|
8215
8230
|
}
|
|
8216
8231
|
function secretPath(botType) {
|
|
8217
8232
|
const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
|
|
8218
|
-
return
|
|
8233
|
+
return resolve12(homedir(), configDirName(), filename);
|
|
8219
8234
|
}
|
|
8220
8235
|
async function sendTelegram(botToken, chatId, text) {
|
|
8221
8236
|
try {
|
|
@@ -8311,7 +8326,7 @@ import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
|
|
|
8311
8326
|
|
|
8312
8327
|
// ../lib/admins-write/src/index.ts
|
|
8313
8328
|
import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync6, renameSync as renameSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
|
|
8314
|
-
import { dirname as dirname3, join as
|
|
8329
|
+
import { dirname as dirname3, join as join14 } from "path";
|
|
8315
8330
|
function logLine(input, result) {
|
|
8316
8331
|
const userIdShort = input.userId.slice(0, 8);
|
|
8317
8332
|
console.error(
|
|
@@ -8353,7 +8368,7 @@ function writeAdminEntry(input) {
|
|
|
8353
8368
|
return result;
|
|
8354
8369
|
}
|
|
8355
8370
|
try {
|
|
8356
|
-
const accountJsonPath =
|
|
8371
|
+
const accountJsonPath = join14(input.accountDir, "account.json");
|
|
8357
8372
|
if (!existsSync10(accountJsonPath)) {
|
|
8358
8373
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
8359
8374
|
}
|
|
@@ -8408,13 +8423,13 @@ function checkAdminAuthInvariant(input) {
|
|
|
8408
8423
|
}
|
|
8409
8424
|
for (const entry of entries) {
|
|
8410
8425
|
if (entry.startsWith(".")) continue;
|
|
8411
|
-
const accountDir =
|
|
8426
|
+
const accountDir = join14(input.accountsDir, entry);
|
|
8412
8427
|
try {
|
|
8413
8428
|
if (!statSync5(accountDir).isDirectory()) continue;
|
|
8414
8429
|
} catch {
|
|
8415
8430
|
continue;
|
|
8416
8431
|
}
|
|
8417
|
-
const accountJsonPath =
|
|
8432
|
+
const accountJsonPath = join14(accountDir, "account.json");
|
|
8418
8433
|
if (!existsSync10(accountJsonPath)) continue;
|
|
8419
8434
|
let admins = [];
|
|
8420
8435
|
try {
|
|
@@ -8703,8 +8718,8 @@ var onboarding_default = app8;
|
|
|
8703
8718
|
|
|
8704
8719
|
// server/routes/client-error.ts
|
|
8705
8720
|
import { appendFileSync, existsSync as existsSync12, renameSync as renameSync3, statSync as statSync6 } from "fs";
|
|
8706
|
-
import { join as
|
|
8707
|
-
var CLIENT_ERRORS_LOG =
|
|
8721
|
+
import { join as join15 } from "path";
|
|
8722
|
+
var CLIENT_ERRORS_LOG = join15(LOG_DIR, "client-errors.log");
|
|
8708
8723
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
8709
8724
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
8710
8725
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -9030,16 +9045,16 @@ var session_default = app10;
|
|
|
9030
9045
|
|
|
9031
9046
|
// server/routes/admin/logs.ts
|
|
9032
9047
|
import { existsSync as existsSync14, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
|
|
9033
|
-
import { resolve as
|
|
9048
|
+
import { resolve as resolve13, basename as basename4 } from "path";
|
|
9034
9049
|
|
|
9035
9050
|
// app/lib/logs-read-resolve.ts
|
|
9036
9051
|
import { existsSync as existsSync13 } from "fs";
|
|
9037
|
-
import { join as
|
|
9052
|
+
import { join as join16 } from "path";
|
|
9038
9053
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
9039
9054
|
const tried = [filename];
|
|
9040
9055
|
const hits = [];
|
|
9041
9056
|
for (const dir of logDirs) {
|
|
9042
|
-
const fullPath =
|
|
9057
|
+
const fullPath = join16(dir, filename);
|
|
9043
9058
|
if (existsSync13(fullPath)) {
|
|
9044
9059
|
hits.push({ path: fullPath, dir });
|
|
9045
9060
|
}
|
|
@@ -9057,7 +9072,7 @@ app11.get("/", async (c) => {
|
|
|
9057
9072
|
const cacheKeyParam = c.req.query("cacheKey");
|
|
9058
9073
|
const download = c.req.query("download") === "1";
|
|
9059
9074
|
const account = resolveAccount();
|
|
9060
|
-
const accountLogDir = account ?
|
|
9075
|
+
const accountLogDir = account ? resolve13(account.accountDir, "logs") : null;
|
|
9061
9076
|
const logDirs = [];
|
|
9062
9077
|
if (accountLogDir) logDirs.push(accountLogDir);
|
|
9063
9078
|
logDirs.push(LOG_DIR);
|
|
@@ -9065,7 +9080,7 @@ app11.get("/", async (c) => {
|
|
|
9065
9080
|
const safe = basename4(fileParam);
|
|
9066
9081
|
const searched = [];
|
|
9067
9082
|
for (const dir of logDirs) {
|
|
9068
|
-
const filePath =
|
|
9083
|
+
const filePath = resolve13(dir, safe);
|
|
9069
9084
|
searched.push(filePath);
|
|
9070
9085
|
try {
|
|
9071
9086
|
const buffer = readFileSync16(filePath);
|
|
@@ -9177,10 +9192,10 @@ app11.get("/", async (c) => {
|
|
|
9177
9192
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
9178
9193
|
continue;
|
|
9179
9194
|
}
|
|
9180
|
-
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(
|
|
9195
|
+
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve13(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
9181
9196
|
seen.add(name);
|
|
9182
9197
|
try {
|
|
9183
|
-
const content = readFileSync16(
|
|
9198
|
+
const content = readFileSync16(resolve13(dir, name));
|
|
9184
9199
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
9185
9200
|
logs[name] = tail.trim() || "(empty)";
|
|
9186
9201
|
} catch (err) {
|
|
@@ -9220,7 +9235,7 @@ var claude_info_default = app12;
|
|
|
9220
9235
|
// server/routes/admin/attachment.ts
|
|
9221
9236
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
9222
9237
|
import { existsSync as existsSync15 } from "fs";
|
|
9223
|
-
import { resolve as
|
|
9238
|
+
import { resolve as resolve14 } from "path";
|
|
9224
9239
|
var app13 = new Hono();
|
|
9225
9240
|
app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
9226
9241
|
const attachmentId = c.req.param("attachmentId");
|
|
@@ -9232,11 +9247,11 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9232
9247
|
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
|
|
9233
9248
|
return new Response("Not found", { status: 404 });
|
|
9234
9249
|
}
|
|
9235
|
-
const dir =
|
|
9250
|
+
const dir = resolve14(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
9236
9251
|
if (!existsSync15(dir)) {
|
|
9237
9252
|
return new Response("Not found", { status: 404 });
|
|
9238
9253
|
}
|
|
9239
|
-
const metaPath =
|
|
9254
|
+
const metaPath = resolve14(dir, `${attachmentId}.meta.json`);
|
|
9240
9255
|
if (!existsSync15(metaPath)) {
|
|
9241
9256
|
return new Response("Not found", { status: 404 });
|
|
9242
9257
|
}
|
|
@@ -9251,7 +9266,7 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9251
9266
|
if (!dataFile) {
|
|
9252
9267
|
return new Response("Not found", { status: 404 });
|
|
9253
9268
|
}
|
|
9254
|
-
const filePath =
|
|
9269
|
+
const filePath = resolve14(dir, dataFile);
|
|
9255
9270
|
const buffer = await readFile2(filePath);
|
|
9256
9271
|
return new Response(new Uint8Array(buffer), {
|
|
9257
9272
|
headers: {
|
|
@@ -9264,13 +9279,13 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
9264
9279
|
var attachment_default = app13;
|
|
9265
9280
|
|
|
9266
9281
|
// server/routes/admin/agents.ts
|
|
9267
|
-
import { resolve as
|
|
9282
|
+
import { resolve as resolve15 } from "path";
|
|
9268
9283
|
import { readdirSync as readdirSync10, readFileSync as readFileSync17, existsSync as existsSync16, rmSync } from "fs";
|
|
9269
9284
|
var app14 = new Hono();
|
|
9270
9285
|
app14.get("/", (c) => {
|
|
9271
9286
|
const account = resolveAccount();
|
|
9272
9287
|
if (!account) return c.json({ agents: [] });
|
|
9273
|
-
const agentsDir =
|
|
9288
|
+
const agentsDir = resolve15(account.accountDir, "agents");
|
|
9274
9289
|
if (!existsSync16(agentsDir)) return c.json({ agents: [] });
|
|
9275
9290
|
const agents = [];
|
|
9276
9291
|
try {
|
|
@@ -9278,7 +9293,7 @@ app14.get("/", (c) => {
|
|
|
9278
9293
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
9279
9294
|
if (!entry.isDirectory()) continue;
|
|
9280
9295
|
if (entry.name === "admin") continue;
|
|
9281
|
-
const configPath2 =
|
|
9296
|
+
const configPath2 = resolve15(agentsDir, entry.name, "config.json");
|
|
9282
9297
|
if (!existsSync16(configPath2)) continue;
|
|
9283
9298
|
try {
|
|
9284
9299
|
const config = JSON.parse(readFileSync17(configPath2, "utf-8"));
|
|
@@ -9307,7 +9322,7 @@ app14.delete("/:slug", async (c) => {
|
|
|
9307
9322
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
9308
9323
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
9309
9324
|
}
|
|
9310
|
-
const agentDir =
|
|
9325
|
+
const agentDir = resolve15(account.accountDir, "agents", slug);
|
|
9311
9326
|
if (!existsSync16(agentDir)) {
|
|
9312
9327
|
return c.json({ error: "Agent not found" }, 404);
|
|
9313
9328
|
}
|
|
@@ -9337,7 +9352,7 @@ app14.post("/:slug/project", async (c) => {
|
|
|
9337
9352
|
if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
|
|
9338
9353
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
9339
9354
|
}
|
|
9340
|
-
const agentDir =
|
|
9355
|
+
const agentDir = resolve15(account.accountDir, "agents", slug);
|
|
9341
9356
|
if (!existsSync16(agentDir)) {
|
|
9342
9357
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
9343
9358
|
}
|
|
@@ -10041,7 +10056,7 @@ var sessions_default = app15;
|
|
|
10041
10056
|
|
|
10042
10057
|
// app/lib/claude-agent/spawn-context.ts
|
|
10043
10058
|
import { existsSync as existsSync18, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync8 } from "fs";
|
|
10044
|
-
import { dirname as dirname4, resolve as
|
|
10059
|
+
import { dirname as dirname4, resolve as resolve16, join as join17 } from "path";
|
|
10045
10060
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
10046
10061
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
10047
10062
|
try {
|
|
@@ -10070,8 +10085,8 @@ function frontmatterField(manifest, field2) {
|
|
|
10070
10085
|
function extractPluginToolDescriptions(pluginDir) {
|
|
10071
10086
|
const out = /* @__PURE__ */ new Map();
|
|
10072
10087
|
const candidates = [
|
|
10073
|
-
|
|
10074
|
-
|
|
10088
|
+
join17(pluginDir, "mcp/dist/index.js"),
|
|
10089
|
+
join17(pluginDir, "mcp/src/index.ts")
|
|
10075
10090
|
];
|
|
10076
10091
|
let raw = null;
|
|
10077
10092
|
for (const path2 of candidates) {
|
|
@@ -10126,24 +10141,24 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
10126
10141
|
}
|
|
10127
10142
|
function listPluginDirs() {
|
|
10128
10143
|
const out = /* @__PURE__ */ new Map();
|
|
10129
|
-
const platformPlugins =
|
|
10144
|
+
const platformPlugins = resolve16(PLATFORM_ROOT, "plugins");
|
|
10130
10145
|
if (existsSync18(platformPlugins)) {
|
|
10131
10146
|
for (const name of readdirSync11(platformPlugins)) {
|
|
10132
|
-
const dir =
|
|
10147
|
+
const dir = join17(platformPlugins, name);
|
|
10133
10148
|
try {
|
|
10134
10149
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
10135
10150
|
} catch {
|
|
10136
10151
|
}
|
|
10137
10152
|
}
|
|
10138
10153
|
}
|
|
10139
|
-
const premiumRoot =
|
|
10154
|
+
const premiumRoot = resolve16(dirname4(PLATFORM_ROOT), "premium-plugins");
|
|
10140
10155
|
if (existsSync18(premiumRoot)) {
|
|
10141
10156
|
for (const bundle of readdirSync11(premiumRoot)) {
|
|
10142
|
-
const bundlePlugins =
|
|
10157
|
+
const bundlePlugins = join17(premiumRoot, bundle, "plugins");
|
|
10143
10158
|
if (!existsSync18(bundlePlugins)) continue;
|
|
10144
10159
|
try {
|
|
10145
10160
|
for (const name of readdirSync11(bundlePlugins)) {
|
|
10146
|
-
const dir =
|
|
10161
|
+
const dir = join17(bundlePlugins, name);
|
|
10147
10162
|
try {
|
|
10148
10163
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
10149
10164
|
} catch {
|
|
@@ -10156,7 +10171,7 @@ function listPluginDirs() {
|
|
|
10156
10171
|
return out;
|
|
10157
10172
|
}
|
|
10158
10173
|
function readEnabledPlugins(accountId) {
|
|
10159
|
-
const accountFile =
|
|
10174
|
+
const accountFile = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
10160
10175
|
if (!existsSync18(accountFile)) return /* @__PURE__ */ new Set();
|
|
10161
10176
|
try {
|
|
10162
10177
|
const parsed = JSON.parse(readFileSync18(accountFile, "utf-8"));
|
|
@@ -10186,7 +10201,7 @@ function computeActivePlugins(accountId) {
|
|
|
10186
10201
|
for (const name of Array.from(enabled).sort()) {
|
|
10187
10202
|
const dir = pluginDirs.get(name);
|
|
10188
10203
|
if (!dir) continue;
|
|
10189
|
-
const fm = readFrontmatter(
|
|
10204
|
+
const fm = readFrontmatter(join17(dir, "PLUGIN.md"));
|
|
10190
10205
|
if (!fm) continue;
|
|
10191
10206
|
const description = frontmatterField(`---
|
|
10192
10207
|
${fm}
|
|
@@ -10203,7 +10218,7 @@ ${fm}
|
|
|
10203
10218
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
10204
10219
|
);
|
|
10205
10220
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
10206
|
-
const hasSource = existsSync18(
|
|
10221
|
+
const hasSource = existsSync18(join17(dir, "mcp/dist/index.js")) || existsSync18(join17(dir, "mcp/src/index.ts"));
|
|
10207
10222
|
if (hasSource) {
|
|
10208
10223
|
console.warn(
|
|
10209
10224
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -10213,7 +10228,7 @@ ${fm}
|
|
|
10213
10228
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
10214
10229
|
const skills = [];
|
|
10215
10230
|
for (const relPath of skillPaths) {
|
|
10216
|
-
const skillPath =
|
|
10231
|
+
const skillPath = join17(dir, relPath);
|
|
10217
10232
|
const skillFm = readFrontmatter(skillPath);
|
|
10218
10233
|
if (!skillFm) continue;
|
|
10219
10234
|
const skillName = frontmatterField(`---
|
|
@@ -10229,7 +10244,7 @@ ${skillFm}
|
|
|
10229
10244
|
return out;
|
|
10230
10245
|
}
|
|
10231
10246
|
function computeSpecialistDomains(accountId) {
|
|
10232
|
-
const specialistsDir =
|
|
10247
|
+
const specialistsDir = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
10233
10248
|
if (!existsSync18(specialistsDir)) return [];
|
|
10234
10249
|
let entries;
|
|
10235
10250
|
try {
|
|
@@ -10257,7 +10272,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
10257
10272
|
const out = [];
|
|
10258
10273
|
for (const file of entries.sort()) {
|
|
10259
10274
|
if (!file.endsWith(".md")) continue;
|
|
10260
|
-
const fm = readFrontmatter(
|
|
10275
|
+
const fm = readFrontmatter(join17(specialistsDir, file));
|
|
10261
10276
|
if (!fm) continue;
|
|
10262
10277
|
const wrapped = `---
|
|
10263
10278
|
${fm}
|
|
@@ -10275,7 +10290,7 @@ ${fm}
|
|
|
10275
10290
|
return out;
|
|
10276
10291
|
}
|
|
10277
10292
|
function computeDormantPlugins(accountId) {
|
|
10278
|
-
const accountFile =
|
|
10293
|
+
const accountFile = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
10279
10294
|
if (!existsSync18(accountFile)) return [];
|
|
10280
10295
|
let enabled;
|
|
10281
10296
|
try {
|
|
@@ -10290,7 +10305,7 @@ function computeDormantPlugins(accountId) {
|
|
|
10290
10305
|
);
|
|
10291
10306
|
return [];
|
|
10292
10307
|
}
|
|
10293
|
-
const pluginsDir =
|
|
10308
|
+
const pluginsDir = resolve16(PLATFORM_ROOT, "plugins");
|
|
10294
10309
|
if (!existsSync18(pluginsDir)) return [];
|
|
10295
10310
|
let entries;
|
|
10296
10311
|
try {
|
|
@@ -10301,7 +10316,7 @@ function computeDormantPlugins(accountId) {
|
|
|
10301
10316
|
const out = [];
|
|
10302
10317
|
for (const name of entries) {
|
|
10303
10318
|
if (enabled.has(name)) continue;
|
|
10304
|
-
const manifestPath =
|
|
10319
|
+
const manifestPath = resolve16(pluginsDir, name, "PLUGIN.md");
|
|
10305
10320
|
if (!existsSync18(manifestPath)) continue;
|
|
10306
10321
|
let manifest;
|
|
10307
10322
|
try {
|
|
@@ -10320,7 +10335,7 @@ function computeDormantPlugins(accountId) {
|
|
|
10320
10335
|
|
|
10321
10336
|
// server/routes/admin/claude-sessions.ts
|
|
10322
10337
|
import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
|
|
10323
|
-
import { resolve as
|
|
10338
|
+
import { resolve as resolve17 } from "path";
|
|
10324
10339
|
function readTunnelState(brandConfigDir) {
|
|
10325
10340
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
10326
10341
|
if (!existsSync19(statePath)) return null;
|
|
@@ -10336,10 +10351,10 @@ function readTunnelState(brandConfigDir) {
|
|
|
10336
10351
|
}
|
|
10337
10352
|
}
|
|
10338
10353
|
function resolveTunnelUrl() {
|
|
10339
|
-
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ??
|
|
10354
|
+
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
10340
10355
|
let brand;
|
|
10341
10356
|
try {
|
|
10342
|
-
brand = JSON.parse(readFileSync19(
|
|
10357
|
+
brand = JSON.parse(readFileSync19(resolve17(platformRoot2, "config", "brand.json"), "utf-8"));
|
|
10343
10358
|
} catch {
|
|
10344
10359
|
return null;
|
|
10345
10360
|
}
|
|
@@ -10584,15 +10599,15 @@ var events_default = app18;
|
|
|
10584
10599
|
import { createReadStream as createReadStream2 } from "fs";
|
|
10585
10600
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
10586
10601
|
import { realpathSync as realpathSync4 } from "fs";
|
|
10587
|
-
import { basename as basename6, dirname as dirname5, join as
|
|
10602
|
+
import { basename as basename6, dirname as dirname5, join as join19, resolve as resolve20, sep as sep5 } from "path";
|
|
10588
10603
|
import { Readable as Readable2 } from "stream";
|
|
10589
10604
|
|
|
10590
10605
|
// app/lib/data-path.ts
|
|
10591
10606
|
import { realpathSync as realpathSync3 } from "fs";
|
|
10592
|
-
import { resolve as
|
|
10593
|
-
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
10594
|
-
var DATA_ROOT =
|
|
10595
|
-
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ?
|
|
10607
|
+
import { resolve as resolve18, normalize, sep as sep3, relative } from "path";
|
|
10608
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "../platform");
|
|
10609
|
+
var DATA_ROOT = resolve18(PLATFORM_ROOT5, "..", "data");
|
|
10610
|
+
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve18(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
10596
10611
|
var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
|
|
10597
10612
|
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;
|
|
10598
10613
|
function crossesForeignAccountPartition(relPath, accountId) {
|
|
@@ -10605,7 +10620,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
|
|
|
10605
10620
|
}
|
|
10606
10621
|
function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
10607
10622
|
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
10608
|
-
const absolute =
|
|
10623
|
+
const absolute = resolve18(rootAbs, cleaned);
|
|
10609
10624
|
let rootReal;
|
|
10610
10625
|
try {
|
|
10611
10626
|
rootReal = realpathSync3(rootAbs);
|
|
@@ -10964,7 +10979,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
10964
10979
|
|
|
10965
10980
|
// app/lib/file-index.ts
|
|
10966
10981
|
import * as fsp from "fs/promises";
|
|
10967
|
-
import { resolve as
|
|
10982
|
+
import { resolve as resolve19, relative as relative2, join as join18, basename as basename5, extname as extname2, sep as sep4 } from "path";
|
|
10968
10983
|
import { tmpdir as tmpdir2 } from "os";
|
|
10969
10984
|
import { execFile as execFile2 } from "child_process";
|
|
10970
10985
|
import { promisify as promisify2 } from "util";
|
|
@@ -11035,7 +11050,7 @@ async function extractPdf(absolute) {
|
|
|
11035
11050
|
return stdout.trim();
|
|
11036
11051
|
}
|
|
11037
11052
|
async function ocrPdf(absolute) {
|
|
11038
|
-
const outPdf =
|
|
11053
|
+
const outPdf = join18(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
11039
11054
|
try {
|
|
11040
11055
|
await execFileAsync2(
|
|
11041
11056
|
"ocrmypdf",
|
|
@@ -11097,7 +11112,7 @@ async function readDisplayName(absolute) {
|
|
|
11097
11112
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
11098
11113
|
if (base === `${stem}.meta.json`) return null;
|
|
11099
11114
|
try {
|
|
11100
|
-
const raw = await fsp.readFile(
|
|
11115
|
+
const raw = await fsp.readFile(join18(dir, `${stem}.meta.json`), "utf-8");
|
|
11101
11116
|
const meta = JSON.parse(raw);
|
|
11102
11117
|
const dn = meta.displayName ?? meta.filename;
|
|
11103
11118
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -11117,7 +11132,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
11117
11132
|
let clean = true;
|
|
11118
11133
|
for (const entry of entries) {
|
|
11119
11134
|
if (entry.isSymbolicLink()) continue;
|
|
11120
|
-
const abs =
|
|
11135
|
+
const abs = join18(root, entry.name);
|
|
11121
11136
|
if (entry.isDirectory()) {
|
|
11122
11137
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
11123
11138
|
if (!sub.clean) clean = false;
|
|
@@ -11272,8 +11287,8 @@ async function reconcileFileIndex(accountId, opts) {
|
|
|
11272
11287
|
return withSession(opts, async (session) => {
|
|
11273
11288
|
const walked = [];
|
|
11274
11289
|
const subtreeRoots = [
|
|
11275
|
-
|
|
11276
|
-
|
|
11290
|
+
resolve19(dataRoot, "uploads", accountId),
|
|
11291
|
+
resolve19(dataRoot, "accounts", accountId)
|
|
11277
11292
|
];
|
|
11278
11293
|
let clean = true;
|
|
11279
11294
|
for (const root of subtreeRoots) {
|
|
@@ -11354,7 +11369,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
|
|
|
11354
11369
|
async function indexFile(accountId, relativePath, opts) {
|
|
11355
11370
|
const dataRoot = opts?.dataRoot ?? DATA_ROOT;
|
|
11356
11371
|
const embed2 = opts?.embed ?? embed;
|
|
11357
|
-
const absolute =
|
|
11372
|
+
const absolute = resolve19(dataRoot, relativePath);
|
|
11358
11373
|
await withSession(opts, async (session) => {
|
|
11359
11374
|
const st = await fsp.stat(absolute);
|
|
11360
11375
|
const wf = {
|
|
@@ -11388,7 +11403,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
|
|
|
11388
11403
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11389
11404
|
async function readMeta(absDir, baseName) {
|
|
11390
11405
|
try {
|
|
11391
|
-
const raw = await readFile4(
|
|
11406
|
+
const raw = await readFile4(join19(absDir, `${baseName}.meta.json`), "utf8");
|
|
11392
11407
|
const parsed = JSON.parse(raw);
|
|
11393
11408
|
if (typeof parsed?.filename === "string") {
|
|
11394
11409
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -11399,7 +11414,7 @@ async function readMeta(absDir, baseName) {
|
|
|
11399
11414
|
}
|
|
11400
11415
|
async function readAccountNames() {
|
|
11401
11416
|
const map = /* @__PURE__ */ new Map();
|
|
11402
|
-
const accountsDir =
|
|
11417
|
+
const accountsDir = resolve20(DATA_ROOT, "accounts");
|
|
11403
11418
|
let names;
|
|
11404
11419
|
try {
|
|
11405
11420
|
names = await readdir3(accountsDir);
|
|
@@ -11408,7 +11423,7 @@ async function readAccountNames() {
|
|
|
11408
11423
|
}
|
|
11409
11424
|
for (const name of names) {
|
|
11410
11425
|
if (!UUID_RE3.test(name)) continue;
|
|
11411
|
-
const configPath2 =
|
|
11426
|
+
const configPath2 = resolve20(accountsDir, name, "account.json");
|
|
11412
11427
|
try {
|
|
11413
11428
|
const raw = await readFile4(configPath2, "utf8");
|
|
11414
11429
|
const parsed = JSON.parse(raw);
|
|
@@ -11426,7 +11441,7 @@ async function readAccountNames() {
|
|
|
11426
11441
|
}
|
|
11427
11442
|
async function enrich(absolute, entry, accountNames) {
|
|
11428
11443
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
11429
|
-
const meta = await readMeta(
|
|
11444
|
+
const meta = await readMeta(join19(absolute, entry.name), entry.name);
|
|
11430
11445
|
if (meta?.filename) {
|
|
11431
11446
|
entry.displayName = meta.filename;
|
|
11432
11447
|
entry.mimeType = meta.mimeType;
|
|
@@ -11524,7 +11539,7 @@ app19.get("/", requireAdminSession, async (c) => {
|
|
|
11524
11539
|
continue;
|
|
11525
11540
|
}
|
|
11526
11541
|
try {
|
|
11527
|
-
const entryPath =
|
|
11542
|
+
const entryPath = join19(absolute, name);
|
|
11528
11543
|
const s = await stat4(entryPath);
|
|
11529
11544
|
entries.push({
|
|
11530
11545
|
name,
|
|
@@ -11649,8 +11664,8 @@ app19.post("/upload", requireAdminSession, async (c) => {
|
|
|
11649
11664
|
}
|
|
11650
11665
|
const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
|
|
11651
11666
|
const finalName = `${Date.now()}-${safeName}`;
|
|
11652
|
-
const destDir =
|
|
11653
|
-
const destPath =
|
|
11667
|
+
const destDir = resolve20(DATA_ROOT, "uploads", accountId);
|
|
11668
|
+
const destPath = resolve20(destDir, finalName);
|
|
11654
11669
|
try {
|
|
11655
11670
|
await mkdir3(destDir, { recursive: true });
|
|
11656
11671
|
const dataRootReal = realpathSync4(DATA_ROOT);
|
|
@@ -11715,7 +11730,7 @@ app19.delete("/", requireAdminSession, async (c) => {
|
|
|
11715
11730
|
}
|
|
11716
11731
|
const dot = base.lastIndexOf(".");
|
|
11717
11732
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
11718
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
11733
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join19(dirname5(absolute), `${stem}.meta.json`) : null;
|
|
11719
11734
|
await unlink2(absolute);
|
|
11720
11735
|
if (sidecarPath) {
|
|
11721
11736
|
try {
|
|
@@ -13764,7 +13779,7 @@ var graph_default_view_default = app25;
|
|
|
13764
13779
|
|
|
13765
13780
|
// server/routes/admin/sidebar-artefacts.ts
|
|
13766
13781
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
13767
|
-
import { resolve as
|
|
13782
|
+
import { resolve as resolve21, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
|
|
13768
13783
|
import { existsSync as existsSync20 } from "fs";
|
|
13769
13784
|
var LIMIT = 50;
|
|
13770
13785
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
@@ -13784,7 +13799,7 @@ app26.get("/", requireAdminSession, async (c) => {
|
|
|
13784
13799
|
if (accountFiles === null) {
|
|
13785
13800
|
return c.json({ error: "Failed to load artefacts" }, 500);
|
|
13786
13801
|
}
|
|
13787
|
-
const accountDir =
|
|
13802
|
+
const accountDir = resolve21(ACCOUNTS_DIR, accountId);
|
|
13788
13803
|
const agents = await fetchAgentTemplateRows(accountDir);
|
|
13789
13804
|
const artefacts = [...accountFiles, ...agents].sort(
|
|
13790
13805
|
(a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
|
|
@@ -13835,8 +13850,8 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
13835
13850
|
async function fetchAgentTemplateRows(accountDir) {
|
|
13836
13851
|
const rows = [];
|
|
13837
13852
|
for (const filename of ADMIN_AGENT_FILES) {
|
|
13838
|
-
const overridePath =
|
|
13839
|
-
const bundledPath =
|
|
13853
|
+
const overridePath = resolve21(accountDir, "agents", "admin", filename);
|
|
13854
|
+
const bundledPath = resolve21(PLATFORM_ROOT, "templates", "agents", "admin", filename);
|
|
13840
13855
|
const labelStem = filename.replace(/\.md$/, "");
|
|
13841
13856
|
const row = await readAgentTemplateRow({
|
|
13842
13857
|
id: `agent-template:admin:${filename}`,
|
|
@@ -13849,12 +13864,12 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
13849
13864
|
});
|
|
13850
13865
|
if (row) rows.push(row);
|
|
13851
13866
|
}
|
|
13852
|
-
const overrideDir =
|
|
13853
|
-
const bundledDir =
|
|
13867
|
+
const overrideDir = resolve21(accountDir, "specialists", "agents");
|
|
13868
|
+
const bundledDir = resolve21(PLATFORM_ROOT, "templates", "specialists", "agents");
|
|
13854
13869
|
const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
|
|
13855
13870
|
for (const filename of specialistNames) {
|
|
13856
|
-
const overridePath =
|
|
13857
|
-
const bundledPath =
|
|
13871
|
+
const overridePath = resolve21(overrideDir, filename);
|
|
13872
|
+
const bundledPath = resolve21(bundledDir, filename);
|
|
13858
13873
|
const row = await readAgentTemplateRow({
|
|
13859
13874
|
id: `agent-template:specialist:${filename}`,
|
|
13860
13875
|
displayName: filename.replace(/\.md$/, ""),
|
|
@@ -14062,6 +14077,36 @@ app29.post("/", requireAdminSession, async (c) => {
|
|
|
14062
14077
|
var session_archive_default = app29;
|
|
14063
14078
|
|
|
14064
14079
|
// server/routes/admin/session-rc-spawn.ts
|
|
14080
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
14081
|
+
function resolveSpawnPlan(host, body, mintId = randomUUID9) {
|
|
14082
|
+
const operator = isOperatorHost(host);
|
|
14083
|
+
const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
|
|
14084
|
+
const name = typeof body.name === "string" && body.name.length > 0 ? body.name : void 0;
|
|
14085
|
+
const webchatBind = resumeId === void 0 || operator;
|
|
14086
|
+
const kind = resumeId === void 0 ? "new" : "resume";
|
|
14087
|
+
const origin = operator ? "operator" : "admin";
|
|
14088
|
+
const payload = {};
|
|
14089
|
+
let sessionId;
|
|
14090
|
+
if (webchatBind) {
|
|
14091
|
+
sessionId = resumeId ?? mintId();
|
|
14092
|
+
const key = `session:${sessionId}`;
|
|
14093
|
+
payload.sessionId = sessionId;
|
|
14094
|
+
payload.role = "admin";
|
|
14095
|
+
payload.channel = "webchat";
|
|
14096
|
+
payload.senderId = key;
|
|
14097
|
+
payload.webchatChannel = webchatChannelDescriptor(key);
|
|
14098
|
+
if (name) payload.name = name;
|
|
14099
|
+
} else {
|
|
14100
|
+
sessionId = resumeId;
|
|
14101
|
+
payload.sessionId = resumeId;
|
|
14102
|
+
if (name) payload.name = name;
|
|
14103
|
+
}
|
|
14104
|
+
return { webchatBind, origin, kind, sessionId, payload };
|
|
14105
|
+
}
|
|
14106
|
+
function shapeWebchatResponse(sessionId, manager) {
|
|
14107
|
+
const outcome = typeof manager?.outcome === "string" ? manager.outcome : "bound";
|
|
14108
|
+
return { sessionId, outcome, target: `/chat?session=${sessionId}` };
|
|
14109
|
+
}
|
|
14065
14110
|
var app30 = new Hono();
|
|
14066
14111
|
app30.post("/", requireAdminSession, async (c) => {
|
|
14067
14112
|
let body;
|
|
@@ -14070,19 +14115,26 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
14070
14115
|
} catch {
|
|
14071
14116
|
body = {};
|
|
14072
14117
|
}
|
|
14073
|
-
const
|
|
14074
|
-
|
|
14075
|
-
|
|
14118
|
+
const host = c.req.header("host") ?? "";
|
|
14119
|
+
const plan = resolveSpawnPlan(host, body);
|
|
14120
|
+
const spawnReqId = randomUUID9();
|
|
14121
|
+
console.log(
|
|
14122
|
+
`[chat-spawn] op=request spawnReqId=${spawnReqId} origin=${plan.origin} kind=${plan.kind} sessionId=${plan.kind === "new" ? "new" : plan.sessionId}`
|
|
14123
|
+
);
|
|
14124
|
+
if (plan.webchatBind) {
|
|
14125
|
+
console.log(`[chat-spawn] op=args spawnReqId=${spawnReqId} webchatChannel=present sessionId=${plan.sessionId}`);
|
|
14126
|
+
}
|
|
14076
14127
|
let res;
|
|
14077
14128
|
try {
|
|
14078
14129
|
res = await fetch(`${managerBase3("session-rc-spawn:wrapper")}/rc-spawn`, {
|
|
14079
14130
|
method: "POST",
|
|
14080
14131
|
headers: { "content-type": "application/json" },
|
|
14081
|
-
body: JSON.stringify(payload)
|
|
14132
|
+
body: JSON.stringify(plan.payload)
|
|
14082
14133
|
});
|
|
14083
14134
|
} catch (err) {
|
|
14084
14135
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14085
14136
|
console.error(`[session-rc-spawn] manager-unreachable err=${msg}`);
|
|
14137
|
+
console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=spawn-failed`);
|
|
14086
14138
|
return c.json({ error: `session manager unreachable: ${msg}` }, 502);
|
|
14087
14139
|
}
|
|
14088
14140
|
const text = await res.text();
|
|
@@ -14093,8 +14145,18 @@ app30.post("/", requireAdminSession, async (c) => {
|
|
|
14093
14145
|
}
|
|
14094
14146
|
if (!res.ok) {
|
|
14095
14147
|
console.error(`[session-rc-spawn] manager-error status=${res.status} body=${text.slice(0, 200)}`);
|
|
14148
|
+
console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=spawn-failed`);
|
|
14096
14149
|
return c.json(parsed ?? { error: text }, res.status);
|
|
14097
14150
|
}
|
|
14151
|
+
if (plan.webchatBind) {
|
|
14152
|
+
const target = `/chat?session=${plan.sessionId}`;
|
|
14153
|
+
console.log(
|
|
14154
|
+
`[chat-spawn] op=acquired spawnReqId=${spawnReqId} pid=${parsed?.spawnedPid ?? "none"} sessionId=${plan.sessionId}`
|
|
14155
|
+
);
|
|
14156
|
+
console.log(`[chat-spawn] op=navigate spawnReqId=${spawnReqId} target=${target}`);
|
|
14157
|
+
console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=bound`);
|
|
14158
|
+
return c.json(shapeWebchatResponse(plan.sessionId, parsed));
|
|
14159
|
+
}
|
|
14098
14160
|
return c.json(parsed ?? {});
|
|
14099
14161
|
});
|
|
14100
14162
|
var session_rc_spawn_default = app30;
|
|
@@ -14222,10 +14284,10 @@ var system_stats_default = app31;
|
|
|
14222
14284
|
|
|
14223
14285
|
// server/routes/admin/health.ts
|
|
14224
14286
|
import { existsSync as existsSync21, readFileSync as readFileSync20 } from "fs";
|
|
14225
|
-
import { resolve as
|
|
14226
|
-
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14287
|
+
import { resolve as resolve22, join as join20 } from "path";
|
|
14288
|
+
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
|
|
14227
14289
|
var brandHostname = "maxy";
|
|
14228
|
-
var brandJsonPath =
|
|
14290
|
+
var brandJsonPath = join20(PLATFORM_ROOT6, "config", "brand.json");
|
|
14229
14291
|
if (existsSync21(brandJsonPath)) {
|
|
14230
14292
|
try {
|
|
14231
14293
|
const brand = JSON.parse(readFileSync20(brandJsonPath, "utf-8"));
|
|
@@ -14233,7 +14295,7 @@ if (existsSync21(brandJsonPath)) {
|
|
|
14233
14295
|
} catch {
|
|
14234
14296
|
}
|
|
14235
14297
|
}
|
|
14236
|
-
var VERSION_FILE =
|
|
14298
|
+
var VERSION_FILE = resolve22(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
|
|
14237
14299
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
14238
14300
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
14239
14301
|
function readVersion() {
|
|
@@ -14289,7 +14351,7 @@ app32.get("/", async (c) => {
|
|
|
14289
14351
|
var health_default2 = app32;
|
|
14290
14352
|
|
|
14291
14353
|
// server/routes/admin/linkedin-ingest.ts
|
|
14292
|
-
import { randomUUID as
|
|
14354
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
14293
14355
|
var TAG25 = "[linkedin-ingest-route]";
|
|
14294
14356
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
14295
14357
|
var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
@@ -14415,7 +14477,7 @@ app33.post("/", requireAdminSession, async (c) => {
|
|
|
14415
14477
|
);
|
|
14416
14478
|
const initialMessage = buildInitialMessage(envelope);
|
|
14417
14479
|
const spawnStart = Date.now();
|
|
14418
|
-
const sessionId =
|
|
14480
|
+
const sessionId = randomUUID10();
|
|
14419
14481
|
console.log(TAG25 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
|
|
14420
14482
|
const spawned = await managerRcSpawn({
|
|
14421
14483
|
sessionId,
|
|
@@ -14781,13 +14843,13 @@ var admin_default = app39;
|
|
|
14781
14843
|
// app/lib/access-gate.ts
|
|
14782
14844
|
import neo4j4 from "neo4j-driver";
|
|
14783
14845
|
import { readFileSync as readFileSync21 } from "fs";
|
|
14784
|
-
import { resolve as
|
|
14785
|
-
import { randomUUID as
|
|
14786
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
14846
|
+
import { resolve as resolve23 } from "path";
|
|
14847
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
14848
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
|
|
14787
14849
|
var driver = null;
|
|
14788
14850
|
function readPassword() {
|
|
14789
14851
|
if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
|
|
14790
|
-
const passwordFile =
|
|
14852
|
+
const passwordFile = resolve23(PLATFORM_ROOT7, "config/.neo4j-password");
|
|
14791
14853
|
try {
|
|
14792
14854
|
return readFileSync21(passwordFile, "utf-8").trim();
|
|
14793
14855
|
} catch {
|
|
@@ -14965,7 +15027,7 @@ async function consumeMagicTokenAndActivate(grantId) {
|
|
|
14965
15027
|
}
|
|
14966
15028
|
}
|
|
14967
15029
|
async function generateNewMagicToken(grantId) {
|
|
14968
|
-
const token =
|
|
15030
|
+
const token = randomUUID11();
|
|
14969
15031
|
const session = getSession3();
|
|
14970
15032
|
try {
|
|
14971
15033
|
const result = await session.run(
|
|
@@ -15077,9 +15139,9 @@ var verify_token_default = app40;
|
|
|
15077
15139
|
|
|
15078
15140
|
// app/lib/access-email.ts
|
|
15079
15141
|
import { spawn as spawn2 } from "child_process";
|
|
15080
|
-
import { resolve as
|
|
15081
|
-
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ??
|
|
15082
|
-
var SEND_SCRIPT =
|
|
15142
|
+
import { resolve as resolve24 } from "path";
|
|
15143
|
+
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
15144
|
+
var SEND_SCRIPT = resolve24(
|
|
15083
15145
|
PLATFORM_ROOT8,
|
|
15084
15146
|
"plugins",
|
|
15085
15147
|
"email",
|
|
@@ -15222,7 +15284,7 @@ var access_default = app42;
|
|
|
15222
15284
|
|
|
15223
15285
|
// server/routes/sites.ts
|
|
15224
15286
|
import { existsSync as existsSync22, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
15225
|
-
import { resolve as
|
|
15287
|
+
import { resolve as resolve25 } from "path";
|
|
15226
15288
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
15227
15289
|
var MIME = {
|
|
15228
15290
|
".html": "text/html; charset=utf-8",
|
|
@@ -15279,8 +15341,8 @@ app43.get("/:rel{.*}", (c) => {
|
|
|
15279
15341
|
}
|
|
15280
15342
|
segments.push(seg);
|
|
15281
15343
|
}
|
|
15282
|
-
const rootDir =
|
|
15283
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
15344
|
+
const rootDir = resolve25(account.accountDir, "sites");
|
|
15345
|
+
let filePath = segments.length === 0 ? rootDir : resolve25(rootDir, ...segments);
|
|
15284
15346
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
15285
15347
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
15286
15348
|
return c.text("Forbidden", 403);
|
|
@@ -15300,7 +15362,7 @@ app43.get("/:rel{.*}", (c) => {
|
|
|
15300
15362
|
return c.redirect(target, 301);
|
|
15301
15363
|
}
|
|
15302
15364
|
if (stat7?.isDirectory()) {
|
|
15303
|
-
filePath =
|
|
15365
|
+
filePath = resolve25(filePath, "index.html");
|
|
15304
15366
|
}
|
|
15305
15367
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
15306
15368
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
@@ -15438,7 +15500,7 @@ var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
|
15438
15500
|
|
|
15439
15501
|
// app/lib/brand-config.ts
|
|
15440
15502
|
import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
|
|
15441
|
-
import { join as
|
|
15503
|
+
import { join as join21 } from "path";
|
|
15442
15504
|
var cached2 = null;
|
|
15443
15505
|
var cachedAttempted = false;
|
|
15444
15506
|
function readBrandConfig() {
|
|
@@ -15446,7 +15508,7 @@ function readBrandConfig() {
|
|
|
15446
15508
|
cachedAttempted = true;
|
|
15447
15509
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
|
|
15448
15510
|
if (!platformRoot2) return null;
|
|
15449
|
-
const brandPath =
|
|
15511
|
+
const brandPath = join21(platformRoot2, "config", "brand.json");
|
|
15450
15512
|
if (!existsSync23(brandPath)) return null;
|
|
15451
15513
|
try {
|
|
15452
15514
|
cached2 = JSON.parse(readFileSync24(brandPath, "utf-8"));
|
|
@@ -15937,14 +15999,14 @@ async function writeEvent(opts) {
|
|
|
15937
15999
|
var visitor_event_default = app46;
|
|
15938
16000
|
|
|
15939
16001
|
// server/routes/session.ts
|
|
15940
|
-
import { resolve as
|
|
16002
|
+
import { resolve as resolve26 } from "path";
|
|
15941
16003
|
import { existsSync as existsSync24, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
|
|
15942
16004
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15943
16005
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
15944
16006
|
try {
|
|
15945
|
-
const cacheDir =
|
|
16007
|
+
const cacheDir = resolve26(MAXY_DIR, "branding-cache", accountId);
|
|
15946
16008
|
mkdirSync5(cacheDir, { recursive: true });
|
|
15947
|
-
writeFileSync9(
|
|
16009
|
+
writeFileSync9(resolve26(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
15948
16010
|
} catch (err) {
|
|
15949
16011
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
15950
16012
|
}
|
|
@@ -16032,8 +16094,8 @@ app47.post("/", async (c) => {
|
|
|
16032
16094
|
}
|
|
16033
16095
|
let agentConfig = null;
|
|
16034
16096
|
if (account) {
|
|
16035
|
-
const agentDir =
|
|
16036
|
-
if (!existsSync24(agentDir) || !existsSync24(
|
|
16097
|
+
const agentDir = resolve26(account.accountDir, "agents", agentSlug);
|
|
16098
|
+
if (!existsSync24(agentDir) || !existsSync24(resolve26(agentDir, "config.json"))) {
|
|
16037
16099
|
return c.json({ error: "Agent not found" }, 404);
|
|
16038
16100
|
}
|
|
16039
16101
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -16313,7 +16375,7 @@ function startGraphHealthTimer() {
|
|
|
16313
16375
|
|
|
16314
16376
|
// app/lib/file-watcher.ts
|
|
16315
16377
|
import * as fsp2 from "fs/promises";
|
|
16316
|
-
import { resolve as
|
|
16378
|
+
import { resolve as resolve27, sep as sep7 } from "path";
|
|
16317
16379
|
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;
|
|
16318
16380
|
var DEFAULT_COALESCE_MS = 500;
|
|
16319
16381
|
var ROOTS = ["uploads", "accounts"];
|
|
@@ -16332,7 +16394,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
16332
16394
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
16333
16395
|
for (const r of ROOTS) {
|
|
16334
16396
|
try {
|
|
16335
|
-
await fsp2.mkdir(
|
|
16397
|
+
await fsp2.mkdir(resolve27(dataRoot, r), { recursive: true });
|
|
16336
16398
|
} catch (err) {
|
|
16337
16399
|
console.error(
|
|
16338
16400
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -16353,7 +16415,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
16353
16415
|
timers.set(relativePath, t);
|
|
16354
16416
|
}
|
|
16355
16417
|
async function runHook(relativePath, accountId) {
|
|
16356
|
-
const absolute =
|
|
16418
|
+
const absolute = resolve27(dataRoot, relativePath);
|
|
16357
16419
|
let exists = false;
|
|
16358
16420
|
try {
|
|
16359
16421
|
const st = await fsp2.stat(absolute);
|
|
@@ -16377,7 +16439,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
16377
16439
|
}
|
|
16378
16440
|
}
|
|
16379
16441
|
async function watchRoot(rootName) {
|
|
16380
|
-
const absRoot =
|
|
16442
|
+
const absRoot = resolve27(dataRoot, rootName);
|
|
16381
16443
|
try {
|
|
16382
16444
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
16383
16445
|
for await (const event of iter) {
|
|
@@ -17272,7 +17334,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
17272
17334
|
// ../lib/entitlement/src/index.ts
|
|
17273
17335
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
17274
17336
|
import { existsSync as existsSync25, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
|
|
17275
|
-
import { resolve as
|
|
17337
|
+
import { resolve as resolve28 } from "path";
|
|
17276
17338
|
|
|
17277
17339
|
// ../lib/entitlement/src/canonicalize.ts
|
|
17278
17340
|
function canonicalize(value) {
|
|
@@ -17307,7 +17369,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
17307
17369
|
var GRACE_DAYS = 7;
|
|
17308
17370
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
17309
17371
|
function pubkeyPath(brand) {
|
|
17310
|
-
return
|
|
17372
|
+
return resolve28(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
17311
17373
|
}
|
|
17312
17374
|
var memo = null;
|
|
17313
17375
|
function memoKey(mtimeMs, account) {
|
|
@@ -17319,7 +17381,7 @@ function resolveEntitlement(brand, account) {
|
|
|
17319
17381
|
if (brand.commercialMode !== true) {
|
|
17320
17382
|
return logResolved(implicitTrust(account), null);
|
|
17321
17383
|
}
|
|
17322
|
-
const entitlementPath =
|
|
17384
|
+
const entitlementPath = resolve28(brand.configDir, "entitlement.json");
|
|
17323
17385
|
if (!existsSync25(entitlementPath)) {
|
|
17324
17386
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
17325
17387
|
}
|
|
@@ -17510,7 +17572,7 @@ function clientFrom(c) {
|
|
|
17510
17572
|
);
|
|
17511
17573
|
}
|
|
17512
17574
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
17513
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT9 ?
|
|
17575
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join22(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
17514
17576
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
17515
17577
|
if (BRAND_JSON_PATH && !existsSync26(BRAND_JSON_PATH)) {
|
|
17516
17578
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
@@ -17536,7 +17598,7 @@ var brandLoginOpts = {
|
|
|
17536
17598
|
bodyFont: BRAND.defaultFonts?.body,
|
|
17537
17599
|
logoContainsName: !!BRAND.logoContainsName
|
|
17538
17600
|
};
|
|
17539
|
-
var ALIAS_DOMAINS_PATH =
|
|
17601
|
+
var ALIAS_DOMAINS_PATH = join22(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
17540
17602
|
function loadAliasDomains() {
|
|
17541
17603
|
try {
|
|
17542
17604
|
if (!existsSync26(ALIAS_DOMAINS_PATH)) return null;
|
|
@@ -17568,7 +17630,7 @@ var app48 = new Hono();
|
|
|
17568
17630
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
17569
17631
|
var waGateway = new WaGateway({
|
|
17570
17632
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
17571
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
17633
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
17572
17634
|
// Task 751 — file delivery on the native channel: resolve the platform
|
|
17573
17635
|
// account + path validation here and funnel through the shared send core.
|
|
17574
17636
|
sendDocument: async ({ senderId, accountId, filePath, caption }) => {
|
|
@@ -17584,7 +17646,7 @@ var waGateway = new WaGateway({
|
|
|
17584
17646
|
caption,
|
|
17585
17647
|
accountId,
|
|
17586
17648
|
maxyAccountId,
|
|
17587
|
-
platformRoot:
|
|
17649
|
+
platformRoot: resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, ".."))
|
|
17588
17650
|
});
|
|
17589
17651
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
17590
17652
|
},
|
|
@@ -17623,8 +17685,8 @@ var waGateway = new WaGateway({
|
|
|
17623
17685
|
app48.route("/", waGateway.routes());
|
|
17624
17686
|
waGateway.startSweeper();
|
|
17625
17687
|
var webchatGateway = new WebchatGateway({
|
|
17626
|
-
gatewayUrl:
|
|
17627
|
-
serverPath:
|
|
17688
|
+
gatewayUrl: webchatGatewayUrl(),
|
|
17689
|
+
serverPath: webchatServerPath(),
|
|
17628
17690
|
ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId }) => {
|
|
17629
17691
|
if (role !== "admin") {
|
|
17630
17692
|
console.error(`[webchat:inbound] op=spawn-refused key=${key} role=${role} reason=public-path-not-wired`);
|
|
@@ -17965,8 +18027,8 @@ app48.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
17965
18027
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
17966
18028
|
return c.text("Not found", 404);
|
|
17967
18029
|
}
|
|
17968
|
-
const filePath =
|
|
17969
|
-
const expectedDir =
|
|
18030
|
+
const filePath = resolve29(account.accountDir, "agents", slug, "assets", filename);
|
|
18031
|
+
const expectedDir = resolve29(account.accountDir, "agents", slug, "assets");
|
|
17970
18032
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
17971
18033
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
17972
18034
|
return c.text("Forbidden", 403);
|
|
@@ -17995,8 +18057,8 @@ app48.get("/generated/:filename", (c) => {
|
|
|
17995
18057
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
17996
18058
|
return c.text("Not found", 404);
|
|
17997
18059
|
}
|
|
17998
|
-
const filePath =
|
|
17999
|
-
const expectedDir =
|
|
18060
|
+
const filePath = resolve29(account.accountDir, "generated", filename);
|
|
18061
|
+
const expectedDir = resolve29(account.accountDir, "generated");
|
|
18000
18062
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
18001
18063
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
18002
18064
|
return c.text("Forbidden", 403);
|
|
@@ -18040,7 +18102,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
18040
18102
|
function readInstalledVersion() {
|
|
18041
18103
|
try {
|
|
18042
18104
|
if (!PLATFORM_ROOT9) return "unknown";
|
|
18043
|
-
const versionFile =
|
|
18105
|
+
const versionFile = join22(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
|
|
18044
18106
|
if (!existsSync26(versionFile)) return "unknown";
|
|
18045
18107
|
const content = readFileSync26(versionFile, "utf-8").trim();
|
|
18046
18108
|
return content || "unknown";
|
|
@@ -18083,7 +18145,7 @@ var clientErrorReporterScript = `<script>
|
|
|
18083
18145
|
function cachedHtml(file) {
|
|
18084
18146
|
let html = htmlCache.get(file);
|
|
18085
18147
|
if (!html) {
|
|
18086
|
-
html = readFileSync26(
|
|
18148
|
+
html = readFileSync26(resolve29(process.cwd(), "public", file), "utf-8");
|
|
18087
18149
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
18088
18150
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
18089
18151
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -18099,11 +18161,11 @@ ${clientErrorReporterScript}
|
|
|
18099
18161
|
}
|
|
18100
18162
|
var brandedHtmlCache = /* @__PURE__ */ new Map();
|
|
18101
18163
|
function loadBrandingCache(agentSlug) {
|
|
18102
|
-
const configDir2 =
|
|
18164
|
+
const configDir2 = join22(homedir3(), BRAND.configDir);
|
|
18103
18165
|
try {
|
|
18104
18166
|
const accountId = getDefaultAccountId();
|
|
18105
18167
|
if (!accountId) return null;
|
|
18106
|
-
const cachePath =
|
|
18168
|
+
const cachePath = join22(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
18107
18169
|
if (!existsSync26(cachePath)) return null;
|
|
18108
18170
|
return JSON.parse(readFileSync26(cachePath, "utf-8"));
|
|
18109
18171
|
} catch {
|
|
@@ -18150,6 +18212,10 @@ function agentUnavailableHtml() {
|
|
|
18150
18212
|
}
|
|
18151
18213
|
app48.get("/", (c) => {
|
|
18152
18214
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
18215
|
+
if (isOperatorHost(host)) {
|
|
18216
|
+
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
18217
|
+
return c.html(cachedHtml("operator.html"));
|
|
18218
|
+
}
|
|
18153
18219
|
if (isPublicHost(host)) {
|
|
18154
18220
|
const defaultSlug = resolveDefaultSlug();
|
|
18155
18221
|
if (!defaultSlug) {
|
|
@@ -18162,6 +18228,7 @@ app48.get("/", (c) => {
|
|
|
18162
18228
|
console.error(`[public-root] op=serve-default slug=${defaultSlug}`);
|
|
18163
18229
|
return c.html(brandedPublicHtml(defaultSlug));
|
|
18164
18230
|
}
|
|
18231
|
+
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
18165
18232
|
return c.html(cachedHtml("index.html"));
|
|
18166
18233
|
});
|
|
18167
18234
|
app48.get("/public", (c) => {
|
|
@@ -18193,7 +18260,7 @@ app48.use("/vnc-popout.html", logViewerFetch);
|
|
|
18193
18260
|
app48.get("/vnc-popout.html", (c) => {
|
|
18194
18261
|
let html = htmlCache.get("vnc-popout.html");
|
|
18195
18262
|
if (!html) {
|
|
18196
|
-
html = readFileSync26(
|
|
18263
|
+
html = readFileSync26(resolve29(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
18197
18264
|
const name = escapeHtml(BRAND.productName);
|
|
18198
18265
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
18199
18266
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -18229,7 +18296,7 @@ app48.get("/g/:slug", (c) => {
|
|
|
18229
18296
|
});
|
|
18230
18297
|
app48.get("/graph", (c) => {
|
|
18231
18298
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
18232
|
-
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
18299
|
+
if (isPublicHost(host) || isOperatorHost(host)) return c.text("Not found", 404);
|
|
18233
18300
|
return c.html(cachedHtml("graph.html"));
|
|
18234
18301
|
});
|
|
18235
18302
|
app48.get("/chat", (c) => {
|
|
@@ -18244,7 +18311,7 @@ app48.get("/data", (c) => {
|
|
|
18244
18311
|
});
|
|
18245
18312
|
app48.get("/browser", (c) => {
|
|
18246
18313
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
18247
|
-
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
18314
|
+
if (isPublicHost(host) || isOperatorHost(host)) return c.text("Not found", 404);
|
|
18248
18315
|
return c.html(cachedHtml("browser.html"));
|
|
18249
18316
|
});
|
|
18250
18317
|
app48.get("/:slug", async (c, next) => {
|
|
@@ -18463,7 +18530,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
18463
18530
|
}
|
|
18464
18531
|
init({
|
|
18465
18532
|
configDir: configDirForWhatsApp,
|
|
18466
|
-
platformRoot:
|
|
18533
|
+
platformRoot: resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, "..")),
|
|
18467
18534
|
accountConfig: bootAccountConfig,
|
|
18468
18535
|
onMessage: async (msg) => {
|
|
18469
18536
|
if (msg.isOwnerMirror) {
|