@rubytech/create-sitedesk-code 0.1.520 → 0.1.522
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 +17 -3
- package/package.json +1 -1
- package/payload/platform/lib/account-schema-regions/package-lock.json +12 -0
- package/payload/platform/lib/active-rules/package-lock.json +12 -0
- package/payload/platform/lib/mcp-lifeline/package-lock.json +12 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +46 -7
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +11 -1
- package/payload/platform/plugins/docs/references/internals.md +4 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +27 -4
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.js +46 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/attachment-metadata-calendar.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +14 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js +35 -4
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +9 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-resolve.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-resolve.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-resolve.test.js +151 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-resolve.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-store.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-store.test.js +151 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/delegated-store.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js +38 -4
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-prefix-wiring.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-prefix-wiring.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-prefix-wiring.test.js +146 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-prefix-wiring.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list-delegated.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list-delegated.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list-delegated.test.js +120 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list-delegated.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js +8 -8
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-path-prefix.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-path-prefix.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-path-prefix.test.js +27 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-path-prefix.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mail-only-guard.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mail-only-guard.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mail-only-guard.test.js +70 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mail-only-guard.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mailbox-add.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mailbox-add.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mailbox-add.test.js +152 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/shared-mailbox-add.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/delegated-store.d.ts +57 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/delegated-store.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/delegated-store.js +163 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/delegated-store.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts +12 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js +21 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts +35 -4
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js +92 -10
- package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/index.js +106 -3
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +49 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +126 -8
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts +13 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js +9 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts +42 -8
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js +59 -19
- package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-add.d.ts +47 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-add.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-add.js +67 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-add.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-remove.d.ts +12 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-remove.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-remove.js +18 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/shared-mailbox-remove.js.map +1 -0
- package/payload/platform/plugins/outlook/references/auth.md +15 -2
- package/payload/platform/plugins/outlook/references/graph-surfaces.md +8 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +21 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -1
- package/payload/platform/scripts/check-architecture-skill-no-drift.mjs +20 -6
- 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 +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +17 -5
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +30 -6
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +53 -21
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts +16 -0
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.js +41 -2
- package/payload/platform/services/whatsapp-channel/dist/turn-follow.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-TIIWMF5G.js → chunk-K7CJGZPU.js} +459 -196
- package/payload/server/{manager-B6OFOXSW.js → manager-RKL7JZ4Y.js} +3 -1
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-SW7mEMcP.js → AdminLoginScreens-zc2_qqh-.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js +2 -0
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js.br +0 -0
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js.gz +0 -0
- package/payload/server/public/assets/{activity-sqbyX0pX.js → activity-DVgO8YuM.js} +1 -1
- package/payload/server/public/assets/activity-DVgO8YuM.js.br +0 -0
- package/payload/server/public/assets/activity-DVgO8YuM.js.gz +0 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js +1 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js.br +0 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js.gz +0 -0
- package/payload/server/public/assets/{agents-BFYM5EDA.js → agents-P0nTIxo-.js} +1 -1
- package/payload/server/public/assets/agents-P0nTIxo-.js.br +0 -0
- package/payload/server/public/assets/agents-P0nTIxo-.js.gz +0 -0
- package/payload/server/public/assets/{browser-DP5GZe4G.js → browser-Mw7DY3ft.js} +1 -1
- package/payload/server/public/assets/browser-Mw7DY3ft.js.br +0 -0
- package/payload/server/public/assets/browser-Mw7DY3ft.js.gz +0 -0
- package/payload/server/public/assets/{calendar-BKaemLDG.js → calendar-B9gvL_1_.js} +1 -1
- package/payload/server/public/assets/calendar-B9gvL_1_.js.br +0 -0
- package/payload/server/public/assets/calendar-B9gvL_1_.js.gz +0 -0
- package/payload/server/public/assets/chat-DBGqh4wg.js +1 -0
- package/payload/server/public/assets/chat-DBGqh4wg.js.br +2 -0
- package/payload/server/public/assets/chat-DBGqh4wg.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js +1 -0
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js.br +0 -0
- package/payload/server/public/assets/chevron-right-BExigCnp.js +1 -0
- package/payload/server/public/assets/chevron-right-BExigCnp.js.br +0 -0
- package/payload/server/public/assets/clock-D8TJvgJC.js +1 -0
- package/payload/server/public/assets/clock-D8TJvgJC.js.br +0 -0
- package/payload/server/public/assets/data-HfFSxaC2.js +1 -0
- package/payload/server/public/assets/data-HfFSxaC2.js.br +0 -0
- package/payload/server/public/assets/data-HfFSxaC2.js.gz +0 -0
- package/payload/server/public/assets/{file-text-BKK7R-k_.js → file-text-dYBnXNEX.js} +1 -1
- package/payload/server/public/assets/file-text-dYBnXNEX.js.br +0 -0
- package/payload/server/public/assets/file-text-dYBnXNEX.js.gz +0 -0
- package/payload/server/public/assets/{graph-FuxYySjK.js → graph-CDyzd1Et.js} +2 -2
- package/payload/server/public/assets/graph-CDyzd1Et.js.br +0 -0
- package/payload/server/public/assets/graph-CDyzd1Et.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-Cip6fmKK.js → graph-labels-D1LkKiJr.js} +1 -1
- package/payload/server/public/assets/graph-labels-D1LkKiJr.js.br +0 -0
- package/payload/server/public/assets/graph-labels-D1LkKiJr.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-D79AhVDo.js → maximize-2-M-iSaznd.js} +1 -1
- package/payload/server/public/assets/maximize-2-M-iSaznd.js.br +0 -0
- package/payload/server/public/assets/maximize-2-M-iSaznd.js.gz +0 -0
- package/payload/server/public/assets/{operator-BPAfgFhP.js → operator-9jfCv1Fg.js} +1 -1
- package/payload/server/public/assets/operator-9jfCv1Fg.js.br +0 -0
- package/payload/server/public/assets/operator-9jfCv1Fg.js.gz +0 -0
- package/payload/server/public/assets/page-CZ-73FAk.js +32 -0
- package/payload/server/public/assets/page-CZ-73FAk.js.br +0 -0
- package/payload/server/public/assets/page-CZ-73FAk.js.gz +0 -0
- package/payload/server/public/assets/{page-BqEyS0W4.js → page-CjwSt7kx.js} +1 -1
- package/payload/server/public/assets/page-CjwSt7kx.js.br +0 -0
- package/payload/server/public/assets/page-CjwSt7kx.js.gz +0 -0
- package/payload/server/public/assets/{public-D1xs3FzD.js → public-CN-ltC8x.js} +1 -1
- package/payload/server/public/assets/public-CN-ltC8x.js.br +0 -0
- package/payload/server/public/assets/public-CN-ltC8x.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-CcU_XD8B.js → rotate-ccw-Buopsc22.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-Buopsc22.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-Buopsc22.js.gz +0 -0
- package/payload/server/public/assets/routines-C-yr8ddT.js +1 -0
- package/payload/server/public/assets/routines-C-yr8ddT.js.br +0 -0
- package/payload/server/public/assets/routines-C-yr8ddT.js.gz +0 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js +1 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js.br +0 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js.gz +0 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js +1 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js.br +0 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-IFqinQJj.js → time-entry-format-BBokCF-D.js} +1 -1
- package/payload/server/public/assets/time-entry-format-BBokCF-D.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-BBokCF-D.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-C5vH__sq.js → triangle-alert-C_AcpTW5.js} +1 -1
- package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-BeL2gPl6.js → useCopyFeedback-TdimmPVR.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js +14 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-Cpw3aOSt.js → useVoiceRecorder-BT2738ZS.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.gz +0 -0
- package/payload/server/public/assets/{wrench-BBEup3hd.js → wrench-B51s5kGA.js} +1 -1
- package/payload/server/public/assets/wrench-B51s5kGA.js.br +0 -0
- package/payload/server/public/assets/wrench-B51s5kGA.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +1238 -653
- package/payload/server/public/assets/AdminLoginScreens-SW7mEMcP.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-SW7mEMcP.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-Djg6ndne.js +0 -2
- package/payload/server/public/assets/AdminShell-Djg6ndne.js.br +0 -0
- package/payload/server/public/assets/AdminShell-Djg6ndne.js.gz +0 -0
- package/payload/server/public/assets/activity-sqbyX0pX.js.br +0 -0
- package/payload/server/public/assets/activity-sqbyX0pX.js.gz +0 -0
- package/payload/server/public/assets/admin-D9Bt47GY.js +0 -1
- package/payload/server/public/assets/admin-D9Bt47GY.js.br +0 -0
- package/payload/server/public/assets/admin-D9Bt47GY.js.gz +0 -0
- package/payload/server/public/assets/agents-BFYM5EDA.js.br +0 -0
- package/payload/server/public/assets/agents-BFYM5EDA.js.gz +0 -0
- package/payload/server/public/assets/browser-DP5GZe4G.js.br +0 -0
- package/payload/server/public/assets/browser-DP5GZe4G.js.gz +0 -0
- package/payload/server/public/assets/calendar-BKaemLDG.js.br +0 -0
- package/payload/server/public/assets/calendar-BKaemLDG.js.gz +0 -0
- package/payload/server/public/assets/chat-DPhT6urD.js +0 -1
- package/payload/server/public/assets/chat-DPhT6urD.js.br +0 -1
- package/payload/server/public/assets/chat-DPhT6urD.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-BSdXvJcH.js +0 -1
- package/payload/server/public/assets/chevron-right-DI7vI3IB.js +0 -1
- package/payload/server/public/assets/chevron-right-DI7vI3IB.js.br +0 -0
- package/payload/server/public/assets/clock-YUTPXZH5.js +0 -1
- package/payload/server/public/assets/clock-YUTPXZH5.js.br +0 -0
- package/payload/server/public/assets/clock-YUTPXZH5.js.gz +0 -0
- package/payload/server/public/assets/data-CfjttTvR.js +0 -1
- package/payload/server/public/assets/data-CfjttTvR.js.br +0 -2
- package/payload/server/public/assets/data-CfjttTvR.js.gz +0 -0
- package/payload/server/public/assets/file-text-BKK7R-k_.js.br +0 -0
- package/payload/server/public/assets/file-text-BKK7R-k_.js.gz +0 -0
- package/payload/server/public/assets/graph-FuxYySjK.js.br +0 -0
- package/payload/server/public/assets/graph-FuxYySjK.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-Cip6fmKK.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Cip6fmKK.js.gz +0 -0
- package/payload/server/public/assets/maximize-2-D79AhVDo.js.br +0 -0
- package/payload/server/public/assets/maximize-2-D79AhVDo.js.gz +0 -0
- package/payload/server/public/assets/operator-BPAfgFhP.js.br +0 -0
- package/payload/server/public/assets/operator-BPAfgFhP.js.gz +0 -0
- package/payload/server/public/assets/page--78CbdFs.js +0 -32
- package/payload/server/public/assets/page--78CbdFs.js.br +0 -0
- package/payload/server/public/assets/page--78CbdFs.js.gz +0 -0
- package/payload/server/public/assets/page-BqEyS0W4.js.br +0 -0
- package/payload/server/public/assets/page-BqEyS0W4.js.gz +0 -0
- package/payload/server/public/assets/public-D1xs3FzD.js.br +0 -0
- package/payload/server/public/assets/public-D1xs3FzD.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-CcU_XD8B.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-CcU_XD8B.js.gz +0 -0
- package/payload/server/public/assets/routines-CA7D0myr.js +0 -1
- package/payload/server/public/assets/routines-CA7D0myr.js.br +0 -0
- package/payload/server/public/assets/routines-CA7D0myr.js.gz +0 -0
- package/payload/server/public/assets/skills-CfVPPSxO.js +0 -1
- package/payload/server/public/assets/skills-CfVPPSxO.js.br +0 -0
- package/payload/server/public/assets/skills-CfVPPSxO.js.gz +0 -0
- package/payload/server/public/assets/tasks-DgieyZqz.js +0 -1
- package/payload/server/public/assets/tasks-DgieyZqz.js.br +0 -0
- package/payload/server/public/assets/tasks-DgieyZqz.js.gz +0 -0
- package/payload/server/public/assets/time-entry-format-IFqinQJj.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-IFqinQJj.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-C5vH__sq.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C5vH__sq.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-BeL2gPl6.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-BeL2gPl6.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CH9qm2Ad.js +0 -14
- package/payload/server/public/assets/useSubAccountSwitcher-CH9qm2Ad.js.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CH9qm2Ad.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DLqUQzOl.css +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-DLqUQzOl.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DLqUQzOl.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Cpw3aOSt.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-Cpw3aOSt.js.gz +0 -0
- package/payload/server/public/assets/wrench-BBEup3hd.js.br +0 -0
- package/payload/server/public/assets/wrench-BBEup3hd.js.gz +0 -0
|
@@ -332,32 +332,32 @@ function ledgerFilePath(account) {
|
|
|
332
332
|
}
|
|
333
333
|
return join(root, `${account}.jsonl`);
|
|
334
334
|
}
|
|
335
|
-
function appendStanza(
|
|
335
|
+
function appendStanza(entry2) {
|
|
336
336
|
try {
|
|
337
337
|
const row = {
|
|
338
|
-
msgId:
|
|
339
|
-
from:
|
|
340
|
-
type:
|
|
338
|
+
msgId: entry2.msgId,
|
|
339
|
+
from: entry2.from,
|
|
340
|
+
type: entry2.type,
|
|
341
341
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
342
342
|
};
|
|
343
|
-
appendFileSync(ledgerFilePath(
|
|
343
|
+
appendFileSync(ledgerFilePath(entry2.account), JSON.stringify(row) + "\n");
|
|
344
344
|
} catch (err) {
|
|
345
345
|
console.error(
|
|
346
|
-
`${TAG3} FAIL op=append msgId=${
|
|
346
|
+
`${TAG3} FAIL op=append msgId=${entry2.msgId} err=${err instanceof Error ? err.message : String(err)}`
|
|
347
347
|
);
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
-
function markDeclined(
|
|
350
|
+
function markDeclined(entry2) {
|
|
351
351
|
try {
|
|
352
352
|
const row = {
|
|
353
|
-
declined:
|
|
354
|
-
reason:
|
|
353
|
+
declined: entry2.msgId,
|
|
354
|
+
reason: entry2.reason,
|
|
355
355
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
356
356
|
};
|
|
357
|
-
appendFileSync(ledgerFilePath(
|
|
357
|
+
appendFileSync(ledgerFilePath(entry2.account), JSON.stringify(row) + "\n");
|
|
358
358
|
} catch (err) {
|
|
359
359
|
console.error(
|
|
360
|
-
`${TAG3} FAIL op=decline msgId=${
|
|
360
|
+
`${TAG3} FAIL op=decline msgId=${entry2.msgId} err=${err instanceof Error ? err.message : String(err)}`
|
|
361
361
|
);
|
|
362
362
|
}
|
|
363
363
|
}
|
|
@@ -375,36 +375,36 @@ function readDeclined(account) {
|
|
|
375
375
|
}
|
|
376
376
|
return out;
|
|
377
377
|
}
|
|
378
|
-
function appendNotifyEligible(
|
|
378
|
+
function appendNotifyEligible(entry2) {
|
|
379
379
|
try {
|
|
380
380
|
const row = {
|
|
381
|
-
notifyEligible:
|
|
382
|
-
upsertType:
|
|
383
|
-
fromMe:
|
|
384
|
-
allowed:
|
|
385
|
-
reason:
|
|
386
|
-
passive:
|
|
387
|
-
persistAccount:
|
|
381
|
+
notifyEligible: entry2.msgId,
|
|
382
|
+
upsertType: entry2.upsertType,
|
|
383
|
+
fromMe: entry2.fromMe,
|
|
384
|
+
allowed: entry2.allowed,
|
|
385
|
+
reason: entry2.reason,
|
|
386
|
+
passive: entry2.passive,
|
|
387
|
+
persistAccount: entry2.persistAccount,
|
|
388
388
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
389
389
|
};
|
|
390
|
-
appendFileSync(ledgerFilePath(
|
|
390
|
+
appendFileSync(ledgerFilePath(entry2.account), JSON.stringify(row) + "\n");
|
|
391
391
|
} catch (err) {
|
|
392
392
|
console.error(
|
|
393
|
-
`${TAG3} FAIL op=append-notify-eligible msgId=${
|
|
393
|
+
`${TAG3} FAIL op=append-notify-eligible msgId=${entry2.msgId} err=${err instanceof Error ? err.message : String(err)}`
|
|
394
394
|
);
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
|
-
function appendNotifyPublished(
|
|
397
|
+
function appendNotifyPublished(entry2) {
|
|
398
398
|
try {
|
|
399
399
|
const row = {
|
|
400
|
-
notifyPublished:
|
|
401
|
-
subscribers:
|
|
400
|
+
notifyPublished: entry2.msgId,
|
|
401
|
+
subscribers: entry2.subscribers,
|
|
402
402
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
403
403
|
};
|
|
404
|
-
appendFileSync(ledgerFilePath(
|
|
404
|
+
appendFileSync(ledgerFilePath(entry2.account), JSON.stringify(row) + "\n");
|
|
405
405
|
} catch (err) {
|
|
406
406
|
console.error(
|
|
407
|
-
`${TAG3} FAIL op=append-notify-published msgId=${
|
|
407
|
+
`${TAG3} FAIL op=append-notify-published msgId=${entry2.msgId} err=${err instanceof Error ? err.message : String(err)}`
|
|
408
408
|
);
|
|
409
409
|
}
|
|
410
410
|
}
|
|
@@ -971,12 +971,6 @@ function jidToE164(jid) {
|
|
|
971
971
|
if (lidMatch) return lidMatch[1];
|
|
972
972
|
return null;
|
|
973
973
|
}
|
|
974
|
-
function senderJidFromTelephone(senderTelephone) {
|
|
975
|
-
if (!senderTelephone) return null;
|
|
976
|
-
if (isGroupJid(senderTelephone)) return null;
|
|
977
|
-
if (isUserJid(senderTelephone)) return senderTelephone;
|
|
978
|
-
return null;
|
|
979
|
-
}
|
|
980
974
|
function isGroupJid(value) {
|
|
981
975
|
const candidate = stripWhatsAppPrefix(value);
|
|
982
976
|
const lower = candidate.toLowerCase();
|
|
@@ -1224,16 +1218,16 @@ function toMillis(v) {
|
|
|
1224
1218
|
if (typeof v.low === "number") return (v.low >>> 0) + (v.high ?? 0) * 4294967296;
|
|
1225
1219
|
return null;
|
|
1226
1220
|
}
|
|
1227
|
-
function readReactionEntry(
|
|
1228
|
-
const targetMsgKeyId =
|
|
1221
|
+
function readReactionEntry(entry2) {
|
|
1222
|
+
const targetMsgKeyId = entry2.key?.id ?? void 0;
|
|
1229
1223
|
if (!targetMsgKeyId) return null;
|
|
1230
|
-
const chatJid =
|
|
1224
|
+
const chatJid = entry2.key?.remoteJid ?? entry2.reaction?.key?.remoteJid ?? void 0;
|
|
1231
1225
|
if (!chatJid) return null;
|
|
1232
1226
|
const isGroup = isGroupJid(chatJid);
|
|
1233
|
-
const reactorKey =
|
|
1227
|
+
const reactorKey = entry2.reaction?.key;
|
|
1234
1228
|
const reactorJid = isGroup ? reactorKey?.participant ?? void 0 : reactorKey?.remoteJid ?? chatJid;
|
|
1235
1229
|
if (!reactorJid) return null;
|
|
1236
|
-
const emoji =
|
|
1230
|
+
const emoji = entry2.reaction?.text ?? "";
|
|
1237
1231
|
return {
|
|
1238
1232
|
targetMsgKeyId,
|
|
1239
1233
|
chatJid,
|
|
@@ -1242,7 +1236,7 @@ function readReactionEntry(entry) {
|
|
|
1242
1236
|
emoji,
|
|
1243
1237
|
removed: !emoji,
|
|
1244
1238
|
fromMe: !!reactorKey?.fromMe,
|
|
1245
|
-
timestampMs: toMillis(
|
|
1239
|
+
timestampMs: toMillis(entry2.reaction?.senderTimestampMs)
|
|
1246
1240
|
};
|
|
1247
1241
|
}
|
|
1248
1242
|
|
|
@@ -1387,7 +1381,7 @@ function summariseRecords(records) {
|
|
|
1387
1381
|
return {
|
|
1388
1382
|
first: sorted[0],
|
|
1389
1383
|
last: sorted[sorted.length - 1],
|
|
1390
|
-
firstNamedSender: sorted.find((r) => r.senderName)?.senderName ?? null
|
|
1384
|
+
firstNamedSender: sorted.find((r) => !r.fromMe && r.senderName)?.senderName ?? null
|
|
1391
1385
|
};
|
|
1392
1386
|
}
|
|
1393
1387
|
function readConversationSummaries(platformAccountId) {
|
|
@@ -1399,10 +1393,10 @@ function readConversationSummaries(platformAccountId) {
|
|
|
1399
1393
|
let bytesRead = 0;
|
|
1400
1394
|
try {
|
|
1401
1395
|
if (!existsSync3(dir)) return out;
|
|
1402
|
-
for (const
|
|
1403
|
-
if (!
|
|
1404
|
-
const remoteJid =
|
|
1405
|
-
const file = join2(dir,
|
|
1396
|
+
for (const entry2 of readdirSync2(dir)) {
|
|
1397
|
+
if (!entry2.endsWith(".jsonl")) continue;
|
|
1398
|
+
const remoteJid = entry2.slice(0, -".jsonl".length);
|
|
1399
|
+
const file = join2(dir, entry2);
|
|
1406
1400
|
seen.add(file);
|
|
1407
1401
|
let size;
|
|
1408
1402
|
let mtimeMs;
|
|
@@ -1451,9 +1445,9 @@ function readAllConversations(platformAccountId) {
|
|
|
1451
1445
|
const out = /* @__PURE__ */ new Map();
|
|
1452
1446
|
try {
|
|
1453
1447
|
if (!existsSync3(dir)) return out;
|
|
1454
|
-
for (const
|
|
1455
|
-
if (!
|
|
1456
|
-
const remoteJid =
|
|
1448
|
+
for (const entry2 of readdirSync2(dir)) {
|
|
1449
|
+
if (!entry2.endsWith(".jsonl")) continue;
|
|
1450
|
+
const remoteJid = entry2.slice(0, -".jsonl".length);
|
|
1457
1451
|
out.set(remoteJid, readConversation(platformAccountId, remoteJid));
|
|
1458
1452
|
}
|
|
1459
1453
|
} catch (err) {
|
|
@@ -1474,16 +1468,16 @@ function normalizeEntry(v) {
|
|
|
1474
1468
|
return typeof v === "string" ? { account: v, mode: "active" } : { account: v.managesAccount, mode: v.mode ?? "active" };
|
|
1475
1469
|
}
|
|
1476
1470
|
function managedAccountFor(accountManagers, phone) {
|
|
1477
|
-
for (const [managerPhone,
|
|
1478
|
-
const { account, mode } = normalizeEntry(
|
|
1471
|
+
for (const [managerPhone, entry2] of Object.entries(accountManagers)) {
|
|
1472
|
+
const { account, mode } = normalizeEntry(entry2);
|
|
1479
1473
|
if (account && phonesMatch(managerPhone, phone)) return { account, mode };
|
|
1480
1474
|
}
|
|
1481
1475
|
return null;
|
|
1482
1476
|
}
|
|
1483
1477
|
function managerPhonesForAccount(accountManagers, subAccountId) {
|
|
1484
1478
|
const phones = [];
|
|
1485
|
-
for (const [managerPhone,
|
|
1486
|
-
const { account } = normalizeEntry(
|
|
1479
|
+
for (const [managerPhone, entry2] of Object.entries(accountManagers)) {
|
|
1480
|
+
const { account } = normalizeEntry(entry2);
|
|
1487
1481
|
if (account && account === subAccountId) phones.push(managerPhone);
|
|
1488
1482
|
}
|
|
1489
1483
|
return phones;
|
|
@@ -1504,7 +1498,7 @@ function resolveAccountConfig(config, accountConfig) {
|
|
|
1504
1498
|
function isAdminPhone(phone, adminPhones) {
|
|
1505
1499
|
const normalized = normalizeE164(phone);
|
|
1506
1500
|
if (!normalized) return false;
|
|
1507
|
-
return adminPhones.some((
|
|
1501
|
+
return adminPhones.some((entry2) => phonesMatch(entry2, normalized));
|
|
1508
1502
|
}
|
|
1509
1503
|
function checkDmAccess(params) {
|
|
1510
1504
|
const { senderPhone, selfPhone, accountId } = params;
|
|
@@ -1526,9 +1520,9 @@ function checkDmAccess(params) {
|
|
|
1526
1520
|
case "open":
|
|
1527
1521
|
return { allowed: true, reason: "dm-policy-open", agentType: "public", effectiveAccountId: accountId };
|
|
1528
1522
|
case "allowlist": {
|
|
1529
|
-
const inList = cfg.allowFrom.some((
|
|
1530
|
-
if (
|
|
1531
|
-
return phonesMatch(
|
|
1523
|
+
const inList = cfg.allowFrom.some((entry2) => {
|
|
1524
|
+
if (entry2 === "*") return true;
|
|
1525
|
+
return phonesMatch(entry2, senderPhone);
|
|
1532
1526
|
});
|
|
1533
1527
|
if (inList) {
|
|
1534
1528
|
return { allowed: true, reason: "allowlist-match", agentType: "public", effectiveAccountId: accountId };
|
|
@@ -1603,8 +1597,8 @@ var NOTIFY_MAX = 5e3;
|
|
|
1603
1597
|
var notifyCache = /* @__PURE__ */ new Map();
|
|
1604
1598
|
function isNotifyDuplicate(msgKeyId) {
|
|
1605
1599
|
const now = Date.now();
|
|
1606
|
-
const
|
|
1607
|
-
if (
|
|
1600
|
+
const entry2 = notifyCache.get(msgKeyId);
|
|
1601
|
+
if (entry2 && now - entry2.ts <= NOTIFY_TTL_MS) return true;
|
|
1608
1602
|
for (const [key, e] of notifyCache) {
|
|
1609
1603
|
if (now - e.ts > NOTIFY_TTL_MS) notifyCache.delete(key);
|
|
1610
1604
|
}
|
|
@@ -1681,15 +1675,15 @@ var ACCESS_LOCKOUT_MS = 15 * 60 * 1e3;
|
|
|
1681
1675
|
var ACCESS_WINDOW_MS = 15 * 60 * 1e3;
|
|
1682
1676
|
function checkAccessRateLimit(ip, agentSlug) {
|
|
1683
1677
|
const key = `${ip}:${agentSlug}`;
|
|
1684
|
-
const
|
|
1685
|
-
if (!
|
|
1678
|
+
const entry2 = rateLimitMap.get(key);
|
|
1679
|
+
if (!entry2) return null;
|
|
1686
1680
|
const now = Date.now();
|
|
1687
|
-
if (
|
|
1688
|
-
const remainingMs =
|
|
1681
|
+
if (entry2.lockedUntil && now < entry2.lockedUntil) {
|
|
1682
|
+
const remainingMs = entry2.lockedUntil - now;
|
|
1689
1683
|
const remainingS = Math.ceil(remainingMs / 1e3);
|
|
1690
1684
|
return `Too many attempts. Try again in ${remainingS}s`;
|
|
1691
1685
|
}
|
|
1692
|
-
if (now -
|
|
1686
|
+
if (now - entry2.firstAttempt > ACCESS_WINDOW_MS) {
|
|
1693
1687
|
rateLimitMap.delete(key);
|
|
1694
1688
|
return null;
|
|
1695
1689
|
}
|
|
@@ -1698,14 +1692,14 @@ function checkAccessRateLimit(ip, agentSlug) {
|
|
|
1698
1692
|
function recordAccessFailedAttempt(ip, agentSlug) {
|
|
1699
1693
|
const key = `${ip}:${agentSlug}`;
|
|
1700
1694
|
const now = Date.now();
|
|
1701
|
-
const
|
|
1702
|
-
if (!
|
|
1695
|
+
const entry2 = rateLimitMap.get(key);
|
|
1696
|
+
if (!entry2 || now - entry2.firstAttempt > ACCESS_WINDOW_MS) {
|
|
1703
1697
|
rateLimitMap.set(key, { attempts: 1, firstAttempt: now });
|
|
1704
1698
|
return;
|
|
1705
1699
|
}
|
|
1706
|
-
|
|
1707
|
-
if (
|
|
1708
|
-
|
|
1700
|
+
entry2.attempts++;
|
|
1701
|
+
if (entry2.attempts >= ACCESS_MAX_ATTEMPTS) {
|
|
1702
|
+
entry2.lockedUntil = now + ACCESS_LOCKOUT_MS;
|
|
1709
1703
|
}
|
|
1710
1704
|
}
|
|
1711
1705
|
function clearAccessRateLimit(ip, agentSlug) {
|
|
@@ -1715,15 +1709,15 @@ var contactRateMap = /* @__PURE__ */ new Map();
|
|
|
1715
1709
|
var REQUEST_LINK_MAX = 3;
|
|
1716
1710
|
var REQUEST_LINK_WINDOW_MS = 60 * 60 * 1e3;
|
|
1717
1711
|
function checkRequestLinkRateLimit(contactValue) {
|
|
1718
|
-
const
|
|
1719
|
-
if (!
|
|
1712
|
+
const entry2 = contactRateMap.get(contactValue);
|
|
1713
|
+
if (!entry2) return null;
|
|
1720
1714
|
const now = Date.now();
|
|
1721
|
-
if (now -
|
|
1715
|
+
if (now - entry2.windowStart > REQUEST_LINK_WINDOW_MS) {
|
|
1722
1716
|
contactRateMap.delete(contactValue);
|
|
1723
1717
|
return null;
|
|
1724
1718
|
}
|
|
1725
|
-
if (
|
|
1726
|
-
const remainingMs = REQUEST_LINK_WINDOW_MS - (now -
|
|
1719
|
+
if (entry2.count >= REQUEST_LINK_MAX) {
|
|
1720
|
+
const remainingMs = REQUEST_LINK_WINDOW_MS - (now - entry2.windowStart);
|
|
1727
1721
|
const remainingM = Math.ceil(remainingMs / 6e4);
|
|
1728
1722
|
return `Too many requests. Try again in ${remainingM} minute(s)`;
|
|
1729
1723
|
}
|
|
@@ -1731,12 +1725,12 @@ function checkRequestLinkRateLimit(contactValue) {
|
|
|
1731
1725
|
}
|
|
1732
1726
|
function recordRequestLinkAttempt(contactValue) {
|
|
1733
1727
|
const now = Date.now();
|
|
1734
|
-
const
|
|
1735
|
-
if (!
|
|
1728
|
+
const entry2 = contactRateMap.get(contactValue);
|
|
1729
|
+
if (!entry2 || now - entry2.windowStart > REQUEST_LINK_WINDOW_MS) {
|
|
1736
1730
|
contactRateMap.set(contactValue, { count: 1, windowStart: now });
|
|
1737
1731
|
return;
|
|
1738
1732
|
}
|
|
1739
|
-
|
|
1733
|
+
entry2.count++;
|
|
1740
1734
|
}
|
|
1741
1735
|
function maskContact(value) {
|
|
1742
1736
|
if (value.includes("@")) {
|
|
@@ -1925,8 +1919,8 @@ var agentSentCache = /* @__PURE__ */ new Map();
|
|
|
1925
1919
|
var inboundCache = /* @__PURE__ */ new Map();
|
|
1926
1920
|
function pruneCache(cache3, ttl, max) {
|
|
1927
1921
|
const now = Date.now();
|
|
1928
|
-
for (const [key,
|
|
1929
|
-
if (now -
|
|
1922
|
+
for (const [key, entry2] of cache3) {
|
|
1923
|
+
if (now - entry2.ts > ttl) cache3.delete(key);
|
|
1930
1924
|
}
|
|
1931
1925
|
if (cache3.size > max) {
|
|
1932
1926
|
const excess = cache3.size - max;
|
|
@@ -1943,22 +1937,22 @@ function trackAgentSentMessage(messageId) {
|
|
|
1943
1937
|
agentSentCache.set(messageId, { ts: Date.now() });
|
|
1944
1938
|
}
|
|
1945
1939
|
function isAgentSentMessage(messageId) {
|
|
1946
|
-
const
|
|
1947
|
-
if (!
|
|
1948
|
-
if (Date.now() -
|
|
1940
|
+
const entry2 = agentSentCache.get(messageId);
|
|
1941
|
+
if (!entry2) return false;
|
|
1942
|
+
if (Date.now() - entry2.ts > AGENT_SENT_TTL_MS) {
|
|
1949
1943
|
agentSentCache.delete(messageId);
|
|
1950
1944
|
return false;
|
|
1951
1945
|
}
|
|
1952
1946
|
return true;
|
|
1953
1947
|
}
|
|
1954
1948
|
function isDuplicateInbound(key) {
|
|
1955
|
-
const
|
|
1956
|
-
if (!
|
|
1949
|
+
const entry2 = inboundCache.get(key);
|
|
1950
|
+
if (!entry2) {
|
|
1957
1951
|
pruneCache(inboundCache, INBOUND_TTL_MS, INBOUND_MAX);
|
|
1958
1952
|
inboundCache.set(key, { ts: Date.now() });
|
|
1959
1953
|
return false;
|
|
1960
1954
|
}
|
|
1961
|
-
if (Date.now() -
|
|
1955
|
+
if (Date.now() - entry2.ts > INBOUND_TTL_MS) {
|
|
1962
1956
|
inboundCache.delete(key);
|
|
1963
1957
|
inboundCache.set(key, { ts: Date.now() });
|
|
1964
1958
|
return false;
|
|
@@ -2019,7 +2013,7 @@ function recordActivity(event) {
|
|
|
2019
2013
|
}
|
|
2020
2014
|
acct[direction]++;
|
|
2021
2015
|
acct.lastEventAt = now;
|
|
2022
|
-
const
|
|
2016
|
+
const entry2 = {
|
|
2023
2017
|
channel: "whatsapp",
|
|
2024
2018
|
accountId,
|
|
2025
2019
|
direction,
|
|
@@ -2027,7 +2021,7 @@ function recordActivity(event) {
|
|
|
2027
2021
|
timestamp: now,
|
|
2028
2022
|
messageType
|
|
2029
2023
|
};
|
|
2030
|
-
recentEvents.push(
|
|
2024
|
+
recentEvents.push(entry2);
|
|
2031
2025
|
if (recentEvents.length > RECENT_EVENTS_MAX) {
|
|
2032
2026
|
recentEvents.splice(0, recentEvents.length - RECENT_EVENTS_MAX);
|
|
2033
2027
|
}
|
|
@@ -2241,12 +2235,16 @@ async function persistWhatsAppMessage(input) {
|
|
|
2241
2235
|
body: input.body,
|
|
2242
2236
|
fromMe: input.fromMe,
|
|
2243
2237
|
senderTelephone,
|
|
2238
|
+
// Spread rather than assigned, so a record with no sender JID has no key at
|
|
2239
|
+
// all on disk instead of an explicit `null` a reader would have to special-case.
|
|
2240
|
+
...input.senderJid ? { senderJid: input.senderJid } : {},
|
|
2244
2241
|
senderName: input.pushName ?? null,
|
|
2245
2242
|
remoteJid: canonicalRemoteJid,
|
|
2246
2243
|
msgKeyId: input.msgKeyId,
|
|
2247
2244
|
quotedId: input.quoted?.id ?? null,
|
|
2248
2245
|
quotedSender: input.quoted?.sender ?? null,
|
|
2249
2246
|
scope,
|
|
2247
|
+
...input.origin ? { origin: input.origin } : {},
|
|
2250
2248
|
...input.attachmentId ? { attachmentId: input.attachmentId } : {},
|
|
2251
2249
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2252
2250
|
};
|
|
@@ -2297,6 +2295,216 @@ function sanitizeReason(err) {
|
|
|
2297
2295
|
return `${err.name}:${msg}`;
|
|
2298
2296
|
}
|
|
2299
2297
|
|
|
2298
|
+
// app/lib/whatsapp/chat-metadata-store.ts
|
|
2299
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync, statSync as statSync2 } from "fs";
|
|
2300
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
2301
|
+
|
|
2302
|
+
// app/lib/data-path.ts
|
|
2303
|
+
import { realpathSync } from "fs";
|
|
2304
|
+
import { resolve as resolve2, normalize, sep, relative, basename, join as join3 } from "path";
|
|
2305
|
+
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve2(process.cwd(), "../platform");
|
|
2306
|
+
var DATA_ROOT = resolve2(PLATFORM_ROOT2, "..", "data");
|
|
2307
|
+
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve2(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
2308
|
+
var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["accounts"]);
|
|
2309
|
+
var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2310
|
+
function crossesForeignAccountPartition(relPath, accountId) {
|
|
2311
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
2312
|
+
if (segs.length < 2) return false;
|
|
2313
|
+
if (!ACCOUNT_PARTITION_DIRS.has(segs[0])) return false;
|
|
2314
|
+
const owner = segs[1];
|
|
2315
|
+
if (!ACCOUNT_UUID_RE.test(owner)) return false;
|
|
2316
|
+
return owner !== accountId;
|
|
2317
|
+
}
|
|
2318
|
+
function isWithinOwnAccountPartition(relPath, accountId) {
|
|
2319
|
+
const segs = relPath.split("/").filter(Boolean);
|
|
2320
|
+
return segs.length >= 2 && segs[0] === "accounts" && segs[1] === accountId;
|
|
2321
|
+
}
|
|
2322
|
+
function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
2323
|
+
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
2324
|
+
const absolute = resolve2(rootAbs, cleaned);
|
|
2325
|
+
let rootReal;
|
|
2326
|
+
try {
|
|
2327
|
+
rootReal = realpathSync(rootAbs);
|
|
2328
|
+
} catch (err) {
|
|
2329
|
+
return {
|
|
2330
|
+
ok: false,
|
|
2331
|
+
status: 500,
|
|
2332
|
+
error: `${rootLabel} not accessible: ${err instanceof Error ? err.message : String(err)}`
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
let resolvedReal;
|
|
2336
|
+
try {
|
|
2337
|
+
resolvedReal = realpathSync(absolute);
|
|
2338
|
+
} catch (err) {
|
|
2339
|
+
const code = err.code;
|
|
2340
|
+
if (code === "ENOENT") {
|
|
2341
|
+
if (absolute !== rootReal && !absolute.startsWith(rootReal + sep)) {
|
|
2342
|
+
return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: absolute };
|
|
2343
|
+
}
|
|
2344
|
+
return { ok: false, status: 404, error: "Not found" };
|
|
2345
|
+
}
|
|
2346
|
+
return {
|
|
2347
|
+
ok: false,
|
|
2348
|
+
status: 500,
|
|
2349
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep)) {
|
|
2353
|
+
return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: resolvedReal };
|
|
2354
|
+
}
|
|
2355
|
+
const relPath = relative(rootReal, resolvedReal) || ".";
|
|
2356
|
+
return { ok: true, absolute: resolvedReal, dataRootReal: rootReal, relative: relPath };
|
|
2357
|
+
}
|
|
2358
|
+
function resolveDataPath(raw) {
|
|
2359
|
+
return resolveUnderRoot(raw, DATA_ROOT, "DATA_ROOT");
|
|
2360
|
+
}
|
|
2361
|
+
function resolveClaudeUploadsPath(raw) {
|
|
2362
|
+
if (!CLAUDE_UPLOADS_ROOT) {
|
|
2363
|
+
return { ok: false, status: 404, error: "Not found" };
|
|
2364
|
+
}
|
|
2365
|
+
return resolveUnderRoot(raw, CLAUDE_UPLOADS_ROOT, "CLAUDE_UPLOADS_ROOT");
|
|
2366
|
+
}
|
|
2367
|
+
function scratchpadTmpBase() {
|
|
2368
|
+
return process.env.MAXY_SCRATCHPAD_BASE ?? "/tmp";
|
|
2369
|
+
}
|
|
2370
|
+
function sessionScratchpadRoot(projectDir, sessionId) {
|
|
2371
|
+
const uid = typeof process.geteuid === "function" ? process.geteuid() : 0;
|
|
2372
|
+
return join3(scratchpadTmpBase(), `claude-${uid}`, basename(projectDir), sessionId, "scratchpad");
|
|
2373
|
+
}
|
|
2374
|
+
function resolveScratchpadPath(raw, scratchpadRootAbs) {
|
|
2375
|
+
return resolveUnderRoot(raw, scratchpadRootAbs, "scratchpad");
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
// app/lib/whatsapp/chat-metadata-store.ts
|
|
2379
|
+
var SOURCE_RANK = { contact: 3, group: 2, chat: 1 };
|
|
2380
|
+
function isSource(v) {
|
|
2381
|
+
return v === "contact" || v === "group" || v === "chat";
|
|
2382
|
+
}
|
|
2383
|
+
function preferEntry(existing, incoming) {
|
|
2384
|
+
if (existing === void 0) return incoming;
|
|
2385
|
+
const a = SOURCE_RANK[existing.source];
|
|
2386
|
+
const b = SOURCE_RANK[incoming.source];
|
|
2387
|
+
if (b > a) return incoming;
|
|
2388
|
+
if (b < a) return existing;
|
|
2389
|
+
return incoming.updatedAt > existing.updatedAt ? incoming : existing;
|
|
2390
|
+
}
|
|
2391
|
+
function parseChatMetadata(raw) {
|
|
2392
|
+
const out = /* @__PURE__ */ new Map();
|
|
2393
|
+
let parsed;
|
|
2394
|
+
try {
|
|
2395
|
+
parsed = JSON.parse(raw);
|
|
2396
|
+
} catch {
|
|
2397
|
+
return out;
|
|
2398
|
+
}
|
|
2399
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return out;
|
|
2400
|
+
for (const [jid, value] of Object.entries(parsed)) {
|
|
2401
|
+
if (value === null || typeof value !== "object") continue;
|
|
2402
|
+
const v = value;
|
|
2403
|
+
if (typeof v.name !== "string" || v.name.length === 0) continue;
|
|
2404
|
+
if (!isSource(v.source)) continue;
|
|
2405
|
+
if (typeof v.updatedAt !== "string") continue;
|
|
2406
|
+
out.set(jid, {
|
|
2407
|
+
jid,
|
|
2408
|
+
name: v.name,
|
|
2409
|
+
source: v.source,
|
|
2410
|
+
isGroup: v.isGroup === true,
|
|
2411
|
+
updatedAt: v.updatedAt
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
return out;
|
|
2415
|
+
}
|
|
2416
|
+
function serializeChatMetadata(map) {
|
|
2417
|
+
const obj = {};
|
|
2418
|
+
for (const [jid, entry2] of map) obj[jid] = entry2;
|
|
2419
|
+
return JSON.stringify(obj);
|
|
2420
|
+
}
|
|
2421
|
+
function chatMetadataPath(accountId) {
|
|
2422
|
+
return join4(DATA_ROOT, "accounts", accountId, "chat-metadata.json");
|
|
2423
|
+
}
|
|
2424
|
+
var readCache = /* @__PURE__ */ new Map();
|
|
2425
|
+
function readChatMetadata(accountId) {
|
|
2426
|
+
const path3 = chatMetadataPath(accountId);
|
|
2427
|
+
try {
|
|
2428
|
+
if (!existsSync4(path3)) return /* @__PURE__ */ new Map();
|
|
2429
|
+
const st = statSync2(path3);
|
|
2430
|
+
const cached = readCache.get(path3);
|
|
2431
|
+
if (cached && cached.size === st.size && cached.mtimeMs === st.mtimeMs) return cached.map;
|
|
2432
|
+
const map = parseChatMetadata(readFileSync5(path3, "utf8"));
|
|
2433
|
+
readCache.set(path3, { size: st.size, mtimeMs: st.mtimeMs, map });
|
|
2434
|
+
return map;
|
|
2435
|
+
} catch (err) {
|
|
2436
|
+
console.error(
|
|
2437
|
+
`[wa-chatmeta] op=read outcome=fail account=${accountId.slice(0, 8)} reason=${(err instanceof Error ? err.message : String(err)).slice(0, 100)}`
|
|
2438
|
+
);
|
|
2439
|
+
return /* @__PURE__ */ new Map();
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
function writeChatMetadataMerged(accountId, updates) {
|
|
2443
|
+
if (updates.length === 0) return -1;
|
|
2444
|
+
const path3 = chatMetadataPath(accountId);
|
|
2445
|
+
try {
|
|
2446
|
+
mkdirSync3(dirname2(path3), { recursive: true });
|
|
2447
|
+
let merged = /* @__PURE__ */ new Map();
|
|
2448
|
+
if (existsSync4(path3)) merged = parseChatMetadata(readFileSync5(path3, "utf8"));
|
|
2449
|
+
for (const entry2 of updates) merged.set(entry2.jid, preferEntry(merged.get(entry2.jid), entry2));
|
|
2450
|
+
const tmp = `${path3}.tmp`;
|
|
2451
|
+
writeFileSync3(tmp, serializeChatMetadata(merged), "utf8");
|
|
2452
|
+
renameSync(tmp, path3);
|
|
2453
|
+
return parseChatMetadata(readFileSync5(path3, "utf8")).size;
|
|
2454
|
+
} catch (err) {
|
|
2455
|
+
console.error(
|
|
2456
|
+
`[wa-chatmeta] op=persist outcome=fail account=${accountId.slice(0, 8)} reason=${(err instanceof Error ? err.message : String(err)).slice(0, 100)}`
|
|
2457
|
+
);
|
|
2458
|
+
return -1;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
// app/lib/whatsapp/chat-metadata-events.ts
|
|
2463
|
+
var NON_CHAT_JIDS = /* @__PURE__ */ new Set(["status@broadcast"]);
|
|
2464
|
+
function isGroupJid2(jid) {
|
|
2465
|
+
return jid.endsWith("@g.us");
|
|
2466
|
+
}
|
|
2467
|
+
function entry(jid, name, source, nowIso) {
|
|
2468
|
+
return { jid, name, source, isGroup: isGroupJid2(jid), updatedAt: nowIso };
|
|
2469
|
+
}
|
|
2470
|
+
function conversationKey(jid, phoneNumber) {
|
|
2471
|
+
if (!jid.endsWith("@lid")) return jid;
|
|
2472
|
+
if (typeof phoneNumber !== "string") return jid;
|
|
2473
|
+
const trimmed = phoneNumber.trim();
|
|
2474
|
+
return trimmed.endsWith("@s.whatsapp.net") ? trimmed : jid;
|
|
2475
|
+
}
|
|
2476
|
+
function usable(jid, name, phoneNumber) {
|
|
2477
|
+
if (typeof jid !== "string" || jid.length === 0) return null;
|
|
2478
|
+
if (NON_CHAT_JIDS.has(jid)) return null;
|
|
2479
|
+
const trimmed = typeof name === "string" ? name.trim() : "";
|
|
2480
|
+
if (trimmed.length === 0) return null;
|
|
2481
|
+
return { jid: conversationKey(jid, phoneNumber), name: trimmed };
|
|
2482
|
+
}
|
|
2483
|
+
function chatEntriesFromChats(chats, nowIso) {
|
|
2484
|
+
const out = [];
|
|
2485
|
+
for (const c of chats) {
|
|
2486
|
+
const ok = usable(c.id, c.name, c.phoneNumber);
|
|
2487
|
+
if (ok) out.push(entry(ok.jid, ok.name, "chat", nowIso));
|
|
2488
|
+
}
|
|
2489
|
+
return out;
|
|
2490
|
+
}
|
|
2491
|
+
function chatEntriesFromContacts(contacts, nowIso) {
|
|
2492
|
+
const out = [];
|
|
2493
|
+
for (const c of contacts) {
|
|
2494
|
+
const ok = usable(c.id, c.name, c.phoneNumber);
|
|
2495
|
+
if (ok) out.push(entry(ok.jid, ok.name, isGroupJid2(ok.jid) ? "chat" : "contact", nowIso));
|
|
2496
|
+
}
|
|
2497
|
+
return out;
|
|
2498
|
+
}
|
|
2499
|
+
function groupEntriesFromUpdates(updates, nowIso) {
|
|
2500
|
+
const out = [];
|
|
2501
|
+
for (const g of updates) {
|
|
2502
|
+
const ok = usable(g.id, g.subject);
|
|
2503
|
+
if (ok) out.push(entry(ok.jid, ok.name, "group", nowIso));
|
|
2504
|
+
}
|
|
2505
|
+
return out;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2300
2508
|
// app/lib/whatsapp/ensure-conversation.ts
|
|
2301
2509
|
var TAG10 = "[whatsapp-persist]";
|
|
2302
2510
|
async function ensureWhatsAppConversation(input) {
|
|
@@ -2329,8 +2537,8 @@ async function ensureWhatsAppConversation(input) {
|
|
|
2329
2537
|
}
|
|
2330
2538
|
|
|
2331
2539
|
// ../lib/account-enumeration/src/index.ts
|
|
2332
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
2333
|
-
import { resolve as
|
|
2540
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
2541
|
+
import { resolve as resolve3 } from "path";
|
|
2334
2542
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2335
2543
|
var cache2 = /* @__PURE__ */ new Map();
|
|
2336
2544
|
function enumerateValidAccountIds(accountsDir) {
|
|
@@ -2349,9 +2557,9 @@ function enumerateValidAccountIds(accountsDir) {
|
|
|
2349
2557
|
const valid = [];
|
|
2350
2558
|
for (const name of names) {
|
|
2351
2559
|
if (!UUID_RE.test(name)) continue;
|
|
2352
|
-
const configPath =
|
|
2560
|
+
const configPath = resolve3(accountsDir, name, "account.json");
|
|
2353
2561
|
try {
|
|
2354
|
-
JSON.parse(
|
|
2562
|
+
JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
2355
2563
|
valid.push(name);
|
|
2356
2564
|
} catch (err) {
|
|
2357
2565
|
const code = err.code;
|
|
@@ -2365,9 +2573,9 @@ function resolveHouseOrSoleAccountId(accountsDir) {
|
|
|
2365
2573
|
const valid = enumerateValidAccountIds(accountsDir);
|
|
2366
2574
|
const houses = [];
|
|
2367
2575
|
for (const id of valid) {
|
|
2368
|
-
const configPath =
|
|
2576
|
+
const configPath = resolve3(accountsDir, id, "account.json");
|
|
2369
2577
|
try {
|
|
2370
|
-
const cfg = JSON.parse(
|
|
2578
|
+
const cfg = JSON.parse(readFileSync6(configPath, "utf-8"));
|
|
2371
2579
|
if (cfg.role === "house") houses.push(id);
|
|
2372
2580
|
} catch {
|
|
2373
2581
|
}
|
|
@@ -2385,7 +2593,7 @@ function getAccountsDirFromEnv() {
|
|
|
2385
2593
|
"[graph-write] MAXY_PLATFORM_ROOT not set \u2014 cannot enforce accountId gate. Set MAXY_PLATFORM_ROOT in the spawning process or pass `accountsDir` explicitly."
|
|
2386
2594
|
);
|
|
2387
2595
|
}
|
|
2388
|
-
return
|
|
2596
|
+
return resolve3(root, "..", "data/accounts");
|
|
2389
2597
|
}
|
|
2390
2598
|
function validateAccountIdEnv(envValue, diskIds) {
|
|
2391
2599
|
if (!envValue) {
|
|
@@ -2401,8 +2609,8 @@ function validateAccountIdEnv(envValue, diskIds) {
|
|
|
2401
2609
|
}
|
|
2402
2610
|
|
|
2403
2611
|
// app/lib/whatsapp/platform-account-id.ts
|
|
2404
|
-
import { readFileSync as
|
|
2405
|
-
import { resolve as
|
|
2612
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
2613
|
+
import { resolve as resolve4 } from "path";
|
|
2406
2614
|
var cachedHouseId = null;
|
|
2407
2615
|
var cachedHouseAccountsDir = null;
|
|
2408
2616
|
function resolveHouseId(accountsDir) {
|
|
@@ -2413,10 +2621,10 @@ function resolveHouseId(accountsDir) {
|
|
|
2413
2621
|
return cachedHouseId;
|
|
2414
2622
|
}
|
|
2415
2623
|
function readChannelRoutingOverride(accountsDir, houseId) {
|
|
2416
|
-
const configPath =
|
|
2624
|
+
const configPath = resolve4(accountsDir, houseId, "account.json");
|
|
2417
2625
|
let raw;
|
|
2418
2626
|
try {
|
|
2419
|
-
raw =
|
|
2627
|
+
raw = readFileSync7(configPath, "utf-8");
|
|
2420
2628
|
} catch {
|
|
2421
2629
|
return null;
|
|
2422
2630
|
}
|
|
@@ -2457,8 +2665,8 @@ function warnNonUuidAccount(caller, accountId) {
|
|
|
2457
2665
|
}
|
|
2458
2666
|
|
|
2459
2667
|
// app/lib/managed-service.ts
|
|
2460
|
-
import { join as
|
|
2461
|
-
import { readFileSync as
|
|
2668
|
+
import { join as join5 } from "path";
|
|
2669
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
2462
2670
|
function isHouseManagedService(accountsDir = ACCOUNTS_DIR) {
|
|
2463
2671
|
let houseId;
|
|
2464
2672
|
try {
|
|
@@ -2468,7 +2676,7 @@ function isHouseManagedService(accountsDir = ACCOUNTS_DIR) {
|
|
|
2468
2676
|
}
|
|
2469
2677
|
try {
|
|
2470
2678
|
const cfg = JSON.parse(
|
|
2471
|
-
|
|
2679
|
+
readFileSync8(join5(accountsDir, houseId, "account.json"), "utf-8")
|
|
2472
2680
|
);
|
|
2473
2681
|
return cfg.managedService === true;
|
|
2474
2682
|
} catch {
|
|
@@ -2482,7 +2690,7 @@ function isCustomerTurnSuppressed(role, managedService) {
|
|
|
2482
2690
|
// app/lib/whatsapp/inbound/media.ts
|
|
2483
2691
|
import { randomUUID as randomUUID4, createHash } from "crypto";
|
|
2484
2692
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
2485
|
-
import { join as
|
|
2693
|
+
import { join as join6 } from "path";
|
|
2486
2694
|
import {
|
|
2487
2695
|
downloadMediaMessage,
|
|
2488
2696
|
downloadContentFromMessage,
|
|
@@ -2492,85 +2700,9 @@ import {
|
|
|
2492
2700
|
// app/lib/attachments.ts
|
|
2493
2701
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2494
2702
|
import { mkdir, writeFile } from "fs/promises";
|
|
2495
|
-
import { realpathSync as realpathSync2, existsSync as
|
|
2703
|
+
import { realpathSync as realpathSync2, existsSync as existsSync5, readFileSync as readFileSync9, readdirSync as readdirSync4 } from "fs";
|
|
2496
2704
|
import { resolve as resolve5, extname } from "path";
|
|
2497
2705
|
|
|
2498
|
-
// app/lib/data-path.ts
|
|
2499
|
-
import { realpathSync } from "fs";
|
|
2500
|
-
import { resolve as resolve4, normalize, sep, relative, basename, join as join4 } from "path";
|
|
2501
|
-
var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve4(process.cwd(), "../platform");
|
|
2502
|
-
var DATA_ROOT = resolve4(PLATFORM_ROOT2, "..", "data");
|
|
2503
|
-
var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve4(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
|
|
2504
|
-
var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["accounts"]);
|
|
2505
|
-
var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2506
|
-
function crossesForeignAccountPartition(relPath, accountId) {
|
|
2507
|
-
const segs = relPath.split("/").filter(Boolean);
|
|
2508
|
-
if (segs.length < 2) return false;
|
|
2509
|
-
if (!ACCOUNT_PARTITION_DIRS.has(segs[0])) return false;
|
|
2510
|
-
const owner = segs[1];
|
|
2511
|
-
if (!ACCOUNT_UUID_RE.test(owner)) return false;
|
|
2512
|
-
return owner !== accountId;
|
|
2513
|
-
}
|
|
2514
|
-
function isWithinOwnAccountPartition(relPath, accountId) {
|
|
2515
|
-
const segs = relPath.split("/").filter(Boolean);
|
|
2516
|
-
return segs.length >= 2 && segs[0] === "accounts" && segs[1] === accountId;
|
|
2517
|
-
}
|
|
2518
|
-
function resolveUnderRoot(raw, rootAbs, rootLabel) {
|
|
2519
|
-
const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
|
|
2520
|
-
const absolute = resolve4(rootAbs, cleaned);
|
|
2521
|
-
let rootReal;
|
|
2522
|
-
try {
|
|
2523
|
-
rootReal = realpathSync(rootAbs);
|
|
2524
|
-
} catch (err) {
|
|
2525
|
-
return {
|
|
2526
|
-
ok: false,
|
|
2527
|
-
status: 500,
|
|
2528
|
-
error: `${rootLabel} not accessible: ${err instanceof Error ? err.message : String(err)}`
|
|
2529
|
-
};
|
|
2530
|
-
}
|
|
2531
|
-
let resolvedReal;
|
|
2532
|
-
try {
|
|
2533
|
-
resolvedReal = realpathSync(absolute);
|
|
2534
|
-
} catch (err) {
|
|
2535
|
-
const code = err.code;
|
|
2536
|
-
if (code === "ENOENT") {
|
|
2537
|
-
if (absolute !== rootReal && !absolute.startsWith(rootReal + sep)) {
|
|
2538
|
-
return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: absolute };
|
|
2539
|
-
}
|
|
2540
|
-
return { ok: false, status: 404, error: "Not found" };
|
|
2541
|
-
}
|
|
2542
|
-
return {
|
|
2543
|
-
ok: false,
|
|
2544
|
-
status: 500,
|
|
2545
|
-
error: err instanceof Error ? err.message : String(err)
|
|
2546
|
-
};
|
|
2547
|
-
}
|
|
2548
|
-
if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep)) {
|
|
2549
|
-
return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: resolvedReal };
|
|
2550
|
-
}
|
|
2551
|
-
const relPath = relative(rootReal, resolvedReal) || ".";
|
|
2552
|
-
return { ok: true, absolute: resolvedReal, dataRootReal: rootReal, relative: relPath };
|
|
2553
|
-
}
|
|
2554
|
-
function resolveDataPath(raw) {
|
|
2555
|
-
return resolveUnderRoot(raw, DATA_ROOT, "DATA_ROOT");
|
|
2556
|
-
}
|
|
2557
|
-
function resolveClaudeUploadsPath(raw) {
|
|
2558
|
-
if (!CLAUDE_UPLOADS_ROOT) {
|
|
2559
|
-
return { ok: false, status: 404, error: "Not found" };
|
|
2560
|
-
}
|
|
2561
|
-
return resolveUnderRoot(raw, CLAUDE_UPLOADS_ROOT, "CLAUDE_UPLOADS_ROOT");
|
|
2562
|
-
}
|
|
2563
|
-
function scratchpadTmpBase() {
|
|
2564
|
-
return process.env.MAXY_SCRATCHPAD_BASE ?? "/tmp";
|
|
2565
|
-
}
|
|
2566
|
-
function sessionScratchpadRoot(projectDir, sessionId) {
|
|
2567
|
-
const uid = typeof process.geteuid === "function" ? process.geteuid() : 0;
|
|
2568
|
-
return join4(scratchpadTmpBase(), `claude-${uid}`, basename(projectDir), sessionId, "scratchpad");
|
|
2569
|
-
}
|
|
2570
|
-
function resolveScratchpadPath(raw, scratchpadRootAbs) {
|
|
2571
|
-
return resolveUnderRoot(raw, scratchpadRootAbs, "scratchpad");
|
|
2572
|
-
}
|
|
2573
|
-
|
|
2574
2706
|
// app/lib/doc-to-text.ts
|
|
2575
2707
|
import { unzipSync, strFromU8 } from "fflate";
|
|
2576
2708
|
var DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
@@ -2591,10 +2723,10 @@ function bareMime(mimeType) {
|
|
|
2591
2723
|
function unescapeXml(s) {
|
|
2592
2724
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
2593
2725
|
}
|
|
2594
|
-
function unzipEntry(buffer,
|
|
2726
|
+
function unzipEntry(buffer, entry2) {
|
|
2595
2727
|
const files = unzipSync(new Uint8Array(buffer));
|
|
2596
|
-
const bytes = files[
|
|
2597
|
-
if (!bytes) throw new Error(`zip entry not found: ${
|
|
2728
|
+
const bytes = files[entry2];
|
|
2729
|
+
if (!bytes) throw new Error(`zip entry not found: ${entry2}`);
|
|
2598
2730
|
return strFromU8(bytes);
|
|
2599
2731
|
}
|
|
2600
2732
|
function docxToText(buffer) {
|
|
@@ -2816,14 +2948,14 @@ async function storeMediaBuffer(accountId, attachmentId, filename, mimeType, buf
|
|
|
2816
2948
|
return writeAttachment(accountId, "", filename, mimeType, buffer.byteLength, buffer, attachmentId);
|
|
2817
2949
|
}
|
|
2818
2950
|
function attachmentExists(accountId, attachmentId) {
|
|
2819
|
-
return
|
|
2951
|
+
return existsSync5(resolve5(uploadsDirFor(accountId, "", attachmentId), `${attachmentId}.meta.json`));
|
|
2820
2952
|
}
|
|
2821
2953
|
function resolveStoredAttachment(accountId, attachmentId) {
|
|
2822
2954
|
if (!ATTACHMENT_ID_RE.test(attachmentId)) return null;
|
|
2823
2955
|
const dir = uploadsDirFor(accountId, "", attachmentId);
|
|
2824
2956
|
let meta;
|
|
2825
2957
|
try {
|
|
2826
|
-
meta = JSON.parse(
|
|
2958
|
+
meta = JSON.parse(readFileSync9(resolve5(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
2827
2959
|
} catch {
|
|
2828
2960
|
return null;
|
|
2829
2961
|
}
|
|
@@ -3173,7 +3305,7 @@ async function downloadInboundMedia(msg, sock, opts) {
|
|
|
3173
3305
|
if (!res) return void 0;
|
|
3174
3306
|
await mkdir2(MEDIA_DIR, { recursive: true });
|
|
3175
3307
|
const ext = mimeToExt(res.mimetype);
|
|
3176
|
-
const filePath =
|
|
3308
|
+
const filePath = join6(MEDIA_DIR, `${randomUUID4()}.${ext}`);
|
|
3177
3309
|
await writeFile2(filePath, res.buffer);
|
|
3178
3310
|
const sizeKB = (res.buffer.length / 1024).toFixed(0);
|
|
3179
3311
|
console.error(`${TAG12} media downloaded type=${res.mimetype} size=${sizeKB}KB path=${filePath}`);
|
|
@@ -3578,6 +3710,7 @@ var connections = /* @__PURE__ */ new Map();
|
|
|
3578
3710
|
var configDir = null;
|
|
3579
3711
|
var whatsAppConfig = {};
|
|
3580
3712
|
var onInboundMessage = null;
|
|
3713
|
+
var onMediaStanza = null;
|
|
3581
3714
|
var onNotify = null;
|
|
3582
3715
|
function buildNotifyPending(args) {
|
|
3583
3716
|
const { body, truncated } = formatNotifyBody(args.text, args.mediaType);
|
|
@@ -3608,13 +3741,13 @@ var messageStore = /* @__PURE__ */ new Map();
|
|
|
3608
3741
|
function messageStoreKey(accountId, remoteJid) {
|
|
3609
3742
|
return `${accountId}:${remoteJid}`;
|
|
3610
3743
|
}
|
|
3611
|
-
function storeMessage(storeKey,
|
|
3744
|
+
function storeMessage(storeKey, entry2) {
|
|
3612
3745
|
let entries = messageStore.get(storeKey);
|
|
3613
3746
|
if (!entries) {
|
|
3614
3747
|
entries = [];
|
|
3615
3748
|
messageStore.set(storeKey, entries);
|
|
3616
3749
|
}
|
|
3617
|
-
entries.push(
|
|
3750
|
+
entries.push(entry2);
|
|
3618
3751
|
if (entries.length > MESSAGE_STORE_MAX) {
|
|
3619
3752
|
const trimmed = entries.length - MESSAGE_STORE_MAX;
|
|
3620
3753
|
entries.splice(0, trimmed);
|
|
@@ -3668,6 +3801,7 @@ async function init(opts) {
|
|
|
3668
3801
|
configDir = opts.configDir;
|
|
3669
3802
|
onInboundMessage = opts.onMessage;
|
|
3670
3803
|
onNotify = opts.onNotify ?? null;
|
|
3804
|
+
onMediaStanza = opts.onMediaStanza ?? null;
|
|
3671
3805
|
loadConfig(opts.accountConfig);
|
|
3672
3806
|
const accountIds = listCredentialAccountIds(configDir);
|
|
3673
3807
|
if (accountIds.length === 0) {
|
|
@@ -3870,6 +4004,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
|
|
|
3870
4004
|
applySelfIdentity(conn, sock, "register");
|
|
3871
4005
|
connections.set(accountId, conn);
|
|
3872
4006
|
monitorInbound(conn);
|
|
4007
|
+
monitorChatMetadata(conn);
|
|
3873
4008
|
try {
|
|
3874
4009
|
await sock.sendPresenceUpdate("available");
|
|
3875
4010
|
console.error(`${TAG16} presence set to available account=${accountId}`);
|
|
@@ -3991,6 +4126,7 @@ async function connectWithReconnect(conn) {
|
|
|
3991
4126
|
conn.sock = sock;
|
|
3992
4127
|
applySelfIdentity(conn, sock, "pre-listener");
|
|
3993
4128
|
monitorInbound(conn);
|
|
4129
|
+
monitorChatMetadata(conn);
|
|
3994
4130
|
console.error(`${TAG16} socket created account=${conn.accountId} \u2014 waiting for connection`);
|
|
3995
4131
|
await waitForConnection(sock);
|
|
3996
4132
|
connectedAt = Date.now();
|
|
@@ -4122,6 +4258,95 @@ function applySelfIdentity(conn, sock, phase) {
|
|
|
4122
4258
|
);
|
|
4123
4259
|
}
|
|
4124
4260
|
}
|
|
4261
|
+
function monitorChatMetadata(conn) {
|
|
4262
|
+
if (!conn.sock) return;
|
|
4263
|
+
const sock = conn.sock;
|
|
4264
|
+
const account = conn.platformAccountId;
|
|
4265
|
+
const canonicalise = async (entries) => {
|
|
4266
|
+
const out = [];
|
|
4267
|
+
for (const e of entries) {
|
|
4268
|
+
if (!e.jid.endsWith("@lid")) {
|
|
4269
|
+
out.push(e);
|
|
4270
|
+
continue;
|
|
4271
|
+
}
|
|
4272
|
+
const { canonical, resolved } = await resolveCanonicalConversationJid(e.jid, conn.lidMapping);
|
|
4273
|
+
if (resolved === "lid2pn") {
|
|
4274
|
+
console.error(`${TAG16} [wa-chatmeta] op=canonical raw=${e.jid} canonical=${canonical}`);
|
|
4275
|
+
out.push({ ...e, jid: canonical });
|
|
4276
|
+
} else {
|
|
4277
|
+
out.push(e);
|
|
4278
|
+
}
|
|
4279
|
+
}
|
|
4280
|
+
return out;
|
|
4281
|
+
};
|
|
4282
|
+
const persist = (kind, entries, perJid) => {
|
|
4283
|
+
if (entries.length === 0) return;
|
|
4284
|
+
if (perJid) {
|
|
4285
|
+
for (const e of entries) {
|
|
4286
|
+
console.error(
|
|
4287
|
+
`${TAG16} [wa-chatmeta] op=event kind=${kind} jid=${e.jid} name=${e.name.length} source=${e.source}`
|
|
4288
|
+
);
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
const total = writeChatMetadataMerged(account, entries);
|
|
4292
|
+
console.error(
|
|
4293
|
+
`${TAG16} [wa-chatmeta] op=persist kind=${kind} account=${account.slice(0, 8)} updates=${entries.length} outcome=${total < 0 ? "fail" : "ok"} entries=${total}`
|
|
4294
|
+
);
|
|
4295
|
+
};
|
|
4296
|
+
sock.ev.on("messaging-history.set", ({ chats, contacts }) => {
|
|
4297
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4298
|
+
const chatEntries = chatEntriesFromChats(chats ?? [], nowIso);
|
|
4299
|
+
const contactEntries = chatEntriesFromContacts(contacts ?? [], nowIso);
|
|
4300
|
+
console.error(
|
|
4301
|
+
`${TAG16} [wa-chatmeta] op=history-set account=${account.slice(0, 8)} chats=${chats?.length ?? 0} contacts=${contacts?.length ?? 0} groups=${chatEntries.filter((e) => e.isGroup).length} named=${chatEntries.length + contactEntries.length}`
|
|
4302
|
+
);
|
|
4303
|
+
void canonicalise([...chatEntries, ...contactEntries]).then((e) => persist("history-set", e, false));
|
|
4304
|
+
});
|
|
4305
|
+
sock.ev.on("chats.upsert", (chats) => {
|
|
4306
|
+
void canonicalise(chatEntriesFromChats(chats ?? [], (/* @__PURE__ */ new Date()).toISOString())).then((e) => persist("chats.upsert", e, true));
|
|
4307
|
+
});
|
|
4308
|
+
sock.ev.on("chats.update", (chats) => {
|
|
4309
|
+
void canonicalise(chatEntriesFromChats(chats ?? [], (/* @__PURE__ */ new Date()).toISOString())).then((e) => persist("chats.update", e, true));
|
|
4310
|
+
});
|
|
4311
|
+
sock.ev.on("contacts.upsert", (contacts) => {
|
|
4312
|
+
void canonicalise(chatEntriesFromContacts(contacts ?? [], (/* @__PURE__ */ new Date()).toISOString())).then((e) => persist("contacts.upsert", e, true));
|
|
4313
|
+
});
|
|
4314
|
+
sock.ev.on("contacts.update", (contacts) => {
|
|
4315
|
+
void canonicalise(chatEntriesFromContacts(contacts ?? [], (/* @__PURE__ */ new Date()).toISOString())).then((e) => persist("contacts.update", e, true));
|
|
4316
|
+
});
|
|
4317
|
+
sock.ev.on("groups.update", (updates) => {
|
|
4318
|
+
persist("groups.update", groupEntriesFromUpdates(updates ?? [], (/* @__PURE__ */ new Date()).toISOString()), true);
|
|
4319
|
+
});
|
|
4320
|
+
const groupFetchAttempted = /* @__PURE__ */ new Set();
|
|
4321
|
+
sock.ev.on("messages.upsert", async (upsert) => {
|
|
4322
|
+
for (const msg of upsert.messages ?? []) {
|
|
4323
|
+
const jid = msg.key?.remoteJid;
|
|
4324
|
+
if (!jid || !jid.endsWith("@g.us")) continue;
|
|
4325
|
+
if (groupFetchAttempted.has(jid)) continue;
|
|
4326
|
+
if (readChatMetadata(account).get(jid)?.source === "group") continue;
|
|
4327
|
+
groupFetchAttempted.add(jid);
|
|
4328
|
+
const startedAt = Date.now();
|
|
4329
|
+
try {
|
|
4330
|
+
const meta = await sock.groupMetadata(jid);
|
|
4331
|
+
console.error(
|
|
4332
|
+
`${TAG16} [wa-chatmeta] op=group-fetch jid=${jid} ms=${Date.now() - startedAt} outcome=ok`
|
|
4333
|
+
);
|
|
4334
|
+
persist(
|
|
4335
|
+
"group-fetch",
|
|
4336
|
+
groupEntriesFromUpdates([{ id: jid, subject: meta.subject }], (/* @__PURE__ */ new Date()).toISOString()),
|
|
4337
|
+
true
|
|
4338
|
+
);
|
|
4339
|
+
} catch (err) {
|
|
4340
|
+
console.error(
|
|
4341
|
+
`${TAG16} [wa-chatmeta] op=group-fetch jid=${jid} ms=${Date.now() - startedAt} outcome=fail reason=${(err instanceof Error ? err.message : String(err)).slice(0, 100)}`
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
});
|
|
4346
|
+
}
|
|
4347
|
+
function listConnections() {
|
|
4348
|
+
return [...connections.values()];
|
|
4349
|
+
}
|
|
4125
4350
|
function monitorInbound(conn) {
|
|
4126
4351
|
if (!conn.sock || !onInboundMessage) return;
|
|
4127
4352
|
const sock = conn.sock;
|
|
@@ -4130,8 +4355,8 @@ function monitorInbound(conn) {
|
|
|
4130
4355
|
conn.debouncer = createInboundDebouncer({
|
|
4131
4356
|
debounceMs,
|
|
4132
4357
|
buildKey: (payload) => {
|
|
4133
|
-
const
|
|
4134
|
-
return `${payload.accountId}:${
|
|
4358
|
+
const conversationKey2 = payload.isGroup ? payload.groupJid : payload.senderPhone;
|
|
4359
|
+
return `${payload.accountId}:${conversationKey2 ?? payload.senderPhone}:${payload.senderPhone}`;
|
|
4135
4360
|
},
|
|
4136
4361
|
onFlush: (entries) => {
|
|
4137
4362
|
if (!onInboundMessage) return;
|
|
@@ -4326,7 +4551,38 @@ function monitorInbound(conn) {
|
|
|
4326
4551
|
msgKeyId: msg.key.id,
|
|
4327
4552
|
fromMe,
|
|
4328
4553
|
senderPhone,
|
|
4554
|
+
// Task 2096 — the sender's wire JID, carried so the reader can
|
|
4555
|
+
// identify a group participant. `senderPhone` above cannot: an
|
|
4556
|
+
// unmapped LID reaches it as bare digits indistinguishable from a
|
|
4557
|
+
// phone number, and anything built from those digits addresses a
|
|
4558
|
+
// different WhatsApp account.
|
|
4559
|
+
//
|
|
4560
|
+
// Inbound only. On a `fromMe` echo the sender is this install, and
|
|
4561
|
+
// `senderJid` above holds the counterparty for a DM (the message's
|
|
4562
|
+
// remoteJid), so passing it would record the wrong person as the
|
|
4563
|
+
// sender of the operator's own message.
|
|
4564
|
+
senderJid: fromMe ? void 0 : senderJid,
|
|
4329
4565
|
selfPhone: conn.selfPhone,
|
|
4566
|
+
// Task 2096 — the group-outbound audit's discriminator. This cache
|
|
4567
|
+
// holds the ids of sends THIS process made through the outbound
|
|
4568
|
+
// helpers, so a stamp here means the agent path produced the
|
|
4569
|
+
// message; an operator typing on their phone or another linked
|
|
4570
|
+
// device leaves it absent.
|
|
4571
|
+
//
|
|
4572
|
+
// Two routes write their own record synchronously after their send
|
|
4573
|
+
// resolves, under the same messageId and store account: the reader
|
|
4574
|
+
// composer (stamping `operator-manual`) and the agent's own
|
|
4575
|
+
// `/api/whatsapp/reply` (stamping `agent` itself). This expression
|
|
4576
|
+
// is still evaluated for their echoes — every `fromMe` message
|
|
4577
|
+
// reaches it — but `appendMessage` then dedupes on `messageId` and
|
|
4578
|
+
// the value computed here is discarded. So the stamp that survives
|
|
4579
|
+
// for those two is the one their route wrote, and this site is what
|
|
4580
|
+
// covers every other agent send, the document path among them.
|
|
4581
|
+
//
|
|
4582
|
+
// Read-only against the same cache the echo suppression below uses
|
|
4583
|
+
// (a hit does not consume the entry), so the ordering of the two is
|
|
4584
|
+
// free.
|
|
4585
|
+
origin: fromMe && msg.key.id && isAgentSentMessage(msg.key.id) ? "agent" : void 0,
|
|
4330
4586
|
timestamp: ts,
|
|
4331
4587
|
pushName: msg.pushName ?? void 0,
|
|
4332
4588
|
quoted: extracted.quotedMessage ? {
|
|
@@ -4449,9 +4705,9 @@ function monitorInbound(conn) {
|
|
|
4449
4705
|
});
|
|
4450
4706
|
console.error(`[whatsapp-reaction] op=subscribed account=${conn.platformAccountId}`);
|
|
4451
4707
|
sock.ev.on("messages.reaction", async (reactions) => {
|
|
4452
|
-
for (const
|
|
4708
|
+
for (const entry2 of reactions) {
|
|
4453
4709
|
try {
|
|
4454
|
-
const sig = readReactionEntry(
|
|
4710
|
+
const sig = readReactionEntry(entry2);
|
|
4455
4711
|
if (!sig) continue;
|
|
4456
4712
|
if (sig.fromMe) continue;
|
|
4457
4713
|
const reactorTelephone = await resolveJidToE164(sig.reactorJid, conn.lidMapping) ?? sig.reactorJid;
|
|
@@ -4609,6 +4865,9 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4609
4865
|
sendReadReceipt(conn.sock, remoteJid, [msg.key.id], isGroup ? senderJid : void 0, conn.accountId);
|
|
4610
4866
|
}
|
|
4611
4867
|
let mediaResult;
|
|
4868
|
+
if (extracted.mediaType && extracted.mediaType !== "audio") {
|
|
4869
|
+
onMediaStanza?.(senderPhone, Date.now());
|
|
4870
|
+
}
|
|
4612
4871
|
if (extracted.mediaType && conn.sock) {
|
|
4613
4872
|
const maxMb = whatsAppConfig.mediaMaxMb ?? 50;
|
|
4614
4873
|
mediaResult = await downloadInboundMedia(msg, conn.sock, {
|
|
@@ -4619,8 +4878,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4619
4878
|
}
|
|
4620
4879
|
}
|
|
4621
4880
|
if (extracted.mediaType === "audio" && mediaResult?.path) {
|
|
4622
|
-
const
|
|
4623
|
-
const debounceKey = `${conn.accountId}:${
|
|
4881
|
+
const conversationKey2 = isGroup ? remoteJid : senderPhone;
|
|
4882
|
+
const debounceKey = `${conn.accountId}:${conversationKey2}:${senderPhone}`;
|
|
4624
4883
|
let resolvePending;
|
|
4625
4884
|
const sttPending = new Promise((resolve6) => {
|
|
4626
4885
|
resolvePending = resolve6;
|
|
@@ -4751,7 +5010,6 @@ export {
|
|
|
4751
5010
|
normalizeE164,
|
|
4752
5011
|
toWhatsappJid,
|
|
4753
5012
|
jidToE164,
|
|
4754
|
-
senderJidFromTelephone,
|
|
4755
5013
|
isGroupJid,
|
|
4756
5014
|
isUserJid,
|
|
4757
5015
|
normalizeTarget,
|
|
@@ -4762,6 +5020,7 @@ export {
|
|
|
4762
5020
|
managerPhonesForAccount,
|
|
4763
5021
|
isAdminPhone,
|
|
4764
5022
|
shouldDispatchInbound,
|
|
5023
|
+
formatSenderPhone,
|
|
4765
5024
|
checkAccessRateLimit,
|
|
4766
5025
|
recordAccessFailedAttempt,
|
|
4767
5026
|
clearAccessRateLimit,
|
|
@@ -4780,10 +5039,6 @@ export {
|
|
|
4780
5039
|
sendComposing,
|
|
4781
5040
|
sendPaused,
|
|
4782
5041
|
sendMediaMessage,
|
|
4783
|
-
resolvePlatformAccountId,
|
|
4784
|
-
warnNonUuidAccount,
|
|
4785
|
-
isHouseManagedService,
|
|
4786
|
-
isCustomerTurnSuppressed,
|
|
4787
5042
|
DATA_ROOT,
|
|
4788
5043
|
crossesForeignAccountPartition,
|
|
4789
5044
|
isWithinOwnAccountPartition,
|
|
@@ -4791,6 +5046,13 @@ export {
|
|
|
4791
5046
|
resolveClaudeUploadsPath,
|
|
4792
5047
|
sessionScratchpadRoot,
|
|
4793
5048
|
resolveScratchpadPath,
|
|
5049
|
+
readChatMetadata,
|
|
5050
|
+
writeChatMetadataMerged,
|
|
5051
|
+
groupEntriesFromUpdates,
|
|
5052
|
+
resolvePlatformAccountId,
|
|
5053
|
+
warnNonUuidAccount,
|
|
5054
|
+
isHouseManagedService,
|
|
5055
|
+
isCustomerTurnSuppressed,
|
|
4794
5056
|
SUPPORTED_MIME_TYPES,
|
|
4795
5057
|
MAX_FILE_SIZE_BYTES,
|
|
4796
5058
|
MAX_FILES_PER_MESSAGE,
|
|
@@ -4833,5 +5095,6 @@ export {
|
|
|
4833
5095
|
getMessages,
|
|
4834
5096
|
listConversationJids,
|
|
4835
5097
|
listStoreAccountKeys,
|
|
4836
|
-
shutdown
|
|
5098
|
+
shutdown,
|
|
5099
|
+
listConnections
|
|
4837
5100
|
};
|