@rubytech/create-maxy-code 0.1.342 → 0.1.344
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/config/brand.json +4 -1
- package/payload/platform/neo4j/schema.cypher +9 -5
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +4 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-hostname.test.d.ts +2 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-hostname.test.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-hostname.test.js +175 -0
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-hostname.test.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +33 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/admin-hostname.d.ts +15 -0
- package/payload/platform/plugins/admin/mcp/dist/lib/admin-hostname.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/lib/admin-hostname.js +86 -0
- package/payload/platform/plugins/admin/mcp/dist/lib/admin-hostname.js.map +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +90 -1
- package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +82 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/functions/api/book.ts +112 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/booking.css +100 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/booking.js +155 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/index.html +47 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/schema.sql +18 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/template/wrangler.toml +14 -0
- package/payload/platform/plugins/docs/PLUGIN.md +1 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +26 -0
- package/payload/platform/plugins/docs/references/calendar-booking.md +56 -0
- package/payload/platform/plugins/docs/references/internals.md +2 -0
- package/payload/platform/plugins/scheduling/PLUGIN.md +23 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +19 -5
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-notify.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-notify.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-notify.test.js +45 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-notify.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js +89 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/booking-reconcile.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-write.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-write.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-write.test.js +118 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/meeting-write.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-classify.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-classify.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-classify.test.js +59 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-classify.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-notify.d.ts +22 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-notify.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-notify.js +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-notify.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts +28 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js +70 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/booking-reconcile.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts +35 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js +123 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-classify.d.ts +23 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-classify.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-classify.js +38 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-classify.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts +21 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +280 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +11 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +34 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +2 -0
- package/payload/server/{chunk-5BG6CHGH.js → chunk-QAKVFSEJ.js} +15 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-Brx8CmXN.js → AdminLoginScreens-CZqsFfP0.js} +1 -1
- package/payload/server/public/assets/AdminShell-DnhBRZv5.js +1 -0
- package/payload/server/public/assets/{Checkbox-aePjWzRH.js → Checkbox-D0FwyuVg.js} +1 -1
- package/payload/server/public/assets/{OperatorConversations-BMIZQR9t.css → OperatorConversations-BG9GrxQU.css} +1 -1
- package/payload/server/public/assets/OperatorConversations-dt0q8mjv.js +9 -0
- package/payload/server/public/assets/admin-CCzmqd1F.js +1 -0
- package/payload/server/public/assets/{arc-CxLB9WCE.js → arc-DpkSQNto.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Csj53u5T.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-D-EdJPSY.js → architectureDiagram-Q4EWVU46-Bw7Yq8O9.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CXx9RgCm.js → blockDiagram-DXYQGD6D-BBtJQFSz.js} +1 -1
- package/payload/server/public/assets/{browser-Bp5kGgyr.js → browser-kmrJq69n.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-RFBXEe0B.js → c4Diagram-AHTNJAMY-JAMgxzOr.js} +1 -1
- package/payload/server/public/assets/calendar-BWf5qrIH.js +1 -0
- package/payload/server/public/assets/channel-BUQUAUts.js +1 -0
- package/payload/server/public/assets/chat-C2e06_q0.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-DBqAFwK9.js → chunk-2KRD3SAO-eDugsc2L.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-DdnFEz6R.js → chunk-336JU56O-BXfECwdC.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-CdknReB2.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-cnw-3Gbs.js → chunk-4BX2VUAB-CByVeKCY.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BnqJ0bDc.js → chunk-4TB4RGXK-CpY0DcUB.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-BwyHvvzo.js → chunk-55IACEB6-C3YxgyIb.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-DXA9U02I.js → chunk-5FUZZQ4R-Bc0d7j8A.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-D78bZ_8D.js → chunk-5PVQY5BW-CTUGMRIa.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-CtE_Mgv7.js → chunk-67CJDMHE-CbdPnpLd.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-CUZDaySl.js → chunk-7N4EOEYR-Cjl2kevz.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-CYQ3jO4X.js → chunk-AA7GKIK3-BgozIh5p.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-BbA_HyTR.js → chunk-BSJP7CBP-6Ufq45NW.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-D7_YqRhG.js → chunk-CIAEETIT-BhhYuMnA.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-B23LrtSw.js → chunk-EDXVE4YY-BfaJ3yDD.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-D3fTHYKN.js → chunk-ENJZ2VHE-C7-hIGVC.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-DFAA2tyh.js → chunk-FMBD7UC4-BQvvyocF.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-BF4IHvlI.js → chunk-FOC6F5B3-C6rBDOxH.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-DBUGemHy.js → chunk-ICPOFSXX-BjOJvkVa.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-rMMs08Eh.js → chunk-K5T4RW27-kKowRHhn.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-BD2r8R2G.js → chunk-KGLVRYIC-bAEV_5eH.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-D4sYTTwM.js → chunk-LIHQZDEY-BLvsQAfg.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-CAs_uFzb.js → chunk-ORNJ4GCN-BzYZfPZ7.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-Fkp-2ORc.js → chunk-OYMX7WX6-CL7WRw42.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-8tHoEDE9.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-D_pxZh25.js → chunk-U2HBQHQK-BdcVGjau.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CeVmvvRf.js → chunk-X2U36JSP-C0CL_Jin.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-iWP54fKp.js → chunk-XPW4576I-CsV7CUxH.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-CNtbWJNN.js → chunk-YZCP3GAM-Cj0_fLkR.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BmlFjU_9.js → chunk-ZZ45TVLE-DLuquyoY.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BEGZ3DLg.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DsLxnm5U.js +1 -0
- package/payload/server/public/assets/clone-uiXbH_kh.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-C7YmF1Pg.js → cose-bilkent-S5V4N54A-BU3EOLXX.js} +1 -1
- package/payload/server/public/assets/{dagre-BAmiDDtR.js → dagre-BRq8C9NU.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-Ca3ESJhc.js → dagre-KV5264BT-CoCAYhFc.js} +1 -1
- package/payload/server/public/assets/data-CZKWSjEH.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-BgT1ORf2.js → diagram-5BDNPKRD-DBy5GNaQ.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BTaUIiem.js → diagram-G4DWMVQ6-l93MsBLv.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-Bdb2g6Uo.js → diagram-MMDJMWI5-BIfXkVlL.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CkLGC0zZ.js → diagram-TYMM5635-BuTJLBny.js} +1 -1
- package/payload/server/public/assets/{dist-Bkbhs3jw.js → dist-CtUNt3w8.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-D_sj4DMg.js → erDiagram-SMLLAGMA-BwPxWDbP.js} +1 -1
- package/payload/server/public/assets/{flatten-E2Sr0FeD.js → flatten-DtM0XAMt.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-iLERoZTe.js → flowDiagram-DWJPFMVM-BhPtHXMR.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-D60hjMBy.js → ganttDiagram-T4ZO3ILL-BlXjprdD.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-D_2KrZoP.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-Di0XM6fi.js → gitGraphDiagram-UUTBAWPF-BW36BDiu.js} +1 -1
- package/payload/server/public/assets/{graph-Bnsvbnkf.js → graph-BxErrIf_.js} +3 -3
- package/payload/server/public/assets/{graph-labels-jduMtwXb.js → graph-labels-Ch5_g_JF.js} +1 -1
- package/payload/server/public/assets/{graphlib-C8fUP7uV.js → graphlib-Bjg3Tq-k.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BP2TNwQ4.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-D1kDtBOY.js +2 -0
- package/payload/server/public/assets/{isEmpty-CLz-UprQ.js → isEmpty-D__iH1WQ.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CwgI4B5Z.js → ishikawaDiagram-UXIWVN3A-CmB-bA_O.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CxBu-tze.js → journeyDiagram-VCZTEJTY-Bt1fJKmc.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-D2qlheA5.js → kanban-definition-6JOO6SKY-DVbksz_J.js} +1 -1
- package/payload/server/public/assets/{line-Bdod7uzQ.js → line-BX2Ugx3B.js} +1 -1
- package/payload/server/public/assets/{linear-BiVe6QzC.js → linear-Bdc-QJWI.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-xZN7hC6M.js → mermaid-parser.core-qv1e-J5x.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-D0IylAac.js → mermaid.core-C_d9YQX_.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-J_Szhwf1.js → mindmap-definition-QFDTVHPH-DwKGvF14.js} +1 -1
- package/payload/server/public/assets/operator-CdlBsCdn.js +1 -0
- package/payload/server/public/assets/{ordinal-5RtyPJVt.js → ordinal-BRQ5CzZY.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-BDg8fde8.js +1 -0
- package/payload/server/public/assets/{page-BT9hkXHm.js → page-DzsVxvM6.js} +3 -3
- package/payload/server/public/assets/pie-ZZUOXDRM-CXDyYMkZ.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CV5DxUVx.js → pieDiagram-DEJITSTG-dUvQC_4S.js} +1 -1
- package/payload/server/public/assets/{public-DvL1Zov1.js → public-BzVhn2va.js} +1 -1
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BsFMVizF.js → quadrantDiagram-34T5L4WZ-CebX_oPa.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-xen_zv8F.js +1 -0
- package/payload/server/public/assets/{reduce-B3Mw_0s1.js → reduce-CkcXOmmJ.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-C5eRRvGc.js → requirementDiagram-MS252O5E-h2euIqGj.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-CJYv5gpw.js → sankeyDiagram-XADWPNL6-DCii3fkF.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-B25563_2.js → sequenceDiagram-FGHM5R23-CQSGYmlq.js} +1 -1
- package/payload/server/public/assets/{src-BKOAoFQc.js → src-48kCpScq.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BLyNJYOA.js → stateDiagram-FHFEXIEX-CVtU0iXH.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BywcXjtb.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-D-HgOM6Q.js → timeline-definition-GMOUNBTQ-ChvsBltI.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-2FBf_1It.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-BDdb30P-.js +1 -0
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-Cw1JElYp.js → vennDiagram-DHZGUBPP-e-EZiiba.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-BLq5MxjR.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BqMWzEko.js → wardleyDiagram-NUSXRM2D-4JaRn1s5.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DBp71TLT.js → xychartDiagram-5P7HB3ND-kxwmCNuM.js} +1 -1
- package/payload/server/public/brand/maxy-app-icon-192.png +0 -0
- package/payload/server/public/brand/maxy-app-icon-512.png +0 -0
- package/payload/server/public/brand/maxy-app-icon-maskable-512.png +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +17 -0
- package/payload/server/public/chat.html +8 -8
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +7 -7
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/operator.html +10 -10
- package/payload/server/public/public.html +8 -8
- package/payload/server/server.js +623 -190
- package/payload/server/public/assets/AdminShell-CHZMDX2u.js +0 -1
- package/payload/server/public/assets/OperatorConversations-DpjPPIOp.js +0 -9
- package/payload/server/public/assets/admin-DIDvfti6.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-DN-MYxff.js +0 -1
- package/payload/server/public/assets/channel-y27xl53N.js +0 -1
- package/payload/server/public/assets/chat-C0IWx7FL.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-D8Iwaegm.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-qHqDpwz3.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DgVoYWhO.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C0WNP3uN.js +0 -1
- package/payload/server/public/assets/clone-D50F_pvg.js +0 -1
- package/payload/server/public/assets/data-RsMye_06.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-D-L2yzYf.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-BQn6jndO.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-BwMdbiXg.js +0 -2
- package/payload/server/public/assets/operator-9K-TElDd.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DmkQBx4h.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-DDnxYUBm.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-7H4k0ChM.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BSVuxZxz.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BLXWTQtW.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-DiePDF5d.js +0 -1
- package/payload/server/public/assets/wardley-RL74JXVD-OSUWK5LN.js +0 -1
- /package/payload/server/public/assets/{_baseFor-DVaNaTfF.js → _baseFor-SRtUHe7G.js} +0 -0
- /package/payload/server/public/assets/{admin-types-CJrGd46U.js → admin-types-Dg11L4MQ.js} +0 -0
- /package/payload/server/public/assets/{array-8_H1156C.js → array-BpsnM-Py.js} +0 -0
- /package/payload/server/public/assets/{chunk-Pqm5yXtL.js → chunk-CAM3fms7.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-h10p_6j-.js → cytoscape.esm-D4Rl1H5h.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-pD7tFa1r.js → defaultLocale-C7sQPl-O.js} +0 -0
- /package/payload/server/public/assets/{init-CwJ4b81e.js → init-BydxaDEV.js} +0 -0
- /package/payload/server/public/assets/{katex-DJPjIBAI.js → katex-B0fVeDx4.js} +0 -0
- /package/payload/server/public/assets/{path-CK8wrAxY.js → path-jlWYQ2i9.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-Bf_JiD2A.js → preload-helper-uTix4PVD.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-Dwml_la6.js → rough.esm-c4PR5shF.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -105,7 +105,7 @@ import {
|
|
|
105
105
|
vncLog,
|
|
106
106
|
walkPremiumBundles,
|
|
107
107
|
writeAdminUserAndPerson
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-QAKVFSEJ.js";
|
|
109
109
|
import {
|
|
110
110
|
__commonJS,
|
|
111
111
|
__toESM
|
|
@@ -1292,8 +1292,9 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1292
1292
|
};
|
|
1293
1293
|
|
|
1294
1294
|
// server/index.ts
|
|
1295
|
-
import { readFileSync as
|
|
1296
|
-
import {
|
|
1295
|
+
import { readFileSync as readFileSync33, existsSync as existsSync31, watchFile } from "fs";
|
|
1296
|
+
import { spawn as spawn3 } from "child_process";
|
|
1297
|
+
import { resolve as resolve33, join as join30, basename as basename10 } from "path";
|
|
1297
1298
|
import { homedir as homedir3 } from "os";
|
|
1298
1299
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1299
1300
|
|
|
@@ -1343,7 +1344,15 @@ function buildManifest(s, b) {
|
|
|
1343
1344
|
display: "standalone",
|
|
1344
1345
|
theme_color: b.themeColor,
|
|
1345
1346
|
background_color: b.backgroundColor,
|
|
1346
|
-
|
|
1347
|
+
// Explicit 192/512 `any` icons (iOS/macOS composite transparency onto black,
|
|
1348
|
+
// so these are opaque) plus a wider-safe-zone `maskable` entry for Android's
|
|
1349
|
+
// circular crop. background_color sets only the splash; the tile background
|
|
1350
|
+
// is baked into the PNGs.
|
|
1351
|
+
icons: [
|
|
1352
|
+
{ src: b.appIcon192, sizes: "192x192", purpose: "any" },
|
|
1353
|
+
{ src: b.appIcon512, sizes: "512x512", purpose: "any" },
|
|
1354
|
+
{ src: b.maskableIcon, sizes: "512x512", purpose: "maskable" }
|
|
1355
|
+
]
|
|
1347
1356
|
};
|
|
1348
1357
|
}
|
|
1349
1358
|
function escAttr(s) {
|
|
@@ -1358,18 +1367,20 @@ function swRegisterScript(s) {
|
|
|
1358
1367
|
"</script>"
|
|
1359
1368
|
].join("\n");
|
|
1360
1369
|
}
|
|
1361
|
-
function
|
|
1370
|
+
function installHeadLines(manifestPath, b) {
|
|
1362
1371
|
return [
|
|
1363
|
-
`<link rel="manifest" href="${escAttr(
|
|
1364
|
-
`<link rel="apple-touch-icon" href="${escAttr(b.
|
|
1372
|
+
`<link rel="manifest" href="${escAttr(manifestPath)}">`,
|
|
1373
|
+
`<link rel="apple-touch-icon" href="${escAttr(b.appleTouchIcon)}">`,
|
|
1365
1374
|
// Both the standards-based and the legacy Apple capable meta: Chromium
|
|
1366
1375
|
// deprecates `apple-mobile-web-app-capable` in favour of
|
|
1367
1376
|
// `mobile-web-app-capable`, while iOS Safari still reads the apple one.
|
|
1368
1377
|
'<meta name="mobile-web-app-capable" content="yes">',
|
|
1369
1378
|
'<meta name="apple-mobile-web-app-capable" content="yes">',
|
|
1370
|
-
`<meta name="theme-color" content="${escAttr(b.themeColor)}"
|
|
1371
|
-
|
|
1372
|
-
|
|
1379
|
+
`<meta name="theme-color" content="${escAttr(b.themeColor)}">`
|
|
1380
|
+
];
|
|
1381
|
+
}
|
|
1382
|
+
function pwaHeadTags(s, b) {
|
|
1383
|
+
return [...installHeadLines(s.manifestPath, b), swRegisterScript(s)].join("\n");
|
|
1373
1384
|
}
|
|
1374
1385
|
function pwaCensus(d) {
|
|
1375
1386
|
const manifestLinked = PWA_SURFACES.filter((s) => {
|
|
@@ -5328,8 +5339,8 @@ function webchatTurnTimeoutMs() {
|
|
|
5328
5339
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
5329
5340
|
}
|
|
5330
5341
|
function createChatRoutes(deps) {
|
|
5331
|
-
const
|
|
5332
|
-
|
|
5342
|
+
const app55 = new Hono();
|
|
5343
|
+
app55.post("/", async (c) => {
|
|
5333
5344
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
5334
5345
|
const contentType = c.req.header("content-type") ?? "";
|
|
5335
5346
|
const account = resolveAccount();
|
|
@@ -5592,7 +5603,7 @@ ${result.result.text}` : result.result.text;
|
|
|
5592
5603
|
}
|
|
5593
5604
|
});
|
|
5594
5605
|
});
|
|
5595
|
-
return
|
|
5606
|
+
return app55;
|
|
5596
5607
|
}
|
|
5597
5608
|
|
|
5598
5609
|
// server/routes/whatsapp.ts
|
|
@@ -8634,8 +8645,8 @@ async function reapplyLeversViaManager() {
|
|
|
8634
8645
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
8635
8646
|
var sendSeq = 0;
|
|
8636
8647
|
function createWebchatRoutes(deps) {
|
|
8637
|
-
const
|
|
8638
|
-
|
|
8648
|
+
const app55 = new Hono();
|
|
8649
|
+
app55.post("/send", requireAdminSession, async (c) => {
|
|
8639
8650
|
let accountId;
|
|
8640
8651
|
try {
|
|
8641
8652
|
accountId = resolvePlatformAccountId();
|
|
@@ -8805,7 +8816,7 @@ ${note}` : note;
|
|
|
8805
8816
|
if (turnTimer.unref) turnTimer.unref();
|
|
8806
8817
|
return c.json({ ok: true });
|
|
8807
8818
|
});
|
|
8808
|
-
|
|
8819
|
+
app55.post("/settings", requireAdminSession, async (c) => {
|
|
8809
8820
|
const body = await c.req.json().catch(() => null);
|
|
8810
8821
|
const op = body?.op;
|
|
8811
8822
|
const value = body?.value;
|
|
@@ -8845,7 +8856,7 @@ ${note}` : note;
|
|
|
8845
8856
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
8846
8857
|
return c.json({ ok: true, settingsApplied });
|
|
8847
8858
|
});
|
|
8848
|
-
|
|
8859
|
+
app55.get("/session", requireAdminSession, async (c) => {
|
|
8849
8860
|
let accountId;
|
|
8850
8861
|
try {
|
|
8851
8862
|
accountId = resolvePlatformAccountId();
|
|
@@ -8921,7 +8932,7 @@ ${note}` : note;
|
|
|
8921
8932
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
8922
8933
|
return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
|
|
8923
8934
|
});
|
|
8924
|
-
|
|
8935
|
+
app55.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
8925
8936
|
const body = await c.req.json().catch(() => null);
|
|
8926
8937
|
const sessionId = body?.sessionId;
|
|
8927
8938
|
const requestId = body?.request_id;
|
|
@@ -8938,7 +8949,7 @@ ${note}` : note;
|
|
|
8938
8949
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
8939
8950
|
return c.json({ ok });
|
|
8940
8951
|
});
|
|
8941
|
-
return
|
|
8952
|
+
return app55;
|
|
8942
8953
|
}
|
|
8943
8954
|
|
|
8944
8955
|
// server/routes/webchat-greeting.ts
|
|
@@ -13449,6 +13460,89 @@ async function dropFileIndex(accountId, relativePath, opts) {
|
|
|
13449
13460
|
});
|
|
13450
13461
|
}
|
|
13451
13462
|
|
|
13463
|
+
// server/lib/zip.ts
|
|
13464
|
+
import { deflateRawSync } from "zlib";
|
|
13465
|
+
var LOCAL_SIG = 67324752;
|
|
13466
|
+
var CENTRAL_SIG = 33639248;
|
|
13467
|
+
var EOCD_SIG = 101010256;
|
|
13468
|
+
var VERSION = 20;
|
|
13469
|
+
var FLAG_UTF8 = 2048;
|
|
13470
|
+
var crcTable = null;
|
|
13471
|
+
function crc32(buf) {
|
|
13472
|
+
if (!crcTable) {
|
|
13473
|
+
crcTable = new Uint32Array(256);
|
|
13474
|
+
for (let n = 0; n < 256; n++) {
|
|
13475
|
+
let c = n;
|
|
13476
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
13477
|
+
crcTable[n] = c >>> 0;
|
|
13478
|
+
}
|
|
13479
|
+
}
|
|
13480
|
+
let crc = 4294967295;
|
|
13481
|
+
for (let i = 0; i < buf.length; i++) crc = crcTable[(crc ^ buf[i]) & 255] ^ crc >>> 8;
|
|
13482
|
+
return (crc ^ 4294967295) >>> 0;
|
|
13483
|
+
}
|
|
13484
|
+
function buildZip(entries) {
|
|
13485
|
+
const localChunks = [];
|
|
13486
|
+
const centralChunks = [];
|
|
13487
|
+
let offset = 0;
|
|
13488
|
+
for (const entry of entries) {
|
|
13489
|
+
const nameBytes = Buffer.from(entry.name, "utf8");
|
|
13490
|
+
const crc = crc32(entry.data);
|
|
13491
|
+
const uncompressedSize = entry.data.length;
|
|
13492
|
+
const deflated = deflateRawSync(entry.data);
|
|
13493
|
+
const useDeflate = deflated.length < uncompressedSize;
|
|
13494
|
+
const method = useDeflate ? 8 : 0;
|
|
13495
|
+
const payload = useDeflate ? deflated : entry.data;
|
|
13496
|
+
const compressedSize = payload.length;
|
|
13497
|
+
const localHeader = Buffer.alloc(30);
|
|
13498
|
+
localHeader.writeUInt32LE(LOCAL_SIG, 0);
|
|
13499
|
+
localHeader.writeUInt16LE(VERSION, 4);
|
|
13500
|
+
localHeader.writeUInt16LE(FLAG_UTF8, 6);
|
|
13501
|
+
localHeader.writeUInt16LE(method, 8);
|
|
13502
|
+
localHeader.writeUInt16LE(0, 10);
|
|
13503
|
+
localHeader.writeUInt16LE(0, 12);
|
|
13504
|
+
localHeader.writeUInt32LE(crc, 14);
|
|
13505
|
+
localHeader.writeUInt32LE(compressedSize, 18);
|
|
13506
|
+
localHeader.writeUInt32LE(uncompressedSize, 22);
|
|
13507
|
+
localHeader.writeUInt16LE(nameBytes.length, 26);
|
|
13508
|
+
localHeader.writeUInt16LE(0, 28);
|
|
13509
|
+
localChunks.push(localHeader, nameBytes, payload);
|
|
13510
|
+
const centralHeader = Buffer.alloc(46);
|
|
13511
|
+
centralHeader.writeUInt32LE(CENTRAL_SIG, 0);
|
|
13512
|
+
centralHeader.writeUInt16LE(VERSION, 4);
|
|
13513
|
+
centralHeader.writeUInt16LE(VERSION, 6);
|
|
13514
|
+
centralHeader.writeUInt16LE(FLAG_UTF8, 8);
|
|
13515
|
+
centralHeader.writeUInt16LE(method, 10);
|
|
13516
|
+
centralHeader.writeUInt16LE(0, 12);
|
|
13517
|
+
centralHeader.writeUInt16LE(0, 14);
|
|
13518
|
+
centralHeader.writeUInt32LE(crc, 16);
|
|
13519
|
+
centralHeader.writeUInt32LE(compressedSize, 20);
|
|
13520
|
+
centralHeader.writeUInt32LE(uncompressedSize, 24);
|
|
13521
|
+
centralHeader.writeUInt16LE(nameBytes.length, 28);
|
|
13522
|
+
centralHeader.writeUInt16LE(0, 30);
|
|
13523
|
+
centralHeader.writeUInt16LE(0, 32);
|
|
13524
|
+
centralHeader.writeUInt16LE(0, 34);
|
|
13525
|
+
centralHeader.writeUInt16LE(0, 36);
|
|
13526
|
+
centralHeader.writeUInt32LE(0, 38);
|
|
13527
|
+
centralHeader.writeUInt32LE(offset, 42);
|
|
13528
|
+
centralChunks.push(centralHeader, nameBytes);
|
|
13529
|
+
offset += localHeader.length + nameBytes.length + payload.length;
|
|
13530
|
+
}
|
|
13531
|
+
const centralDir = Buffer.concat(centralChunks);
|
|
13532
|
+
const centralSize = centralDir.length;
|
|
13533
|
+
const centralOffset = offset;
|
|
13534
|
+
const eocd = Buffer.alloc(22);
|
|
13535
|
+
eocd.writeUInt32LE(EOCD_SIG, 0);
|
|
13536
|
+
eocd.writeUInt16LE(0, 4);
|
|
13537
|
+
eocd.writeUInt16LE(0, 6);
|
|
13538
|
+
eocd.writeUInt16LE(entries.length, 8);
|
|
13539
|
+
eocd.writeUInt16LE(entries.length, 10);
|
|
13540
|
+
eocd.writeUInt32LE(centralSize, 12);
|
|
13541
|
+
eocd.writeUInt32LE(centralOffset, 16);
|
|
13542
|
+
eocd.writeUInt16LE(0, 20);
|
|
13543
|
+
return Buffer.concat([...localChunks, centralDir, eocd]);
|
|
13544
|
+
}
|
|
13545
|
+
|
|
13452
13546
|
// server/routes/admin/files.ts
|
|
13453
13547
|
var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
13454
13548
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -13766,6 +13860,61 @@ app20.get("/download", requireAdminSession, async (c) => {
|
|
|
13766
13860
|
return c.json({ error: message }, 500);
|
|
13767
13861
|
}
|
|
13768
13862
|
});
|
|
13863
|
+
var ZIP_MAX_FILES = 200;
|
|
13864
|
+
var ZIP_MAX_TOTAL_BYTES = 256 * 1024 * 1024;
|
|
13865
|
+
app20.get("/download-zip", requireAdminSession, async (c) => {
|
|
13866
|
+
const cacheKey = c.var.cacheKey;
|
|
13867
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
13868
|
+
if (!accountId) {
|
|
13869
|
+
console.error(`[data] auth-rejected endpoint="/api/admin/files/download-zip" reason="no account for session"`);
|
|
13870
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
13871
|
+
}
|
|
13872
|
+
const rawPaths = c.req.queries("path") ?? [];
|
|
13873
|
+
if (rawPaths.length === 0) return c.json({ error: "path required" }, 400);
|
|
13874
|
+
if (rawPaths.length > ZIP_MAX_FILES) {
|
|
13875
|
+
return c.json({ error: `Too many files (max ${ZIP_MAX_FILES})` }, 413);
|
|
13876
|
+
}
|
|
13877
|
+
const entries = [];
|
|
13878
|
+
let total = 0;
|
|
13879
|
+
for (const rawPath of rawPaths) {
|
|
13880
|
+
const resolution = resolveDataPath(rawPath);
|
|
13881
|
+
if (!resolution.ok) {
|
|
13882
|
+
if (resolution.status === 403) {
|
|
13883
|
+
console.error(`[data] path-traversal-blocked endpoint="/api/admin/files/download-zip" requested="${rawPath}" resolved="${resolution.resolved ?? "n/a"}"`);
|
|
13884
|
+
}
|
|
13885
|
+
return c.json({ error: resolution.error }, resolution.status);
|
|
13886
|
+
}
|
|
13887
|
+
const { absolute, relative: relPath } = resolution;
|
|
13888
|
+
if (crossesForeignAccountPartition(relPath, accountId)) {
|
|
13889
|
+
console.error(`[data] account-scope-blocked endpoint="/api/admin/files/download-zip" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
13890
|
+
return c.json({ error: "Not found" }, 404);
|
|
13891
|
+
}
|
|
13892
|
+
try {
|
|
13893
|
+
const info = await stat5(absolute);
|
|
13894
|
+
if (!info.isFile()) return c.json({ error: "Path is not a file" }, 400);
|
|
13895
|
+
total += info.size;
|
|
13896
|
+
if (total > ZIP_MAX_TOTAL_BYTES) {
|
|
13897
|
+
return c.json({ error: "Selection too large to zip" }, 413);
|
|
13898
|
+
}
|
|
13899
|
+
entries.push({ name: basename8(absolute), data: await readFile5(absolute) });
|
|
13900
|
+
} catch (err) {
|
|
13901
|
+
const code = err.code;
|
|
13902
|
+
if (code === "ENOENT") return c.json({ error: "Not found" }, 404);
|
|
13903
|
+
throw err;
|
|
13904
|
+
}
|
|
13905
|
+
}
|
|
13906
|
+
const archive = buildZip(entries);
|
|
13907
|
+
console.error(`[data] file-download-zip files=${entries.length} bytes=${archive.length}`);
|
|
13908
|
+
return new Response(new Uint8Array(archive), {
|
|
13909
|
+
status: 200,
|
|
13910
|
+
headers: {
|
|
13911
|
+
"Content-Type": "application/zip",
|
|
13912
|
+
"Content-Length": String(archive.length),
|
|
13913
|
+
"Content-Disposition": `attachment; filename="files.zip"`,
|
|
13914
|
+
"Cache-Control": "no-store"
|
|
13915
|
+
}
|
|
13916
|
+
});
|
|
13917
|
+
});
|
|
13769
13918
|
function dataUploadCeiling() {
|
|
13770
13919
|
const override = Number(process.env.MAXY_DATA_UPLOAD_MAX_BYTES);
|
|
13771
13920
|
return Number.isFinite(override) && override > 0 ? override : MAX_DATA_UPLOAD_BYTES;
|
|
@@ -17431,49 +17580,118 @@ app42.post("/launch", requireAdminSession, async (c) => {
|
|
|
17431
17580
|
});
|
|
17432
17581
|
var browser_default = app42;
|
|
17433
17582
|
|
|
17434
|
-
// server/routes/admin/
|
|
17583
|
+
// server/routes/admin/calendar.ts
|
|
17435
17584
|
var app43 = new Hono();
|
|
17436
|
-
app43.
|
|
17437
|
-
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
|
|
17441
|
-
|
|
17442
|
-
|
|
17443
|
-
|
|
17444
|
-
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17585
|
+
app43.get("/meetings", requireAdminSession, async (c) => {
|
|
17586
|
+
const cacheKey = c.var.cacheKey;
|
|
17587
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
17588
|
+
if (!accountId) {
|
|
17589
|
+
console.error('[calendar] op=admin-read auth-rejected reason="no account for session"');
|
|
17590
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
17591
|
+
}
|
|
17592
|
+
const from = c.req.query("from");
|
|
17593
|
+
const to = c.req.query("to");
|
|
17594
|
+
if (!from || !to) return c.json({ error: "from and to (ISO) required" }, 400);
|
|
17595
|
+
const session = getSession();
|
|
17596
|
+
try {
|
|
17597
|
+
const res = await session.run(
|
|
17598
|
+
`MATCH (m:Meeting {accountId: $accountId})
|
|
17599
|
+
WHERE NOT (m.endsAt IS NOT NULL AND m.endsAt <= datetime($from))
|
|
17600
|
+
AND m.startsAt < datetime($to)
|
|
17601
|
+
RETURN elementId(m) AS id, m.title AS title,
|
|
17602
|
+
toString(m.startsAt) AS startsAt, toString(m.endsAt) AS endsAt,
|
|
17603
|
+
m.location AS location, coalesce(m.isAllDay, false) AS isAllDay,
|
|
17604
|
+
'meeting' AS kind
|
|
17605
|
+
UNION
|
|
17606
|
+
MATCH (e:Event {accountId: $accountId})
|
|
17607
|
+
WHERE e.actionPlugin IS NULL
|
|
17608
|
+
AND NOT (e.endDate IS NOT NULL AND datetime(e.endDate) <= datetime($from))
|
|
17609
|
+
AND datetime(e.startDate) < datetime($to)
|
|
17610
|
+
RETURN elementId(e) AS id, e.name AS title,
|
|
17611
|
+
toString(datetime(e.startDate)) AS startsAt,
|
|
17612
|
+
CASE WHEN e.endDate IS NULL THEN null ELSE toString(datetime(e.endDate)) END AS endsAt,
|
|
17613
|
+
e.location AS location, false AS isAllDay,
|
|
17614
|
+
'event' AS kind
|
|
17615
|
+
UNION
|
|
17616
|
+
MATCH (t:Task {accountId: $accountId})
|
|
17617
|
+
WHERE t.dueDate IS NOT NULL
|
|
17618
|
+
AND datetime(t.dueDate) >= datetime($from)
|
|
17619
|
+
AND datetime(t.dueDate) < datetime($to)
|
|
17620
|
+
RETURN elementId(t) AS id, t.name AS title,
|
|
17621
|
+
toString(datetime(t.dueDate)) AS startsAt, null AS endsAt,
|
|
17622
|
+
null AS location, true AS isAllDay,
|
|
17623
|
+
'task' AS kind`,
|
|
17624
|
+
{ accountId, from, to }
|
|
17625
|
+
);
|
|
17626
|
+
const meetings = res.records.map((r) => ({
|
|
17627
|
+
meetingId: r.get("id"),
|
|
17628
|
+
title: r.get("title"),
|
|
17629
|
+
startsAt: r.get("startsAt"),
|
|
17630
|
+
endsAt: r.get("endsAt"),
|
|
17631
|
+
location: r.get("location"),
|
|
17632
|
+
isAllDay: r.get("isAllDay"),
|
|
17633
|
+
kind: r.get("kind")
|
|
17634
|
+
})).sort((a, b) => new Date(a.startsAt).getTime() - new Date(b.startsAt).getTime());
|
|
17635
|
+
const counts = { meeting: 0, event: 0, task: 0 };
|
|
17636
|
+
for (const m of meetings) counts[m.kind]++;
|
|
17637
|
+
console.log(
|
|
17638
|
+
`[calendar] op=admin-read events=${counts.event} meetings=${counts.meeting} tasks=${counts.task} range=${from}..${to}`
|
|
17639
|
+
);
|
|
17640
|
+
return c.json({ meetings });
|
|
17641
|
+
} catch (err) {
|
|
17642
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17643
|
+
console.error(`[calendar] op=admin-read-fail err="${message}"`);
|
|
17644
|
+
return c.json({ error: `Calendar unavailable: ${message}` }, 503);
|
|
17645
|
+
} finally {
|
|
17646
|
+
await session.close();
|
|
17647
|
+
}
|
|
17648
|
+
});
|
|
17649
|
+
var calendar_default = app43;
|
|
17650
|
+
|
|
17651
|
+
// server/routes/admin/index.ts
|
|
17652
|
+
var app44 = new Hono();
|
|
17653
|
+
app44.route("/session", session_default);
|
|
17654
|
+
app44.route("/logs", logs_default);
|
|
17655
|
+
app44.route("/claude-info", claude_info_default);
|
|
17656
|
+
app44.route("/attachment", attachment_default);
|
|
17657
|
+
app44.route("/agents", agents_default);
|
|
17658
|
+
app44.route("/sessions", sessions_default);
|
|
17659
|
+
app44.route("/claude-sessions", claude_sessions_default);
|
|
17660
|
+
app44.route("/log-ingest", log_ingest_default);
|
|
17661
|
+
app44.route("/events", events_default);
|
|
17662
|
+
app44.route("/files", files_default);
|
|
17663
|
+
app44.route("/graph-search", graph_search_default);
|
|
17664
|
+
app44.route("/graph-subgraph", graph_subgraph_default);
|
|
17665
|
+
app44.route("/graph-delete", graph_delete_default);
|
|
17666
|
+
app44.route("/graph-restore", graph_restore_default);
|
|
17667
|
+
app44.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
17668
|
+
app44.route("/graph-default-view", graph_default_view_default);
|
|
17669
|
+
app44.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
17670
|
+
app44.route("/sidebar-sessions", sidebar_sessions_default);
|
|
17671
|
+
app44.route("/session-delete", session_delete_default);
|
|
17672
|
+
app44.route("/session-stop", session_stop_default);
|
|
17673
|
+
app44.route("/session-archive", session_archive_default);
|
|
17674
|
+
app44.route("/session-rename", session_rename_default);
|
|
17675
|
+
app44.route("/browser", browser_default);
|
|
17676
|
+
app44.route("/session-rc-spawn", session_rc_spawn_default);
|
|
17677
|
+
app44.route("/session-reseat", session_reseat_default);
|
|
17678
|
+
app44.route("/system-stats", system_stats_default);
|
|
17679
|
+
app44.route("/health-brand", health_default2);
|
|
17680
|
+
app44.route("/linkedin-ingest", linkedin_ingest_default);
|
|
17681
|
+
app44.route("/post-turn-context", post_turn_context_default);
|
|
17682
|
+
app44.route("/public-session-context", public_session_context_default);
|
|
17683
|
+
app44.route("/public-session-exit", public_session_exit_default);
|
|
17684
|
+
app44.route("/access-session-evict", access_session_evict_default);
|
|
17685
|
+
app44.route("/enrol-person", enrol_person_default);
|
|
17686
|
+
app44.route("/calendar", calendar_default);
|
|
17687
|
+
var admin_default = app44;
|
|
17470
17688
|
|
|
17471
17689
|
// server/routes/access/verify-token.ts
|
|
17472
17690
|
var TAG37 = "[access-verify]";
|
|
17473
17691
|
var MINT_TAG = "[access-session-mint]";
|
|
17474
17692
|
var COOKIE_NAME = "__access_session";
|
|
17475
|
-
var
|
|
17476
|
-
|
|
17693
|
+
var app45 = new Hono();
|
|
17694
|
+
app45.post("/", async (c) => {
|
|
17477
17695
|
const ip = c.var.clientIp || "unknown";
|
|
17478
17696
|
let body;
|
|
17479
17697
|
try {
|
|
@@ -17555,7 +17773,7 @@ app44.post("/", async (c) => {
|
|
|
17555
17773
|
displayName: grant.displayName
|
|
17556
17774
|
});
|
|
17557
17775
|
});
|
|
17558
|
-
var verify_token_default =
|
|
17776
|
+
var verify_token_default = app45;
|
|
17559
17777
|
|
|
17560
17778
|
// app/lib/access-email.ts
|
|
17561
17779
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -17618,9 +17836,9 @@ async function sendMagicLinkEmail(payload) {
|
|
|
17618
17836
|
|
|
17619
17837
|
// server/routes/access/request-magic-link.ts
|
|
17620
17838
|
var TAG38 = "[access-request-link]";
|
|
17621
|
-
var
|
|
17839
|
+
var app46 = new Hono();
|
|
17622
17840
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
17623
|
-
|
|
17841
|
+
app46.post("/", async (c) => {
|
|
17624
17842
|
let body;
|
|
17625
17843
|
try {
|
|
17626
17844
|
body = await c.req.json();
|
|
@@ -17694,13 +17912,13 @@ app45.post("/", async (c) => {
|
|
|
17694
17912
|
);
|
|
17695
17913
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
17696
17914
|
});
|
|
17697
|
-
var request_magic_link_default =
|
|
17915
|
+
var request_magic_link_default = app46;
|
|
17698
17916
|
|
|
17699
17917
|
// server/routes/access/index.ts
|
|
17700
|
-
var
|
|
17701
|
-
|
|
17702
|
-
|
|
17703
|
-
var access_default =
|
|
17918
|
+
var app47 = new Hono();
|
|
17919
|
+
app47.route("/verify-token", verify_token_default);
|
|
17920
|
+
app47.route("/request-magic-link", request_magic_link_default);
|
|
17921
|
+
var access_default = app47;
|
|
17704
17922
|
|
|
17705
17923
|
// server/routes/sites.ts
|
|
17706
17924
|
import { existsSync as existsSync26, readFileSync as readFileSync28, realpathSync as realpathSync7, statSync as statSync11 } from "fs";
|
|
@@ -17735,8 +17953,8 @@ function getExt(p) {
|
|
|
17735
17953
|
if (idx < p.lastIndexOf("/")) return "";
|
|
17736
17954
|
return p.slice(idx).toLowerCase();
|
|
17737
17955
|
}
|
|
17738
|
-
var
|
|
17739
|
-
|
|
17956
|
+
var app48 = new Hono();
|
|
17957
|
+
app48.get("/:rel{.*}", (c) => {
|
|
17740
17958
|
const reqPath = c.req.path;
|
|
17741
17959
|
const rawRel = c.req.param("rel") ?? "";
|
|
17742
17960
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -17839,7 +18057,7 @@ app47.get("/:rel{.*}", (c) => {
|
|
|
17839
18057
|
"X-Content-Type-Options": "nosniff"
|
|
17840
18058
|
});
|
|
17841
18059
|
});
|
|
17842
|
-
var sites_default =
|
|
18060
|
+
var sites_default = app48;
|
|
17843
18061
|
|
|
17844
18062
|
// app/lib/visitor-token.ts
|
|
17845
18063
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -17939,7 +18157,7 @@ function readBrandConfig() {
|
|
|
17939
18157
|
}
|
|
17940
18158
|
|
|
17941
18159
|
// server/routes/visitor-consent.ts
|
|
17942
|
-
var
|
|
18160
|
+
var app49 = new Hono();
|
|
17943
18161
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
17944
18162
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
17945
18163
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -17984,17 +18202,17 @@ function siteSlugFromReferer(referer) {
|
|
|
17984
18202
|
return "";
|
|
17985
18203
|
}
|
|
17986
18204
|
}
|
|
17987
|
-
|
|
18205
|
+
app49.options("/consent", (c) => {
|
|
17988
18206
|
const origin = getOrigin(c);
|
|
17989
18207
|
setCorsHeaders(c, origin);
|
|
17990
18208
|
return c.body(null, 204);
|
|
17991
18209
|
});
|
|
17992
|
-
|
|
18210
|
+
app49.options("/brand-config", (c) => {
|
|
17993
18211
|
const origin = getOrigin(c);
|
|
17994
18212
|
setCorsHeaders(c, origin);
|
|
17995
18213
|
return c.body(null, 204);
|
|
17996
18214
|
});
|
|
17997
|
-
|
|
18215
|
+
app49.post("/consent", async (c) => {
|
|
17998
18216
|
const origin = getOrigin(c);
|
|
17999
18217
|
setCorsHeaders(c, origin);
|
|
18000
18218
|
let raw;
|
|
@@ -18034,7 +18252,7 @@ app48.post("/consent", async (c) => {
|
|
|
18034
18252
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
18035
18253
|
return c.body(null, 204);
|
|
18036
18254
|
});
|
|
18037
|
-
|
|
18255
|
+
app49.get("/brand-config", (c) => {
|
|
18038
18256
|
const origin = getOrigin(c);
|
|
18039
18257
|
setCorsHeaders(c, origin);
|
|
18040
18258
|
const brand = readBrandConfig();
|
|
@@ -18044,7 +18262,7 @@ app48.get("/brand-config", (c) => {
|
|
|
18044
18262
|
c.header("Cache-Control", "public, max-age=300");
|
|
18045
18263
|
return c.json({ consent: { copy, palette } });
|
|
18046
18264
|
});
|
|
18047
|
-
var visitor_consent_default =
|
|
18265
|
+
var visitor_consent_default = app49;
|
|
18048
18266
|
|
|
18049
18267
|
// server/routes/listings.ts
|
|
18050
18268
|
function getCookie(headerValue, name) {
|
|
@@ -18071,8 +18289,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
18071
18289
|
}
|
|
18072
18290
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
18073
18291
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
18074
|
-
var
|
|
18075
|
-
|
|
18292
|
+
var app50 = new Hono();
|
|
18293
|
+
app50.get("/:slug/click", async (c) => {
|
|
18076
18294
|
const slug = c.req.param("slug") ?? "";
|
|
18077
18295
|
const rawSession = c.req.query("session") ?? "";
|
|
18078
18296
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -18136,10 +18354,10 @@ app49.get("/:slug/click", async (c) => {
|
|
|
18136
18354
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
18137
18355
|
return c.redirect(redirectUrl, 302);
|
|
18138
18356
|
});
|
|
18139
|
-
var listings_default =
|
|
18357
|
+
var listings_default = app50;
|
|
18140
18358
|
|
|
18141
18359
|
// server/routes/visitor-event.ts
|
|
18142
|
-
var
|
|
18360
|
+
var app51 = new Hono();
|
|
18143
18361
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
18144
18362
|
var buckets = /* @__PURE__ */ new Map();
|
|
18145
18363
|
var RATE_LIMIT = 60;
|
|
@@ -18206,12 +18424,12 @@ function originAllowed(origin, allowlist) {
|
|
|
18206
18424
|
return false;
|
|
18207
18425
|
}
|
|
18208
18426
|
}
|
|
18209
|
-
|
|
18427
|
+
app51.options("/event", (c) => {
|
|
18210
18428
|
const origin = getOrigin2(c);
|
|
18211
18429
|
setCorsHeaders2(c, origin);
|
|
18212
18430
|
return c.body(null, 204);
|
|
18213
18431
|
});
|
|
18214
|
-
|
|
18432
|
+
app51.post("/event", async (c) => {
|
|
18215
18433
|
const origin = getOrigin2(c);
|
|
18216
18434
|
setCorsHeaders2(c, origin);
|
|
18217
18435
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -18416,7 +18634,7 @@ async function writeEvent(opts) {
|
|
|
18416
18634
|
);
|
|
18417
18635
|
}
|
|
18418
18636
|
}
|
|
18419
|
-
var visitor_event_default =
|
|
18637
|
+
var visitor_event_default = app51;
|
|
18420
18638
|
|
|
18421
18639
|
// server/routes/session.ts
|
|
18422
18640
|
import { resolve as resolve29 } from "path";
|
|
@@ -18462,8 +18680,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
18462
18680
|
headers
|
|
18463
18681
|
});
|
|
18464
18682
|
}
|
|
18465
|
-
var
|
|
18466
|
-
|
|
18683
|
+
var app52 = new Hono();
|
|
18684
|
+
app52.post("/", async (c) => {
|
|
18467
18685
|
let body;
|
|
18468
18686
|
try {
|
|
18469
18687
|
body = await c.req.json();
|
|
@@ -18610,7 +18828,175 @@ app51.post("/", async (c) => {
|
|
|
18610
18828
|
newVisitorId
|
|
18611
18829
|
);
|
|
18612
18830
|
});
|
|
18613
|
-
var session_default2 =
|
|
18831
|
+
var session_default2 = app52;
|
|
18832
|
+
|
|
18833
|
+
// server/lib/calendar-availability.ts
|
|
18834
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
18835
|
+
import { join as join28 } from "path";
|
|
18836
|
+
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
18837
|
+
var REQUIRED_KEYS = [
|
|
18838
|
+
"timezone",
|
|
18839
|
+
"durationMins",
|
|
18840
|
+
"bufferMins",
|
|
18841
|
+
"weekly"
|
|
18842
|
+
];
|
|
18843
|
+
function readAvailabilityConfig(accountDir) {
|
|
18844
|
+
const path2 = join28(accountDir, AVAILABILITY_FILENAME);
|
|
18845
|
+
let raw;
|
|
18846
|
+
try {
|
|
18847
|
+
raw = readFileSync31(path2, "utf-8");
|
|
18848
|
+
} catch {
|
|
18849
|
+
throw new Error(`availability not configured: ${path2} not found`);
|
|
18850
|
+
}
|
|
18851
|
+
let parsed;
|
|
18852
|
+
try {
|
|
18853
|
+
parsed = JSON.parse(raw);
|
|
18854
|
+
} catch (err) {
|
|
18855
|
+
throw new Error(`invalid JSON in ${path2}: ${err.message}`);
|
|
18856
|
+
}
|
|
18857
|
+
const cfg = parsed;
|
|
18858
|
+
for (const key of REQUIRED_KEYS) {
|
|
18859
|
+
if (cfg[key] === void 0 || cfg[key] === null) {
|
|
18860
|
+
throw new Error(`availability config ${path2} missing required key: ${key}`);
|
|
18861
|
+
}
|
|
18862
|
+
}
|
|
18863
|
+
return cfg;
|
|
18864
|
+
}
|
|
18865
|
+
|
|
18866
|
+
// server/lib/calendar-slots.ts
|
|
18867
|
+
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
18868
|
+
function tzOffsetMs(instant, timeZone) {
|
|
18869
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
18870
|
+
timeZone,
|
|
18871
|
+
hour12: false,
|
|
18872
|
+
year: "numeric",
|
|
18873
|
+
month: "2-digit",
|
|
18874
|
+
day: "2-digit",
|
|
18875
|
+
hour: "2-digit",
|
|
18876
|
+
minute: "2-digit",
|
|
18877
|
+
second: "2-digit"
|
|
18878
|
+
});
|
|
18879
|
+
const parts = {};
|
|
18880
|
+
for (const p of dtf.formatToParts(instant)) parts[p.type] = p.value;
|
|
18881
|
+
let hour = Number(parts.hour);
|
|
18882
|
+
if (hour === 24) hour = 0;
|
|
18883
|
+
const asUTC = Date.UTC(
|
|
18884
|
+
Number(parts.year),
|
|
18885
|
+
Number(parts.month) - 1,
|
|
18886
|
+
Number(parts.day),
|
|
18887
|
+
hour,
|
|
18888
|
+
Number(parts.minute),
|
|
18889
|
+
Number(parts.second)
|
|
18890
|
+
);
|
|
18891
|
+
return asUTC - instant.getTime();
|
|
18892
|
+
}
|
|
18893
|
+
function zonedWallClockToUtc(y, m, d, hh, mm, timeZone) {
|
|
18894
|
+
const naiveUtc = Date.UTC(y, m - 1, d, hh, mm, 0, 0);
|
|
18895
|
+
const offset = tzOffsetMs(new Date(naiveUtc), timeZone);
|
|
18896
|
+
return new Date(naiveUtc - offset);
|
|
18897
|
+
}
|
|
18898
|
+
function tzCalendarDate(instant, timeZone) {
|
|
18899
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
18900
|
+
timeZone,
|
|
18901
|
+
year: "numeric",
|
|
18902
|
+
month: "2-digit",
|
|
18903
|
+
day: "2-digit"
|
|
18904
|
+
});
|
|
18905
|
+
const parts = {};
|
|
18906
|
+
for (const p of dtf.formatToParts(instant)) parts[p.type] = p.value;
|
|
18907
|
+
return { y: Number(parts.year), m: Number(parts.month), d: Number(parts.day) };
|
|
18908
|
+
}
|
|
18909
|
+
function parseHHMM(s) {
|
|
18910
|
+
const [hh, mm] = s.split(":").map(Number);
|
|
18911
|
+
return { hh, mm };
|
|
18912
|
+
}
|
|
18913
|
+
function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
18914
|
+
const tz = config.timezone;
|
|
18915
|
+
const durMs = config.durationMins * 6e4;
|
|
18916
|
+
const bufMs = config.bufferMins * 6e4;
|
|
18917
|
+
const from = new Date(fromISO).getTime();
|
|
18918
|
+
const to = new Date(toISO).getTime();
|
|
18919
|
+
const busyMs = busy.map((b) => ({ start: new Date(b.start).getTime(), end: new Date(b.end).getTime() }));
|
|
18920
|
+
const slots = [];
|
|
18921
|
+
const firstDate = tzCalendarDate(new Date(from), tz);
|
|
18922
|
+
let dayMidnight = zonedWallClockToUtc(firstDate.y, firstDate.m, firstDate.d, 0, 0, tz);
|
|
18923
|
+
for (let guard = 0; guard < 400 && dayMidnight.getTime() < to; guard++) {
|
|
18924
|
+
const { y, m, d } = tzCalendarDate(dayMidnight, tz);
|
|
18925
|
+
const weekday = WEEKDAYS[new Date(Date.UTC(y, m - 1, d)).getUTCDay()];
|
|
18926
|
+
const windows = config.weekly[weekday] ?? [];
|
|
18927
|
+
for (const [openStr, closeStr] of windows) {
|
|
18928
|
+
const open = parseHHMM(openStr);
|
|
18929
|
+
const close = parseHHMM(closeStr);
|
|
18930
|
+
const openUtc = zonedWallClockToUtc(y, m, d, open.hh, open.mm, tz).getTime();
|
|
18931
|
+
const closeUtc = zonedWallClockToUtc(y, m, d, close.hh, close.mm, tz).getTime();
|
|
18932
|
+
for (let s = openUtc; s + durMs <= closeUtc; s += durMs) {
|
|
18933
|
+
const slotEnd = s + durMs;
|
|
18934
|
+
if (s < from || s >= to) continue;
|
|
18935
|
+
const blocked = busyMs.some((b) => b.start < slotEnd + bufMs && b.end > s - bufMs);
|
|
18936
|
+
if (blocked) continue;
|
|
18937
|
+
slots.push({ start: new Date(s).toISOString(), end: new Date(slotEnd).toISOString() });
|
|
18938
|
+
}
|
|
18939
|
+
}
|
|
18940
|
+
const next = tzCalendarDate(new Date(dayMidnight.getTime() + 26 * 36e5), tz);
|
|
18941
|
+
dayMidnight = zonedWallClockToUtc(next.y, next.m, next.d, 0, 0, tz);
|
|
18942
|
+
}
|
|
18943
|
+
return slots;
|
|
18944
|
+
}
|
|
18945
|
+
|
|
18946
|
+
// server/routes/calendar-public.ts
|
|
18947
|
+
var app53 = new Hono();
|
|
18948
|
+
function setCors(c) {
|
|
18949
|
+
c.header("Access-Control-Allow-Origin", "*");
|
|
18950
|
+
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
18951
|
+
c.header("Access-Control-Allow-Headers", "content-type");
|
|
18952
|
+
}
|
|
18953
|
+
app53.options("/free-busy", (c) => {
|
|
18954
|
+
setCors(c);
|
|
18955
|
+
return c.body(null, 204);
|
|
18956
|
+
});
|
|
18957
|
+
app53.get("/free-busy", async (c) => {
|
|
18958
|
+
setCors(c);
|
|
18959
|
+
const from = c.req.query("from");
|
|
18960
|
+
const to = c.req.query("to");
|
|
18961
|
+
if (!from || !to) return c.json({ error: "from and to (ISO) required" }, 400);
|
|
18962
|
+
if (Number.isNaN(Date.parse(from)) || Number.isNaN(Date.parse(to))) {
|
|
18963
|
+
return c.json({ error: "from and to must be parseable ISO timestamps" }, 400);
|
|
18964
|
+
}
|
|
18965
|
+
const account = resolveAccount();
|
|
18966
|
+
if (!account) return c.json({ error: "No account configured" }, 500);
|
|
18967
|
+
let config;
|
|
18968
|
+
try {
|
|
18969
|
+
config = readAvailabilityConfig(account.accountDir);
|
|
18970
|
+
} catch (err) {
|
|
18971
|
+
console.error(`[calendar] op=free-busy-unconfigured err="${err.message}"`);
|
|
18972
|
+
return c.json({ error: "Availability not configured" }, 404);
|
|
18973
|
+
}
|
|
18974
|
+
const session = getSession();
|
|
18975
|
+
try {
|
|
18976
|
+
const res = await session.run(
|
|
18977
|
+
`MATCH (m:Meeting {accountId: $accountId})
|
|
18978
|
+
WHERE NOT (m.endsAt IS NOT NULL AND m.endsAt <= datetime($from))
|
|
18979
|
+
AND m.startsAt < datetime($to)
|
|
18980
|
+
RETURN toString(m.startsAt) AS start, toString(m.endsAt) AS end`,
|
|
18981
|
+
{ accountId: account.accountId, from, to }
|
|
18982
|
+
);
|
|
18983
|
+
const busy = res.records.map((r) => {
|
|
18984
|
+
const start = r.get("start");
|
|
18985
|
+
const rawEnd = r.get("end");
|
|
18986
|
+
const end = rawEnd ?? new Date(new Date(start).getTime() + config.durationMins * 6e4).toISOString();
|
|
18987
|
+
return { start, end };
|
|
18988
|
+
});
|
|
18989
|
+
const slots = computeOpenSlots(config, busy, from, to);
|
|
18990
|
+
return c.json({ durationMins: config.durationMins, timezone: config.timezone, slots });
|
|
18991
|
+
} catch (err) {
|
|
18992
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18993
|
+
console.error(`[calendar] op=free-busy-fail err="${message}"`);
|
|
18994
|
+
return c.json({ error: `Availability unavailable: ${message}` }, 503);
|
|
18995
|
+
} finally {
|
|
18996
|
+
await session.close();
|
|
18997
|
+
}
|
|
18998
|
+
});
|
|
18999
|
+
var calendar_public_default = app53;
|
|
18614
19000
|
|
|
18615
19001
|
// app/lib/graph-health.ts
|
|
18616
19002
|
var import_dist4 = __toESM(require_dist3(), 1);
|
|
@@ -18958,7 +19344,7 @@ async function migrateUploads(opts = {}) {
|
|
|
18958
19344
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
18959
19345
|
import { readdir as readdir6, readFile as readFile7, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
18960
19346
|
import { existsSync as existsSync29 } from "fs";
|
|
18961
|
-
import { join as
|
|
19347
|
+
import { join as join29 } from "path";
|
|
18962
19348
|
var ADMIN_ROLE2 = "admin";
|
|
18963
19349
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
18964
19350
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -19003,7 +19389,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
19003
19389
|
}
|
|
19004
19390
|
for (const slug of slugs) {
|
|
19005
19391
|
if (!slug.isDirectory()) continue;
|
|
19006
|
-
const slugDir =
|
|
19392
|
+
const slugDir = join29(projectsRoot, slug.name);
|
|
19007
19393
|
let entries;
|
|
19008
19394
|
try {
|
|
19009
19395
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -19012,9 +19398,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
19012
19398
|
}
|
|
19013
19399
|
for (const entry of entries) {
|
|
19014
19400
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
19015
|
-
out.push(
|
|
19401
|
+
out.push(join29(slugDir, entry.name));
|
|
19016
19402
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
19017
|
-
const subDir =
|
|
19403
|
+
const subDir = join29(slugDir, entry.name);
|
|
19018
19404
|
let subs;
|
|
19019
19405
|
try {
|
|
19020
19406
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -19022,7 +19408,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
19022
19408
|
continue;
|
|
19023
19409
|
}
|
|
19024
19410
|
for (const s of subs) {
|
|
19025
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
19411
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join29(subDir, s.name));
|
|
19026
19412
|
}
|
|
19027
19413
|
}
|
|
19028
19414
|
}
|
|
@@ -19034,7 +19420,7 @@ function shortId(path2) {
|
|
|
19034
19420
|
return base.slice(0, 8);
|
|
19035
19421
|
}
|
|
19036
19422
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
19037
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
19423
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join29(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
19038
19424
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
19039
19425
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
19040
19426
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -19376,8 +19762,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
19376
19762
|
|
|
19377
19763
|
// app/lib/whatsapp/gateway/routes.ts
|
|
19378
19764
|
function createWaChannelRoutes(deps) {
|
|
19379
|
-
const
|
|
19380
|
-
|
|
19765
|
+
const app55 = new Hono();
|
|
19766
|
+
app55.get("/wa-channel/inbound", (c) => {
|
|
19381
19767
|
const senderId = c.req.query("senderId");
|
|
19382
19768
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
19383
19769
|
return streamSSE(c, async (stream2) => {
|
|
@@ -19395,7 +19781,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19395
19781
|
}
|
|
19396
19782
|
});
|
|
19397
19783
|
});
|
|
19398
|
-
|
|
19784
|
+
app55.post("/wa-channel/reply", async (c) => {
|
|
19399
19785
|
const body = await c.req.json().catch(() => null);
|
|
19400
19786
|
const senderId = body?.senderId;
|
|
19401
19787
|
const text = body?.text;
|
|
@@ -19416,7 +19802,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19416
19802
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
19417
19803
|
return c.json({ ok: true });
|
|
19418
19804
|
});
|
|
19419
|
-
|
|
19805
|
+
app55.post("/wa-channel/reply-document", async (c) => {
|
|
19420
19806
|
const body = await c.req.json().catch(() => null);
|
|
19421
19807
|
const senderId = body?.senderId;
|
|
19422
19808
|
const files = body?.files;
|
|
@@ -19455,7 +19841,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19455
19841
|
}
|
|
19456
19842
|
return c.json({ ok: true, results });
|
|
19457
19843
|
});
|
|
19458
|
-
|
|
19844
|
+
app55.post("/wa-channel/ready", async (c) => {
|
|
19459
19845
|
const body = await c.req.json().catch(() => null);
|
|
19460
19846
|
const senderId = body?.senderId;
|
|
19461
19847
|
if (typeof senderId !== "string") {
|
|
@@ -19464,7 +19850,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19464
19850
|
deps.onReady?.(senderId);
|
|
19465
19851
|
return c.json({ ok: true });
|
|
19466
19852
|
});
|
|
19467
|
-
|
|
19853
|
+
app55.post("/wa-channel/received", async (c) => {
|
|
19468
19854
|
const body = await c.req.json().catch(() => null);
|
|
19469
19855
|
const senderId = body?.senderId;
|
|
19470
19856
|
const waMessageId = body?.waMessageId;
|
|
@@ -19474,7 +19860,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19474
19860
|
deps.onReceived?.(senderId, waMessageId);
|
|
19475
19861
|
return c.json({ ok: true });
|
|
19476
19862
|
});
|
|
19477
|
-
|
|
19863
|
+
app55.post("/wa-channel/turn-end", async (c) => {
|
|
19478
19864
|
const body = await c.req.json().catch(() => null);
|
|
19479
19865
|
const senderId = body?.senderId;
|
|
19480
19866
|
const sessionId = body?.sessionId;
|
|
@@ -19505,7 +19891,7 @@ function createWaChannelRoutes(deps) {
|
|
|
19505
19891
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=fallback bytes=${bytes}`);
|
|
19506
19892
|
return c.json({ ok: true, delivered: "fallback" });
|
|
19507
19893
|
});
|
|
19508
|
-
return
|
|
19894
|
+
return app55;
|
|
19509
19895
|
}
|
|
19510
19896
|
|
|
19511
19897
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -19798,8 +20184,8 @@ var InboundHub2 = class {
|
|
|
19798
20184
|
|
|
19799
20185
|
// app/lib/webchat/gateway/routes.ts
|
|
19800
20186
|
function createWebchatChannelRoutes(deps) {
|
|
19801
|
-
const
|
|
19802
|
-
|
|
20187
|
+
const app55 = new Hono();
|
|
20188
|
+
app55.get("/webchat-channel/inbound", (c) => {
|
|
19803
20189
|
const key = c.req.query("key");
|
|
19804
20190
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
19805
20191
|
return streamSSE(c, async (stream2) => {
|
|
@@ -19817,7 +20203,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19817
20203
|
}
|
|
19818
20204
|
});
|
|
19819
20205
|
});
|
|
19820
|
-
|
|
20206
|
+
app55.post("/webchat-channel/reply", async (c) => {
|
|
19821
20207
|
const body = await c.req.json().catch(() => null);
|
|
19822
20208
|
const key = body?.key;
|
|
19823
20209
|
const text = body?.text;
|
|
@@ -19827,7 +20213,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19827
20213
|
deps.onReply?.(key, text);
|
|
19828
20214
|
return c.json({ ok: true });
|
|
19829
20215
|
});
|
|
19830
|
-
|
|
20216
|
+
app55.post("/webchat-channel/ready", async (c) => {
|
|
19831
20217
|
const body = await c.req.json().catch(() => null);
|
|
19832
20218
|
const key = body?.key;
|
|
19833
20219
|
if (typeof key !== "string") {
|
|
@@ -19836,7 +20222,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19836
20222
|
deps.onReady?.(key);
|
|
19837
20223
|
return c.json({ ok: true });
|
|
19838
20224
|
});
|
|
19839
|
-
|
|
20225
|
+
app55.post("/webchat-channel/permission-request", async (c) => {
|
|
19840
20226
|
const body = await c.req.json().catch(() => null);
|
|
19841
20227
|
const key = body?.key;
|
|
19842
20228
|
const requestId = body?.request_id;
|
|
@@ -19850,7 +20236,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19850
20236
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
19851
20237
|
return c.json(verdict);
|
|
19852
20238
|
});
|
|
19853
|
-
|
|
20239
|
+
app55.post("/webchat-channel/received", async (c) => {
|
|
19854
20240
|
const body = await c.req.json().catch(() => null);
|
|
19855
20241
|
const key = body?.key;
|
|
19856
20242
|
const messageId = body?.messageId;
|
|
@@ -19860,7 +20246,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19860
20246
|
deps.onReceived?.(key, messageId);
|
|
19861
20247
|
return c.json({ ok: true });
|
|
19862
20248
|
});
|
|
19863
|
-
|
|
20249
|
+
app55.post("/webchat-channel/turn-end", async (c) => {
|
|
19864
20250
|
const body = await c.req.json().catch(() => null);
|
|
19865
20251
|
const key = body?.key;
|
|
19866
20252
|
const sessionId = body?.sessionId;
|
|
@@ -19880,7 +20266,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
19880
20266
|
console.error(`[webchat-native] op=turn-undelivered channel=webchat key=${k} sessionId=${sid} bytes=${finalBytes}`);
|
|
19881
20267
|
return c.json({ ok: true, delivered: "undelivered" });
|
|
19882
20268
|
});
|
|
19883
|
-
return
|
|
20269
|
+
return app55;
|
|
19884
20270
|
}
|
|
19885
20271
|
|
|
19886
20272
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -20372,7 +20758,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
20372
20758
|
|
|
20373
20759
|
// ../lib/entitlement/src/index.ts
|
|
20374
20760
|
import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
|
|
20375
|
-
import { existsSync as existsSync30, readFileSync as
|
|
20761
|
+
import { existsSync as existsSync30, readFileSync as readFileSync32, statSync as statSync12 } from "fs";
|
|
20376
20762
|
import { resolve as resolve32 } from "path";
|
|
20377
20763
|
|
|
20378
20764
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -20436,7 +20822,7 @@ function resolveEntitlement(brand, account) {
|
|
|
20436
20822
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
20437
20823
|
let pubkeyPem;
|
|
20438
20824
|
try {
|
|
20439
|
-
pubkeyPem =
|
|
20825
|
+
pubkeyPem = readFileSync32(pubkeyPath(brand), "utf-8");
|
|
20440
20826
|
} catch (err) {
|
|
20441
20827
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
20442
20828
|
reason: "pubkey-missing"
|
|
@@ -20450,7 +20836,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
20450
20836
|
}
|
|
20451
20837
|
let envelope;
|
|
20452
20838
|
try {
|
|
20453
|
-
envelope = JSON.parse(
|
|
20839
|
+
envelope = JSON.parse(readFileSync32(entitlementPath, "utf-8"));
|
|
20454
20840
|
} catch {
|
|
20455
20841
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
20456
20842
|
}
|
|
@@ -20611,14 +20997,14 @@ function clientFrom(c) {
|
|
|
20611
20997
|
);
|
|
20612
20998
|
}
|
|
20613
20999
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
20614
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
21000
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join30(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
20615
21001
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
20616
21002
|
if (BRAND_JSON_PATH && !existsSync31(BRAND_JSON_PATH)) {
|
|
20617
21003
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
20618
21004
|
}
|
|
20619
21005
|
if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
|
|
20620
21006
|
try {
|
|
20621
|
-
const parsed = JSON.parse(
|
|
21007
|
+
const parsed = JSON.parse(readFileSync33(BRAND_JSON_PATH, "utf-8"));
|
|
20622
21008
|
BRAND = { ...BRAND, ...parsed };
|
|
20623
21009
|
} catch (err) {
|
|
20624
21010
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -20626,6 +21012,12 @@ if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
|
|
|
20626
21012
|
}
|
|
20627
21013
|
}
|
|
20628
21014
|
var brandFaviconPath = BRAND.assets?.favicon ? `/brand/${BRAND.assets.favicon}` : "/favicon.ico";
|
|
21015
|
+
var brandAssetsBoot = BRAND.assets ?? {};
|
|
21016
|
+
var brandIconPathBoot = brandAssetsBoot.icon ? `/brand/${brandAssetsBoot.icon}` : "/brand/maxy-monochrome.png";
|
|
21017
|
+
var brandAppIcon512Path = brandAssetsBoot.appIcon ? `/brand/${brandAssetsBoot.appIcon}` : brandIconPathBoot;
|
|
21018
|
+
var brandAppIcon192Path = brandAssetsBoot.appIcon192 ? `/brand/${brandAssetsBoot.appIcon192}` : brandAppIcon512Path;
|
|
21019
|
+
var brandMaskableIconPath = brandAssetsBoot.maskableIcon ? `/brand/${brandAssetsBoot.maskableIcon}` : brandAppIcon512Path;
|
|
21020
|
+
var ADMIN_MANIFEST_PATH = PWA_SURFACES.find((s) => s.surface === "admin").manifestPath;
|
|
20629
21021
|
var brandLoginOpts = {
|
|
20630
21022
|
primaryColor: BRAND.defaultColors?.primary,
|
|
20631
21023
|
primaryHoverColor: BRAND.defaultColors?.primaryHover,
|
|
@@ -20637,13 +21029,18 @@ var brandLoginOpts = {
|
|
|
20637
21029
|
bodyFont: BRAND.defaultFonts?.body,
|
|
20638
21030
|
logoContainsName: !!BRAND.logoContainsName,
|
|
20639
21031
|
tagline: BRAND.tagline,
|
|
20640
|
-
ogCardPath: BRAND.assets?.ogCard ? `/brand/${BRAND.assets.ogCard}` : void 0
|
|
21032
|
+
ogCardPath: BRAND.assets?.ogCard ? `/brand/${BRAND.assets.ogCard}` : void 0,
|
|
21033
|
+
// Make the sign-in page installable: link the admin manifest + opaque
|
|
21034
|
+
// apple-touch-icon so an install from there adopts the brand name + icon.
|
|
21035
|
+
manifestPath: ADMIN_MANIFEST_PATH,
|
|
21036
|
+
appleTouchIconPath: brandAppIcon512Path,
|
|
21037
|
+
themeColor: BRAND.defaultColors?.primary
|
|
20641
21038
|
};
|
|
20642
|
-
var ALIAS_DOMAINS_PATH =
|
|
21039
|
+
var ALIAS_DOMAINS_PATH = join30(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
20643
21040
|
function loadAliasDomains() {
|
|
20644
21041
|
try {
|
|
20645
21042
|
if (!existsSync31(ALIAS_DOMAINS_PATH)) return null;
|
|
20646
|
-
const parsed = JSON.parse(
|
|
21043
|
+
const parsed = JSON.parse(readFileSync33(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
20647
21044
|
if (!Array.isArray(parsed)) {
|
|
20648
21045
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
20649
21046
|
return null;
|
|
@@ -20667,11 +21064,11 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
20667
21064
|
function isPublicHost(host) {
|
|
20668
21065
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
20669
21066
|
}
|
|
20670
|
-
var
|
|
21067
|
+
var app54 = new Hono();
|
|
20671
21068
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
20672
21069
|
var waGateway = new WaGateway({
|
|
20673
21070
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
20674
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
21071
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join30(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
20675
21072
|
// Task 751 — file delivery on the native channel: resolve the platform
|
|
20676
21073
|
// account + path validation here and funnel through the shared send core.
|
|
20677
21074
|
sendDocument: async ({ senderId, accountId, filePath, caption }) => {
|
|
@@ -20687,7 +21084,7 @@ var waGateway = new WaGateway({
|
|
|
20687
21084
|
caption,
|
|
20688
21085
|
accountId,
|
|
20689
21086
|
maxyAccountId,
|
|
20690
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
21087
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join30(__dirname, ".."))
|
|
20691
21088
|
});
|
|
20692
21089
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
20693
21090
|
},
|
|
@@ -20717,7 +21114,7 @@ var waGateway = new WaGateway({
|
|
|
20717
21114
|
nativeFileFollowers.set(senderId, ac);
|
|
20718
21115
|
}
|
|
20719
21116
|
});
|
|
20720
|
-
|
|
21117
|
+
app54.route("/", waGateway.routes());
|
|
20721
21118
|
waGateway.startSweeper();
|
|
20722
21119
|
var webchatGateway = new WebchatGateway({
|
|
20723
21120
|
gatewayUrl: webchatGatewayUrl(),
|
|
@@ -20790,15 +21187,15 @@ var webchatGateway = new WebchatGateway({
|
|
|
20790
21187
|
deleteSession: (sessionId) => managerDelete(sessionId),
|
|
20791
21188
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
20792
21189
|
});
|
|
20793
|
-
|
|
21190
|
+
app54.route("/", webchatGateway.routes());
|
|
20794
21191
|
webchatGateway.startSweeper();
|
|
20795
21192
|
webchatGateway.startPublicReaper();
|
|
20796
21193
|
var chatRoutes = createChatRoutes({
|
|
20797
21194
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
20798
21195
|
awaitReply: (key, timeoutMs) => webchatGateway.awaitReply(key, timeoutMs)
|
|
20799
21196
|
});
|
|
20800
|
-
|
|
20801
|
-
|
|
21197
|
+
app54.use("*", clientIpMiddleware);
|
|
21198
|
+
app54.use("*", async (c, next) => {
|
|
20802
21199
|
await next();
|
|
20803
21200
|
c.header("X-Content-Type-Options", "nosniff");
|
|
20804
21201
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -20808,7 +21205,7 @@ app52.use("*", async (c, next) => {
|
|
|
20808
21205
|
);
|
|
20809
21206
|
});
|
|
20810
21207
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
20811
|
-
|
|
21208
|
+
app54.use("*", async (c, next) => {
|
|
20812
21209
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
20813
21210
|
await next();
|
|
20814
21211
|
return;
|
|
@@ -20826,7 +21223,7 @@ app52.use("*", async (c, next) => {
|
|
|
20826
21223
|
});
|
|
20827
21224
|
}
|
|
20828
21225
|
});
|
|
20829
|
-
|
|
21226
|
+
app54.use("*", async (c, next) => {
|
|
20830
21227
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
20831
21228
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
20832
21229
|
await next();
|
|
@@ -20864,7 +21261,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
20864
21261
|
return { ...brandLoginOpts, origin };
|
|
20865
21262
|
}
|
|
20866
21263
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
20867
|
-
|
|
21264
|
+
app54.post("/__remote-auth/login", async (c) => {
|
|
20868
21265
|
const client = clientFrom(c);
|
|
20869
21266
|
const clientIp = client.ip || "unknown";
|
|
20870
21267
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -20909,7 +21306,7 @@ app52.post("/__remote-auth/login", async (c) => {
|
|
|
20909
21306
|
}
|
|
20910
21307
|
});
|
|
20911
21308
|
});
|
|
20912
|
-
|
|
21309
|
+
app54.get("/__remote-auth/logout", (c) => {
|
|
20913
21310
|
const client = clientFrom(c);
|
|
20914
21311
|
const clientIp = client.ip || "unknown";
|
|
20915
21312
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -20922,7 +21319,7 @@ app52.get("/__remote-auth/logout", (c) => {
|
|
|
20922
21319
|
}
|
|
20923
21320
|
});
|
|
20924
21321
|
});
|
|
20925
|
-
|
|
21322
|
+
app54.post("/__remote-auth/change-password", async (c) => {
|
|
20926
21323
|
const client = clientFrom(c);
|
|
20927
21324
|
const clientIp = client.ip || "unknown";
|
|
20928
21325
|
const rateLimited = checkRateLimit(client);
|
|
@@ -20981,13 +21378,13 @@ app52.post("/__remote-auth/change-password", async (c) => {
|
|
|
20981
21378
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
20982
21379
|
}
|
|
20983
21380
|
});
|
|
20984
|
-
|
|
21381
|
+
app54.get("/__remote-auth/setup", (c) => {
|
|
20985
21382
|
if (isRemoteAuthConfigured()) {
|
|
20986
21383
|
return c.redirect("/");
|
|
20987
21384
|
}
|
|
20988
21385
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
20989
21386
|
});
|
|
20990
|
-
|
|
21387
|
+
app54.post("/__remote-auth/set-initial-password", async (c) => {
|
|
20991
21388
|
if (isRemoteAuthConfigured()) {
|
|
20992
21389
|
return c.redirect("/");
|
|
20993
21390
|
}
|
|
@@ -21025,10 +21422,10 @@ app52.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
21025
21422
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
21026
21423
|
}
|
|
21027
21424
|
});
|
|
21028
|
-
|
|
21425
|
+
app54.get("/api/remote-auth/status", (c) => {
|
|
21029
21426
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
21030
21427
|
});
|
|
21031
|
-
|
|
21428
|
+
app54.post("/api/remote-auth/set-password", async (c) => {
|
|
21032
21429
|
let body;
|
|
21033
21430
|
try {
|
|
21034
21431
|
body = await c.req.json();
|
|
@@ -21067,13 +21464,17 @@ app52.post("/api/remote-auth/set-password", async (c) => {
|
|
|
21067
21464
|
return c.json({ error: "Failed to save password" }, 500);
|
|
21068
21465
|
}
|
|
21069
21466
|
});
|
|
21070
|
-
|
|
21467
|
+
app54.route("/api/_client-error", client_error_default);
|
|
21071
21468
|
console.log("[client-error-route] mounted");
|
|
21072
21469
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
21073
|
-
|
|
21470
|
+
app54.use("*", async (c, next) => {
|
|
21074
21471
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21075
21472
|
const path2 = c.req.path;
|
|
21076
|
-
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/") ||
|
|
21473
|
+
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
|
|
21474
|
+
// origin) against the brand host with no admin cookie. It is public by
|
|
21475
|
+
// design — open slots only, no :Meeting detail — so it bypasses the gate
|
|
21476
|
+
// exactly like /brand/. The detail-leak guard lives in the route + its test.
|
|
21477
|
+
path2 === "/api/calendar/free-busy" || PWA_PUBLIC_PATHS.has(path2)) {
|
|
21077
21478
|
await next();
|
|
21078
21479
|
return;
|
|
21079
21480
|
}
|
|
@@ -21110,25 +21511,26 @@ app52.use("*", async (c, next) => {
|
|
|
21110
21511
|
}
|
|
21111
21512
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path2 }), 200);
|
|
21112
21513
|
});
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21514
|
+
app54.route("/api/health", health_default);
|
|
21515
|
+
app54.route("/api/chat", chatRoutes);
|
|
21516
|
+
app54.route("/api/whatsapp", whatsapp_default);
|
|
21517
|
+
app54.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
21518
|
+
app54.route("/api/public-reader", public_reader_default);
|
|
21519
|
+
app54.route("/api/webchat", createWebchatRoutes({
|
|
21119
21520
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
21120
21521
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
21121
21522
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
21122
21523
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
21123
21524
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
21124
21525
|
}));
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21526
|
+
app54.route("/api/webchat/greeting", webchat_greeting_default);
|
|
21527
|
+
app54.route("/api/telegram", telegram_default);
|
|
21528
|
+
app54.route("/api/quickbooks", quickbooks_default);
|
|
21529
|
+
app54.route("/api/onboarding", onboarding_default);
|
|
21530
|
+
app54.route("/api/admin", admin_default);
|
|
21531
|
+
app54.route("/api/access", access_default);
|
|
21532
|
+
app54.route("/api/session", session_default2);
|
|
21533
|
+
app54.route("/api/calendar", calendar_public_default);
|
|
21132
21534
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
21133
21535
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
21134
21536
|
var IMAGE_MIME = {
|
|
@@ -21140,7 +21542,7 @@ var IMAGE_MIME = {
|
|
|
21140
21542
|
".svg": "image/svg+xml",
|
|
21141
21543
|
".ico": "image/x-icon"
|
|
21142
21544
|
};
|
|
21143
|
-
|
|
21545
|
+
app54.get("/agent-assets/:slug/:filename", (c) => {
|
|
21144
21546
|
const slug = c.req.param("slug");
|
|
21145
21547
|
const filename = c.req.param("filename");
|
|
21146
21548
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -21169,13 +21571,13 @@ app52.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
21169
21571
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21170
21572
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21171
21573
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
21172
|
-
const body =
|
|
21574
|
+
const body = readFileSync33(filePath);
|
|
21173
21575
|
return c.body(body, 200, {
|
|
21174
21576
|
"Content-Type": contentType,
|
|
21175
21577
|
"Cache-Control": "public, max-age=3600"
|
|
21176
21578
|
});
|
|
21177
21579
|
});
|
|
21178
|
-
|
|
21580
|
+
app54.get("/generated/:filename", (c) => {
|
|
21179
21581
|
const filename = c.req.param("filename");
|
|
21180
21582
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
21181
21583
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -21199,22 +21601,22 @@ app52.get("/generated/:filename", (c) => {
|
|
|
21199
21601
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
21200
21602
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
21201
21603
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
21202
|
-
const body =
|
|
21604
|
+
const body = readFileSync33(filePath);
|
|
21203
21605
|
return c.body(body, 200, {
|
|
21204
21606
|
"Content-Type": contentType,
|
|
21205
21607
|
"Cache-Control": "public, max-age=86400"
|
|
21206
21608
|
});
|
|
21207
21609
|
});
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
|
|
21610
|
+
app54.route("/sites", sites_default);
|
|
21611
|
+
app54.route("/listings", listings_default);
|
|
21612
|
+
app54.route("/v", visitor_event_default);
|
|
21613
|
+
app54.route("/v", visitor_consent_default);
|
|
21212
21614
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
21213
21615
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
21214
21616
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
21215
21617
|
if (BRAND_JSON_PATH && existsSync31(BRAND_JSON_PATH)) {
|
|
21216
21618
|
try {
|
|
21217
|
-
const fullBrand = JSON.parse(
|
|
21619
|
+
const fullBrand = JSON.parse(readFileSync33(BRAND_JSON_PATH, "utf-8"));
|
|
21218
21620
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
21219
21621
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
21220
21622
|
} catch {
|
|
@@ -21240,11 +21642,12 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
21240
21642
|
})}</script>`;
|
|
21241
21643
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
21242
21644
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
21243
|
-
var
|
|
21244
|
-
|
|
21645
|
+
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
21646
|
+
(p) => existsSync31(resolve33(process.cwd(), "public", p.replace(/^\//, "")))
|
|
21647
|
+
);
|
|
21245
21648
|
var SW_SOURCE = (() => {
|
|
21246
21649
|
try {
|
|
21247
|
-
return
|
|
21650
|
+
return readFileSync33(resolve33(process.cwd(), "public", "sw.js"), "utf-8");
|
|
21248
21651
|
} catch {
|
|
21249
21652
|
return null;
|
|
21250
21653
|
}
|
|
@@ -21252,9 +21655,9 @@ var SW_SOURCE = (() => {
|
|
|
21252
21655
|
function readInstalledVersion() {
|
|
21253
21656
|
try {
|
|
21254
21657
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
21255
|
-
const versionFile =
|
|
21658
|
+
const versionFile = join30(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
21256
21659
|
if (!existsSync31(versionFile)) return "unknown";
|
|
21257
|
-
const content =
|
|
21660
|
+
const content = readFileSync33(versionFile, "utf-8").trim();
|
|
21258
21661
|
return content || "unknown";
|
|
21259
21662
|
} catch {
|
|
21260
21663
|
return "unknown";
|
|
@@ -21295,12 +21698,12 @@ var clientErrorReporterScript = `<script>
|
|
|
21295
21698
|
function cachedHtml(file) {
|
|
21296
21699
|
let html = htmlCache.get(file);
|
|
21297
21700
|
if (!html) {
|
|
21298
|
-
html =
|
|
21701
|
+
html = readFileSync33(resolve33(process.cwd(), "public", file), "utf-8");
|
|
21299
21702
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
21300
21703
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
21301
21704
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
21302
21705
|
const pwaSurface = pwaSurfaceForShell(file);
|
|
21303
|
-
const pwaHead = pwaSurface ? "\n" + pwaHeadTags(pwaSurface, {
|
|
21706
|
+
const pwaHead = pwaSurface ? "\n" + pwaHeadTags(pwaSurface, { appleTouchIcon: brandAppIcon512Path, themeColor: brandThemeColor }) + "\n" : "";
|
|
21304
21707
|
const headInjection = (file === "index.html" ? `${brandScript}
|
|
21305
21708
|
${versionScript}
|
|
21306
21709
|
${clientErrorReporterScript}
|
|
@@ -21312,13 +21715,13 @@ ${clientErrorReporterScript}
|
|
|
21312
21715
|
return html;
|
|
21313
21716
|
}
|
|
21314
21717
|
function loadBrandingCache(agentSlug) {
|
|
21315
|
-
const configDir2 =
|
|
21718
|
+
const configDir2 = join30(homedir3(), BRAND.configDir);
|
|
21316
21719
|
try {
|
|
21317
21720
|
const accountId = getDefaultAccountId();
|
|
21318
21721
|
if (!accountId) return null;
|
|
21319
|
-
const cachePath =
|
|
21722
|
+
const cachePath = join30(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
21320
21723
|
if (!existsSync31(cachePath)) return null;
|
|
21321
|
-
return JSON.parse(
|
|
21724
|
+
return JSON.parse(readFileSync33(cachePath, "utf-8"));
|
|
21322
21725
|
} catch {
|
|
21323
21726
|
return null;
|
|
21324
21727
|
}
|
|
@@ -21362,7 +21765,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
21362
21765
|
function agentUnavailableHtml() {
|
|
21363
21766
|
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
|
|
21364
21767
|
}
|
|
21365
|
-
|
|
21768
|
+
app54.get("/", (c) => {
|
|
21366
21769
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21367
21770
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
21368
21771
|
if (klass === "operator") {
|
|
@@ -21384,12 +21787,12 @@ app52.get("/", (c) => {
|
|
|
21384
21787
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
21385
21788
|
return c.html(cachedHtml("index.html"));
|
|
21386
21789
|
});
|
|
21387
|
-
|
|
21790
|
+
app54.get("/public", (c) => {
|
|
21388
21791
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21389
21792
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21390
21793
|
return c.html(cachedHtml("public.html"));
|
|
21391
21794
|
});
|
|
21392
|
-
|
|
21795
|
+
app54.get("/public-chat", (c) => {
|
|
21393
21796
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21394
21797
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21395
21798
|
return c.html(cachedHtml("public.html"));
|
|
@@ -21408,12 +21811,12 @@ async function logViewerFetch(c, next) {
|
|
|
21408
21811
|
duration_ms: Date.now() - start
|
|
21409
21812
|
});
|
|
21410
21813
|
}
|
|
21411
|
-
|
|
21412
|
-
|
|
21413
|
-
|
|
21814
|
+
app54.use("/vnc-viewer.html", logViewerFetch);
|
|
21815
|
+
app54.use("/vnc-popout.html", logViewerFetch);
|
|
21816
|
+
app54.get("/vnc-popout.html", (c) => {
|
|
21414
21817
|
let html = htmlCache.get("vnc-popout.html");
|
|
21415
21818
|
if (!html) {
|
|
21416
|
-
html =
|
|
21819
|
+
html = readFileSync33(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
21417
21820
|
const name = escapeHtml(BRAND.productName);
|
|
21418
21821
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
21419
21822
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -21423,7 +21826,7 @@ app52.get("/vnc-popout.html", (c) => {
|
|
|
21423
21826
|
}
|
|
21424
21827
|
return c.html(html);
|
|
21425
21828
|
});
|
|
21426
|
-
|
|
21829
|
+
app54.post("/api/vnc/client-event", async (c) => {
|
|
21427
21830
|
let body;
|
|
21428
21831
|
try {
|
|
21429
21832
|
body = await c.req.json();
|
|
@@ -21444,25 +21847,27 @@ app52.post("/api/vnc/client-event", async (c) => {
|
|
|
21444
21847
|
});
|
|
21445
21848
|
return c.json({ ok: true });
|
|
21446
21849
|
});
|
|
21447
|
-
|
|
21850
|
+
app54.get("/g/:slug", (c) => {
|
|
21448
21851
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
21449
21852
|
});
|
|
21450
21853
|
for (const pwa of PWA_SURFACES) {
|
|
21451
|
-
|
|
21854
|
+
app54.get(pwa.manifestPath, (c) => {
|
|
21452
21855
|
const manifest = buildManifest(pwa, {
|
|
21453
21856
|
productName: BRAND.productName,
|
|
21454
|
-
|
|
21857
|
+
appIcon192: brandAppIcon192Path,
|
|
21858
|
+
appIcon512: brandAppIcon512Path,
|
|
21859
|
+
maskableIcon: brandMaskableIconPath,
|
|
21455
21860
|
themeColor: brandThemeColor,
|
|
21456
21861
|
backgroundColor: brandBackgroundColor
|
|
21457
21862
|
});
|
|
21458
21863
|
c.header("Content-Type", MANIFEST_CONTENT_TYPE);
|
|
21459
21864
|
console.log(
|
|
21460
|
-
`[pwa] op=manifest surface=${pwa.surface} brand=${BRAND.productName} status=200 ct=${MANIFEST_CONTENT_TYPE} icon=${
|
|
21865
|
+
`[pwa] op=manifest surface=${pwa.surface} brand=${BRAND.productName} status=200 ct=${MANIFEST_CONTENT_TYPE} icon=${brandAppIcon512Path} iconExists=${brandAppIconsExist}`
|
|
21461
21866
|
);
|
|
21462
21867
|
return c.body(JSON.stringify(manifest));
|
|
21463
21868
|
});
|
|
21464
21869
|
}
|
|
21465
|
-
|
|
21870
|
+
app54.get("/sw.js", (c) => {
|
|
21466
21871
|
if (SW_SOURCE == null) {
|
|
21467
21872
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
21468
21873
|
return c.text("Service worker unavailable", 500);
|
|
@@ -21471,27 +21876,32 @@ app52.get("/sw.js", (c) => {
|
|
|
21471
21876
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
21472
21877
|
return c.body(SW_SOURCE);
|
|
21473
21878
|
});
|
|
21474
|
-
|
|
21879
|
+
app54.get("/graph", (c) => {
|
|
21475
21880
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21476
21881
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
21477
21882
|
return c.html(cachedHtml("graph.html"));
|
|
21478
21883
|
});
|
|
21479
|
-
|
|
21884
|
+
app54.get("/chat", (c) => {
|
|
21480
21885
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21481
21886
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21482
21887
|
return c.html(cachedHtml("chat.html"));
|
|
21483
21888
|
});
|
|
21484
|
-
|
|
21889
|
+
app54.get("/data", (c) => {
|
|
21485
21890
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21486
21891
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21487
21892
|
return c.html(cachedHtml("data.html"));
|
|
21488
21893
|
});
|
|
21489
|
-
|
|
21894
|
+
app54.get("/calendar", (c) => {
|
|
21895
|
+
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21896
|
+
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
21897
|
+
return c.html(cachedHtml("calendar.html"));
|
|
21898
|
+
});
|
|
21899
|
+
app54.get("/browser", (c) => {
|
|
21490
21900
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21491
21901
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
21492
21902
|
return c.html(cachedHtml("browser.html"));
|
|
21493
21903
|
});
|
|
21494
|
-
|
|
21904
|
+
app54.get("/:slug", async (c, next) => {
|
|
21495
21905
|
const slug = c.req.param("slug");
|
|
21496
21906
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
21497
21907
|
const account = resolveAccount();
|
|
@@ -21506,13 +21916,13 @@ app52.get("/:slug", async (c, next) => {
|
|
|
21506
21916
|
await next();
|
|
21507
21917
|
});
|
|
21508
21918
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
21509
|
-
|
|
21919
|
+
app54.get("/favicon.ico", (c) => {
|
|
21510
21920
|
c.header("Cache-Control", "public, max-age=300");
|
|
21511
21921
|
return c.redirect(brandFaviconPath, 302);
|
|
21512
21922
|
});
|
|
21513
21923
|
}
|
|
21514
|
-
|
|
21515
|
-
|
|
21924
|
+
app54.use("/*", serveStatic({ root: "./public" }));
|
|
21925
|
+
app54.all("*", (c) => {
|
|
21516
21926
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
21517
21927
|
const path2 = c.req.path;
|
|
21518
21928
|
if (isPublicHost(host)) {
|
|
@@ -21526,8 +21936,30 @@ app52.all("*", (c) => {
|
|
|
21526
21936
|
});
|
|
21527
21937
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
21528
21938
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
21529
|
-
var httpServer = serve({ fetch:
|
|
21939
|
+
var httpServer = serve({ fetch: app54.fetch, port, hostname });
|
|
21530
21940
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
21941
|
+
{
|
|
21942
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join30(__dirname, "..");
|
|
21943
|
+
const reconcileScript = resolve33(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
21944
|
+
const RECONCILE_INTERVAL_MS = 12e4;
|
|
21945
|
+
const runReconcile = () => {
|
|
21946
|
+
if (!existsSync31(reconcileScript)) return;
|
|
21947
|
+
try {
|
|
21948
|
+
const child = spawn3(process.execPath, [reconcileScript], {
|
|
21949
|
+
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
21950
|
+
stdio: "inherit"
|
|
21951
|
+
});
|
|
21952
|
+
child.unref();
|
|
21953
|
+
child.on("error", (err) => console.error(`[calendar-reconcile] spawn-failed err="${err.message}"`));
|
|
21954
|
+
} catch (err) {
|
|
21955
|
+
console.error(`[calendar-reconcile] spawn-failed err="${err.message}"`);
|
|
21956
|
+
}
|
|
21957
|
+
};
|
|
21958
|
+
const firstRun = setTimeout(runReconcile, 15e3);
|
|
21959
|
+
firstRun.unref();
|
|
21960
|
+
const loop = setInterval(runReconcile, RECONCILE_INTERVAL_MS);
|
|
21961
|
+
loop.unref();
|
|
21962
|
+
}
|
|
21531
21963
|
{
|
|
21532
21964
|
const census = pwaCensus({
|
|
21533
21965
|
shellHtml: (file) => {
|
|
@@ -21537,7 +21969,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
21537
21969
|
return null;
|
|
21538
21970
|
}
|
|
21539
21971
|
},
|
|
21540
|
-
iconExists: () =>
|
|
21972
|
+
iconExists: () => brandAppIconsExist
|
|
21541
21973
|
});
|
|
21542
21974
|
console.log(
|
|
21543
21975
|
`[pwa-census] surfaces=${census.surfaces} manifest-linked=${census.manifestLinked} icons-present=${census.iconsPresent}`
|
|
@@ -21569,6 +22001,7 @@ var SUBAPP_MANIFEST = [
|
|
|
21569
22001
|
{ prefix: "/api/admin", file: "server/routes/admin/index.ts", subapp: admin_default },
|
|
21570
22002
|
{ prefix: "/api/access", file: "server/routes/access/index.ts", subapp: access_default },
|
|
21571
22003
|
{ prefix: "/api/session", file: "server/routes/session.ts", subapp: session_default2 },
|
|
22004
|
+
{ prefix: "/api/calendar", file: "server/routes/calendar-public.ts", subapp: calendar_public_default },
|
|
21572
22005
|
{ prefix: "/api/_client-error", file: "server/routes/client-error.ts", subapp: client_error_default },
|
|
21573
22006
|
{ prefix: "/listings", file: "server/routes/listings.ts", subapp: listings_default },
|
|
21574
22007
|
{ prefix: "/v", file: "server/routes/visitor-event.ts", subapp: visitor_event_default },
|
|
@@ -21580,7 +22013,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
21580
22013
|
}
|
|
21581
22014
|
try {
|
|
21582
22015
|
const registered = [];
|
|
21583
|
-
for (const r of
|
|
22016
|
+
for (const r of app54.routes ?? []) {
|
|
21584
22017
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
21585
22018
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
21586
22019
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -21624,7 +22057,7 @@ async function runAdminUserReconcileTick() {
|
|
|
21624
22057
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
21625
22058
|
return;
|
|
21626
22059
|
}
|
|
21627
|
-
const usersRaw =
|
|
22060
|
+
const usersRaw = readFileSync33(USERS_FILE, "utf-8").trim();
|
|
21628
22061
|
if (!usersRaw) {
|
|
21629
22062
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
21630
22063
|
return;
|
|
@@ -21738,7 +22171,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
21738
22171
|
}
|
|
21739
22172
|
init({
|
|
21740
22173
|
configDir: configDirForWhatsApp,
|
|
21741
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
22174
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join30(__dirname, "..")),
|
|
21742
22175
|
accountConfig: bootAccountConfig,
|
|
21743
22176
|
onMessage: async (msg) => {
|
|
21744
22177
|
if (msg.isOwnerMirror) {
|