@rubytech/create-maxy-code 0.1.285 → 0.1.287
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/samba-provision.test.js +84 -16
- package/dist/index.js +17 -8
- package/dist/samba-provision.js +81 -24
- package/dist/uninstall.js +5 -1
- package/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +52 -3
- package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-directive.test.sh +55 -0
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +29 -13
- package/payload/platform/plugins/admin/hooks/prompt-optimiser-directive.sh +60 -11
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +30 -17
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/deployment.md +1 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
- package/payload/platform/plugins/docs/references/samba.md +25 -12
- package/payload/platform/plugins/whatsapp/PLUGIN.md +4 -0
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
- package/payload/platform/scripts/__tests__/prompt-optimiser-audit.test.sh +59 -0
- package/payload/platform/scripts/installer-device-verify.sh +74 -3
- package/payload/platform/scripts/prompt-optimiser-audit.sh +82 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +46 -7
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +49 -9
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +70 -17
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/server/{chunk-QHD5TKLQ.js → chunk-EAJMRICW.js} +21 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/AdminShell-DkP2rJdF.js +1 -0
- package/payload/server/public/assets/{Checkbox-BdDmGlvK.js → Checkbox-CsQq7YPC.js} +1 -1
- package/payload/server/public/assets/{admin-BYtGQJ0d.js → admin-C_bkVvXh.js} +1 -1
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CBx_GoUY.js → architectureDiagram-Q4EWVU46-PGePlVpb.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DvWR4fpv.js → blockDiagram-DXYQGD6D-BJCbJRRs.js} +1 -1
- package/payload/server/public/assets/{browser-2PXsTraZ.js → browser-DynPFG_A.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BbSOxeeU.js → c4Diagram-AHTNJAMY-DcMhi4gF.js} +1 -1
- package/payload/server/public/assets/channel-idaGQqlP.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DJzmXTk5.js → chunk-336JU56O-0vhS0MI-.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-BSwzskM5.js → chunk-426QAEUC-DbVU-p-q.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-C-fH8BTZ.js → chunk-4TB4RGXK-dgx3qIz_.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-DW-MaiGX.js → chunk-5FUZZQ4R-BglTosdT.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-DlKbwC1X.js → chunk-5PVQY5BW-hZB3AxUF.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-DnkdxwAt.js → chunk-EDXVE4YY-DXqLJyYa.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-BTfezWsj.js → chunk-ENJZ2VHE-BD4I_a54.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BGg8uTtu.js → chunk-ICPOFSXX-BdQx0Ahc.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-CYJInav8.js → chunk-OYMX7WX6-BDjtbZvS.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-B6kD6ZHU.js → chunk-U2HBQHQK-hYN7A3g_.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-7tvWkjym.js → chunk-X2U36JSP-D3njJ7WG.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-D6NjOb5l.js → chunk-YZCP3GAM-BfZKEcvU.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-Dqz69eJy.js → chunk-ZZ45TVLE-DLJMNqLn.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CmRFpirU.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DFy8xZjP.js +1 -0
- package/payload/server/public/assets/clone-kFPktUPQ.js +1 -0
- package/payload/server/public/assets/{dagre-di-KHpsq.js → dagre-DVLE4-m6.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-DswETLwm.js → dagre-KV5264BT-DGjcX5uz.js} +1 -1
- package/payload/server/public/assets/{data-B6vpe0Zj.js → data-D1FFhz2k.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-DWmq_Zkl.js → diagram-5BDNPKRD-CQI2o8Cv.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BVi6yjLL.js → diagram-G4DWMVQ6-C8kXsEdQ.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-D6XKyUAT.js → diagram-MMDJMWI5-DaWrNg_c.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-sU1d7P6W.js → diagram-TYMM5635-Ql9QPUxX.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-CY6qPZvu.js → erDiagram-SMLLAGMA-B2fBZhPo.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CE9hd869.js → flowDiagram-DWJPFMVM-BA0LiOm5.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-Cbb885gt.js → ganttDiagram-T4ZO3ILL-CBKdEgUk.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BNzO3jBu.js → gitGraphDiagram-UUTBAWPF-BIyEfuwB.js} +1 -1
- package/payload/server/public/assets/{graph-DfegJdnT.js → graph-BxWBNsFs.js} +1 -1
- package/payload/server/public/assets/{graph-labels-BG4aqzs6.js → graph-labels-DSLdDXoF.js} +1 -1
- package/payload/server/public/assets/{graphlib-CIzKPoW_.js → graphlib-Cv4SvsQN.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-DWGtofAT.js → infoDiagram-42DDH7IO-DovHLDHz.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-UG1rus6G.js → ishikawaDiagram-UXIWVN3A-haFza9s4.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CYhHYXmj.js → journeyDiagram-VCZTEJTY-l-8tJ21z.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CWHj9DHX.js → kanban-definition-6JOO6SKY-DSZUvFLs.js} +1 -1
- package/payload/server/public/assets/{line-vMN9CmXx.js → line-mfTElknw.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-5X7WWCZe.js → mermaid-parser.core-4temHHPS.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-B0zUZsT6.js → mermaid.core-DO2iS9my.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-BGr68ynR.js → mindmap-definition-QFDTVHPH-Cymf2IGG.js} +1 -1
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-Bo3zU_w2.js → pieDiagram-DEJITSTG-_2tmuvMb.js} +1 -1
- package/payload/server/public/assets/{public-DCZ92LR9.js → public-Rz_GzOrN.js} +3 -3
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-o-dLMRj-.js → quadrantDiagram-34T5L4WZ-CVCrGnBi.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-D_O_ZclX.js → requirementDiagram-MS252O5E-Bc-o8i8Z.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Doz7uWIn.js → sankeyDiagram-XADWPNL6-DrTBxqE6.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-r1VW_jgc.js → sequenceDiagram-FGHM5R23-BjVjSsUJ.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-B7O06aua.js → stateDiagram-FHFEXIEX-DWAJP6ly.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BHDyrxpj.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-WS2AL0yL.js → timeline-definition-GMOUNBTQ-Br_nbteH.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-lFraIQzT.css → useSelectionMode-BLb-o9RX.css} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-_-FLcVAh.js → vennDiagram-DHZGUBPP-D_ozeKV6.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-nZ3oO0ih.js → wardleyDiagram-NUSXRM2D-B87ZKC2B.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CqTdRM37.js → xychartDiagram-5P7HB3ND-DosRlk2T.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +5 -5
- package/payload/server/public/public.html +4 -4
- package/payload/server/server.js +269 -81
- package/payload/server/public/assets/AdminShell-DwPVr9K1.js +0 -1
- package/payload/server/public/assets/channel-C4NqYS8u.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CI3_kz04.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-UP3RcKH9.js +0 -1
- package/payload/server/public/assets/clone-CvAPweMB.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Bo1g66pA.js +0 -1
- /package/payload/server/public/assets/{useSelectionMode-mzxTOyBv.js → useSelectionMode-hZ5bdL8b.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
listValidAccounts,
|
|
63
63
|
loadAdminUserName,
|
|
64
64
|
loadUserProfile,
|
|
65
|
+
loadWhatsappSenderName,
|
|
65
66
|
persistMessage,
|
|
66
67
|
projectAgent,
|
|
67
68
|
reconcileEnabledPlugins,
|
|
@@ -96,7 +97,7 @@ import {
|
|
|
96
97
|
vncLog,
|
|
97
98
|
walkPremiumBundles,
|
|
98
99
|
writeAdminUserAndPerson
|
|
99
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-EAJMRICW.js";
|
|
100
101
|
import {
|
|
101
102
|
__commonJS,
|
|
102
103
|
__toESM
|
|
@@ -1201,7 +1202,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1201
1202
|
};
|
|
1202
1203
|
|
|
1203
1204
|
// server/index.ts
|
|
1204
|
-
import { readFileSync as readFileSync24, existsSync as
|
|
1205
|
+
import { readFileSync as readFileSync24, existsSync as existsSync25, watchFile } from "fs";
|
|
1205
1206
|
import { resolve as resolve27, join as join19, basename as basename7 } from "path";
|
|
1206
1207
|
import { homedir as homedir3 } from "os";
|
|
1207
1208
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
@@ -6861,7 +6862,7 @@ app3.get("/group-info", async (c) => {
|
|
|
6861
6862
|
var whatsapp_default = app3;
|
|
6862
6863
|
|
|
6863
6864
|
// server/routes/whatsapp-reader.ts
|
|
6864
|
-
import { readFileSync as readFileSync10, watch, statSync as statSync4, openSync, readSync, closeSync } from "fs";
|
|
6865
|
+
import { readFileSync as readFileSync10, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync6 } from "fs";
|
|
6865
6866
|
import { basename as basename2, dirname, join as join9, resolve as resolve9, sep as sep2 } from "path";
|
|
6866
6867
|
|
|
6867
6868
|
// server/routes/admin/sidebar-sessions.ts
|
|
@@ -7126,7 +7127,9 @@ function selectAdminChannelSessions(rows) {
|
|
|
7126
7127
|
senderId: r.senderId,
|
|
7127
7128
|
startedAt: r.startedAt,
|
|
7128
7129
|
channel: r.channel,
|
|
7129
|
-
operatorName: null
|
|
7130
|
+
operatorName: null,
|
|
7131
|
+
whatsappName: null,
|
|
7132
|
+
lastMessageAt: r.lastMessageAt
|
|
7130
7133
|
}));
|
|
7131
7134
|
}
|
|
7132
7135
|
|
|
@@ -7264,6 +7267,12 @@ function toolResultTurns(content, ts) {
|
|
|
7264
7267
|
}
|
|
7265
7268
|
return out;
|
|
7266
7269
|
}
|
|
7270
|
+
function lastTurnTs(turns) {
|
|
7271
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
7272
|
+
if (turns[i].ts) return turns[i].ts;
|
|
7273
|
+
}
|
|
7274
|
+
return null;
|
|
7275
|
+
}
|
|
7267
7276
|
function parseTranscript(lines) {
|
|
7268
7277
|
const out = [];
|
|
7269
7278
|
for (const line of lines) {
|
|
@@ -7340,6 +7349,7 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7340
7349
|
} catch {
|
|
7341
7350
|
}
|
|
7342
7351
|
const { title } = resolveTitle(body, sessionId, userTitles);
|
|
7352
|
+
const lastMessageAt = lastTurnTs(parseTranscript(body.split("\n")));
|
|
7343
7353
|
rows.push({
|
|
7344
7354
|
sessionId,
|
|
7345
7355
|
projectDir,
|
|
@@ -7347,7 +7357,8 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7347
7357
|
startedAt: meta.startedAt ?? "",
|
|
7348
7358
|
role: meta.role,
|
|
7349
7359
|
channel: meta.channel,
|
|
7350
|
-
senderId: meta.senderId
|
|
7360
|
+
senderId: meta.senderId,
|
|
7361
|
+
lastMessageAt
|
|
7351
7362
|
});
|
|
7352
7363
|
}
|
|
7353
7364
|
const selected = selectAdminChannelSessions(rows);
|
|
@@ -7363,11 +7374,13 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7363
7374
|
}
|
|
7364
7375
|
const admins = account?.config.admins ?? [];
|
|
7365
7376
|
const nameBySender = /* @__PURE__ */ new Map();
|
|
7377
|
+
const whatsappNameBySender = /* @__PURE__ */ new Map();
|
|
7366
7378
|
const distinct = [...new Set(selected.map((r) => r.senderId).filter((s) => !!s))];
|
|
7367
7379
|
await Promise.all(
|
|
7368
7380
|
distinct.map(async (senderId) => {
|
|
7369
7381
|
if (!account) {
|
|
7370
7382
|
nameBySender.set(senderId, null);
|
|
7383
|
+
whatsappNameBySender.set(senderId, null);
|
|
7371
7384
|
return;
|
|
7372
7385
|
}
|
|
7373
7386
|
const idRes = classifyAdminUserId(users, admins, senderId);
|
|
@@ -7375,12 +7388,22 @@ app5.get("/conversations", requireAdminSession, async (c) => {
|
|
|
7375
7388
|
const { name, reason } = resolveOperatorDisplay(idRes, nameRes);
|
|
7376
7389
|
if (reason) console.error(`[wa-reader] op=operator-unresolved senderId=${senderId} reason=${reason}`);
|
|
7377
7390
|
nameBySender.set(senderId, name);
|
|
7391
|
+
if (!name) {
|
|
7392
|
+
const waName = await loadWhatsappSenderName(account.accountId, senderId);
|
|
7393
|
+
if (waName) console.error(`[wa-reader] op=operator-name-fallback senderId=${senderId} source=whatsapp-pushname`);
|
|
7394
|
+
whatsappNameBySender.set(senderId, waName);
|
|
7395
|
+
} else {
|
|
7396
|
+
whatsappNameBySender.set(senderId, null);
|
|
7397
|
+
}
|
|
7378
7398
|
})
|
|
7379
7399
|
);
|
|
7380
7400
|
const conversations = selected.map((r) => ({
|
|
7381
7401
|
...r,
|
|
7382
|
-
operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null
|
|
7402
|
+
operatorName: r.senderId ? nameBySender.get(r.senderId) ?? null : null,
|
|
7403
|
+
whatsappName: r.senderId ? whatsappNameBySender.get(r.senderId) ?? null : null
|
|
7383
7404
|
}));
|
|
7405
|
+
const withTimestamp = conversations.filter((conv) => conv.lastMessageAt).length;
|
|
7406
|
+
console.log(`[wa-reader] op=conversations count=${conversations.length} withTimestamp=${withTimestamp}`);
|
|
7384
7407
|
return c.json({ conversations });
|
|
7385
7408
|
});
|
|
7386
7409
|
function readFrom(path2, from) {
|
|
@@ -7492,12 +7515,60 @@ data: ${JSON.stringify(turn)}
|
|
|
7492
7515
|
headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
|
|
7493
7516
|
});
|
|
7494
7517
|
});
|
|
7518
|
+
var DIRECTIVE_NAME_RE = /^\d+-\d+\.txt$/;
|
|
7519
|
+
function directiveStoreDir(sessionId) {
|
|
7520
|
+
const account = resolveAccount();
|
|
7521
|
+
if (!account) return null;
|
|
7522
|
+
return resolve9(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
|
|
7523
|
+
}
|
|
7524
|
+
app5.get("/directives", requireAdminSession, (c) => {
|
|
7525
|
+
const sessionId = c.req.query("sessionId") ?? "";
|
|
7526
|
+
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
7527
|
+
const dir = directiveStoreDir(sessionId);
|
|
7528
|
+
if (!dir || !existsSync7(dir)) return c.json({ entries: [] });
|
|
7529
|
+
let names;
|
|
7530
|
+
try {
|
|
7531
|
+
names = readdirSync6(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
7532
|
+
} catch {
|
|
7533
|
+
return c.json({ entries: [] });
|
|
7534
|
+
}
|
|
7535
|
+
const entries = names.map((name) => {
|
|
7536
|
+
const [secsPart, pidPart] = name.replace(/\.txt$/, "").split("-");
|
|
7537
|
+
const secs = Number(secsPart);
|
|
7538
|
+
const pid = Number(pidPart);
|
|
7539
|
+
let len = 0;
|
|
7540
|
+
try {
|
|
7541
|
+
len = statSync4(join9(dir, name)).size;
|
|
7542
|
+
} catch {
|
|
7543
|
+
}
|
|
7544
|
+
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
7545
|
+
}).sort((a, b) => a.secs - b.secs || a.pid - b.pid).map(({ name, ts, len }) => ({ name, ts, len }));
|
|
7546
|
+
return c.json({ entries });
|
|
7547
|
+
});
|
|
7548
|
+
app5.get("/directive", requireAdminSession, (c) => {
|
|
7549
|
+
const sessionId = c.req.query("sessionId") ?? "";
|
|
7550
|
+
const name = c.req.query("name") ?? "";
|
|
7551
|
+
if (!SESSION_ID_RE2.test(sessionId) || !DIRECTIVE_NAME_RE.test(name)) {
|
|
7552
|
+
return c.json({ error: "bad reference" }, 400);
|
|
7553
|
+
}
|
|
7554
|
+
const dir = directiveStoreDir(sessionId);
|
|
7555
|
+
if (!dir) return c.json({ error: "no account" }, 404);
|
|
7556
|
+
const path2 = resolve9(join9(dir, name));
|
|
7557
|
+
if (!path2.startsWith(dir + sep2)) return c.json({ error: "bad reference" }, 400);
|
|
7558
|
+
let body;
|
|
7559
|
+
try {
|
|
7560
|
+
body = readFileSync10(path2, "utf8");
|
|
7561
|
+
} catch {
|
|
7562
|
+
return c.json({ error: "not found" }, 404);
|
|
7563
|
+
}
|
|
7564
|
+
return c.text(body);
|
|
7565
|
+
});
|
|
7495
7566
|
var whatsapp_reader_default = app5;
|
|
7496
7567
|
|
|
7497
7568
|
// server/routes/telegram.ts
|
|
7498
7569
|
import { homedir } from "os";
|
|
7499
7570
|
import { resolve as resolve10, join as join10 } from "path";
|
|
7500
|
-
import { existsSync as
|
|
7571
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11 } from "fs";
|
|
7501
7572
|
|
|
7502
7573
|
// app/lib/telegram/access-control.ts
|
|
7503
7574
|
function checkTelegramAccess(params) {
|
|
@@ -7549,7 +7620,7 @@ var DISPATCH_TIMEOUT_MS = 12e4;
|
|
|
7549
7620
|
function configDirName() {
|
|
7550
7621
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve10(process.cwd(), "..");
|
|
7551
7622
|
const brandPath = join10(platformRoot2, "config", "brand.json");
|
|
7552
|
-
if (
|
|
7623
|
+
if (existsSync8(brandPath)) {
|
|
7553
7624
|
try {
|
|
7554
7625
|
return JSON.parse(readFileSync11(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
7555
7626
|
} catch {
|
|
@@ -7583,7 +7654,7 @@ app6.post("/", async (c) => {
|
|
|
7583
7654
|
return c.json({ ok: false }, 400);
|
|
7584
7655
|
}
|
|
7585
7656
|
const sp = secretPath(botType);
|
|
7586
|
-
if (!
|
|
7657
|
+
if (!existsSync8(sp)) {
|
|
7587
7658
|
console.error(`${TAG21} op=reject reason=no-secret-file botType=${botType}`);
|
|
7588
7659
|
return c.json({ ok: false }, 401);
|
|
7589
7660
|
}
|
|
@@ -7650,11 +7721,11 @@ var telegram_default = app6;
|
|
|
7650
7721
|
|
|
7651
7722
|
// server/routes/onboarding.ts
|
|
7652
7723
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
|
|
7653
|
-
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as
|
|
7724
|
+
import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync10, readFileSync as readFileSync13, unlinkSync } from "fs";
|
|
7654
7725
|
import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
|
|
7655
7726
|
|
|
7656
7727
|
// ../lib/admins-write/src/index.ts
|
|
7657
|
-
import { existsSync as
|
|
7728
|
+
import { existsSync as existsSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
|
|
7658
7729
|
import { dirname as dirname2, join as join11 } from "path";
|
|
7659
7730
|
function logLine(input, result) {
|
|
7660
7731
|
const userIdShort = input.userId.slice(0, 8);
|
|
@@ -7672,7 +7743,7 @@ function writeAdminEntry(input) {
|
|
|
7672
7743
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
7673
7744
|
try {
|
|
7674
7745
|
let users = [];
|
|
7675
|
-
if (
|
|
7746
|
+
if (existsSync9(input.usersFile)) {
|
|
7676
7747
|
const raw = readFileSync12(input.usersFile, "utf-8").trim();
|
|
7677
7748
|
if (raw) {
|
|
7678
7749
|
const parsed = JSON.parse(raw);
|
|
@@ -7698,7 +7769,7 @@ function writeAdminEntry(input) {
|
|
|
7698
7769
|
}
|
|
7699
7770
|
try {
|
|
7700
7771
|
const accountJsonPath = join11(input.accountDir, "account.json");
|
|
7701
|
-
if (!
|
|
7772
|
+
if (!existsSync9(accountJsonPath)) {
|
|
7702
7773
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
7703
7774
|
}
|
|
7704
7775
|
const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
|
|
@@ -7725,7 +7796,7 @@ function checkAdminAuthInvariant(input) {
|
|
|
7725
7796
|
usersWithoutAccount: []
|
|
7726
7797
|
};
|
|
7727
7798
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
7728
|
-
if (
|
|
7799
|
+
if (existsSync9(input.usersFile)) {
|
|
7729
7800
|
try {
|
|
7730
7801
|
const raw = readFileSync12(input.usersFile, "utf-8").trim();
|
|
7731
7802
|
if (raw) {
|
|
@@ -7740,10 +7811,10 @@ function checkAdminAuthInvariant(input) {
|
|
|
7740
7811
|
}
|
|
7741
7812
|
}
|
|
7742
7813
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
7743
|
-
if (
|
|
7814
|
+
if (existsSync9(input.accountsDir)) {
|
|
7744
7815
|
let entries;
|
|
7745
7816
|
try {
|
|
7746
|
-
entries =
|
|
7817
|
+
entries = readdirSync7(input.accountsDir);
|
|
7747
7818
|
} catch (err) {
|
|
7748
7819
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7749
7820
|
console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
|
|
@@ -7759,7 +7830,7 @@ function checkAdminAuthInvariant(input) {
|
|
|
7759
7830
|
continue;
|
|
7760
7831
|
}
|
|
7761
7832
|
const accountJsonPath = join11(accountDir, "account.json");
|
|
7762
|
-
if (!
|
|
7833
|
+
if (!existsSync9(accountJsonPath)) continue;
|
|
7763
7834
|
let admins = [];
|
|
7764
7835
|
try {
|
|
7765
7836
|
const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
|
|
@@ -7802,7 +7873,7 @@ function hashPin2(pin) {
|
|
|
7802
7873
|
return createHash3("sha256").update(pin).digest("hex");
|
|
7803
7874
|
}
|
|
7804
7875
|
function readUsersFile2() {
|
|
7805
|
-
if (!
|
|
7876
|
+
if (!existsSync10(USERS_FILE)) return null;
|
|
7806
7877
|
const raw = readFileSync13(USERS_FILE, "utf-8").trim();
|
|
7807
7878
|
if (!raw) return [];
|
|
7808
7879
|
return JSON.parse(raw);
|
|
@@ -7957,7 +8028,7 @@ app7.post("/set-pin", async (c) => {
|
|
|
7957
8028
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
7958
8029
|
if (process.platform === "linux") {
|
|
7959
8030
|
let installOwner = null;
|
|
7960
|
-
if (
|
|
8031
|
+
if (existsSync10(INSTALL_OWNER_FILE)) {
|
|
7961
8032
|
try {
|
|
7962
8033
|
const raw = readFileSync13(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
7963
8034
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -8040,7 +8111,7 @@ app7.delete("/set-pin", async (c) => {
|
|
|
8040
8111
|
var onboarding_default = app7;
|
|
8041
8112
|
|
|
8042
8113
|
// server/routes/client-error.ts
|
|
8043
|
-
import { appendFileSync, existsSync as
|
|
8114
|
+
import { appendFileSync, existsSync as existsSync11, renameSync as renameSync2, statSync as statSync6 } from "fs";
|
|
8044
8115
|
import { join as join12 } from "path";
|
|
8045
8116
|
var CLIENT_ERRORS_LOG = join12(LOG_DIR, "client-errors.log");
|
|
8046
8117
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
@@ -8085,7 +8156,7 @@ function stackHead(stack) {
|
|
|
8085
8156
|
}
|
|
8086
8157
|
function rotateIfNeeded() {
|
|
8087
8158
|
try {
|
|
8088
|
-
if (!
|
|
8159
|
+
if (!existsSync11(CLIENT_ERRORS_LOG)) return;
|
|
8089
8160
|
const stats = statSync6(CLIENT_ERRORS_LOG);
|
|
8090
8161
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
8091
8162
|
renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
@@ -8367,18 +8438,18 @@ app9.post("/", async (c) => {
|
|
|
8367
8438
|
var session_default = app9;
|
|
8368
8439
|
|
|
8369
8440
|
// server/routes/admin/logs.ts
|
|
8370
|
-
import { existsSync as
|
|
8441
|
+
import { existsSync as existsSync13, readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
|
|
8371
8442
|
import { resolve as resolve11, basename as basename3 } from "path";
|
|
8372
8443
|
|
|
8373
8444
|
// app/lib/logs-read-resolve.ts
|
|
8374
|
-
import { existsSync as
|
|
8445
|
+
import { existsSync as existsSync12 } from "fs";
|
|
8375
8446
|
import { join as join13 } from "path";
|
|
8376
8447
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
8377
8448
|
const tried = [filename];
|
|
8378
8449
|
const hits = [];
|
|
8379
8450
|
for (const dir of logDirs) {
|
|
8380
8451
|
const fullPath = join13(dir, filename);
|
|
8381
|
-
if (
|
|
8452
|
+
if (existsSync12(fullPath)) {
|
|
8382
8453
|
hits.push({ path: fullPath, dir });
|
|
8383
8454
|
}
|
|
8384
8455
|
}
|
|
@@ -8506,10 +8577,10 @@ app10.get("/", async (c) => {
|
|
|
8506
8577
|
const seen = /* @__PURE__ */ new Set();
|
|
8507
8578
|
const logs = {};
|
|
8508
8579
|
for (const dir of logDirs) {
|
|
8509
|
-
if (!
|
|
8580
|
+
if (!existsSync13(dir)) continue;
|
|
8510
8581
|
let files;
|
|
8511
8582
|
try {
|
|
8512
|
-
files =
|
|
8583
|
+
files = readdirSync8(dir).filter((f) => f.endsWith(".log"));
|
|
8513
8584
|
} catch (err) {
|
|
8514
8585
|
const reason = err instanceof Error ? err.message : String(err);
|
|
8515
8586
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
@@ -8557,7 +8628,7 @@ var claude_info_default = app11;
|
|
|
8557
8628
|
|
|
8558
8629
|
// server/routes/admin/attachment.ts
|
|
8559
8630
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
8560
|
-
import { existsSync as
|
|
8631
|
+
import { existsSync as existsSync14 } from "fs";
|
|
8561
8632
|
import { resolve as resolve12 } from "path";
|
|
8562
8633
|
var app12 = new Hono();
|
|
8563
8634
|
app12.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
@@ -8571,11 +8642,11 @@ app12.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
8571
8642
|
return new Response("Not found", { status: 404 });
|
|
8572
8643
|
}
|
|
8573
8644
|
const dir = resolve12(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
8574
|
-
if (!
|
|
8645
|
+
if (!existsSync14(dir)) {
|
|
8575
8646
|
return new Response("Not found", { status: 404 });
|
|
8576
8647
|
}
|
|
8577
8648
|
const metaPath = resolve12(dir, `${attachmentId}.meta.json`);
|
|
8578
|
-
if (!
|
|
8649
|
+
if (!existsSync14(metaPath)) {
|
|
8579
8650
|
return new Response("Not found", { status: 404 });
|
|
8580
8651
|
}
|
|
8581
8652
|
let meta;
|
|
@@ -8603,21 +8674,21 @@ var attachment_default = app12;
|
|
|
8603
8674
|
|
|
8604
8675
|
// server/routes/admin/agents.ts
|
|
8605
8676
|
import { resolve as resolve13 } from "path";
|
|
8606
|
-
import { readdirSync as
|
|
8677
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync15, existsSync as existsSync15, rmSync } from "fs";
|
|
8607
8678
|
var app13 = new Hono();
|
|
8608
8679
|
app13.get("/", (c) => {
|
|
8609
8680
|
const account = resolveAccount();
|
|
8610
8681
|
if (!account) return c.json({ agents: [] });
|
|
8611
8682
|
const agentsDir = resolve13(account.accountDir, "agents");
|
|
8612
|
-
if (!
|
|
8683
|
+
if (!existsSync15(agentsDir)) return c.json({ agents: [] });
|
|
8613
8684
|
const agents = [];
|
|
8614
8685
|
try {
|
|
8615
|
-
const entries =
|
|
8686
|
+
const entries = readdirSync9(agentsDir, { withFileTypes: true });
|
|
8616
8687
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
8617
8688
|
if (!entry.isDirectory()) continue;
|
|
8618
8689
|
if (entry.name === "admin") continue;
|
|
8619
8690
|
const configPath2 = resolve13(agentsDir, entry.name, "config.json");
|
|
8620
|
-
if (!
|
|
8691
|
+
if (!existsSync15(configPath2)) continue;
|
|
8621
8692
|
try {
|
|
8622
8693
|
const config = JSON.parse(readFileSync15(configPath2, "utf-8"));
|
|
8623
8694
|
agents.push({
|
|
@@ -8646,7 +8717,7 @@ app13.delete("/:slug", async (c) => {
|
|
|
8646
8717
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
8647
8718
|
}
|
|
8648
8719
|
const agentDir = resolve13(account.accountDir, "agents", slug);
|
|
8649
|
-
if (!
|
|
8720
|
+
if (!existsSync15(agentDir)) {
|
|
8650
8721
|
return c.json({ error: "Agent not found" }, 404);
|
|
8651
8722
|
}
|
|
8652
8723
|
try {
|
|
@@ -8676,7 +8747,7 @@ app13.post("/:slug/project", async (c) => {
|
|
|
8676
8747
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
8677
8748
|
}
|
|
8678
8749
|
const agentDir = resolve13(account.accountDir, "agents", slug);
|
|
8679
|
-
if (!
|
|
8750
|
+
if (!existsSync15(agentDir)) {
|
|
8680
8751
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
8681
8752
|
}
|
|
8682
8753
|
try {
|
|
@@ -8692,7 +8763,7 @@ var agents_default = app13;
|
|
|
8692
8763
|
// server/routes/admin/sessions.ts
|
|
8693
8764
|
import crypto2 from "crypto";
|
|
8694
8765
|
import { resolve as resolvePath } from "path";
|
|
8695
|
-
import { existsSync as
|
|
8766
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync3, createWriteStream } from "fs";
|
|
8696
8767
|
|
|
8697
8768
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
8698
8769
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -8852,7 +8923,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
8852
8923
|
let reason = null;
|
|
8853
8924
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
8854
8925
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
8855
|
-
else if (!
|
|
8926
|
+
else if (!existsSync16(a.storagePath)) reason = "missing-file";
|
|
8856
8927
|
if (reason) {
|
|
8857
8928
|
invalid++;
|
|
8858
8929
|
try {
|
|
@@ -9378,7 +9449,7 @@ app14.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
9378
9449
|
var sessions_default = app14;
|
|
9379
9450
|
|
|
9380
9451
|
// app/lib/claude-agent/spawn-context.ts
|
|
9381
|
-
import { existsSync as
|
|
9452
|
+
import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
|
|
9382
9453
|
import { dirname as dirname3, resolve as resolve14, join as join14 } from "path";
|
|
9383
9454
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
9384
9455
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
@@ -9413,7 +9484,7 @@ function extractPluginToolDescriptions(pluginDir) {
|
|
|
9413
9484
|
];
|
|
9414
9485
|
let raw = null;
|
|
9415
9486
|
for (const path2 of candidates) {
|
|
9416
|
-
if (!
|
|
9487
|
+
if (!existsSync17(path2)) continue;
|
|
9417
9488
|
try {
|
|
9418
9489
|
raw = readFileSync16(path2, "utf-8");
|
|
9419
9490
|
break;
|
|
@@ -9465,8 +9536,8 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
9465
9536
|
function listPluginDirs() {
|
|
9466
9537
|
const out = /* @__PURE__ */ new Map();
|
|
9467
9538
|
const platformPlugins = resolve14(PLATFORM_ROOT, "plugins");
|
|
9468
|
-
if (
|
|
9469
|
-
for (const name of
|
|
9539
|
+
if (existsSync17(platformPlugins)) {
|
|
9540
|
+
for (const name of readdirSync10(platformPlugins)) {
|
|
9470
9541
|
const dir = join14(platformPlugins, name);
|
|
9471
9542
|
try {
|
|
9472
9543
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
@@ -9475,12 +9546,12 @@ function listPluginDirs() {
|
|
|
9475
9546
|
}
|
|
9476
9547
|
}
|
|
9477
9548
|
const premiumRoot = resolve14(dirname3(PLATFORM_ROOT), "premium-plugins");
|
|
9478
|
-
if (
|
|
9479
|
-
for (const bundle of
|
|
9549
|
+
if (existsSync17(premiumRoot)) {
|
|
9550
|
+
for (const bundle of readdirSync10(premiumRoot)) {
|
|
9480
9551
|
const bundlePlugins = join14(premiumRoot, bundle, "plugins");
|
|
9481
|
-
if (!
|
|
9552
|
+
if (!existsSync17(bundlePlugins)) continue;
|
|
9482
9553
|
try {
|
|
9483
|
-
for (const name of
|
|
9554
|
+
for (const name of readdirSync10(bundlePlugins)) {
|
|
9484
9555
|
const dir = join14(bundlePlugins, name);
|
|
9485
9556
|
try {
|
|
9486
9557
|
if (statSync8(dir).isDirectory()) out.set(name, dir);
|
|
@@ -9495,7 +9566,7 @@ function listPluginDirs() {
|
|
|
9495
9566
|
}
|
|
9496
9567
|
function readEnabledPlugins(accountId) {
|
|
9497
9568
|
const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
9498
|
-
if (!
|
|
9569
|
+
if (!existsSync17(accountFile)) return /* @__PURE__ */ new Set();
|
|
9499
9570
|
try {
|
|
9500
9571
|
const parsed = JSON.parse(readFileSync16(accountFile, "utf-8"));
|
|
9501
9572
|
return new Set(
|
|
@@ -9506,7 +9577,7 @@ function readEnabledPlugins(accountId) {
|
|
|
9506
9577
|
}
|
|
9507
9578
|
}
|
|
9508
9579
|
function readFrontmatter(path2) {
|
|
9509
|
-
if (!
|
|
9580
|
+
if (!existsSync17(path2)) return null;
|
|
9510
9581
|
let raw;
|
|
9511
9582
|
try {
|
|
9512
9583
|
raw = readFileSync16(path2, "utf-8");
|
|
@@ -9541,7 +9612,7 @@ ${fm}
|
|
|
9541
9612
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
9542
9613
|
);
|
|
9543
9614
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
9544
|
-
const hasSource =
|
|
9615
|
+
const hasSource = existsSync17(join14(dir, "mcp/dist/index.js")) || existsSync17(join14(dir, "mcp/src/index.ts"));
|
|
9545
9616
|
if (hasSource) {
|
|
9546
9617
|
console.warn(
|
|
9547
9618
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -9568,10 +9639,10 @@ ${skillFm}
|
|
|
9568
9639
|
}
|
|
9569
9640
|
function computeSpecialistDomains(accountId) {
|
|
9570
9641
|
const specialistsDir = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
9571
|
-
if (!
|
|
9642
|
+
if (!existsSync17(specialistsDir)) return [];
|
|
9572
9643
|
let entries;
|
|
9573
9644
|
try {
|
|
9574
|
-
entries =
|
|
9645
|
+
entries = readdirSync10(specialistsDir);
|
|
9575
9646
|
} catch {
|
|
9576
9647
|
return [];
|
|
9577
9648
|
}
|
|
@@ -9614,7 +9685,7 @@ ${fm}
|
|
|
9614
9685
|
}
|
|
9615
9686
|
function computeDormantPlugins(accountId) {
|
|
9616
9687
|
const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
9617
|
-
if (!
|
|
9688
|
+
if (!existsSync17(accountFile)) return [];
|
|
9618
9689
|
let enabled;
|
|
9619
9690
|
try {
|
|
9620
9691
|
const raw = readFileSync16(accountFile, "utf-8");
|
|
@@ -9629,10 +9700,10 @@ function computeDormantPlugins(accountId) {
|
|
|
9629
9700
|
return [];
|
|
9630
9701
|
}
|
|
9631
9702
|
const pluginsDir = resolve14(PLATFORM_ROOT, "plugins");
|
|
9632
|
-
if (!
|
|
9703
|
+
if (!existsSync17(pluginsDir)) return [];
|
|
9633
9704
|
let entries;
|
|
9634
9705
|
try {
|
|
9635
|
-
entries =
|
|
9706
|
+
entries = readdirSync10(pluginsDir);
|
|
9636
9707
|
} catch {
|
|
9637
9708
|
return [];
|
|
9638
9709
|
}
|
|
@@ -9640,7 +9711,7 @@ function computeDormantPlugins(accountId) {
|
|
|
9640
9711
|
for (const name of entries) {
|
|
9641
9712
|
if (enabled.has(name)) continue;
|
|
9642
9713
|
const manifestPath = resolve14(pluginsDir, name, "PLUGIN.md");
|
|
9643
|
-
if (!
|
|
9714
|
+
if (!existsSync17(manifestPath)) continue;
|
|
9644
9715
|
let manifest;
|
|
9645
9716
|
try {
|
|
9646
9717
|
manifest = readFileSync16(manifestPath, "utf-8");
|
|
@@ -9657,11 +9728,11 @@ function computeDormantPlugins(accountId) {
|
|
|
9657
9728
|
}
|
|
9658
9729
|
|
|
9659
9730
|
// server/routes/admin/claude-sessions.ts
|
|
9660
|
-
import { existsSync as
|
|
9731
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
|
|
9661
9732
|
import { resolve as resolve15 } from "path";
|
|
9662
9733
|
function readTunnelState(brandConfigDir) {
|
|
9663
9734
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
9664
|
-
if (!
|
|
9735
|
+
if (!existsSync18(statePath)) return null;
|
|
9665
9736
|
try {
|
|
9666
9737
|
const parsed = JSON.parse(readFileSync17(statePath, "utf-8"));
|
|
9667
9738
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -13097,7 +13168,7 @@ var graph_default_view_default = app24;
|
|
|
13097
13168
|
// server/routes/admin/sidebar-artefacts.ts
|
|
13098
13169
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
13099
13170
|
import { resolve as resolve19, relative as relative3, isAbsolute, sep as sep6, basename as basename6 } from "path";
|
|
13100
|
-
import { existsSync as
|
|
13171
|
+
import { existsSync as existsSync19 } from "fs";
|
|
13101
13172
|
var LIMIT = 50;
|
|
13102
13173
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
13103
13174
|
function toDataRootRelPath(absPath) {
|
|
@@ -13203,7 +13274,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
13203
13274
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
13204
13275
|
const names = /* @__PURE__ */ new Set();
|
|
13205
13276
|
for (const dir of [overrideDir, bundledDir]) {
|
|
13206
|
-
if (!
|
|
13277
|
+
if (!existsSync19(dir)) continue;
|
|
13207
13278
|
try {
|
|
13208
13279
|
const entries = await readdir4(dir);
|
|
13209
13280
|
for (const entry of entries) {
|
|
@@ -13218,7 +13289,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
13218
13289
|
}
|
|
13219
13290
|
async function readAgentTemplateRow(inp) {
|
|
13220
13291
|
let chosenPath = null;
|
|
13221
|
-
if (
|
|
13292
|
+
if (existsSync19(inp.overridePath)) {
|
|
13222
13293
|
try {
|
|
13223
13294
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
13224
13295
|
chosenPath = inp.overridePath;
|
|
@@ -13229,7 +13300,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
13229
13300
|
);
|
|
13230
13301
|
return null;
|
|
13231
13302
|
}
|
|
13232
|
-
} else if (
|
|
13303
|
+
} else if (existsSync19(inp.bundledPath)) {
|
|
13233
13304
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
13234
13305
|
console.error(
|
|
13235
13306
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -13553,12 +13624,12 @@ app30.get("/", async (c) => {
|
|
|
13553
13624
|
var system_stats_default = app30;
|
|
13554
13625
|
|
|
13555
13626
|
// server/routes/admin/health.ts
|
|
13556
|
-
import { existsSync as
|
|
13627
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
|
|
13557
13628
|
import { resolve as resolve20, join as join17 } from "path";
|
|
13558
13629
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
|
|
13559
13630
|
var brandHostname = "maxy";
|
|
13560
13631
|
var brandJsonPath = join17(PLATFORM_ROOT6, "config", "brand.json");
|
|
13561
|
-
if (
|
|
13632
|
+
if (existsSync20(brandJsonPath)) {
|
|
13562
13633
|
try {
|
|
13563
13634
|
const brand = JSON.parse(readFileSync18(brandJsonPath, "utf-8"));
|
|
13564
13635
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -13569,7 +13640,7 @@ var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
13569
13640
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
13570
13641
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
13571
13642
|
function readVersion() {
|
|
13572
|
-
if (!
|
|
13643
|
+
if (!existsSync20(VERSION_FILE)) return "unknown";
|
|
13573
13644
|
return readFileSync18(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
13574
13645
|
}
|
|
13575
13646
|
async function probeConversationDb() {
|
|
@@ -14553,7 +14624,7 @@ app41.route("/request-magic-link", request_magic_link_default);
|
|
|
14553
14624
|
var access_default = app41;
|
|
14554
14625
|
|
|
14555
14626
|
// server/routes/sites.ts
|
|
14556
|
-
import { existsSync as
|
|
14627
|
+
import { existsSync as existsSync21, readFileSync as readFileSync20, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
|
|
14557
14628
|
import { resolve as resolve23 } from "path";
|
|
14558
14629
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
14559
14630
|
var MIME = {
|
|
@@ -14619,7 +14690,7 @@ app42.get("/:rel{.*}", (c) => {
|
|
|
14619
14690
|
}
|
|
14620
14691
|
let stat7;
|
|
14621
14692
|
try {
|
|
14622
|
-
stat7 =
|
|
14693
|
+
stat7 = existsSync21(filePath) ? statSync9(filePath) : null;
|
|
14623
14694
|
} catch {
|
|
14624
14695
|
stat7 = null;
|
|
14625
14696
|
}
|
|
@@ -14638,7 +14709,7 @@ app42.get("/:rel{.*}", (c) => {
|
|
|
14638
14709
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
14639
14710
|
return c.text("Forbidden", 403);
|
|
14640
14711
|
}
|
|
14641
|
-
if (!
|
|
14712
|
+
if (!existsSync21(filePath)) {
|
|
14642
14713
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
14643
14714
|
return c.text("Not found", 404);
|
|
14644
14715
|
}
|
|
@@ -14769,7 +14840,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
14769
14840
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
14770
14841
|
|
|
14771
14842
|
// app/lib/brand-config.ts
|
|
14772
|
-
import { existsSync as
|
|
14843
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "fs";
|
|
14773
14844
|
import { join as join18 } from "path";
|
|
14774
14845
|
var cached2 = null;
|
|
14775
14846
|
var cachedAttempted = false;
|
|
@@ -14779,7 +14850,7 @@ function readBrandConfig() {
|
|
|
14779
14850
|
const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
|
|
14780
14851
|
if (!platformRoot2) return null;
|
|
14781
14852
|
const brandPath = join18(platformRoot2, "config", "brand.json");
|
|
14782
|
-
if (!
|
|
14853
|
+
if (!existsSync22(brandPath)) return null;
|
|
14783
14854
|
try {
|
|
14784
14855
|
cached2 = JSON.parse(readFileSync22(brandPath, "utf-8"));
|
|
14785
14856
|
return cached2;
|
|
@@ -15270,7 +15341,7 @@ var visitor_event_default = app45;
|
|
|
15270
15341
|
|
|
15271
15342
|
// server/routes/session.ts
|
|
15272
15343
|
import { resolve as resolve24 } from "path";
|
|
15273
|
-
import { existsSync as
|
|
15344
|
+
import { existsSync as existsSync23, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
|
|
15274
15345
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
15275
15346
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
15276
15347
|
try {
|
|
@@ -15365,7 +15436,7 @@ app46.post("/", async (c) => {
|
|
|
15365
15436
|
let agentConfig = null;
|
|
15366
15437
|
if (account) {
|
|
15367
15438
|
const agentDir = resolve24(account.accountDir, "agents", agentSlug);
|
|
15368
|
-
if (!
|
|
15439
|
+
if (!existsSync23(agentDir) || !existsSync23(resolve24(agentDir, "config.json"))) {
|
|
15369
15440
|
return c.json({ error: "Agent not found" }, 404);
|
|
15370
15441
|
}
|
|
15371
15442
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -16054,6 +16125,45 @@ function createWaChannelRoutes(deps) {
|
|
|
16054
16125
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
16055
16126
|
return c.json({ ok: true });
|
|
16056
16127
|
});
|
|
16128
|
+
app48.post("/wa-channel/reply-document", async (c) => {
|
|
16129
|
+
const body = await c.req.json().catch(() => null);
|
|
16130
|
+
const senderId = body?.senderId;
|
|
16131
|
+
const files = body?.files;
|
|
16132
|
+
const caption = typeof body?.caption === "string" ? body.caption : void 0;
|
|
16133
|
+
if (typeof senderId !== "string" || !Array.isArray(files) || files.length === 0 || !files.every((f) => typeof f === "string")) {
|
|
16134
|
+
return c.json({ error: "senderId and a non-empty files string array required" }, 400);
|
|
16135
|
+
}
|
|
16136
|
+
const results = [];
|
|
16137
|
+
for (let i = 0; i < files.length; i++) {
|
|
16138
|
+
const file = files[i];
|
|
16139
|
+
console.error(`[whatsapp-native] op=reply-document-request senderId=${senderId} file=${file}`);
|
|
16140
|
+
let outcome;
|
|
16141
|
+
try {
|
|
16142
|
+
outcome = await deps.sendDocument(senderId, file, i === 0 ? caption : void 0);
|
|
16143
|
+
} catch (err) {
|
|
16144
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16145
|
+
const terminal = err instanceof WaReplyError ? err.terminal : false;
|
|
16146
|
+
console.error(
|
|
16147
|
+
`[whatsapp-native] op=reply-document-failed senderId=${senderId} file=${file} terminal=${terminal} error=${message}`
|
|
16148
|
+
);
|
|
16149
|
+
return c.json({ error: message, terminal }, 403);
|
|
16150
|
+
}
|
|
16151
|
+
if (outcome.ok) {
|
|
16152
|
+
console.error(`[whatsapp-native] op=reply-document-dispatch senderId=${senderId} file=${file}`);
|
|
16153
|
+
console.error(`[whatsapp-native] op=reply-document-reconciled senderId=${senderId} file=${file}`);
|
|
16154
|
+
results.push({ file, ok: true, messageId: outcome.messageId });
|
|
16155
|
+
} else {
|
|
16156
|
+
console.error(
|
|
16157
|
+
`[whatsapp-adaptor] file-delivery-unreconciled senderId=${senderId} file=${file} reason=${outcome.error}`
|
|
16158
|
+
);
|
|
16159
|
+
console.error(
|
|
16160
|
+
`[whatsapp-native] op=reply-document-failed senderId=${senderId} file=${file} terminal=false error=${outcome.error}`
|
|
16161
|
+
);
|
|
16162
|
+
results.push({ file, ok: false, error: outcome.error });
|
|
16163
|
+
}
|
|
16164
|
+
}
|
|
16165
|
+
return c.json({ ok: true, results });
|
|
16166
|
+
});
|
|
16057
16167
|
app48.post("/wa-channel/ready", async (c) => {
|
|
16058
16168
|
const body = await c.req.json().catch(() => null);
|
|
16059
16169
|
const senderId = body?.senderId;
|
|
@@ -16086,6 +16196,10 @@ var WaGateway = class {
|
|
|
16086
16196
|
}
|
|
16087
16197
|
hub = new InboundHub();
|
|
16088
16198
|
replies = /* @__PURE__ */ new Map();
|
|
16199
|
+
// Per-sender document-delivery context (the Baileys accountId), set on every
|
|
16200
|
+
// inbound. Its presence is the reply-only guard: a sender with no inbound has
|
|
16201
|
+
// no context, so a file reply to a cold recipient is refused.
|
|
16202
|
+
docContexts = /* @__PURE__ */ new Map();
|
|
16089
16203
|
spawning = /* @__PURE__ */ new Set();
|
|
16090
16204
|
seq = 0;
|
|
16091
16205
|
/** Hono sub-app exposing the loopback channel routes; mount on the UI app. */
|
|
@@ -16093,6 +16207,7 @@ var WaGateway = class {
|
|
|
16093
16207
|
return createWaChannelRoutes({
|
|
16094
16208
|
hub: this.hub,
|
|
16095
16209
|
sendOutbound: (senderId, text) => this.sendOutbound(senderId, text),
|
|
16210
|
+
sendDocument: (senderId, filePath, caption) => this.sendDocument(senderId, filePath, caption),
|
|
16096
16211
|
onReady: (senderId) => {
|
|
16097
16212
|
const count = this.hub.markReady(senderId, Date.now());
|
|
16098
16213
|
if (count > 0) console.error(`[whatsapp-native] op=drained senderId=${senderId} count=${count}`);
|
|
@@ -16137,6 +16252,7 @@ var WaGateway = class {
|
|
|
16137
16252
|
const openable = input.media.filter((m) => m.type !== "audio");
|
|
16138
16253
|
const mediaField = openable.length > 0 ? `media=${openable.map((m) => m.type).join(",")} mediaPaths=${openable.map((m) => m.path).join(",")}` : input.media.some((m) => m.type === "audio") ? "media=audio mediaPath=transcribed" : "media=none";
|
|
16139
16254
|
this.replies.set(input.senderId, input.reply);
|
|
16255
|
+
this.docContexts.set(input.senderId, { accountId: input.accountId });
|
|
16140
16256
|
this.hub.deliver(
|
|
16141
16257
|
{
|
|
16142
16258
|
senderId: input.senderId,
|
|
@@ -16169,8 +16285,47 @@ var WaGateway = class {
|
|
|
16169
16285
|
if (!reply) throw new Error(`wa-gateway: no reply route for sender ${senderId}`);
|
|
16170
16286
|
await reply(text);
|
|
16171
16287
|
}
|
|
16288
|
+
/** Deliver a file to a sender as a WhatsApp document. Throws `WaReplyError`
|
|
16289
|
+
* (reply-only guard) when no inbound has registered a document context for
|
|
16290
|
+
* the sender — file delivery is only ever a reply on a live conversation. */
|
|
16291
|
+
async sendDocument(senderId, filePath, caption) {
|
|
16292
|
+
const ctx = this.docContexts.get(senderId);
|
|
16293
|
+
if (!ctx) throw new WaReplyError(`no conversation for sender ${senderId}`, false);
|
|
16294
|
+
return this.deps.sendDocument({ senderId, accountId: ctx.accountId, filePath, caption });
|
|
16295
|
+
}
|
|
16172
16296
|
};
|
|
16173
16297
|
|
|
16298
|
+
// app/lib/whatsapp/gateway/native-file-follower.ts
|
|
16299
|
+
function startNativeFileFollower(input) {
|
|
16300
|
+
const entry = {
|
|
16301
|
+
sessionId: input.sessionId,
|
|
16302
|
+
role: "admin",
|
|
16303
|
+
channel: "whatsapp",
|
|
16304
|
+
accountId: input.accountId,
|
|
16305
|
+
senderId: input.senderId,
|
|
16306
|
+
agentSlug: "admin",
|
|
16307
|
+
lastInboundAt: Date.now(),
|
|
16308
|
+
writeChain: Promise.resolve(),
|
|
16309
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
16310
|
+
pendingTurnText: "",
|
|
16311
|
+
followerAbort: null,
|
|
16312
|
+
followerRunning: false,
|
|
16313
|
+
sliceToken: "",
|
|
16314
|
+
personId: null,
|
|
16315
|
+
name: null
|
|
16316
|
+
};
|
|
16317
|
+
return startFollower({
|
|
16318
|
+
entry,
|
|
16319
|
+
tag: "[whatsapp-adaptor]",
|
|
16320
|
+
fileDelivery: makeWhatsAppFileDelivery(entry),
|
|
16321
|
+
// A resumed session's JSONL already holds prior SendUserFile tool_uses;
|
|
16322
|
+
// suppress replay so historical files are not re-sent on attach.
|
|
16323
|
+
suppressResumeReplay: true,
|
|
16324
|
+
onClose: input.onClose ?? (() => {
|
|
16325
|
+
})
|
|
16326
|
+
});
|
|
16327
|
+
}
|
|
16328
|
+
|
|
16174
16329
|
// app/lib/whatsapp/inbound/channel-admin-binding-drift.ts
|
|
16175
16330
|
function findChannelAdminBindingDrift(adminPhones, admins, users) {
|
|
16176
16331
|
const drift = [];
|
|
@@ -16236,7 +16391,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
16236
16391
|
|
|
16237
16392
|
// ../lib/entitlement/src/index.ts
|
|
16238
16393
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
16239
|
-
import { existsSync as
|
|
16394
|
+
import { existsSync as existsSync24, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
|
|
16240
16395
|
import { resolve as resolve26 } from "path";
|
|
16241
16396
|
|
|
16242
16397
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -16285,7 +16440,7 @@ function resolveEntitlement(brand, account) {
|
|
|
16285
16440
|
return logResolved(implicitTrust(account), null);
|
|
16286
16441
|
}
|
|
16287
16442
|
const entitlementPath = resolve26(brand.configDir, "entitlement.json");
|
|
16288
|
-
if (!
|
|
16443
|
+
if (!existsSync24(entitlementPath)) {
|
|
16289
16444
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
16290
16445
|
}
|
|
16291
16446
|
const stat7 = statSync10(entitlementPath);
|
|
@@ -16477,10 +16632,10 @@ function clientFrom(c) {
|
|
|
16477
16632
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
16478
16633
|
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join19(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
16479
16634
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
16480
|
-
if (BRAND_JSON_PATH && !
|
|
16635
|
+
if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
|
|
16481
16636
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
16482
16637
|
}
|
|
16483
|
-
if (BRAND_JSON_PATH &&
|
|
16638
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
16484
16639
|
try {
|
|
16485
16640
|
const parsed = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
|
|
16486
16641
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -16504,7 +16659,7 @@ var brandLoginOpts = {
|
|
|
16504
16659
|
var ALIAS_DOMAINS_PATH = join19(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
16505
16660
|
function loadAliasDomains() {
|
|
16506
16661
|
try {
|
|
16507
|
-
if (!
|
|
16662
|
+
if (!existsSync25(ALIAS_DOMAINS_PATH)) return null;
|
|
16508
16663
|
const parsed = JSON.parse(readFileSync24(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
16509
16664
|
if (!Array.isArray(parsed)) {
|
|
16510
16665
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -16530,9 +16685,29 @@ function isPublicHost(host) {
|
|
|
16530
16685
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
16531
16686
|
}
|
|
16532
16687
|
var app47 = new Hono();
|
|
16688
|
+
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
16533
16689
|
var waGateway = new WaGateway({
|
|
16534
16690
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
16535
16691
|
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
16692
|
+
// Task 751 — file delivery on the native channel: resolve the platform
|
|
16693
|
+
// account + path validation here and funnel through the shared send core.
|
|
16694
|
+
sendDocument: async ({ senderId, accountId, filePath, caption }) => {
|
|
16695
|
+
let maxyAccountId;
|
|
16696
|
+
try {
|
|
16697
|
+
maxyAccountId = resolvePlatformAccountId();
|
|
16698
|
+
} catch (err) {
|
|
16699
|
+
return { ok: false, error: `account-unresolved: ${err instanceof Error ? err.message : String(err)}` };
|
|
16700
|
+
}
|
|
16701
|
+
const result = await sendWhatsAppDocument({
|
|
16702
|
+
to: senderId,
|
|
16703
|
+
filePath,
|
|
16704
|
+
caption,
|
|
16705
|
+
accountId,
|
|
16706
|
+
maxyAccountId,
|
|
16707
|
+
platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, ".."))
|
|
16708
|
+
});
|
|
16709
|
+
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
16710
|
+
},
|
|
16536
16711
|
ensureChannelSession: async ({ accountId, senderId, gatewayUrl, serverPath }) => {
|
|
16537
16712
|
const userId = resolveAdminUserId({ accountId, senderPhone: senderId }) ?? void 0;
|
|
16538
16713
|
console.error(`[whatsapp-native] op=admin-identity senderId=${senderId} userId=${userId ?? "owner-fallback"}`);
|
|
@@ -16549,7 +16724,20 @@ var waGateway = new WaGateway({
|
|
|
16549
16724
|
});
|
|
16550
16725
|
if ("error" in result) {
|
|
16551
16726
|
console.error(`[whatsapp-native] spawn-failed senderId=${senderId} error=${result.error} status=${result.status}`);
|
|
16727
|
+
return;
|
|
16552
16728
|
}
|
|
16729
|
+
const prior = nativeFileFollowers.get(senderId);
|
|
16730
|
+
if (prior) prior.abort();
|
|
16731
|
+
let ac;
|
|
16732
|
+
ac = startNativeFileFollower({
|
|
16733
|
+
sessionId: adminSessionIdFor(accountId, senderId),
|
|
16734
|
+
senderId,
|
|
16735
|
+
accountId,
|
|
16736
|
+
onClose: () => {
|
|
16737
|
+
if (nativeFileFollowers.get(senderId) === ac) nativeFileFollowers.delete(senderId);
|
|
16738
|
+
}
|
|
16739
|
+
});
|
|
16740
|
+
nativeFileFollowers.set(senderId, ac);
|
|
16553
16741
|
}
|
|
16554
16742
|
});
|
|
16555
16743
|
app47.route("/", waGateway.routes());
|
|
@@ -16878,7 +17066,7 @@ app47.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
16878
17066
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
16879
17067
|
return c.text("Forbidden", 403);
|
|
16880
17068
|
}
|
|
16881
|
-
if (!
|
|
17069
|
+
if (!existsSync25(filePath)) {
|
|
16882
17070
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
16883
17071
|
return c.text("Not found", 404);
|
|
16884
17072
|
}
|
|
@@ -16908,7 +17096,7 @@ app47.get("/generated/:filename", (c) => {
|
|
|
16908
17096
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
16909
17097
|
return c.text("Forbidden", 403);
|
|
16910
17098
|
}
|
|
16911
|
-
if (!
|
|
17099
|
+
if (!existsSync25(filePath)) {
|
|
16912
17100
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
16913
17101
|
return c.text("Not found", 404);
|
|
16914
17102
|
}
|
|
@@ -16928,7 +17116,7 @@ app47.route("/v", visitor_consent_default);
|
|
|
16928
17116
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
16929
17117
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
16930
17118
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
16931
|
-
if (BRAND_JSON_PATH &&
|
|
17119
|
+
if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
|
|
16932
17120
|
try {
|
|
16933
17121
|
const fullBrand = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
|
|
16934
17122
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -16948,7 +17136,7 @@ function readInstalledVersion() {
|
|
|
16948
17136
|
try {
|
|
16949
17137
|
if (!PLATFORM_ROOT9) return "unknown";
|
|
16950
17138
|
const versionFile = join19(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
|
|
16951
|
-
if (!
|
|
17139
|
+
if (!existsSync25(versionFile)) return "unknown";
|
|
16952
17140
|
const content = readFileSync24(versionFile, "utf-8").trim();
|
|
16953
17141
|
return content || "unknown";
|
|
16954
17142
|
} catch {
|
|
@@ -17011,7 +17199,7 @@ function loadBrandingCache(agentSlug) {
|
|
|
17011
17199
|
const accountId = getDefaultAccountId();
|
|
17012
17200
|
if (!accountId) return null;
|
|
17013
17201
|
const cachePath = join19(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
17014
|
-
if (!
|
|
17202
|
+
if (!existsSync25(cachePath)) return null;
|
|
17015
17203
|
return JSON.parse(readFileSync24(cachePath, "utf-8"));
|
|
17016
17204
|
} catch {
|
|
17017
17205
|
return null;
|
|
@@ -17256,7 +17444,7 @@ try {
|
|
|
17256
17444
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
17257
17445
|
async function runAdminUserReconcileTick() {
|
|
17258
17446
|
try {
|
|
17259
|
-
if (!
|
|
17447
|
+
if (!existsSync25(USERS_FILE)) {
|
|
17260
17448
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
17261
17449
|
return;
|
|
17262
17450
|
}
|