@rubytech/create-sitedesk-code 0.1.522 → 0.1.523
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +28 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/caption-coverage.test.ts +7 -0
- package/payload/platform/lib/graph-style/src/index.ts +24 -0
- package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.js.map +1 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts +16 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +83 -6
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +117 -10
- package/payload/platform/lib/routine-templates/dist/index.d.ts +151 -0
- package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/index.js +207 -0
- package/payload/platform/lib/routine-templates/dist/index.js.map +1 -0
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +57 -0
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/roster.js +182 -0
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts +2 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.js +64 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.js.map +1 -0
- package/payload/platform/lib/routine-templates/package.json +6 -0
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +170 -0
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +298 -0
- package/payload/platform/lib/routine-templates/src/index.ts +299 -0
- package/payload/platform/lib/routine-templates/src/roster.ts +206 -0
- package/payload/platform/lib/routine-templates/src/seed-cli.ts +65 -0
- package/payload/platform/lib/routine-templates/tsconfig.json +9 -0
- package/payload/platform/lib/routine-templates/vitest.config.ts +9 -0
- package/payload/platform/neo4j/edge-annotations.json +2 -2
- package/payload/platform/neo4j/schema.cypher +25 -1
- package/payload/platform/package.json +3 -2
- package/payload/platform/plugins/admin/PLUGIN.md +2 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +39 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +277 -61
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +265 -59
- package/payload/platform/plugins/docs/references/memory-guide.md +11 -1
- package/payload/platform/plugins/graph/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/graph/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +12 -5
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js +197 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +55 -9
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +96 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +7 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts +29 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js +126 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js +7 -4
- package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +18 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +7 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +4 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
- package/payload/platform/plugins/memory/references/schema-estate-agent.md +2 -2
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +4 -4
- package/payload/platform/plugins/quickbooks/PLUGIN.md +10 -10
- package/payload/platform/plugins/scheduling/PLUGIN.md +49 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +48 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js +78 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js +457 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts +35 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js +39 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +175 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js +533 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +123 -9
- 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__/routine-roster-audit.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +189 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +95 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js +114 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +109 -2
- 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 +340 -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.d.ts +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +210 -45
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +43 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js +55 -7
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js +45 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js +96 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +2 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts +5 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +13 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +24 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts +33 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js +51 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js.map +1 -0
- 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 +12 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +30 -2
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
- package/payload/platform/scripts/check-specialist-tool-surface.mjs +92 -16
- package/payload/platform/scripts/seed-neo4j.sh +41 -0
- package/payload/platform/scripts/verify-skill-tool-surface.sh +91 -2
- 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/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-K7CJGZPU.js → chunk-VUXKXOJU.js} +342 -152
- package/payload/server/{chunk-UX2FRNO7.js → chunk-WT2PFGY4.js} +37 -265
- package/payload/server/{chunk-PXNY2TAP.js → chunk-XCR5D2G3.js} +239 -10
- package/payload/server/{manager-RKL7JZ4Y.js → manager-4TJK3YOY.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-zc2_qqh-.js → AdminLoginScreens-uknqh2Pm.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js +2 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js.br +0 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js.gz +0 -0
- package/payload/server/public/assets/{activity-DVgO8YuM.js → activity-B4KfMJqO.js} +1 -1
- package/payload/server/public/assets/activity-B4KfMJqO.js.br +0 -0
- package/payload/server/public/assets/activity-B4KfMJqO.js.gz +0 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js +1 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js.br +0 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js.gz +0 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js +1 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js.br +0 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js.gz +0 -0
- package/payload/server/public/assets/{browser-Mw7DY3ft.js → browser-B3hSzI3O.js} +1 -1
- package/payload/server/public/assets/browser-B3hSzI3O.js.br +0 -0
- package/payload/server/public/assets/browser-B3hSzI3O.js.gz +0 -0
- package/payload/server/public/assets/{calendar-B9gvL_1_.js → calendar-BggxXxhS.js} +1 -1
- package/payload/server/public/assets/calendar-BggxXxhS.js.br +0 -0
- package/payload/server/public/assets/calendar-BggxXxhS.js.gz +0 -0
- package/payload/server/public/assets/chat-flivHt0t.js +1 -0
- package/payload/server/public/assets/chat-flivHt0t.js.br +0 -0
- package/payload/server/public/assets/chat-flivHt0t.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-nVRThX7f.js +1 -0
- package/payload/server/public/assets/chevron-right-CLqfrkRA.js +1 -0
- package/payload/server/public/assets/chevron-right-CLqfrkRA.js.br +0 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js +1 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js.br +0 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js.gz +0 -0
- package/payload/server/public/assets/data-Ckjkne54.js +1 -0
- package/payload/server/public/assets/data-Ckjkne54.js.br +3 -0
- package/payload/server/public/assets/data-Ckjkne54.js.gz +0 -0
- package/payload/server/public/assets/{file-text-dYBnXNEX.js → file-text-BKs9eyiw.js} +1 -1
- package/payload/server/public/assets/file-text-BKs9eyiw.js.br +0 -0
- package/payload/server/public/assets/file-text-BKs9eyiw.js.gz +0 -0
- package/payload/server/public/assets/{graph-CDyzd1Et.js → graph-DTi71NaZ.js} +3 -3
- package/payload/server/public/assets/graph-DTi71NaZ.js.br +0 -0
- package/payload/server/public/assets/graph-DTi71NaZ.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js +1 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js.br +0 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-M-iSaznd.js → maximize-2-zC94tsxY.js} +1 -1
- package/payload/server/public/assets/maximize-2-zC94tsxY.js.br +0 -0
- package/payload/server/public/assets/maximize-2-zC94tsxY.js.gz +0 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js +1 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js.br +0 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js.gz +0 -0
- package/payload/server/public/assets/page-BFm91p0e.js +1 -0
- package/payload/server/public/assets/page-BFm91p0e.js.br +0 -0
- package/payload/server/public/assets/page-BFm91p0e.js.gz +0 -0
- package/payload/server/public/assets/{page-CZ-73FAk.js → page-Ccl0FazM.js} +3 -3
- package/payload/server/public/assets/page-Ccl0FazM.js.br +0 -0
- package/payload/server/public/assets/page-Ccl0FazM.js.gz +0 -0
- package/payload/server/public/assets/{public-CN-ltC8x.js → public-BpC6cn9S.js} +1 -1
- package/payload/server/public/assets/public-BpC6cn9S.js.br +0 -0
- package/payload/server/public/assets/public-BpC6cn9S.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-Buopsc22.js → rotate-ccw-BNcqbHkZ.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.gz +0 -0
- package/payload/server/public/assets/routines-D5iia-XG.js +1 -0
- package/payload/server/public/assets/routines-D5iia-XG.js.br +0 -0
- package/payload/server/public/assets/routines-D5iia-XG.js.gz +0 -0
- package/payload/server/public/assets/{skills-DiiuVzDK.js → skills-COLAw_jt.js} +1 -1
- package/payload/server/public/assets/skills-COLAw_jt.js.br +0 -0
- package/payload/server/public/assets/skills-COLAw_jt.js.gz +0 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js +1 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js.br +0 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-BBokCF-D.js → time-entry-format-laTFzawg.js} +1 -1
- package/payload/server/public/assets/time-entry-format-laTFzawg.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-laTFzawg.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-C_AcpTW5.js → triangle-alert-DrwqhEog.js} +1 -1
- package/payload/server/public/assets/triangle-alert-DrwqhEog.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-DrwqhEog.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-TdimmPVR.js → useCopyFeedback-Cxme5GK6.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js +14 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-BT2738ZS.js → useVoiceRecorder-DUBpVa2T.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.gz +0 -0
- package/payload/server/public/assets/{wrench-B51s5kGA.js → wrench-DWuxPnzF.js} +1 -1
- package/payload/server/public/assets/wrench-DWuxPnzF.js.br +0 -0
- package/payload/server/public/assets/wrench-DWuxPnzF.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 +5910 -5369
- 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 +0 -2
- 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-DVgO8YuM.js.br +0 -0
- package/payload/server/public/assets/activity-DVgO8YuM.js.gz +0 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js +0 -1
- 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-P0nTIxo-.js +0 -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-Mw7DY3ft.js.br +0 -0
- package/payload/server/public/assets/browser-Mw7DY3ft.js.gz +0 -0
- 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 +0 -1
- package/payload/server/public/assets/chat-DBGqh4wg.js.br +0 -2
- package/payload/server/public/assets/chat-DBGqh4wg.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js +0 -1
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js.br +0 -0
- package/payload/server/public/assets/chevron-right-BExigCnp.js +0 -1
- package/payload/server/public/assets/chevron-right-BExigCnp.js.br +0 -0
- package/payload/server/public/assets/clock-D8TJvgJC.js +0 -1
- package/payload/server/public/assets/clock-D8TJvgJC.js.br +0 -0
- package/payload/server/public/assets/data-HfFSxaC2.js +0 -1
- 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-dYBnXNEX.js.br +0 -0
- package/payload/server/public/assets/file-text-dYBnXNEX.js.gz +0 -0
- 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-D1LkKiJr.js +0 -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-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-9jfCv1Fg.js +0 -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.br +0 -0
- package/payload/server/public/assets/page-CZ-73FAk.js.gz +0 -0
- package/payload/server/public/assets/page-CjwSt7kx.js +0 -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-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-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 +0 -1
- 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.br +0 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js.gz +0 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js +0 -1
- 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-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-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-TdimmPVR.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js +0 -14
- 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 +0 -1
- 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-BT2738ZS.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.gz +0 -0
- package/payload/server/public/assets/wrench-B51s5kGA.js.br +0 -0
- package/payload/server/public/assets/wrench-B51s5kGA.js.gz +0 -0
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
ensureConversation,
|
|
7
7
|
getSession,
|
|
8
8
|
getUserTimezone,
|
|
9
|
-
isValidAccountId
|
|
10
|
-
|
|
9
|
+
isValidAccountId,
|
|
10
|
+
registerLoop
|
|
11
|
+
} from "./chunk-XCR5D2G3.js";
|
|
11
12
|
|
|
12
13
|
// app/lib/whatsapp/schema.ts
|
|
13
14
|
import { z } from "zod";
|
|
@@ -257,7 +258,6 @@ import { inspect } from "util";
|
|
|
257
258
|
import {
|
|
258
259
|
Browsers,
|
|
259
260
|
DisconnectReason,
|
|
260
|
-
fetchLatestBaileysVersion,
|
|
261
261
|
makeCacheableSignalKeyStore,
|
|
262
262
|
makeWASocket,
|
|
263
263
|
useMultiFileAuthState
|
|
@@ -318,6 +318,18 @@ function resolveDebugWindow(authDir, nowMs = Date.now()) {
|
|
|
318
318
|
return state;
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
+
// app/lib/whatsapp/companion-reg.ts
|
|
322
|
+
var PRIMARY_IDENTITY_PUB = "primary_identity_pub";
|
|
323
|
+
function classifyCompanionReg(node) {
|
|
324
|
+
const outer = node?.content;
|
|
325
|
+
const child = Array.isArray(outer) ? outer.find((c) => c?.tag === "link_code_companion_reg") : void 0;
|
|
326
|
+
const rawStage = child?.attrs?.stage;
|
|
327
|
+
const stage = typeof rawStage === "string" && rawStage ? rawStage : "absent";
|
|
328
|
+
const inner = child?.content;
|
|
329
|
+
const children = Array.isArray(inner) ? inner.map((c) => c?.tag).filter((t) => typeof t === "string") : [];
|
|
330
|
+
return { stage, children, parseable: children.includes(PRIMARY_IDENTITY_PUB) };
|
|
331
|
+
}
|
|
332
|
+
|
|
321
333
|
// app/lib/whatsapp/ingest-ledger.ts
|
|
322
334
|
import { existsSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, readdirSync } from "fs";
|
|
323
335
|
import { join } from "path";
|
|
@@ -471,8 +483,102 @@ function listLedgerAccounts() {
|
|
|
471
483
|
}
|
|
472
484
|
}
|
|
473
485
|
|
|
486
|
+
// app/lib/whatsapp/version-census.ts
|
|
487
|
+
import { DEFAULT_CONNECTION_CONFIG, fetchLatestBaileysVersion } from "@whiskeysockets/baileys";
|
|
488
|
+
var TAG4 = "[whatsapp:version]";
|
|
489
|
+
var BAILEYS_VERSION_URL = "https://raw.githubusercontent.com/WhiskeySockets/Baileys/master/src/Defaults/index.ts";
|
|
490
|
+
var VERSION_RE = /const version = \[(\d+),\s*(\d+),\s*(\d+)\]/;
|
|
491
|
+
var presented = /* @__PURE__ */ new Map();
|
|
492
|
+
var behindSince = null;
|
|
493
|
+
function packagedVersion() {
|
|
494
|
+
return DEFAULT_CONNECTION_CONFIG.version.join(".");
|
|
495
|
+
}
|
|
496
|
+
function messageOf(err) {
|
|
497
|
+
return err instanceof Error ? err.message : String(err);
|
|
498
|
+
}
|
|
499
|
+
var PROBE_TIMEOUT_MS = 5e3;
|
|
500
|
+
async function probeSourceAge(fetchImpl) {
|
|
501
|
+
const none = (probe) => ({ sourceAgeSec: null, edge: null, probe });
|
|
502
|
+
try {
|
|
503
|
+
const res = await fetchImpl(BAILEYS_VERSION_URL, {
|
|
504
|
+
method: "HEAD",
|
|
505
|
+
signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
|
|
506
|
+
});
|
|
507
|
+
if (!res.ok) return none(`http-${res.status}`);
|
|
508
|
+
const header = res.headers.get("age") !== null ? "age" : "source-age";
|
|
509
|
+
const raw = res.headers.get(header);
|
|
510
|
+
const n = raw === null ? Number.NaN : Number.parseInt(raw, 10);
|
|
511
|
+
if (!Number.isFinite(n)) return none("no-header");
|
|
512
|
+
return { sourceAgeSec: n, edge: res.headers.get("x-served-by"), probe: header };
|
|
513
|
+
} catch (err) {
|
|
514
|
+
return none(err instanceof Error && err.name === "TimeoutError" ? "timeout" : "net-error");
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
async function resolveWaVersion(opts) {
|
|
518
|
+
const { account } = opts;
|
|
519
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
520
|
+
const fetchVersion = opts.fetchVersion ?? fetchLatestBaileysVersion;
|
|
521
|
+
const now = opts.now ?? Date.now;
|
|
522
|
+
const timed = (async () => {
|
|
523
|
+
const t0 = now();
|
|
524
|
+
const r2 = await fetchVersion();
|
|
525
|
+
return { r: r2, ms: now() - t0 };
|
|
526
|
+
})();
|
|
527
|
+
const [{ r, ms }, probe] = await Promise.all([timed, probeSourceAge(fetchImpl)]);
|
|
528
|
+
const err = r.error;
|
|
529
|
+
const origin = r.isLatest === false || err !== void 0 ? "packaged-fallback" : "fetched";
|
|
530
|
+
const versionStr = r.version.join(".");
|
|
531
|
+
const packaged = packagedVersion();
|
|
532
|
+
presented.set(account, versionStr);
|
|
533
|
+
console.error(
|
|
534
|
+
`${TAG4} op=resolve account=${account} version=${versionStr} origin=${origin} sourceAgeSec=${probe.sourceAgeSec ?? "unknown"} probe=${probe.probe} edge=${probe.edge ?? "unknown"} packaged=${packaged} matchesPackaged=${versionStr === packaged} fetchMs=${ms} error=${err === void 0 ? "none" : `"${messageOf(err)}"`}`
|
|
535
|
+
);
|
|
536
|
+
return { version: r.version };
|
|
537
|
+
}
|
|
538
|
+
var CENSUS_INTERVAL_MS = 15 * 60 * 1e3;
|
|
539
|
+
async function runVersionDriftCensus(opts = {}) {
|
|
540
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
541
|
+
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
542
|
+
let upstream = null;
|
|
543
|
+
let reason = "net-error";
|
|
544
|
+
try {
|
|
545
|
+
const res = await fetchImpl(BAILEYS_VERSION_URL);
|
|
546
|
+
if (!res.ok) {
|
|
547
|
+
reason = `http-${res.status}`;
|
|
548
|
+
} else {
|
|
549
|
+
const m = VERSION_RE.exec(await res.text());
|
|
550
|
+
if (m) upstream = `${m[1]}.${m[2]}.${m[3]}`;
|
|
551
|
+
else reason = "parse-failed";
|
|
552
|
+
}
|
|
553
|
+
} catch {
|
|
554
|
+
upstream = null;
|
|
555
|
+
reason = "net-error";
|
|
556
|
+
}
|
|
557
|
+
const distinct = [...new Set(presented.values())].sort();
|
|
558
|
+
const presentedStr = distinct.length === 0 ? "none" : distinct.join(",");
|
|
559
|
+
if (upstream !== null && distinct.length > 0) {
|
|
560
|
+
if (distinct.some((v) => v !== upstream)) {
|
|
561
|
+
if (behindSince === null) behindSince = now().toISOString();
|
|
562
|
+
} else {
|
|
563
|
+
behindSince = null;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
console.error(
|
|
567
|
+
`${TAG4} op=drift-census presented=${presentedStr} upstream=${upstream ?? reason} behindSince=${behindSince ?? "none"}`
|
|
568
|
+
);
|
|
569
|
+
return `presented=${presentedStr} upstream=${upstream ?? reason}`;
|
|
570
|
+
}
|
|
571
|
+
function startVersionDriftCensus(intervalMs = CENSUS_INTERVAL_MS) {
|
|
572
|
+
return registerLoop({
|
|
573
|
+
name: "whatsapp-version-drift",
|
|
574
|
+
intervalMs,
|
|
575
|
+
firstRunDelayMs: 0,
|
|
576
|
+
run: () => runVersionDriftCensus()
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
474
580
|
// app/lib/whatsapp/session.ts
|
|
475
|
-
var
|
|
581
|
+
var TAG5 = "[whatsapp:session]";
|
|
476
582
|
var WIRE_TAG = "[whatsapp:wire]";
|
|
477
583
|
var baileysPkgVersion = (() => {
|
|
478
584
|
try {
|
|
@@ -482,7 +588,7 @@ var baileysPkgVersion = (() => {
|
|
|
482
588
|
return "unknown";
|
|
483
589
|
}
|
|
484
590
|
})();
|
|
485
|
-
console.error(`${
|
|
591
|
+
console.error(`${TAG5} baileys package loaded version=${baileysPkgVersion}`);
|
|
486
592
|
var __BAILEYS_TAG = "[whatsapp:baileys]";
|
|
487
593
|
var INSPECT_OPTS = {
|
|
488
594
|
depth: null,
|
|
@@ -543,7 +649,7 @@ function createBaileysLogger(bindings = {}, authDir) {
|
|
|
543
649
|
}
|
|
544
650
|
var credsSaveQueue = Promise.resolve();
|
|
545
651
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
546
|
-
console.error(`${
|
|
652
|
+
console.error(`${TAG5} draining credential save queue\u2026`);
|
|
547
653
|
const timer = new Promise(
|
|
548
654
|
(resolve6) => setTimeout(() => resolve6("timeout"), timeoutMs)
|
|
549
655
|
);
|
|
@@ -552,9 +658,9 @@ async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
|
552
658
|
timer
|
|
553
659
|
]);
|
|
554
660
|
if (result === "timeout") {
|
|
555
|
-
console.error(`${
|
|
661
|
+
console.error(`${TAG5} credential save queue drain timed out after ${timeoutMs}ms`);
|
|
556
662
|
} else {
|
|
557
|
-
console.error(`${
|
|
663
|
+
console.error(`${TAG5} credential save queue drained`);
|
|
558
664
|
}
|
|
559
665
|
}
|
|
560
666
|
function readCredsJsonRaw2(filePath) {
|
|
@@ -577,11 +683,11 @@ async function safeSaveCreds(authDir, saveCreds) {
|
|
|
577
683
|
JSON.parse(raw);
|
|
578
684
|
fsSync2.copyFileSync(credsPath, backupPath);
|
|
579
685
|
} catch (err) {
|
|
580
|
-
console.warn(`${
|
|
686
|
+
console.warn(`${TAG5} backup pre-copy failed (parse or write) authDir=${authDir}: ${String(err)}`);
|
|
581
687
|
}
|
|
582
688
|
}
|
|
583
689
|
} catch (err) {
|
|
584
|
-
console.warn(`${
|
|
690
|
+
console.warn(`${TAG5} backup preparation failed authDir=${authDir}: ${String(err)}`);
|
|
585
691
|
}
|
|
586
692
|
try {
|
|
587
693
|
await Promise.resolve(saveCreds());
|
|
@@ -589,39 +695,39 @@ async function safeSaveCreds(authDir, saveCreds) {
|
|
|
589
695
|
try {
|
|
590
696
|
const stats = await fs3.stat(credsPath);
|
|
591
697
|
if (stats.size <= 1) {
|
|
592
|
-
console.error(`${
|
|
698
|
+
console.error(`${TAG5} WARNING: creds file empty/truncated after save path=${credsPath} size=${stats.size}`);
|
|
593
699
|
} else {
|
|
594
|
-
console.error(`${
|
|
700
|
+
console.error(`${TAG5} creds saved and verified path=${credsPath} size=${stats.size}`);
|
|
595
701
|
}
|
|
596
702
|
} catch (statErr) {
|
|
597
|
-
console.error(`${
|
|
703
|
+
console.error(`${TAG5} creds NOT found on disk after save path=${credsPath}: ${String(statErr)}`);
|
|
598
704
|
}
|
|
599
705
|
} catch (err) {
|
|
600
|
-
console.error(`${
|
|
706
|
+
console.error(`${TAG5} failed saving creds to ${authDir}: ${String(err)}`);
|
|
601
707
|
}
|
|
602
708
|
}
|
|
603
709
|
function enqueueSaveCreds(authDir, saveCreds) {
|
|
604
710
|
credsSaveQueue = credsSaveQueue.then(() => safeSaveCreds(authDir, saveCreds)).catch((err) => {
|
|
605
|
-
console.error(`${
|
|
711
|
+
console.error(`${TAG5} creds save queue error: ${String(err)}`);
|
|
606
712
|
});
|
|
607
713
|
}
|
|
608
714
|
async function createWaSocket(opts) {
|
|
609
|
-
const { authDir, onQr, onConnectionUpdate, silent, correlationId, account, getCodeIssuedTs } = opts;
|
|
715
|
+
const { authDir, onQr, onConnectionUpdate, silent, correlationId, account, getCodeIssuedTs, onCompanionReg } = opts;
|
|
610
716
|
const cid = correlationId ?? "none";
|
|
611
717
|
const acct = account ?? "unknown";
|
|
612
718
|
await fs3.mkdir(authDir, { recursive: true });
|
|
613
719
|
maybeRestoreCredsFromBackup(authDir);
|
|
614
720
|
const { state, saveCreds } = await useMultiFileAuthState(authDir);
|
|
615
|
-
const { version } = await
|
|
721
|
+
const { version } = await resolveWaVersion({ account: acct });
|
|
616
722
|
if (!silent) {
|
|
617
723
|
const preCensus = credsCensus(authDir);
|
|
618
724
|
console.error(
|
|
619
|
-
`${
|
|
725
|
+
`${TAG5} op=creds-pre cid=${cid} account=${acct} credsPresent=${preCensus.credsPresent} registered=${preCensus.registered} hasAccount=${preCensus.hasAccountSignature}`
|
|
620
726
|
);
|
|
621
727
|
}
|
|
622
728
|
const openTs = Date.now();
|
|
623
729
|
console.error(
|
|
624
|
-
`${
|
|
730
|
+
`${TAG5} op=socket-open cid=${cid} account=${acct} baileysVersion=${baileysPkgVersion} waProtocolVersion=${version.join(".")} openTs=${openTs}`
|
|
625
731
|
);
|
|
626
732
|
const baileysLogger = createBaileysLogger({}, authDir);
|
|
627
733
|
const sock = makeWASocket({
|
|
@@ -638,7 +744,7 @@ async function createWaSocket(opts) {
|
|
|
638
744
|
fireInitQueries: false
|
|
639
745
|
});
|
|
640
746
|
sock.ev.on("creds.update", () => {
|
|
641
|
-
console.error(`${
|
|
747
|
+
console.error(`${TAG5} creds.update received \u2014 saving to ${authDir}`);
|
|
642
748
|
enqueueSaveCreds(authDir, saveCreds);
|
|
643
749
|
});
|
|
644
750
|
let qrSequence = 0;
|
|
@@ -658,14 +764,14 @@ async function createWaSocket(opts) {
|
|
|
658
764
|
parts.push(`disconnectReason=${formatError(update.lastDisconnect.error)}`);
|
|
659
765
|
}
|
|
660
766
|
if (!silent && parts.length > 0) {
|
|
661
|
-
console.error(`${
|
|
767
|
+
console.error(`${TAG5} connection.update ${parts.join(" ")}`);
|
|
662
768
|
}
|
|
663
769
|
if (update.qr && !silent) {
|
|
664
770
|
const now = Date.now();
|
|
665
771
|
const sinceLastRefMs = lastQrTs ? now - lastQrTs : null;
|
|
666
772
|
lastQrTs = now;
|
|
667
773
|
console.error(
|
|
668
|
-
`${
|
|
774
|
+
`${TAG5} op=qr cid=${cid} qr=#${qrSequence} sinceOpenMs=${now - openTs} sinceLastRefMs=${sinceLastRefMs ?? "n/a"}`
|
|
669
775
|
);
|
|
670
776
|
}
|
|
671
777
|
if (update.isNewLogin === true && !pairSuccessLogged && !silent) {
|
|
@@ -674,7 +780,7 @@ async function createWaSocket(opts) {
|
|
|
674
780
|
const sinceCodeIssuedMs = codeIssuedTs ? Date.now() - codeIssuedTs : null;
|
|
675
781
|
const afterCensus = credsCensus(authDir);
|
|
676
782
|
console.error(
|
|
677
|
-
`${
|
|
783
|
+
`${TAG5} op=pair-success cid=${cid} account=${acct} sinceCodeIssuedMs=${sinceCodeIssuedMs ?? "n/a"} hasAccountAfter=${afterCensus.hasAccountSignature}`
|
|
678
784
|
);
|
|
679
785
|
}
|
|
680
786
|
if (update.qr && onQr) {
|
|
@@ -684,25 +790,25 @@ async function createWaSocket(opts) {
|
|
|
684
790
|
const status = getStatusCode(update.lastDisconnect?.error);
|
|
685
791
|
if (!silent) {
|
|
686
792
|
console.error(
|
|
687
|
-
`${
|
|
793
|
+
`${TAG5} op=close cid=${cid} account=${acct} status=${status ?? "unknown"} reason="${formatError(update.lastDisconnect?.error)}" socketLifeMs=${Date.now() - openTs} kind=${closeKind(status, everOpen)}`
|
|
688
794
|
);
|
|
689
795
|
}
|
|
690
796
|
if (status === DisconnectReason.loggedOut && !silent) {
|
|
691
|
-
console.error(`${
|
|
797
|
+
console.error(`${TAG5} session logged out (401) \u2014 re-link required`);
|
|
692
798
|
}
|
|
693
799
|
}
|
|
694
800
|
if (update.connection === "open") {
|
|
695
801
|
everOpen = true;
|
|
696
|
-
if (!silent) console.error(`${
|
|
802
|
+
if (!silent) console.error(`${TAG5} connected`);
|
|
697
803
|
}
|
|
698
804
|
onConnectionUpdate?.(update);
|
|
699
805
|
} catch (err) {
|
|
700
|
-
console.error(`${
|
|
806
|
+
console.error(`${TAG5} connection.update handler error: ${String(err)}`);
|
|
701
807
|
}
|
|
702
808
|
});
|
|
703
809
|
if (sock.ws && typeof sock.ws.on === "function") {
|
|
704
810
|
sock.ws.on("error", (err) => {
|
|
705
|
-
console.error(`${
|
|
811
|
+
console.error(`${TAG5} WebSocket error: ${String(err)}`);
|
|
706
812
|
});
|
|
707
813
|
sock.ws.on("CB:message", (node) => {
|
|
708
814
|
const attrs = node?.attrs ?? {};
|
|
@@ -718,6 +824,21 @@ async function createWaSocket(opts) {
|
|
|
718
824
|
});
|
|
719
825
|
}
|
|
720
826
|
});
|
|
827
|
+
if (!silent) {
|
|
828
|
+
sock.ws.on("CB:notification,type:link_code_companion_reg", (node) => {
|
|
829
|
+
try {
|
|
830
|
+
const census = classifyCompanionReg(node);
|
|
831
|
+
console.error(
|
|
832
|
+
`${TAG5} op=companion-reg cid=${cid} account=${acct} stage=${census.stage} children=${census.children.join(",") || "none"} parseable=${census.parseable}`
|
|
833
|
+
);
|
|
834
|
+
onCompanionReg?.(census);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
console.error(
|
|
837
|
+
`${TAG5} op=companion-reg-observer-error cid=${cid} account=${acct} err=${String(err)}`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
}
|
|
721
842
|
}
|
|
722
843
|
return sock;
|
|
723
844
|
}
|
|
@@ -826,6 +947,26 @@ function computeBackoff(attempt, config = {}) {
|
|
|
826
947
|
return Math.round(jitter);
|
|
827
948
|
}
|
|
828
949
|
|
|
950
|
+
// app/lib/whatsapp/link-census.ts
|
|
951
|
+
var HEALTH_TAG = "[whatsapp-health]";
|
|
952
|
+
var LINK_CENSUS_INTERVAL_MS = 15 * 6e4;
|
|
953
|
+
function downMsFor(row, now) {
|
|
954
|
+
if (row.connected) return "0";
|
|
955
|
+
if (row.lastConnectedAt === void 0) return "unknown";
|
|
956
|
+
return String(now - row.lastConnectedAt);
|
|
957
|
+
}
|
|
958
|
+
function linkCensusLines(rows, now) {
|
|
959
|
+
if (rows.length === 0) return [`${HEALTH_TAG} op=link-census accounts=0`];
|
|
960
|
+
return rows.map(
|
|
961
|
+
(row) => `${HEALTH_TAG} op=link-census account=${row.accountId} connected=${row.connected} stuck=${Boolean(row.sessionStuckReason)} downMs=${downMsFor(row, now)} lastError=${row.lastError ?? "none"}`
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
function runLinkCensus(read, now) {
|
|
965
|
+
const rows = read();
|
|
966
|
+
for (const line of linkCensusLines(rows, now)) console.error(line);
|
|
967
|
+
return rows.length;
|
|
968
|
+
}
|
|
969
|
+
|
|
829
970
|
// app/lib/whatsapp/init-queries.ts
|
|
830
971
|
import { inspect as inspect2 } from "util";
|
|
831
972
|
|
|
@@ -855,7 +996,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
855
996
|
}
|
|
856
997
|
|
|
857
998
|
// app/lib/whatsapp/init-queries.ts
|
|
858
|
-
var
|
|
999
|
+
var TAG6 = "[whatsapp:init]";
|
|
859
1000
|
var DEFAULT_QUERY_TIMEOUT_MS = 15e3;
|
|
860
1001
|
var INSPECT_OPTS2 = {
|
|
861
1002
|
depth: null,
|
|
@@ -883,20 +1024,20 @@ async function runInitQueries(sock, ctx) {
|
|
|
883
1024
|
elapsedMs: 0
|
|
884
1025
|
};
|
|
885
1026
|
console.error(
|
|
886
|
-
`${
|
|
1027
|
+
`${TAG6} runInitQueries start account=${ctx.accountId} attempt=${ctx.attempt} selfPhone=${ctx.selfPhone ?? "unknown"} authDir=${ctx.authDir} queryTimeoutMs=${queryTimeoutMs}`
|
|
887
1028
|
);
|
|
888
1029
|
console.error(
|
|
889
|
-
`${
|
|
1030
|
+
`${TAG6} fetchProps SKIPPED account=${ctx.accountId} reason=no-platform-consumer`
|
|
890
1031
|
);
|
|
891
1032
|
if (ctx.signal?.aborted) {
|
|
892
1033
|
result.aborted = true;
|
|
893
1034
|
result.elapsedMs = Date.now() - startedAt;
|
|
894
1035
|
console.error(
|
|
895
|
-
`${
|
|
1036
|
+
`${TAG6} runInitQueries aborted before start account=${ctx.accountId}`
|
|
896
1037
|
);
|
|
897
1038
|
return result;
|
|
898
1039
|
}
|
|
899
|
-
console.error(`${
|
|
1040
|
+
console.error(`${TAG6} fetchBlocklist start account=${ctx.accountId}`);
|
|
900
1041
|
try {
|
|
901
1042
|
const blocklist = await withTimeout(
|
|
902
1043
|
"fetchBlocklist",
|
|
@@ -906,24 +1047,24 @@ async function runInitQueries(sock, ctx) {
|
|
|
906
1047
|
const count = Array.isArray(blocklist) ? blocklist.length : 0;
|
|
907
1048
|
result.blocklistOk = true;
|
|
908
1049
|
console.error(
|
|
909
|
-
`${
|
|
1050
|
+
`${TAG6} fetchBlocklist ok account=${ctx.accountId} count=${count}`
|
|
910
1051
|
);
|
|
911
1052
|
} catch (err) {
|
|
912
1053
|
const formatted = formatErr(err);
|
|
913
1054
|
result.errors.blocklist = formatted;
|
|
914
1055
|
console.error(
|
|
915
|
-
`${
|
|
1056
|
+
`${TAG6} fetchBlocklist FAILED account=${ctx.accountId}: ${formatted}`
|
|
916
1057
|
);
|
|
917
1058
|
}
|
|
918
1059
|
if (ctx.signal?.aborted) {
|
|
919
1060
|
result.aborted = true;
|
|
920
1061
|
result.elapsedMs = Date.now() - startedAt;
|
|
921
1062
|
console.error(
|
|
922
|
-
`${
|
|
1063
|
+
`${TAG6} runInitQueries aborted mid-sequence account=${ctx.accountId} after=fetchBlocklist`
|
|
923
1064
|
);
|
|
924
1065
|
return result;
|
|
925
1066
|
}
|
|
926
|
-
console.error(`${
|
|
1067
|
+
console.error(`${TAG6} fetchPrivacySettings start account=${ctx.accountId}`);
|
|
927
1068
|
try {
|
|
928
1069
|
const settings = await withTimeout(
|
|
929
1070
|
"fetchPrivacySettings",
|
|
@@ -933,18 +1074,18 @@ async function runInitQueries(sock, ctx) {
|
|
|
933
1074
|
);
|
|
934
1075
|
result.privacySettingsOk = true;
|
|
935
1076
|
console.error(
|
|
936
|
-
`${
|
|
1077
|
+
`${TAG6} fetchPrivacySettings ok account=${ctx.accountId} keys=${settings ? Object.keys(settings).join(",") : ""}`
|
|
937
1078
|
);
|
|
938
1079
|
} catch (err) {
|
|
939
1080
|
const formatted = formatErr(err);
|
|
940
1081
|
result.errors.privacySettings = formatted;
|
|
941
1082
|
console.error(
|
|
942
|
-
`${
|
|
1083
|
+
`${TAG6} fetchPrivacySettings FAILED account=${ctx.accountId}: ${formatted}`
|
|
943
1084
|
);
|
|
944
1085
|
}
|
|
945
1086
|
result.elapsedMs = Date.now() - startedAt;
|
|
946
1087
|
console.error(
|
|
947
|
-
`${
|
|
1088
|
+
`${TAG6} runInitQueries done account=${ctx.accountId} blocklistOk=${result.blocklistOk} privacySettingsOk=${result.privacySettingsOk} elapsedMs=${result.elapsedMs}`
|
|
948
1089
|
);
|
|
949
1090
|
return result;
|
|
950
1091
|
}
|
|
@@ -1961,7 +2102,7 @@ function isDuplicateInbound(key) {
|
|
|
1961
2102
|
}
|
|
1962
2103
|
|
|
1963
2104
|
// app/lib/whatsapp/inbound/self-chat.ts
|
|
1964
|
-
var
|
|
2105
|
+
var TAG7 = "[whatsapp:self-chat]";
|
|
1965
2106
|
function normalizeJid(jid) {
|
|
1966
2107
|
const m = jid.match(/^(\d+)(?::\d+)?@(s\.whatsapp\.net|lid)$/i);
|
|
1967
2108
|
return m ? `${m[1]}@${m[2].toLowerCase()}` : jid;
|
|
@@ -1981,10 +2122,10 @@ function evaluateSelfChatCommand(input) {
|
|
|
1981
2122
|
const connAtMs = input.lastConnectedAtMs ?? 0;
|
|
1982
2123
|
const msgId = input.msgId ?? "?";
|
|
1983
2124
|
console.error(
|
|
1984
|
-
`${
|
|
2125
|
+
`${TAG7} op=seen account=${input.accountId} msgId=${msgId} tsMs=${tsMs} connAtMs=${connAtMs} fromMe=true`
|
|
1985
2126
|
);
|
|
1986
2127
|
const skip = (reason) => {
|
|
1987
|
-
console.error(`${
|
|
2128
|
+
console.error(`${TAG7} op=skip account=${input.accountId} msgId=${msgId} reason=${reason}`);
|
|
1988
2129
|
return { kind: "skip", reason };
|
|
1989
2130
|
};
|
|
1990
2131
|
if (input.msgId && isAgentSentMessage(input.msgId)) return skip("echo");
|
|
@@ -1992,13 +2133,13 @@ function evaluateSelfChatCommand(input) {
|
|
|
1992
2133
|
if (isDuplicateInbound(`${input.accountId}:${input.remoteJid}:${input.msgId}`)) return skip("duplicate");
|
|
1993
2134
|
if (!input.text) return skip("no-text");
|
|
1994
2135
|
console.error(
|
|
1995
|
-
`${
|
|
2136
|
+
`${TAG7} op=dispatch account=${input.accountId} msgId=${msgId} bytes=${Buffer.byteLength(input.text, "utf8")} agentType=admin`
|
|
1996
2137
|
);
|
|
1997
2138
|
return { kind: "dispatch", text: input.text };
|
|
1998
2139
|
}
|
|
1999
2140
|
|
|
2000
2141
|
// app/lib/whatsapp/activity.ts
|
|
2001
|
-
var
|
|
2142
|
+
var TAG8 = "[whatsapp:activity]";
|
|
2002
2143
|
var RECENT_EVENTS_MAX = 200;
|
|
2003
2144
|
var counters = /* @__PURE__ */ new Map();
|
|
2004
2145
|
var recentEvents = [];
|
|
@@ -2026,10 +2167,10 @@ function recordActivity(event) {
|
|
|
2026
2167
|
recentEvents.splice(0, recentEvents.length - RECENT_EVENTS_MAX);
|
|
2027
2168
|
}
|
|
2028
2169
|
console.error(
|
|
2029
|
-
`${
|
|
2170
|
+
`${TAG8} channel-activity: direction=${direction} account=${accountId} jid=${jid}` + (messageType ? ` type=${messageType}` : "")
|
|
2030
2171
|
);
|
|
2031
2172
|
} catch (err) {
|
|
2032
|
-
console.error(`${
|
|
2173
|
+
console.error(`${TAG8} recording failed: ${String(err)}`);
|
|
2033
2174
|
}
|
|
2034
2175
|
}
|
|
2035
2176
|
function getChannelActivity(accountId) {
|
|
@@ -2050,7 +2191,7 @@ function getChannelActivity(accountId) {
|
|
|
2050
2191
|
}
|
|
2051
2192
|
|
|
2052
2193
|
// app/lib/whatsapp/outbound/send.ts
|
|
2053
|
-
var
|
|
2194
|
+
var TAG9 = "[whatsapp:outbound]";
|
|
2054
2195
|
function buildQuoted(q) {
|
|
2055
2196
|
return {
|
|
2056
2197
|
key: {
|
|
@@ -2071,14 +2212,14 @@ async function sendTextMessage(sock, to, text, opts) {
|
|
|
2071
2212
|
const messageId = result?.key?.id;
|
|
2072
2213
|
if (messageId) {
|
|
2073
2214
|
trackAgentSentMessage(messageId);
|
|
2074
|
-
console.error(`${
|
|
2215
|
+
console.error(`${TAG9} sent text to=${jid} id=${messageId}`);
|
|
2075
2216
|
}
|
|
2076
2217
|
if (opts?.accountId) {
|
|
2077
2218
|
recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: "text" });
|
|
2078
2219
|
}
|
|
2079
2220
|
return { success: true, messageId: messageId ?? void 0 };
|
|
2080
2221
|
} catch (err) {
|
|
2081
|
-
console.error(`${
|
|
2222
|
+
console.error(`${TAG9} send failed to=${to}: ${String(err)}`);
|
|
2082
2223
|
return { success: false, error: String(err) };
|
|
2083
2224
|
}
|
|
2084
2225
|
}
|
|
@@ -2155,20 +2296,20 @@ async function sendMediaMessage(sock, to, media, opts) {
|
|
|
2155
2296
|
const messageId = result?.key?.id;
|
|
2156
2297
|
if (messageId) {
|
|
2157
2298
|
trackAgentSentMessage(messageId);
|
|
2158
|
-
console.error(`${
|
|
2299
|
+
console.error(`${TAG9} sent ${media.type} to=${jid} id=${messageId}`);
|
|
2159
2300
|
}
|
|
2160
2301
|
if (opts?.accountId) {
|
|
2161
2302
|
recordActivity({ accountId: opts.accountId, direction: "outbound", jid, messageType: media.type });
|
|
2162
2303
|
}
|
|
2163
2304
|
return { success: true, messageId: messageId ?? void 0 };
|
|
2164
2305
|
} catch (err) {
|
|
2165
|
-
console.error(`${
|
|
2306
|
+
console.error(`${TAG9} send media failed to=${to}: ${String(err)}`);
|
|
2166
2307
|
return { success: false, error: String(err) };
|
|
2167
2308
|
}
|
|
2168
2309
|
}
|
|
2169
2310
|
|
|
2170
2311
|
// app/lib/whatsapp/persist-message.ts
|
|
2171
|
-
var
|
|
2312
|
+
var TAG10 = "[whatsapp-persist]";
|
|
2172
2313
|
var sessionWriteLocks = /* @__PURE__ */ new Map();
|
|
2173
2314
|
async function persistWhatsAppMessage(input) {
|
|
2174
2315
|
if (!input.body && !input.attachmentId || !input.msgKeyId) return null;
|
|
@@ -2219,14 +2360,14 @@ async function persistWhatsAppMessage(input) {
|
|
|
2219
2360
|
};
|
|
2220
2361
|
const result = await session.run(cypher, params);
|
|
2221
2362
|
if (result.records.length === 0) {
|
|
2222
|
-
console.error(`${
|
|
2363
|
+
console.error(`${TAG10} skip reason=conversation-not-found accountId=${input.platformAccountId} cacheKey=${input.cacheKey} messageId=${messageId}`);
|
|
2223
2364
|
return null;
|
|
2224
2365
|
}
|
|
2225
2366
|
const rec = result.records[0];
|
|
2226
2367
|
const senderElementId = rec.get("senderElementId");
|
|
2227
2368
|
const senderReused = rec.get("senderReused") === true;
|
|
2228
2369
|
console.error(
|
|
2229
|
-
`${
|
|
2370
|
+
`${TAG10} sender-resolved telephone=${senderTelephone} nodeKind=Person elementId=${senderElementId} reused=${senderReused}`
|
|
2230
2371
|
);
|
|
2231
2372
|
const diskRecord = {
|
|
2232
2373
|
messageId,
|
|
@@ -2252,18 +2393,18 @@ async function persistWhatsAppMessage(input) {
|
|
|
2252
2393
|
const { created } = appendMessage(input.platformAccountId, diskRecord, altDedupeRemoteJids);
|
|
2253
2394
|
const ms = Date.now() - t0;
|
|
2254
2395
|
if (!created) {
|
|
2255
|
-
console.error(`${
|
|
2396
|
+
console.error(`${TAG10} noop reason=existing-message messageId=${messageId}`);
|
|
2256
2397
|
return { messageId, created: false, senderElementId };
|
|
2257
2398
|
}
|
|
2258
2399
|
console.error(
|
|
2259
|
-
`${
|
|
2400
|
+
`${TAG10} write messageId=${messageId} accountId=${input.platformAccountId} cacheKey=${input.cacheKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} attachment=${input.attachmentId ?? "none"} ms=${ms}`
|
|
2260
2401
|
);
|
|
2261
2402
|
return { messageId, created: true, senderElementId };
|
|
2262
2403
|
} catch (err) {
|
|
2263
2404
|
const ms = Date.now() - t0;
|
|
2264
2405
|
const reason = sanitizeReason(err);
|
|
2265
2406
|
console.error(
|
|
2266
|
-
`${
|
|
2407
|
+
`${TAG10} FAIL accountId=${input.platformAccountId} waname=${input.accountId} remoteJid=${input.remoteJid} msgKey=${input.msgKeyId} reason=${reason} ms=${ms}`
|
|
2267
2408
|
);
|
|
2268
2409
|
return null;
|
|
2269
2410
|
} finally {
|
|
@@ -2506,7 +2647,7 @@ function groupEntriesFromUpdates(updates, nowIso) {
|
|
|
2506
2647
|
}
|
|
2507
2648
|
|
|
2508
2649
|
// app/lib/whatsapp/ensure-conversation.ts
|
|
2509
|
-
var
|
|
2650
|
+
var TAG11 = "[whatsapp-persist]";
|
|
2510
2651
|
async function ensureWhatsAppConversation(input) {
|
|
2511
2652
|
const t0 = Date.now();
|
|
2512
2653
|
try {
|
|
@@ -2518,19 +2659,19 @@ async function ensureWhatsAppConversation(input) {
|
|
|
2518
2659
|
const ms = Date.now() - t0;
|
|
2519
2660
|
if (!result.sessionId) {
|
|
2520
2661
|
console.error(
|
|
2521
|
-
`${
|
|
2662
|
+
`${TAG11} conversation-merged FAIL cacheKey=${input.cacheKey} reason=null-sessionId ms=${ms}`
|
|
2522
2663
|
);
|
|
2523
2664
|
return null;
|
|
2524
2665
|
}
|
|
2525
2666
|
console.error(
|
|
2526
|
-
`${
|
|
2667
|
+
`${TAG11} conversation-merged cacheKey=${input.cacheKey} agentType=${input.agentType} channel=whatsapp accountId=${input.platformAccountId} connectionAccountId=${input.connectionAccountId ?? input.platformAccountId} created=${result.created} ms=${ms}`
|
|
2527
2668
|
);
|
|
2528
2669
|
return { sessionId: result.sessionId, created: result.created };
|
|
2529
2670
|
} catch (err) {
|
|
2530
2671
|
const ms = Date.now() - t0;
|
|
2531
2672
|
const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
|
|
2532
2673
|
console.error(
|
|
2533
|
-
`${
|
|
2674
|
+
`${TAG11} conversation-merged FAIL cacheKey=${input.cacheKey} reason=${reason} ms=${ms}`
|
|
2534
2675
|
);
|
|
2535
2676
|
return null;
|
|
2536
2677
|
}
|
|
@@ -3103,7 +3244,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
|
|
|
3103
3244
|
}
|
|
3104
3245
|
|
|
3105
3246
|
// app/lib/whatsapp/inbound/media-download-guard.ts
|
|
3106
|
-
var
|
|
3247
|
+
var TAG12 = "[media-guard]";
|
|
3107
3248
|
var inFlight = 0;
|
|
3108
3249
|
var containedCount = 0;
|
|
3109
3250
|
function containedSinceBoot() {
|
|
@@ -3133,13 +3274,13 @@ function handleEscapedMediaError(err, channel) {
|
|
|
3133
3274
|
if (undiciFrame && inFlight > 0) {
|
|
3134
3275
|
containedCount += 1;
|
|
3135
3276
|
console.error(
|
|
3136
|
-
`${
|
|
3277
|
+
`${TAG12} op=contained channel=${channel} inFlight=${inFlight} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)}
|
|
3137
3278
|
${stack}`
|
|
3138
3279
|
);
|
|
3139
3280
|
return true;
|
|
3140
3281
|
}
|
|
3141
3282
|
console.error(
|
|
3142
|
-
`${
|
|
3283
|
+
`${TAG12} op=escaped channel=${channel} inFlight=${inFlight} undiciFrame=${undiciFrame} err=${err instanceof Error ? err.message : String(err)} cause=${causeCode(err)} contained=false`
|
|
3143
3284
|
);
|
|
3144
3285
|
return false;
|
|
3145
3286
|
}
|
|
@@ -3164,11 +3305,11 @@ function installMediaDownloadGuard() {
|
|
|
3164
3305
|
);
|
|
3165
3306
|
process.exit(1);
|
|
3166
3307
|
});
|
|
3167
|
-
console.error(`${
|
|
3308
|
+
console.error(`${TAG12} op=installed`);
|
|
3168
3309
|
}
|
|
3169
3310
|
|
|
3170
3311
|
// app/lib/whatsapp/inbound/media.ts
|
|
3171
|
-
var
|
|
3312
|
+
var TAG13 = "[whatsapp:media]";
|
|
3172
3313
|
var MEDIA_DIR = "/tmp/maxy-media";
|
|
3173
3314
|
var DOWNLOAD_TIMEOUT_MS = 45e3;
|
|
3174
3315
|
var DETACHED_GRACE_MS = 3e5;
|
|
@@ -3258,25 +3399,25 @@ async function downloadInboundMediaBuffer(msg, sock, opts) {
|
|
|
3258
3399
|
}
|
|
3259
3400
|
);
|
|
3260
3401
|
if (!buffer || buffer.length === 0) {
|
|
3261
|
-
console.error(`${
|
|
3402
|
+
console.error(`${TAG13} primary download returned empty, trying direct fallback`);
|
|
3262
3403
|
const downloadable = getDownloadableContent(content);
|
|
3263
3404
|
if (downloadable) {
|
|
3264
3405
|
try {
|
|
3265
3406
|
const stream = await downloadContentFromMessage(downloadable.downloadable, downloadable.mediaType);
|
|
3266
3407
|
buffer = await streamToBuffer(stream);
|
|
3267
3408
|
} catch (fallbackErr) {
|
|
3268
|
-
console.error(`${
|
|
3409
|
+
console.error(`${TAG13} direct download fallback failed: ${String(fallbackErr)}`);
|
|
3269
3410
|
}
|
|
3270
3411
|
}
|
|
3271
3412
|
}
|
|
3272
3413
|
if (!buffer || buffer.length === 0) {
|
|
3273
|
-
console.error(`${
|
|
3414
|
+
console.error(`${TAG13} download failed: empty buffer for ${mimetype ?? "unknown"}`);
|
|
3274
3415
|
return void 0;
|
|
3275
3416
|
}
|
|
3276
3417
|
if (buffer.length > maxBytes) {
|
|
3277
3418
|
const sizeMB = (buffer.length / (1024 * 1024)).toFixed(1);
|
|
3278
3419
|
const limitMB = (maxBytes / (1024 * 1024)).toFixed(0);
|
|
3279
|
-
console.error(`${
|
|
3420
|
+
console.error(`${TAG13} media too large type=${mimetype ?? "unknown"} size=${sizeMB}MB limit=${limitMB}MB`);
|
|
3280
3421
|
return void 0;
|
|
3281
3422
|
}
|
|
3282
3423
|
return {
|
|
@@ -3290,7 +3431,7 @@ async function downloadInboundMediaBuffer(msg, sock, opts) {
|
|
|
3290
3431
|
endMediaDownload();
|
|
3291
3432
|
return settled;
|
|
3292
3433
|
} catch (err) {
|
|
3293
|
-
console.error(`${
|
|
3434
|
+
console.error(`${TAG13} media download failed type=${mimetype ?? "unknown"} error=${String(err)}`);
|
|
3294
3435
|
if (isTimeoutError(err)) {
|
|
3295
3436
|
const t = setTimeout(endMediaDownload, DETACHED_GRACE_MS);
|
|
3296
3437
|
t.unref?.();
|
|
@@ -3308,7 +3449,7 @@ async function downloadInboundMedia(msg, sock, opts) {
|
|
|
3308
3449
|
const filePath = join6(MEDIA_DIR, `${randomUUID4()}.${ext}`);
|
|
3309
3450
|
await writeFile2(filePath, res.buffer);
|
|
3310
3451
|
const sizeKB = (res.buffer.length / 1024).toFixed(0);
|
|
3311
|
-
console.error(`${
|
|
3452
|
+
console.error(`${TAG13} media downloaded type=${res.mimetype} size=${sizeKB}KB path=${filePath}`);
|
|
3312
3453
|
return { path: filePath, mimetype: res.mimetype, size: res.buffer.length };
|
|
3313
3454
|
}
|
|
3314
3455
|
async function storeInboundMediaServable(msg, sock, accountId, seed, opts) {
|
|
@@ -3317,15 +3458,15 @@ async function storeInboundMediaServable(msg, sock, accountId, seed, opts) {
|
|
|
3317
3458
|
if (attachmentExists(accountId, attachmentId)) return attachmentId;
|
|
3318
3459
|
const res = await downloadInboundMediaBufferCached(msg, sock, opts);
|
|
3319
3460
|
if (!res) {
|
|
3320
|
-
console.error(`${
|
|
3461
|
+
console.error(`${TAG13} servable-store skip reason=no-buffer id=${attachmentId}`);
|
|
3321
3462
|
return null;
|
|
3322
3463
|
}
|
|
3323
3464
|
const filename = res.filename ?? `${attachmentId}.${mimeToExt(res.mimetype)}`;
|
|
3324
3465
|
await storeMediaBuffer(accountId, attachmentId, filename, res.mimetype, res.buffer);
|
|
3325
|
-
console.error(`${
|
|
3466
|
+
console.error(`${TAG13} servable-store ok id=${attachmentId} mime=${res.mimetype} bytes=${res.buffer.length}`);
|
|
3326
3467
|
return attachmentId;
|
|
3327
3468
|
} catch (err) {
|
|
3328
|
-
console.error(`${
|
|
3469
|
+
console.error(`${TAG13} servable-store FAIL id=${attachmentId} reason=${String(err).slice(0, 120)}`);
|
|
3329
3470
|
return null;
|
|
3330
3471
|
}
|
|
3331
3472
|
}
|
|
@@ -3373,7 +3514,7 @@ function createBoundedQueue(limit, opts) {
|
|
|
3373
3514
|
}
|
|
3374
3515
|
|
|
3375
3516
|
// app/lib/whatsapp/inbound/debounce.ts
|
|
3376
|
-
var
|
|
3517
|
+
var TAG14 = "[whatsapp:debounce]";
|
|
3377
3518
|
var STT_TAG = "[whatsapp:stt-await]";
|
|
3378
3519
|
function createInboundDebouncer(opts) {
|
|
3379
3520
|
const { debounceMs, buildKey, onFlush, onError } = opts;
|
|
@@ -3404,7 +3545,7 @@ function createInboundDebouncer(opts) {
|
|
|
3404
3545
|
pending.delete(key);
|
|
3405
3546
|
const batchSize = batch.entries.length;
|
|
3406
3547
|
try {
|
|
3407
|
-
console.error(`${
|
|
3548
|
+
console.error(`${TAG14} debounce flush key=${key} batchSize=${batchSize}`);
|
|
3408
3549
|
const result = onFlush(batch.entries);
|
|
3409
3550
|
if (result && typeof result.catch === "function") {
|
|
3410
3551
|
result.catch(onError);
|
|
@@ -3484,7 +3625,7 @@ function combineInboundBatch(entries) {
|
|
|
3484
3625
|
}
|
|
3485
3626
|
|
|
3486
3627
|
// app/lib/whatsapp/opening-hours.ts
|
|
3487
|
-
var
|
|
3628
|
+
var TAG15 = "[whatsapp:hours]";
|
|
3488
3629
|
async function isBusinessOpen(accountId) {
|
|
3489
3630
|
try {
|
|
3490
3631
|
const timezone = await resolveTimezone(accountId);
|
|
@@ -3502,7 +3643,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3502
3643
|
{ accountId, dayOfWeek, previousDayOfWeek }
|
|
3503
3644
|
);
|
|
3504
3645
|
if (result.records.length === 0) {
|
|
3505
|
-
console.error(`${
|
|
3646
|
+
console.error(`${TAG15} [${accountId}] business hours check: no opening hours configured, treating as open`);
|
|
3506
3647
|
return { open: true, reason: "no opening hours configured" };
|
|
3507
3648
|
}
|
|
3508
3649
|
const specs = result.records.filter((r) => r.get("opens") != null && r.get("closes") != null).map((r) => ({
|
|
@@ -3511,7 +3652,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3511
3652
|
closes: String(r.get("closes")).trim()
|
|
3512
3653
|
}));
|
|
3513
3654
|
if (specs.length === 0) {
|
|
3514
|
-
console.error(`${
|
|
3655
|
+
console.error(`${TAG15} [${accountId}] business hours check: no opening hours configured, treating as open`);
|
|
3515
3656
|
return { open: true, reason: "no opening hours configured" };
|
|
3516
3657
|
}
|
|
3517
3658
|
for (const spec of specs) {
|
|
@@ -3521,7 +3662,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3521
3662
|
if (spec.opens > spec.closes && currentTime < spec.closes) {
|
|
3522
3663
|
const hoursStr = `${spec.opens}-${spec.closes} (${spec.day})`;
|
|
3523
3664
|
console.error(
|
|
3524
|
-
`${
|
|
3665
|
+
`${TAG15} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
|
|
3525
3666
|
);
|
|
3526
3667
|
return {
|
|
3527
3668
|
open: true,
|
|
@@ -3534,7 +3675,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3534
3675
|
} else if (isTimeInRange(currentTime, spec.opens, spec.closes)) {
|
|
3535
3676
|
const hoursStr = `${spec.opens}-${spec.closes}`;
|
|
3536
3677
|
console.error(
|
|
3537
|
-
`${
|
|
3678
|
+
`${TAG15} [${accountId}] business hours check: open (day=${dayOfWeek}, time=${currentTime}, hours=${hoursStr})`
|
|
3538
3679
|
);
|
|
3539
3680
|
return {
|
|
3540
3681
|
open: true,
|
|
@@ -3548,7 +3689,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3548
3689
|
const todaySpecs = specs.filter((s) => s.day === dayOfWeek);
|
|
3549
3690
|
const allHours = todaySpecs.map((s) => `${s.opens}-${s.closes}`).join(", ") || "none today";
|
|
3550
3691
|
console.error(
|
|
3551
|
-
`${
|
|
3692
|
+
`${TAG15} [${accountId}] business hours check: closed (day=${dayOfWeek}, time=${currentTime}, hours=${allHours})`
|
|
3552
3693
|
);
|
|
3553
3694
|
return {
|
|
3554
3695
|
open: false,
|
|
@@ -3562,7 +3703,7 @@ async function isBusinessOpen(accountId) {
|
|
|
3562
3703
|
}
|
|
3563
3704
|
} catch (err) {
|
|
3564
3705
|
console.error(
|
|
3565
|
-
`${
|
|
3706
|
+
`${TAG15} [${accountId}] business hours check failed, treating as open: ${err instanceof Error ? err.message : String(err)}`
|
|
3566
3707
|
);
|
|
3567
3708
|
return { open: true, reason: "hours check failed (treating as open)" };
|
|
3568
3709
|
}
|
|
@@ -3608,7 +3749,7 @@ import { execFile } from "child_process";
|
|
|
3608
3749
|
import { unlink, stat } from "fs/promises";
|
|
3609
3750
|
import { promisify } from "util";
|
|
3610
3751
|
var execFileAsync = promisify(execFile);
|
|
3611
|
-
var
|
|
3752
|
+
var TAG16 = "[stt]";
|
|
3612
3753
|
var WHISPER_BINARY = process.env.WHISPER_BINARY ?? "/opt/whisper.cpp/build/bin/whisper-cli";
|
|
3613
3754
|
var WHISPER_MODEL = process.env.WHISPER_MODEL ?? "/opt/whisper.cpp/models/ggml-base.bin";
|
|
3614
3755
|
var WHISPER_TIMEOUT_MS = 20 * 60 * 1e3;
|
|
@@ -3627,11 +3768,11 @@ async function transcribe(audioPath, mimetype) {
|
|
|
3627
3768
|
const s = await stat(audioPath);
|
|
3628
3769
|
audioBytes = s.size;
|
|
3629
3770
|
} catch {
|
|
3630
|
-
console.error(`${
|
|
3771
|
+
console.error(`${TAG16} failed: file not readable path=${audioPath}`);
|
|
3631
3772
|
return void 0;
|
|
3632
3773
|
}
|
|
3633
3774
|
console.error(
|
|
3634
|
-
`${
|
|
3775
|
+
`${TAG16} start provider=whisper-local audio_bytes=${audioBytes} mimetype=${mimetype} path=${audioPath}`
|
|
3635
3776
|
);
|
|
3636
3777
|
const wavPath = audioPath.replace(/\.[^.]+$/, "") + ".wav";
|
|
3637
3778
|
try {
|
|
@@ -3650,7 +3791,7 @@ async function transcribe(audioPath, mimetype) {
|
|
|
3650
3791
|
], { timeout: 3e4 });
|
|
3651
3792
|
} catch (err) {
|
|
3652
3793
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3653
|
-
console.error(`${
|
|
3794
|
+
console.error(`${TAG16} failed: ffmpeg conversion error=${reason}`);
|
|
3654
3795
|
return void 0;
|
|
3655
3796
|
}
|
|
3656
3797
|
try {
|
|
@@ -3666,20 +3807,20 @@ async function transcribe(audioPath, mimetype) {
|
|
|
3666
3807
|
const durationMs = Date.now() - startMs;
|
|
3667
3808
|
const { text, count: stripped } = stripSpecialTokens(stdout.trim());
|
|
3668
3809
|
if (!text) {
|
|
3669
|
-
console.error(`${
|
|
3810
|
+
console.error(`${TAG16} failed: whisper returned empty output duration_ms=${durationMs}`);
|
|
3670
3811
|
return void 0;
|
|
3671
3812
|
}
|
|
3672
3813
|
const langMatch = stderr.match(/auto-detected language:\s*(\w+)/);
|
|
3673
3814
|
const language = langMatch?.[1] ?? "unknown";
|
|
3674
3815
|
const words = text.split(/\s+/).filter(Boolean).length;
|
|
3675
3816
|
console.error(
|
|
3676
|
-
`${
|
|
3817
|
+
`${TAG16} done provider=whisper-local duration_ms=${durationMs} words=${words} stripped=${stripped} lang=${language}`
|
|
3677
3818
|
);
|
|
3678
3819
|
return { text, language, durationMs };
|
|
3679
3820
|
} catch (err) {
|
|
3680
3821
|
const durationMs = Date.now() - startMs;
|
|
3681
3822
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3682
|
-
console.error(`${
|
|
3823
|
+
console.error(`${TAG16} failed provider=whisper-local duration_ms=${durationMs} error=${reason}`);
|
|
3683
3824
|
return void 0;
|
|
3684
3825
|
} finally {
|
|
3685
3826
|
unlink(wavPath).catch(() => {
|
|
@@ -3698,8 +3839,9 @@ var WaReplyError = class extends Error {
|
|
|
3698
3839
|
};
|
|
3699
3840
|
|
|
3700
3841
|
// app/lib/whatsapp/manager.ts
|
|
3701
|
-
var
|
|
3842
|
+
var TAG17 = "[whatsapp:manager]";
|
|
3702
3843
|
var MAX_RECONNECT_ATTEMPTS = 10;
|
|
3844
|
+
var REARM_INTERVAL_MS = 15 * 6e4;
|
|
3703
3845
|
var MESSAGE_STORE_MAX = 500;
|
|
3704
3846
|
var APPEND_MEDIA_CONCURRENCY = 3;
|
|
3705
3847
|
var APPEND_MEDIA_MAX_PENDING = 24;
|
|
@@ -3751,7 +3893,7 @@ function storeMessage(storeKey, entry2) {
|
|
|
3751
3893
|
if (entries.length > MESSAGE_STORE_MAX) {
|
|
3752
3894
|
const trimmed = entries.length - MESSAGE_STORE_MAX;
|
|
3753
3895
|
entries.splice(0, trimmed);
|
|
3754
|
-
console.error(`${
|
|
3896
|
+
console.error(`${TAG17} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
|
|
3755
3897
|
}
|
|
3756
3898
|
}
|
|
3757
3899
|
function deriveCacheKey(input) {
|
|
@@ -3795,7 +3937,7 @@ function buildSelfChatDispatch(input) {
|
|
|
3795
3937
|
}
|
|
3796
3938
|
async function init(opts) {
|
|
3797
3939
|
if (initialized) {
|
|
3798
|
-
console.error(`${
|
|
3940
|
+
console.error(`${TAG17} already initialized`);
|
|
3799
3941
|
return;
|
|
3800
3942
|
}
|
|
3801
3943
|
configDir = opts.configDir;
|
|
@@ -3805,20 +3947,20 @@ async function init(opts) {
|
|
|
3805
3947
|
loadConfig(opts.accountConfig);
|
|
3806
3948
|
const accountIds = listCredentialAccountIds(configDir);
|
|
3807
3949
|
if (accountIds.length === 0) {
|
|
3808
|
-
console.error(`${
|
|
3950
|
+
console.error(`${TAG17} init: no stored WhatsApp credentials found`);
|
|
3809
3951
|
initialized = true;
|
|
3810
3952
|
return;
|
|
3811
3953
|
}
|
|
3812
|
-
console.error(`${
|
|
3954
|
+
console.error(`${TAG17} init: found ${accountIds.length} credentialed account(s): ${accountIds.join(", ")}`);
|
|
3813
3955
|
initialized = true;
|
|
3814
3956
|
for (const accountId of accountIds) {
|
|
3815
3957
|
const accountCfg = whatsAppConfig.accounts?.[accountId];
|
|
3816
3958
|
if (accountCfg?.enabled === false) {
|
|
3817
|
-
console.error(`${
|
|
3959
|
+
console.error(`${TAG17} skipping disabled account=${accountId}`);
|
|
3818
3960
|
continue;
|
|
3819
3961
|
}
|
|
3820
3962
|
startConnection(accountId).catch((err) => {
|
|
3821
|
-
console.error(`${
|
|
3963
|
+
console.error(`${TAG17} failed to auto-start account=${accountId}: ${formatError(err)}`);
|
|
3822
3964
|
});
|
|
3823
3965
|
}
|
|
3824
3966
|
}
|
|
@@ -3827,7 +3969,7 @@ async function startConnection(accountId) {
|
|
|
3827
3969
|
const authDir = resolveAuthDir(configDir, accountId);
|
|
3828
3970
|
const hasAuth = await authExists(authDir);
|
|
3829
3971
|
if (!hasAuth) {
|
|
3830
|
-
console.error(`${
|
|
3972
|
+
console.error(`${TAG17} no credentials for account=${accountId}`);
|
|
3831
3973
|
return;
|
|
3832
3974
|
}
|
|
3833
3975
|
let platformAccountId;
|
|
@@ -3858,6 +4000,7 @@ async function startConnection(accountId) {
|
|
|
3858
4000
|
selfJid: null,
|
|
3859
4001
|
selfLid: null,
|
|
3860
4002
|
reconnectAttempts: 0,
|
|
4003
|
+
rearmAttempts: 0,
|
|
3861
4004
|
abortController: new AbortController(),
|
|
3862
4005
|
debouncer: null,
|
|
3863
4006
|
lidMapping: null
|
|
@@ -3881,11 +4024,11 @@ async function stopConnection(accountId) {
|
|
|
3881
4024
|
conn.sock.ev.removeAllListeners("creds.update");
|
|
3882
4025
|
conn.sock.ws?.close?.();
|
|
3883
4026
|
} catch (err) {
|
|
3884
|
-
console.warn(`${
|
|
4027
|
+
console.warn(`${TAG17} socket cleanup error during stop account=${accountId}: ${String(err)}`);
|
|
3885
4028
|
}
|
|
3886
4029
|
}
|
|
3887
4030
|
connections.delete(accountId);
|
|
3888
|
-
console.error(`${
|
|
4031
|
+
console.error(`${TAG17} stopped account=${accountId}`);
|
|
3889
4032
|
}
|
|
3890
4033
|
function getStatus() {
|
|
3891
4034
|
return Array.from(connections.values()).map((conn) => ({
|
|
@@ -3996,6 +4139,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
|
|
|
3996
4139
|
selfJid: null,
|
|
3997
4140
|
selfLid: null,
|
|
3998
4141
|
reconnectAttempts: 0,
|
|
4142
|
+
rearmAttempts: 0,
|
|
3999
4143
|
lastConnectedAt: Date.now(),
|
|
4000
4144
|
abortController: new AbortController(),
|
|
4001
4145
|
debouncer: null,
|
|
@@ -4007,9 +4151,9 @@ async function registerLoginSocket(accountId, sock, authDir) {
|
|
|
4007
4151
|
monitorChatMetadata(conn);
|
|
4008
4152
|
try {
|
|
4009
4153
|
await sock.sendPresenceUpdate("available");
|
|
4010
|
-
console.error(`${
|
|
4154
|
+
console.error(`${TAG17} presence set to available account=${accountId}`);
|
|
4011
4155
|
} catch (err) {
|
|
4012
|
-
console.error(`${
|
|
4156
|
+
console.error(`${TAG17} presence update failed account=${accountId}: ${String(err)}`);
|
|
4013
4157
|
}
|
|
4014
4158
|
await runInitQueries(sock, {
|
|
4015
4159
|
accountId,
|
|
@@ -4020,7 +4164,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
|
|
|
4020
4164
|
});
|
|
4021
4165
|
watchForDisconnect(conn);
|
|
4022
4166
|
attachSelfIdRefreshOnCredsUpdate(conn);
|
|
4023
|
-
console.error(`${
|
|
4167
|
+
console.error(`${TAG17} registered login socket for account=${accountId} phone=${conn.selfPhone ?? "unknown"}`);
|
|
4024
4168
|
}
|
|
4025
4169
|
function attachSelfIdRefreshOnCredsUpdate(conn) {
|
|
4026
4170
|
if (!conn.sock) return;
|
|
@@ -4079,7 +4223,7 @@ async function shutdown() {
|
|
|
4079
4223
|
const ids = Array.from(connections.keys());
|
|
4080
4224
|
await Promise.all(ids.map((id) => stopConnection(id)));
|
|
4081
4225
|
initialized = false;
|
|
4082
|
-
console.error(`${
|
|
4226
|
+
console.error(`${TAG17} shutdown complete`);
|
|
4083
4227
|
}
|
|
4084
4228
|
function loadConfig(accountConfig) {
|
|
4085
4229
|
try {
|
|
@@ -4090,30 +4234,43 @@ function loadConfig(accountConfig) {
|
|
|
4090
4234
|
if (result.ok) {
|
|
4091
4235
|
whatsAppConfig = result.data;
|
|
4092
4236
|
if (result.droppedKeys.length > 0) {
|
|
4093
|
-
console.error(`${
|
|
4237
|
+
console.error(`${TAG17} config: dropped unknown keys=[${result.droppedKeys.join(",")}] preserved known config`);
|
|
4094
4238
|
}
|
|
4095
4239
|
} else {
|
|
4096
|
-
console.error(`${
|
|
4240
|
+
console.error(`${TAG17} config validation failed: ${result.error.message}`);
|
|
4097
4241
|
whatsAppConfig = {};
|
|
4098
4242
|
}
|
|
4099
4243
|
const diskAdmin = Array.isArray(wa.adminPhones) ? wa.adminPhones : [];
|
|
4100
4244
|
if (diskAdmin.length > 0 && (whatsAppConfig.adminPhones?.length ?? 0) === 0) {
|
|
4101
|
-
console.error(`${
|
|
4245
|
+
console.error(`${TAG17} WARN adminPhones present on disk but empty after load`);
|
|
4102
4246
|
}
|
|
4103
4247
|
}
|
|
4104
4248
|
} catch (err) {
|
|
4105
|
-
console.error(`${
|
|
4249
|
+
console.error(`${TAG17} config load error: ${String(err)}`);
|
|
4106
4250
|
whatsAppConfig = {};
|
|
4107
4251
|
}
|
|
4108
4252
|
}
|
|
4253
|
+
function sinceStuckMs(conn) {
|
|
4254
|
+
return conn.stuckSinceMs === void 0 ? 0 : Date.now() - conn.stuckSinceMs;
|
|
4255
|
+
}
|
|
4256
|
+
function clearStuck(conn) {
|
|
4257
|
+
if (!conn.sessionStuckReason) return;
|
|
4258
|
+
console.error(
|
|
4259
|
+
`${HEALTH_TAG} op=rearm account=${conn.accountId} attempt=${conn.rearmAttempts} sinceStuckMs=${sinceStuckMs(conn)} outcome=connected`
|
|
4260
|
+
);
|
|
4261
|
+
conn.sessionStuckReason = void 0;
|
|
4262
|
+
conn.stuckSinceMs = void 0;
|
|
4263
|
+
conn.rearmAttempts = 0;
|
|
4264
|
+
}
|
|
4109
4265
|
async function connectWithReconnect(conn) {
|
|
4110
4266
|
const maxAttempts = MAX_RECONNECT_ATTEMPTS;
|
|
4111
4267
|
while (!conn.abortController.signal.aborted) {
|
|
4112
4268
|
let uptimeMs = 0;
|
|
4113
4269
|
let cycleError = null;
|
|
4114
4270
|
let connectedAt;
|
|
4271
|
+
let heldTimer;
|
|
4115
4272
|
try {
|
|
4116
|
-
console.error(`${
|
|
4273
|
+
console.error(`${TAG17} connecting account=${conn.accountId} attempt=${conn.reconnectAttempts}`);
|
|
4117
4274
|
if (conn.debouncer) {
|
|
4118
4275
|
await conn.debouncer.destroy();
|
|
4119
4276
|
conn.debouncer = null;
|
|
@@ -4127,7 +4284,7 @@ async function connectWithReconnect(conn) {
|
|
|
4127
4284
|
applySelfIdentity(conn, sock, "pre-listener");
|
|
4128
4285
|
monitorInbound(conn);
|
|
4129
4286
|
monitorChatMetadata(conn);
|
|
4130
|
-
console.error(`${
|
|
4287
|
+
console.error(`${TAG17} socket created account=${conn.accountId} \u2014 waiting for connection`);
|
|
4131
4288
|
await waitForConnection(sock);
|
|
4132
4289
|
connectedAt = Date.now();
|
|
4133
4290
|
conn.connected = true;
|
|
@@ -4135,12 +4292,19 @@ async function connectWithReconnect(conn) {
|
|
|
4135
4292
|
conn.lastError = void 0;
|
|
4136
4293
|
conn.terminalReason = void 0;
|
|
4137
4294
|
applySelfIdentity(conn, sock, "post-connect");
|
|
4138
|
-
console.error(`${
|
|
4295
|
+
console.error(`${TAG17} connected account=${conn.accountId} phone=${conn.selfPhone ?? "unknown"}`);
|
|
4296
|
+
if (conn.sessionStuckReason) {
|
|
4297
|
+
heldTimer = setTimeout(() => {
|
|
4298
|
+
if (!conn.connected || connections.get(conn.accountId) !== conn) return;
|
|
4299
|
+
clearStuck(conn);
|
|
4300
|
+
}, STABLE_UPTIME_MS);
|
|
4301
|
+
if (typeof heldTimer.unref === "function") heldTimer.unref();
|
|
4302
|
+
}
|
|
4139
4303
|
try {
|
|
4140
4304
|
await sock.sendPresenceUpdate("available");
|
|
4141
|
-
console.error(`${
|
|
4305
|
+
console.error(`${TAG17} presence set to available account=${conn.accountId}`);
|
|
4142
4306
|
} catch (err) {
|
|
4143
|
-
console.error(`${
|
|
4307
|
+
console.error(`${TAG17} presence update failed account=${conn.accountId}: ${String(err)}`);
|
|
4144
4308
|
}
|
|
4145
4309
|
await runInitQueries(sock, {
|
|
4146
4310
|
accountId: conn.accountId,
|
|
@@ -4163,13 +4327,20 @@ async function connectWithReconnect(conn) {
|
|
|
4163
4327
|
}
|
|
4164
4328
|
const classification = classifyDisconnect(err);
|
|
4165
4329
|
conn.lastError = classification.message;
|
|
4166
|
-
console.error(`${
|
|
4330
|
+
console.error(`${TAG17} disconnect account=${conn.accountId}: ${classification.kind} \u2014 ${classification.message}`);
|
|
4167
4331
|
if (!classification.shouldRetry) {
|
|
4168
4332
|
conn.terminalReason = classification.message;
|
|
4169
|
-
|
|
4333
|
+
if (conn.sessionStuckReason) {
|
|
4334
|
+
console.error(
|
|
4335
|
+
`${HEALTH_TAG} op=rearm account=${conn.accountId} attempt=${conn.rearmAttempts} sinceStuckMs=${sinceStuckMs(conn)} outcome=skipped-terminal`
|
|
4336
|
+
);
|
|
4337
|
+
}
|
|
4338
|
+
console.error(`${TAG17} terminal disconnect for account=${conn.accountId}, stopping reconnection`);
|
|
4339
|
+
if (heldTimer !== void 0) clearTimeout(heldTimer);
|
|
4170
4340
|
return;
|
|
4171
4341
|
}
|
|
4172
4342
|
}
|
|
4343
|
+
if (heldTimer !== void 0) clearTimeout(heldTimer);
|
|
4173
4344
|
const decision = computeReconnectNextState({
|
|
4174
4345
|
reconnectAttempts: conn.reconnectAttempts,
|
|
4175
4346
|
uptimeMs,
|
|
@@ -4177,28 +4348,44 @@ async function connectWithReconnect(conn) {
|
|
|
4177
4348
|
maxAttempts
|
|
4178
4349
|
});
|
|
4179
4350
|
if (decision.action === "abort") {
|
|
4180
|
-
const stuckReason = `
|
|
4351
|
+
const stuckReason = `RETRYING SLOWLY account=${conn.accountId} attempts=${decision.finalAttempts}/${maxAttempts} rearmIntervalMs=${REARM_INTERVAL_MS} uptimeMsLast=${uptimeMs} stableThresholdMs=${STABLE_UPTIME_MS} lastError=${conn.lastError ?? "(none)"}`;
|
|
4352
|
+
if (conn.rearmAttempts > 0) {
|
|
4353
|
+
console.error(
|
|
4354
|
+
`${HEALTH_TAG} op=rearm account=${conn.accountId} attempt=${conn.rearmAttempts} sinceStuckMs=${sinceStuckMs(conn)} outcome=failed`
|
|
4355
|
+
);
|
|
4356
|
+
}
|
|
4181
4357
|
console.error(
|
|
4182
|
-
`${
|
|
4358
|
+
`${TAG17} ${stuckReason} \u2014 re-arming in ${REARM_INTERVAL_MS}ms and every ${REARM_INTERVAL_MS}ms after; a re-pair via QR ends the wait sooner`
|
|
4183
4359
|
);
|
|
4184
4360
|
conn.sessionStuckReason = stuckReason;
|
|
4185
4361
|
conn.lastError = stuckReason;
|
|
4186
|
-
|
|
4362
|
+
if (conn.stuckSinceMs === void 0) conn.stuckSinceMs = Date.now();
|
|
4363
|
+
await new Promise((resolve6) => {
|
|
4364
|
+
const timer = setTimeout(resolve6, REARM_INTERVAL_MS);
|
|
4365
|
+
conn.abortController.signal.addEventListener("abort", () => {
|
|
4366
|
+
clearTimeout(timer);
|
|
4367
|
+
resolve6();
|
|
4368
|
+
}, { once: true });
|
|
4369
|
+
});
|
|
4370
|
+
if (conn.abortController.signal.aborted) return;
|
|
4371
|
+
conn.rearmAttempts += 1;
|
|
4372
|
+
continue;
|
|
4187
4373
|
}
|
|
4188
4374
|
conn.reconnectAttempts = decision.nextAttempts;
|
|
4189
4375
|
if (decision.reason === "short-lived") {
|
|
4190
4376
|
console.error(
|
|
4191
|
-
`${
|
|
4377
|
+
`${TAG17} short-lived session account=${conn.accountId} uptimeMs=${uptimeMs} attempt=${decision.nextAttempts}/${maxAttempts} lastError=${conn.lastError ?? "(clean disconnect)"}`
|
|
4192
4378
|
);
|
|
4193
4379
|
} else {
|
|
4380
|
+
clearStuck(conn);
|
|
4194
4381
|
console.error(
|
|
4195
|
-
`${
|
|
4382
|
+
`${TAG17} session stable account=${conn.accountId} uptimeMs=${uptimeMs} \u2014 reconnect counter reset`
|
|
4196
4383
|
);
|
|
4197
4384
|
}
|
|
4198
4385
|
if (decision.reason === "short-lived" || cycleError) {
|
|
4199
4386
|
const delay = computeBackoff(Math.max(1, decision.nextAttempts));
|
|
4200
4387
|
console.error(
|
|
4201
|
-
`${
|
|
4388
|
+
`${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
4202
4389
|
);
|
|
4203
4390
|
await new Promise((resolve6) => {
|
|
4204
4391
|
const timer = setTimeout(resolve6, delay);
|
|
@@ -4232,11 +4419,11 @@ function watchForDisconnect(conn) {
|
|
|
4232
4419
|
conn.sock.ev.on("connection.update", (update) => {
|
|
4233
4420
|
if (update.connection === "close") {
|
|
4234
4421
|
if (connections.get(conn.accountId) !== conn) return;
|
|
4235
|
-
console.error(`${
|
|
4422
|
+
console.error(`${TAG17} socket disconnected for account=${conn.accountId}`);
|
|
4236
4423
|
conn.connected = false;
|
|
4237
4424
|
conn.sock = null;
|
|
4238
4425
|
connectWithReconnect(conn).catch((err) => {
|
|
4239
|
-
console.error(`${
|
|
4426
|
+
console.error(`${TAG17} reconnection failed for account=${conn.accountId}: ${formatError(err)}`);
|
|
4240
4427
|
});
|
|
4241
4428
|
}
|
|
4242
4429
|
});
|
|
@@ -4271,7 +4458,7 @@ function monitorChatMetadata(conn) {
|
|
|
4271
4458
|
}
|
|
4272
4459
|
const { canonical, resolved } = await resolveCanonicalConversationJid(e.jid, conn.lidMapping);
|
|
4273
4460
|
if (resolved === "lid2pn") {
|
|
4274
|
-
console.error(`${
|
|
4461
|
+
console.error(`${TAG17} [wa-chatmeta] op=canonical raw=${e.jid} canonical=${canonical}`);
|
|
4275
4462
|
out.push({ ...e, jid: canonical });
|
|
4276
4463
|
} else {
|
|
4277
4464
|
out.push(e);
|
|
@@ -4284,13 +4471,13 @@ function monitorChatMetadata(conn) {
|
|
|
4284
4471
|
if (perJid) {
|
|
4285
4472
|
for (const e of entries) {
|
|
4286
4473
|
console.error(
|
|
4287
|
-
`${
|
|
4474
|
+
`${TAG17} [wa-chatmeta] op=event kind=${kind} jid=${e.jid} name=${e.name.length} source=${e.source}`
|
|
4288
4475
|
);
|
|
4289
4476
|
}
|
|
4290
4477
|
}
|
|
4291
4478
|
const total = writeChatMetadataMerged(account, entries);
|
|
4292
4479
|
console.error(
|
|
4293
|
-
`${
|
|
4480
|
+
`${TAG17} [wa-chatmeta] op=persist kind=${kind} account=${account.slice(0, 8)} updates=${entries.length} outcome=${total < 0 ? "fail" : "ok"} entries=${total}`
|
|
4294
4481
|
);
|
|
4295
4482
|
};
|
|
4296
4483
|
sock.ev.on("messaging-history.set", ({ chats, contacts }) => {
|
|
@@ -4298,7 +4485,7 @@ function monitorChatMetadata(conn) {
|
|
|
4298
4485
|
const chatEntries = chatEntriesFromChats(chats ?? [], nowIso);
|
|
4299
4486
|
const contactEntries = chatEntriesFromContacts(contacts ?? [], nowIso);
|
|
4300
4487
|
console.error(
|
|
4301
|
-
`${
|
|
4488
|
+
`${TAG17} [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
4489
|
);
|
|
4303
4490
|
void canonicalise([...chatEntries, ...contactEntries]).then((e) => persist("history-set", e, false));
|
|
4304
4491
|
});
|
|
@@ -4329,7 +4516,7 @@ function monitorChatMetadata(conn) {
|
|
|
4329
4516
|
try {
|
|
4330
4517
|
const meta = await sock.groupMetadata(jid);
|
|
4331
4518
|
console.error(
|
|
4332
|
-
`${
|
|
4519
|
+
`${TAG17} [wa-chatmeta] op=group-fetch jid=${jid} ms=${Date.now() - startedAt} outcome=ok`
|
|
4333
4520
|
);
|
|
4334
4521
|
persist(
|
|
4335
4522
|
"group-fetch",
|
|
@@ -4338,7 +4525,7 @@ function monitorChatMetadata(conn) {
|
|
|
4338
4525
|
);
|
|
4339
4526
|
} catch (err) {
|
|
4340
4527
|
console.error(
|
|
4341
|
-
`${
|
|
4528
|
+
`${TAG17} [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
4529
|
);
|
|
4343
4530
|
}
|
|
4344
4531
|
}
|
|
@@ -4351,7 +4538,7 @@ function monitorInbound(conn) {
|
|
|
4351
4538
|
if (!conn.sock || !onInboundMessage) return;
|
|
4352
4539
|
const sock = conn.sock;
|
|
4353
4540
|
const debounceMs = whatsAppConfig.accounts?.[conn.accountId]?.debounceMs ?? whatsAppConfig.debounceMs ?? 0;
|
|
4354
|
-
console.error(`${
|
|
4541
|
+
console.error(`${TAG17} monitorInbound started account=${conn.accountId} debounceMs=${debounceMs}`);
|
|
4355
4542
|
conn.debouncer = createInboundDebouncer({
|
|
4356
4543
|
debounceMs,
|
|
4357
4544
|
buildKey: (payload) => {
|
|
@@ -4361,12 +4548,12 @@ function monitorInbound(conn) {
|
|
|
4361
4548
|
onFlush: (entries) => {
|
|
4362
4549
|
if (!onInboundMessage) return;
|
|
4363
4550
|
if (entries.length > 1) {
|
|
4364
|
-
console.error(`${
|
|
4551
|
+
console.error(`${TAG17} debounce: combining ${entries.length} messages account=${conn.accountId} from=${entries[0].senderPhone}`);
|
|
4365
4552
|
}
|
|
4366
4553
|
dispatchInboundPayload(conn, combineInboundBatch(entries));
|
|
4367
4554
|
},
|
|
4368
4555
|
onError: (err) => {
|
|
4369
|
-
console.error(`${
|
|
4556
|
+
console.error(`${TAG17} debounce flush error account=${conn.accountId}: ${String(err)}`);
|
|
4370
4557
|
}
|
|
4371
4558
|
});
|
|
4372
4559
|
sock.ev.on("messages.upsert", async (upsert) => {
|
|
@@ -4479,7 +4666,7 @@ function monitorInbound(conn) {
|
|
|
4479
4666
|
}
|
|
4480
4667
|
const entries = messageStore.get(storeKey);
|
|
4481
4668
|
console.error(
|
|
4482
|
-
`${
|
|
4669
|
+
`${TAG17} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) storeAccount=${persistAccountId} socketOwner=${conn.platformAccountId}`
|
|
4483
4670
|
);
|
|
4484
4671
|
recordActivity({
|
|
4485
4672
|
accountId: conn.accountId,
|
|
@@ -4533,7 +4720,7 @@ function monitorInbound(conn) {
|
|
|
4533
4720
|
const wantsServableMedia = mediaServable && !!conn.sock && (!fromMe || !alreadyRecorded);
|
|
4534
4721
|
if (fromMe && mediaServable && !!conn.sock) {
|
|
4535
4722
|
console.error(
|
|
4536
|
-
`${
|
|
4723
|
+
`${TAG17} fromMe-media-echo msgKey=${msg.key.id} decision=${alreadyRecorded ? "skip" : "store"} reason=${alreadyRecorded ? "already-recorded" : "no-prior-record"}`
|
|
4537
4724
|
);
|
|
4538
4725
|
}
|
|
4539
4726
|
const mediaSeed = `whatsapp-live:${conn.accountId}:${canonicalRemoteJid}:${msg.key.id}`;
|
|
@@ -4616,7 +4803,7 @@ function monitorInbound(conn) {
|
|
|
4616
4803
|
receiptDeferredToWorker = true;
|
|
4617
4804
|
if (!accepted) {
|
|
4618
4805
|
console.error(
|
|
4619
|
-
`${
|
|
4806
|
+
`${TAG17} append-media overflow account=${conn.platformAccountId} msgKey=${msgKeyId ?? "?"} \u2014 pending cap ${APPEND_MEDIA_MAX_PENDING} reached, text-fallback persist, inline media shed`
|
|
4620
4807
|
);
|
|
4621
4808
|
const persisted = await persistWhatsAppMessage({
|
|
4622
4809
|
...basePersist,
|
|
@@ -4693,13 +4880,13 @@ function monitorInbound(conn) {
|
|
|
4693
4880
|
const skippedSenderJid = isGroupJid(remoteJid) ? msg.key.participant ?? remoteJid : remoteJid;
|
|
4694
4881
|
const skippedSenderPhone = await resolveJidToE164(skippedSenderJid, conn.lidMapping) ?? skippedSenderJid;
|
|
4695
4882
|
console.error(
|
|
4696
|
-
`${
|
|
4883
|
+
`${TAG17} append-type message ${msg.key.id ?? "?"} dispatch skipped from=${skippedSenderPhone}${msg.pushName ? ` name=${msg.pushName}` : ""} account=${conn.accountId} (persistence not confirmed here)`
|
|
4697
4884
|
);
|
|
4698
4885
|
continue;
|
|
4699
4886
|
}
|
|
4700
4887
|
await handleInboundMessage(conn, msg);
|
|
4701
4888
|
} catch (err) {
|
|
4702
|
-
console.error(`${
|
|
4889
|
+
console.error(`${TAG17} inbound handler error account=${conn.accountId}: ${String(err)}`);
|
|
4703
4890
|
}
|
|
4704
4891
|
}
|
|
4705
4892
|
});
|
|
@@ -4755,31 +4942,31 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4755
4942
|
const remoteJid = msg.key.remoteJid;
|
|
4756
4943
|
if (!remoteJid) return;
|
|
4757
4944
|
if (remoteJid === "status@broadcast") {
|
|
4758
|
-
console.error(`${
|
|
4945
|
+
console.error(`${TAG17} drop: status broadcast account=${conn.accountId}`);
|
|
4759
4946
|
return;
|
|
4760
4947
|
}
|
|
4761
4948
|
if (!msg.message) {
|
|
4762
|
-
console.error(`${
|
|
4949
|
+
console.error(`${TAG17} drop: empty message account=${conn.accountId} from=${remoteJid}`);
|
|
4763
4950
|
return;
|
|
4764
4951
|
}
|
|
4765
4952
|
const dedupKey = `${conn.accountId}:${remoteJid}:${msg.key.id}`;
|
|
4766
4953
|
if (isDuplicateInbound(dedupKey)) {
|
|
4767
|
-
console.error(`${
|
|
4954
|
+
console.error(`${TAG17} drop: duplicate account=${conn.accountId} key=${dedupKey}`);
|
|
4768
4955
|
return;
|
|
4769
4956
|
}
|
|
4770
4957
|
if (msg.key.fromMe) {
|
|
4771
4958
|
if (msg.key.id && isAgentSentMessage(msg.key.id)) {
|
|
4772
|
-
console.error(`${
|
|
4959
|
+
console.error(`${TAG17} drop: echo suppression account=${conn.accountId} msgId=${msg.key.id}`);
|
|
4773
4960
|
return;
|
|
4774
4961
|
}
|
|
4775
4962
|
const extracted2 = extractMessage(msg);
|
|
4776
4963
|
if (!extracted2.text) {
|
|
4777
|
-
console.error(`${
|
|
4964
|
+
console.error(`${TAG17} owner reply skipped \u2014 no text content account=${conn.accountId}`);
|
|
4778
4965
|
return;
|
|
4779
4966
|
}
|
|
4780
4967
|
const isGroup2 = isGroupJid(remoteJid);
|
|
4781
4968
|
const senderPhone2 = conn.selfPhone ?? "owner";
|
|
4782
|
-
console.error(`${
|
|
4969
|
+
console.error(`${TAG17} owner reply mirrored to session from=${senderPhone2} account=${conn.accountId}`);
|
|
4783
4970
|
const reply2 = async (text) => {
|
|
4784
4971
|
const currentSock = conn.sock;
|
|
4785
4972
|
if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
|
|
@@ -4813,7 +5000,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4813
5000
|
}
|
|
4814
5001
|
const extracted = extractMessage(msg);
|
|
4815
5002
|
if (!extracted.text && !extracted.mediaType) {
|
|
4816
|
-
console.error(`${
|
|
5003
|
+
console.error(`${TAG17} drop: no text or media account=${conn.accountId} from=${remoteJid}`);
|
|
4817
5004
|
return;
|
|
4818
5005
|
}
|
|
4819
5006
|
const isGroup = isGroupJid(remoteJid);
|
|
@@ -4837,7 +5024,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4837
5024
|
});
|
|
4838
5025
|
}
|
|
4839
5026
|
console.error(
|
|
4840
|
-
`${
|
|
5027
|
+
`${TAG17} inbound account=${conn.accountId} from=${senderPhone} group=${isGroup} access=${accessResult.allowed ? "allowed" : "blocked"}(${accessResult.reason}) agent=${accessResult.agentType}` + (extracted.mediaType ? ` media=${extracted.mediaType}` : "") + (extracted.quotedMessage ? ` replyTo=${extracted.quotedMessage.id}` : "")
|
|
4841
5028
|
);
|
|
4842
5029
|
if (!accessResult.allowed && accessResult.reason === "account-manager-unresolved") {
|
|
4843
5030
|
console.error(
|
|
@@ -4874,7 +5061,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4874
5061
|
maxBytes: maxMb * 1024 * 1024
|
|
4875
5062
|
});
|
|
4876
5063
|
if (!mediaResult) {
|
|
4877
|
-
console.error(`${
|
|
5064
|
+
console.error(`${TAG17} media download returned undefined account=${conn.accountId} type=${extracted.mediaType} from=${remoteJid}`);
|
|
4878
5065
|
}
|
|
4879
5066
|
}
|
|
4880
5067
|
if (extracted.mediaType === "audio" && mediaResult?.path) {
|
|
@@ -4896,7 +5083,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4896
5083
|
}
|
|
4897
5084
|
const reply = async (text) => {
|
|
4898
5085
|
if (isGroupJid(remoteJid)) {
|
|
4899
|
-
console.error(`${
|
|
5086
|
+
console.error(`${TAG17} op=group-reply-blocked jid=${remoteJid}`);
|
|
4900
5087
|
throw new WaReplyError("group reply blocked \u2014 observe-only", false);
|
|
4901
5088
|
}
|
|
4902
5089
|
const currentSock = conn.sock;
|
|
@@ -4943,15 +5130,15 @@ async function handleInboundMessage(conn, msg) {
|
|
|
4943
5130
|
if (accessResult.agentType === "public") {
|
|
4944
5131
|
const hoursResult = await isBusinessOpen(conn.accountId);
|
|
4945
5132
|
if (!hoursResult.open) {
|
|
4946
|
-
console.error(`${
|
|
5133
|
+
console.error(`${TAG17} [${conn.accountId}] dispatch skipped: business closed`);
|
|
4947
5134
|
const afterHoursMessage = whatsAppConfig.accounts?.[conn.accountId]?.afterHoursMessage ?? whatsAppConfig.afterHoursMessage;
|
|
4948
5135
|
if (afterHoursMessage) {
|
|
4949
5136
|
try {
|
|
4950
5137
|
await reply(afterHoursMessage);
|
|
4951
|
-
console.error(`${
|
|
5138
|
+
console.error(`${TAG17} [${conn.accountId}] after-hours auto-reply sent to ${remoteJid}`);
|
|
4952
5139
|
} catch (err) {
|
|
4953
5140
|
console.error(
|
|
4954
|
-
`${
|
|
5141
|
+
`${TAG17} [${conn.accountId}] after-hours auto-reply failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4955
5142
|
);
|
|
4956
5143
|
}
|
|
4957
5144
|
}
|
|
@@ -5000,6 +5187,7 @@ export {
|
|
|
5000
5187
|
getAuthAgeMs,
|
|
5001
5188
|
clearAuth,
|
|
5002
5189
|
discardAuthDirSync,
|
|
5190
|
+
startVersionDriftCensus,
|
|
5003
5191
|
drainCredsSaveQueue,
|
|
5004
5192
|
createWaSocket,
|
|
5005
5193
|
waitForConnection,
|
|
@@ -5007,6 +5195,8 @@ export {
|
|
|
5007
5195
|
formatError,
|
|
5008
5196
|
closeKind,
|
|
5009
5197
|
classifyDisconnect,
|
|
5198
|
+
LINK_CENSUS_INTERVAL_MS,
|
|
5199
|
+
runLinkCensus,
|
|
5010
5200
|
normalizeE164,
|
|
5011
5201
|
toWhatsappJid,
|
|
5012
5202
|
jidToE164,
|