@rubytech/create-sitedesk-code 0.1.528 → 0.1.529
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/lib/account-ingest-token/dist/index.d.ts +21 -0
- package/payload/platform/lib/account-ingest-token/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/account-ingest-token/dist/index.js +128 -0
- package/payload/platform/lib/account-ingest-token/dist/index.js.map +1 -0
- package/payload/platform/lib/account-ingest-token/src/index.ts +137 -0
- package/payload/platform/lib/account-ingest-token/tsconfig.json +8 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts +5 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/src/index.ts +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +5 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +37 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts +10 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js +22 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js.map +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +25 -4
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +22 -1
- package/payload/platform/plugins/docs/references/linkedin-extension.md +2 -2
- package/payload/platform/plugins/linkedin-extension/extension/README.md +3 -3
- package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +12 -7
- package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +4 -1
- package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +4 -1
- package/payload/platform/plugins/linkedin-extension/extension/options/options.html +3 -3
- package/payload/platform/plugins/linkedin-extension/extension/options/options.js +24 -16
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +45 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +15 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-Bx9vPuUg.js → AdminLoginScreens-zfexKfbT.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-BxJPbC3p.js → AdminShell-Cbk0TL1B.js} +1 -1
- package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.br +0 -0
- package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.gz +0 -0
- package/payload/server/public/assets/{CdpScreencastSurface-5HLhTQTV.js → CdpScreencastSurface-CLSQHh4e.js} +1 -1
- package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.br +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.gz +0 -0
- package/payload/server/public/assets/{activity-BaSYn62l.js → activity-u275Oc-u.js} +1 -1
- package/payload/server/public/assets/activity-u275Oc-u.js.br +0 -0
- package/payload/server/public/assets/activity-u275Oc-u.js.gz +0 -0
- package/payload/server/public/assets/{admin-CYCKrV_x.js → admin-Du1nR_hP.js} +1 -1
- package/payload/server/public/assets/admin-Du1nR_hP.js.br +0 -0
- package/payload/server/public/assets/admin-Du1nR_hP.js.gz +0 -0
- package/payload/server/public/assets/{agents-D8EJG-ta.js → agents-DJTxRLLU.js} +1 -1
- package/payload/server/public/assets/agents-DJTxRLLU.js.br +0 -0
- package/payload/server/public/assets/agents-DJTxRLLU.js.gz +0 -0
- package/payload/server/public/assets/{browser-D6Y_Zu8C.js → browser-Bft6zVkX.js} +1 -1
- package/payload/server/public/assets/browser-Bft6zVkX.js.br +0 -0
- package/payload/server/public/assets/browser-Bft6zVkX.js.gz +0 -0
- package/payload/server/public/assets/{calendar-DD4oVa-r.js → calendar-Ct-DCCqY.js} +1 -1
- package/payload/server/public/assets/calendar-Ct-DCCqY.js.br +0 -0
- package/payload/server/public/assets/calendar-Ct-DCCqY.js.gz +0 -0
- package/payload/server/public/assets/chat-pqasbAg8.js +1 -0
- package/payload/server/public/assets/chat-pqasbAg8.js.br +0 -0
- package/payload/server/public/assets/chat-pqasbAg8.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-C8LTc7lb.js +1 -0
- package/payload/server/public/assets/chevron-right-Lz9t7Hed.js +1 -0
- package/payload/server/public/assets/chevron-right-Lz9t7Hed.js.br +0 -0
- package/payload/server/public/assets/clock-D6QQFHwJ.js +1 -0
- package/payload/server/public/assets/clock-D6QQFHwJ.js.br +0 -0
- package/payload/server/public/assets/clock-D6QQFHwJ.js.gz +0 -0
- package/payload/server/public/assets/data-B1JJ3Y1T.js +1 -0
- package/payload/server/public/assets/data-B1JJ3Y1T.js.br +0 -0
- package/payload/server/public/assets/data-B1JJ3Y1T.js.gz +0 -0
- package/payload/server/public/assets/{file-download-sXU3_umF.js → file-download-C_fSe4dm.js} +1 -1
- package/payload/server/public/assets/file-download-C_fSe4dm.js.br +0 -0
- package/payload/server/public/assets/file-download-C_fSe4dm.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CeXBviDH.js → file-text-D7GbEcqj.js} +1 -1
- package/payload/server/public/assets/file-text-D7GbEcqj.js.br +0 -0
- package/payload/server/public/assets/file-text-D7GbEcqj.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-D2pQkgYW.js → graph-labels-Dlcb6cW7.js} +1 -1
- package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.gz +0 -0
- package/payload/server/public/assets/{graph-BSuDP6k7.js → graph-yl5qU1kO.js} +1 -1
- package/payload/server/public/assets/graph-yl5qU1kO.js.br +0 -0
- package/payload/server/public/assets/graph-yl5qU1kO.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-DlzSNygU.js → maximize-2-BS689r4W.js} +1 -1
- package/payload/server/public/assets/maximize-2-BS689r4W.js.br +0 -0
- package/payload/server/public/assets/maximize-2-BS689r4W.js.gz +0 -0
- package/payload/server/public/assets/{operator-BP61-xjz.js → operator-CvapnpIW.js} +1 -1
- package/payload/server/public/assets/operator-CvapnpIW.js.br +0 -0
- package/payload/server/public/assets/operator-CvapnpIW.js.gz +0 -0
- package/payload/server/public/assets/{page-eQ4OVros.js → page-987y4JbQ.js} +1 -1
- package/payload/server/public/assets/page-987y4JbQ.js.br +0 -0
- package/payload/server/public/assets/page-987y4JbQ.js.gz +0 -0
- package/payload/server/public/assets/{page-DX7ArY_s.js → page-DWkUH4Z_.js} +1 -1
- package/payload/server/public/assets/page-DWkUH4Z_.js.br +0 -0
- package/payload/server/public/assets/page-DWkUH4Z_.js.gz +0 -0
- package/payload/server/public/assets/{public-DPDKFKM2.js → public-D5pi-VFn.js} +1 -1
- package/payload/server/public/assets/public-D5pi-VFn.js.br +0 -0
- package/payload/server/public/assets/public-D5pi-VFn.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-BR0JbPFV.js → rotate-ccw-zNxnK36R.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.gz +0 -0
- package/payload/server/public/assets/routines-mZzrGA5y.js +2 -0
- package/payload/server/public/assets/routines-mZzrGA5y.js.br +0 -0
- package/payload/server/public/assets/routines-mZzrGA5y.js.gz +0 -0
- package/payload/server/public/assets/{skills-fH0uA7cj.js → skills-5A8PockT.js} +1 -1
- package/payload/server/public/assets/skills-5A8PockT.js.br +0 -0
- package/payload/server/public/assets/skills-5A8PockT.js.gz +0 -0
- package/payload/server/public/assets/{tasks-CrVzFrTR.js → tasks-B1_2wc6L.js} +1 -1
- package/payload/server/public/assets/tasks-B1_2wc6L.js.br +0 -0
- package/payload/server/public/assets/tasks-B1_2wc6L.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-C_0jiMpQ.js → time-entry-format-CJ2FSSQt.js} +1 -1
- package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-eLJHC_QJ.js → triangle-alert-CedsrgME.js} +1 -1
- package/payload/server/public/assets/triangle-alert-CedsrgME.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-CedsrgME.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-vPCmdOmY.js → useCopyFeedback-zjZZUC2-.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.gz +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css → useSubAccountSwitcher-72THldvm.css} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-72THldvm.css.br +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css.gz → useSubAccountSwitcher-72THldvm.css.gz} +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-D5bFDRqL.js → useVoiceRecorder-CJecnefX.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.gz +0 -0
- package/payload/server/public/assets/{wrench-sXisQXkf.js → wrench-D8BH20W8.js} +1 -1
- package/payload/server/public/assets/wrench-D8BH20W8.js.br +0 -0
- package/payload/server/public/assets/wrench-D8BH20W8.js.gz +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +16 -16
- package/payload/server/public/operator.html +15 -15
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +7 -7
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +343 -205
- package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-BxJPbC3p.js.br +0 -0
- package/payload/server/public/assets/AdminShell-BxJPbC3p.js.gz +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.br +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.gz +0 -0
- package/payload/server/public/assets/activity-BaSYn62l.js.br +0 -0
- package/payload/server/public/assets/activity-BaSYn62l.js.gz +0 -0
- package/payload/server/public/assets/admin-CYCKrV_x.js.br +0 -0
- package/payload/server/public/assets/admin-CYCKrV_x.js.gz +0 -0
- package/payload/server/public/assets/agents-D8EJG-ta.js.br +0 -0
- package/payload/server/public/assets/agents-D8EJG-ta.js.gz +0 -0
- package/payload/server/public/assets/browser-D6Y_Zu8C.js.br +0 -0
- package/payload/server/public/assets/browser-D6Y_Zu8C.js.gz +0 -0
- package/payload/server/public/assets/calendar-DD4oVa-r.js.br +0 -0
- package/payload/server/public/assets/calendar-DD4oVa-r.js.gz +0 -0
- package/payload/server/public/assets/chat-CwWs69PO.js +0 -1
- package/payload/server/public/assets/chat-CwWs69PO.js.br +0 -0
- package/payload/server/public/assets/chat-CwWs69PO.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-ClfIy5Fx.js +0 -1
- package/payload/server/public/assets/chevron-right-B0QvXpxl.js +0 -1
- package/payload/server/public/assets/chevron-right-B0QvXpxl.js.br +0 -0
- package/payload/server/public/assets/clock-BIaRnIP_.js +0 -1
- package/payload/server/public/assets/clock-BIaRnIP_.js.br +0 -0
- package/payload/server/public/assets/clock-BIaRnIP_.js.gz +0 -0
- package/payload/server/public/assets/data-O_9Kiicl.js +0 -1
- package/payload/server/public/assets/data-O_9Kiicl.js.br +0 -2
- package/payload/server/public/assets/data-O_9Kiicl.js.gz +0 -0
- package/payload/server/public/assets/file-download-sXU3_umF.js.br +0 -0
- package/payload/server/public/assets/file-download-sXU3_umF.js.gz +0 -0
- package/payload/server/public/assets/file-text-CeXBviDH.js.br +0 -0
- package/payload/server/public/assets/file-text-CeXBviDH.js.gz +0 -0
- package/payload/server/public/assets/graph-BSuDP6k7.js.br +0 -0
- package/payload/server/public/assets/graph-BSuDP6k7.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-D2pQkgYW.js.br +0 -0
- package/payload/server/public/assets/graph-labels-D2pQkgYW.js.gz +0 -0
- package/payload/server/public/assets/maximize-2-DlzSNygU.js.br +0 -0
- package/payload/server/public/assets/maximize-2-DlzSNygU.js.gz +0 -0
- package/payload/server/public/assets/operator-BP61-xjz.js.br +0 -0
- package/payload/server/public/assets/operator-BP61-xjz.js.gz +0 -0
- package/payload/server/public/assets/page-DX7ArY_s.js.br +0 -0
- package/payload/server/public/assets/page-DX7ArY_s.js.gz +0 -0
- package/payload/server/public/assets/page-eQ4OVros.js.br +0 -0
- package/payload/server/public/assets/page-eQ4OVros.js.gz +0 -0
- package/payload/server/public/assets/public-DPDKFKM2.js.br +0 -0
- package/payload/server/public/assets/public-DPDKFKM2.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.gz +0 -0
- package/payload/server/public/assets/routines-y413YZa-.js +0 -1
- package/payload/server/public/assets/routines-y413YZa-.js.br +0 -0
- package/payload/server/public/assets/routines-y413YZa-.js.gz +0 -0
- package/payload/server/public/assets/skills-fH0uA7cj.js.br +0 -0
- package/payload/server/public/assets/skills-fH0uA7cj.js.gz +0 -0
- package/payload/server/public/assets/tasks-CrVzFrTR.js.br +0 -0
- package/payload/server/public/assets/tasks-CrVzFrTR.js.gz +0 -0
- package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.br +0 -1
- package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.br +0 -1
- package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DxuUS_C7.css.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.gz +0 -0
- package/payload/server/public/assets/wrench-sXisQXkf.js.br +0 -0
- package/payload/server/public/assets/wrench-sXisQXkf.js.gz +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js → useSubAccountSwitcher-HjQZjJBr.js} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.br → useSubAccountSwitcher-HjQZjJBr.js.br} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.gz → useSubAccountSwitcher-HjQZjJBr.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1800,10 +1800,10 @@ var require_dist5 = __commonJS({
|
|
|
1800
1800
|
});
|
|
1801
1801
|
|
|
1802
1802
|
// server/index.ts
|
|
1803
|
-
import { readFileSync as
|
|
1803
|
+
import { readFileSync as readFileSync46, existsSync as existsSync49, watchFile, readdirSync as readdirSync29, statSync as statSync25 } from "fs";
|
|
1804
1804
|
import { spawn as spawn3 } from "child_process";
|
|
1805
1805
|
import { createHash as createHash7 } from "crypto";
|
|
1806
|
-
import { resolve as
|
|
1806
|
+
import { resolve as resolve45, join as join52, basename as basename16 } from "path";
|
|
1807
1807
|
import { homedir as homedir4 } from "os";
|
|
1808
1808
|
|
|
1809
1809
|
// server/lib/route-cache-watchers.ts
|
|
@@ -3299,20 +3299,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
3299
3299
|
|
|
3300
3300
|
// server/routes/health.ts
|
|
3301
3301
|
function checkPort(port2, timeoutMs = 500) {
|
|
3302
|
-
return new Promise((
|
|
3302
|
+
return new Promise((resolve46) => {
|
|
3303
3303
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
3304
3304
|
socket.setTimeout(timeoutMs);
|
|
3305
3305
|
socket.once("connect", () => {
|
|
3306
3306
|
socket.destroy();
|
|
3307
|
-
|
|
3307
|
+
resolve46(true);
|
|
3308
3308
|
});
|
|
3309
3309
|
socket.once("error", () => {
|
|
3310
3310
|
socket.destroy();
|
|
3311
|
-
|
|
3311
|
+
resolve46(false);
|
|
3312
3312
|
});
|
|
3313
3313
|
socket.once("timeout", () => {
|
|
3314
3314
|
socket.destroy();
|
|
3315
|
-
|
|
3315
|
+
resolve46(false);
|
|
3316
3316
|
});
|
|
3317
3317
|
});
|
|
3318
3318
|
}
|
|
@@ -5003,7 +5003,7 @@ async function defaultResolve(accountId) {
|
|
|
5003
5003
|
return resolveSocket2(accountId);
|
|
5004
5004
|
}
|
|
5005
5005
|
async function fetchAvatar(accountId, jid, deps = {}) {
|
|
5006
|
-
const
|
|
5006
|
+
const resolve46 = deps.resolve;
|
|
5007
5007
|
const httpGet = deps.httpGet ?? defaultHttpGet;
|
|
5008
5008
|
const maxAgeMs = deps.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
5009
5009
|
const cached3 = readAvatar(accountId, jid);
|
|
@@ -5013,7 +5013,7 @@ async function fetchAvatar(accountId, jid, deps = {}) {
|
|
|
5013
5013
|
return "fresh";
|
|
5014
5014
|
}
|
|
5015
5015
|
console.log(`${TAG6} op=cache jid=${jid} hit=false ageMs=${ageMs2}`);
|
|
5016
|
-
const res =
|
|
5016
|
+
const res = resolve46 ? resolve46(accountId) : await defaultResolve(accountId);
|
|
5017
5017
|
if (!res.ok) {
|
|
5018
5018
|
console.log(`${TAG6} op=no-socket jid=${jid} account=${accountId.slice(0, 8)} reason=${res.reason}`);
|
|
5019
5019
|
return "no-socket";
|
|
@@ -5982,8 +5982,8 @@ async function startLogin(opts) {
|
|
|
5982
5982
|
await clearAuth(authDir);
|
|
5983
5983
|
let resolveCode = null;
|
|
5984
5984
|
let rejectCode = null;
|
|
5985
|
-
const codePromise = new Promise((
|
|
5986
|
-
resolveCode =
|
|
5985
|
+
const codePromise = new Promise((resolve46, reject) => {
|
|
5986
|
+
resolveCode = resolve46;
|
|
5987
5987
|
rejectCode = reject;
|
|
5988
5988
|
});
|
|
5989
5989
|
const codeTimer = setTimeout(
|
|
@@ -6729,10 +6729,10 @@ app3.post("/config", async (c) => {
|
|
|
6729
6729
|
const entries2 = readdirSync7(agentsDir, { withFileTypes: true });
|
|
6730
6730
|
for (const entry of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6731
6731
|
if (!entry.isDirectory() || entry.name === "admin") continue;
|
|
6732
|
-
const
|
|
6733
|
-
if (!existsSync7(
|
|
6732
|
+
const configPath3 = resolve7(agentsDir, entry.name, "config.json");
|
|
6733
|
+
if (!existsSync7(configPath3)) continue;
|
|
6734
6734
|
try {
|
|
6735
|
-
const config = JSON.parse(readFileSync9(
|
|
6735
|
+
const config = JSON.parse(readFileSync9(configPath3, "utf-8"));
|
|
6736
6736
|
agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
|
|
6737
6737
|
} catch {
|
|
6738
6738
|
console.error(`${TAG14} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
|
|
@@ -7905,10 +7905,10 @@ function discoverPortalAccounts(accountsDir, shared = null) {
|
|
|
7905
7905
|
if (!existsSync8(accountsDir)) return [];
|
|
7906
7906
|
const found = [];
|
|
7907
7907
|
for (const accountId of readdirSync8(accountsDir)) {
|
|
7908
|
-
const
|
|
7909
|
-
if (!existsSync8(
|
|
7908
|
+
const configPath3 = join15(accountsDir, accountId, "data-portal.json");
|
|
7909
|
+
if (!existsSync8(configPath3)) continue;
|
|
7910
7910
|
try {
|
|
7911
|
-
const cfg = JSON.parse(readFileSync10(
|
|
7911
|
+
const cfg = JSON.parse(readFileSync10(configPath3, "utf-8"));
|
|
7912
7912
|
if (typeof cfg.portalDbName === "string" && cfg.portalDbName.length > 0 && typeof cfg.bucketName === "string" && cfg.bucketName.length > 0) {
|
|
7913
7913
|
found.push({
|
|
7914
7914
|
accountId,
|
|
@@ -13037,7 +13037,7 @@ app13.post("/", async (c) => {
|
|
|
13037
13037
|
const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
|
|
13038
13038
|
return `${k}=${safe}`;
|
|
13039
13039
|
}).join(" ");
|
|
13040
|
-
const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle", "dashboard-load"]);
|
|
13040
|
+
const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle", "dashboard-load", "routines"]);
|
|
13041
13041
|
if (TAGGED_PREFIX_SOURCES.has(source)) {
|
|
13042
13042
|
console.log(
|
|
13043
13043
|
`[${source}] ts=${ts} ip=${ip} version=${version || "unknown"}${extra ? " " + extra : ""}`
|
|
@@ -13136,15 +13136,15 @@ function operatorRoleFor(config, userId) {
|
|
|
13136
13136
|
async function buildAccountOptionList(accounts, userId) {
|
|
13137
13137
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
13138
13138
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
13139
|
-
const
|
|
13139
|
+
const resolve46 = async (a) => {
|
|
13140
13140
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
13141
13141
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
13142
13142
|
};
|
|
13143
13143
|
const houseOptions = await Promise.all(
|
|
13144
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
13144
|
+
accounts.filter((a) => a.config.role === "house").map(resolve46)
|
|
13145
13145
|
);
|
|
13146
13146
|
const nonHouseOptions = await Promise.all(
|
|
13147
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
13147
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve46)
|
|
13148
13148
|
);
|
|
13149
13149
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
13150
13150
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -14269,10 +14269,10 @@ app20.get("/", requireAdminSession, (c) => {
|
|
|
14269
14269
|
for (const entry of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
14270
14270
|
if (!entry.isDirectory()) continue;
|
|
14271
14271
|
if (entry.name === "admin") continue;
|
|
14272
|
-
const
|
|
14273
|
-
if (!existsSync30(
|
|
14272
|
+
const configPath3 = resolve20(agentsDir, entry.name, "config.json");
|
|
14273
|
+
if (!existsSync30(configPath3)) continue;
|
|
14274
14274
|
try {
|
|
14275
|
-
const config = JSON.parse(readFileSync28(
|
|
14275
|
+
const config = JSON.parse(readFileSync28(configPath3, "utf-8"));
|
|
14276
14276
|
agents.push({
|
|
14277
14277
|
slug: entry.name,
|
|
14278
14278
|
displayName: config.displayName ?? entry.name,
|
|
@@ -14406,11 +14406,11 @@ app20.get("/:slug", requireAdminSession, (c) => {
|
|
|
14406
14406
|
});
|
|
14407
14407
|
}
|
|
14408
14408
|
const agentDir = resolve20(account.accountDir, "agents", slug);
|
|
14409
|
-
const
|
|
14410
|
-
if (!existsSync30(
|
|
14409
|
+
const configPath3 = resolve20(agentDir, "config.json");
|
|
14410
|
+
if (!existsSync30(configPath3)) return c.json({ error: "Agent not found" }, 404);
|
|
14411
14411
|
let config;
|
|
14412
14412
|
try {
|
|
14413
|
-
config = JSON.parse(readFileSync28(
|
|
14413
|
+
config = JSON.parse(readFileSync28(configPath3, "utf-8"));
|
|
14414
14414
|
} catch {
|
|
14415
14415
|
console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
|
|
14416
14416
|
return c.json({ error: "Agent config unreadable" }, 500);
|
|
@@ -16907,9 +16907,9 @@ async function readAccountNames() {
|
|
|
16907
16907
|
}
|
|
16908
16908
|
for (const name of names) {
|
|
16909
16909
|
if (!UUID_RE3.test(name)) continue;
|
|
16910
|
-
const
|
|
16910
|
+
const configPath3 = resolve24(accountsDir, name, "account.json");
|
|
16911
16911
|
try {
|
|
16912
|
-
const raw = await readFile9(
|
|
16912
|
+
const raw = await readFile9(configPath3, "utf8");
|
|
16913
16913
|
const parsed = JSON.parse(raw);
|
|
16914
16914
|
if (typeof parsed?.name === "string" && parsed.name.length > 0) {
|
|
16915
16915
|
map.set(name, parsed.name);
|
|
@@ -21259,6 +21259,56 @@ var health_default2 = app41;
|
|
|
21259
21259
|
// server/routes/admin/linkedin-ingest.ts
|
|
21260
21260
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
21261
21261
|
|
|
21262
|
+
// ../lib/account-ingest-token/src/index.ts
|
|
21263
|
+
import { randomBytes, timingSafeEqual } from "crypto";
|
|
21264
|
+
import { existsSync as existsSync37, readdirSync as readdirSync24, readFileSync as readFileSync34, writeFileSync as writeFileSync14 } from "fs";
|
|
21265
|
+
import { resolve as resolve30 } from "path";
|
|
21266
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21267
|
+
var INGEST_TOKEN_FIELD = "ingestToken";
|
|
21268
|
+
var TOKEN_RE = /^[0-9a-f]{64}$/;
|
|
21269
|
+
function configPath2(accountsDir, accountId) {
|
|
21270
|
+
return resolve30(accountsDir, accountId, "account.json");
|
|
21271
|
+
}
|
|
21272
|
+
function readConfig2(accountsDir, accountId) {
|
|
21273
|
+
const path = configPath2(accountsDir, accountId);
|
|
21274
|
+
if (!existsSync37(path)) return null;
|
|
21275
|
+
try {
|
|
21276
|
+
const parsed = JSON.parse(readFileSync34(path, "utf-8"));
|
|
21277
|
+
return parsed !== null && typeof parsed === "object" ? parsed : null;
|
|
21278
|
+
} catch {
|
|
21279
|
+
return null;
|
|
21280
|
+
}
|
|
21281
|
+
}
|
|
21282
|
+
function readIngestToken(accountsDir, accountId) {
|
|
21283
|
+
const value = readConfig2(accountsDir, accountId)?.[INGEST_TOKEN_FIELD];
|
|
21284
|
+
return typeof value === "string" && TOKEN_RE.test(value) ? value : null;
|
|
21285
|
+
}
|
|
21286
|
+
function listAccountIdsOnDisk(accountsDir) {
|
|
21287
|
+
if (!existsSync37(accountsDir)) return [];
|
|
21288
|
+
let entries2;
|
|
21289
|
+
try {
|
|
21290
|
+
entries2 = readdirSync24(accountsDir);
|
|
21291
|
+
} catch {
|
|
21292
|
+
return [];
|
|
21293
|
+
}
|
|
21294
|
+
return entries2.filter(
|
|
21295
|
+
(name) => UUID_RE4.test(name) && existsSync37(resolve30(accountsDir, name, "account.json"))
|
|
21296
|
+
);
|
|
21297
|
+
}
|
|
21298
|
+
function resolveAccountIdByIngestToken(accountsDir, token) {
|
|
21299
|
+
if (typeof token !== "string" || !TOKEN_RE.test(token)) return null;
|
|
21300
|
+
const probe = Buffer.from(token, "utf-8");
|
|
21301
|
+
for (const accountId of listAccountIdsOnDisk(accountsDir)) {
|
|
21302
|
+
const stored = readIngestToken(accountsDir, accountId);
|
|
21303
|
+
if (!stored) continue;
|
|
21304
|
+
const candidate = Buffer.from(stored, "utf-8");
|
|
21305
|
+
if (candidate.length === probe.length && timingSafeEqual(candidate, probe)) {
|
|
21306
|
+
return accountId;
|
|
21307
|
+
}
|
|
21308
|
+
}
|
|
21309
|
+
return null;
|
|
21310
|
+
}
|
|
21311
|
+
|
|
21262
21312
|
// app/lib/channel-pty-bridge/manager-client.ts
|
|
21263
21313
|
function managerBase2() {
|
|
21264
21314
|
const port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "channel-pty-bridge:manager-client" });
|
|
@@ -21483,8 +21533,29 @@ function buildInitialMessage(env) {
|
|
|
21483
21533
|
}
|
|
21484
21534
|
return header;
|
|
21485
21535
|
}
|
|
21536
|
+
var AUTH_TAG = "[linkedin-ingest-auth]";
|
|
21537
|
+
var requireIngestToken = async (c, next) => {
|
|
21538
|
+
let token = "";
|
|
21539
|
+
try {
|
|
21540
|
+
const body = await c.req.json();
|
|
21541
|
+
if (body && typeof body.ingest_token === "string") token = body.ingest_token;
|
|
21542
|
+
} catch {
|
|
21543
|
+
}
|
|
21544
|
+
if (!token) {
|
|
21545
|
+
console.error(`${AUTH_TAG} outcome=reject status=400 code=token-missing path=${c.req.path}`);
|
|
21546
|
+
return c.json({ ok: false, error: "auth", code: "token-missing" }, 400);
|
|
21547
|
+
}
|
|
21548
|
+
const accountId = resolveAccountIdByIngestToken(ACCOUNTS_DIR, token);
|
|
21549
|
+
if (!accountId) {
|
|
21550
|
+
console.error(`${AUTH_TAG} outcome=reject status=401 code=token-unknown path=${c.req.path}`);
|
|
21551
|
+
return c.json({ ok: false, error: "auth", code: "token-unknown" }, 401);
|
|
21552
|
+
}
|
|
21553
|
+
c.set("ingestAccountId", accountId);
|
|
21554
|
+
console.log(`${AUTH_TAG} outcome=accept accountId=${accountId.slice(0, 8)} path=${c.req.path}`);
|
|
21555
|
+
await next();
|
|
21556
|
+
};
|
|
21486
21557
|
var app42 = new Hono();
|
|
21487
|
-
app42.post("/",
|
|
21558
|
+
app42.post("/", requireIngestToken, async (c) => {
|
|
21488
21559
|
let body;
|
|
21489
21560
|
try {
|
|
21490
21561
|
body = await c.req.json();
|
|
@@ -21498,8 +21569,7 @@ app42.post("/", requireAdminSession, async (c) => {
|
|
|
21498
21569
|
return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
|
|
21499
21570
|
}
|
|
21500
21571
|
const envelope = v.envelope;
|
|
21501
|
-
const
|
|
21502
|
-
const senderId = getAccountIdForSession(cacheKey) ?? "";
|
|
21572
|
+
const senderId = c.var.ingestAccountId ?? "";
|
|
21503
21573
|
if (!senderId) {
|
|
21504
21574
|
console.error(TAG22 + " rejected status=500 reason=admin-account-not-resolved");
|
|
21505
21575
|
return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
|
|
@@ -22009,7 +22079,7 @@ app48.post("/screencast-event", requireAdminSession, async (c) => {
|
|
|
22009
22079
|
var browser_default = app48;
|
|
22010
22080
|
|
|
22011
22081
|
// server/routes/admin/calendar.ts
|
|
22012
|
-
import { existsSync as
|
|
22082
|
+
import { existsSync as existsSync38 } from "fs";
|
|
22013
22083
|
import { join as join44 } from "path";
|
|
22014
22084
|
|
|
22015
22085
|
// server/lib/calendar-ics.ts
|
|
@@ -22109,7 +22179,7 @@ function countVEvents(ics) {
|
|
|
22109
22179
|
}
|
|
22110
22180
|
|
|
22111
22181
|
// server/lib/calendar-availability.ts
|
|
22112
|
-
import { readFileSync as
|
|
22182
|
+
import { readFileSync as readFileSync35 } from "fs";
|
|
22113
22183
|
import { join as join43 } from "path";
|
|
22114
22184
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
22115
22185
|
var REQUIRED_KEYS = [
|
|
@@ -22122,7 +22192,7 @@ function readAvailabilityConfig(accountDir) {
|
|
|
22122
22192
|
const path = join43(accountDir, AVAILABILITY_FILENAME);
|
|
22123
22193
|
let raw;
|
|
22124
22194
|
try {
|
|
22125
|
-
raw =
|
|
22195
|
+
raw = readFileSync35(path, "utf-8");
|
|
22126
22196
|
} catch {
|
|
22127
22197
|
throw new Error(`availability not configured: ${path} not found`);
|
|
22128
22198
|
}
|
|
@@ -22482,7 +22552,7 @@ app49.get("/booking-link", requireAdminSession, (c) => {
|
|
|
22482
22552
|
}
|
|
22483
22553
|
const id82 = account.accountId.slice(0, 8);
|
|
22484
22554
|
try {
|
|
22485
|
-
if (!
|
|
22555
|
+
if (!existsSync38(join44(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
22486
22556
|
console.log(`[calendar] op=booking-link accountId=${id82} bookingDomain=none source=availability-config`);
|
|
22487
22557
|
return c.json({ bookingDomain: null });
|
|
22488
22558
|
}
|
|
@@ -22501,7 +22571,7 @@ app49.get("/booking-link", requireAdminSession, (c) => {
|
|
|
22501
22571
|
var calendar_default = app49;
|
|
22502
22572
|
|
|
22503
22573
|
// server/routes/admin/data-portal.ts
|
|
22504
|
-
import { existsSync as
|
|
22574
|
+
import { existsSync as existsSync39, readFileSync as readFileSync36 } from "fs";
|
|
22505
22575
|
import { join as join45 } from "path";
|
|
22506
22576
|
var app50 = new Hono();
|
|
22507
22577
|
var PORTAL_FILENAME = "data-portal.json";
|
|
@@ -22514,11 +22584,11 @@ app50.get("/portal-link", requireAdminSession, (c) => {
|
|
|
22514
22584
|
const id82 = account.accountId.slice(0, 8);
|
|
22515
22585
|
try {
|
|
22516
22586
|
const path = join45(account.accountDir, PORTAL_FILENAME);
|
|
22517
|
-
if (!
|
|
22587
|
+
if (!existsSync39(path)) {
|
|
22518
22588
|
console.log(`[data-portal] op=portal-link accountId=${id82} portalDomain=none source=data-portal-config`);
|
|
22519
22589
|
return c.json({ portalDomain: null });
|
|
22520
22590
|
}
|
|
22521
|
-
const cfg = JSON.parse(
|
|
22591
|
+
const cfg = JSON.parse(readFileSync36(path, "utf-8"));
|
|
22522
22592
|
const portalDomain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
|
|
22523
22593
|
console.log(`[data-portal] op=portal-link accountId=${id82} portalDomain=${portalDomain ?? "none"} source=data-portal-config`);
|
|
22524
22594
|
return c.json({ portalDomain });
|
|
@@ -22535,8 +22605,8 @@ import cronParser from "cron-parser";
|
|
|
22535
22605
|
import { int as int2 } from "neo4j-driver";
|
|
22536
22606
|
|
|
22537
22607
|
// ../lib/agent-dispatch-rule/src/index.ts
|
|
22538
|
-
import { readFileSync as
|
|
22539
|
-
import { resolve as
|
|
22608
|
+
import { readFileSync as readFileSync37 } from "fs";
|
|
22609
|
+
import { resolve as resolve31 } from "path";
|
|
22540
22610
|
function normalizeE1642(value) {
|
|
22541
22611
|
let candidate = value.trim().replace(/[\s\-().]/g, "");
|
|
22542
22612
|
candidate = candidate.replace(/^whatsapp:/i, "");
|
|
@@ -22553,7 +22623,7 @@ function phonesMatch2(a, b) {
|
|
|
22553
22623
|
function readChannelAdmins(accountDir, channel) {
|
|
22554
22624
|
let config = {};
|
|
22555
22625
|
try {
|
|
22556
|
-
config = JSON.parse(
|
|
22626
|
+
config = JSON.parse(readFileSync37(resolve31(accountDir, "account.json"), "utf-8"));
|
|
22557
22627
|
} catch {
|
|
22558
22628
|
config = {};
|
|
22559
22629
|
}
|
|
@@ -22585,9 +22655,16 @@ function registeredAccountForDestination(houseDir, houseAccountId, destination)
|
|
|
22585
22655
|
if (adminPhones.some((p) => phonesMatch2(p, destination))) return houseAccountId;
|
|
22586
22656
|
return null;
|
|
22587
22657
|
}
|
|
22658
|
+
function boundSubAccountFor(accountDir, destination) {
|
|
22659
|
+
const { accountManagers } = readChannelAdmins(accountDir, "whatsapp");
|
|
22660
|
+
for (const [managerPhone, subAccountId] of Object.entries(accountManagers)) {
|
|
22661
|
+
if (subAccountId && phonesMatch2(managerPhone, destination)) return subAccountId;
|
|
22662
|
+
}
|
|
22663
|
+
return null;
|
|
22664
|
+
}
|
|
22588
22665
|
function validateAgentDestination(accountsDir, houseAccountId, creatingAccountId, channel, destination) {
|
|
22589
22666
|
if (channel === "whatsapp") {
|
|
22590
|
-
const houseDir =
|
|
22667
|
+
const houseDir = resolve31(accountsDir, houseAccountId);
|
|
22591
22668
|
const registered = registeredAccountForDestination(houseDir, houseAccountId, destination);
|
|
22592
22669
|
if (registered === null) return { valid: false, reason: "not-registered" };
|
|
22593
22670
|
if (creatingAccountId === houseAccountId) return { valid: true };
|
|
@@ -22599,7 +22676,7 @@ function validateAgentDestination(accountsDir, houseAccountId, creatingAccountId
|
|
|
22599
22676
|
scheduleAccount: creatingAccountId
|
|
22600
22677
|
};
|
|
22601
22678
|
}
|
|
22602
|
-
const { adminUsers } = readChannelAdmins(
|
|
22679
|
+
const { adminUsers } = readChannelAdmins(resolve31(accountsDir, creatingAccountId), "telegram");
|
|
22603
22680
|
const asNumber = Number(destination);
|
|
22604
22681
|
const ok = Number.isInteger(asNumber) && adminUsers.includes(asNumber);
|
|
22605
22682
|
return ok ? { valid: true } : { valid: false, reason: "not-registered" };
|
|
@@ -22609,7 +22686,7 @@ function listDispatchDestinations(input) {
|
|
|
22609
22686
|
const managers = [];
|
|
22610
22687
|
const admins = [];
|
|
22611
22688
|
if (houseAccountId !== null) {
|
|
22612
|
-
const houseDir =
|
|
22689
|
+
const houseDir = resolve31(accountsDir, houseAccountId);
|
|
22613
22690
|
const { adminPhones, accountManagers } = readChannelAdmins(houseDir, "whatsapp");
|
|
22614
22691
|
const seen = /* @__PURE__ */ new Set();
|
|
22615
22692
|
for (const [phone, subAccountId] of Object.entries(accountManagers)) {
|
|
@@ -22627,7 +22704,7 @@ function listDispatchDestinations(input) {
|
|
|
22627
22704
|
admins.push({ channel: "whatsapp", destination: phone, label: "House admin" });
|
|
22628
22705
|
}
|
|
22629
22706
|
}
|
|
22630
|
-
const { adminUsers } = readChannelAdmins(
|
|
22707
|
+
const { adminUsers } = readChannelAdmins(resolve31(accountsDir, accountId), "telegram");
|
|
22631
22708
|
const telegram = [...adminUsers].sort((a, b) => a - b).map((id) => ({ channel: "telegram", destination: String(id), label: "Telegram admin" }));
|
|
22632
22709
|
const byDestination = (a, b) => a.destination.localeCompare(b.destination);
|
|
22633
22710
|
return [...managers.sort(byDestination), ...admins.sort(byDestination), ...telegram];
|
|
@@ -23294,8 +23371,8 @@ app51.delete("/:eventId", requireAdminSession, async (c) => {
|
|
|
23294
23371
|
var routines_default = app51;
|
|
23295
23372
|
|
|
23296
23373
|
// server/routes/admin/skills.ts
|
|
23297
|
-
import { existsSync as
|
|
23298
|
-
import { resolve as
|
|
23374
|
+
import { existsSync as existsSync40, readdirSync as readdirSync25, readFileSync as readFileSync38, rmSync as rmSync5 } from "fs";
|
|
23375
|
+
import { resolve as resolve32 } from "path";
|
|
23299
23376
|
var app52 = new Hono();
|
|
23300
23377
|
var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
23301
23378
|
function splitSkillMd(text) {
|
|
@@ -23318,9 +23395,9 @@ function stripQuotes(s) {
|
|
|
23318
23395
|
return s;
|
|
23319
23396
|
}
|
|
23320
23397
|
function subdirs2(dir) {
|
|
23321
|
-
if (!
|
|
23398
|
+
if (!existsSync40(dir)) return [];
|
|
23322
23399
|
try {
|
|
23323
|
-
return
|
|
23400
|
+
return readdirSync25(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
23324
23401
|
} catch {
|
|
23325
23402
|
return [];
|
|
23326
23403
|
}
|
|
@@ -23333,19 +23410,19 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
23333
23410
|
}
|
|
23334
23411
|
ensureAccountWatchers(acct.accountId, acct.accountDir);
|
|
23335
23412
|
const { value, state } = await getOrCompute("skills", acct.accountId, async () => {
|
|
23336
|
-
const pluginsDir =
|
|
23413
|
+
const pluginsDir = resolve32(acct.accountDir, "plugins");
|
|
23337
23414
|
const skills = [];
|
|
23338
23415
|
let pluginCount = 0;
|
|
23339
23416
|
for (const plugin of subdirs2(pluginsDir)) {
|
|
23340
23417
|
pluginCount++;
|
|
23341
|
-
const skillsDir =
|
|
23418
|
+
const skillsDir = resolve32(pluginsDir, plugin, "skills");
|
|
23342
23419
|
for (const skill of subdirs2(skillsDir)) {
|
|
23343
|
-
const skillMd =
|
|
23344
|
-
if (!
|
|
23420
|
+
const skillMd = resolve32(skillsDir, skill, "SKILL.md");
|
|
23421
|
+
if (!existsSync40(skillMd)) continue;
|
|
23345
23422
|
try {
|
|
23346
|
-
const { frontmatter } = splitSkillMd(
|
|
23347
|
-
const refsDir =
|
|
23348
|
-
const refCount =
|
|
23423
|
+
const { frontmatter } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
|
|
23424
|
+
const refsDir = resolve32(skillsDir, skill, "references");
|
|
23425
|
+
const refCount = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
|
|
23349
23426
|
skills.push({ plugin, skill, description: frontmatter.description, refCount });
|
|
23350
23427
|
} catch (err) {
|
|
23351
23428
|
console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -23367,15 +23444,15 @@ app52.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23367
23444
|
console.error(`[admin:skills] op=get outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
23368
23445
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
23369
23446
|
}
|
|
23370
|
-
const skillDir =
|
|
23371
|
-
const skillMd =
|
|
23372
|
-
const found =
|
|
23447
|
+
const skillDir = resolve32(acct.accountDir, "plugins", plugin, "skills", skill);
|
|
23448
|
+
const skillMd = resolve32(skillDir, "SKILL.md");
|
|
23449
|
+
const found = existsSync40(skillMd);
|
|
23373
23450
|
console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
|
|
23374
23451
|
if (!found) return c.json({ error: "Skill not found" }, 404);
|
|
23375
23452
|
try {
|
|
23376
|
-
const { frontmatter, body } = splitSkillMd(
|
|
23377
|
-
const refsDir =
|
|
23378
|
-
const references =
|
|
23453
|
+
const { frontmatter, body } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
|
|
23454
|
+
const refsDir = resolve32(skillDir, "references");
|
|
23455
|
+
const references = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
|
|
23379
23456
|
return c.json({ skill: { plugin, skill, frontmatter, body, references } });
|
|
23380
23457
|
} catch (err) {
|
|
23381
23458
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -23392,10 +23469,10 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23392
23469
|
console.error(`[admin:skills] op=delete outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
23393
23470
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
23394
23471
|
}
|
|
23395
|
-
const pluginDir =
|
|
23396
|
-
const skillsDir =
|
|
23397
|
-
const skillDir =
|
|
23398
|
-
if (!
|
|
23472
|
+
const pluginDir = resolve32(acct.accountDir, "plugins", plugin);
|
|
23473
|
+
const skillsDir = resolve32(pluginDir, "skills");
|
|
23474
|
+
const skillDir = resolve32(skillsDir, skill);
|
|
23475
|
+
if (!existsSync40(resolve32(skillDir, "SKILL.md"))) {
|
|
23399
23476
|
console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
|
|
23400
23477
|
return c.json({ error: "Skill not found" }, 404);
|
|
23401
23478
|
}
|
|
@@ -23403,7 +23480,7 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23403
23480
|
rmSync5(skillDir, { recursive: true, force: true });
|
|
23404
23481
|
const pluginDirRemoved = subdirs2(skillsDir).length === 0;
|
|
23405
23482
|
if (pluginDirRemoved) rmSync5(pluginDir, { recursive: true, force: true });
|
|
23406
|
-
const skillDirGone = !
|
|
23483
|
+
const skillDirGone = !existsSync40(skillDir);
|
|
23407
23484
|
if (!skillDirGone) {
|
|
23408
23485
|
console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
|
|
23409
23486
|
return c.json({ error: "Delete did not remove the skill directory" }, 503);
|
|
@@ -23875,20 +23952,20 @@ app57.post("/", requireAdminSession, async (c) => {
|
|
|
23875
23952
|
var task_time_adjust_default = app57;
|
|
23876
23953
|
|
|
23877
23954
|
// app/lib/admin-roster.ts
|
|
23878
|
-
import { existsSync as
|
|
23879
|
-
import { resolve as
|
|
23955
|
+
import { existsSync as existsSync41, readdirSync as readdirSync26, readFileSync as readFileSync39 } from "fs";
|
|
23956
|
+
import { resolve as resolve33 } from "path";
|
|
23880
23957
|
function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
23881
23958
|
let entries2;
|
|
23882
23959
|
try {
|
|
23883
|
-
entries2 =
|
|
23960
|
+
entries2 = readdirSync26(accountsDir);
|
|
23884
23961
|
} catch {
|
|
23885
23962
|
return [];
|
|
23886
23963
|
}
|
|
23887
23964
|
for (const entry of entries2) {
|
|
23888
|
-
const cfgPath =
|
|
23889
|
-
if (!
|
|
23965
|
+
const cfgPath = resolve33(accountsDir, entry, "account.json");
|
|
23966
|
+
if (!existsSync41(cfgPath)) continue;
|
|
23890
23967
|
try {
|
|
23891
|
-
const cfg = JSON.parse(
|
|
23968
|
+
const cfg = JSON.parse(readFileSync39(cfgPath, "utf-8"));
|
|
23892
23969
|
if (cfg.role !== "house") continue;
|
|
23893
23970
|
if (!Array.isArray(cfg.admins)) return [];
|
|
23894
23971
|
return cfg.admins.map(
|
|
@@ -24218,7 +24295,21 @@ app61.get("/", requireAdminSession, async (c) => {
|
|
|
24218
24295
|
var admin_users_list_default = app61;
|
|
24219
24296
|
|
|
24220
24297
|
// server/routes/admin/dispatch-destinations.ts
|
|
24298
|
+
import { resolve as resolve34 } from "path";
|
|
24221
24299
|
var TAG37 = "[admin:routines]";
|
|
24300
|
+
function scopeFor(d, houseDir, houseAccountId) {
|
|
24301
|
+
if (d.channel !== "whatsapp") return null;
|
|
24302
|
+
if (d.label === "Account manager") return boundSubAccountFor(houseDir, d.destination);
|
|
24303
|
+
return houseAccountId;
|
|
24304
|
+
}
|
|
24305
|
+
function telephoneVariants(destination) {
|
|
24306
|
+
const digits = normalizeE1642(destination);
|
|
24307
|
+
if (digits.length === 0) return [destination];
|
|
24308
|
+
return [.../* @__PURE__ */ new Set([destination, digits, `+${digits}`])];
|
|
24309
|
+
}
|
|
24310
|
+
function scrubDigitRuns(message) {
|
|
24311
|
+
return message.replace(/\d{7,}/g, "<redacted>");
|
|
24312
|
+
}
|
|
24222
24313
|
var app62 = new Hono();
|
|
24223
24314
|
app62.get("/", requireAdminSession, async (c) => {
|
|
24224
24315
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
@@ -24234,15 +24325,62 @@ app62.get("/", requireAdminSession, async (c) => {
|
|
|
24234
24325
|
console.error(`${TAG37} op=destinations account=${accountId.slice(0, 8)} outcome=house-unresolved reason="${message}"`);
|
|
24235
24326
|
}
|
|
24236
24327
|
const destinations = listDispatchDestinations({ accountsDir: ACCOUNTS_DIR, houseAccountId, accountId });
|
|
24328
|
+
const houseDir = houseAccountId === null ? null : resolve34(ACCOUNTS_DIR, houseAccountId);
|
|
24329
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
24330
|
+
for (const d of destinations) {
|
|
24331
|
+
const scope = houseDir === null || houseAccountId === null ? null : scopeFor(d, houseDir, houseAccountId);
|
|
24332
|
+
if (scope === null) continue;
|
|
24333
|
+
const list = byScope.get(scope);
|
|
24334
|
+
if (list) list.push(d);
|
|
24335
|
+
else byScope.set(scope, [d]);
|
|
24336
|
+
}
|
|
24337
|
+
let namesUnresolved = null;
|
|
24338
|
+
let named = 0;
|
|
24339
|
+
if (byScope.size > 0) {
|
|
24340
|
+
let session = null;
|
|
24341
|
+
try {
|
|
24342
|
+
session = getSession();
|
|
24343
|
+
for (const [scopeAccountId, rows] of byScope) {
|
|
24344
|
+
const telephones = [...new Set(rows.flatMap((d) => telephoneVariants(d.destination)))];
|
|
24345
|
+
const result = await session.run(
|
|
24346
|
+
`MATCH (p:Person {accountId: $accountId}) WHERE p.telephone IN $telephones
|
|
24347
|
+
RETURN p.telephone AS telephone, p.givenName AS givenName, p.familyName AS familyName`,
|
|
24348
|
+
{ accountId: scopeAccountId, telephones }
|
|
24349
|
+
);
|
|
24350
|
+
const found = /* @__PURE__ */ new Map();
|
|
24351
|
+
for (const rec of result.records) {
|
|
24352
|
+
const tel = rec.get("telephone");
|
|
24353
|
+
if (!tel) continue;
|
|
24354
|
+
const name = [rec.get("givenName"), rec.get("familyName")].filter(Boolean).join(" ");
|
|
24355
|
+
if (name.length > 0) found.set(normalizeE1642(tel), name);
|
|
24356
|
+
}
|
|
24357
|
+
for (const d of rows) {
|
|
24358
|
+
const hit = found.get(normalizeE1642(d.destination));
|
|
24359
|
+
if (hit) {
|
|
24360
|
+
d.name = hit;
|
|
24361
|
+
named += 1;
|
|
24362
|
+
}
|
|
24363
|
+
}
|
|
24364
|
+
}
|
|
24365
|
+
} catch (err) {
|
|
24366
|
+
namesUnresolved = scrubDigitRuns(err instanceof Error ? err.message : String(err));
|
|
24367
|
+
for (const d of destinations) delete d.name;
|
|
24368
|
+
named = 0;
|
|
24369
|
+
} finally {
|
|
24370
|
+
if (session) await session.close();
|
|
24371
|
+
}
|
|
24372
|
+
}
|
|
24373
|
+
const scopes = [...byScope.keys()];
|
|
24374
|
+
const nameScope = scopes.length === 0 ? "none" : scopes.every((s) => s === houseAccountId) ? "house" : scopes.some((s) => s === houseAccountId) ? "mixed" : "account";
|
|
24237
24375
|
console.log(
|
|
24238
|
-
`${TAG37} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length}` + (houseAccountId === null ? " outcome=house-unresolved" : "")
|
|
24376
|
+
`${TAG37} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length} named=${named} unnamed=${destinations.length - named} nameScope=${nameScope}` + (houseAccountId === null ? " outcome=house-unresolved" : "") + (namesUnresolved === null ? "" : ` outcome=names-unresolved reason="${namesUnresolved}"`)
|
|
24239
24377
|
);
|
|
24240
24378
|
return c.json({ destinations });
|
|
24241
24379
|
});
|
|
24242
24380
|
var dispatch_destinations_default = app62;
|
|
24243
24381
|
|
|
24244
24382
|
// server/routes/admin/activity.ts
|
|
24245
|
-
import { readdirSync as
|
|
24383
|
+
import { readdirSync as readdirSync27 } from "fs";
|
|
24246
24384
|
var app63 = new Hono();
|
|
24247
24385
|
var TAG38 = "[activity]";
|
|
24248
24386
|
function resolveHouseAccountId(accounts) {
|
|
@@ -24258,7 +24396,7 @@ function requestToken() {
|
|
|
24258
24396
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
24259
24397
|
function countAccountDirsOnDisk() {
|
|
24260
24398
|
try {
|
|
24261
|
-
return
|
|
24399
|
+
return readdirSync27(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
24262
24400
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
24263
24401
|
).length;
|
|
24264
24402
|
} catch {
|
|
@@ -24522,9 +24660,9 @@ var verify_token_default = app65;
|
|
|
24522
24660
|
|
|
24523
24661
|
// app/lib/access-email.ts
|
|
24524
24662
|
import { spawn as spawn2 } from "child_process";
|
|
24525
|
-
import { resolve as
|
|
24526
|
-
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
24527
|
-
var SEND_SCRIPT =
|
|
24663
|
+
import { resolve as resolve35 } from "path";
|
|
24664
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve35(process.cwd(), "..");
|
|
24665
|
+
var SEND_SCRIPT = resolve35(
|
|
24528
24666
|
PLATFORM_ROOT5,
|
|
24529
24667
|
"plugins",
|
|
24530
24668
|
"email",
|
|
@@ -24666,8 +24804,8 @@ app67.route("/request-magic-link", request_magic_link_default);
|
|
|
24666
24804
|
var access_default = app67;
|
|
24667
24805
|
|
|
24668
24806
|
// server/routes/sites.ts
|
|
24669
|
-
import { existsSync as
|
|
24670
|
-
import { resolve as
|
|
24807
|
+
import { existsSync as existsSync42, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync22 } from "fs";
|
|
24808
|
+
import { resolve as resolve36 } from "path";
|
|
24671
24809
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
24672
24810
|
var MIME = {
|
|
24673
24811
|
".html": "text/html; charset=utf-8",
|
|
@@ -24724,15 +24862,15 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24724
24862
|
}
|
|
24725
24863
|
segments.push(seg);
|
|
24726
24864
|
}
|
|
24727
|
-
const rootDir =
|
|
24728
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
24865
|
+
const rootDir = resolve36(account.accountDir, "sites");
|
|
24866
|
+
let filePath = segments.length === 0 ? rootDir : resolve36(rootDir, ...segments);
|
|
24729
24867
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
24730
24868
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24731
24869
|
return c.text("Forbidden", 403);
|
|
24732
24870
|
}
|
|
24733
24871
|
let stat11;
|
|
24734
24872
|
try {
|
|
24735
|
-
stat11 =
|
|
24873
|
+
stat11 = existsSync42(filePath) ? statSync22(filePath) : null;
|
|
24736
24874
|
} catch {
|
|
24737
24875
|
stat11 = null;
|
|
24738
24876
|
}
|
|
@@ -24745,13 +24883,13 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24745
24883
|
return c.redirect(target, 301);
|
|
24746
24884
|
}
|
|
24747
24885
|
if (stat11?.isDirectory()) {
|
|
24748
|
-
filePath =
|
|
24886
|
+
filePath = resolve36(filePath, "index.html");
|
|
24749
24887
|
}
|
|
24750
24888
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
24751
24889
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24752
24890
|
return c.text("Forbidden", 403);
|
|
24753
24891
|
}
|
|
24754
|
-
if (!
|
|
24892
|
+
if (!existsSync42(filePath)) {
|
|
24755
24893
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
24756
24894
|
return c.text("Not found", 404);
|
|
24757
24895
|
}
|
|
@@ -24770,7 +24908,7 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24770
24908
|
}
|
|
24771
24909
|
let body;
|
|
24772
24910
|
try {
|
|
24773
|
-
body =
|
|
24911
|
+
body = readFileSync40(realPath);
|
|
24774
24912
|
} catch (err) {
|
|
24775
24913
|
const code = err?.code;
|
|
24776
24914
|
if (code === "EISDIR") {
|
|
@@ -24805,8 +24943,8 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24805
24943
|
var sites_default = app68;
|
|
24806
24944
|
|
|
24807
24945
|
// app/lib/visitor-token.ts
|
|
24808
|
-
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
24809
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
24946
|
+
import { createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
24947
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync15 } from "fs";
|
|
24810
24948
|
import { dirname as dirname15 } from "path";
|
|
24811
24949
|
var TOKEN_PREFIX = "v1.";
|
|
24812
24950
|
var SECRET_BYTES = 32;
|
|
@@ -24815,21 +24953,21 @@ var cachedSecret = null;
|
|
|
24815
24953
|
function getSecret() {
|
|
24816
24954
|
if (cachedSecret) return cachedSecret;
|
|
24817
24955
|
try {
|
|
24818
|
-
const hex2 =
|
|
24956
|
+
const hex2 = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
24819
24957
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
24820
24958
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
24821
24959
|
return cachedSecret;
|
|
24822
24960
|
}
|
|
24823
24961
|
} catch {
|
|
24824
24962
|
}
|
|
24825
|
-
const fresh =
|
|
24963
|
+
const fresh = randomBytes2(SECRET_BYTES).toString("hex");
|
|
24826
24964
|
try {
|
|
24827
24965
|
mkdirSync8(dirname15(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
|
|
24828
|
-
|
|
24966
|
+
writeFileSync15(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
24829
24967
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
24830
24968
|
} catch {
|
|
24831
24969
|
}
|
|
24832
|
-
const hex =
|
|
24970
|
+
const hex = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
24833
24971
|
cachedSecret = Buffer.from(hex, "hex");
|
|
24834
24972
|
return cachedSecret;
|
|
24835
24973
|
}
|
|
@@ -24862,7 +25000,7 @@ function verifyVisitorToken(token, now = Date.now()) {
|
|
|
24862
25000
|
const expected = signPayload(payloadJson, getSecret());
|
|
24863
25001
|
const expectedBuf = Buffer.from(expected, "utf-8");
|
|
24864
25002
|
const provBuf = Buffer.from(sigB64, "utf-8");
|
|
24865
|
-
if (expectedBuf.length !== provBuf.length || !
|
|
25003
|
+
if (expectedBuf.length !== provBuf.length || !timingSafeEqual2(expectedBuf, provBuf)) {
|
|
24866
25004
|
return { ok: false, reason: "bad-sig" };
|
|
24867
25005
|
}
|
|
24868
25006
|
let payload;
|
|
@@ -24882,7 +25020,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
24882
25020
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
24883
25021
|
|
|
24884
25022
|
// app/lib/brand-config.ts
|
|
24885
|
-
import { existsSync as
|
|
25023
|
+
import { existsSync as existsSync43, readFileSync as readFileSync42 } from "fs";
|
|
24886
25024
|
import { join as join47 } from "path";
|
|
24887
25025
|
var cached2 = null;
|
|
24888
25026
|
var cachedAttempted = false;
|
|
@@ -24892,9 +25030,9 @@ function readBrandConfig() {
|
|
|
24892
25030
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
24893
25031
|
if (!platformRoot5) return null;
|
|
24894
25032
|
const brandPath = join47(platformRoot5, "config", "brand.json");
|
|
24895
|
-
if (!
|
|
25033
|
+
if (!existsSync43(brandPath)) return null;
|
|
24896
25034
|
try {
|
|
24897
|
-
cached2 = JSON.parse(
|
|
25035
|
+
cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
|
|
24898
25036
|
return cached2;
|
|
24899
25037
|
} catch {
|
|
24900
25038
|
return null;
|
|
@@ -25391,14 +25529,14 @@ async function writeEvent(opts) {
|
|
|
25391
25529
|
var visitor_event_default = app71;
|
|
25392
25530
|
|
|
25393
25531
|
// server/routes/session.ts
|
|
25394
|
-
import { resolve as
|
|
25395
|
-
import { existsSync as
|
|
25396
|
-
var
|
|
25532
|
+
import { resolve as resolve37 } from "path";
|
|
25533
|
+
import { existsSync as existsSync44, writeFileSync as writeFileSync16, mkdirSync as mkdirSync9 } from "fs";
|
|
25534
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
25397
25535
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
25398
25536
|
try {
|
|
25399
|
-
const cacheDir =
|
|
25537
|
+
const cacheDir = resolve37(MAXY_DIR, "branding-cache", accountId);
|
|
25400
25538
|
mkdirSync9(cacheDir, { recursive: true });
|
|
25401
|
-
|
|
25539
|
+
writeFileSync16(resolve37(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
25402
25540
|
} catch (err) {
|
|
25403
25541
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25404
25542
|
}
|
|
@@ -25408,7 +25546,7 @@ function parseVisitorCookie2(cookieHeader) {
|
|
|
25408
25546
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
25409
25547
|
if (!match) return null;
|
|
25410
25548
|
const value = decodeURIComponent(match[1]).trim();
|
|
25411
|
-
return
|
|
25549
|
+
return UUID_RE5.test(value) ? value : null;
|
|
25412
25550
|
}
|
|
25413
25551
|
function parseAccessSessionId2(cookieHeader) {
|
|
25414
25552
|
if (!cookieHeader) return null;
|
|
@@ -25475,8 +25613,8 @@ app72.post("/", async (c) => {
|
|
|
25475
25613
|
}
|
|
25476
25614
|
let agentConfig = null;
|
|
25477
25615
|
if (account) {
|
|
25478
|
-
const agentDir =
|
|
25479
|
-
if (!
|
|
25616
|
+
const agentDir = resolve37(account.accountDir, "agents", agentSlug);
|
|
25617
|
+
if (!existsSync44(agentDir) || !existsSync44(resolve37(agentDir, "config.json"))) {
|
|
25480
25618
|
return c.json({ error: "Agent not found" }, 404);
|
|
25481
25619
|
}
|
|
25482
25620
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -25506,7 +25644,7 @@ app72.post("/", async (c) => {
|
|
|
25506
25644
|
);
|
|
25507
25645
|
}
|
|
25508
25646
|
}
|
|
25509
|
-
if (body.session_key && typeof body.session_key === "string" &&
|
|
25647
|
+
if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
|
|
25510
25648
|
if (visitorId) {
|
|
25511
25649
|
const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
|
|
25512
25650
|
if (recent) {
|
|
@@ -25736,7 +25874,7 @@ var calendar_public_default = app73;
|
|
|
25736
25874
|
// server/routes/portal-fetch.ts
|
|
25737
25875
|
import { createReadStream as createReadStream3 } from "fs";
|
|
25738
25876
|
import { stat as stat8, readFile as readFile11, realpath } from "fs/promises";
|
|
25739
|
-
import { join as join48, resolve as
|
|
25877
|
+
import { join as join48, resolve as resolve38, sep as sep11 } from "path";
|
|
25740
25878
|
import { Readable as Readable3 } from "stream";
|
|
25741
25879
|
var app74 = new Hono();
|
|
25742
25880
|
var TAG41 = "[portal-fetch]";
|
|
@@ -25789,7 +25927,7 @@ ${expiresAtMs}`)
|
|
|
25789
25927
|
return diff === 0;
|
|
25790
25928
|
}
|
|
25791
25929
|
async function readAccountSecret(accountId) {
|
|
25792
|
-
const path =
|
|
25930
|
+
const path = resolve38(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
|
|
25793
25931
|
let text;
|
|
25794
25932
|
try {
|
|
25795
25933
|
text = await readFile11(path, "utf8");
|
|
@@ -25825,7 +25963,7 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
|
25825
25963
|
const exposeFolders = await readExposeFolders2(accountDir);
|
|
25826
25964
|
const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
|
|
25827
25965
|
if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
|
|
25828
|
-
const lexical =
|
|
25966
|
+
const lexical = resolve38(accountDir, relPath);
|
|
25829
25967
|
let root;
|
|
25830
25968
|
let absolute;
|
|
25831
25969
|
try {
|
|
@@ -25874,7 +26012,7 @@ async function handle(c, headOnly) {
|
|
|
25874
26012
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
25875
26013
|
}
|
|
25876
26014
|
const target = await resolveFetchTarget(
|
|
25877
|
-
|
|
26015
|
+
resolve38(DATA_ROOT, "accounts", accountId),
|
|
25878
26016
|
relPath,
|
|
25879
26017
|
owner || void 0
|
|
25880
26018
|
);
|
|
@@ -25988,7 +26126,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
25988
26126
|
}
|
|
25989
26127
|
|
|
25990
26128
|
// app/lib/ledger-census.ts
|
|
25991
|
-
import { readdirSync as
|
|
26129
|
+
import { readdirSync as readdirSync28, readFileSync as readFileSync43, statSync as statSync23 } from "fs";
|
|
25992
26130
|
import { join as join49 } from "path";
|
|
25993
26131
|
|
|
25994
26132
|
// ../lib/ledger-core/dist/reconcile.js
|
|
@@ -26037,7 +26175,7 @@ var DAY_MS = 864e5;
|
|
|
26037
26175
|
function countWriteRejects24h(logDir, now) {
|
|
26038
26176
|
let entries2;
|
|
26039
26177
|
try {
|
|
26040
|
-
entries2 =
|
|
26178
|
+
entries2 = readdirSync28(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
26041
26179
|
} catch {
|
|
26042
26180
|
return 0;
|
|
26043
26181
|
}
|
|
@@ -26046,7 +26184,7 @@ function countWriteRejects24h(logDir, now) {
|
|
|
26046
26184
|
const path = join49(logDir, name);
|
|
26047
26185
|
try {
|
|
26048
26186
|
if (now - statSync23(path).mtimeMs > DAY_MS) continue;
|
|
26049
|
-
for (const line of
|
|
26187
|
+
for (const line of readFileSync43(path, "utf8").split("\n")) {
|
|
26050
26188
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
26051
26189
|
}
|
|
26052
26190
|
} catch {
|
|
@@ -26315,7 +26453,7 @@ function startGraphHealthTimer() {
|
|
|
26315
26453
|
|
|
26316
26454
|
// app/lib/file-watcher.ts
|
|
26317
26455
|
import * as fsp2 from "fs/promises";
|
|
26318
|
-
import { resolve as
|
|
26456
|
+
import { resolve as resolve39, sep as sep12 } from "path";
|
|
26319
26457
|
var ACCOUNT_UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26320
26458
|
var DEFAULT_COALESCE_MS = 500;
|
|
26321
26459
|
var ROOTS = ["accounts"];
|
|
@@ -26334,7 +26472,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26334
26472
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
26335
26473
|
for (const r of ROOTS) {
|
|
26336
26474
|
try {
|
|
26337
|
-
await fsp2.mkdir(
|
|
26475
|
+
await fsp2.mkdir(resolve39(dataRoot, r), { recursive: true });
|
|
26338
26476
|
} catch (err) {
|
|
26339
26477
|
console.error(
|
|
26340
26478
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -26355,7 +26493,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26355
26493
|
timers.set(relativePath, t);
|
|
26356
26494
|
}
|
|
26357
26495
|
async function runHook(relativePath, accountId) {
|
|
26358
|
-
const absolute =
|
|
26496
|
+
const absolute = resolve39(dataRoot, relativePath);
|
|
26359
26497
|
let exists = false;
|
|
26360
26498
|
try {
|
|
26361
26499
|
const st = await fsp2.stat(absolute);
|
|
@@ -26379,7 +26517,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26379
26517
|
}
|
|
26380
26518
|
}
|
|
26381
26519
|
async function watchRoot(rootName) {
|
|
26382
|
-
const absRoot =
|
|
26520
|
+
const absRoot = resolve39(dataRoot, rootName);
|
|
26383
26521
|
try {
|
|
26384
26522
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
26385
26523
|
for await (const event of iter) {
|
|
@@ -26418,7 +26556,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26418
26556
|
|
|
26419
26557
|
// app/lib/migrate-uploads.ts
|
|
26420
26558
|
import { mkdir as mkdir4, readdir as readdir6, rename as rename4, rm as rm3 } from "fs/promises";
|
|
26421
|
-
import { dirname as dirname16, relative as relative8, resolve as
|
|
26559
|
+
import { dirname as dirname16, relative as relative8, resolve as resolve40 } from "path";
|
|
26422
26560
|
var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26423
26561
|
async function walkFiles(dir) {
|
|
26424
26562
|
const out = [];
|
|
@@ -26429,7 +26567,7 @@ async function walkFiles(dir) {
|
|
|
26429
26567
|
return out;
|
|
26430
26568
|
}
|
|
26431
26569
|
for (const e of entries2) {
|
|
26432
|
-
const abs =
|
|
26570
|
+
const abs = resolve40(dir, e.name);
|
|
26433
26571
|
if (e.isDirectory()) {
|
|
26434
26572
|
out.push(...await walkFiles(abs));
|
|
26435
26573
|
} else if (e.isFile()) {
|
|
@@ -26449,7 +26587,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26449
26587
|
let moved = 0;
|
|
26450
26588
|
for (const oldAbs of files) {
|
|
26451
26589
|
const suffix = relative8(srcDir, oldAbs);
|
|
26452
|
-
const newAbs =
|
|
26590
|
+
const newAbs = resolve40(destDir, suffix);
|
|
26453
26591
|
await mkdir4(dirname16(newAbs), { recursive: true });
|
|
26454
26592
|
await rename4(oldAbs, newAbs);
|
|
26455
26593
|
moved++;
|
|
@@ -26476,7 +26614,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26476
26614
|
}
|
|
26477
26615
|
async function migrateUploads(opts = {}) {
|
|
26478
26616
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
26479
|
-
const oldRoot =
|
|
26617
|
+
const oldRoot = resolve40(dataRoot, "uploads");
|
|
26480
26618
|
let topEntries;
|
|
26481
26619
|
try {
|
|
26482
26620
|
topEntries = await readdir6(oldRoot, { withFileTypes: true });
|
|
@@ -26497,8 +26635,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26497
26635
|
const name = entry.name;
|
|
26498
26636
|
if (ACCOUNT_UUID_RE4.test(name)) {
|
|
26499
26637
|
moved += await relocateTree(
|
|
26500
|
-
|
|
26501
|
-
|
|
26638
|
+
resolve40(oldRoot, name),
|
|
26639
|
+
resolve40(dataRoot, "accounts", name, "uploads"),
|
|
26502
26640
|
dataRoot,
|
|
26503
26641
|
name,
|
|
26504
26642
|
session
|
|
@@ -26510,8 +26648,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26510
26648
|
continue;
|
|
26511
26649
|
}
|
|
26512
26650
|
moved += await relocateTree(
|
|
26513
|
-
|
|
26514
|
-
|
|
26651
|
+
resolve40(oldRoot, "public"),
|
|
26652
|
+
resolve40(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
26515
26653
|
dataRoot,
|
|
26516
26654
|
null,
|
|
26517
26655
|
// public uploads carry no graph nodes
|
|
@@ -26541,7 +26679,7 @@ async function migrateUploads(opts = {}) {
|
|
|
26541
26679
|
|
|
26542
26680
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
26543
26681
|
import { readdir as readdir7, readFile as readFile12, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
|
|
26544
|
-
import { existsSync as
|
|
26682
|
+
import { existsSync as existsSync45 } from "fs";
|
|
26545
26683
|
import { join as join50 } from "path";
|
|
26546
26684
|
var ADMIN_ROLE2 = "admin";
|
|
26547
26685
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
@@ -26571,7 +26709,7 @@ async function writeRaw(path, obj) {
|
|
|
26571
26709
|
await rename5(tmp, path);
|
|
26572
26710
|
} catch (err) {
|
|
26573
26711
|
try {
|
|
26574
|
-
if (
|
|
26712
|
+
if (existsSync45(tmp)) await unlink4(tmp);
|
|
26575
26713
|
} catch {
|
|
26576
26714
|
}
|
|
26577
26715
|
throw err;
|
|
@@ -26694,7 +26832,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
|
|
|
26694
26832
|
|
|
26695
26833
|
// app/lib/migrate-sidecar-account-ids.ts
|
|
26696
26834
|
import { readdir as readdir8, readFile as readFile13, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
|
|
26697
|
-
import { existsSync as
|
|
26835
|
+
import { existsSync as existsSync46 } from "fs";
|
|
26698
26836
|
import { join as join51 } from "path";
|
|
26699
26837
|
var SESSION_META_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
26700
26838
|
function projectSlugForCwd(cwd) {
|
|
@@ -26721,7 +26859,7 @@ async function writeRaw2(path, obj) {
|
|
|
26721
26859
|
await rename6(tmp, path);
|
|
26722
26860
|
} catch (err) {
|
|
26723
26861
|
try {
|
|
26724
|
-
if (
|
|
26862
|
+
if (existsSync46(tmp)) await unlink5(tmp);
|
|
26725
26863
|
} catch {
|
|
26726
26864
|
}
|
|
26727
26865
|
throw err;
|
|
@@ -27897,16 +28035,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27897
28035
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
27898
28036
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
27899
28037
|
awaitReply(key, timeoutMs) {
|
|
27900
|
-
return new Promise((
|
|
28038
|
+
return new Promise((resolve46) => {
|
|
27901
28039
|
const timer = setTimeout(() => {
|
|
27902
28040
|
this.replyAwaiters.delete(key);
|
|
27903
|
-
|
|
28041
|
+
resolve46({ timeout: true });
|
|
27904
28042
|
}, timeoutMs);
|
|
27905
28043
|
if (timer.unref) timer.unref();
|
|
27906
28044
|
this.replyAwaiters.set(key, (r) => {
|
|
27907
28045
|
clearTimeout(timer);
|
|
27908
28046
|
this.replyAwaiters.delete(key);
|
|
27909
|
-
|
|
28047
|
+
resolve46(r);
|
|
27910
28048
|
});
|
|
27911
28049
|
});
|
|
27912
28050
|
}
|
|
@@ -27917,11 +28055,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27917
28055
|
* terminal dialog stays answerable). */
|
|
27918
28056
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
27919
28057
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
27920
|
-
return new Promise((
|
|
28058
|
+
return new Promise((resolve46) => {
|
|
27921
28059
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
27922
28060
|
const timer = setTimeout(() => {
|
|
27923
28061
|
this.pendingPrompts.delete(k);
|
|
27924
|
-
|
|
28062
|
+
resolve46({ timeout: true });
|
|
27925
28063
|
}, timeoutMs);
|
|
27926
28064
|
if (timer.unref) timer.unref();
|
|
27927
28065
|
this.pendingPrompts.set(k, {
|
|
@@ -27931,7 +28069,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27931
28069
|
clearTimeout(timer);
|
|
27932
28070
|
this.pendingPrompts.delete(k);
|
|
27933
28071
|
this.deps.onPointerChange?.(p.key);
|
|
27934
|
-
|
|
28072
|
+
resolve46(r);
|
|
27935
28073
|
}
|
|
27936
28074
|
});
|
|
27937
28075
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -28507,7 +28645,7 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
28507
28645
|
|
|
28508
28646
|
// app/lib/webchat/file-delivery.ts
|
|
28509
28647
|
import { realpathSync as realpathSync9 } from "fs";
|
|
28510
|
-
import { resolve as
|
|
28648
|
+
import { resolve as resolve41 } from "path";
|
|
28511
28649
|
|
|
28512
28650
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
28513
28651
|
var SEND_USER_FILE = "SendUserFile";
|
|
@@ -28608,7 +28746,7 @@ function makeWebchatSendFile(entry) {
|
|
|
28608
28746
|
console.error(`${TAG45} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
28609
28747
|
return { ok: false, error: "no-account" };
|
|
28610
28748
|
}
|
|
28611
|
-
const accountDir =
|
|
28749
|
+
const accountDir = resolve41(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
28612
28750
|
try {
|
|
28613
28751
|
const resolved = realpathSync9(filePath);
|
|
28614
28752
|
const accountResolved = realpathSync9(accountDir);
|
|
@@ -29172,7 +29310,7 @@ function buildTelegramSpawnRequest(input) {
|
|
|
29172
29310
|
// app/lib/telegram/outbound/send-document.ts
|
|
29173
29311
|
import { realpathSync as realpathSync10 } from "fs";
|
|
29174
29312
|
import { readFile as readFile14, stat as stat10 } from "fs/promises";
|
|
29175
|
-
import { resolve as
|
|
29313
|
+
import { resolve as resolve42, basename as basename15 } from "path";
|
|
29176
29314
|
var TAG47 = "[telegram:outbound]";
|
|
29177
29315
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
29178
29316
|
async function sendTelegramDocument(input) {
|
|
@@ -29183,7 +29321,7 @@ async function sendTelegramDocument(input) {
|
|
|
29183
29321
|
if (!maxyAccountId || !platformRoot5) {
|
|
29184
29322
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
29185
29323
|
}
|
|
29186
|
-
const accountDir =
|
|
29324
|
+
const accountDir = resolve42(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
29187
29325
|
let accountResolved;
|
|
29188
29326
|
try {
|
|
29189
29327
|
accountResolved = realpathSync10(accountDir);
|
|
@@ -29591,14 +29729,14 @@ function resolveScheduledEffectiveAccountForInstall(accountDir, destination) {
|
|
|
29591
29729
|
}
|
|
29592
29730
|
|
|
29593
29731
|
// server/lib/booking-site-accounts.ts
|
|
29594
|
-
import { existsSync as
|
|
29595
|
-
import { resolve as
|
|
29732
|
+
import { existsSync as existsSync47, readFileSync as readFileSync44 } from "fs";
|
|
29733
|
+
import { resolve as resolve43 } from "path";
|
|
29596
29734
|
function listBookingSiteAccounts(accounts) {
|
|
29597
29735
|
return accounts.filter((a) => {
|
|
29598
|
-
const availPath =
|
|
29599
|
-
if (!
|
|
29736
|
+
const availPath = resolve43(a.accountDir, "calendar-availability.json");
|
|
29737
|
+
if (!existsSync47(availPath)) return false;
|
|
29600
29738
|
try {
|
|
29601
|
-
const cfg = JSON.parse(
|
|
29739
|
+
const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
|
|
29602
29740
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
29603
29741
|
} catch {
|
|
29604
29742
|
return false;
|
|
@@ -29636,8 +29774,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
29636
29774
|
|
|
29637
29775
|
// ../lib/entitlement/src/index.ts
|
|
29638
29776
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
29639
|
-
import { existsSync as
|
|
29640
|
-
import { resolve as
|
|
29777
|
+
import { existsSync as existsSync48, readFileSync as readFileSync45, statSync as statSync24 } from "fs";
|
|
29778
|
+
import { resolve as resolve44 } from "path";
|
|
29641
29779
|
|
|
29642
29780
|
// ../lib/entitlement/src/canonicalize.ts
|
|
29643
29781
|
function canonicalize(value) {
|
|
@@ -29672,7 +29810,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
29672
29810
|
var GRACE_DAYS = 7;
|
|
29673
29811
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
29674
29812
|
function pubkeyPath(brand) {
|
|
29675
|
-
return
|
|
29813
|
+
return resolve44(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
29676
29814
|
}
|
|
29677
29815
|
var memo = null;
|
|
29678
29816
|
function memoKey(mtimeMs, account) {
|
|
@@ -29684,8 +29822,8 @@ function resolveEntitlement(brand, account) {
|
|
|
29684
29822
|
if (brand.commercialMode !== true) {
|
|
29685
29823
|
return logResolved(implicitTrust(account), null);
|
|
29686
29824
|
}
|
|
29687
|
-
const entitlementPath =
|
|
29688
|
-
if (!
|
|
29825
|
+
const entitlementPath = resolve44(brand.configDir, "entitlement.json");
|
|
29826
|
+
if (!existsSync48(entitlementPath)) {
|
|
29689
29827
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
29690
29828
|
}
|
|
29691
29829
|
const stat11 = statSync24(entitlementPath);
|
|
@@ -29700,7 +29838,7 @@ function resolveEntitlement(brand, account) {
|
|
|
29700
29838
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
29701
29839
|
let pubkeyPem;
|
|
29702
29840
|
try {
|
|
29703
|
-
pubkeyPem =
|
|
29841
|
+
pubkeyPem = readFileSync45(pubkeyPath(brand), "utf-8");
|
|
29704
29842
|
} catch (err) {
|
|
29705
29843
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
29706
29844
|
reason: "pubkey-missing"
|
|
@@ -29714,7 +29852,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
29714
29852
|
}
|
|
29715
29853
|
let envelope;
|
|
29716
29854
|
try {
|
|
29717
|
-
envelope = JSON.parse(
|
|
29855
|
+
envelope = JSON.parse(readFileSync45(entitlementPath, "utf-8"));
|
|
29718
29856
|
} catch {
|
|
29719
29857
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
29720
29858
|
}
|
|
@@ -29878,12 +30016,12 @@ installMediaDownloadGuard();
|
|
|
29878
30016
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
29879
30017
|
var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join52(PLATFORM_ROOT6, "config", "brand.json") : "";
|
|
29880
30018
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
29881
|
-
if (BRAND_JSON_PATH && !
|
|
30019
|
+
if (BRAND_JSON_PATH && !existsSync49(BRAND_JSON_PATH)) {
|
|
29882
30020
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
29883
30021
|
}
|
|
29884
|
-
if (BRAND_JSON_PATH &&
|
|
30022
|
+
if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
|
|
29885
30023
|
try {
|
|
29886
|
-
const parsed = JSON.parse(
|
|
30024
|
+
const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
29887
30025
|
BRAND = { ...BRAND, ...parsed };
|
|
29888
30026
|
} catch (err) {
|
|
29889
30027
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -29918,8 +30056,8 @@ var brandLoginOpts = {
|
|
|
29918
30056
|
var ALIAS_DOMAINS_PATH = join52(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
29919
30057
|
function loadAliasDomains() {
|
|
29920
30058
|
try {
|
|
29921
|
-
if (!
|
|
29922
|
-
const parsed = JSON.parse(
|
|
30059
|
+
if (!existsSync49(ALIAS_DOMAINS_PATH)) return null;
|
|
30060
|
+
const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
29923
30061
|
if (!Array.isArray(parsed)) {
|
|
29924
30062
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
29925
30063
|
return null;
|
|
@@ -29994,7 +30132,7 @@ var waGateway = new WaGateway({
|
|
|
29994
30132
|
fetchStandingRules: fetchAccountStandingRules,
|
|
29995
30133
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
29996
30134
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
29997
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
30135
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
29998
30136
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
29999
30137
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
30000
30138
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -30009,7 +30147,7 @@ var waGateway = new WaGateway({
|
|
|
30009
30147
|
caption,
|
|
30010
30148
|
accountId,
|
|
30011
30149
|
maxyAccountId,
|
|
30012
|
-
platformRoot:
|
|
30150
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."))
|
|
30013
30151
|
});
|
|
30014
30152
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
30015
30153
|
},
|
|
@@ -30711,20 +30849,20 @@ app75.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
30711
30849
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
30712
30850
|
return c.text("Not found", 404);
|
|
30713
30851
|
}
|
|
30714
|
-
const filePath =
|
|
30715
|
-
const expectedDir =
|
|
30852
|
+
const filePath = resolve45(account.accountDir, "agents", slug, "assets", filename);
|
|
30853
|
+
const expectedDir = resolve45(account.accountDir, "agents", slug, "assets");
|
|
30716
30854
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30717
30855
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
30718
30856
|
return c.text("Forbidden", 403);
|
|
30719
30857
|
}
|
|
30720
|
-
if (!
|
|
30858
|
+
if (!existsSync49(filePath)) {
|
|
30721
30859
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
30722
30860
|
return c.text("Not found", 404);
|
|
30723
30861
|
}
|
|
30724
30862
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30725
30863
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30726
30864
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
30727
|
-
const body =
|
|
30865
|
+
const body = readFileSync46(filePath);
|
|
30728
30866
|
return c.body(body, 200, {
|
|
30729
30867
|
"Content-Type": contentType,
|
|
30730
30868
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -30741,20 +30879,20 @@ app75.get("/generated/:filename", (c) => {
|
|
|
30741
30879
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30742
30880
|
return c.text("Not found", 404);
|
|
30743
30881
|
}
|
|
30744
|
-
const filePath =
|
|
30745
|
-
const expectedDir =
|
|
30882
|
+
const filePath = resolve45(account.accountDir, "generated", filename);
|
|
30883
|
+
const expectedDir = resolve45(account.accountDir, "generated");
|
|
30746
30884
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30747
30885
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
30748
30886
|
return c.text("Forbidden", 403);
|
|
30749
30887
|
}
|
|
30750
|
-
if (!
|
|
30888
|
+
if (!existsSync49(filePath)) {
|
|
30751
30889
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30752
30890
|
return c.text("Not found", 404);
|
|
30753
30891
|
}
|
|
30754
30892
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30755
30893
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30756
30894
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
30757
|
-
const body =
|
|
30895
|
+
const body = readFileSync46(filePath);
|
|
30758
30896
|
return c.body(body, 200, {
|
|
30759
30897
|
"Content-Type": contentType,
|
|
30760
30898
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -30767,9 +30905,9 @@ app75.route("/v", visitor_consent_default);
|
|
|
30767
30905
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
30768
30906
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
30769
30907
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
30770
|
-
if (BRAND_JSON_PATH &&
|
|
30908
|
+
if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
|
|
30771
30909
|
try {
|
|
30772
|
-
const fullBrand = JSON.parse(
|
|
30910
|
+
const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
30773
30911
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
30774
30912
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
30775
30913
|
} catch {
|
|
@@ -30796,11 +30934,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
30796
30934
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
30797
30935
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
30798
30936
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
30799
|
-
(p) =>
|
|
30937
|
+
(p) => existsSync49(resolve45(process.cwd(), "public", p.replace(/^\//, "")))
|
|
30800
30938
|
);
|
|
30801
30939
|
var SW_SOURCE = (() => {
|
|
30802
30940
|
try {
|
|
30803
|
-
return
|
|
30941
|
+
return readFileSync46(resolve45(process.cwd(), "public", "sw.js"), "utf-8");
|
|
30804
30942
|
} catch {
|
|
30805
30943
|
return null;
|
|
30806
30944
|
}
|
|
@@ -30809,8 +30947,8 @@ function readInstalledVersion() {
|
|
|
30809
30947
|
try {
|
|
30810
30948
|
if (!PLATFORM_ROOT6) return "unknown";
|
|
30811
30949
|
const versionFile = join52(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
|
|
30812
|
-
if (!
|
|
30813
|
-
const content =
|
|
30950
|
+
if (!existsSync49(versionFile)) return "unknown";
|
|
30951
|
+
const content = readFileSync46(versionFile, "utf-8").trim();
|
|
30814
30952
|
return content || "unknown";
|
|
30815
30953
|
} catch {
|
|
30816
30954
|
return "unknown";
|
|
@@ -30821,7 +30959,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
|
|
|
30821
30959
|
function cachedHtml(file) {
|
|
30822
30960
|
let html = htmlCache.get(file);
|
|
30823
30961
|
if (!html) {
|
|
30824
|
-
html =
|
|
30962
|
+
html = readFileSync46(resolve45(process.cwd(), "public", file), "utf-8");
|
|
30825
30963
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
30826
30964
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
30827
30965
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -30843,8 +30981,8 @@ function loadBrandingCache(agentSlug) {
|
|
|
30843
30981
|
const accountId = getDefaultAccountId();
|
|
30844
30982
|
if (!accountId) return null;
|
|
30845
30983
|
const cachePath = join52(configDir, "branding-cache", accountId, `${agentSlug}.json`);
|
|
30846
|
-
if (!
|
|
30847
|
-
return JSON.parse(
|
|
30984
|
+
if (!existsSync49(cachePath)) return null;
|
|
30985
|
+
return JSON.parse(readFileSync46(cachePath, "utf-8"));
|
|
30848
30986
|
} catch {
|
|
30849
30987
|
return null;
|
|
30850
30988
|
}
|
|
@@ -30939,7 +31077,7 @@ app75.use("/vnc-popout.html", logViewerFetch);
|
|
|
30939
31077
|
app75.get("/vnc-popout.html", (c) => {
|
|
30940
31078
|
let html = htmlCache.get("vnc-popout.html");
|
|
30941
31079
|
if (!html) {
|
|
30942
|
-
html =
|
|
31080
|
+
html = readFileSync46(resolve45(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
30943
31081
|
const name = escapeHtml(BRAND.productName);
|
|
30944
31082
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
30945
31083
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -31092,9 +31230,9 @@ var httpServer = serve({ fetch: app75.fetch, port, hostname });
|
|
|
31092
31230
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
31093
31231
|
{
|
|
31094
31232
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31095
|
-
const reconcileScript =
|
|
31233
|
+
const reconcileScript = resolve45(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
31096
31234
|
const runReconcile = (ctx) => {
|
|
31097
|
-
if (!
|
|
31235
|
+
if (!existsSync49(reconcileScript)) return;
|
|
31098
31236
|
try {
|
|
31099
31237
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
31100
31238
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -31133,14 +31271,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31133
31271
|
{
|
|
31134
31272
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
31135
31273
|
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31136
|
-
const dreamSweepScript =
|
|
31274
|
+
const dreamSweepScript = resolve45(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
31137
31275
|
registerLoop({
|
|
31138
31276
|
name: "dream-cycle-sweep",
|
|
31139
31277
|
intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
|
|
31140
31278
|
firstRunDelayMs: 3e4,
|
|
31141
31279
|
detached: true,
|
|
31142
31280
|
run: (ctx) => {
|
|
31143
|
-
if (!
|
|
31281
|
+
if (!existsSync49(dreamSweepScript)) return;
|
|
31144
31282
|
try {
|
|
31145
31283
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
31146
31284
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -31157,10 +31295,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31157
31295
|
}
|
|
31158
31296
|
{
|
|
31159
31297
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31160
|
-
const outlookScript =
|
|
31298
|
+
const outlookScript = resolve45(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
31161
31299
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
31162
31300
|
const runOutlookComplete = (ctx) => {
|
|
31163
|
-
if (!
|
|
31301
|
+
if (!existsSync49(outlookScript)) return;
|
|
31164
31302
|
try {
|
|
31165
31303
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
31166
31304
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -31183,18 +31321,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31183
31321
|
}
|
|
31184
31322
|
{
|
|
31185
31323
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31186
|
-
const strandedAccountsDir =
|
|
31324
|
+
const strandedAccountsDir = resolve45(auditRoot, "..", "data/accounts");
|
|
31187
31325
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
31188
31326
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
31189
31327
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31190
31328
|
const runStrandedAudit = () => {
|
|
31191
31329
|
try {
|
|
31192
|
-
if (!
|
|
31330
|
+
if (!existsSync49(strandedAccountsDir)) return;
|
|
31193
31331
|
const now = Date.now();
|
|
31194
|
-
for (const name of
|
|
31332
|
+
for (const name of readdirSync29(strandedAccountsDir)) {
|
|
31195
31333
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
31196
|
-
const pendingPath2 =
|
|
31197
|
-
if (!
|
|
31334
|
+
const pendingPath2 = resolve45(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
31335
|
+
if (!existsSync49(pendingPath2)) continue;
|
|
31198
31336
|
const ageMs2 = now - statSync25(pendingPath2).mtimeMs;
|
|
31199
31337
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
31200
31338
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
@@ -31213,7 +31351,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31213
31351
|
}
|
|
31214
31352
|
{
|
|
31215
31353
|
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31216
|
-
const googleAccountsDir =
|
|
31354
|
+
const googleAccountsDir = resolve45(googleRoot, "..", "data/accounts");
|
|
31217
31355
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
31218
31356
|
const runGooglePendingAuditSafe = () => {
|
|
31219
31357
|
try {
|
|
@@ -31228,10 +31366,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31228
31366
|
firstRunDelayMs: 27e3,
|
|
31229
31367
|
run: runGooglePendingAuditSafe
|
|
31230
31368
|
});
|
|
31231
|
-
const googleAuditScript =
|
|
31369
|
+
const googleAuditScript = resolve45(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
31232
31370
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
31233
31371
|
const runGoogleAccountAudit = (ctx) => {
|
|
31234
|
-
if (!
|
|
31372
|
+
if (!existsSync49(googleAuditScript)) return;
|
|
31235
31373
|
try {
|
|
31236
31374
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
31237
31375
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -31324,7 +31462,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31324
31462
|
}
|
|
31325
31463
|
{
|
|
31326
31464
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31327
|
-
const publishScript =
|
|
31465
|
+
const publishScript = resolve45(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
31328
31466
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
31329
31467
|
const bookingAccounts = () => {
|
|
31330
31468
|
try {
|
|
@@ -31335,7 +31473,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31335
31473
|
}
|
|
31336
31474
|
};
|
|
31337
31475
|
const spawnPublish = (account, ctx) => {
|
|
31338
|
-
if (!
|
|
31476
|
+
if (!existsSync49(publishScript)) return;
|
|
31339
31477
|
try {
|
|
31340
31478
|
const child = spawn3(process.execPath, [publishScript], {
|
|
31341
31479
|
env: {
|
|
@@ -31354,21 +31492,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31354
31492
|
}
|
|
31355
31493
|
};
|
|
31356
31494
|
const auditSnapshotAge = (account) => {
|
|
31357
|
-
const availPath =
|
|
31495
|
+
const availPath = resolve45(account.accountDir, "calendar-availability.json");
|
|
31358
31496
|
let hasBookingSite = false;
|
|
31359
31497
|
try {
|
|
31360
|
-
if (
|
|
31361
|
-
const cfg = JSON.parse(
|
|
31498
|
+
if (existsSync49(availPath)) {
|
|
31499
|
+
const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
|
|
31362
31500
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
31363
31501
|
}
|
|
31364
31502
|
} catch {
|
|
31365
31503
|
}
|
|
31366
31504
|
if (!hasBookingSite) return;
|
|
31367
|
-
const statePath =
|
|
31505
|
+
const statePath = resolve45(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
31368
31506
|
let lastSuccessAt = null;
|
|
31369
|
-
if (
|
|
31507
|
+
if (existsSync49(statePath)) {
|
|
31370
31508
|
try {
|
|
31371
|
-
const rec = JSON.parse(
|
|
31509
|
+
const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
|
|
31372
31510
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
31373
31511
|
} catch {
|
|
31374
31512
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -31401,11 +31539,11 @@ startTimeEntryCensus(() => getSession());
|
|
|
31401
31539
|
startLedgerCensus(() => getSession());
|
|
31402
31540
|
{
|
|
31403
31541
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31404
|
-
const auditScript =
|
|
31542
|
+
const auditScript = resolve45(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
31405
31543
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
31406
31544
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
31407
31545
|
const runConnectorAudit = (ctx) => {
|
|
31408
|
-
if (!
|
|
31546
|
+
if (!existsSync49(auditScript)) return;
|
|
31409
31547
|
try {
|
|
31410
31548
|
const child = spawn3(process.execPath, [auditScript], {
|
|
31411
31549
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -31525,11 +31663,11 @@ try {
|
|
|
31525
31663
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31526
31664
|
async function runAdminUserReconcileTick() {
|
|
31527
31665
|
try {
|
|
31528
|
-
if (!
|
|
31666
|
+
if (!existsSync49(USERS_FILE)) {
|
|
31529
31667
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
31530
31668
|
return;
|
|
31531
31669
|
}
|
|
31532
|
-
const usersRaw =
|
|
31670
|
+
const usersRaw = readFileSync46(USERS_FILE, "utf-8").trim();
|
|
31533
31671
|
if (!usersRaw) {
|
|
31534
31672
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
31535
31673
|
return;
|
|
@@ -31581,8 +31719,8 @@ registerLoop({
|
|
|
31581
31719
|
});
|
|
31582
31720
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31583
31721
|
function countUsersRows() {
|
|
31584
|
-
if (!
|
|
31585
|
-
const raw =
|
|
31722
|
+
if (!existsSync49(USERS_FILE)) return 0;
|
|
31723
|
+
const raw = readFileSync46(USERS_FILE, "utf-8").trim();
|
|
31586
31724
|
if (!raw) return 0;
|
|
31587
31725
|
const users = JSON.parse(raw);
|
|
31588
31726
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -31716,7 +31854,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
31716
31854
|
}
|
|
31717
31855
|
init({
|
|
31718
31856
|
configDir: configDirForWhatsApp,
|
|
31719
|
-
platformRoot:
|
|
31857
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..")),
|
|
31720
31858
|
accountConfig: bootAccountConfig,
|
|
31721
31859
|
// Task 2074 — enrich with the sub-account name and fan out to every open
|
|
31722
31860
|
// admin SSE stream. Fire-and-forget: the manager's persist path must not
|