@rubytech/create-sitedesk-code 0.1.528 → 0.1.530
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +13 -0
- 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/lib/routine-templates/dist/index.d.ts +19 -3
- package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/index.js +22 -4
- package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +19 -6
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.js +127 -17
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +46 -3
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +52 -10
- package/payload/platform/lib/routine-templates/src/index.ts +30 -4
- package/payload/platform/lib/routine-templates/src/roster.ts +147 -17
- 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 +31 -6
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +28 -3
- 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/PLUGIN.md +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +5 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js +100 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts +36 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js +82 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js +99 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +12 -12
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js +79 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js +23 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +61 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -1
- 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 +33 -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 +111 -9
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +21 -69
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts +24 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js +87 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js +123 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js +71 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js +14 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +9 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +19 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +24 -9
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.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/{chunk-UTIHI6KV.js → chunk-2YMGNYA3.js} +12 -12
- package/payload/server/{manager-B4LRDZKC.js → manager-XPRN5UF5.js} +1 -1
- package/payload/server/package.json +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-7Czw3MAC.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-BxJPbC3p.js → AdminShell-D5GApZ_n.js} +1 -1
- package/payload/server/public/assets/AdminShell-D5GApZ_n.js.br +0 -0
- package/payload/server/public/assets/AdminShell-D5GApZ_n.js.gz +0 -0
- package/payload/server/public/assets/{CdpScreencastSurface-5HLhTQTV.js → CdpScreencastSurface-BbekDUFw.js} +1 -1
- package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.br +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.gz +0 -0
- package/payload/server/public/assets/{activity-BaSYn62l.js → activity-ClI-RgJu.js} +1 -1
- package/payload/server/public/assets/activity-ClI-RgJu.js.br +0 -0
- package/payload/server/public/assets/activity-ClI-RgJu.js.gz +0 -0
- package/payload/server/public/assets/{admin-CYCKrV_x.js → admin-svtCmBPk.js} +1 -1
- package/payload/server/public/assets/admin-svtCmBPk.js.br +0 -0
- package/payload/server/public/assets/admin-svtCmBPk.js.gz +0 -0
- package/payload/server/public/assets/{agents-D8EJG-ta.js → agents-BO8YBj8d.js} +1 -1
- package/payload/server/public/assets/agents-BO8YBj8d.js.br +0 -0
- package/payload/server/public/assets/agents-BO8YBj8d.js.gz +0 -0
- package/payload/server/public/assets/{browser-D6Y_Zu8C.js → browser-Bj8oTG5R.js} +1 -1
- package/payload/server/public/assets/browser-Bj8oTG5R.js.br +0 -0
- package/payload/server/public/assets/browser-Bj8oTG5R.js.gz +0 -0
- package/payload/server/public/assets/{calendar-DD4oVa-r.js → calendar-CrkSY8U7.js} +1 -1
- package/payload/server/public/assets/calendar-CrkSY8U7.js.br +0 -0
- package/payload/server/public/assets/calendar-CrkSY8U7.js.gz +0 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js +1 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js.br +0 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-CdUzxzeB.js +1 -0
- package/payload/server/public/assets/chevron-left-CdUzxzeB.js.br +0 -0
- package/payload/server/public/assets/chevron-right-CKGwd-M0.js +1 -0
- package/payload/server/public/assets/chevron-right-CKGwd-M0.js.br +0 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js +1 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js.br +0 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js.gz +0 -0
- package/payload/server/public/assets/data-DF0Pstdp.js +1 -0
- package/payload/server/public/assets/data-DF0Pstdp.js.br +1 -0
- package/payload/server/public/assets/data-DF0Pstdp.js.gz +0 -0
- package/payload/server/public/assets/{file-download-sXU3_umF.js → file-download-Di_s0_4w.js} +1 -1
- package/payload/server/public/assets/file-download-Di_s0_4w.js.br +0 -0
- package/payload/server/public/assets/file-download-Di_s0_4w.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CeXBviDH.js → file-text-CP1KIrJV.js} +1 -1
- package/payload/server/public/assets/file-text-CP1KIrJV.js.br +1 -0
- package/payload/server/public/assets/file-text-CP1KIrJV.js.gz +0 -0
- package/payload/server/public/assets/{graph-BSuDP6k7.js → graph-BCMscnCV.js} +1 -1
- package/payload/server/public/assets/graph-BCMscnCV.js.br +0 -0
- package/payload/server/public/assets/graph-BCMscnCV.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-D2pQkgYW.js → graph-labels-CgP17xHK.js} +1 -1
- package/payload/server/public/assets/graph-labels-CgP17xHK.js.br +0 -0
- package/payload/server/public/assets/graph-labels-CgP17xHK.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-DlzSNygU.js → maximize-2-DkQzDv-g.js} +1 -1
- package/payload/server/public/assets/maximize-2-DkQzDv-g.js.br +0 -0
- package/payload/server/public/assets/maximize-2-DkQzDv-g.js.gz +0 -0
- package/payload/server/public/assets/{operator-BP61-xjz.js → operator-CLbCar9e.js} +1 -1
- package/payload/server/public/assets/operator-CLbCar9e.js.br +0 -0
- package/payload/server/public/assets/operator-CLbCar9e.js.gz +0 -0
- package/payload/server/public/assets/{page-DX7ArY_s.js → page-CNJl3tWT.js} +1 -1
- package/payload/server/public/assets/page-CNJl3tWT.js.br +0 -0
- package/payload/server/public/assets/page-CNJl3tWT.js.gz +0 -0
- package/payload/server/public/assets/{page-eQ4OVros.js → page-CPVUAwb8.js} +1 -1
- package/payload/server/public/assets/page-CPVUAwb8.js.br +0 -0
- package/payload/server/public/assets/page-CPVUAwb8.js.gz +0 -0
- package/payload/server/public/assets/{public-DPDKFKM2.js → public-DQea3Ybz.js} +1 -1
- package/payload/server/public/assets/public-DQea3Ybz.js.br +0 -0
- package/payload/server/public/assets/public-DQea3Ybz.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-BR0JbPFV.js → rotate-ccw-DPw0vXC0.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.gz +0 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js +2 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js.br +0 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js.gz +0 -0
- package/payload/server/public/assets/{skills-fH0uA7cj.js → skills-0FOjKUM-.js} +1 -1
- package/payload/server/public/assets/skills-0FOjKUM-.js.br +0 -0
- package/payload/server/public/assets/skills-0FOjKUM-.js.gz +0 -0
- package/payload/server/public/assets/{tasks-CrVzFrTR.js → tasks-BUVsPEGm.js} +1 -1
- package/payload/server/public/assets/tasks-BUVsPEGm.js.br +0 -0
- package/payload/server/public/assets/tasks-BUVsPEGm.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-C_0jiMpQ.js → time-entry-format-B6fX_19a.js} +1 -1
- package/payload/server/public/assets/time-entry-format-B6fX_19a.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-B6fX_19a.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-eLJHC_QJ.js → triangle-alert-vAaSDhVq.js} +1 -1
- package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-vPCmdOmY.js → useCopyFeedback-BvIRgs7W.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.gz +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css → useSubAccountSwitcher-DM5Y9eio.css} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-DM5Y9eio.css.br +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css.gz → useSubAccountSwitcher-DM5Y9eio.css.gz} +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-D5bFDRqL.js → useVoiceRecorder-CiDOh8PG.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.gz +0 -0
- package/payload/server/public/assets/{wrench-sXisQXkf.js → wrench-BNBtwT2p.js} +1 -1
- package/payload/server/public/assets/wrench-BNBtwT2p.js.br +0 -0
- package/payload/server/public/assets/wrench-BNBtwT2p.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 +353 -209
- 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-BEwQMRMo.js} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.br → useSubAccountSwitcher-BEwQMRMo.js.br} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.gz → useSubAccountSwitcher-BEwQMRMo.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -183,7 +183,7 @@ import {
|
|
|
183
183
|
waitForConnection,
|
|
184
184
|
warnNonUuidAccount,
|
|
185
185
|
writeChatMetadataMerged
|
|
186
|
-
} from "./chunk-
|
|
186
|
+
} from "./chunk-2YMGNYA3.js";
|
|
187
187
|
import {
|
|
188
188
|
ACCOUNTS_DIR,
|
|
189
189
|
BIN_DIR,
|
|
@@ -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
|
}
|
|
@@ -4999,11 +4999,11 @@ async function defaultHttpGet(url) {
|
|
|
4999
4999
|
}
|
|
5000
5000
|
}
|
|
5001
5001
|
async function defaultResolve(accountId) {
|
|
5002
|
-
const { resolveSocket: resolveSocket2 } = await import("./manager-
|
|
5002
|
+
const { resolveSocket: resolveSocket2 } = await import("./manager-XPRN5UF5.js");
|
|
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];
|
|
@@ -22643,7 +22720,8 @@ var ROUTINE_COLS = `e.eventId AS eventId, e.name AS name, e.eventStatus AS event
|
|
|
22643
22720
|
e.timezone AS timezone, e.startDate AS startDate,
|
|
22644
22721
|
e.agentChannel AS agentChannel, e.agentDestination AS agentDestination, e.agentPrompt AS agentPrompt,
|
|
22645
22722
|
e.actionPlugin AS actionPlugin, e.actionTool AS actionTool, e.actionArgs AS actionArgs,
|
|
22646
|
-
e.notes AS notes, e.
|
|
22723
|
+
e.notes AS notes, e.routineDescription AS routineDescription,
|
|
22724
|
+
e.lastDispatchResult AS lastDispatchResult, e.lastDispatchAt AS lastDispatchAt,
|
|
22647
22725
|
e.suspendedInBulk AS suspendedInBulk`;
|
|
22648
22726
|
function mapRoutine(r) {
|
|
22649
22727
|
const g = (k) => r.get(k) ?? null;
|
|
@@ -22663,11 +22741,16 @@ function mapRoutine(r) {
|
|
|
22663
22741
|
actionTool: g("actionTool"),
|
|
22664
22742
|
actionArgs: g("actionArgs"),
|
|
22665
22743
|
notes: g("notes"),
|
|
22744
|
+
// Task 2214 — read-only on the wire. Deliberately absent from the PATCH
|
|
22745
|
+
// field set below: the roster is its only writer, so a PATCH that accepted
|
|
22746
|
+
// it would be discarded by the next seed, and silently accepting an edit
|
|
22747
|
+
// that the next upgrade throws away is worse than refusing it.
|
|
22748
|
+
routineDescription: g("routineDescription"),
|
|
22666
22749
|
lastDispatchResult: g("lastDispatchResult"),
|
|
22667
22750
|
lastDispatchAt: g("lastDispatchAt"),
|
|
22668
22751
|
// Task 2106 — on the wire so the page can gate Resume all on the set the
|
|
22669
22752
|
// server will actually act on. Without it the control reads `suspended`,
|
|
22670
|
-
// which includes the
|
|
22753
|
+
// which includes the thirteen seeded roster rows on every fresh install, and
|
|
22671
22754
|
// pressing it reports restoring nothing.
|
|
22672
22755
|
suspendedInBulk: r.get("suspendedInBulk") === true
|
|
22673
22756
|
};
|
|
@@ -23294,8 +23377,8 @@ app51.delete("/:eventId", requireAdminSession, async (c) => {
|
|
|
23294
23377
|
var routines_default = app51;
|
|
23295
23378
|
|
|
23296
23379
|
// server/routes/admin/skills.ts
|
|
23297
|
-
import { existsSync as
|
|
23298
|
-
import { resolve as
|
|
23380
|
+
import { existsSync as existsSync40, readdirSync as readdirSync25, readFileSync as readFileSync38, rmSync as rmSync5 } from "fs";
|
|
23381
|
+
import { resolve as resolve32 } from "path";
|
|
23299
23382
|
var app52 = new Hono();
|
|
23300
23383
|
var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
23301
23384
|
function splitSkillMd(text) {
|
|
@@ -23318,9 +23401,9 @@ function stripQuotes(s) {
|
|
|
23318
23401
|
return s;
|
|
23319
23402
|
}
|
|
23320
23403
|
function subdirs2(dir) {
|
|
23321
|
-
if (!
|
|
23404
|
+
if (!existsSync40(dir)) return [];
|
|
23322
23405
|
try {
|
|
23323
|
-
return
|
|
23406
|
+
return readdirSync25(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
23324
23407
|
} catch {
|
|
23325
23408
|
return [];
|
|
23326
23409
|
}
|
|
@@ -23333,19 +23416,19 @@ app52.get("/", requireAdminSession, async (c) => {
|
|
|
23333
23416
|
}
|
|
23334
23417
|
ensureAccountWatchers(acct.accountId, acct.accountDir);
|
|
23335
23418
|
const { value, state } = await getOrCompute("skills", acct.accountId, async () => {
|
|
23336
|
-
const pluginsDir =
|
|
23419
|
+
const pluginsDir = resolve32(acct.accountDir, "plugins");
|
|
23337
23420
|
const skills = [];
|
|
23338
23421
|
let pluginCount = 0;
|
|
23339
23422
|
for (const plugin of subdirs2(pluginsDir)) {
|
|
23340
23423
|
pluginCount++;
|
|
23341
|
-
const skillsDir =
|
|
23424
|
+
const skillsDir = resolve32(pluginsDir, plugin, "skills");
|
|
23342
23425
|
for (const skill of subdirs2(skillsDir)) {
|
|
23343
|
-
const skillMd =
|
|
23344
|
-
if (!
|
|
23426
|
+
const skillMd = resolve32(skillsDir, skill, "SKILL.md");
|
|
23427
|
+
if (!existsSync40(skillMd)) continue;
|
|
23345
23428
|
try {
|
|
23346
|
-
const { frontmatter } = splitSkillMd(
|
|
23347
|
-
const refsDir =
|
|
23348
|
-
const refCount =
|
|
23429
|
+
const { frontmatter } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
|
|
23430
|
+
const refsDir = resolve32(skillsDir, skill, "references");
|
|
23431
|
+
const refCount = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
|
|
23349
23432
|
skills.push({ plugin, skill, description: frontmatter.description, refCount });
|
|
23350
23433
|
} catch (err) {
|
|
23351
23434
|
console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -23367,15 +23450,15 @@ app52.get("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23367
23450
|
console.error(`[admin:skills] op=get outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
23368
23451
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
23369
23452
|
}
|
|
23370
|
-
const skillDir =
|
|
23371
|
-
const skillMd =
|
|
23372
|
-
const found =
|
|
23453
|
+
const skillDir = resolve32(acct.accountDir, "plugins", plugin, "skills", skill);
|
|
23454
|
+
const skillMd = resolve32(skillDir, "SKILL.md");
|
|
23455
|
+
const found = existsSync40(skillMd);
|
|
23373
23456
|
console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
|
|
23374
23457
|
if (!found) return c.json({ error: "Skill not found" }, 404);
|
|
23375
23458
|
try {
|
|
23376
|
-
const { frontmatter, body } = splitSkillMd(
|
|
23377
|
-
const refsDir =
|
|
23378
|
-
const references =
|
|
23459
|
+
const { frontmatter, body } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
|
|
23460
|
+
const refsDir = resolve32(skillDir, "references");
|
|
23461
|
+
const references = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
|
|
23379
23462
|
return c.json({ skill: { plugin, skill, frontmatter, body, references } });
|
|
23380
23463
|
} catch (err) {
|
|
23381
23464
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -23392,10 +23475,10 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23392
23475
|
console.error(`[admin:skills] op=delete outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
|
|
23393
23476
|
return c.json({ error: "Invalid plugin or skill name" }, 400);
|
|
23394
23477
|
}
|
|
23395
|
-
const pluginDir =
|
|
23396
|
-
const skillsDir =
|
|
23397
|
-
const skillDir =
|
|
23398
|
-
if (!
|
|
23478
|
+
const pluginDir = resolve32(acct.accountDir, "plugins", plugin);
|
|
23479
|
+
const skillsDir = resolve32(pluginDir, "skills");
|
|
23480
|
+
const skillDir = resolve32(skillsDir, skill);
|
|
23481
|
+
if (!existsSync40(resolve32(skillDir, "SKILL.md"))) {
|
|
23399
23482
|
console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
|
|
23400
23483
|
return c.json({ error: "Skill not found" }, 404);
|
|
23401
23484
|
}
|
|
@@ -23403,7 +23486,7 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
23403
23486
|
rmSync5(skillDir, { recursive: true, force: true });
|
|
23404
23487
|
const pluginDirRemoved = subdirs2(skillsDir).length === 0;
|
|
23405
23488
|
if (pluginDirRemoved) rmSync5(pluginDir, { recursive: true, force: true });
|
|
23406
|
-
const skillDirGone = !
|
|
23489
|
+
const skillDirGone = !existsSync40(skillDir);
|
|
23407
23490
|
if (!skillDirGone) {
|
|
23408
23491
|
console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
|
|
23409
23492
|
return c.json({ error: "Delete did not remove the skill directory" }, 503);
|
|
@@ -23875,20 +23958,20 @@ app57.post("/", requireAdminSession, async (c) => {
|
|
|
23875
23958
|
var task_time_adjust_default = app57;
|
|
23876
23959
|
|
|
23877
23960
|
// app/lib/admin-roster.ts
|
|
23878
|
-
import { existsSync as
|
|
23879
|
-
import { resolve as
|
|
23961
|
+
import { existsSync as existsSync41, readdirSync as readdirSync26, readFileSync as readFileSync39 } from "fs";
|
|
23962
|
+
import { resolve as resolve33 } from "path";
|
|
23880
23963
|
function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
23881
23964
|
let entries2;
|
|
23882
23965
|
try {
|
|
23883
|
-
entries2 =
|
|
23966
|
+
entries2 = readdirSync26(accountsDir);
|
|
23884
23967
|
} catch {
|
|
23885
23968
|
return [];
|
|
23886
23969
|
}
|
|
23887
23970
|
for (const entry of entries2) {
|
|
23888
|
-
const cfgPath =
|
|
23889
|
-
if (!
|
|
23971
|
+
const cfgPath = resolve33(accountsDir, entry, "account.json");
|
|
23972
|
+
if (!existsSync41(cfgPath)) continue;
|
|
23890
23973
|
try {
|
|
23891
|
-
const cfg = JSON.parse(
|
|
23974
|
+
const cfg = JSON.parse(readFileSync39(cfgPath, "utf-8"));
|
|
23892
23975
|
if (cfg.role !== "house") continue;
|
|
23893
23976
|
if (!Array.isArray(cfg.admins)) return [];
|
|
23894
23977
|
return cfg.admins.map(
|
|
@@ -24218,7 +24301,21 @@ app61.get("/", requireAdminSession, async (c) => {
|
|
|
24218
24301
|
var admin_users_list_default = app61;
|
|
24219
24302
|
|
|
24220
24303
|
// server/routes/admin/dispatch-destinations.ts
|
|
24304
|
+
import { resolve as resolve34 } from "path";
|
|
24221
24305
|
var TAG37 = "[admin:routines]";
|
|
24306
|
+
function scopeFor(d, houseDir, houseAccountId) {
|
|
24307
|
+
if (d.channel !== "whatsapp") return null;
|
|
24308
|
+
if (d.label === "Account manager") return boundSubAccountFor(houseDir, d.destination);
|
|
24309
|
+
return houseAccountId;
|
|
24310
|
+
}
|
|
24311
|
+
function telephoneVariants(destination) {
|
|
24312
|
+
const digits = normalizeE1642(destination);
|
|
24313
|
+
if (digits.length === 0) return [destination];
|
|
24314
|
+
return [.../* @__PURE__ */ new Set([destination, digits, `+${digits}`])];
|
|
24315
|
+
}
|
|
24316
|
+
function scrubDigitRuns(message) {
|
|
24317
|
+
return message.replace(/\d{7,}/g, "<redacted>");
|
|
24318
|
+
}
|
|
24222
24319
|
var app62 = new Hono();
|
|
24223
24320
|
app62.get("/", requireAdminSession, async (c) => {
|
|
24224
24321
|
const accountId = getAccountIdForSession(c.var.cacheKey);
|
|
@@ -24234,15 +24331,62 @@ app62.get("/", requireAdminSession, async (c) => {
|
|
|
24234
24331
|
console.error(`${TAG37} op=destinations account=${accountId.slice(0, 8)} outcome=house-unresolved reason="${message}"`);
|
|
24235
24332
|
}
|
|
24236
24333
|
const destinations = listDispatchDestinations({ accountsDir: ACCOUNTS_DIR, houseAccountId, accountId });
|
|
24334
|
+
const houseDir = houseAccountId === null ? null : resolve34(ACCOUNTS_DIR, houseAccountId);
|
|
24335
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
24336
|
+
for (const d of destinations) {
|
|
24337
|
+
const scope = houseDir === null || houseAccountId === null ? null : scopeFor(d, houseDir, houseAccountId);
|
|
24338
|
+
if (scope === null) continue;
|
|
24339
|
+
const list = byScope.get(scope);
|
|
24340
|
+
if (list) list.push(d);
|
|
24341
|
+
else byScope.set(scope, [d]);
|
|
24342
|
+
}
|
|
24343
|
+
let namesUnresolved = null;
|
|
24344
|
+
let named = 0;
|
|
24345
|
+
if (byScope.size > 0) {
|
|
24346
|
+
let session = null;
|
|
24347
|
+
try {
|
|
24348
|
+
session = getSession();
|
|
24349
|
+
for (const [scopeAccountId, rows] of byScope) {
|
|
24350
|
+
const telephones = [...new Set(rows.flatMap((d) => telephoneVariants(d.destination)))];
|
|
24351
|
+
const result = await session.run(
|
|
24352
|
+
`MATCH (p:Person {accountId: $accountId}) WHERE p.telephone IN $telephones
|
|
24353
|
+
RETURN p.telephone AS telephone, p.givenName AS givenName, p.familyName AS familyName`,
|
|
24354
|
+
{ accountId: scopeAccountId, telephones }
|
|
24355
|
+
);
|
|
24356
|
+
const found = /* @__PURE__ */ new Map();
|
|
24357
|
+
for (const rec of result.records) {
|
|
24358
|
+
const tel = rec.get("telephone");
|
|
24359
|
+
if (!tel) continue;
|
|
24360
|
+
const name = [rec.get("givenName"), rec.get("familyName")].filter(Boolean).join(" ");
|
|
24361
|
+
if (name.length > 0) found.set(normalizeE1642(tel), name);
|
|
24362
|
+
}
|
|
24363
|
+
for (const d of rows) {
|
|
24364
|
+
const hit = found.get(normalizeE1642(d.destination));
|
|
24365
|
+
if (hit) {
|
|
24366
|
+
d.name = hit;
|
|
24367
|
+
named += 1;
|
|
24368
|
+
}
|
|
24369
|
+
}
|
|
24370
|
+
}
|
|
24371
|
+
} catch (err) {
|
|
24372
|
+
namesUnresolved = scrubDigitRuns(err instanceof Error ? err.message : String(err));
|
|
24373
|
+
for (const d of destinations) delete d.name;
|
|
24374
|
+
named = 0;
|
|
24375
|
+
} finally {
|
|
24376
|
+
if (session) await session.close();
|
|
24377
|
+
}
|
|
24378
|
+
}
|
|
24379
|
+
const scopes = [...byScope.keys()];
|
|
24380
|
+
const nameScope = scopes.length === 0 ? "none" : scopes.every((s) => s === houseAccountId) ? "house" : scopes.some((s) => s === houseAccountId) ? "mixed" : "account";
|
|
24237
24381
|
console.log(
|
|
24238
|
-
`${TAG37} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length}` + (houseAccountId === null ? " outcome=house-unresolved" : "")
|
|
24382
|
+
`${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
24383
|
);
|
|
24240
24384
|
return c.json({ destinations });
|
|
24241
24385
|
});
|
|
24242
24386
|
var dispatch_destinations_default = app62;
|
|
24243
24387
|
|
|
24244
24388
|
// server/routes/admin/activity.ts
|
|
24245
|
-
import { readdirSync as
|
|
24389
|
+
import { readdirSync as readdirSync27 } from "fs";
|
|
24246
24390
|
var app63 = new Hono();
|
|
24247
24391
|
var TAG38 = "[activity]";
|
|
24248
24392
|
function resolveHouseAccountId(accounts) {
|
|
@@ -24258,7 +24402,7 @@ function requestToken() {
|
|
|
24258
24402
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
24259
24403
|
function countAccountDirsOnDisk() {
|
|
24260
24404
|
try {
|
|
24261
|
-
return
|
|
24405
|
+
return readdirSync27(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
24262
24406
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
24263
24407
|
).length;
|
|
24264
24408
|
} catch {
|
|
@@ -24522,9 +24666,9 @@ var verify_token_default = app65;
|
|
|
24522
24666
|
|
|
24523
24667
|
// app/lib/access-email.ts
|
|
24524
24668
|
import { spawn as spawn2 } from "child_process";
|
|
24525
|
-
import { resolve as
|
|
24526
|
-
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ??
|
|
24527
|
-
var SEND_SCRIPT =
|
|
24669
|
+
import { resolve as resolve35 } from "path";
|
|
24670
|
+
var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve35(process.cwd(), "..");
|
|
24671
|
+
var SEND_SCRIPT = resolve35(
|
|
24528
24672
|
PLATFORM_ROOT5,
|
|
24529
24673
|
"plugins",
|
|
24530
24674
|
"email",
|
|
@@ -24666,8 +24810,8 @@ app67.route("/request-magic-link", request_magic_link_default);
|
|
|
24666
24810
|
var access_default = app67;
|
|
24667
24811
|
|
|
24668
24812
|
// server/routes/sites.ts
|
|
24669
|
-
import { existsSync as
|
|
24670
|
-
import { resolve as
|
|
24813
|
+
import { existsSync as existsSync42, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync22 } from "fs";
|
|
24814
|
+
import { resolve as resolve36 } from "path";
|
|
24671
24815
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
24672
24816
|
var MIME = {
|
|
24673
24817
|
".html": "text/html; charset=utf-8",
|
|
@@ -24724,15 +24868,15 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24724
24868
|
}
|
|
24725
24869
|
segments.push(seg);
|
|
24726
24870
|
}
|
|
24727
|
-
const rootDir =
|
|
24728
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
24871
|
+
const rootDir = resolve36(account.accountDir, "sites");
|
|
24872
|
+
let filePath = segments.length === 0 ? rootDir : resolve36(rootDir, ...segments);
|
|
24729
24873
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
24730
24874
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24731
24875
|
return c.text("Forbidden", 403);
|
|
24732
24876
|
}
|
|
24733
24877
|
let stat11;
|
|
24734
24878
|
try {
|
|
24735
|
-
stat11 =
|
|
24879
|
+
stat11 = existsSync42(filePath) ? statSync22(filePath) : null;
|
|
24736
24880
|
} catch {
|
|
24737
24881
|
stat11 = null;
|
|
24738
24882
|
}
|
|
@@ -24745,13 +24889,13 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24745
24889
|
return c.redirect(target, 301);
|
|
24746
24890
|
}
|
|
24747
24891
|
if (stat11?.isDirectory()) {
|
|
24748
|
-
filePath =
|
|
24892
|
+
filePath = resolve36(filePath, "index.html");
|
|
24749
24893
|
}
|
|
24750
24894
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
24751
24895
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24752
24896
|
return c.text("Forbidden", 403);
|
|
24753
24897
|
}
|
|
24754
|
-
if (!
|
|
24898
|
+
if (!existsSync42(filePath)) {
|
|
24755
24899
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
24756
24900
|
return c.text("Not found", 404);
|
|
24757
24901
|
}
|
|
@@ -24770,7 +24914,7 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24770
24914
|
}
|
|
24771
24915
|
let body;
|
|
24772
24916
|
try {
|
|
24773
|
-
body =
|
|
24917
|
+
body = readFileSync40(realPath);
|
|
24774
24918
|
} catch (err) {
|
|
24775
24919
|
const code = err?.code;
|
|
24776
24920
|
if (code === "EISDIR") {
|
|
@@ -24805,8 +24949,8 @@ app68.get("/:rel{.*}", (c) => {
|
|
|
24805
24949
|
var sites_default = app68;
|
|
24806
24950
|
|
|
24807
24951
|
// app/lib/visitor-token.ts
|
|
24808
|
-
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
24809
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
24952
|
+
import { createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
24953
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync15 } from "fs";
|
|
24810
24954
|
import { dirname as dirname15 } from "path";
|
|
24811
24955
|
var TOKEN_PREFIX = "v1.";
|
|
24812
24956
|
var SECRET_BYTES = 32;
|
|
@@ -24815,21 +24959,21 @@ var cachedSecret = null;
|
|
|
24815
24959
|
function getSecret() {
|
|
24816
24960
|
if (cachedSecret) return cachedSecret;
|
|
24817
24961
|
try {
|
|
24818
|
-
const hex2 =
|
|
24962
|
+
const hex2 = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
24819
24963
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
24820
24964
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
24821
24965
|
return cachedSecret;
|
|
24822
24966
|
}
|
|
24823
24967
|
} catch {
|
|
24824
24968
|
}
|
|
24825
|
-
const fresh =
|
|
24969
|
+
const fresh = randomBytes2(SECRET_BYTES).toString("hex");
|
|
24826
24970
|
try {
|
|
24827
24971
|
mkdirSync8(dirname15(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
|
|
24828
|
-
|
|
24972
|
+
writeFileSync15(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
|
|
24829
24973
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
24830
24974
|
} catch {
|
|
24831
24975
|
}
|
|
24832
|
-
const hex =
|
|
24976
|
+
const hex = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
24833
24977
|
cachedSecret = Buffer.from(hex, "hex");
|
|
24834
24978
|
return cachedSecret;
|
|
24835
24979
|
}
|
|
@@ -24862,7 +25006,7 @@ function verifyVisitorToken(token, now = Date.now()) {
|
|
|
24862
25006
|
const expected = signPayload(payloadJson, getSecret());
|
|
24863
25007
|
const expectedBuf = Buffer.from(expected, "utf-8");
|
|
24864
25008
|
const provBuf = Buffer.from(sigB64, "utf-8");
|
|
24865
|
-
if (expectedBuf.length !== provBuf.length || !
|
|
25009
|
+
if (expectedBuf.length !== provBuf.length || !timingSafeEqual2(expectedBuf, provBuf)) {
|
|
24866
25010
|
return { ok: false, reason: "bad-sig" };
|
|
24867
25011
|
}
|
|
24868
25012
|
let payload;
|
|
@@ -24882,7 +25026,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
24882
25026
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
24883
25027
|
|
|
24884
25028
|
// app/lib/brand-config.ts
|
|
24885
|
-
import { existsSync as
|
|
25029
|
+
import { existsSync as existsSync43, readFileSync as readFileSync42 } from "fs";
|
|
24886
25030
|
import { join as join47 } from "path";
|
|
24887
25031
|
var cached2 = null;
|
|
24888
25032
|
var cachedAttempted = false;
|
|
@@ -24892,9 +25036,9 @@ function readBrandConfig() {
|
|
|
24892
25036
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
24893
25037
|
if (!platformRoot5) return null;
|
|
24894
25038
|
const brandPath = join47(platformRoot5, "config", "brand.json");
|
|
24895
|
-
if (!
|
|
25039
|
+
if (!existsSync43(brandPath)) return null;
|
|
24896
25040
|
try {
|
|
24897
|
-
cached2 = JSON.parse(
|
|
25041
|
+
cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
|
|
24898
25042
|
return cached2;
|
|
24899
25043
|
} catch {
|
|
24900
25044
|
return null;
|
|
@@ -25391,14 +25535,14 @@ async function writeEvent(opts) {
|
|
|
25391
25535
|
var visitor_event_default = app71;
|
|
25392
25536
|
|
|
25393
25537
|
// server/routes/session.ts
|
|
25394
|
-
import { resolve as
|
|
25395
|
-
import { existsSync as
|
|
25396
|
-
var
|
|
25538
|
+
import { resolve as resolve37 } from "path";
|
|
25539
|
+
import { existsSync as existsSync44, writeFileSync as writeFileSync16, mkdirSync as mkdirSync9 } from "fs";
|
|
25540
|
+
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
25541
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
25398
25542
|
try {
|
|
25399
|
-
const cacheDir =
|
|
25543
|
+
const cacheDir = resolve37(MAXY_DIR, "branding-cache", accountId);
|
|
25400
25544
|
mkdirSync9(cacheDir, { recursive: true });
|
|
25401
|
-
|
|
25545
|
+
writeFileSync16(resolve37(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
25402
25546
|
} catch (err) {
|
|
25403
25547
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25404
25548
|
}
|
|
@@ -25408,7 +25552,7 @@ function parseVisitorCookie2(cookieHeader) {
|
|
|
25408
25552
|
const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
|
|
25409
25553
|
if (!match) return null;
|
|
25410
25554
|
const value = decodeURIComponent(match[1]).trim();
|
|
25411
|
-
return
|
|
25555
|
+
return UUID_RE5.test(value) ? value : null;
|
|
25412
25556
|
}
|
|
25413
25557
|
function parseAccessSessionId2(cookieHeader) {
|
|
25414
25558
|
if (!cookieHeader) return null;
|
|
@@ -25475,8 +25619,8 @@ app72.post("/", async (c) => {
|
|
|
25475
25619
|
}
|
|
25476
25620
|
let agentConfig = null;
|
|
25477
25621
|
if (account) {
|
|
25478
|
-
const agentDir =
|
|
25479
|
-
if (!
|
|
25622
|
+
const agentDir = resolve37(account.accountDir, "agents", agentSlug);
|
|
25623
|
+
if (!existsSync44(agentDir) || !existsSync44(resolve37(agentDir, "config.json"))) {
|
|
25480
25624
|
return c.json({ error: "Agent not found" }, 404);
|
|
25481
25625
|
}
|
|
25482
25626
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -25506,7 +25650,7 @@ app72.post("/", async (c) => {
|
|
|
25506
25650
|
);
|
|
25507
25651
|
}
|
|
25508
25652
|
}
|
|
25509
|
-
if (body.session_key && typeof body.session_key === "string" &&
|
|
25653
|
+
if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
|
|
25510
25654
|
if (visitorId) {
|
|
25511
25655
|
const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
|
|
25512
25656
|
if (recent) {
|
|
@@ -25736,7 +25880,7 @@ var calendar_public_default = app73;
|
|
|
25736
25880
|
// server/routes/portal-fetch.ts
|
|
25737
25881
|
import { createReadStream as createReadStream3 } from "fs";
|
|
25738
25882
|
import { stat as stat8, readFile as readFile11, realpath } from "fs/promises";
|
|
25739
|
-
import { join as join48, resolve as
|
|
25883
|
+
import { join as join48, resolve as resolve38, sep as sep11 } from "path";
|
|
25740
25884
|
import { Readable as Readable3 } from "stream";
|
|
25741
25885
|
var app74 = new Hono();
|
|
25742
25886
|
var TAG41 = "[portal-fetch]";
|
|
@@ -25789,7 +25933,7 @@ ${expiresAtMs}`)
|
|
|
25789
25933
|
return diff === 0;
|
|
25790
25934
|
}
|
|
25791
25935
|
async function readAccountSecret(accountId) {
|
|
25792
|
-
const path =
|
|
25936
|
+
const path = resolve38(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
|
|
25793
25937
|
let text;
|
|
25794
25938
|
try {
|
|
25795
25939
|
text = await readFile11(path, "utf8");
|
|
@@ -25825,7 +25969,7 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
|
25825
25969
|
const exposeFolders = await readExposeFolders2(accountDir);
|
|
25826
25970
|
const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
|
|
25827
25971
|
if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
|
|
25828
|
-
const lexical =
|
|
25972
|
+
const lexical = resolve38(accountDir, relPath);
|
|
25829
25973
|
let root;
|
|
25830
25974
|
let absolute;
|
|
25831
25975
|
try {
|
|
@@ -25874,7 +26018,7 @@ async function handle(c, headOnly) {
|
|
|
25874
26018
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
25875
26019
|
}
|
|
25876
26020
|
const target = await resolveFetchTarget(
|
|
25877
|
-
|
|
26021
|
+
resolve38(DATA_ROOT, "accounts", accountId),
|
|
25878
26022
|
relPath,
|
|
25879
26023
|
owner || void 0
|
|
25880
26024
|
);
|
|
@@ -25988,7 +26132,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
25988
26132
|
}
|
|
25989
26133
|
|
|
25990
26134
|
// app/lib/ledger-census.ts
|
|
25991
|
-
import { readdirSync as
|
|
26135
|
+
import { readdirSync as readdirSync28, readFileSync as readFileSync43, statSync as statSync23 } from "fs";
|
|
25992
26136
|
import { join as join49 } from "path";
|
|
25993
26137
|
|
|
25994
26138
|
// ../lib/ledger-core/dist/reconcile.js
|
|
@@ -26037,7 +26181,7 @@ var DAY_MS = 864e5;
|
|
|
26037
26181
|
function countWriteRejects24h(logDir, now) {
|
|
26038
26182
|
let entries2;
|
|
26039
26183
|
try {
|
|
26040
|
-
entries2 =
|
|
26184
|
+
entries2 = readdirSync28(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
26041
26185
|
} catch {
|
|
26042
26186
|
return 0;
|
|
26043
26187
|
}
|
|
@@ -26046,7 +26190,7 @@ function countWriteRejects24h(logDir, now) {
|
|
|
26046
26190
|
const path = join49(logDir, name);
|
|
26047
26191
|
try {
|
|
26048
26192
|
if (now - statSync23(path).mtimeMs > DAY_MS) continue;
|
|
26049
|
-
for (const line of
|
|
26193
|
+
for (const line of readFileSync43(path, "utf8").split("\n")) {
|
|
26050
26194
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
26051
26195
|
}
|
|
26052
26196
|
} catch {
|
|
@@ -26315,7 +26459,7 @@ function startGraphHealthTimer() {
|
|
|
26315
26459
|
|
|
26316
26460
|
// app/lib/file-watcher.ts
|
|
26317
26461
|
import * as fsp2 from "fs/promises";
|
|
26318
|
-
import { resolve as
|
|
26462
|
+
import { resolve as resolve39, sep as sep12 } from "path";
|
|
26319
26463
|
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
26464
|
var DEFAULT_COALESCE_MS = 500;
|
|
26321
26465
|
var ROOTS = ["accounts"];
|
|
@@ -26334,7 +26478,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26334
26478
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
26335
26479
|
for (const r of ROOTS) {
|
|
26336
26480
|
try {
|
|
26337
|
-
await fsp2.mkdir(
|
|
26481
|
+
await fsp2.mkdir(resolve39(dataRoot, r), { recursive: true });
|
|
26338
26482
|
} catch (err) {
|
|
26339
26483
|
console.error(
|
|
26340
26484
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -26355,7 +26499,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26355
26499
|
timers.set(relativePath, t);
|
|
26356
26500
|
}
|
|
26357
26501
|
async function runHook(relativePath, accountId) {
|
|
26358
|
-
const absolute =
|
|
26502
|
+
const absolute = resolve39(dataRoot, relativePath);
|
|
26359
26503
|
let exists = false;
|
|
26360
26504
|
try {
|
|
26361
26505
|
const st = await fsp2.stat(absolute);
|
|
@@ -26379,7 +26523,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26379
26523
|
}
|
|
26380
26524
|
}
|
|
26381
26525
|
async function watchRoot(rootName) {
|
|
26382
|
-
const absRoot =
|
|
26526
|
+
const absRoot = resolve39(dataRoot, rootName);
|
|
26383
26527
|
try {
|
|
26384
26528
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
26385
26529
|
for await (const event of iter) {
|
|
@@ -26418,7 +26562,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26418
26562
|
|
|
26419
26563
|
// app/lib/migrate-uploads.ts
|
|
26420
26564
|
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
|
|
26565
|
+
import { dirname as dirname16, relative as relative8, resolve as resolve40 } from "path";
|
|
26422
26566
|
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
26567
|
async function walkFiles(dir) {
|
|
26424
26568
|
const out = [];
|
|
@@ -26429,7 +26573,7 @@ async function walkFiles(dir) {
|
|
|
26429
26573
|
return out;
|
|
26430
26574
|
}
|
|
26431
26575
|
for (const e of entries2) {
|
|
26432
|
-
const abs =
|
|
26576
|
+
const abs = resolve40(dir, e.name);
|
|
26433
26577
|
if (e.isDirectory()) {
|
|
26434
26578
|
out.push(...await walkFiles(abs));
|
|
26435
26579
|
} else if (e.isFile()) {
|
|
@@ -26449,7 +26593,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26449
26593
|
let moved = 0;
|
|
26450
26594
|
for (const oldAbs of files) {
|
|
26451
26595
|
const suffix = relative8(srcDir, oldAbs);
|
|
26452
|
-
const newAbs =
|
|
26596
|
+
const newAbs = resolve40(destDir, suffix);
|
|
26453
26597
|
await mkdir4(dirname16(newAbs), { recursive: true });
|
|
26454
26598
|
await rename4(oldAbs, newAbs);
|
|
26455
26599
|
moved++;
|
|
@@ -26476,7 +26620,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26476
26620
|
}
|
|
26477
26621
|
async function migrateUploads(opts = {}) {
|
|
26478
26622
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
26479
|
-
const oldRoot =
|
|
26623
|
+
const oldRoot = resolve40(dataRoot, "uploads");
|
|
26480
26624
|
let topEntries;
|
|
26481
26625
|
try {
|
|
26482
26626
|
topEntries = await readdir6(oldRoot, { withFileTypes: true });
|
|
@@ -26497,8 +26641,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26497
26641
|
const name = entry.name;
|
|
26498
26642
|
if (ACCOUNT_UUID_RE4.test(name)) {
|
|
26499
26643
|
moved += await relocateTree(
|
|
26500
|
-
|
|
26501
|
-
|
|
26644
|
+
resolve40(oldRoot, name),
|
|
26645
|
+
resolve40(dataRoot, "accounts", name, "uploads"),
|
|
26502
26646
|
dataRoot,
|
|
26503
26647
|
name,
|
|
26504
26648
|
session
|
|
@@ -26510,8 +26654,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26510
26654
|
continue;
|
|
26511
26655
|
}
|
|
26512
26656
|
moved += await relocateTree(
|
|
26513
|
-
|
|
26514
|
-
|
|
26657
|
+
resolve40(oldRoot, "public"),
|
|
26658
|
+
resolve40(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
26515
26659
|
dataRoot,
|
|
26516
26660
|
null,
|
|
26517
26661
|
// public uploads carry no graph nodes
|
|
@@ -26541,7 +26685,7 @@ async function migrateUploads(opts = {}) {
|
|
|
26541
26685
|
|
|
26542
26686
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
26543
26687
|
import { readdir as readdir7, readFile as readFile12, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
|
|
26544
|
-
import { existsSync as
|
|
26688
|
+
import { existsSync as existsSync45 } from "fs";
|
|
26545
26689
|
import { join as join50 } from "path";
|
|
26546
26690
|
var ADMIN_ROLE2 = "admin";
|
|
26547
26691
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
@@ -26571,7 +26715,7 @@ async function writeRaw(path, obj) {
|
|
|
26571
26715
|
await rename5(tmp, path);
|
|
26572
26716
|
} catch (err) {
|
|
26573
26717
|
try {
|
|
26574
|
-
if (
|
|
26718
|
+
if (existsSync45(tmp)) await unlink4(tmp);
|
|
26575
26719
|
} catch {
|
|
26576
26720
|
}
|
|
26577
26721
|
throw err;
|
|
@@ -26694,7 +26838,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
|
|
|
26694
26838
|
|
|
26695
26839
|
// app/lib/migrate-sidecar-account-ids.ts
|
|
26696
26840
|
import { readdir as readdir8, readFile as readFile13, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
|
|
26697
|
-
import { existsSync as
|
|
26841
|
+
import { existsSync as existsSync46 } from "fs";
|
|
26698
26842
|
import { join as join51 } from "path";
|
|
26699
26843
|
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
26844
|
function projectSlugForCwd(cwd) {
|
|
@@ -26721,7 +26865,7 @@ async function writeRaw2(path, obj) {
|
|
|
26721
26865
|
await rename6(tmp, path);
|
|
26722
26866
|
} catch (err) {
|
|
26723
26867
|
try {
|
|
26724
|
-
if (
|
|
26868
|
+
if (existsSync46(tmp)) await unlink5(tmp);
|
|
26725
26869
|
} catch {
|
|
26726
26870
|
}
|
|
26727
26871
|
throw err;
|
|
@@ -27897,16 +28041,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27897
28041
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
27898
28042
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
27899
28043
|
awaitReply(key, timeoutMs) {
|
|
27900
|
-
return new Promise((
|
|
28044
|
+
return new Promise((resolve46) => {
|
|
27901
28045
|
const timer = setTimeout(() => {
|
|
27902
28046
|
this.replyAwaiters.delete(key);
|
|
27903
|
-
|
|
28047
|
+
resolve46({ timeout: true });
|
|
27904
28048
|
}, timeoutMs);
|
|
27905
28049
|
if (timer.unref) timer.unref();
|
|
27906
28050
|
this.replyAwaiters.set(key, (r) => {
|
|
27907
28051
|
clearTimeout(timer);
|
|
27908
28052
|
this.replyAwaiters.delete(key);
|
|
27909
|
-
|
|
28053
|
+
resolve46(r);
|
|
27910
28054
|
});
|
|
27911
28055
|
});
|
|
27912
28056
|
}
|
|
@@ -27917,11 +28061,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27917
28061
|
* terminal dialog stays answerable). */
|
|
27918
28062
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
27919
28063
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
27920
|
-
return new Promise((
|
|
28064
|
+
return new Promise((resolve46) => {
|
|
27921
28065
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
27922
28066
|
const timer = setTimeout(() => {
|
|
27923
28067
|
this.pendingPrompts.delete(k);
|
|
27924
|
-
|
|
28068
|
+
resolve46({ timeout: true });
|
|
27925
28069
|
}, timeoutMs);
|
|
27926
28070
|
if (timer.unref) timer.unref();
|
|
27927
28071
|
this.pendingPrompts.set(k, {
|
|
@@ -27931,7 +28075,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27931
28075
|
clearTimeout(timer);
|
|
27932
28076
|
this.pendingPrompts.delete(k);
|
|
27933
28077
|
this.deps.onPointerChange?.(p.key);
|
|
27934
|
-
|
|
28078
|
+
resolve46(r);
|
|
27935
28079
|
}
|
|
27936
28080
|
});
|
|
27937
28081
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -28507,7 +28651,7 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
28507
28651
|
|
|
28508
28652
|
// app/lib/webchat/file-delivery.ts
|
|
28509
28653
|
import { realpathSync as realpathSync9 } from "fs";
|
|
28510
|
-
import { resolve as
|
|
28654
|
+
import { resolve as resolve41 } from "path";
|
|
28511
28655
|
|
|
28512
28656
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
28513
28657
|
var SEND_USER_FILE = "SendUserFile";
|
|
@@ -28608,7 +28752,7 @@ function makeWebchatSendFile(entry) {
|
|
|
28608
28752
|
console.error(`${TAG45} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
28609
28753
|
return { ok: false, error: "no-account" };
|
|
28610
28754
|
}
|
|
28611
|
-
const accountDir =
|
|
28755
|
+
const accountDir = resolve41(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
28612
28756
|
try {
|
|
28613
28757
|
const resolved = realpathSync9(filePath);
|
|
28614
28758
|
const accountResolved = realpathSync9(accountDir);
|
|
@@ -29172,7 +29316,7 @@ function buildTelegramSpawnRequest(input) {
|
|
|
29172
29316
|
// app/lib/telegram/outbound/send-document.ts
|
|
29173
29317
|
import { realpathSync as realpathSync10 } from "fs";
|
|
29174
29318
|
import { readFile as readFile14, stat as stat10 } from "fs/promises";
|
|
29175
|
-
import { resolve as
|
|
29319
|
+
import { resolve as resolve42, basename as basename15 } from "path";
|
|
29176
29320
|
var TAG47 = "[telegram:outbound]";
|
|
29177
29321
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
29178
29322
|
async function sendTelegramDocument(input) {
|
|
@@ -29183,7 +29327,7 @@ async function sendTelegramDocument(input) {
|
|
|
29183
29327
|
if (!maxyAccountId || !platformRoot5) {
|
|
29184
29328
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
29185
29329
|
}
|
|
29186
|
-
const accountDir =
|
|
29330
|
+
const accountDir = resolve42(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
29187
29331
|
let accountResolved;
|
|
29188
29332
|
try {
|
|
29189
29333
|
accountResolved = realpathSync10(accountDir);
|
|
@@ -29591,14 +29735,14 @@ function resolveScheduledEffectiveAccountForInstall(accountDir, destination) {
|
|
|
29591
29735
|
}
|
|
29592
29736
|
|
|
29593
29737
|
// server/lib/booking-site-accounts.ts
|
|
29594
|
-
import { existsSync as
|
|
29595
|
-
import { resolve as
|
|
29738
|
+
import { existsSync as existsSync47, readFileSync as readFileSync44 } from "fs";
|
|
29739
|
+
import { resolve as resolve43 } from "path";
|
|
29596
29740
|
function listBookingSiteAccounts(accounts) {
|
|
29597
29741
|
return accounts.filter((a) => {
|
|
29598
|
-
const availPath =
|
|
29599
|
-
if (!
|
|
29742
|
+
const availPath = resolve43(a.accountDir, "calendar-availability.json");
|
|
29743
|
+
if (!existsSync47(availPath)) return false;
|
|
29600
29744
|
try {
|
|
29601
|
-
const cfg = JSON.parse(
|
|
29745
|
+
const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
|
|
29602
29746
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
29603
29747
|
} catch {
|
|
29604
29748
|
return false;
|
|
@@ -29636,8 +29780,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
29636
29780
|
|
|
29637
29781
|
// ../lib/entitlement/src/index.ts
|
|
29638
29782
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
29639
|
-
import { existsSync as
|
|
29640
|
-
import { resolve as
|
|
29783
|
+
import { existsSync as existsSync48, readFileSync as readFileSync45, statSync as statSync24 } from "fs";
|
|
29784
|
+
import { resolve as resolve44 } from "path";
|
|
29641
29785
|
|
|
29642
29786
|
// ../lib/entitlement/src/canonicalize.ts
|
|
29643
29787
|
function canonicalize(value) {
|
|
@@ -29672,7 +29816,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
29672
29816
|
var GRACE_DAYS = 7;
|
|
29673
29817
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
29674
29818
|
function pubkeyPath(brand) {
|
|
29675
|
-
return
|
|
29819
|
+
return resolve44(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
29676
29820
|
}
|
|
29677
29821
|
var memo = null;
|
|
29678
29822
|
function memoKey(mtimeMs, account) {
|
|
@@ -29684,8 +29828,8 @@ function resolveEntitlement(brand, account) {
|
|
|
29684
29828
|
if (brand.commercialMode !== true) {
|
|
29685
29829
|
return logResolved(implicitTrust(account), null);
|
|
29686
29830
|
}
|
|
29687
|
-
const entitlementPath =
|
|
29688
|
-
if (!
|
|
29831
|
+
const entitlementPath = resolve44(brand.configDir, "entitlement.json");
|
|
29832
|
+
if (!existsSync48(entitlementPath)) {
|
|
29689
29833
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
29690
29834
|
}
|
|
29691
29835
|
const stat11 = statSync24(entitlementPath);
|
|
@@ -29700,7 +29844,7 @@ function resolveEntitlement(brand, account) {
|
|
|
29700
29844
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
29701
29845
|
let pubkeyPem;
|
|
29702
29846
|
try {
|
|
29703
|
-
pubkeyPem =
|
|
29847
|
+
pubkeyPem = readFileSync45(pubkeyPath(brand), "utf-8");
|
|
29704
29848
|
} catch (err) {
|
|
29705
29849
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
29706
29850
|
reason: "pubkey-missing"
|
|
@@ -29714,7 +29858,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
29714
29858
|
}
|
|
29715
29859
|
let envelope;
|
|
29716
29860
|
try {
|
|
29717
|
-
envelope = JSON.parse(
|
|
29861
|
+
envelope = JSON.parse(readFileSync45(entitlementPath, "utf-8"));
|
|
29718
29862
|
} catch {
|
|
29719
29863
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
29720
29864
|
}
|
|
@@ -29878,12 +30022,12 @@ installMediaDownloadGuard();
|
|
|
29878
30022
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
29879
30023
|
var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join52(PLATFORM_ROOT6, "config", "brand.json") : "";
|
|
29880
30024
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
29881
|
-
if (BRAND_JSON_PATH && !
|
|
30025
|
+
if (BRAND_JSON_PATH && !existsSync49(BRAND_JSON_PATH)) {
|
|
29882
30026
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
29883
30027
|
}
|
|
29884
|
-
if (BRAND_JSON_PATH &&
|
|
30028
|
+
if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
|
|
29885
30029
|
try {
|
|
29886
|
-
const parsed = JSON.parse(
|
|
30030
|
+
const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
29887
30031
|
BRAND = { ...BRAND, ...parsed };
|
|
29888
30032
|
} catch (err) {
|
|
29889
30033
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -29918,8 +30062,8 @@ var brandLoginOpts = {
|
|
|
29918
30062
|
var ALIAS_DOMAINS_PATH = join52(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
29919
30063
|
function loadAliasDomains() {
|
|
29920
30064
|
try {
|
|
29921
|
-
if (!
|
|
29922
|
-
const parsed = JSON.parse(
|
|
30065
|
+
if (!existsSync49(ALIAS_DOMAINS_PATH)) return null;
|
|
30066
|
+
const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
29923
30067
|
if (!Array.isArray(parsed)) {
|
|
29924
30068
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
29925
30069
|
return null;
|
|
@@ -29994,7 +30138,7 @@ var waGateway = new WaGateway({
|
|
|
29994
30138
|
fetchStandingRules: fetchAccountStandingRules,
|
|
29995
30139
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
29996
30140
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
29997
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
30141
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
29998
30142
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
29999
30143
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
30000
30144
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -30009,7 +30153,7 @@ var waGateway = new WaGateway({
|
|
|
30009
30153
|
caption,
|
|
30010
30154
|
accountId,
|
|
30011
30155
|
maxyAccountId,
|
|
30012
|
-
platformRoot:
|
|
30156
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."))
|
|
30013
30157
|
});
|
|
30014
30158
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
30015
30159
|
},
|
|
@@ -30711,20 +30855,20 @@ app75.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
30711
30855
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
30712
30856
|
return c.text("Not found", 404);
|
|
30713
30857
|
}
|
|
30714
|
-
const filePath =
|
|
30715
|
-
const expectedDir =
|
|
30858
|
+
const filePath = resolve45(account.accountDir, "agents", slug, "assets", filename);
|
|
30859
|
+
const expectedDir = resolve45(account.accountDir, "agents", slug, "assets");
|
|
30716
30860
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30717
30861
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
30718
30862
|
return c.text("Forbidden", 403);
|
|
30719
30863
|
}
|
|
30720
|
-
if (!
|
|
30864
|
+
if (!existsSync49(filePath)) {
|
|
30721
30865
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
30722
30866
|
return c.text("Not found", 404);
|
|
30723
30867
|
}
|
|
30724
30868
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30725
30869
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30726
30870
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
30727
|
-
const body =
|
|
30871
|
+
const body = readFileSync46(filePath);
|
|
30728
30872
|
return c.body(body, 200, {
|
|
30729
30873
|
"Content-Type": contentType,
|
|
30730
30874
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -30741,20 +30885,20 @@ app75.get("/generated/:filename", (c) => {
|
|
|
30741
30885
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30742
30886
|
return c.text("Not found", 404);
|
|
30743
30887
|
}
|
|
30744
|
-
const filePath =
|
|
30745
|
-
const expectedDir =
|
|
30888
|
+
const filePath = resolve45(account.accountDir, "generated", filename);
|
|
30889
|
+
const expectedDir = resolve45(account.accountDir, "generated");
|
|
30746
30890
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30747
30891
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
30748
30892
|
return c.text("Forbidden", 403);
|
|
30749
30893
|
}
|
|
30750
|
-
if (!
|
|
30894
|
+
if (!existsSync49(filePath)) {
|
|
30751
30895
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30752
30896
|
return c.text("Not found", 404);
|
|
30753
30897
|
}
|
|
30754
30898
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30755
30899
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30756
30900
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
30757
|
-
const body =
|
|
30901
|
+
const body = readFileSync46(filePath);
|
|
30758
30902
|
return c.body(body, 200, {
|
|
30759
30903
|
"Content-Type": contentType,
|
|
30760
30904
|
"Cache-Control": "public, max-age=86400"
|
|
@@ -30767,9 +30911,9 @@ app75.route("/v", visitor_consent_default);
|
|
|
30767
30911
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
30768
30912
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
30769
30913
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
30770
|
-
if (BRAND_JSON_PATH &&
|
|
30914
|
+
if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
|
|
30771
30915
|
try {
|
|
30772
|
-
const fullBrand = JSON.parse(
|
|
30916
|
+
const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
|
|
30773
30917
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
30774
30918
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
30775
30919
|
} catch {
|
|
@@ -30796,11 +30940,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
30796
30940
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
30797
30941
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
30798
30942
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
30799
|
-
(p) =>
|
|
30943
|
+
(p) => existsSync49(resolve45(process.cwd(), "public", p.replace(/^\//, "")))
|
|
30800
30944
|
);
|
|
30801
30945
|
var SW_SOURCE = (() => {
|
|
30802
30946
|
try {
|
|
30803
|
-
return
|
|
30947
|
+
return readFileSync46(resolve45(process.cwd(), "public", "sw.js"), "utf-8");
|
|
30804
30948
|
} catch {
|
|
30805
30949
|
return null;
|
|
30806
30950
|
}
|
|
@@ -30809,8 +30953,8 @@ function readInstalledVersion() {
|
|
|
30809
30953
|
try {
|
|
30810
30954
|
if (!PLATFORM_ROOT6) return "unknown";
|
|
30811
30955
|
const versionFile = join52(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
|
|
30812
|
-
if (!
|
|
30813
|
-
const content =
|
|
30956
|
+
if (!existsSync49(versionFile)) return "unknown";
|
|
30957
|
+
const content = readFileSync46(versionFile, "utf-8").trim();
|
|
30814
30958
|
return content || "unknown";
|
|
30815
30959
|
} catch {
|
|
30816
30960
|
return "unknown";
|
|
@@ -30821,7 +30965,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
|
|
|
30821
30965
|
function cachedHtml(file) {
|
|
30822
30966
|
let html = htmlCache.get(file);
|
|
30823
30967
|
if (!html) {
|
|
30824
|
-
html =
|
|
30968
|
+
html = readFileSync46(resolve45(process.cwd(), "public", file), "utf-8");
|
|
30825
30969
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
30826
30970
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
30827
30971
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -30843,8 +30987,8 @@ function loadBrandingCache(agentSlug) {
|
|
|
30843
30987
|
const accountId = getDefaultAccountId();
|
|
30844
30988
|
if (!accountId) return null;
|
|
30845
30989
|
const cachePath = join52(configDir, "branding-cache", accountId, `${agentSlug}.json`);
|
|
30846
|
-
if (!
|
|
30847
|
-
return JSON.parse(
|
|
30990
|
+
if (!existsSync49(cachePath)) return null;
|
|
30991
|
+
return JSON.parse(readFileSync46(cachePath, "utf-8"));
|
|
30848
30992
|
} catch {
|
|
30849
30993
|
return null;
|
|
30850
30994
|
}
|
|
@@ -30939,7 +31083,7 @@ app75.use("/vnc-popout.html", logViewerFetch);
|
|
|
30939
31083
|
app75.get("/vnc-popout.html", (c) => {
|
|
30940
31084
|
let html = htmlCache.get("vnc-popout.html");
|
|
30941
31085
|
if (!html) {
|
|
30942
|
-
html =
|
|
31086
|
+
html = readFileSync46(resolve45(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
30943
31087
|
const name = escapeHtml(BRAND.productName);
|
|
30944
31088
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
30945
31089
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -31092,9 +31236,9 @@ var httpServer = serve({ fetch: app75.fetch, port, hostname });
|
|
|
31092
31236
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
31093
31237
|
{
|
|
31094
31238
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31095
|
-
const reconcileScript =
|
|
31239
|
+
const reconcileScript = resolve45(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
31096
31240
|
const runReconcile = (ctx) => {
|
|
31097
|
-
if (!
|
|
31241
|
+
if (!existsSync49(reconcileScript)) return;
|
|
31098
31242
|
try {
|
|
31099
31243
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
31100
31244
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -31133,14 +31277,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31133
31277
|
{
|
|
31134
31278
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
31135
31279
|
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31136
|
-
const dreamSweepScript =
|
|
31280
|
+
const dreamSweepScript = resolve45(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
31137
31281
|
registerLoop({
|
|
31138
31282
|
name: "dream-cycle-sweep",
|
|
31139
31283
|
intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
|
|
31140
31284
|
firstRunDelayMs: 3e4,
|
|
31141
31285
|
detached: true,
|
|
31142
31286
|
run: (ctx) => {
|
|
31143
|
-
if (!
|
|
31287
|
+
if (!existsSync49(dreamSweepScript)) return;
|
|
31144
31288
|
try {
|
|
31145
31289
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
31146
31290
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -31157,10 +31301,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31157
31301
|
}
|
|
31158
31302
|
{
|
|
31159
31303
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31160
|
-
const outlookScript =
|
|
31304
|
+
const outlookScript = resolve45(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
31161
31305
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
31162
31306
|
const runOutlookComplete = (ctx) => {
|
|
31163
|
-
if (!
|
|
31307
|
+
if (!existsSync49(outlookScript)) return;
|
|
31164
31308
|
try {
|
|
31165
31309
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
31166
31310
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -31183,18 +31327,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31183
31327
|
}
|
|
31184
31328
|
{
|
|
31185
31329
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31186
|
-
const strandedAccountsDir =
|
|
31330
|
+
const strandedAccountsDir = resolve45(auditRoot, "..", "data/accounts");
|
|
31187
31331
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
31188
31332
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
31189
31333
|
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
31334
|
const runStrandedAudit = () => {
|
|
31191
31335
|
try {
|
|
31192
|
-
if (!
|
|
31336
|
+
if (!existsSync49(strandedAccountsDir)) return;
|
|
31193
31337
|
const now = Date.now();
|
|
31194
|
-
for (const name of
|
|
31338
|
+
for (const name of readdirSync29(strandedAccountsDir)) {
|
|
31195
31339
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
31196
|
-
const pendingPath2 =
|
|
31197
|
-
if (!
|
|
31340
|
+
const pendingPath2 = resolve45(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
31341
|
+
if (!existsSync49(pendingPath2)) continue;
|
|
31198
31342
|
const ageMs2 = now - statSync25(pendingPath2).mtimeMs;
|
|
31199
31343
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
31200
31344
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
@@ -31213,7 +31357,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31213
31357
|
}
|
|
31214
31358
|
{
|
|
31215
31359
|
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31216
|
-
const googleAccountsDir =
|
|
31360
|
+
const googleAccountsDir = resolve45(googleRoot, "..", "data/accounts");
|
|
31217
31361
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
31218
31362
|
const runGooglePendingAuditSafe = () => {
|
|
31219
31363
|
try {
|
|
@@ -31228,10 +31372,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31228
31372
|
firstRunDelayMs: 27e3,
|
|
31229
31373
|
run: runGooglePendingAuditSafe
|
|
31230
31374
|
});
|
|
31231
|
-
const googleAuditScript =
|
|
31375
|
+
const googleAuditScript = resolve45(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
31232
31376
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
31233
31377
|
const runGoogleAccountAudit = (ctx) => {
|
|
31234
|
-
if (!
|
|
31378
|
+
if (!existsSync49(googleAuditScript)) return;
|
|
31235
31379
|
try {
|
|
31236
31380
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
31237
31381
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -31324,7 +31468,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31324
31468
|
}
|
|
31325
31469
|
{
|
|
31326
31470
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31327
|
-
const publishScript =
|
|
31471
|
+
const publishScript = resolve45(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
31328
31472
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
31329
31473
|
const bookingAccounts = () => {
|
|
31330
31474
|
try {
|
|
@@ -31335,7 +31479,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31335
31479
|
}
|
|
31336
31480
|
};
|
|
31337
31481
|
const spawnPublish = (account, ctx) => {
|
|
31338
|
-
if (!
|
|
31482
|
+
if (!existsSync49(publishScript)) return;
|
|
31339
31483
|
try {
|
|
31340
31484
|
const child = spawn3(process.execPath, [publishScript], {
|
|
31341
31485
|
env: {
|
|
@@ -31354,21 +31498,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31354
31498
|
}
|
|
31355
31499
|
};
|
|
31356
31500
|
const auditSnapshotAge = (account) => {
|
|
31357
|
-
const availPath =
|
|
31501
|
+
const availPath = resolve45(account.accountDir, "calendar-availability.json");
|
|
31358
31502
|
let hasBookingSite = false;
|
|
31359
31503
|
try {
|
|
31360
|
-
if (
|
|
31361
|
-
const cfg = JSON.parse(
|
|
31504
|
+
if (existsSync49(availPath)) {
|
|
31505
|
+
const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
|
|
31362
31506
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
31363
31507
|
}
|
|
31364
31508
|
} catch {
|
|
31365
31509
|
}
|
|
31366
31510
|
if (!hasBookingSite) return;
|
|
31367
|
-
const statePath =
|
|
31511
|
+
const statePath = resolve45(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
31368
31512
|
let lastSuccessAt = null;
|
|
31369
|
-
if (
|
|
31513
|
+
if (existsSync49(statePath)) {
|
|
31370
31514
|
try {
|
|
31371
|
-
const rec = JSON.parse(
|
|
31515
|
+
const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
|
|
31372
31516
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
31373
31517
|
} catch {
|
|
31374
31518
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -31401,11 +31545,11 @@ startTimeEntryCensus(() => getSession());
|
|
|
31401
31545
|
startLedgerCensus(() => getSession());
|
|
31402
31546
|
{
|
|
31403
31547
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
|
|
31404
|
-
const auditScript =
|
|
31548
|
+
const auditScript = resolve45(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
31405
31549
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
31406
31550
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
31407
31551
|
const runConnectorAudit = (ctx) => {
|
|
31408
|
-
if (!
|
|
31552
|
+
if (!existsSync49(auditScript)) return;
|
|
31409
31553
|
try {
|
|
31410
31554
|
const child = spawn3(process.execPath, [auditScript], {
|
|
31411
31555
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -31525,11 +31669,11 @@ try {
|
|
|
31525
31669
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31526
31670
|
async function runAdminUserReconcileTick() {
|
|
31527
31671
|
try {
|
|
31528
|
-
if (!
|
|
31672
|
+
if (!existsSync49(USERS_FILE)) {
|
|
31529
31673
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
31530
31674
|
return;
|
|
31531
31675
|
}
|
|
31532
|
-
const usersRaw =
|
|
31676
|
+
const usersRaw = readFileSync46(USERS_FILE, "utf-8").trim();
|
|
31533
31677
|
if (!usersRaw) {
|
|
31534
31678
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
31535
31679
|
return;
|
|
@@ -31581,8 +31725,8 @@ registerLoop({
|
|
|
31581
31725
|
});
|
|
31582
31726
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31583
31727
|
function countUsersRows() {
|
|
31584
|
-
if (!
|
|
31585
|
-
const raw =
|
|
31728
|
+
if (!existsSync49(USERS_FILE)) return 0;
|
|
31729
|
+
const raw = readFileSync46(USERS_FILE, "utf-8").trim();
|
|
31586
31730
|
if (!raw) return 0;
|
|
31587
31731
|
const users = JSON.parse(raw);
|
|
31588
31732
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -31716,7 +31860,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
31716
31860
|
}
|
|
31717
31861
|
init({
|
|
31718
31862
|
configDir: configDirForWhatsApp,
|
|
31719
|
-
platformRoot:
|
|
31863
|
+
platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..")),
|
|
31720
31864
|
accountConfig: bootAccountConfig,
|
|
31721
31865
|
// Task 2074 — enrich with the sub-account name and fan out to every open
|
|
31722
31866
|
// admin SSE stream. Fire-and-forget: the manager's persist path must not
|