@rubytech/create-maxy-code 0.1.503 → 0.1.505
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/models/dist/index.d.ts +5 -5
- package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/models/dist/index.js +7 -7
- package/payload/platform/lib/models/dist/index.js.map +1 -1
- package/payload/platform/lib/models/src/index.ts +7 -7
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +47 -2
- package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
- package/payload/platform/plugins/docs/references/admin-session.md +1 -1
- package/payload/platform/plugins/docs/references/admin-ui.md +46 -1
- package/payload/platform/plugins/work/PLUGIN.md +3 -3
- package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.d.ts +2 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.d.ts.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.js +55 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.js.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js +2 -2
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-create-assigned-admin-env.test.js +33 -1
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-create-assigned-admin-env.test.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.d.ts +2 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.d.ts.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.js +73 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.js.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/index.js +5 -2
- package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.d.ts +13 -0
- package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.d.ts.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.js +66 -0
- package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.js.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js +2 -2
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts +8 -0
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +31 -13
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts +4 -0
- package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-list.js +3 -2
- package/payload/platform/plugins/work/mcp/dist/tools/work-list.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts +7 -0
- package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-update.js +31 -0
- package/payload/platform/plugins/work/mcp/dist/tools/work-update.js.map +1 -1
- package/payload/platform/scripts/logs-read-jsonl.test.sh +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +2 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pricing.d.ts +19 -11
- package/payload/platform/services/claude-session-manager/dist/pricing.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pricing.js +18 -15
- package/payload/platform/services/claude-session-manager/dist/pricing.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-metering.js +3 -3
- package/payload/platform/services/claude-session-manager/dist/session-metering.js.map +1 -1
- package/payload/platform/templates/account.json +1 -1
- package/payload/platform/templates/specialists/agents/coding-assistant.md +1 -1
- package/payload/platform/templates/specialists/agents/content-producer.md +1 -1
- package/payload/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/platform/templates/specialists/agents/research-assistant.md +1 -1
- package/payload/server/public/activity.html +6 -6
- package/payload/server/public/agents.html +18 -0
- package/payload/server/public/assets/{AdminLoginScreens-Bv_bKKeL.js → AdminLoginScreens-DeWt3H7l.js} +1 -1
- package/payload/server/public/assets/AdminShell-u32d8puE.js +2 -0
- package/payload/server/public/assets/{activity-DZFYDHNA.js → activity-DjP45-DD.js} +1 -1
- package/payload/server/public/assets/admin-Bo-Y6Vjx.js +1 -0
- package/payload/server/public/assets/agents-C80aCXd8.js +1 -0
- package/payload/server/public/assets/{arc-CvlzUHOf.js → arc-DaI5MLTq.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-DWZIX5aV.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-I1Hs0RJA.js → architectureDiagram-Q4EWVU46-CBGVUEN9.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Df5jTGtl.js → blockDiagram-DXYQGD6D-DS6dS4GZ.js} +1 -1
- package/payload/server/public/assets/{browser-Bt4-LKLU.js → browser-ULvl_K5x.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B6WY5IDv.js → c4Diagram-AHTNJAMY-hBSBUZPt.js} +1 -1
- package/payload/server/public/assets/calendar-CGMrT6WZ.js +1 -0
- package/payload/server/public/assets/channel-BEokjAeE.js +1 -0
- package/payload/server/public/assets/chat-DnWXaWD4.js +1 -0
- package/payload/server/public/assets/chevron-left-BB5Iljw-.js +1 -0
- package/payload/server/public/assets/chevron-right-DijU96_j.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BsIIFDkc.js → chunk-2KRD3SAO-B6koUoB7.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-j9z1VtyC.js → chunk-336JU56O-BF6BRh8u.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-pbQ4PWBU.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-C9i7prxq.js → chunk-4BX2VUAB-7sO95xR2.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DH0QVGcv.js → chunk-4TB4RGXK-GCTndJYx.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-Dnd_YCPA.js → chunk-55IACEB6-ggIJf_TC.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-D5sSz3yN.js → chunk-5FUZZQ4R-DeGmkimt.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-CJrwWjAT.js → chunk-5PVQY5BW-aFIQKk_U.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-SjP6_hUw.js → chunk-67CJDMHE-LS8rUbii.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-fAuhVJD0.js → chunk-7N4EOEYR-JKOVngS0.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-DZxa7KVg.js → chunk-AA7GKIK3-CoXnTVK6.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-DjeG3eQ-.js → chunk-BSJP7CBP-CcsqObFg.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-RYQULNJm.js → chunk-CIAEETIT-CpsybR7q.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-Cahapnon.js → chunk-EDXVE4YY-BZ2I9PSq.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-1146X1L4.js → chunk-ENJZ2VHE-DbTwt6OZ.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-BCFumtcP.js → chunk-FMBD7UC4-D27VnSCa.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-CkrtX8Zt.js → chunk-FOC6F5B3-C0tU2UFl.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-Ba1y3DaW.js → chunk-ICPOFSXX-UPPu2OIq.js} +1 -1
- package/payload/server/public/assets/{chunk-K5T4RW27-CF-PI3uQ.js → chunk-K5T4RW27-DIKxqyYw.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-SFFC6ZC-.js → chunk-KGLVRYIC-CiL4YVLo.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-DbOLEP4R.js → chunk-LIHQZDEY-ejKezVlD.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-VB963bkN.js → chunk-ORNJ4GCN-Cc0vqc-D.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-DWYY1pQa.js → chunk-OYMX7WX6-Drxn1qG0.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-Dhlh7Pkk.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-DAH1diYP.js → chunk-U2HBQHQK-DnbQIkRP.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-Dmw9coXz.js → chunk-X2U36JSP-CauTSVWg.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-DaAUON1-.js → chunk-XPW4576I-DZqqB9Zi.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-BUcfkEef.js → chunk-YZCP3GAM-BGHo4Li-.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BLD-vFRO.js → chunk-ZZ45TVLE-DWGJKPd7.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-D2z_ZV1x.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BJwJoNEK.js +1 -0
- package/payload/server/public/assets/clock-DsmnhhJh.js +1 -0
- package/payload/server/public/assets/clone-Bn7XXVhr.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-CoZX0uki.js → cose-bilkent-S5V4N54A-D-95BzXL.js} +1 -1
- package/payload/server/public/assets/{dagre-Bmjs8zJA.js → dagre-BZYNBHvT.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BZCP2wnq.js → dagre-KV5264BT-DyU4HQLQ.js} +1 -1
- package/payload/server/public/assets/data-JPlhOLGC.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-8Nt9a4xX.js → diagram-5BDNPKRD-CCttJ9XA.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-vh5tcYqJ.js → diagram-G4DWMVQ6-DvkpgSLO.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DGf--jc8.js → diagram-MMDJMWI5-DHmW5Y9k.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CsO7TIdw.js → diagram-TYMM5635-C6T4hwzO.js} +1 -1
- package/payload/server/public/assets/{dist-cdnE4DqK.js → dist-QvbmK1IP.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-4a78yV8_.js → erDiagram-SMLLAGMA-5v_o7s3T.js} +1 -1
- package/payload/server/public/assets/{file-text-BpLcZKld.js → file-text-C5K6DMcK.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BoQBXs6t.js → flowDiagram-DWJPFMVM-3UhCDsjt.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CvzqwCC8.js → ganttDiagram-T4ZO3ILL-F2zgHIIQ.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-C-FvNTHZ.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-D_nBxay_.js → gitGraphDiagram-UUTBAWPF-oQc1N3dT.js} +1 -1
- package/payload/server/public/assets/graph-CO6e1bgD.js +51 -0
- package/payload/server/public/assets/{graph-labels-Bx19ZYvJ.js → graph-labels-iliQjlfE.js} +1 -1
- package/payload/server/public/assets/{graphlib-D0NdsKJI.js → graphlib-DY4-AT2Q.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BjLPgHAC.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-CXNKLTui.js +2 -0
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-auW-s0i0.js → ishikawaDiagram-UXIWVN3A-wJhSOkuw.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-3Q6AWK4A.js → journeyDiagram-VCZTEJTY-DgadC6Pz.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-B4MPFp98.js → kanban-definition-6JOO6SKY-Bs4nQqXI.js} +1 -1
- package/payload/server/public/assets/{line-26MdeG5Z.js → line-Bnmxy1hO.js} +1 -1
- package/payload/server/public/assets/{linear-Dq9s_bDO.js → linear-RvwZxFzh.js} +1 -1
- package/payload/server/public/assets/{maximize-2-BhR-Ec21.js → maximize-2-D-64XK6V.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-vLEpOXgf.js → mermaid-parser.core-DeNV8RtA.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-Durk4m6D.js → mermaid.core-BU9IiSCP.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DOIg-TyG.js → mindmap-definition-QFDTVHPH-D1PMUxxm.js} +1 -1
- package/payload/server/public/assets/operator-DyXgogJ1.js +1 -0
- package/payload/server/public/assets/packet-4T2RLAQJ-BBAZASfb.js +1 -0
- package/payload/server/public/assets/page-DrbiAFS-.js +32 -0
- package/payload/server/public/assets/page-WeM2ry61.js +1 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-CCJUnMeG.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-DtgBHZfi.js → pieDiagram-DEJITSTG-BzdNzoKA.js} +1 -1
- package/payload/server/public/assets/{public-DZHPsyKX.js → public-B9NVDBxW.js} +1 -1
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BTc5Qn2y.js → quadrantDiagram-34T5L4WZ-oFr1MJRO.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BsRU8Aep.js +1 -0
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-BNgOO5YW.js → requirementDiagram-MS252O5E-C9QBQxDh.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-D9qOBLig.js → rotate-ccw-P35h7ogS.js} +1 -1
- package/payload/server/public/assets/routines-BeiynLF7.js +1 -0
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-MyUATmVt.js → sankeyDiagram-XADWPNL6-c_y3bvVv.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-CBJrF5Vi.js → sequenceDiagram-FGHM5R23-YwlCBPHE.js} +1 -1
- package/payload/server/public/assets/skills-C5H7ohLp.js +1 -0
- package/payload/server/public/assets/{src-DekKlUCp.js → src-C2WwTWSY.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-6wbUjn1Q.js → stateDiagram-FHFEXIEX-BFE3e-FM.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CpjB4ykI.js +1 -0
- package/payload/server/public/assets/tasks-CI74_b6H.js +1 -0
- package/payload/server/public/assets/{time-entry-format-RkCW7hKu.js → time-entry-format-CDhHCMrW.js} +1 -1
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BHjTMCGY.js → timeline-definition-GMOUNBTQ-azqhmRwZ.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BDzhKA6v.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-epHpdeWa.js +1 -0
- package/payload/server/public/assets/{triangle-alert-k8ulav-N.js → triangle-alert-OgY71rDV.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-DN1WA5vU.js → useCopyFeedback-jOGmWwa3.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-6AFuRawP.js +9 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-fvBunpOC.css → useSubAccountSwitcher-AFSwtthL.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-v--TIxaM.js → useVoiceRecorder-CnE3fhfV.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-yo3-cf0U.js → vennDiagram-DHZGUBPP-Da2RfFs8.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-DNSZCrxV.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DZlyFzrg.js → wardleyDiagram-NUSXRM2D-HdrdBYES.js} +1 -1
- package/payload/server/public/assets/{wrench-CKhz8KnQ.js → wrench-B1hsCj0R.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-B5HV5h80.js → xychartDiagram-5P7HB3ND-DMk6rTcQ.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +14 -15
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/graph.html +10 -10
- package/payload/server/public/index.html +15 -16
- package/payload/server/public/operator.html +15 -16
- package/payload/server/public/public.html +14 -15
- package/payload/server/public/routines.html +7 -7
- package/payload/server/public/skills.html +6 -6
- package/payload/server/public/tasks.html +7 -7
- package/payload/server/server.js +800 -454
- package/payload/server/public/assets/AdminShell-Gq8DU_ig.js +0 -2
- package/payload/server/public/assets/admin-DLUOixl6.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-BQc779DH.js +0 -1
- package/payload/server/public/assets/bot-CrEhKW1l.js +0 -1
- package/payload/server/public/assets/calendar-B8ujkn_K.js +0 -1
- package/payload/server/public/assets/channel-AqnC3SHu.js +0 -1
- package/payload/server/public/assets/chat-lQXd6gsM.js +0 -1
- package/payload/server/public/assets/chevron-left-CQ8rcBoO.js +0 -1
- package/payload/server/public/assets/chevron-right-CSRSqblN.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-CO02gU5d.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-BiFMbK8t.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BdRqzScB.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-ChPLgHbS.js +0 -1
- package/payload/server/public/assets/clock-B7Ba8AZL.js +0 -1
- package/payload/server/public/assets/clone-TKtrjWBC.js +0 -1
- package/payload/server/public/assets/data-BdlGqjKM.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-DfcaTE9L.js +0 -1
- package/payload/server/public/assets/graph-HB0199x-.js +0 -51
- package/payload/server/public/assets/info-OMHHGYJF-CD-u6gw9.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-C6gPQCvO.js +0 -2
- package/payload/server/public/assets/operator-Bf3hP3qo.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-BaLYeIrU.js +0 -1
- package/payload/server/public/assets/page-Bs24tO-C.js +0 -32
- package/payload/server/public/assets/page-FnCmAeHc.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-CL-XJtk-.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-Cn-g6F_h.js +0 -1
- package/payload/server/public/assets/routines-lGiYaMiX.js +0 -1
- package/payload/server/public/assets/skills-y-h0P9rC.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdMdfBeC.js +0 -1
- package/payload/server/public/assets/tasks-Cyc1EfLA.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CmZoOGlC.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-H27WFS-y.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-iQGqNJhI.js +0 -9
- package/payload/server/public/assets/wardley-RL74JXVD-DNpWIvU4.js +0 -1
- /package/payload/server/public/assets/{chunk-CCr-iYLO.js → chunk-CltuBf4Z.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -146,7 +146,7 @@ var require_dist = __commonJS({
|
|
|
146
146
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
147
147
|
exports.ACTIVE_CANDIDATE_FLOOR = exports.SAME_SUBJECT_COSINE = void 0;
|
|
148
148
|
exports.formatStandingRulesBlock = formatStandingRulesBlock2;
|
|
149
|
-
exports.resolveOwnerUserId =
|
|
149
|
+
exports.resolveOwnerUserId = resolveOwnerUserId3;
|
|
150
150
|
exports.queryActiveRuleCandidates = queryActiveRuleCandidates;
|
|
151
151
|
exports.resolveActiveRules = resolveActiveRules2;
|
|
152
152
|
exports.activeRuleSet = activeRuleSet;
|
|
@@ -159,7 +159,7 @@ var require_dist = __commonJS({
|
|
|
159
159
|
return `## Standing rules
|
|
160
160
|
${lines.join("\n")}`;
|
|
161
161
|
}
|
|
162
|
-
async function
|
|
162
|
+
async function resolveOwnerUserId3(session, accountId) {
|
|
163
163
|
const res = await session.run(`
|
|
164
164
|
MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
165
165
|
RETURN au.userId AS userId
|
|
@@ -194,7 +194,7 @@ ${lines.join("\n")}`;
|
|
|
194
194
|
async function resolveCandidates(session, accountId) {
|
|
195
195
|
let ownerUserId;
|
|
196
196
|
try {
|
|
197
|
-
ownerUserId = await
|
|
197
|
+
ownerUserId = await resolveOwnerUserId3(session, accountId);
|
|
198
198
|
} catch {
|
|
199
199
|
return { candidates: [], ownerUserId: null, source: "owner-error" };
|
|
200
200
|
}
|
|
@@ -1753,10 +1753,10 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1753
1753
|
};
|
|
1754
1754
|
|
|
1755
1755
|
// server/index.ts
|
|
1756
|
-
import { readFileSync as
|
|
1756
|
+
import { readFileSync as readFileSync47, existsSync as existsSync46, watchFile, readdirSync as readdirSync28, statSync as statSync20 } from "fs";
|
|
1757
1757
|
import { spawn as spawn3 } from "child_process";
|
|
1758
1758
|
import { createHash as createHash7 } from "crypto";
|
|
1759
|
-
import { resolve as
|
|
1759
|
+
import { resolve as resolve44, join as join47, basename as basename14 } from "path";
|
|
1760
1760
|
import { homedir as homedir4 } from "os";
|
|
1761
1761
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1762
1762
|
|
|
@@ -3030,7 +3030,7 @@ var credsSaveQueue = Promise.resolve();
|
|
|
3030
3030
|
async function drainCredsSaveQueue(timeoutMs = 5e3) {
|
|
3031
3031
|
console.error(`${TAG6} draining credential save queue\u2026`);
|
|
3032
3032
|
const timer = new Promise(
|
|
3033
|
-
(
|
|
3033
|
+
(resolve45) => setTimeout(() => resolve45("timeout"), timeoutMs)
|
|
3034
3034
|
);
|
|
3035
3035
|
const result = await Promise.race([
|
|
3036
3036
|
credsSaveQueue.then(() => "drained"),
|
|
@@ -3207,11 +3207,11 @@ async function createWaSocket(opts) {
|
|
|
3207
3207
|
return sock;
|
|
3208
3208
|
}
|
|
3209
3209
|
async function waitForConnection(sock) {
|
|
3210
|
-
return new Promise((
|
|
3210
|
+
return new Promise((resolve45, reject) => {
|
|
3211
3211
|
const handler = (update) => {
|
|
3212
3212
|
if (update.connection === "open") {
|
|
3213
3213
|
sock.ev.off("connection.update", handler);
|
|
3214
|
-
|
|
3214
|
+
resolve45();
|
|
3215
3215
|
}
|
|
3216
3216
|
if (update.connection === "close") {
|
|
3217
3217
|
sock.ev.off("connection.update", handler);
|
|
@@ -3319,7 +3319,7 @@ function isTimeoutError(err) {
|
|
|
3319
3319
|
return Boolean(err?.__maxyTimeout);
|
|
3320
3320
|
}
|
|
3321
3321
|
function withTimeout(label, promise, timeoutMs) {
|
|
3322
|
-
return new Promise((
|
|
3322
|
+
return new Promise((resolve45, reject) => {
|
|
3323
3323
|
const timer = setTimeout(() => {
|
|
3324
3324
|
const err = new Error(`${label} timed out after ${timeoutMs}ms`);
|
|
3325
3325
|
err.__maxyTimeout = true;
|
|
@@ -3329,7 +3329,7 @@ function withTimeout(label, promise, timeoutMs) {
|
|
|
3329
3329
|
promise.then(
|
|
3330
3330
|
(value) => {
|
|
3331
3331
|
clearTimeout(timer);
|
|
3332
|
-
|
|
3332
|
+
resolve45(value);
|
|
3333
3333
|
},
|
|
3334
3334
|
(err) => {
|
|
3335
3335
|
clearTimeout(timer);
|
|
@@ -4394,8 +4394,8 @@ async function persistWhatsAppMessage(input) {
|
|
|
4394
4394
|
const { givenName, familyName } = splitName(input.pushName);
|
|
4395
4395
|
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
4396
4396
|
let release;
|
|
4397
|
-
const mine = new Promise((
|
|
4398
|
-
release =
|
|
4397
|
+
const mine = new Promise((resolve45) => {
|
|
4398
|
+
release = resolve45;
|
|
4399
4399
|
});
|
|
4400
4400
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
4401
4401
|
sessionWriteLocks.set(input.cacheKey, chained);
|
|
@@ -6132,11 +6132,11 @@ async function connectWithReconnect(conn) {
|
|
|
6132
6132
|
console.error(
|
|
6133
6133
|
`${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
|
|
6134
6134
|
);
|
|
6135
|
-
await new Promise((
|
|
6136
|
-
const timer = setTimeout(
|
|
6135
|
+
await new Promise((resolve45) => {
|
|
6136
|
+
const timer = setTimeout(resolve45, delay);
|
|
6137
6137
|
conn.abortController.signal.addEventListener("abort", () => {
|
|
6138
6138
|
clearTimeout(timer);
|
|
6139
|
-
|
|
6139
|
+
resolve45();
|
|
6140
6140
|
}, { once: true });
|
|
6141
6141
|
});
|
|
6142
6142
|
}
|
|
@@ -6144,16 +6144,16 @@ async function connectWithReconnect(conn) {
|
|
|
6144
6144
|
}
|
|
6145
6145
|
}
|
|
6146
6146
|
function waitForDisconnectEvent(conn) {
|
|
6147
|
-
return new Promise((
|
|
6147
|
+
return new Promise((resolve45) => {
|
|
6148
6148
|
if (!conn.sock) {
|
|
6149
|
-
|
|
6149
|
+
resolve45();
|
|
6150
6150
|
return;
|
|
6151
6151
|
}
|
|
6152
6152
|
const sock = conn.sock;
|
|
6153
6153
|
const handler = (update) => {
|
|
6154
6154
|
if (update.connection === "close") {
|
|
6155
6155
|
sock.ev.off("connection.update", handler);
|
|
6156
|
-
|
|
6156
|
+
resolve45();
|
|
6157
6157
|
}
|
|
6158
6158
|
};
|
|
6159
6159
|
sock.ev.on("connection.update", handler);
|
|
@@ -6627,8 +6627,8 @@ async function handleInboundMessage(conn, msg) {
|
|
|
6627
6627
|
const conversationKey = isGroup ? remoteJid : senderPhone;
|
|
6628
6628
|
const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
|
|
6629
6629
|
let resolvePending;
|
|
6630
|
-
const sttPending = new Promise((
|
|
6631
|
-
resolvePending =
|
|
6630
|
+
const sttPending = new Promise((resolve45) => {
|
|
6631
|
+
resolvePending = resolve45;
|
|
6632
6632
|
});
|
|
6633
6633
|
if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
|
|
6634
6634
|
try {
|
|
@@ -7017,20 +7017,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
|
|
|
7017
7017
|
|
|
7018
7018
|
// server/routes/health.ts
|
|
7019
7019
|
function checkPort(port2, timeoutMs = 500) {
|
|
7020
|
-
return new Promise((
|
|
7020
|
+
return new Promise((resolve45) => {
|
|
7021
7021
|
const socket = createConnection2(port2, "127.0.0.1");
|
|
7022
7022
|
socket.setTimeout(timeoutMs);
|
|
7023
7023
|
socket.once("connect", () => {
|
|
7024
7024
|
socket.destroy();
|
|
7025
|
-
|
|
7025
|
+
resolve45(true);
|
|
7026
7026
|
});
|
|
7027
7027
|
socket.once("error", () => {
|
|
7028
7028
|
socket.destroy();
|
|
7029
|
-
|
|
7029
|
+
resolve45(false);
|
|
7030
7030
|
});
|
|
7031
7031
|
socket.once("timeout", () => {
|
|
7032
7032
|
socket.destroy();
|
|
7033
|
-
|
|
7033
|
+
resolve45(false);
|
|
7034
7034
|
});
|
|
7035
7035
|
});
|
|
7036
7036
|
}
|
|
@@ -7285,8 +7285,8 @@ function webchatTurnTimeoutMs() {
|
|
|
7285
7285
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
7286
7286
|
}
|
|
7287
7287
|
function createChatRoutes(deps) {
|
|
7288
|
-
const
|
|
7289
|
-
|
|
7288
|
+
const app70 = new Hono();
|
|
7289
|
+
app70.post("/", async (c) => {
|
|
7290
7290
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
7291
7291
|
const contentType = c.req.header("content-type") ?? "";
|
|
7292
7292
|
const account = resolveAccount();
|
|
@@ -7550,7 +7550,7 @@ ${result.result.text}` : result.result.text;
|
|
|
7550
7550
|
}
|
|
7551
7551
|
});
|
|
7552
7552
|
});
|
|
7553
|
-
return
|
|
7553
|
+
return app70;
|
|
7554
7554
|
}
|
|
7555
7555
|
|
|
7556
7556
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -7584,8 +7584,8 @@ function isLoopbackAddr(addr) {
|
|
|
7584
7584
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
7585
7585
|
}
|
|
7586
7586
|
function createScheduleInjectRoutes(deps) {
|
|
7587
|
-
const
|
|
7588
|
-
|
|
7587
|
+
const app70 = new Hono();
|
|
7588
|
+
app70.post("/", async (c) => {
|
|
7589
7589
|
const env = c.env;
|
|
7590
7590
|
const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
|
|
7591
7591
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
@@ -7686,7 +7686,7 @@ function createScheduleInjectRoutes(deps) {
|
|
|
7686
7686
|
console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
|
|
7687
7687
|
return c.json({ ok: true }, 200);
|
|
7688
7688
|
});
|
|
7689
|
-
return
|
|
7689
|
+
return app70;
|
|
7690
7690
|
}
|
|
7691
7691
|
|
|
7692
7692
|
// server/index.ts
|
|
@@ -8369,8 +8369,8 @@ async function startLogin(opts) {
|
|
|
8369
8369
|
await clearAuth(authDir);
|
|
8370
8370
|
let resolveCode = null;
|
|
8371
8371
|
let rejectCode = null;
|
|
8372
|
-
const codePromise = new Promise((
|
|
8373
|
-
resolveCode =
|
|
8372
|
+
const codePromise = new Promise((resolve45, reject) => {
|
|
8373
|
+
resolveCode = resolve45;
|
|
8374
8374
|
rejectCode = reject;
|
|
8375
8375
|
});
|
|
8376
8376
|
const codeTimer = setTimeout(
|
|
@@ -13578,7 +13578,7 @@ function writeCanonicalOverrideId(accountDir, userId, sessionId) {
|
|
|
13578
13578
|
}
|
|
13579
13579
|
|
|
13580
13580
|
// ../lib/models/src/index.ts
|
|
13581
|
-
var OPUS_MODEL = "claude-opus-
|
|
13581
|
+
var OPUS_MODEL = "claude-opus-5[1m]";
|
|
13582
13582
|
var SONNET_MODEL = "claude-sonnet-5";
|
|
13583
13583
|
var HAIKU_MODEL = "claude-haiku-4-5";
|
|
13584
13584
|
var MODEL_CONTEXT_WINDOW = {
|
|
@@ -13590,7 +13590,7 @@ function contextWindow(model) {
|
|
|
13590
13590
|
return MODEL_CONTEXT_WINDOW[model] ?? 2e5;
|
|
13591
13591
|
}
|
|
13592
13592
|
var MODEL_DISPLAY_NAMES = {
|
|
13593
|
-
[OPUS_MODEL]: "Opus
|
|
13593
|
+
[OPUS_MODEL]: "Opus 5 (1M context)",
|
|
13594
13594
|
[SONNET_MODEL]: "Sonnet 5",
|
|
13595
13595
|
[HAIKU_MODEL]: "Haiku 4.5"
|
|
13596
13596
|
};
|
|
@@ -13993,8 +13993,8 @@ async function reapplyLeversViaManager() {
|
|
|
13993
13993
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
13994
13994
|
var sendSeq = 0;
|
|
13995
13995
|
function createWebchatRoutes(deps) {
|
|
13996
|
-
const
|
|
13997
|
-
|
|
13996
|
+
const app70 = new Hono();
|
|
13997
|
+
app70.post("/send", requireAdminSession, async (c) => {
|
|
13998
13998
|
let accountId;
|
|
13999
13999
|
try {
|
|
14000
14000
|
accountId = resolvePlatformAccountId();
|
|
@@ -14197,7 +14197,7 @@ ${note}` : note;
|
|
|
14197
14197
|
if (turnTimer.unref) turnTimer.unref();
|
|
14198
14198
|
return c.json({ ok: true });
|
|
14199
14199
|
});
|
|
14200
|
-
|
|
14200
|
+
app70.post("/interrupt", requireAdminSession, async (c) => {
|
|
14201
14201
|
const cacheKey = c.get("cacheKey");
|
|
14202
14202
|
const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
|
|
14203
14203
|
const primaryUserId = resolvePrimaryAdminUserId();
|
|
@@ -14225,7 +14225,7 @@ ${note}` : note;
|
|
|
14225
14225
|
}
|
|
14226
14226
|
return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
|
|
14227
14227
|
});
|
|
14228
|
-
|
|
14228
|
+
app70.post("/settings", requireAdminSession, async (c) => {
|
|
14229
14229
|
const body = await c.req.json().catch(() => null);
|
|
14230
14230
|
const op = body?.op;
|
|
14231
14231
|
const value = body?.value;
|
|
@@ -14265,7 +14265,7 @@ ${note}` : note;
|
|
|
14265
14265
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
14266
14266
|
return c.json({ ok: true, settingsApplied });
|
|
14267
14267
|
});
|
|
14268
|
-
|
|
14268
|
+
app70.get("/session", requireAdminSession, async (c) => {
|
|
14269
14269
|
let accountId;
|
|
14270
14270
|
try {
|
|
14271
14271
|
accountId = resolvePlatformAccountId();
|
|
@@ -14343,7 +14343,7 @@ ${note}` : note;
|
|
|
14343
14343
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
14344
14344
|
return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
|
|
14345
14345
|
});
|
|
14346
|
-
|
|
14346
|
+
app70.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
14347
14347
|
const body = await c.req.json().catch(() => null);
|
|
14348
14348
|
const sessionId = body?.sessionId;
|
|
14349
14349
|
const requestId = body?.request_id;
|
|
@@ -14360,7 +14360,7 @@ ${note}` : note;
|
|
|
14360
14360
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
14361
14361
|
return c.json({ ok });
|
|
14362
14362
|
});
|
|
14363
|
-
return
|
|
14363
|
+
return app70;
|
|
14364
14364
|
}
|
|
14365
14365
|
|
|
14366
14366
|
// server/routes/webchat-greeting.ts
|
|
@@ -15716,15 +15716,15 @@ function operatorRoleFor(config, userId) {
|
|
|
15716
15716
|
async function buildAccountOptionList(accounts, userId) {
|
|
15717
15717
|
const houseAccount = accounts.find((a) => a.config.role === "house");
|
|
15718
15718
|
console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
|
|
15719
|
-
const
|
|
15719
|
+
const resolve45 = async (a) => {
|
|
15720
15720
|
const businessName = await fetchAccountName(a.accountId) || void 0;
|
|
15721
15721
|
return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
|
|
15722
15722
|
};
|
|
15723
15723
|
const houseOptions = await Promise.all(
|
|
15724
|
-
accounts.filter((a) => a.config.role === "house").map(
|
|
15724
|
+
accounts.filter((a) => a.config.role === "house").map(resolve45)
|
|
15725
15725
|
);
|
|
15726
15726
|
const nonHouseOptions = await Promise.all(
|
|
15727
|
-
accounts.filter((a) => a.config.role !== "house").map(
|
|
15727
|
+
accounts.filter((a) => a.config.role !== "house").map(resolve45)
|
|
15728
15728
|
);
|
|
15729
15729
|
const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
|
|
15730
15730
|
nonHouseOptions.sort((x, y) => {
|
|
@@ -16169,36 +16169,175 @@ var session_upload_default = app17;
|
|
|
16169
16169
|
// server/routes/admin/agents.ts
|
|
16170
16170
|
import { resolve as resolve22 } from "path";
|
|
16171
16171
|
import { readdirSync as readdirSync21, readFileSync as readFileSync32, existsSync as existsSync30, rmSync as rmSync2 } from "fs";
|
|
16172
|
+
var SLUG_UNSAFE = (s) => s.includes("/") || s.includes("..") || s.includes("\\");
|
|
16173
|
+
function subdirs(dir) {
|
|
16174
|
+
if (!existsSync30(dir)) return [];
|
|
16175
|
+
try {
|
|
16176
|
+
return readdirSync21(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
16177
|
+
} catch {
|
|
16178
|
+
return [];
|
|
16179
|
+
}
|
|
16180
|
+
}
|
|
16181
|
+
function splitFrontmatter(text) {
|
|
16182
|
+
const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
16183
|
+
const fm = {};
|
|
16184
|
+
if (!m) return { fm, body: text };
|
|
16185
|
+
for (const line of m[1].split(/\r?\n/)) {
|
|
16186
|
+
const kv = line.match(/^([A-Za-z][\w-]*):[ \t]*(.*)$/);
|
|
16187
|
+
if (kv) fm[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, "").trim();
|
|
16188
|
+
}
|
|
16189
|
+
return { fm, body: text.slice(m[0].length) };
|
|
16190
|
+
}
|
|
16191
|
+
function listSpecialists(accountDir) {
|
|
16192
|
+
const pluginsDir = resolve22(accountDir, "plugins");
|
|
16193
|
+
const specialists = [];
|
|
16194
|
+
let specialistsSkipped = 0;
|
|
16195
|
+
for (const plugin of subdirs(pluginsDir).sort()) {
|
|
16196
|
+
const agentsDirP = resolve22(pluginsDir, plugin, "agents");
|
|
16197
|
+
if (!existsSync30(agentsDirP)) continue;
|
|
16198
|
+
let entries;
|
|
16199
|
+
try {
|
|
16200
|
+
entries = readdirSync21(agentsDirP, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
16201
|
+
} catch {
|
|
16202
|
+
continue;
|
|
16203
|
+
}
|
|
16204
|
+
for (const entry of entries) {
|
|
16205
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
16206
|
+
try {
|
|
16207
|
+
const { fm } = splitFrontmatter(readFileSync32(resolve22(agentsDirP, entry.name), "utf-8"));
|
|
16208
|
+
if (!fm.name) {
|
|
16209
|
+
specialistsSkipped++;
|
|
16210
|
+
console.error(`[admin/agents] op=list-specialist-skip plugin=${plugin} file=${entry.name}`);
|
|
16211
|
+
continue;
|
|
16212
|
+
}
|
|
16213
|
+
specialists.push({
|
|
16214
|
+
slug: entry.name.replace(/\.md$/, ""),
|
|
16215
|
+
displayName: fm.name,
|
|
16216
|
+
kind: "specialist",
|
|
16217
|
+
plugin,
|
|
16218
|
+
description: fm.description ?? ""
|
|
16219
|
+
});
|
|
16220
|
+
} catch {
|
|
16221
|
+
specialistsSkipped++;
|
|
16222
|
+
console.error(`[admin/agents] op=list-specialist-skip plugin=${plugin} file=${entry.name}`);
|
|
16223
|
+
}
|
|
16224
|
+
}
|
|
16225
|
+
}
|
|
16226
|
+
return { specialists, specialistsSkipped };
|
|
16227
|
+
}
|
|
16228
|
+
var OWNED_DOCS = [
|
|
16229
|
+
{ file: "IDENTITY.md", key: "identity" },
|
|
16230
|
+
{ file: "SOUL.md", key: "soul" },
|
|
16231
|
+
{ file: "KNOWLEDGE.md", key: "knowledge" },
|
|
16232
|
+
{ file: "KNOWLEDGE-SUMMARY.md", key: "knowledgeSummary" }
|
|
16233
|
+
];
|
|
16172
16234
|
var app18 = new Hono();
|
|
16173
16235
|
app18.get("/", (c) => {
|
|
16174
16236
|
const account = resolveAccount();
|
|
16175
|
-
if (!account) return c.json({ agents: [] });
|
|
16176
|
-
const agentsDir = resolve22(account.accountDir, "agents");
|
|
16177
|
-
if (!existsSync30(agentsDir)) return c.json({ agents: [] });
|
|
16237
|
+
if (!account) return c.json({ agents: [], skipped: 0, specialistsSkipped: 0 });
|
|
16178
16238
|
const agents = [];
|
|
16239
|
+
let skipped = 0;
|
|
16240
|
+
const agentsDir = resolve22(account.accountDir, "agents");
|
|
16241
|
+
if (existsSync30(agentsDir)) {
|
|
16242
|
+
try {
|
|
16243
|
+
const entries = readdirSync21(agentsDir, { withFileTypes: true });
|
|
16244
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
16245
|
+
if (!entry.isDirectory()) continue;
|
|
16246
|
+
if (entry.name === "admin") continue;
|
|
16247
|
+
const configPath2 = resolve22(agentsDir, entry.name, "config.json");
|
|
16248
|
+
if (!existsSync30(configPath2)) continue;
|
|
16249
|
+
try {
|
|
16250
|
+
const config = JSON.parse(readFileSync32(configPath2, "utf-8"));
|
|
16251
|
+
agents.push({
|
|
16252
|
+
slug: entry.name,
|
|
16253
|
+
displayName: config.displayName ?? entry.name,
|
|
16254
|
+
status: config.status ?? "unknown",
|
|
16255
|
+
kind: "public"
|
|
16256
|
+
});
|
|
16257
|
+
} catch {
|
|
16258
|
+
skipped++;
|
|
16259
|
+
console.error(`[admin/agents] failed to parse config.json for agent "${entry.name}" \u2014 skipping`);
|
|
16260
|
+
}
|
|
16261
|
+
}
|
|
16262
|
+
} catch (err) {
|
|
16263
|
+
console.error(`[admin/agents] failed to scan agents directory: ${err}`);
|
|
16264
|
+
}
|
|
16265
|
+
}
|
|
16266
|
+
const { specialists, specialistsSkipped } = listSpecialists(account.accountDir);
|
|
16267
|
+
console.log(`[admin/agents] op=list agents=${agents.length} specialists=${specialists.length} skipped=${skipped} specialistsSkipped=${specialistsSkipped}`);
|
|
16268
|
+
return c.json({ agents: [...agents, ...specialists], skipped, specialistsSkipped });
|
|
16269
|
+
});
|
|
16270
|
+
app18.get("/:slug", (c) => {
|
|
16271
|
+
const slug = c.req.param("slug");
|
|
16272
|
+
const account = resolveAccount();
|
|
16273
|
+
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
16274
|
+
if (SLUG_UNSAFE(slug)) return c.json({ error: "Invalid agent slug" }, 400);
|
|
16275
|
+
const pluginParam = c.req.query("plugin");
|
|
16276
|
+
if (pluginParam) {
|
|
16277
|
+
if (SLUG_UNSAFE(pluginParam)) return c.json({ error: "Invalid plugin" }, 400);
|
|
16278
|
+
const file = resolve22(account.accountDir, "plugins", pluginParam, "agents", `${slug}.md`);
|
|
16279
|
+
if (!existsSync30(file)) return c.json({ error: "Agent not found" }, 404);
|
|
16280
|
+
const { fm, body } = splitFrontmatter(readFileSync32(file, "utf-8"));
|
|
16281
|
+
const skills = subdirs(resolve22(account.accountDir, "plugins", pluginParam, "skills"));
|
|
16282
|
+
console.log(`[admin/agents] op=detail slug=${slug} kind=specialist plugin=${pluginParam}`);
|
|
16283
|
+
return c.json({
|
|
16284
|
+
agent: {
|
|
16285
|
+
kind: "specialist",
|
|
16286
|
+
slug,
|
|
16287
|
+
displayName: fm.name ?? slug,
|
|
16288
|
+
description: fm.description ?? "",
|
|
16289
|
+
summary: fm.summary ?? "",
|
|
16290
|
+
model: fm.model ?? null,
|
|
16291
|
+
tools: fm.tools ? fm.tools.split(",").map((t) => t.trim()).filter(Boolean) : [],
|
|
16292
|
+
systemPrompt: body.trim(),
|
|
16293
|
+
skills
|
|
16294
|
+
}
|
|
16295
|
+
});
|
|
16296
|
+
}
|
|
16297
|
+
const agentDir = resolve22(account.accountDir, "agents", slug);
|
|
16298
|
+
const configPath2 = resolve22(agentDir, "config.json");
|
|
16299
|
+
if (!existsSync30(configPath2)) return c.json({ error: "Agent not found" }, 404);
|
|
16300
|
+
let config;
|
|
16179
16301
|
try {
|
|
16180
|
-
|
|
16181
|
-
|
|
16182
|
-
|
|
16183
|
-
|
|
16184
|
-
|
|
16185
|
-
|
|
16186
|
-
|
|
16187
|
-
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
}
|
|
16194
|
-
|
|
16302
|
+
config = JSON.parse(readFileSync32(configPath2, "utf-8"));
|
|
16303
|
+
} catch {
|
|
16304
|
+
console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
|
|
16305
|
+
return c.json({ error: "Agent config unreadable" }, 500);
|
|
16306
|
+
}
|
|
16307
|
+
const docs = {};
|
|
16308
|
+
const present = {};
|
|
16309
|
+
for (const { file, key } of OWNED_DOCS) {
|
|
16310
|
+
const p = resolve22(agentDir, file);
|
|
16311
|
+
try {
|
|
16312
|
+
if (existsSync30(p)) {
|
|
16313
|
+
docs[key] = readFileSync32(p, "utf-8");
|
|
16314
|
+
present[key] = true;
|
|
16315
|
+
} else {
|
|
16316
|
+
docs[key] = "";
|
|
16317
|
+
present[key] = false;
|
|
16195
16318
|
}
|
|
16319
|
+
} catch {
|
|
16320
|
+
console.error(`[admin/agents] op=detail slug=${slug} doc=${file} error="read failed, treating as absent"`);
|
|
16321
|
+
docs[key] = "";
|
|
16322
|
+
present[key] = false;
|
|
16196
16323
|
}
|
|
16197
|
-
} catch (err) {
|
|
16198
|
-
console.error(`[admin/agents] failed to scan agents directory: ${err}`);
|
|
16199
|
-
return c.json({ agents: [] });
|
|
16200
16324
|
}
|
|
16201
|
-
|
|
16325
|
+
const found = Object.keys(present).filter((k) => present[k]);
|
|
16326
|
+
console.log(`[admin/agents] op=detail slug=${slug} present=${found.join(",") || "none"}`);
|
|
16327
|
+
return c.json({
|
|
16328
|
+
agent: {
|
|
16329
|
+
slug,
|
|
16330
|
+
displayName: config.displayName ?? slug,
|
|
16331
|
+
status: config.status ?? "unknown",
|
|
16332
|
+
model: config.model ?? null,
|
|
16333
|
+
knowledgeKeywords: config.knowledgeKeywords ?? [],
|
|
16334
|
+
identity: docs.identity,
|
|
16335
|
+
soul: docs.soul,
|
|
16336
|
+
knowledge: docs.knowledge,
|
|
16337
|
+
knowledgeSummary: docs.knowledgeSummary,
|
|
16338
|
+
present
|
|
16339
|
+
}
|
|
16340
|
+
});
|
|
16202
16341
|
});
|
|
16203
16342
|
app18.delete("/:slug", async (c) => {
|
|
16204
16343
|
const slug = c.req.param("slug");
|
|
@@ -16207,7 +16346,7 @@ app18.delete("/:slug", async (c) => {
|
|
|
16207
16346
|
if (slug === "admin") {
|
|
16208
16347
|
return c.json({ error: "Cannot delete the admin agent" }, 403);
|
|
16209
16348
|
}
|
|
16210
|
-
if (
|
|
16349
|
+
if (SLUG_UNSAFE(slug)) {
|
|
16211
16350
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
16212
16351
|
}
|
|
16213
16352
|
const agentDir = resolve22(account.accountDir, "agents", slug);
|
|
@@ -16237,7 +16376,7 @@ app18.post("/:slug/project", async (c) => {
|
|
|
16237
16376
|
if (slug === "admin") {
|
|
16238
16377
|
return c.json({ error: "Cannot project the admin agent" }, 403);
|
|
16239
16378
|
}
|
|
16240
|
-
if (
|
|
16379
|
+
if (SLUG_UNSAFE(slug)) {
|
|
16241
16380
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
16242
16381
|
}
|
|
16243
16382
|
const agentDir = resolve22(account.accountDir, "agents", slug);
|
|
@@ -17496,18 +17635,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
17496
17635
|
]);
|
|
17497
17636
|
var app22 = new Hono();
|
|
17498
17637
|
app22.post("/", async (c) => {
|
|
17499
|
-
const
|
|
17638
|
+
const TAG58 = "[admin:events]";
|
|
17500
17639
|
let body;
|
|
17501
17640
|
try {
|
|
17502
17641
|
body = await c.req.json();
|
|
17503
17642
|
} catch (err) {
|
|
17504
17643
|
const detail = err instanceof Error ? err.message : String(err);
|
|
17505
|
-
console.error(`${
|
|
17644
|
+
console.error(`${TAG58} reject reason=body-not-json detail=${detail}`);
|
|
17506
17645
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
17507
17646
|
}
|
|
17508
17647
|
const event = typeof body.event === "string" ? body.event : "";
|
|
17509
17648
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
17510
|
-
console.error(`${
|
|
17649
|
+
console.error(`${TAG58} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
17511
17650
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
17512
17651
|
}
|
|
17513
17652
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -24021,7 +24160,7 @@ function accountDirForSession(cacheKey) {
|
|
|
24021
24160
|
const match = listValidAccounts().find((a) => a.accountId === accountId);
|
|
24022
24161
|
return match ? { accountId, accountDir: match.accountDir } : null;
|
|
24023
24162
|
}
|
|
24024
|
-
function
|
|
24163
|
+
function subdirs2(dir) {
|
|
24025
24164
|
if (!existsSync38(dir)) return [];
|
|
24026
24165
|
try {
|
|
24027
24166
|
return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -24038,10 +24177,10 @@ app49.get("/", requireAdminSession, async (c) => {
|
|
|
24038
24177
|
const pluginsDir = resolve32(acct.accountDir, "plugins");
|
|
24039
24178
|
const skills = [];
|
|
24040
24179
|
let pluginCount = 0;
|
|
24041
|
-
for (const plugin of
|
|
24180
|
+
for (const plugin of subdirs2(pluginsDir)) {
|
|
24042
24181
|
pluginCount++;
|
|
24043
24182
|
const skillsDir = resolve32(pluginsDir, plugin, "skills");
|
|
24044
|
-
for (const skill of
|
|
24183
|
+
for (const skill of subdirs2(skillsDir)) {
|
|
24045
24184
|
const skillMd = resolve32(skillsDir, skill, "SKILL.md");
|
|
24046
24185
|
if (!existsSync38(skillMd)) continue;
|
|
24047
24186
|
try {
|
|
@@ -24101,7 +24240,7 @@ app49.delete("/:plugin/:skill", requireAdminSession, async (c) => {
|
|
|
24101
24240
|
}
|
|
24102
24241
|
try {
|
|
24103
24242
|
rmSync3(skillDir, { recursive: true, force: true });
|
|
24104
|
-
const pluginDirRemoved =
|
|
24243
|
+
const pluginDirRemoved = subdirs2(skillsDir).length === 0;
|
|
24105
24244
|
if (pluginDirRemoved) rmSync3(pluginDir, { recursive: true, force: true });
|
|
24106
24245
|
const skillDirGone = !existsSync38(skillDir);
|
|
24107
24246
|
if (!skillDirGone) {
|
|
@@ -24162,12 +24301,19 @@ app50.get("/", requireAdminSession, async (c) => {
|
|
|
24162
24301
|
// it: a second ASSIGNED_TO edge would fan the row out, duplicating
|
|
24163
24302
|
// rowKey and double-counting the assignee.
|
|
24164
24303
|
WITH t, openTe, head(collect(a)) AS assignee
|
|
24304
|
+
// The AdminUser carries no name property (Task 1570); the name lives on
|
|
24305
|
+
// its owned Person. Resolve it here so an assigned task shows a real name
|
|
24306
|
+
// rather than a userId slice (Task 1982).
|
|
24307
|
+
OPTIONAL MATCH (assignee)-[:OWNS]->(ap:Person) WHERE ap.accountId = assignee.accountId
|
|
24308
|
+
WITH t, openTe, assignee, head(collect(ap)) AS assigneePerson
|
|
24165
24309
|
RETURN t.taskId AS taskId, elementId(t) AS rowKey, t.name AS name, t.clientName AS clientName,
|
|
24166
24310
|
t.propertyAddress AS propertyAddress, t.fee AS fee, t.status AS status,
|
|
24167
24311
|
coalesce(t.secondsLogged, 0) AS secondsLogged,
|
|
24168
24312
|
openTe.startedAt AS runningStartedAt,
|
|
24169
24313
|
t.createdAt AS createdAt,
|
|
24170
|
-
assignee.userId AS assigneeUserId,
|
|
24314
|
+
assignee.userId AS assigneeUserId,
|
|
24315
|
+
assigneePerson.givenName AS assigneeGivenName,
|
|
24316
|
+
assigneePerson.familyName AS assigneeFamilyName
|
|
24171
24317
|
ORDER BY t.createdAt DESC`,
|
|
24172
24318
|
{ accountId }
|
|
24173
24319
|
);
|
|
@@ -24192,6 +24338,9 @@ app50.get("/", requireAdminSession, async (c) => {
|
|
|
24192
24338
|
if (createdAt === null) missingCreatedAt++;
|
|
24193
24339
|
const assigneeUserId = rec.get("assigneeUserId") ?? null;
|
|
24194
24340
|
if (assigneeUserId !== null) assigned++;
|
|
24341
|
+
const assigneeGivenName = rec.get("assigneeGivenName") ?? null;
|
|
24342
|
+
const assigneeFamilyName = rec.get("assigneeFamilyName") ?? null;
|
|
24343
|
+
const assigneeName = assigneeGivenName && assigneeGivenName.trim().length > 0 ? assigneeFamilyName && assigneeFamilyName.trim().length > 0 ? `${assigneeGivenName.trim()} ${assigneeFamilyName.trim()}` : assigneeGivenName.trim() : null;
|
|
24195
24344
|
const row = {
|
|
24196
24345
|
taskId,
|
|
24197
24346
|
rowKey: rec.get("rowKey"),
|
|
@@ -24205,7 +24354,7 @@ app50.get("/", requireAdminSession, async (c) => {
|
|
|
24205
24354
|
runningStartedAt,
|
|
24206
24355
|
createdAt,
|
|
24207
24356
|
assigneeUserId,
|
|
24208
|
-
assigneeName
|
|
24357
|
+
assigneeName
|
|
24209
24358
|
};
|
|
24210
24359
|
if (COMPLETED.has(status)) completed.push(row);
|
|
24211
24360
|
else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
|
|
@@ -24487,10 +24636,200 @@ app54.post("/", requireAdminSession, async (c) => {
|
|
|
24487
24636
|
});
|
|
24488
24637
|
var task_time_adjust_default = app54;
|
|
24489
24638
|
|
|
24490
|
-
//
|
|
24491
|
-
import { readdirSync as readdirSync25 } from "fs";
|
|
24639
|
+
// app/lib/admin-roster.ts
|
|
24640
|
+
import { existsSync as existsSync39, readdirSync as readdirSync25, readFileSync as readFileSync40 } from "fs";
|
|
24641
|
+
import { resolve as resolve33 } from "path";
|
|
24642
|
+
function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
|
|
24643
|
+
let entries;
|
|
24644
|
+
try {
|
|
24645
|
+
entries = readdirSync25(accountsDir);
|
|
24646
|
+
} catch {
|
|
24647
|
+
return [];
|
|
24648
|
+
}
|
|
24649
|
+
for (const entry of entries) {
|
|
24650
|
+
const cfgPath = resolve33(accountsDir, entry, "account.json");
|
|
24651
|
+
if (!existsSync39(cfgPath)) continue;
|
|
24652
|
+
try {
|
|
24653
|
+
const cfg = JSON.parse(readFileSync40(cfgPath, "utf-8"));
|
|
24654
|
+
if (cfg.role !== "house") continue;
|
|
24655
|
+
if (!Array.isArray(cfg.admins)) return [];
|
|
24656
|
+
return cfg.admins.map(
|
|
24657
|
+
(a) => a && typeof a === "object" && typeof a.userId === "string" ? a.userId : null
|
|
24658
|
+
).filter((u) => u !== null && u.length > 0);
|
|
24659
|
+
} catch {
|
|
24660
|
+
}
|
|
24661
|
+
}
|
|
24662
|
+
return [];
|
|
24663
|
+
}
|
|
24664
|
+
async function resolveOwnerUserId2(accountId) {
|
|
24665
|
+
const session = getSession();
|
|
24666
|
+
try {
|
|
24667
|
+
const r = await session.run(
|
|
24668
|
+
`MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
24669
|
+
RETURN au.userId AS userId ORDER BY au.createdAt ASC LIMIT 1`,
|
|
24670
|
+
{ accountId }
|
|
24671
|
+
);
|
|
24672
|
+
return r.records.length > 0 ? r.records[0].get("userId") ?? null : null;
|
|
24673
|
+
} finally {
|
|
24674
|
+
await session.close();
|
|
24675
|
+
}
|
|
24676
|
+
}
|
|
24677
|
+
async function resolveAllowedAssigneeIds(accountId, accountsDir = ACCOUNTS_DIR) {
|
|
24678
|
+
const houseIds = readHouseAdminUserIds(accountsDir);
|
|
24679
|
+
const ownerId = await resolveOwnerUserId2(accountId);
|
|
24680
|
+
const ids = new Set(houseIds);
|
|
24681
|
+
if (ownerId) ids.add(ownerId);
|
|
24682
|
+
return { ids, ownerId, houseIds };
|
|
24683
|
+
}
|
|
24684
|
+
async function resolveAssignableAdmins(accountId, accountsDir = ACCOUNTS_DIR) {
|
|
24685
|
+
const { ownerId, houseIds } = await resolveAllowedAssigneeIds(accountId, accountsDir);
|
|
24686
|
+
const candidates = Array.from(/* @__PURE__ */ new Set([...ownerId ? [ownerId] : [], ...houseIds]));
|
|
24687
|
+
if (candidates.length === 0) return [];
|
|
24688
|
+
const session = getSession();
|
|
24689
|
+
try {
|
|
24690
|
+
const r = await session.run(
|
|
24691
|
+
`UNWIND $userIds AS uid
|
|
24692
|
+
MATCH (au:AdminUser {userId: uid})
|
|
24693
|
+
OPTIONAL MATCH (au)-[:OWNS]->(p:Person) WHERE p.accountId = au.accountId
|
|
24694
|
+
RETURN au.userId AS userId, p.givenName AS givenName, p.familyName AS familyName`,
|
|
24695
|
+
{ userIds: candidates }
|
|
24696
|
+
);
|
|
24697
|
+
const present = /* @__PURE__ */ new Set();
|
|
24698
|
+
const out = [];
|
|
24699
|
+
for (const rec of r.records) {
|
|
24700
|
+
const userId = rec.get("userId");
|
|
24701
|
+
present.add(userId);
|
|
24702
|
+
const given = rec.get("givenName") ?? null;
|
|
24703
|
+
const family = rec.get("familyName") ?? null;
|
|
24704
|
+
const name = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
|
|
24705
|
+
out.push({ userId, name, kind: userId === ownerId ? "owner" : "house-admin" });
|
|
24706
|
+
}
|
|
24707
|
+
const dropped = candidates.filter((u) => !present.has(u));
|
|
24708
|
+
if (dropped.length > 0) {
|
|
24709
|
+
console.error(
|
|
24710
|
+
`[admin-roster] op=roster account=${accountId} dropped-no-adminuser=${dropped.length} ids=${dropped.map((u) => u.slice(0, 8)).join(",")}`
|
|
24711
|
+
);
|
|
24712
|
+
}
|
|
24713
|
+
out.sort((a, b) => {
|
|
24714
|
+
if (a.kind !== b.kind) return a.kind === "owner" ? -1 : 1;
|
|
24715
|
+
return (a.name ?? a.userId).localeCompare(b.name ?? b.userId);
|
|
24716
|
+
});
|
|
24717
|
+
return out;
|
|
24718
|
+
} finally {
|
|
24719
|
+
await session.close();
|
|
24720
|
+
}
|
|
24721
|
+
}
|
|
24722
|
+
|
|
24723
|
+
// server/routes/admin/task-assign.ts
|
|
24724
|
+
var TAG44 = "[task-assign]";
|
|
24492
24725
|
var app55 = new Hono();
|
|
24493
|
-
|
|
24726
|
+
app55.post("/", requireAdminSession, async (c) => {
|
|
24727
|
+
const cacheKey = c.var.cacheKey;
|
|
24728
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
24729
|
+
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
24730
|
+
let body;
|
|
24731
|
+
try {
|
|
24732
|
+
body = await c.req.json();
|
|
24733
|
+
} catch {
|
|
24734
|
+
return c.json({ error: "invalid-json" }, 400);
|
|
24735
|
+
}
|
|
24736
|
+
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
24737
|
+
if (!taskId) {
|
|
24738
|
+
const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
|
|
24739
|
+
console.error(`${TAG44} op=assign rejected reason=${reason} account=${accountId}`);
|
|
24740
|
+
return c.json({ error: "taskId required" }, 400);
|
|
24741
|
+
}
|
|
24742
|
+
const rawAssignee = body.assigneeUserId;
|
|
24743
|
+
if (rawAssignee !== null && rawAssignee !== void 0 && typeof rawAssignee !== "string") {
|
|
24744
|
+
return c.json({ error: "assigneeUserId must be a string or null" }, 400);
|
|
24745
|
+
}
|
|
24746
|
+
const assigneeUserId = typeof rawAssignee === "string" && rawAssignee.length > 0 ? rawAssignee : null;
|
|
24747
|
+
if (assigneeUserId !== null) {
|
|
24748
|
+
const { ids } = await resolveAllowedAssigneeIds(accountId);
|
|
24749
|
+
if (!ids.has(assigneeUserId)) {
|
|
24750
|
+
console.error(
|
|
24751
|
+
`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=not-in-roster`
|
|
24752
|
+
);
|
|
24753
|
+
return c.json({ error: "assignee-not-in-roster" }, 403);
|
|
24754
|
+
}
|
|
24755
|
+
}
|
|
24756
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24757
|
+
const session = getSession();
|
|
24758
|
+
try {
|
|
24759
|
+
const cleared = await session.run(
|
|
24760
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
24761
|
+
OPTIONAL MATCH (t)-[r:ASSIGNED_TO]->(:AdminUser) DELETE r
|
|
24762
|
+
RETURN t.taskId AS taskId`,
|
|
24763
|
+
{ taskId, accountId, now }
|
|
24764
|
+
);
|
|
24765
|
+
if (cleared.records.length === 0) {
|
|
24766
|
+
return c.json({ error: "task-not-found" }, 404);
|
|
24767
|
+
}
|
|
24768
|
+
if (assigneeUserId === null) {
|
|
24769
|
+
await session.run(
|
|
24770
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId}) SET t.updatedAt = $now`,
|
|
24771
|
+
{ taskId, accountId, now }
|
|
24772
|
+
);
|
|
24773
|
+
console.log(`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=none assigned=false source=route`);
|
|
24774
|
+
return c.json({ ok: true, assigneeUserId: null, assigneeName: null });
|
|
24775
|
+
}
|
|
24776
|
+
const set = await session.run(
|
|
24777
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
24778
|
+
MATCH (au:AdminUser {userId: $assigneeUserId})
|
|
24779
|
+
MERGE (t)-[:ASSIGNED_TO]->(au)
|
|
24780
|
+
SET t.updatedAt = $now
|
|
24781
|
+
WITH t, au
|
|
24782
|
+
OPTIONAL MATCH (au)-[:OWNS]->(p:Person) WHERE p.accountId = au.accountId
|
|
24783
|
+
RETURN au.userId AS userId, p.givenName AS givenName, p.familyName AS familyName`,
|
|
24784
|
+
{ taskId, accountId, assigneeUserId, now }
|
|
24785
|
+
);
|
|
24786
|
+
if (set.records.length === 0) {
|
|
24787
|
+
console.error(
|
|
24788
|
+
`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=no-adminuser-node`
|
|
24789
|
+
);
|
|
24790
|
+
return c.json({ error: "assignee-no-admin-node" }, 409);
|
|
24791
|
+
}
|
|
24792
|
+
const given = set.records[0].get("givenName") ?? null;
|
|
24793
|
+
const family = set.records[0].get("familyName") ?? null;
|
|
24794
|
+
const assigneeName = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
|
|
24795
|
+
console.log(
|
|
24796
|
+
`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=true source=route`
|
|
24797
|
+
);
|
|
24798
|
+
return c.json({ ok: true, assigneeUserId, assigneeName });
|
|
24799
|
+
} catch (err) {
|
|
24800
|
+
console.error(`${TAG44} op=assign error="${err instanceof Error ? err.message : String(err)}"`);
|
|
24801
|
+
return c.json({ error: "task-assign-failed" }, 500);
|
|
24802
|
+
} finally {
|
|
24803
|
+
await session.close();
|
|
24804
|
+
}
|
|
24805
|
+
});
|
|
24806
|
+
var task_assign_default = app55;
|
|
24807
|
+
|
|
24808
|
+
// server/routes/admin/admin-users-list.ts
|
|
24809
|
+
var TAG45 = "[admin-users]";
|
|
24810
|
+
var app56 = new Hono();
|
|
24811
|
+
app56.get("/", requireAdminSession, async (c) => {
|
|
24812
|
+
const cacheKey = c.var.cacheKey;
|
|
24813
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
24814
|
+
if (!accountId) {
|
|
24815
|
+
console.error(`${TAG45} op=list auth-rejected reason="no account for session"`);
|
|
24816
|
+
return c.json({ error: "Account not found for session" }, 401);
|
|
24817
|
+
}
|
|
24818
|
+
try {
|
|
24819
|
+
const users = await resolveAssignableAdmins(accountId);
|
|
24820
|
+
console.log(`${TAG45} op=list account=${accountId} count=${users.length}`);
|
|
24821
|
+
return c.json({ ok: true, users });
|
|
24822
|
+
} catch (err) {
|
|
24823
|
+
console.error(`${TAG45} op=list error="${err instanceof Error ? err.message : String(err)}"`);
|
|
24824
|
+
return c.json({ error: "admin-users-list-failed" }, 500);
|
|
24825
|
+
}
|
|
24826
|
+
});
|
|
24827
|
+
var admin_users_list_default = app56;
|
|
24828
|
+
|
|
24829
|
+
// server/routes/admin/activity.ts
|
|
24830
|
+
import { readdirSync as readdirSync26 } from "fs";
|
|
24831
|
+
var app57 = new Hono();
|
|
24832
|
+
var TAG46 = "[activity]";
|
|
24494
24833
|
function resolveHouseAccountId(accounts) {
|
|
24495
24834
|
const houses = accounts.filter((a) => a.config.role === "house");
|
|
24496
24835
|
if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
|
|
@@ -24504,14 +24843,14 @@ function requestToken() {
|
|
|
24504
24843
|
var short = (id) => id ? id.slice(0, 8) : "unset";
|
|
24505
24844
|
function countAccountDirsOnDisk() {
|
|
24506
24845
|
try {
|
|
24507
|
-
return
|
|
24846
|
+
return readdirSync26(ACCOUNTS_DIR, { withFileTypes: true }).filter(
|
|
24508
24847
|
(e) => e.isDirectory() && !e.name.startsWith(".")
|
|
24509
24848
|
).length;
|
|
24510
24849
|
} catch {
|
|
24511
24850
|
return null;
|
|
24512
24851
|
}
|
|
24513
24852
|
}
|
|
24514
|
-
|
|
24853
|
+
app57.get("/", requireAdminSession, async (c) => {
|
|
24515
24854
|
const req = requestToken();
|
|
24516
24855
|
const cacheKey = c.var.cacheKey;
|
|
24517
24856
|
const caller2 = getAccountIdForSession(cacheKey) ?? null;
|
|
@@ -24519,19 +24858,19 @@ app55.get("/", requireAdminSession, async (c) => {
|
|
|
24519
24858
|
const house = resolveHouseAccountId(valid);
|
|
24520
24859
|
const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
|
|
24521
24860
|
console.log(
|
|
24522
|
-
`${
|
|
24861
|
+
`${TAG46} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
|
|
24523
24862
|
);
|
|
24524
24863
|
if (!isHouse) {
|
|
24525
24864
|
const reason = house.accountId === null ? house.reason : "not-house";
|
|
24526
24865
|
console.error(
|
|
24527
|
-
`${
|
|
24866
|
+
`${TAG46} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
|
|
24528
24867
|
);
|
|
24529
24868
|
return c.json({ error: "house-only" }, 403);
|
|
24530
24869
|
}
|
|
24531
|
-
console.log(`${
|
|
24870
|
+
console.log(`${TAG46} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
|
|
24532
24871
|
const onDisk = countAccountDirsOnDisk();
|
|
24533
24872
|
console.log(
|
|
24534
|
-
`${
|
|
24873
|
+
`${TAG46} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
|
|
24535
24874
|
);
|
|
24536
24875
|
const start = Date.now();
|
|
24537
24876
|
let res;
|
|
@@ -24547,17 +24886,17 @@ app55.get("/", requireAdminSession, async (c) => {
|
|
|
24547
24886
|
});
|
|
24548
24887
|
} catch (err) {
|
|
24549
24888
|
console.error(
|
|
24550
|
-
`${
|
|
24889
|
+
`${TAG46} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
|
|
24551
24890
|
);
|
|
24552
24891
|
return c.json({ error: "manager-unreachable" }, 502);
|
|
24553
24892
|
}
|
|
24554
24893
|
if (res.status !== 200) {
|
|
24555
|
-
console.error(`${
|
|
24894
|
+
console.error(`${TAG46} op=manager-fail req=${req} reason=status status=${res.status}`);
|
|
24556
24895
|
return c.json({ error: `manager-status-${res.status}` }, 502);
|
|
24557
24896
|
}
|
|
24558
24897
|
const body = await res.json().catch(() => null);
|
|
24559
24898
|
if (!body || !Array.isArray(body.rows)) {
|
|
24560
|
-
console.error(`${
|
|
24899
|
+
console.error(`${TAG46} op=manager-fail req=${req} reason=bad-json`);
|
|
24561
24900
|
return c.json({ error: "manager-bad-json" }, 502);
|
|
24562
24901
|
}
|
|
24563
24902
|
const rows = body.rows;
|
|
@@ -24568,10 +24907,10 @@ app55.get("/", requireAdminSession, async (c) => {
|
|
|
24568
24907
|
const ageNull = rows.filter((r) => r.ageMs === null).length;
|
|
24569
24908
|
const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
|
|
24570
24909
|
console.log(
|
|
24571
|
-
`${
|
|
24910
|
+
`${TAG46} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
|
|
24572
24911
|
);
|
|
24573
24912
|
console.log(
|
|
24574
|
-
`${
|
|
24913
|
+
`${TAG46} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
|
|
24575
24914
|
);
|
|
24576
24915
|
const names = {};
|
|
24577
24916
|
await Promise.all(
|
|
@@ -24590,7 +24929,7 @@ app55.get("/", requireAdminSession, async (c) => {
|
|
|
24590
24929
|
return acc;
|
|
24591
24930
|
}, {});
|
|
24592
24931
|
console.log(
|
|
24593
|
-
`${
|
|
24932
|
+
`${TAG46} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
|
|
24594
24933
|
);
|
|
24595
24934
|
return c.json({
|
|
24596
24935
|
rows,
|
|
@@ -24620,63 +24959,65 @@ app55.get("/", requireAdminSession, async (c) => {
|
|
|
24620
24959
|
}
|
|
24621
24960
|
});
|
|
24622
24961
|
});
|
|
24623
|
-
var activity_default =
|
|
24962
|
+
var activity_default = app57;
|
|
24624
24963
|
|
|
24625
24964
|
// server/routes/admin/index.ts
|
|
24626
|
-
var
|
|
24627
|
-
|
|
24628
|
-
|
|
24629
|
-
|
|
24630
|
-
|
|
24631
|
-
|
|
24632
|
-
|
|
24633
|
-
|
|
24634
|
-
|
|
24635
|
-
|
|
24636
|
-
|
|
24637
|
-
|
|
24638
|
-
|
|
24639
|
-
|
|
24640
|
-
|
|
24641
|
-
|
|
24642
|
-
|
|
24643
|
-
|
|
24644
|
-
|
|
24645
|
-
|
|
24646
|
-
|
|
24647
|
-
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
|
|
24653
|
-
|
|
24654
|
-
|
|
24655
|
-
|
|
24656
|
-
|
|
24657
|
-
|
|
24658
|
-
|
|
24659
|
-
|
|
24660
|
-
|
|
24661
|
-
|
|
24662
|
-
|
|
24663
|
-
|
|
24664
|
-
|
|
24665
|
-
|
|
24666
|
-
|
|
24667
|
-
|
|
24668
|
-
|
|
24669
|
-
|
|
24670
|
-
|
|
24671
|
-
|
|
24672
|
-
|
|
24965
|
+
var app58 = new Hono();
|
|
24966
|
+
app58.route("/session", session_default);
|
|
24967
|
+
app58.route("/accounts", accounts_default);
|
|
24968
|
+
app58.route("/logs", logs_default);
|
|
24969
|
+
app58.route("/claude-info", claude_info_default);
|
|
24970
|
+
app58.route("/attachment", attachment_default);
|
|
24971
|
+
app58.route("/session-upload", session_upload_default);
|
|
24972
|
+
app58.route("/agents", agents_default);
|
|
24973
|
+
app58.route("/sessions", sessions_default);
|
|
24974
|
+
app58.route("/claude-sessions", claude_sessions_default);
|
|
24975
|
+
app58.route("/log-ingest", log_ingest_default);
|
|
24976
|
+
app58.route("/events", events_default);
|
|
24977
|
+
app58.route("/files", files_default);
|
|
24978
|
+
app58.route("/graph-search", graph_search_default);
|
|
24979
|
+
app58.route("/graph-subgraph", graph_subgraph_default);
|
|
24980
|
+
app58.route("/graph-delete", graph_delete_default);
|
|
24981
|
+
app58.route("/graph-restore", graph_restore_default);
|
|
24982
|
+
app58.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
24983
|
+
app58.route("/graph-default-view", graph_default_view_default);
|
|
24984
|
+
app58.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
24985
|
+
app58.route("/sidebar-sessions", sidebar_sessions_default);
|
|
24986
|
+
app58.route("/session-delete", session_delete_default);
|
|
24987
|
+
app58.route("/session-stop", session_stop_default);
|
|
24988
|
+
app58.route("/session-archive", session_archive_default);
|
|
24989
|
+
app58.route("/session-rename", session_rename_default);
|
|
24990
|
+
app58.route("/session-usage", session_usage_default);
|
|
24991
|
+
app58.route("/browser", browser_default);
|
|
24992
|
+
app58.route("/session-rc-spawn", session_rc_spawn_default);
|
|
24993
|
+
app58.route("/session-reseat", session_reseat_default);
|
|
24994
|
+
app58.route("/system-stats", system_stats_default);
|
|
24995
|
+
app58.route("/health-brand", health_default2);
|
|
24996
|
+
app58.route("/linkedin-ingest", linkedin_ingest_default);
|
|
24997
|
+
app58.route("/post-turn-context", post_turn_context_default);
|
|
24998
|
+
app58.route("/public-session-context", public_session_context_default);
|
|
24999
|
+
app58.route("/public-session-exit", public_session_exit_default);
|
|
25000
|
+
app58.route("/access-session-evict", access_session_evict_default);
|
|
25001
|
+
app58.route("/enrol-person", enrol_person_default);
|
|
25002
|
+
app58.route("/calendar", calendar_default);
|
|
25003
|
+
app58.route("/routines", routines_default);
|
|
25004
|
+
app58.route("/skills", skills_default);
|
|
25005
|
+
app58.route("/tasks-list", tasks_list_default);
|
|
25006
|
+
app58.route("/task-timer-start", task_timer_start_default);
|
|
25007
|
+
app58.route("/task-timer-stop", task_timer_stop_default);
|
|
25008
|
+
app58.route("/task-complete", task_complete_default);
|
|
25009
|
+
app58.route("/task-time-adjust", task_time_adjust_default);
|
|
25010
|
+
app58.route("/task-assign", task_assign_default);
|
|
25011
|
+
app58.route("/admin-users-list", admin_users_list_default);
|
|
25012
|
+
app58.route("/activity", activity_default);
|
|
25013
|
+
var admin_default = app58;
|
|
24673
25014
|
|
|
24674
25015
|
// server/routes/access/verify-token.ts
|
|
24675
|
-
var
|
|
25016
|
+
var TAG47 = "[access-verify]";
|
|
24676
25017
|
var MINT_TAG = "[access-session-mint]";
|
|
24677
25018
|
var COOKIE_NAME = "__access_session";
|
|
24678
|
-
var
|
|
24679
|
-
|
|
25019
|
+
var app59 = new Hono();
|
|
25020
|
+
app59.post("/", async (c) => {
|
|
24680
25021
|
const ip = c.var.clientIp || "unknown";
|
|
24681
25022
|
let body;
|
|
24682
25023
|
try {
|
|
@@ -24691,39 +25032,39 @@ app57.post("/", async (c) => {
|
|
|
24691
25032
|
}
|
|
24692
25033
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
24693
25034
|
if (rateMsg) {
|
|
24694
|
-
console.error(`${
|
|
25035
|
+
console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
24695
25036
|
return c.json({ error: rateMsg }, 429);
|
|
24696
25037
|
}
|
|
24697
25038
|
const grant = await findGrantByMagicToken(token);
|
|
24698
25039
|
if (!grant) {
|
|
24699
25040
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
24700
|
-
console.error(`${
|
|
25041
|
+
console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
24701
25042
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
24702
25043
|
}
|
|
24703
25044
|
if (grant.agentSlug !== agentSlug) {
|
|
24704
25045
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
24705
25046
|
console.error(
|
|
24706
|
-
`${
|
|
25047
|
+
`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
24707
25048
|
);
|
|
24708
25049
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
24709
25050
|
}
|
|
24710
25051
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
24711
25052
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
24712
25053
|
console.error(
|
|
24713
|
-
`${
|
|
25054
|
+
`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
24714
25055
|
);
|
|
24715
25056
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
24716
25057
|
}
|
|
24717
25058
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
24718
25059
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
24719
25060
|
console.error(
|
|
24720
|
-
`${
|
|
25061
|
+
`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
24721
25062
|
);
|
|
24722
25063
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
24723
25064
|
}
|
|
24724
25065
|
if (!grant.sliceToken) {
|
|
24725
25066
|
console.error(
|
|
24726
|
-
`${
|
|
25067
|
+
`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
24727
25068
|
);
|
|
24728
25069
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
24729
25070
|
}
|
|
@@ -24739,12 +25080,12 @@ app57.post("/", async (c) => {
|
|
|
24739
25080
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
24740
25081
|
} catch (err) {
|
|
24741
25082
|
console.error(
|
|
24742
|
-
`${
|
|
25083
|
+
`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
24743
25084
|
);
|
|
24744
25085
|
return c.json({ error: "verification-failed" }, 500);
|
|
24745
25086
|
}
|
|
24746
25087
|
clearAccessRateLimit(ip, agentSlug);
|
|
24747
|
-
console.log(`${
|
|
25088
|
+
console.log(`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
24748
25089
|
console.log(
|
|
24749
25090
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
24750
25091
|
);
|
|
@@ -24758,13 +25099,13 @@ app57.post("/", async (c) => {
|
|
|
24758
25099
|
displayName: grant.displayName
|
|
24759
25100
|
});
|
|
24760
25101
|
});
|
|
24761
|
-
var verify_token_default =
|
|
25102
|
+
var verify_token_default = app59;
|
|
24762
25103
|
|
|
24763
25104
|
// app/lib/access-email.ts
|
|
24764
25105
|
import { spawn as spawn2 } from "child_process";
|
|
24765
|
-
import { resolve as
|
|
24766
|
-
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ??
|
|
24767
|
-
var SEND_SCRIPT =
|
|
25106
|
+
import { resolve as resolve34 } from "path";
|
|
25107
|
+
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve34(process.cwd(), "..");
|
|
25108
|
+
var SEND_SCRIPT = resolve34(
|
|
24768
25109
|
PLATFORM_ROOT7,
|
|
24769
25110
|
"plugins",
|
|
24770
25111
|
"email",
|
|
@@ -24820,10 +25161,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
24820
25161
|
}
|
|
24821
25162
|
|
|
24822
25163
|
// server/routes/access/request-magic-link.ts
|
|
24823
|
-
var
|
|
24824
|
-
var
|
|
25164
|
+
var TAG48 = "[access-request-link]";
|
|
25165
|
+
var app60 = new Hono();
|
|
24825
25166
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
24826
|
-
|
|
25167
|
+
app60.post("/", async (c) => {
|
|
24827
25168
|
let body;
|
|
24828
25169
|
try {
|
|
24829
25170
|
body = await c.req.json();
|
|
@@ -24837,18 +25178,18 @@ app58.post("/", async (c) => {
|
|
|
24837
25178
|
}
|
|
24838
25179
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
24839
25180
|
if (rateMsg) {
|
|
24840
|
-
console.error(`${
|
|
25181
|
+
console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
24841
25182
|
return c.json({ error: rateMsg }, 429);
|
|
24842
25183
|
}
|
|
24843
25184
|
recordRequestLinkAttempt(contactValue);
|
|
24844
25185
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
24845
25186
|
if (!accountId) {
|
|
24846
|
-
console.error(`${
|
|
25187
|
+
console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
24847
25188
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24848
25189
|
}
|
|
24849
25190
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
24850
25191
|
if (!grant) {
|
|
24851
|
-
console.log(`${
|
|
25192
|
+
console.log(`${TAG48} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
24852
25193
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24853
25194
|
}
|
|
24854
25195
|
let token;
|
|
@@ -24856,7 +25197,7 @@ app58.post("/", async (c) => {
|
|
|
24856
25197
|
token = await generateNewMagicToken(grant.grantId);
|
|
24857
25198
|
} catch (err) {
|
|
24858
25199
|
console.error(
|
|
24859
|
-
`${
|
|
25200
|
+
`${TAG48} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
24860
25201
|
);
|
|
24861
25202
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24862
25203
|
}
|
|
@@ -24888,26 +25229,26 @@ app58.post("/", async (c) => {
|
|
|
24888
25229
|
});
|
|
24889
25230
|
if (!sendResult.ok) {
|
|
24890
25231
|
console.error(
|
|
24891
|
-
`${
|
|
25232
|
+
`${TAG48} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
24892
25233
|
);
|
|
24893
25234
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24894
25235
|
}
|
|
24895
25236
|
console.log(
|
|
24896
|
-
`${
|
|
25237
|
+
`${TAG48} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
24897
25238
|
);
|
|
24898
25239
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
24899
25240
|
});
|
|
24900
|
-
var request_magic_link_default =
|
|
25241
|
+
var request_magic_link_default = app60;
|
|
24901
25242
|
|
|
24902
25243
|
// server/routes/access/index.ts
|
|
24903
|
-
var
|
|
24904
|
-
|
|
24905
|
-
|
|
24906
|
-
var access_default =
|
|
25244
|
+
var app61 = new Hono();
|
|
25245
|
+
app61.route("/verify-token", verify_token_default);
|
|
25246
|
+
app61.route("/request-magic-link", request_magic_link_default);
|
|
25247
|
+
var access_default = app61;
|
|
24907
25248
|
|
|
24908
25249
|
// server/routes/sites.ts
|
|
24909
|
-
import { existsSync as
|
|
24910
|
-
import { resolve as
|
|
25250
|
+
import { existsSync as existsSync40, readFileSync as readFileSync41, realpathSync as realpathSync8, statSync as statSync17 } from "fs";
|
|
25251
|
+
import { resolve as resolve35 } from "path";
|
|
24911
25252
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
24912
25253
|
var MIME = {
|
|
24913
25254
|
".html": "text/html; charset=utf-8",
|
|
@@ -24938,8 +25279,8 @@ function getExt(p) {
|
|
|
24938
25279
|
if (idx < p.lastIndexOf("/")) return "";
|
|
24939
25280
|
return p.slice(idx).toLowerCase();
|
|
24940
25281
|
}
|
|
24941
|
-
var
|
|
24942
|
-
|
|
25282
|
+
var app62 = new Hono();
|
|
25283
|
+
app62.get("/:rel{.*}", (c) => {
|
|
24943
25284
|
const reqPath = c.req.path;
|
|
24944
25285
|
const rawRel = c.req.param("rel") ?? "";
|
|
24945
25286
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -24964,15 +25305,15 @@ app60.get("/:rel{.*}", (c) => {
|
|
|
24964
25305
|
}
|
|
24965
25306
|
segments.push(seg);
|
|
24966
25307
|
}
|
|
24967
|
-
const rootDir =
|
|
24968
|
-
let filePath = segments.length === 0 ? rootDir :
|
|
25308
|
+
const rootDir = resolve35(account.accountDir, "sites");
|
|
25309
|
+
let filePath = segments.length === 0 ? rootDir : resolve35(rootDir, ...segments);
|
|
24969
25310
|
if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
|
|
24970
25311
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24971
25312
|
return c.text("Forbidden", 403);
|
|
24972
25313
|
}
|
|
24973
25314
|
let stat11;
|
|
24974
25315
|
try {
|
|
24975
|
-
stat11 =
|
|
25316
|
+
stat11 = existsSync40(filePath) ? statSync17(filePath) : null;
|
|
24976
25317
|
} catch {
|
|
24977
25318
|
stat11 = null;
|
|
24978
25319
|
}
|
|
@@ -24985,13 +25326,13 @@ app60.get("/:rel{.*}", (c) => {
|
|
|
24985
25326
|
return c.redirect(target, 301);
|
|
24986
25327
|
}
|
|
24987
25328
|
if (stat11?.isDirectory()) {
|
|
24988
|
-
filePath =
|
|
25329
|
+
filePath = resolve35(filePath, "index.html");
|
|
24989
25330
|
}
|
|
24990
25331
|
if (!filePath.startsWith(rootDir + "/")) {
|
|
24991
25332
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
24992
25333
|
return c.text("Forbidden", 403);
|
|
24993
25334
|
}
|
|
24994
|
-
if (!
|
|
25335
|
+
if (!existsSync40(filePath)) {
|
|
24995
25336
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
24996
25337
|
return c.text("Not found", 404);
|
|
24997
25338
|
}
|
|
@@ -25010,7 +25351,7 @@ app60.get("/:rel{.*}", (c) => {
|
|
|
25010
25351
|
}
|
|
25011
25352
|
let body;
|
|
25012
25353
|
try {
|
|
25013
|
-
body =
|
|
25354
|
+
body = readFileSync41(realPath);
|
|
25014
25355
|
} catch (err) {
|
|
25015
25356
|
const code = err?.code;
|
|
25016
25357
|
if (code === "EISDIR") {
|
|
@@ -25042,11 +25383,11 @@ app60.get("/:rel{.*}", (c) => {
|
|
|
25042
25383
|
"X-Content-Type-Options": "nosniff"
|
|
25043
25384
|
});
|
|
25044
25385
|
});
|
|
25045
|
-
var sites_default =
|
|
25386
|
+
var sites_default = app62;
|
|
25046
25387
|
|
|
25047
25388
|
// app/lib/visitor-token.ts
|
|
25048
25389
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
25049
|
-
import { mkdirSync as mkdirSync8, readFileSync as
|
|
25390
|
+
import { mkdirSync as mkdirSync8, readFileSync as readFileSync42, writeFileSync as writeFileSync14 } from "fs";
|
|
25050
25391
|
import { dirname as dirname14 } from "path";
|
|
25051
25392
|
var TOKEN_PREFIX = "v1.";
|
|
25052
25393
|
var SECRET_BYTES = 32;
|
|
@@ -25055,7 +25396,7 @@ var cachedSecret = null;
|
|
|
25055
25396
|
function getSecret() {
|
|
25056
25397
|
if (cachedSecret) return cachedSecret;
|
|
25057
25398
|
try {
|
|
25058
|
-
const hex2 =
|
|
25399
|
+
const hex2 = readFileSync42(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
25059
25400
|
if (hex2.length === SECRET_BYTES * 2) {
|
|
25060
25401
|
cachedSecret = Buffer.from(hex2, "hex");
|
|
25061
25402
|
return cachedSecret;
|
|
@@ -25069,7 +25410,7 @@ function getSecret() {
|
|
|
25069
25410
|
console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
|
|
25070
25411
|
} catch {
|
|
25071
25412
|
}
|
|
25072
|
-
const hex =
|
|
25413
|
+
const hex = readFileSync42(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
|
|
25073
25414
|
cachedSecret = Buffer.from(hex, "hex");
|
|
25074
25415
|
return cachedSecret;
|
|
25075
25416
|
}
|
|
@@ -25122,7 +25463,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
25122
25463
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
25123
25464
|
|
|
25124
25465
|
// app/lib/brand-config.ts
|
|
25125
|
-
import { existsSync as
|
|
25466
|
+
import { existsSync as existsSync41, readFileSync as readFileSync43 } from "fs";
|
|
25126
25467
|
import { join as join43 } from "path";
|
|
25127
25468
|
var cached2 = null;
|
|
25128
25469
|
var cachedAttempted = false;
|
|
@@ -25132,9 +25473,9 @@ function readBrandConfig() {
|
|
|
25132
25473
|
const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
|
|
25133
25474
|
if (!platformRoot5) return null;
|
|
25134
25475
|
const brandPath = join43(platformRoot5, "config", "brand.json");
|
|
25135
|
-
if (!
|
|
25476
|
+
if (!existsSync41(brandPath)) return null;
|
|
25136
25477
|
try {
|
|
25137
|
-
cached2 = JSON.parse(
|
|
25478
|
+
cached2 = JSON.parse(readFileSync43(brandPath, "utf-8"));
|
|
25138
25479
|
return cached2;
|
|
25139
25480
|
} catch {
|
|
25140
25481
|
return null;
|
|
@@ -25142,7 +25483,7 @@ function readBrandConfig() {
|
|
|
25142
25483
|
}
|
|
25143
25484
|
|
|
25144
25485
|
// server/routes/visitor-consent.ts
|
|
25145
|
-
var
|
|
25486
|
+
var app63 = new Hono();
|
|
25146
25487
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
25147
25488
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
25148
25489
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -25187,17 +25528,17 @@ function siteSlugFromReferer(referer) {
|
|
|
25187
25528
|
return "";
|
|
25188
25529
|
}
|
|
25189
25530
|
}
|
|
25190
|
-
|
|
25531
|
+
app63.options("/consent", (c) => {
|
|
25191
25532
|
const origin = getOrigin(c);
|
|
25192
25533
|
setCorsHeaders(c, origin);
|
|
25193
25534
|
return c.body(null, 204);
|
|
25194
25535
|
});
|
|
25195
|
-
|
|
25536
|
+
app63.options("/brand-config", (c) => {
|
|
25196
25537
|
const origin = getOrigin(c);
|
|
25197
25538
|
setCorsHeaders(c, origin);
|
|
25198
25539
|
return c.body(null, 204);
|
|
25199
25540
|
});
|
|
25200
|
-
|
|
25541
|
+
app63.post("/consent", async (c) => {
|
|
25201
25542
|
const origin = getOrigin(c);
|
|
25202
25543
|
setCorsHeaders(c, origin);
|
|
25203
25544
|
let raw;
|
|
@@ -25237,7 +25578,7 @@ app61.post("/consent", async (c) => {
|
|
|
25237
25578
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
25238
25579
|
return c.body(null, 204);
|
|
25239
25580
|
});
|
|
25240
|
-
|
|
25581
|
+
app63.get("/brand-config", (c) => {
|
|
25241
25582
|
const origin = getOrigin(c);
|
|
25242
25583
|
setCorsHeaders(c, origin);
|
|
25243
25584
|
const brand = readBrandConfig();
|
|
@@ -25247,7 +25588,7 @@ app61.get("/brand-config", (c) => {
|
|
|
25247
25588
|
c.header("Cache-Control", "public, max-age=300");
|
|
25248
25589
|
return c.json({ consent: { copy, palette } });
|
|
25249
25590
|
});
|
|
25250
|
-
var visitor_consent_default =
|
|
25591
|
+
var visitor_consent_default = app63;
|
|
25251
25592
|
|
|
25252
25593
|
// server/routes/listings.ts
|
|
25253
25594
|
function getCookie(headerValue, name) {
|
|
@@ -25274,8 +25615,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
25274
25615
|
}
|
|
25275
25616
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
25276
25617
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
25277
|
-
var
|
|
25278
|
-
|
|
25618
|
+
var app64 = new Hono();
|
|
25619
|
+
app64.get("/:slug/click", async (c) => {
|
|
25279
25620
|
const slug = c.req.param("slug") ?? "";
|
|
25280
25621
|
const rawSession = c.req.query("session") ?? "";
|
|
25281
25622
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -25339,10 +25680,10 @@ app62.get("/:slug/click", async (c) => {
|
|
|
25339
25680
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
25340
25681
|
return c.redirect(redirectUrl, 302);
|
|
25341
25682
|
});
|
|
25342
|
-
var listings_default =
|
|
25683
|
+
var listings_default = app64;
|
|
25343
25684
|
|
|
25344
25685
|
// server/routes/visitor-event.ts
|
|
25345
|
-
var
|
|
25686
|
+
var app65 = new Hono();
|
|
25346
25687
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
25347
25688
|
var buckets = /* @__PURE__ */ new Map();
|
|
25348
25689
|
var RATE_LIMIT = 60;
|
|
@@ -25418,12 +25759,12 @@ function originAllowed(origin, allowlist) {
|
|
|
25418
25759
|
return false;
|
|
25419
25760
|
}
|
|
25420
25761
|
}
|
|
25421
|
-
|
|
25762
|
+
app65.options("/event", (c) => {
|
|
25422
25763
|
const origin = getOrigin2(c);
|
|
25423
25764
|
setCorsHeaders2(c, origin);
|
|
25424
25765
|
return c.body(null, 204);
|
|
25425
25766
|
});
|
|
25426
|
-
|
|
25767
|
+
app65.post("/event", async (c) => {
|
|
25427
25768
|
const origin = getOrigin2(c);
|
|
25428
25769
|
setCorsHeaders2(c, origin);
|
|
25429
25770
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -25628,17 +25969,17 @@ async function writeEvent(opts) {
|
|
|
25628
25969
|
);
|
|
25629
25970
|
}
|
|
25630
25971
|
}
|
|
25631
|
-
var visitor_event_default =
|
|
25972
|
+
var visitor_event_default = app65;
|
|
25632
25973
|
|
|
25633
25974
|
// server/routes/session.ts
|
|
25634
|
-
import { resolve as
|
|
25635
|
-
import { existsSync as
|
|
25975
|
+
import { resolve as resolve36 } from "path";
|
|
25976
|
+
import { existsSync as existsSync42, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
|
|
25636
25977
|
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
25637
25978
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
25638
25979
|
try {
|
|
25639
|
-
const cacheDir =
|
|
25980
|
+
const cacheDir = resolve36(MAXY_DIR, "branding-cache", accountId);
|
|
25640
25981
|
mkdirSync9(cacheDir, { recursive: true });
|
|
25641
|
-
writeFileSync15(
|
|
25982
|
+
writeFileSync15(resolve36(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
|
|
25642
25983
|
} catch (err) {
|
|
25643
25984
|
console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25644
25985
|
}
|
|
@@ -25674,8 +26015,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
25674
26015
|
headers
|
|
25675
26016
|
});
|
|
25676
26017
|
}
|
|
25677
|
-
var
|
|
25678
|
-
|
|
26018
|
+
var app66 = new Hono();
|
|
26019
|
+
app66.post("/", async (c) => {
|
|
25679
26020
|
let body;
|
|
25680
26021
|
try {
|
|
25681
26022
|
body = await c.req.json();
|
|
@@ -25715,8 +26056,8 @@ app64.post("/", async (c) => {
|
|
|
25715
26056
|
}
|
|
25716
26057
|
let agentConfig = null;
|
|
25717
26058
|
if (account) {
|
|
25718
|
-
const agentDir =
|
|
25719
|
-
if (!
|
|
26059
|
+
const agentDir = resolve36(account.accountDir, "agents", agentSlug);
|
|
26060
|
+
if (!existsSync42(agentDir) || !existsSync42(resolve36(agentDir, "config.json"))) {
|
|
25720
26061
|
return c.json({ error: "Agent not found" }, 404);
|
|
25721
26062
|
}
|
|
25722
26063
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -25822,7 +26163,7 @@ app64.post("/", async (c) => {
|
|
|
25822
26163
|
newVisitorId
|
|
25823
26164
|
);
|
|
25824
26165
|
});
|
|
25825
|
-
var session_default2 =
|
|
26166
|
+
var session_default2 = app66;
|
|
25826
26167
|
|
|
25827
26168
|
// server/lib/calendar-slots.ts
|
|
25828
26169
|
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
@@ -25905,17 +26246,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
|
25905
26246
|
}
|
|
25906
26247
|
|
|
25907
26248
|
// server/routes/calendar-public.ts
|
|
25908
|
-
var
|
|
26249
|
+
var app67 = new Hono();
|
|
25909
26250
|
function setCors(c) {
|
|
25910
26251
|
c.header("Access-Control-Allow-Origin", "*");
|
|
25911
26252
|
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
25912
26253
|
c.header("Access-Control-Allow-Headers", "content-type");
|
|
25913
26254
|
}
|
|
25914
|
-
|
|
26255
|
+
app67.options("/free-busy", (c) => {
|
|
25915
26256
|
setCors(c);
|
|
25916
26257
|
return c.body(null, 204);
|
|
25917
26258
|
});
|
|
25918
|
-
|
|
26259
|
+
app67.get("/free-busy", async (c) => {
|
|
25919
26260
|
setCors(c);
|
|
25920
26261
|
const from = c.req.query("from");
|
|
25921
26262
|
const to = c.req.query("to");
|
|
@@ -25971,15 +26312,15 @@ app65.get("/free-busy", async (c) => {
|
|
|
25971
26312
|
await session.close();
|
|
25972
26313
|
}
|
|
25973
26314
|
});
|
|
25974
|
-
var calendar_public_default =
|
|
26315
|
+
var calendar_public_default = app67;
|
|
25975
26316
|
|
|
25976
26317
|
// server/routes/portal-fetch.ts
|
|
25977
26318
|
import { createReadStream as createReadStream3 } from "fs";
|
|
25978
26319
|
import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
|
|
25979
|
-
import { join as join44, resolve as
|
|
26320
|
+
import { join as join44, resolve as resolve37, sep as sep10 } from "path";
|
|
25980
26321
|
import { Readable as Readable3 } from "stream";
|
|
25981
|
-
var
|
|
25982
|
-
var
|
|
26322
|
+
var app68 = new Hono();
|
|
26323
|
+
var TAG49 = "[portal-fetch]";
|
|
25983
26324
|
async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
|
|
25984
26325
|
if (!secret || !signature) return false;
|
|
25985
26326
|
if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return false;
|
|
@@ -26029,19 +26370,19 @@ ${expiresAtMs}`)
|
|
|
26029
26370
|
return diff === 0;
|
|
26030
26371
|
}
|
|
26031
26372
|
async function readAccountSecret(accountId) {
|
|
26032
|
-
const path3 =
|
|
26373
|
+
const path3 = resolve37(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
|
|
26033
26374
|
let text;
|
|
26034
26375
|
try {
|
|
26035
26376
|
text = await readFile9(path3, "utf8");
|
|
26036
26377
|
} catch {
|
|
26037
|
-
console.error(`${
|
|
26378
|
+
console.error(`${TAG49} op=no-secret account="${accountId}" path="${path3}"`);
|
|
26038
26379
|
return "";
|
|
26039
26380
|
}
|
|
26040
26381
|
for (const line of text.split("\n")) {
|
|
26041
26382
|
const m = line.match(/^PORTAL_FETCH_SECRET=(.*)$/);
|
|
26042
26383
|
if (m) return m[1].trim();
|
|
26043
26384
|
}
|
|
26044
|
-
console.error(`${
|
|
26385
|
+
console.error(`${TAG49} op=no-secret account="${accountId}" reason=key-absent path="${path3}"`);
|
|
26045
26386
|
return "";
|
|
26046
26387
|
}
|
|
26047
26388
|
function isValidAccountId2(value) {
|
|
@@ -26065,7 +26406,7 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
|
|
|
26065
26406
|
const exposeFolders = await readExposeFolders2(accountDir);
|
|
26066
26407
|
const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
|
|
26067
26408
|
if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
|
|
26068
|
-
const lexical =
|
|
26409
|
+
const lexical = resolve37(accountDir, relPath);
|
|
26069
26410
|
let root;
|
|
26070
26411
|
let absolute;
|
|
26071
26412
|
try {
|
|
@@ -26101,33 +26442,33 @@ async function handle(c, headOnly) {
|
|
|
26101
26442
|
const sig = c.req.query("sig") ?? "";
|
|
26102
26443
|
const owner = c.req.query("owner") ?? "";
|
|
26103
26444
|
console.log(
|
|
26104
|
-
`${
|
|
26445
|
+
`${TAG49} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
|
|
26105
26446
|
);
|
|
26106
26447
|
if (!isValidAccountId2(accountId)) {
|
|
26107
|
-
console.error(`${
|
|
26448
|
+
console.error(`${TAG49} op=denied account=${q(accountId)} reason=account-id`);
|
|
26108
26449
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
26109
26450
|
}
|
|
26110
26451
|
const secret = await readAccountSecret(accountId);
|
|
26111
26452
|
const verified = owner ? await verifyOwnUploadSignature(secret, accountId, owner, relPath, exp, sig, Date.now()) : await verifySignature(secret, accountId, relPath, exp, sig, Date.now());
|
|
26112
26453
|
if (!verified) {
|
|
26113
|
-
console.error(`${
|
|
26454
|
+
console.error(`${TAG49} op=denied account=${q(accountId)} reason=secret`);
|
|
26114
26455
|
return c.json({ ok: false, error: "denied" }, 401);
|
|
26115
26456
|
}
|
|
26116
26457
|
const target = await resolveFetchTarget(
|
|
26117
|
-
|
|
26458
|
+
resolve37(DATA_ROOT, "accounts", accountId),
|
|
26118
26459
|
relPath,
|
|
26119
26460
|
owner || void 0
|
|
26120
26461
|
);
|
|
26121
26462
|
if (!target.ok) {
|
|
26122
26463
|
const op = target.reason === "enoent" ? "miss" : "denied";
|
|
26123
|
-
console.error(`${
|
|
26464
|
+
console.error(`${TAG49} op=${op} account=${accountId} reason=${target.reason}`);
|
|
26124
26465
|
return c.json({ ok: false, error: "not found" }, 404);
|
|
26125
26466
|
}
|
|
26126
26467
|
if (headOnly) {
|
|
26127
|
-
console.log(`${
|
|
26468
|
+
console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
|
|
26128
26469
|
return c.body(null, 200);
|
|
26129
26470
|
}
|
|
26130
|
-
console.log(`${
|
|
26471
|
+
console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes}`);
|
|
26131
26472
|
return new Response(Readable3.toWeb(createReadStream3(target.absolute)), {
|
|
26132
26473
|
status: 200,
|
|
26133
26474
|
headers: {
|
|
@@ -26141,12 +26482,12 @@ async function handle(c, headOnly) {
|
|
|
26141
26482
|
}
|
|
26142
26483
|
});
|
|
26143
26484
|
}
|
|
26144
|
-
|
|
26145
|
-
|
|
26146
|
-
var portal_fetch_default =
|
|
26485
|
+
app68.get("/fetch", (c) => handle(c, false));
|
|
26486
|
+
app68.on("HEAD", "/fetch", (c) => handle(c, true));
|
|
26487
|
+
var portal_fetch_default = app68;
|
|
26147
26488
|
|
|
26148
26489
|
// app/lib/timeentry-census.ts
|
|
26149
|
-
var
|
|
26490
|
+
var TAG50 = "[timeentry-census]";
|
|
26150
26491
|
function reconcileTimeEntries(rows, now, horizonMs) {
|
|
26151
26492
|
const openEntries = rows.openEntries.length;
|
|
26152
26493
|
let oldestOpenAgeMs = 0;
|
|
@@ -26186,12 +26527,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
|
26186
26527
|
sumAdjustments: toNum(r.get("sumAdjustments"))
|
|
26187
26528
|
}));
|
|
26188
26529
|
const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
|
|
26189
|
-
const line = `${
|
|
26530
|
+
const line = `${TAG50} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
|
|
26190
26531
|
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
26191
26532
|
else console.log(line);
|
|
26192
26533
|
return finding;
|
|
26193
26534
|
} catch (err) {
|
|
26194
|
-
console.error(`${
|
|
26535
|
+
console.error(`${TAG50} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
26195
26536
|
return null;
|
|
26196
26537
|
}
|
|
26197
26538
|
}
|
|
@@ -26205,13 +26546,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
26205
26546
|
try {
|
|
26206
26547
|
session = openSession();
|
|
26207
26548
|
} catch (err) {
|
|
26208
|
-
console.error(`${
|
|
26549
|
+
console.error(`${TAG50} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
26209
26550
|
return;
|
|
26210
26551
|
}
|
|
26211
26552
|
try {
|
|
26212
26553
|
await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
|
|
26213
26554
|
} catch (err) {
|
|
26214
|
-
console.error(`${
|
|
26555
|
+
console.error(`${TAG50} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
26215
26556
|
} finally {
|
|
26216
26557
|
try {
|
|
26217
26558
|
await session.close();
|
|
@@ -26228,7 +26569,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
26228
26569
|
}
|
|
26229
26570
|
|
|
26230
26571
|
// app/lib/ledger-census.ts
|
|
26231
|
-
import { readdirSync as
|
|
26572
|
+
import { readdirSync as readdirSync27, readFileSync as readFileSync44, statSync as statSync18 } from "fs";
|
|
26232
26573
|
import { join as join45 } from "path";
|
|
26233
26574
|
|
|
26234
26575
|
// ../lib/ledger-core/dist/reconcile.js
|
|
@@ -26272,12 +26613,12 @@ function formatCensusLine(f) {
|
|
|
26272
26613
|
}
|
|
26273
26614
|
|
|
26274
26615
|
// app/lib/ledger-census.ts
|
|
26275
|
-
var
|
|
26616
|
+
var TAG51 = "[ledger-census]";
|
|
26276
26617
|
var DAY_MS = 864e5;
|
|
26277
26618
|
function countWriteRejects24h(logDir, now) {
|
|
26278
26619
|
let entries;
|
|
26279
26620
|
try {
|
|
26280
|
-
entries =
|
|
26621
|
+
entries = readdirSync27(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
|
|
26281
26622
|
} catch {
|
|
26282
26623
|
return 0;
|
|
26283
26624
|
}
|
|
@@ -26286,7 +26627,7 @@ function countWriteRejects24h(logDir, now) {
|
|
|
26286
26627
|
const path3 = join45(logDir, name);
|
|
26287
26628
|
try {
|
|
26288
26629
|
if (now - statSync18(path3).mtimeMs > DAY_MS) continue;
|
|
26289
|
-
for (const line of
|
|
26630
|
+
for (const line of readFileSync44(path3, "utf8").split("\n")) {
|
|
26290
26631
|
if (line.includes("[graph-write] reject")) total += 1;
|
|
26291
26632
|
}
|
|
26292
26633
|
} catch {
|
|
@@ -26348,7 +26689,7 @@ async function runLedgerCensusOnce(session, now) {
|
|
|
26348
26689
|
else console.log(line);
|
|
26349
26690
|
return finding;
|
|
26350
26691
|
} catch (err) {
|
|
26351
|
-
console.error(`${
|
|
26692
|
+
console.error(`${TAG51} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
26352
26693
|
return null;
|
|
26353
26694
|
}
|
|
26354
26695
|
}
|
|
@@ -26361,7 +26702,7 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
26361
26702
|
session = openSession();
|
|
26362
26703
|
} catch (err) {
|
|
26363
26704
|
console.error(
|
|
26364
|
-
`${
|
|
26705
|
+
`${TAG51} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
26365
26706
|
);
|
|
26366
26707
|
return;
|
|
26367
26708
|
}
|
|
@@ -26369,7 +26710,7 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
26369
26710
|
await runLedgerCensusOnce(session, Date.now());
|
|
26370
26711
|
} catch (err) {
|
|
26371
26712
|
console.error(
|
|
26372
|
-
`${
|
|
26713
|
+
`${TAG51} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
|
|
26373
26714
|
);
|
|
26374
26715
|
} finally {
|
|
26375
26716
|
try {
|
|
@@ -26387,7 +26728,7 @@ function startLedgerCensus(openSession, opts = {}) {
|
|
|
26387
26728
|
}
|
|
26388
26729
|
|
|
26389
26730
|
// app/lib/conversation-audit.ts
|
|
26390
|
-
var
|
|
26731
|
+
var TAG52 = "[conversation-audit]";
|
|
26391
26732
|
async function runConversationAudit() {
|
|
26392
26733
|
const session = getSession();
|
|
26393
26734
|
try {
|
|
@@ -26424,12 +26765,12 @@ async function runConversationAudit() {
|
|
|
26424
26765
|
multiAnchored: Number(multiRec?.get("multiAnchored") ?? 0)
|
|
26425
26766
|
};
|
|
26426
26767
|
console.error(
|
|
26427
|
-
`${
|
|
26768
|
+
`${TAG52} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
|
|
26428
26769
|
);
|
|
26429
26770
|
return result;
|
|
26430
26771
|
} catch (err) {
|
|
26431
26772
|
const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
|
|
26432
|
-
console.error(`${
|
|
26773
|
+
console.error(`${TAG52} op=failed reason=${reason}`);
|
|
26433
26774
|
return null;
|
|
26434
26775
|
} finally {
|
|
26435
26776
|
await session.close();
|
|
@@ -26555,7 +26896,7 @@ function startGraphHealthTimer() {
|
|
|
26555
26896
|
|
|
26556
26897
|
// app/lib/file-watcher.ts
|
|
26557
26898
|
import * as fsp2 from "fs/promises";
|
|
26558
|
-
import { resolve as
|
|
26899
|
+
import { resolve as resolve38, sep as sep11 } from "path";
|
|
26559
26900
|
var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26560
26901
|
var DEFAULT_COALESCE_MS = 500;
|
|
26561
26902
|
var ROOTS = ["accounts"];
|
|
@@ -26574,7 +26915,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26574
26915
|
const dropFn = opts.drop ?? dropFileIndex;
|
|
26575
26916
|
for (const r of ROOTS) {
|
|
26576
26917
|
try {
|
|
26577
|
-
await fsp2.mkdir(
|
|
26918
|
+
await fsp2.mkdir(resolve38(dataRoot, r), { recursive: true });
|
|
26578
26919
|
} catch (err) {
|
|
26579
26920
|
console.error(
|
|
26580
26921
|
`[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
|
|
@@ -26595,7 +26936,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26595
26936
|
timers.set(relativePath, t);
|
|
26596
26937
|
}
|
|
26597
26938
|
async function runHook(relativePath, accountId) {
|
|
26598
|
-
const absolute =
|
|
26939
|
+
const absolute = resolve38(dataRoot, relativePath);
|
|
26599
26940
|
let exists = false;
|
|
26600
26941
|
try {
|
|
26601
26942
|
const st = await fsp2.stat(absolute);
|
|
@@ -26619,7 +26960,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26619
26960
|
}
|
|
26620
26961
|
}
|
|
26621
26962
|
async function watchRoot(rootName) {
|
|
26622
|
-
const absRoot =
|
|
26963
|
+
const absRoot = resolve38(dataRoot, rootName);
|
|
26623
26964
|
try {
|
|
26624
26965
|
const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
|
|
26625
26966
|
for await (const event of iter) {
|
|
@@ -26658,7 +26999,7 @@ async function startFileWatcher(opts = {}) {
|
|
|
26658
26999
|
|
|
26659
27000
|
// app/lib/migrate-uploads.ts
|
|
26660
27001
|
import { mkdir as mkdir6, readdir as readdir6, rename as rename3, rm as rm3 } from "fs/promises";
|
|
26661
|
-
import { dirname as dirname15, relative as relative7, resolve as
|
|
27002
|
+
import { dirname as dirname15, relative as relative7, resolve as resolve39 } from "path";
|
|
26662
27003
|
var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
26663
27004
|
async function walkFiles(dir) {
|
|
26664
27005
|
const out = [];
|
|
@@ -26669,7 +27010,7 @@ async function walkFiles(dir) {
|
|
|
26669
27010
|
return out;
|
|
26670
27011
|
}
|
|
26671
27012
|
for (const e of entries) {
|
|
26672
|
-
const abs =
|
|
27013
|
+
const abs = resolve39(dir, e.name);
|
|
26673
27014
|
if (e.isDirectory()) {
|
|
26674
27015
|
out.push(...await walkFiles(abs));
|
|
26675
27016
|
} else if (e.isFile()) {
|
|
@@ -26689,7 +27030,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26689
27030
|
let moved = 0;
|
|
26690
27031
|
for (const oldAbs of files) {
|
|
26691
27032
|
const suffix = relative7(srcDir, oldAbs);
|
|
26692
|
-
const newAbs =
|
|
27033
|
+
const newAbs = resolve39(destDir, suffix);
|
|
26693
27034
|
await mkdir6(dirname15(newAbs), { recursive: true });
|
|
26694
27035
|
await rename3(oldAbs, newAbs);
|
|
26695
27036
|
moved++;
|
|
@@ -26716,7 +27057,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
|
|
|
26716
27057
|
}
|
|
26717
27058
|
async function migrateUploads(opts = {}) {
|
|
26718
27059
|
const dataRoot = opts.dataRoot ?? DATA_ROOT;
|
|
26719
|
-
const oldRoot =
|
|
27060
|
+
const oldRoot = resolve39(dataRoot, "uploads");
|
|
26720
27061
|
let topEntries;
|
|
26721
27062
|
try {
|
|
26722
27063
|
topEntries = await readdir6(oldRoot, { withFileTypes: true });
|
|
@@ -26737,8 +27078,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26737
27078
|
const name = entry.name;
|
|
26738
27079
|
if (ACCOUNT_UUID_RE5.test(name)) {
|
|
26739
27080
|
moved += await relocateTree(
|
|
26740
|
-
|
|
26741
|
-
|
|
27081
|
+
resolve39(oldRoot, name),
|
|
27082
|
+
resolve39(dataRoot, "accounts", name, "uploads"),
|
|
26742
27083
|
dataRoot,
|
|
26743
27084
|
name,
|
|
26744
27085
|
session
|
|
@@ -26750,8 +27091,8 @@ async function migrateUploads(opts = {}) {
|
|
|
26750
27091
|
continue;
|
|
26751
27092
|
}
|
|
26752
27093
|
moved += await relocateTree(
|
|
26753
|
-
|
|
26754
|
-
|
|
27094
|
+
resolve39(oldRoot, "public"),
|
|
27095
|
+
resolve39(dataRoot, "accounts", installAccountId, "uploads", "public"),
|
|
26755
27096
|
dataRoot,
|
|
26756
27097
|
null,
|
|
26757
27098
|
// public uploads carry no graph nodes
|
|
@@ -26781,7 +27122,7 @@ async function migrateUploads(opts = {}) {
|
|
|
26781
27122
|
|
|
26782
27123
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
26783
27124
|
import { readdir as readdir7, readFile as readFile10, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
|
|
26784
|
-
import { existsSync as
|
|
27125
|
+
import { existsSync as existsSync43 } from "fs";
|
|
26785
27126
|
import { join as join46 } from "path";
|
|
26786
27127
|
var ADMIN_ROLE2 = "admin";
|
|
26787
27128
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
@@ -26811,7 +27152,7 @@ async function writeRaw(path3, obj) {
|
|
|
26811
27152
|
await rename4(tmp, path3);
|
|
26812
27153
|
} catch (err) {
|
|
26813
27154
|
try {
|
|
26814
|
-
if (
|
|
27155
|
+
if (existsSync43(tmp)) await unlink4(tmp);
|
|
26815
27156
|
} catch {
|
|
26816
27157
|
}
|
|
26817
27158
|
throw err;
|
|
@@ -27200,8 +27541,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
27200
27541
|
|
|
27201
27542
|
// app/lib/whatsapp/gateway/routes.ts
|
|
27202
27543
|
function createWaChannelRoutes(deps) {
|
|
27203
|
-
const
|
|
27204
|
-
|
|
27544
|
+
const app70 = new Hono();
|
|
27545
|
+
app70.get("/wa-channel/inbound", (c) => {
|
|
27205
27546
|
const senderId = c.req.query("senderId");
|
|
27206
27547
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
27207
27548
|
return streamSSE(c, async (stream2) => {
|
|
@@ -27219,7 +27560,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27219
27560
|
}
|
|
27220
27561
|
});
|
|
27221
27562
|
});
|
|
27222
|
-
|
|
27563
|
+
app70.post("/wa-channel/reply", async (c) => {
|
|
27223
27564
|
const body = await c.req.json().catch(() => null);
|
|
27224
27565
|
const senderId = body?.senderId;
|
|
27225
27566
|
const text = body?.text;
|
|
@@ -27240,7 +27581,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27240
27581
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
27241
27582
|
return c.json({ ok: true });
|
|
27242
27583
|
});
|
|
27243
|
-
|
|
27584
|
+
app70.post("/wa-channel/reply-document", async (c) => {
|
|
27244
27585
|
const body = await c.req.json().catch(() => null);
|
|
27245
27586
|
const senderId = body?.senderId;
|
|
27246
27587
|
const files = body?.files;
|
|
@@ -27279,7 +27620,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27279
27620
|
}
|
|
27280
27621
|
return c.json({ ok: true, results });
|
|
27281
27622
|
});
|
|
27282
|
-
|
|
27623
|
+
app70.post("/wa-channel/ready", async (c) => {
|
|
27283
27624
|
const body = await c.req.json().catch(() => null);
|
|
27284
27625
|
const senderId = body?.senderId;
|
|
27285
27626
|
if (typeof senderId !== "string") {
|
|
@@ -27288,7 +27629,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27288
27629
|
deps.onReady?.(senderId);
|
|
27289
27630
|
return c.json({ ok: true });
|
|
27290
27631
|
});
|
|
27291
|
-
|
|
27632
|
+
app70.post("/wa-channel/received", async (c) => {
|
|
27292
27633
|
const body = await c.req.json().catch(() => null);
|
|
27293
27634
|
const senderId = body?.senderId;
|
|
27294
27635
|
const waMessageId = body?.waMessageId;
|
|
@@ -27298,7 +27639,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27298
27639
|
deps.onReceived?.(senderId, waMessageId);
|
|
27299
27640
|
return c.json({ ok: true });
|
|
27300
27641
|
});
|
|
27301
|
-
|
|
27642
|
+
app70.post("/wa-channel/turn-end", async (c) => {
|
|
27302
27643
|
const body = await c.req.json().catch(() => null);
|
|
27303
27644
|
const senderId = body?.senderId;
|
|
27304
27645
|
const sessionId = body?.sessionId;
|
|
@@ -27331,7 +27672,7 @@ function createWaChannelRoutes(deps) {
|
|
|
27331
27672
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
|
|
27332
27673
|
return c.json({ ok: true, delivered: "none" });
|
|
27333
27674
|
});
|
|
27334
|
-
return
|
|
27675
|
+
return app70;
|
|
27335
27676
|
}
|
|
27336
27677
|
|
|
27337
27678
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -27746,8 +28087,8 @@ var InboundHub2 = class {
|
|
|
27746
28087
|
|
|
27747
28088
|
// app/lib/webchat/gateway/routes.ts
|
|
27748
28089
|
function createWebchatChannelRoutes(deps) {
|
|
27749
|
-
const
|
|
27750
|
-
|
|
28090
|
+
const app70 = new Hono();
|
|
28091
|
+
app70.get("/webchat-channel/inbound", (c) => {
|
|
27751
28092
|
const key = c.req.query("key");
|
|
27752
28093
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
27753
28094
|
return streamSSE(c, async (stream2) => {
|
|
@@ -27765,7 +28106,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27765
28106
|
}
|
|
27766
28107
|
});
|
|
27767
28108
|
});
|
|
27768
|
-
|
|
28109
|
+
app70.post("/webchat-channel/reply", async (c) => {
|
|
27769
28110
|
const body = await c.req.json().catch(() => null);
|
|
27770
28111
|
const key = body?.key;
|
|
27771
28112
|
const text = body?.text;
|
|
@@ -27775,7 +28116,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27775
28116
|
deps.onReply?.(key, text);
|
|
27776
28117
|
return c.json({ ok: true });
|
|
27777
28118
|
});
|
|
27778
|
-
|
|
28119
|
+
app70.post("/webchat-channel/connector-auth", async (c) => {
|
|
27779
28120
|
const body = await c.req.json().catch(() => null);
|
|
27780
28121
|
const key = body?.key;
|
|
27781
28122
|
const sessionId = body?.sessionId;
|
|
@@ -27788,7 +28129,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27788
28129
|
const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
|
|
27789
28130
|
return c.json(result);
|
|
27790
28131
|
});
|
|
27791
|
-
|
|
28132
|
+
app70.post("/webchat-channel/ready", async (c) => {
|
|
27792
28133
|
const body = await c.req.json().catch(() => null);
|
|
27793
28134
|
const key = body?.key;
|
|
27794
28135
|
if (typeof key !== "string") {
|
|
@@ -27797,7 +28138,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27797
28138
|
deps.onReady?.(key);
|
|
27798
28139
|
return c.json({ ok: true });
|
|
27799
28140
|
});
|
|
27800
|
-
|
|
28141
|
+
app70.post("/webchat-channel/permission-request", async (c) => {
|
|
27801
28142
|
const body = await c.req.json().catch(() => null);
|
|
27802
28143
|
const key = body?.key;
|
|
27803
28144
|
const requestId = body?.request_id;
|
|
@@ -27811,7 +28152,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27811
28152
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
27812
28153
|
return c.json(verdict);
|
|
27813
28154
|
});
|
|
27814
|
-
|
|
28155
|
+
app70.post("/webchat-channel/received", async (c) => {
|
|
27815
28156
|
const body = await c.req.json().catch(() => null);
|
|
27816
28157
|
const key = body?.key;
|
|
27817
28158
|
const messageId = body?.messageId;
|
|
@@ -27821,7 +28162,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27821
28162
|
deps.onReceived?.(key, messageId);
|
|
27822
28163
|
return c.json({ ok: true });
|
|
27823
28164
|
});
|
|
27824
|
-
|
|
28165
|
+
app70.post("/webchat-channel/turn-end", async (c) => {
|
|
27825
28166
|
const body = await c.req.json().catch(() => null);
|
|
27826
28167
|
const key = body?.key;
|
|
27827
28168
|
const sessionId = body?.sessionId;
|
|
@@ -27835,7 +28176,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
27835
28176
|
console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=${replied ? "yes" : "no"} trailing=${finalBytes}`);
|
|
27836
28177
|
return c.json({ ok: true });
|
|
27837
28178
|
});
|
|
27838
|
-
return
|
|
28179
|
+
return app70;
|
|
27839
28180
|
}
|
|
27840
28181
|
|
|
27841
28182
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -27893,16 +28234,16 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27893
28234
|
* The public /api/chat route awaits this to return the reply on the same SSE
|
|
27894
28235
|
* response, preserving the pre-756 POST→single-blob browser contract. */
|
|
27895
28236
|
awaitReply(key, timeoutMs) {
|
|
27896
|
-
return new Promise((
|
|
28237
|
+
return new Promise((resolve45) => {
|
|
27897
28238
|
const timer = setTimeout(() => {
|
|
27898
28239
|
this.replyAwaiters.delete(key);
|
|
27899
|
-
|
|
28240
|
+
resolve45({ timeout: true });
|
|
27900
28241
|
}, timeoutMs);
|
|
27901
28242
|
if (timer.unref) timer.unref();
|
|
27902
28243
|
this.replyAwaiters.set(key, (r) => {
|
|
27903
28244
|
clearTimeout(timer);
|
|
27904
28245
|
this.replyAwaiters.delete(key);
|
|
27905
|
-
|
|
28246
|
+
resolve45(r);
|
|
27906
28247
|
});
|
|
27907
28248
|
});
|
|
27908
28249
|
}
|
|
@@ -27913,11 +28254,11 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27913
28254
|
* terminal dialog stays answerable). */
|
|
27914
28255
|
awaitPermissionVerdict(p, timeoutMs) {
|
|
27915
28256
|
const k = _WebchatGateway.promptKey(p.key, p.requestId);
|
|
27916
|
-
return new Promise((
|
|
28257
|
+
return new Promise((resolve45) => {
|
|
27917
28258
|
this.pendingPrompts.get(k)?.resolve({ timeout: true });
|
|
27918
28259
|
const timer = setTimeout(() => {
|
|
27919
28260
|
this.pendingPrompts.delete(k);
|
|
27920
|
-
|
|
28261
|
+
resolve45({ timeout: true });
|
|
27921
28262
|
}, timeoutMs);
|
|
27922
28263
|
if (timer.unref) timer.unref();
|
|
27923
28264
|
this.pendingPrompts.set(k, {
|
|
@@ -27926,7 +28267,7 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
27926
28267
|
resolve: (r) => {
|
|
27927
28268
|
clearTimeout(timer);
|
|
27928
28269
|
this.pendingPrompts.delete(k);
|
|
27929
|
-
|
|
28270
|
+
resolve45(r);
|
|
27930
28271
|
}
|
|
27931
28272
|
});
|
|
27932
28273
|
console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
|
|
@@ -28491,7 +28832,7 @@ async function fanOut(subscribers, text, onError, tag) {
|
|
|
28491
28832
|
|
|
28492
28833
|
// app/lib/webchat/file-delivery.ts
|
|
28493
28834
|
import { realpathSync as realpathSync9 } from "fs";
|
|
28494
|
-
import { resolve as
|
|
28835
|
+
import { resolve as resolve40 } from "path";
|
|
28495
28836
|
|
|
28496
28837
|
// app/lib/channel-pty-bridge/file-delivery.ts
|
|
28497
28838
|
var SEND_USER_FILE = "SendUserFile";
|
|
@@ -28582,29 +28923,29 @@ function makeFileDelivery(opts) {
|
|
|
28582
28923
|
}
|
|
28583
28924
|
|
|
28584
28925
|
// app/lib/webchat/file-delivery.ts
|
|
28585
|
-
var
|
|
28926
|
+
var TAG53 = "[webchat-adaptor]";
|
|
28586
28927
|
function platformRoot2() {
|
|
28587
28928
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
28588
28929
|
}
|
|
28589
28930
|
function makeWebchatSendFile(entry) {
|
|
28590
28931
|
return async (filePath) => {
|
|
28591
28932
|
if (!entry.accountId) {
|
|
28592
|
-
console.error(`${
|
|
28933
|
+
console.error(`${TAG53} file-delivery reject reason=no-account sender=${entry.senderId}`);
|
|
28593
28934
|
return { ok: false, error: "no-account" };
|
|
28594
28935
|
}
|
|
28595
|
-
const accountDir =
|
|
28936
|
+
const accountDir = resolve40(platformRoot2(), "..", "data/accounts", entry.accountId);
|
|
28596
28937
|
try {
|
|
28597
28938
|
const resolved = realpathSync9(filePath);
|
|
28598
28939
|
const accountResolved = realpathSync9(accountDir);
|
|
28599
28940
|
if (!resolved.startsWith(accountResolved + "/")) {
|
|
28600
|
-
console.error(`${
|
|
28941
|
+
console.error(`${TAG53} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
|
|
28601
28942
|
return { ok: false, error: "outside-account" };
|
|
28602
28943
|
}
|
|
28603
28944
|
return { ok: true };
|
|
28604
28945
|
} catch (err) {
|
|
28605
28946
|
const code = err.code;
|
|
28606
28947
|
console.error(
|
|
28607
|
-
`${
|
|
28948
|
+
`${TAG53} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
|
|
28608
28949
|
);
|
|
28609
28950
|
return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
|
|
28610
28951
|
}
|
|
@@ -28613,7 +28954,7 @@ function makeWebchatSendFile(entry) {
|
|
|
28613
28954
|
function makeWebchatFileDelivery(entry) {
|
|
28614
28955
|
return makeFileDelivery({
|
|
28615
28956
|
entry,
|
|
28616
|
-
tag:
|
|
28957
|
+
tag: TAG53,
|
|
28617
28958
|
channel: "webchat",
|
|
28618
28959
|
sendFile: makeWebchatSendFile(entry),
|
|
28619
28960
|
deferUntilVerdict: true
|
|
@@ -28675,7 +29016,7 @@ function buildPublicWebchatSpawnRequest(input) {
|
|
|
28675
29016
|
}
|
|
28676
29017
|
|
|
28677
29018
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
28678
|
-
var
|
|
29019
|
+
var TAG54 = "[whatsapp-adaptor]";
|
|
28679
29020
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
28680
29021
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
28681
29022
|
function platformRoot3() {
|
|
@@ -28693,7 +29034,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
28693
29034
|
});
|
|
28694
29035
|
if (result.ok) return { ok: true };
|
|
28695
29036
|
console.error(
|
|
28696
|
-
`${
|
|
29037
|
+
`${TAG54} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
28697
29038
|
);
|
|
28698
29039
|
return { ok: false, error: result.error };
|
|
28699
29040
|
};
|
|
@@ -28701,7 +29042,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
28701
29042
|
function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
28702
29043
|
const shared = makeFileDelivery({
|
|
28703
29044
|
entry,
|
|
28704
|
-
tag:
|
|
29045
|
+
tag: TAG54,
|
|
28705
29046
|
channel: "whatsapp",
|
|
28706
29047
|
sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
|
|
28707
29048
|
});
|
|
@@ -28736,7 +29077,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
|
28736
29077
|
if (!delivered) {
|
|
28737
29078
|
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
28738
29079
|
console.error(
|
|
28739
|
-
`${
|
|
29080
|
+
`${TAG54} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
28740
29081
|
);
|
|
28741
29082
|
}
|
|
28742
29083
|
}
|
|
@@ -28919,8 +29260,8 @@ var InboundHub3 = class {
|
|
|
28919
29260
|
|
|
28920
29261
|
// app/lib/telegram/gateway/routes.ts
|
|
28921
29262
|
function createTelegramChannelRoutes(deps) {
|
|
28922
|
-
const
|
|
28923
|
-
|
|
29263
|
+
const app70 = new Hono();
|
|
29264
|
+
app70.get("/tg-channel/inbound", (c) => {
|
|
28924
29265
|
const key = c.req.query("key");
|
|
28925
29266
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
28926
29267
|
return streamSSE(c, async (stream2) => {
|
|
@@ -28938,7 +29279,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28938
29279
|
}
|
|
28939
29280
|
});
|
|
28940
29281
|
});
|
|
28941
|
-
|
|
29282
|
+
app70.post("/tg-channel/reply", async (c) => {
|
|
28942
29283
|
const body = await c.req.json().catch(() => null);
|
|
28943
29284
|
const key = body?.key;
|
|
28944
29285
|
const text = body?.text;
|
|
@@ -28954,7 +29295,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28954
29295
|
console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
28955
29296
|
return c.json({ ok: true });
|
|
28956
29297
|
});
|
|
28957
|
-
|
|
29298
|
+
app70.post("/tg-channel/ready", async (c) => {
|
|
28958
29299
|
const body = await c.req.json().catch(() => null);
|
|
28959
29300
|
const key = body?.key;
|
|
28960
29301
|
if (typeof key !== "string") {
|
|
@@ -28963,7 +29304,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28963
29304
|
deps.onReady?.(key);
|
|
28964
29305
|
return c.json({ ok: true });
|
|
28965
29306
|
});
|
|
28966
|
-
|
|
29307
|
+
app70.post("/tg-channel/received", async (c) => {
|
|
28967
29308
|
const body = await c.req.json().catch(() => null);
|
|
28968
29309
|
const key = body?.key;
|
|
28969
29310
|
const messageId = body?.messageId;
|
|
@@ -28973,7 +29314,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
28973
29314
|
deps.onReceived?.(key, messageId);
|
|
28974
29315
|
return c.json({ ok: true });
|
|
28975
29316
|
});
|
|
28976
|
-
|
|
29317
|
+
app70.post("/tg-channel/turn-end", async (c) => {
|
|
28977
29318
|
const body = await c.req.json().catch(() => null);
|
|
28978
29319
|
const key = body?.key;
|
|
28979
29320
|
const sessionId = body?.sessionId;
|
|
@@ -29006,7 +29347,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
29006
29347
|
console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
|
|
29007
29348
|
return c.json({ ok: true, delivered: "none" });
|
|
29008
29349
|
});
|
|
29009
|
-
return
|
|
29350
|
+
return app70;
|
|
29010
29351
|
}
|
|
29011
29352
|
|
|
29012
29353
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
@@ -29156,8 +29497,8 @@ function buildTelegramSpawnRequest(input) {
|
|
|
29156
29497
|
// app/lib/telegram/outbound/send-document.ts
|
|
29157
29498
|
import { realpathSync as realpathSync10 } from "fs";
|
|
29158
29499
|
import { readFile as readFile11, stat as stat10 } from "fs/promises";
|
|
29159
|
-
import { resolve as
|
|
29160
|
-
var
|
|
29500
|
+
import { resolve as resolve41, basename as basename13 } from "path";
|
|
29501
|
+
var TAG55 = "[telegram:outbound]";
|
|
29161
29502
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
29162
29503
|
async function sendTelegramDocument(input) {
|
|
29163
29504
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
|
|
@@ -29167,17 +29508,17 @@ async function sendTelegramDocument(input) {
|
|
|
29167
29508
|
if (!maxyAccountId || !platformRoot5) {
|
|
29168
29509
|
return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
|
|
29169
29510
|
}
|
|
29170
|
-
const accountDir =
|
|
29511
|
+
const accountDir = resolve41(platformRoot5, "..", "data/accounts", maxyAccountId);
|
|
29171
29512
|
let accountResolved;
|
|
29172
29513
|
try {
|
|
29173
29514
|
accountResolved = realpathSync10(accountDir);
|
|
29174
29515
|
} catch (err) {
|
|
29175
29516
|
const code = err.code;
|
|
29176
29517
|
if (code === "ENOENT") {
|
|
29177
|
-
console.error(`${
|
|
29518
|
+
console.error(`${TAG55} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
|
|
29178
29519
|
return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
|
|
29179
29520
|
}
|
|
29180
|
-
console.error(`${
|
|
29521
|
+
console.error(`${TAG55} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
29181
29522
|
return { ok: false, status: 500, error: String(err) };
|
|
29182
29523
|
}
|
|
29183
29524
|
let resolvedPath;
|
|
@@ -29186,14 +29527,14 @@ async function sendTelegramDocument(input) {
|
|
|
29186
29527
|
} catch (err) {
|
|
29187
29528
|
const code = err.code;
|
|
29188
29529
|
if (code === "ENOENT") {
|
|
29189
|
-
console.error(`${
|
|
29530
|
+
console.error(`${TAG55} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
|
|
29190
29531
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
29191
29532
|
}
|
|
29192
|
-
console.error(`${
|
|
29533
|
+
console.error(`${TAG55} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
|
|
29193
29534
|
return { ok: false, status: 500, error: String(err) };
|
|
29194
29535
|
}
|
|
29195
29536
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
29196
|
-
console.error(`${
|
|
29537
|
+
console.error(`${TAG55} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
29197
29538
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
29198
29539
|
}
|
|
29199
29540
|
const fileStat = await stat10(resolvedPath);
|
|
@@ -29226,13 +29567,13 @@ async function sendTelegramDocument(input) {
|
|
|
29226
29567
|
error = e instanceof Error ? e.message : String(e);
|
|
29227
29568
|
}
|
|
29228
29569
|
console.error(
|
|
29229
|
-
`${
|
|
29570
|
+
`${TAG55} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
29230
29571
|
);
|
|
29231
29572
|
return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
29232
29573
|
}
|
|
29233
29574
|
|
|
29234
29575
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
29235
|
-
var
|
|
29576
|
+
var TAG56 = "[telegram:outbound]";
|
|
29236
29577
|
function platformRoot4() {
|
|
29237
29578
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
29238
29579
|
}
|
|
@@ -29244,11 +29585,11 @@ function makeTelegramSendFile(entry) {
|
|
|
29244
29585
|
botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
|
|
29245
29586
|
}
|
|
29246
29587
|
if (!botToken) {
|
|
29247
|
-
console.error(`${
|
|
29588
|
+
console.error(`${TAG56} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
|
|
29248
29589
|
return { ok: false, error: "no-bot-token" };
|
|
29249
29590
|
}
|
|
29250
29591
|
if (entry.replyTarget == null) {
|
|
29251
|
-
console.error(`${
|
|
29592
|
+
console.error(`${TAG56} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
|
|
29252
29593
|
return { ok: false, error: "no-reply-target" };
|
|
29253
29594
|
}
|
|
29254
29595
|
const result = await sendTelegramDocument({
|
|
@@ -29265,7 +29606,7 @@ function makeTelegramSendFile(entry) {
|
|
|
29265
29606
|
function makeTelegramFileDelivery(entry) {
|
|
29266
29607
|
return makeFileDelivery({
|
|
29267
29608
|
entry,
|
|
29268
|
-
tag:
|
|
29609
|
+
tag: TAG56,
|
|
29269
29610
|
channel: "telegram",
|
|
29270
29611
|
sendFile: makeTelegramSendFile(entry)
|
|
29271
29612
|
});
|
|
@@ -29306,7 +29647,7 @@ function startTelegramNativeFileFollower(input) {
|
|
|
29306
29647
|
|
|
29307
29648
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
29308
29649
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
29309
|
-
var
|
|
29650
|
+
var TAG57 = "[public-session-review]";
|
|
29310
29651
|
var CONSUMED_CAP = 500;
|
|
29311
29652
|
var consumed = /* @__PURE__ */ new Set();
|
|
29312
29653
|
function consumeOnce(sessionId) {
|
|
@@ -29333,7 +29674,7 @@ async function fetchJsonl(sessionId) {
|
|
|
29333
29674
|
return await res.text();
|
|
29334
29675
|
} catch (err) {
|
|
29335
29676
|
console.error(
|
|
29336
|
-
`${
|
|
29677
|
+
`${TAG57} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
29337
29678
|
);
|
|
29338
29679
|
return null;
|
|
29339
29680
|
}
|
|
@@ -29357,7 +29698,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
29357
29698
|
const res = await fetch(url);
|
|
29358
29699
|
if (!res.ok) {
|
|
29359
29700
|
console.error(
|
|
29360
|
-
`${
|
|
29701
|
+
`${TAG57} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
29361
29702
|
);
|
|
29362
29703
|
return [];
|
|
29363
29704
|
}
|
|
@@ -29365,7 +29706,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
29365
29706
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
29366
29707
|
} catch (err) {
|
|
29367
29708
|
console.error(
|
|
29368
|
-
`${
|
|
29709
|
+
`${TAG57} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
29369
29710
|
);
|
|
29370
29711
|
return [];
|
|
29371
29712
|
}
|
|
@@ -29394,7 +29735,7 @@ function composeInitialMessage(input) {
|
|
|
29394
29735
|
}
|
|
29395
29736
|
async function dispatchReviewer(input, initialMessage) {
|
|
29396
29737
|
const sessionId = randomUUID16();
|
|
29397
|
-
console.log(`${
|
|
29738
|
+
console.log(`${TAG57} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
29398
29739
|
const spawned = await managerRcSpawn({
|
|
29399
29740
|
sessionId,
|
|
29400
29741
|
initialMessage,
|
|
@@ -29414,21 +29755,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
29414
29755
|
const dispatchedAt = Date.now();
|
|
29415
29756
|
if (consumed.has(input.sessionId)) {
|
|
29416
29757
|
console.log(
|
|
29417
|
-
`${
|
|
29758
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
29418
29759
|
);
|
|
29419
29760
|
return;
|
|
29420
29761
|
}
|
|
29421
29762
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
29422
29763
|
if (!jsonl) {
|
|
29423
29764
|
console.log(
|
|
29424
|
-
`${
|
|
29765
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
29425
29766
|
);
|
|
29426
29767
|
return;
|
|
29427
29768
|
}
|
|
29428
29769
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
29429
29770
|
if (operatorTurns === 0) {
|
|
29430
29771
|
console.log(
|
|
29431
|
-
`${
|
|
29772
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
29432
29773
|
);
|
|
29433
29774
|
return;
|
|
29434
29775
|
}
|
|
@@ -29442,19 +29783,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
29442
29783
|
});
|
|
29443
29784
|
if (!consumeOnce(input.sessionId)) {
|
|
29444
29785
|
console.log(
|
|
29445
|
-
`${
|
|
29786
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
29446
29787
|
);
|
|
29447
29788
|
return;
|
|
29448
29789
|
}
|
|
29449
29790
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
29450
29791
|
if (!dispatched.ok) {
|
|
29451
29792
|
console.error(
|
|
29452
|
-
`${
|
|
29793
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
29453
29794
|
);
|
|
29454
29795
|
return;
|
|
29455
29796
|
}
|
|
29456
29797
|
console.log(
|
|
29457
|
-
`${
|
|
29798
|
+
`${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
29458
29799
|
);
|
|
29459
29800
|
}
|
|
29460
29801
|
|
|
@@ -29559,14 +29900,14 @@ function warnOnChannelAdminBindingDrift() {
|
|
|
29559
29900
|
}
|
|
29560
29901
|
|
|
29561
29902
|
// server/lib/booking-site-accounts.ts
|
|
29562
|
-
import { existsSync as
|
|
29563
|
-
import { resolve as
|
|
29903
|
+
import { existsSync as existsSync44, readFileSync as readFileSync45 } from "fs";
|
|
29904
|
+
import { resolve as resolve42 } from "path";
|
|
29564
29905
|
function listBookingSiteAccounts(accounts) {
|
|
29565
29906
|
return accounts.filter((a) => {
|
|
29566
|
-
const availPath =
|
|
29567
|
-
if (!
|
|
29907
|
+
const availPath = resolve42(a.accountDir, "calendar-availability.json");
|
|
29908
|
+
if (!existsSync44(availPath)) return false;
|
|
29568
29909
|
try {
|
|
29569
|
-
const cfg = JSON.parse(
|
|
29910
|
+
const cfg = JSON.parse(readFileSync45(availPath, "utf-8"));
|
|
29570
29911
|
return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
29571
29912
|
} catch {
|
|
29572
29913
|
return false;
|
|
@@ -29604,8 +29945,8 @@ function broadcastAdminShutdown(reason) {
|
|
|
29604
29945
|
|
|
29605
29946
|
// ../lib/entitlement/src/index.ts
|
|
29606
29947
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
29607
|
-
import { existsSync as
|
|
29608
|
-
import { resolve as
|
|
29948
|
+
import { existsSync as existsSync45, readFileSync as readFileSync46, statSync as statSync19 } from "fs";
|
|
29949
|
+
import { resolve as resolve43 } from "path";
|
|
29609
29950
|
|
|
29610
29951
|
// ../lib/entitlement/src/canonicalize.ts
|
|
29611
29952
|
function canonicalize(value) {
|
|
@@ -29640,7 +29981,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
|
|
|
29640
29981
|
var GRACE_DAYS = 7;
|
|
29641
29982
|
var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
|
|
29642
29983
|
function pubkeyPath(brand) {
|
|
29643
|
-
return
|
|
29984
|
+
return resolve43(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
|
|
29644
29985
|
}
|
|
29645
29986
|
var memo = null;
|
|
29646
29987
|
function memoKey(mtimeMs, account) {
|
|
@@ -29652,8 +29993,8 @@ function resolveEntitlement(brand, account) {
|
|
|
29652
29993
|
if (brand.commercialMode !== true) {
|
|
29653
29994
|
return logResolved(implicitTrust(account), null);
|
|
29654
29995
|
}
|
|
29655
|
-
const entitlementPath =
|
|
29656
|
-
if (!
|
|
29996
|
+
const entitlementPath = resolve43(brand.configDir, "entitlement.json");
|
|
29997
|
+
if (!existsSync45(entitlementPath)) {
|
|
29657
29998
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
29658
29999
|
}
|
|
29659
30000
|
const stat11 = statSync19(entitlementPath);
|
|
@@ -29668,7 +30009,7 @@ function resolveEntitlement(brand, account) {
|
|
|
29668
30009
|
function verifyAndResolve(brand, entitlementPath, account) {
|
|
29669
30010
|
let pubkeyPem;
|
|
29670
30011
|
try {
|
|
29671
|
-
pubkeyPem =
|
|
30012
|
+
pubkeyPem = readFileSync46(pubkeyPath(brand), "utf-8");
|
|
29672
30013
|
} catch (err) {
|
|
29673
30014
|
return logResolved(anonymousFallback("pubkey-missing"), {
|
|
29674
30015
|
reason: "pubkey-missing"
|
|
@@ -29682,7 +30023,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
|
|
|
29682
30023
|
}
|
|
29683
30024
|
let envelope;
|
|
29684
30025
|
try {
|
|
29685
|
-
envelope = JSON.parse(
|
|
30026
|
+
envelope = JSON.parse(readFileSync46(entitlementPath, "utf-8"));
|
|
29686
30027
|
} catch {
|
|
29687
30028
|
return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
|
|
29688
30029
|
}
|
|
@@ -29846,12 +30187,12 @@ installMediaDownloadGuard();
|
|
|
29846
30187
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
29847
30188
|
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join47(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
29848
30189
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
29849
|
-
if (BRAND_JSON_PATH && !
|
|
30190
|
+
if (BRAND_JSON_PATH && !existsSync46(BRAND_JSON_PATH)) {
|
|
29850
30191
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
29851
30192
|
}
|
|
29852
|
-
if (BRAND_JSON_PATH &&
|
|
30193
|
+
if (BRAND_JSON_PATH && existsSync46(BRAND_JSON_PATH)) {
|
|
29853
30194
|
try {
|
|
29854
|
-
const parsed = JSON.parse(
|
|
30195
|
+
const parsed = JSON.parse(readFileSync47(BRAND_JSON_PATH, "utf-8"));
|
|
29855
30196
|
BRAND = { ...BRAND, ...parsed };
|
|
29856
30197
|
} catch (err) {
|
|
29857
30198
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -29886,8 +30227,8 @@ var brandLoginOpts = {
|
|
|
29886
30227
|
var ALIAS_DOMAINS_PATH = join47(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
29887
30228
|
function loadAliasDomains() {
|
|
29888
30229
|
try {
|
|
29889
|
-
if (!
|
|
29890
|
-
const parsed = JSON.parse(
|
|
30230
|
+
if (!existsSync46(ALIAS_DOMAINS_PATH)) return null;
|
|
30231
|
+
const parsed = JSON.parse(readFileSync47(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
29891
30232
|
if (!Array.isArray(parsed)) {
|
|
29892
30233
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
29893
30234
|
return null;
|
|
@@ -29911,7 +30252,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
29911
30252
|
function isPublicHost(host) {
|
|
29912
30253
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
29913
30254
|
}
|
|
29914
|
-
var
|
|
30255
|
+
var app69 = new Hono();
|
|
29915
30256
|
function resolveChannelOverride(accountId, channel, senderId) {
|
|
29916
30257
|
try {
|
|
29917
30258
|
const dir = listValidAccounts().find((a) => a.accountId === accountId)?.accountDir;
|
|
@@ -29960,7 +30301,7 @@ var waGateway = new WaGateway({
|
|
|
29960
30301
|
fetchStandingRules: fetchAccountStandingRules,
|
|
29961
30302
|
resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
|
|
29962
30303
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
29963
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ??
|
|
30304
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
29964
30305
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
29965
30306
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
29966
30307
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -29975,7 +30316,7 @@ var waGateway = new WaGateway({
|
|
|
29975
30316
|
caption,
|
|
29976
30317
|
accountId,
|
|
29977
30318
|
maxyAccountId,
|
|
29978
|
-
platformRoot:
|
|
30319
|
+
platformRoot: resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
|
|
29979
30320
|
});
|
|
29980
30321
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
29981
30322
|
},
|
|
@@ -30087,7 +30428,7 @@ var waGateway = new WaGateway({
|
|
|
30087
30428
|
nativeFileFollowers.set(senderId, ac);
|
|
30088
30429
|
}
|
|
30089
30430
|
});
|
|
30090
|
-
|
|
30431
|
+
app69.route("/", waGateway.routes());
|
|
30091
30432
|
waGateway.startSweeper();
|
|
30092
30433
|
function runDuplicateSenderAudit() {
|
|
30093
30434
|
try {
|
|
@@ -30210,7 +30551,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
30210
30551
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
30211
30552
|
});
|
|
30212
30553
|
setWebchatGateway(webchatGateway);
|
|
30213
|
-
|
|
30554
|
+
app69.route("/", webchatGateway.routes());
|
|
30214
30555
|
webchatGateway.startSweeper();
|
|
30215
30556
|
webchatGateway.startPublicReaper();
|
|
30216
30557
|
var telegramFileFollowers = /* @__PURE__ */ new Map();
|
|
@@ -30254,7 +30595,7 @@ var telegramGateway = new TelegramGateway({
|
|
|
30254
30595
|
}
|
|
30255
30596
|
});
|
|
30256
30597
|
setTelegramGateway(telegramGateway);
|
|
30257
|
-
|
|
30598
|
+
app69.route("/", telegramGateway.routes());
|
|
30258
30599
|
telegramGateway.startSweeper();
|
|
30259
30600
|
var chatRoutes = createChatRoutes({
|
|
30260
30601
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
@@ -30288,19 +30629,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
30288
30629
|
return managed.account;
|
|
30289
30630
|
}
|
|
30290
30631
|
});
|
|
30291
|
-
|
|
30292
|
-
|
|
30632
|
+
app69.route("/api/channel/schedule-inject", scheduleInjectRoutes);
|
|
30633
|
+
app69.use("*", clientIpMiddleware);
|
|
30293
30634
|
function allowsSameOriginFraming(path3) {
|
|
30294
30635
|
return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download" || path3 === "/api/admin/session-upload";
|
|
30295
30636
|
}
|
|
30296
|
-
|
|
30637
|
+
app69.use("*", async (c, next) => {
|
|
30297
30638
|
await next();
|
|
30298
30639
|
c.header("X-Content-Type-Options", "nosniff");
|
|
30299
30640
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
30300
30641
|
c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
|
|
30301
30642
|
});
|
|
30302
30643
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
30303
|
-
|
|
30644
|
+
app69.use("*", async (c, next) => {
|
|
30304
30645
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
30305
30646
|
await next();
|
|
30306
30647
|
return;
|
|
@@ -30318,7 +30659,7 @@ app67.use("*", async (c, next) => {
|
|
|
30318
30659
|
});
|
|
30319
30660
|
}
|
|
30320
30661
|
});
|
|
30321
|
-
|
|
30662
|
+
app69.use("*", async (c, next) => {
|
|
30322
30663
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30323
30664
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
30324
30665
|
await next();
|
|
@@ -30356,7 +30697,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
30356
30697
|
return { ...brandLoginOpts, origin };
|
|
30357
30698
|
}
|
|
30358
30699
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
30359
|
-
|
|
30700
|
+
app69.post("/__remote-auth/login", async (c) => {
|
|
30360
30701
|
const client = clientFrom(c);
|
|
30361
30702
|
const clientIp = client.ip || "unknown";
|
|
30362
30703
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -30401,7 +30742,7 @@ app67.post("/__remote-auth/login", async (c) => {
|
|
|
30401
30742
|
}
|
|
30402
30743
|
});
|
|
30403
30744
|
});
|
|
30404
|
-
|
|
30745
|
+
app69.get("/__remote-auth/logout", (c) => {
|
|
30405
30746
|
const client = clientFrom(c);
|
|
30406
30747
|
const clientIp = client.ip || "unknown";
|
|
30407
30748
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -30414,7 +30755,7 @@ app67.get("/__remote-auth/logout", (c) => {
|
|
|
30414
30755
|
}
|
|
30415
30756
|
});
|
|
30416
30757
|
});
|
|
30417
|
-
|
|
30758
|
+
app69.post("/__remote-auth/change-password", async (c) => {
|
|
30418
30759
|
const client = clientFrom(c);
|
|
30419
30760
|
const clientIp = client.ip || "unknown";
|
|
30420
30761
|
const rateLimited = checkRateLimit(client);
|
|
@@ -30473,13 +30814,13 @@ app67.post("/__remote-auth/change-password", async (c) => {
|
|
|
30473
30814
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
30474
30815
|
}
|
|
30475
30816
|
});
|
|
30476
|
-
|
|
30817
|
+
app69.get("/__remote-auth/setup", (c) => {
|
|
30477
30818
|
if (isRemoteAuthConfigured()) {
|
|
30478
30819
|
return c.redirect("/");
|
|
30479
30820
|
}
|
|
30480
30821
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
30481
30822
|
});
|
|
30482
|
-
|
|
30823
|
+
app69.post("/__remote-auth/set-initial-password", async (c) => {
|
|
30483
30824
|
if (isRemoteAuthConfigured()) {
|
|
30484
30825
|
return c.redirect("/");
|
|
30485
30826
|
}
|
|
@@ -30517,10 +30858,10 @@ app67.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
30517
30858
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
30518
30859
|
}
|
|
30519
30860
|
});
|
|
30520
|
-
|
|
30861
|
+
app69.get("/api/remote-auth/status", (c) => {
|
|
30521
30862
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
30522
30863
|
});
|
|
30523
|
-
|
|
30864
|
+
app69.post("/api/remote-auth/set-password", async (c) => {
|
|
30524
30865
|
let body;
|
|
30525
30866
|
try {
|
|
30526
30867
|
body = await c.req.json();
|
|
@@ -30559,10 +30900,10 @@ app67.post("/api/remote-auth/set-password", async (c) => {
|
|
|
30559
30900
|
return c.json({ error: "Failed to save password" }, 500);
|
|
30560
30901
|
}
|
|
30561
30902
|
});
|
|
30562
|
-
|
|
30903
|
+
app69.route("/api/_client-error", client_error_default);
|
|
30563
30904
|
console.log("[client-error-route] mounted");
|
|
30564
30905
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
30565
|
-
|
|
30906
|
+
app69.use("*", async (c, next) => {
|
|
30566
30907
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30567
30908
|
const path3 = c.req.path;
|
|
30568
30909
|
if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
|
|
@@ -30606,28 +30947,28 @@ app67.use("*", async (c, next) => {
|
|
|
30606
30947
|
}
|
|
30607
30948
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
|
|
30608
30949
|
});
|
|
30609
|
-
|
|
30610
|
-
|
|
30611
|
-
|
|
30612
|
-
|
|
30613
|
-
|
|
30614
|
-
|
|
30615
|
-
|
|
30950
|
+
app69.route("/api/health", health_default);
|
|
30951
|
+
app69.route("/api/chat", chatRoutes);
|
|
30952
|
+
app69.route("/api/whatsapp", whatsapp_default);
|
|
30953
|
+
app69.route("/api/storage", storage_broker_default);
|
|
30954
|
+
app69.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
30955
|
+
app69.route("/api/public-reader", public_reader_default);
|
|
30956
|
+
app69.route("/api/webchat", createWebchatRoutes({
|
|
30616
30957
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
30617
30958
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
30618
30959
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
30619
30960
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
30620
30961
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
30621
30962
|
}));
|
|
30622
|
-
|
|
30623
|
-
|
|
30624
|
-
|
|
30625
|
-
|
|
30626
|
-
|
|
30627
|
-
|
|
30628
|
-
|
|
30629
|
-
|
|
30630
|
-
|
|
30963
|
+
app69.route("/api/webchat/greeting", webchat_greeting_default);
|
|
30964
|
+
app69.route("/api/telegram", telegram_default);
|
|
30965
|
+
app69.route("/api/quickbooks", quickbooks_default);
|
|
30966
|
+
app69.route("/api/onboarding", onboarding_default);
|
|
30967
|
+
app69.route("/api/admin", admin_default);
|
|
30968
|
+
app69.route("/api/access", access_default);
|
|
30969
|
+
app69.route("/api/session", session_default2);
|
|
30970
|
+
app69.route("/api/calendar", calendar_public_default);
|
|
30971
|
+
app69.route("/api/portal", portal_fetch_default);
|
|
30631
30972
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
30632
30973
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
30633
30974
|
var IMAGE_MIME = {
|
|
@@ -30639,7 +30980,7 @@ var IMAGE_MIME = {
|
|
|
30639
30980
|
".svg": "image/svg+xml",
|
|
30640
30981
|
".ico": "image/x-icon"
|
|
30641
30982
|
};
|
|
30642
|
-
|
|
30983
|
+
app69.get("/agent-assets/:slug/:filename", (c) => {
|
|
30643
30984
|
const slug = c.req.param("slug");
|
|
30644
30985
|
const filename = c.req.param("filename");
|
|
30645
30986
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -30655,26 +30996,26 @@ app67.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
30655
30996
|
console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
|
|
30656
30997
|
return c.text("Not found", 404);
|
|
30657
30998
|
}
|
|
30658
|
-
const filePath =
|
|
30659
|
-
const expectedDir =
|
|
30999
|
+
const filePath = resolve44(account.accountDir, "agents", slug, "assets", filename);
|
|
31000
|
+
const expectedDir = resolve44(account.accountDir, "agents", slug, "assets");
|
|
30660
31001
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30661
31002
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
30662
31003
|
return c.text("Forbidden", 403);
|
|
30663
31004
|
}
|
|
30664
|
-
if (!
|
|
31005
|
+
if (!existsSync46(filePath)) {
|
|
30665
31006
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
30666
31007
|
return c.text("Not found", 404);
|
|
30667
31008
|
}
|
|
30668
31009
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30669
31010
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30670
31011
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
30671
|
-
const body =
|
|
31012
|
+
const body = readFileSync47(filePath);
|
|
30672
31013
|
return c.body(body, 200, {
|
|
30673
31014
|
"Content-Type": contentType,
|
|
30674
31015
|
"Cache-Control": "public, max-age=3600"
|
|
30675
31016
|
});
|
|
30676
31017
|
});
|
|
30677
|
-
|
|
31018
|
+
app69.get("/generated/:filename", (c) => {
|
|
30678
31019
|
const filename = c.req.param("filename");
|
|
30679
31020
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
30680
31021
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -30685,35 +31026,35 @@ app67.get("/generated/:filename", (c) => {
|
|
|
30685
31026
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30686
31027
|
return c.text("Not found", 404);
|
|
30687
31028
|
}
|
|
30688
|
-
const filePath =
|
|
30689
|
-
const expectedDir =
|
|
31029
|
+
const filePath = resolve44(account.accountDir, "generated", filename);
|
|
31030
|
+
const expectedDir = resolve44(account.accountDir, "generated");
|
|
30690
31031
|
if (!filePath.startsWith(expectedDir + "/")) {
|
|
30691
31032
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
30692
31033
|
return c.text("Forbidden", 403);
|
|
30693
31034
|
}
|
|
30694
|
-
if (!
|
|
31035
|
+
if (!existsSync46(filePath)) {
|
|
30695
31036
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
30696
31037
|
return c.text("Not found", 404);
|
|
30697
31038
|
}
|
|
30698
31039
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
30699
31040
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
30700
31041
|
console.log(`[generated] serve file=${filename} status=200`);
|
|
30701
|
-
const body =
|
|
31042
|
+
const body = readFileSync47(filePath);
|
|
30702
31043
|
return c.body(body, 200, {
|
|
30703
31044
|
"Content-Type": contentType,
|
|
30704
31045
|
"Cache-Control": "public, max-age=86400"
|
|
30705
31046
|
});
|
|
30706
31047
|
});
|
|
30707
|
-
|
|
30708
|
-
|
|
30709
|
-
|
|
30710
|
-
|
|
31048
|
+
app69.route("/sites", sites_default);
|
|
31049
|
+
app69.route("/listings", listings_default);
|
|
31050
|
+
app69.route("/v", visitor_event_default);
|
|
31051
|
+
app69.route("/v", visitor_consent_default);
|
|
30711
31052
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
30712
31053
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
30713
31054
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
30714
|
-
if (BRAND_JSON_PATH &&
|
|
31055
|
+
if (BRAND_JSON_PATH && existsSync46(BRAND_JSON_PATH)) {
|
|
30715
31056
|
try {
|
|
30716
|
-
const fullBrand = JSON.parse(
|
|
31057
|
+
const fullBrand = JSON.parse(readFileSync47(BRAND_JSON_PATH, "utf-8"));
|
|
30717
31058
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
30718
31059
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
30719
31060
|
} catch {
|
|
@@ -30740,11 +31081,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
30740
31081
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
30741
31082
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
30742
31083
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
30743
|
-
(p) =>
|
|
31084
|
+
(p) => existsSync46(resolve44(process.cwd(), "public", p.replace(/^\//, "")))
|
|
30744
31085
|
);
|
|
30745
31086
|
var SW_SOURCE = (() => {
|
|
30746
31087
|
try {
|
|
30747
|
-
return
|
|
31088
|
+
return readFileSync47(resolve44(process.cwd(), "public", "sw.js"), "utf-8");
|
|
30748
31089
|
} catch {
|
|
30749
31090
|
return null;
|
|
30750
31091
|
}
|
|
@@ -30753,8 +31094,8 @@ function readInstalledVersion() {
|
|
|
30753
31094
|
try {
|
|
30754
31095
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
30755
31096
|
const versionFile = join47(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
30756
|
-
if (!
|
|
30757
|
-
const content =
|
|
31097
|
+
if (!existsSync46(versionFile)) return "unknown";
|
|
31098
|
+
const content = readFileSync47(versionFile, "utf-8").trim();
|
|
30758
31099
|
return content || "unknown";
|
|
30759
31100
|
} catch {
|
|
30760
31101
|
return "unknown";
|
|
@@ -30795,7 +31136,7 @@ var clientErrorReporterScript = `<script>
|
|
|
30795
31136
|
function cachedHtml(file) {
|
|
30796
31137
|
let html = htmlCache.get(file);
|
|
30797
31138
|
if (!html) {
|
|
30798
|
-
html =
|
|
31139
|
+
html = readFileSync47(resolve44(process.cwd(), "public", file), "utf-8");
|
|
30799
31140
|
const productNameEsc = escapeHtml(BRAND.productName);
|
|
30800
31141
|
html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
|
|
30801
31142
|
html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
|
|
@@ -30817,8 +31158,8 @@ function loadBrandingCache(agentSlug) {
|
|
|
30817
31158
|
const accountId = getDefaultAccountId();
|
|
30818
31159
|
if (!accountId) return null;
|
|
30819
31160
|
const cachePath = join47(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
30820
|
-
if (!
|
|
30821
|
-
return JSON.parse(
|
|
31161
|
+
if (!existsSync46(cachePath)) return null;
|
|
31162
|
+
return JSON.parse(readFileSync47(cachePath, "utf-8"));
|
|
30822
31163
|
} catch {
|
|
30823
31164
|
return null;
|
|
30824
31165
|
}
|
|
@@ -30862,7 +31203,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
30862
31203
|
function agentUnavailableHtml() {
|
|
30863
31204
|
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>`;
|
|
30864
31205
|
}
|
|
30865
|
-
|
|
31206
|
+
app69.get("/", (c) => {
|
|
30866
31207
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30867
31208
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
30868
31209
|
if (klass === "operator") {
|
|
@@ -30884,12 +31225,12 @@ app67.get("/", (c) => {
|
|
|
30884
31225
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
30885
31226
|
return c.html(cachedHtml("index.html"));
|
|
30886
31227
|
});
|
|
30887
|
-
|
|
31228
|
+
app69.get("/public", (c) => {
|
|
30888
31229
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30889
31230
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30890
31231
|
return c.html(cachedHtml("public.html"));
|
|
30891
31232
|
});
|
|
30892
|
-
|
|
31233
|
+
app69.get("/public-chat", (c) => {
|
|
30893
31234
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30894
31235
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30895
31236
|
return c.html(cachedHtml("public.html"));
|
|
@@ -30908,12 +31249,12 @@ async function logViewerFetch(c, next) {
|
|
|
30908
31249
|
duration_ms: Date.now() - start
|
|
30909
31250
|
});
|
|
30910
31251
|
}
|
|
30911
|
-
|
|
30912
|
-
|
|
30913
|
-
|
|
31252
|
+
app69.use("/vnc-viewer.html", logViewerFetch);
|
|
31253
|
+
app69.use("/vnc-popout.html", logViewerFetch);
|
|
31254
|
+
app69.get("/vnc-popout.html", (c) => {
|
|
30914
31255
|
let html = htmlCache.get("vnc-popout.html");
|
|
30915
31256
|
if (!html) {
|
|
30916
|
-
html =
|
|
31257
|
+
html = readFileSync47(resolve44(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
30917
31258
|
const name = escapeHtml(BRAND.productName);
|
|
30918
31259
|
html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
|
|
30919
31260
|
html = html.replace("</head>", ` ${brandScript}
|
|
@@ -30923,7 +31264,7 @@ app67.get("/vnc-popout.html", (c) => {
|
|
|
30923
31264
|
}
|
|
30924
31265
|
return c.html(html);
|
|
30925
31266
|
});
|
|
30926
|
-
|
|
31267
|
+
app69.post("/api/vnc/client-event", async (c) => {
|
|
30927
31268
|
let body;
|
|
30928
31269
|
try {
|
|
30929
31270
|
body = await c.req.json();
|
|
@@ -30944,11 +31285,11 @@ app67.post("/api/vnc/client-event", async (c) => {
|
|
|
30944
31285
|
});
|
|
30945
31286
|
return c.json({ ok: true });
|
|
30946
31287
|
});
|
|
30947
|
-
|
|
31288
|
+
app69.get("/g/:slug", (c) => {
|
|
30948
31289
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
30949
31290
|
});
|
|
30950
31291
|
for (const pwa of PWA_SURFACES) {
|
|
30951
|
-
|
|
31292
|
+
app69.get(pwa.manifestPath, (c) => {
|
|
30952
31293
|
const manifest = buildManifest(pwa, {
|
|
30953
31294
|
productName: BRAND.productName,
|
|
30954
31295
|
appIcon192: brandAppIcon192Path,
|
|
@@ -30964,7 +31305,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
30964
31305
|
return c.body(JSON.stringify(manifest));
|
|
30965
31306
|
});
|
|
30966
31307
|
}
|
|
30967
|
-
|
|
31308
|
+
app69.get("/sw.js", (c) => {
|
|
30968
31309
|
if (SW_SOURCE == null) {
|
|
30969
31310
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
30970
31311
|
return c.text("Service worker unavailable", 500);
|
|
@@ -30973,12 +31314,12 @@ app67.get("/sw.js", (c) => {
|
|
|
30973
31314
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
30974
31315
|
return c.body(SW_SOURCE);
|
|
30975
31316
|
});
|
|
30976
|
-
|
|
31317
|
+
app69.get("/graph", (c) => {
|
|
30977
31318
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30978
31319
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
30979
31320
|
return c.html(cachedHtml("graph.html"));
|
|
30980
31321
|
});
|
|
30981
|
-
|
|
31322
|
+
app69.get("/chat", (c) => {
|
|
30982
31323
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30983
31324
|
if (isOperatorHost(host, getOperatorDomains())) {
|
|
30984
31325
|
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
@@ -30987,42 +31328,47 @@ app67.get("/chat", (c) => {
|
|
|
30987
31328
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30988
31329
|
return c.html(cachedHtml("chat.html"));
|
|
30989
31330
|
});
|
|
30990
|
-
|
|
31331
|
+
app69.get("/data", (c) => {
|
|
30991
31332
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30992
31333
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30993
31334
|
return c.html(cachedHtml("data.html"));
|
|
30994
31335
|
});
|
|
30995
|
-
|
|
31336
|
+
app69.get("/tasks", (c) => {
|
|
30996
31337
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
30997
31338
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
30998
31339
|
return c.html(cachedHtml("tasks.html"));
|
|
30999
31340
|
});
|
|
31000
|
-
|
|
31341
|
+
app69.get("/activity", (c) => {
|
|
31001
31342
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31002
31343
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
31003
31344
|
return c.html(cachedHtml("activity.html"));
|
|
31004
31345
|
});
|
|
31005
|
-
|
|
31346
|
+
app69.get("/calendar", (c) => {
|
|
31006
31347
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31007
31348
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
31008
31349
|
return c.html(cachedHtml("calendar.html"));
|
|
31009
31350
|
});
|
|
31010
|
-
|
|
31351
|
+
app69.get("/routines", (c) => {
|
|
31011
31352
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31012
31353
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
31013
31354
|
return c.html(cachedHtml("routines.html"));
|
|
31014
31355
|
});
|
|
31015
|
-
|
|
31356
|
+
app69.get("/skills", (c) => {
|
|
31016
31357
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31017
31358
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
31018
31359
|
return c.html(cachedHtml("skills.html"));
|
|
31019
31360
|
});
|
|
31020
|
-
|
|
31361
|
+
app69.get("/agents", (c) => {
|
|
31362
|
+
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31363
|
+
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
31364
|
+
return c.html(cachedHtml("agents.html"));
|
|
31365
|
+
});
|
|
31366
|
+
app69.get("/browser", (c) => {
|
|
31021
31367
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31022
31368
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
31023
31369
|
return c.html(cachedHtml("browser.html"));
|
|
31024
31370
|
});
|
|
31025
|
-
|
|
31371
|
+
app69.get("/:slug", async (c, next) => {
|
|
31026
31372
|
const slug = c.req.param("slug");
|
|
31027
31373
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
31028
31374
|
const account = resolveAccount();
|
|
@@ -31037,13 +31383,13 @@ app67.get("/:slug", async (c, next) => {
|
|
|
31037
31383
|
await next();
|
|
31038
31384
|
});
|
|
31039
31385
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
31040
|
-
|
|
31386
|
+
app69.get("/favicon.ico", (c) => {
|
|
31041
31387
|
c.header("Cache-Control", "public, max-age=300");
|
|
31042
31388
|
return c.redirect(brandFaviconPath, 302);
|
|
31043
31389
|
});
|
|
31044
31390
|
}
|
|
31045
|
-
|
|
31046
|
-
|
|
31391
|
+
app69.use("/*", serveStatic({ root: "./public" }));
|
|
31392
|
+
app69.all("*", (c) => {
|
|
31047
31393
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
31048
31394
|
const path3 = c.req.path;
|
|
31049
31395
|
if (isPublicHost(host)) {
|
|
@@ -31057,13 +31403,13 @@ app67.all("*", (c) => {
|
|
|
31057
31403
|
});
|
|
31058
31404
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
31059
31405
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
31060
|
-
var httpServer = serve({ fetch:
|
|
31406
|
+
var httpServer = serve({ fetch: app69.fetch, port, hostname });
|
|
31061
31407
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
31062
31408
|
{
|
|
31063
31409
|
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31064
|
-
const reconcileScript =
|
|
31410
|
+
const reconcileScript = resolve44(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
31065
31411
|
const runReconcile = (ctx) => {
|
|
31066
|
-
if (!
|
|
31412
|
+
if (!existsSync46(reconcileScript)) return;
|
|
31067
31413
|
try {
|
|
31068
31414
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
31069
31415
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -31102,14 +31448,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31102
31448
|
{
|
|
31103
31449
|
const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
|
|
31104
31450
|
const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31105
|
-
const dreamSweepScript =
|
|
31451
|
+
const dreamSweepScript = resolve44(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
|
|
31106
31452
|
registerLoop({
|
|
31107
31453
|
name: "dream-cycle-sweep",
|
|
31108
31454
|
intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
|
|
31109
31455
|
firstRunDelayMs: 3e4,
|
|
31110
31456
|
detached: true,
|
|
31111
31457
|
run: (ctx) => {
|
|
31112
|
-
if (!
|
|
31458
|
+
if (!existsSync46(dreamSweepScript)) return;
|
|
31113
31459
|
try {
|
|
31114
31460
|
const child = spawn3(process.execPath, [dreamSweepScript], {
|
|
31115
31461
|
env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
|
|
@@ -31126,10 +31472,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31126
31472
|
}
|
|
31127
31473
|
{
|
|
31128
31474
|
const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31129
|
-
const outlookScript =
|
|
31475
|
+
const outlookScript = resolve44(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
|
|
31130
31476
|
const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
|
|
31131
31477
|
const runOutlookComplete = (ctx) => {
|
|
31132
|
-
if (!
|
|
31478
|
+
if (!existsSync46(outlookScript)) return;
|
|
31133
31479
|
try {
|
|
31134
31480
|
const child = spawn3(process.execPath, [outlookScript], {
|
|
31135
31481
|
env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
|
|
@@ -31152,18 +31498,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31152
31498
|
}
|
|
31153
31499
|
{
|
|
31154
31500
|
const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31155
|
-
const strandedAccountsDir =
|
|
31501
|
+
const strandedAccountsDir = resolve44(auditRoot, "..", "data/accounts");
|
|
31156
31502
|
const STRANDED_AUDIT_INTERVAL_MS = 3e5;
|
|
31157
31503
|
const STRANDED_AGE_MS = 16 * 6e4;
|
|
31158
31504
|
const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31159
31505
|
const runStrandedAudit = () => {
|
|
31160
31506
|
try {
|
|
31161
|
-
if (!
|
|
31507
|
+
if (!existsSync46(strandedAccountsDir)) return;
|
|
31162
31508
|
const now = Date.now();
|
|
31163
|
-
for (const name of
|
|
31509
|
+
for (const name of readdirSync28(strandedAccountsDir)) {
|
|
31164
31510
|
if (!STRANDED_UUID_RE.test(name)) continue;
|
|
31165
|
-
const pendingPath2 =
|
|
31166
|
-
if (!
|
|
31511
|
+
const pendingPath2 = resolve44(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
|
|
31512
|
+
if (!existsSync46(pendingPath2)) continue;
|
|
31167
31513
|
const ageMs2 = now - statSync20(pendingPath2).mtimeMs;
|
|
31168
31514
|
if (ageMs2 > STRANDED_AGE_MS) {
|
|
31169
31515
|
console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
|
|
@@ -31182,7 +31528,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31182
31528
|
}
|
|
31183
31529
|
{
|
|
31184
31530
|
const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31185
|
-
const googleAccountsDir =
|
|
31531
|
+
const googleAccountsDir = resolve44(googleRoot, "..", "data/accounts");
|
|
31186
31532
|
const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
|
|
31187
31533
|
const runGooglePendingAuditSafe = () => {
|
|
31188
31534
|
try {
|
|
@@ -31197,10 +31543,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31197
31543
|
firstRunDelayMs: 27e3,
|
|
31198
31544
|
run: runGooglePendingAuditSafe
|
|
31199
31545
|
});
|
|
31200
|
-
const googleAuditScript =
|
|
31546
|
+
const googleAuditScript = resolve44(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
|
|
31201
31547
|
const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
|
|
31202
31548
|
const runGoogleAccountAudit = (ctx) => {
|
|
31203
|
-
if (!
|
|
31549
|
+
if (!existsSync46(googleAuditScript)) return;
|
|
31204
31550
|
try {
|
|
31205
31551
|
const child = spawn3(process.execPath, [googleAuditScript], {
|
|
31206
31552
|
env: { ...process.env, PLATFORM_ROOT: googleRoot },
|
|
@@ -31272,7 +31618,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31272
31618
|
}
|
|
31273
31619
|
{
|
|
31274
31620
|
const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31275
|
-
const publishScript =
|
|
31621
|
+
const publishScript = resolve44(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
|
|
31276
31622
|
const PUBLISH_INTERVAL_MS = 3e5;
|
|
31277
31623
|
const bookingAccounts = () => {
|
|
31278
31624
|
try {
|
|
@@ -31283,7 +31629,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31283
31629
|
}
|
|
31284
31630
|
};
|
|
31285
31631
|
const spawnPublish = (account, ctx) => {
|
|
31286
|
-
if (!
|
|
31632
|
+
if (!existsSync46(publishScript)) return;
|
|
31287
31633
|
try {
|
|
31288
31634
|
const child = spawn3(process.execPath, [publishScript], {
|
|
31289
31635
|
env: {
|
|
@@ -31302,21 +31648,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
31302
31648
|
}
|
|
31303
31649
|
};
|
|
31304
31650
|
const auditSnapshotAge = (account) => {
|
|
31305
|
-
const availPath =
|
|
31651
|
+
const availPath = resolve44(account.accountDir, "calendar-availability.json");
|
|
31306
31652
|
let hasBookingSite = false;
|
|
31307
31653
|
try {
|
|
31308
|
-
if (
|
|
31309
|
-
const cfg = JSON.parse(
|
|
31654
|
+
if (existsSync46(availPath)) {
|
|
31655
|
+
const cfg = JSON.parse(readFileSync47(availPath, "utf-8"));
|
|
31310
31656
|
hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
|
|
31311
31657
|
}
|
|
31312
31658
|
} catch {
|
|
31313
31659
|
}
|
|
31314
31660
|
if (!hasBookingSite) return;
|
|
31315
|
-
const statePath =
|
|
31661
|
+
const statePath = resolve44(account.accountDir, "state", "booking-availability", "last-publish.json");
|
|
31316
31662
|
let lastSuccessAt = null;
|
|
31317
|
-
if (
|
|
31663
|
+
if (existsSync46(statePath)) {
|
|
31318
31664
|
try {
|
|
31319
|
-
const rec = JSON.parse(
|
|
31665
|
+
const rec = JSON.parse(readFileSync47(statePath, "utf-8"));
|
|
31320
31666
|
lastSuccessAt = rec.lastSuccessAt ?? null;
|
|
31321
31667
|
} catch {
|
|
31322
31668
|
console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
|
|
@@ -31349,11 +31695,11 @@ startTimeEntryCensus(() => getSession());
|
|
|
31349
31695
|
startLedgerCensus(() => getSession());
|
|
31350
31696
|
{
|
|
31351
31697
|
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
|
|
31352
|
-
const auditScript =
|
|
31698
|
+
const auditScript = resolve44(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
31353
31699
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
31354
31700
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
31355
31701
|
const runConnectorAudit = (ctx) => {
|
|
31356
|
-
if (!
|
|
31702
|
+
if (!existsSync46(auditScript)) return;
|
|
31357
31703
|
try {
|
|
31358
31704
|
const child = spawn3(process.execPath, [auditScript], {
|
|
31359
31705
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -31433,7 +31779,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
31433
31779
|
}
|
|
31434
31780
|
try {
|
|
31435
31781
|
const registered = [];
|
|
31436
|
-
for (const r of
|
|
31782
|
+
for (const r of app69.routes ?? []) {
|
|
31437
31783
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
31438
31784
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
31439
31785
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -31473,11 +31819,11 @@ try {
|
|
|
31473
31819
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31474
31820
|
async function runAdminUserReconcileTick() {
|
|
31475
31821
|
try {
|
|
31476
|
-
if (!
|
|
31822
|
+
if (!existsSync46(USERS_FILE)) {
|
|
31477
31823
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
31478
31824
|
return;
|
|
31479
31825
|
}
|
|
31480
|
-
const usersRaw =
|
|
31826
|
+
const usersRaw = readFileSync47(USERS_FILE, "utf-8").trim();
|
|
31481
31827
|
if (!usersRaw) {
|
|
31482
31828
|
console.error("[adminuser-self-heal] skip reason=empty-users-file");
|
|
31483
31829
|
return;
|
|
@@ -31524,8 +31870,8 @@ registerLoop({
|
|
|
31524
31870
|
});
|
|
31525
31871
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
31526
31872
|
function countUsersRows() {
|
|
31527
|
-
if (!
|
|
31528
|
-
const raw =
|
|
31873
|
+
if (!existsSync46(USERS_FILE)) return 0;
|
|
31874
|
+
const raw = readFileSync47(USERS_FILE, "utf-8").trim();
|
|
31529
31875
|
if (!raw) return 0;
|
|
31530
31876
|
const users = JSON.parse(raw);
|
|
31531
31877
|
return users.filter((u) => typeof u.userId === "string").length;
|
|
@@ -31658,7 +32004,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
31658
32004
|
}
|
|
31659
32005
|
init({
|
|
31660
32006
|
configDir: configDirForWhatsApp,
|
|
31661
|
-
platformRoot:
|
|
32007
|
+
platformRoot: resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
|
|
31662
32008
|
accountConfig: bootAccountConfig,
|
|
31663
32009
|
onMessage: async (msg) => {
|
|
31664
32010
|
if (isObserveAccount(msg.accountId)) {
|