@rubytech/create-maxy-code 0.1.436 → 0.1.437
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/active-rules/dist/index.d.ts +14 -0
- package/payload/platform/lib/active-rules/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/active-rules/dist/index.js +56 -9
- package/payload/platform/lib/active-rules/dist/index.js.map +1 -1
- package/payload/platform/lib/active-rules/src/index.test.ts +106 -0
- package/payload/platform/lib/active-rules/src/index.ts +98 -9
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +6 -6
- package/payload/platform/plugins/docs/references/admin-session.md +2 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/docs/references/internals.md +3 -3
- package/payload/platform/plugins/memory/mcp/dist/index.js +12 -3
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js +79 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js +50 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js +114 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +15 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +17 -17
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +21 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +19 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +4 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +16 -6
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +7 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts +4 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.js.map +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-CMh1pdOp.js → AdminLoginScreens-DeR71H29.js} +1 -1
- package/payload/server/public/assets/AdminShell-DlAVQUda.js +2 -0
- package/payload/server/public/assets/{Checkbox-OCfZCTCO.js → Checkbox-B629mOPp.js} +1 -1
- package/payload/server/public/assets/{admin-Bi2uYnAg.js → admin-C15h-NL0.js} +1 -1
- package/payload/server/public/assets/{arc-Bm9oSOth.js → arc-qKfXIt8v.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-C2dK88g3.js → architectureDiagram-Q4EWVU46-DkVrGn7G.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DfLSsjCJ.js → blockDiagram-DXYQGD6D-DqavswGH.js} +1 -1
- package/payload/server/public/assets/browser-B7xQLIRK.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Bxkmp6OL.js → c4Diagram-AHTNJAMY-B7fyKiXe.js} +1 -1
- package/payload/server/public/assets/calendar-A-vGm6pL.js +1 -0
- package/payload/server/public/assets/channel-j70eMvcL.js +1 -0
- package/payload/server/public/assets/chat-DAae6Z51.js +1 -0
- package/payload/server/public/assets/chevron-left-u4tjq7fI.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BVNDFwNH.js → chunk-2KRD3SAO-DsgMtGkv.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-Daz6nMta.js → chunk-336JU56O-CkdISfNt.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-DTldfvwP.js → chunk-4BX2VUAB-CYpiF2bl.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DhM8pwRG.js → chunk-4TB4RGXK-CWyc_F7v.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-CzTsbIHo.js → chunk-55IACEB6-BbzKMw2Z.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-BrcObZhe.js → chunk-5FUZZQ4R-u19Nai9e.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-SFqTuS11.js → chunk-5PVQY5BW-Ba8by6Uy.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-EIbrSGOo.js → chunk-67CJDMHE-BwUuxtyb.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-B1D4Jorr.js → chunk-7N4EOEYR-BRH9iM9L.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-BKHiX4cC.js → chunk-AA7GKIK3-BGoztgLL.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-xBzu29m7.js → chunk-BSJP7CBP-C5GDAZTl.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-x2x0gMpL.js → chunk-CIAEETIT-ChY32VPS.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-D5UkD28M.js → chunk-EDXVE4YY-CPSD3p6p.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-Dbz67a7E.js → chunk-ENJZ2VHE-D1oL-iUr.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-XfWvuu2F.js → chunk-FMBD7UC4-CPvYEr54.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-DfOEDS4q.js → chunk-FOC6F5B3-9Yyj7Vbz.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-D_WEZZvg.js → chunk-ICPOFSXX-BaYgh8FR.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-7O627Xi1.js → chunk-K5T4RW27-5ucpeRvm.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-BXI3XDP9.js → chunk-KGLVRYIC-DW-FHk7T.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-B9cFNN0l.js → chunk-LIHQZDEY-CGGVfAyG.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-BR3UNDTn.js → chunk-ORNJ4GCN-Bv8EUa5d.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-2wKIEtFZ.js → chunk-OYMX7WX6-C1mXJnyw.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-augM3AXB.js → chunk-U2HBQHQK-PwSQz6EP.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-BAM9q9ZQ.js → chunk-X2U36JSP--NPHTBlU.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-DxPpji5P.js → chunk-XPW4576I-Bbc7Da32.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-BD3ClFXP.js → chunk-YZCP3GAM-D-9v8e--.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CqxhLPep.js → chunk-ZZ45TVLE-CMPg670Q.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +1 -0
- package/payload/server/public/assets/clone-DjPWA_NH.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-xywWX-9i.js → cose-bilkent-S5V4N54A-NVSb1Bhy.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-ChRpqqiH.js → dagre-KV5264BT-V2Ai1DFl.js} +1 -1
- package/payload/server/public/assets/{dagre-BaHjDQ-8.js → dagre-QfLcO-1j.js} +1 -1
- package/payload/server/public/assets/data-BNWpKx1d.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-KjwTpyBi.js → diagram-5BDNPKRD-Caw21693.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-DZO9njAF.js → diagram-G4DWMVQ6-CgwVkT2q.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-Bus-U-TI.js → diagram-MMDJMWI5-DFUrLZhs.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CfJodFgq.js → diagram-TYMM5635-CEEiEuZJ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-Bt5zqWiW.js → erDiagram-SMLLAGMA-CG10NrT3.js} +1 -1
- package/payload/server/public/assets/file-download-4mKJxUi-.js +1 -0
- package/payload/server/public/assets/{flatten-Bpu1L63d.js → flatten-DAO0sfCM.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B64Q590S.js → flowDiagram-DWJPFMVM-BqkV9Okv.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BWdgCEpH.js → ganttDiagram-T4ZO3ILL-DRiCDQF6.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-Djq2B0WT.js → gitGraphDiagram-UUTBAWPF-BZV2voyy.js} +1 -1
- package/payload/server/public/assets/{graph-CrJ-itbq.js → graph-D0orIRAh.js} +3 -3
- package/payload/server/public/assets/{graph-labels-CmCWaKJT.js → graph-labels-B8YAdo3Z.js} +1 -1
- package/payload/server/public/assets/{graphlib-CNJh9_lx.js → graphlib-DGPThX8M.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +2 -0
- package/payload/server/public/assets/{isEmpty-DkDEVnMZ.js → isEmpty-Cb_U81C6.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-V3ACkWCW.js → ishikawaDiagram-UXIWVN3A-BKsAxSvp.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-9T0qZeH3.js → journeyDiagram-VCZTEJTY-CmliuOd-.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CxZ0ukx3.js → kanban-definition-6JOO6SKY-DAlElMb-.js} +1 -1
- package/payload/server/public/assets/{line-DUHKCQZT.js → line-DKZqLKAC.js} +1 -1
- package/payload/server/public/assets/{linear-BgIBblun.js → linear-CbSGdh1x.js} +1 -1
- package/payload/server/public/assets/{maximize-2-_cJWIgx2.js → maximize-2-CxstTgoK.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-CyHygs0-.js → mermaid-parser.core-DFvbao9C.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-L55fJBSx.js → mermaid.core-C0vEBxDm.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DczaUX_E.js → mindmap-definition-QFDTVHPH-CShASUKd.js} +1 -1
- package/payload/server/public/assets/operator-DZzuotDB.js +1 -0
- package/payload/server/public/assets/{ordinal-DK3QISRR.js → ordinal-H0tVmBDP.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +1 -0
- package/payload/server/public/assets/{page-DbUaFfk6.js → page-3g0A19Rv.js} +6 -6
- package/payload/server/public/assets/page-Ck_pLhAk.js +1 -0
- package/payload/server/public/assets/{pdf-render-COLA4aPx.js → pdf-render-jAQU0nXt.js} +1 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-Da5TdnNt.js → pieDiagram-DEJITSTG-CBZHpDAJ.js} +1 -1
- package/payload/server/public/assets/{public-CYhDdDJd.js → public-WFUQw9AD.js} +1 -1
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DX7J81uh.js → quadrantDiagram-34T5L4WZ-n3bB3K91.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +1 -0
- package/payload/server/public/assets/{reduce-uzWdoyL7.js → reduce-DAvwat-a.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DJQGrZPG.js → requirementDiagram-MS252O5E-DiDvQK3c.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-COGQTi7n.js +1 -0
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Ba8fGz96.js → sankeyDiagram-XADWPNL6-DWDQQZmd.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BmDPC7qx.js → sequenceDiagram-FGHM5R23-DmAqRlBT.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-1VkptYFz.js → stateDiagram-FHFEXIEX-D4R-n6bZ.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +1 -0
- package/payload/server/public/assets/tasks-B97VpwEJ.js +1 -0
- package/payload/server/public/assets/{time-entry-format-D477WAes.js → time-entry-format-C09rDHo9.js} +1 -1
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-B92U3T_f.js → timeline-definition-GMOUNBTQ-CjiHGP4l.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CSk9KjhY.js +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DLJFISqf.js +9 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-BKCWKo97.css → useSubAccountSwitcher-Dzmd7Aip.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-CZPtVpM-.js → useVoiceRecorder-DCyJQkFK.js} +2 -2
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-Y6Wkihrs.js → vennDiagram-DHZGUBPP-CBdDQ7c-.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-iJpfal2z.js → wardleyDiagram-NUSXRM2D-BlIQPKLb.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-S0bv7oH0.js → xychartDiagram-5P7HB3ND-CslKgh9B.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +13 -12
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +11 -10
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +15 -14
- package/payload/server/public/public.html +13 -12
- package/payload/server/public/tasks.html +5 -4
- package/payload/server/server.js +688 -539
- package/payload/server/public/assets/AdminShell-X9Bg3AKc.js +0 -2
- package/payload/server/public/assets/architecture-YZFGNWBL-Bbnxm4F4.js +0 -1
- package/payload/server/public/assets/browser-B0ieZy-b.js +0 -1
- package/payload/server/public/assets/calendar-CRL2_9Fl.js +0 -1
- package/payload/server/public/assets/channel-CatPTq-5.js +0 -1
- package/payload/server/public/assets/chat-DUc7bt5W.js +0 -1
- package/payload/server/public/assets/chevron-left-B2DKUxLk.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-CqLMwOdA.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CjWy8NJ7.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DHhR5rdN.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DH4pAdfu.js +0 -1
- package/payload/server/public/assets/clone-DCKzwjWW.js +0 -1
- package/payload/server/public/assets/data-C1ftMulP.js +0 -1
- package/payload/server/public/assets/file-download-CHTyUQqS.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-Ps5HDzLh.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-gtlpwIig.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-CPrWlrsa.js +0 -2
- package/payload/server/public/assets/operator-B3Mi3TW0.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DrSn1e0n.js +0 -1
- package/payload/server/public/assets/page-C1G57kPZ.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-C09i6N-g.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-CMZN2KQH.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdgkPHuh.js +0 -1
- package/payload/server/public/assets/tasks-0OcRiBdQ.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CeuUM5oL.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-C--fAaJv.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-CpfVOO26.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-Bo7bnFtC.js +0 -9
- package/payload/server/public/assets/wardley-RL74JXVD-4WPJ2UA9.js +0 -1
- /package/payload/server/public/assets/{_baseFor-Q4DeIqQC.js → _baseFor-D3BqAOBr.js} +0 -0
- /package/payload/server/public/assets/{array-WaOTgZu7.js → array-iYP9fzJp.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-CMmjo4hO.js → cytoscape.esm-BQSBzPsB.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-BxqJVxq5.js → defaultLocale-BrdA1gDi.js} +0 -0
- /package/payload/server/public/assets/{dist-Dx-cpU53.js → dist-Cvgxm7qv.js} +0 -0
- /package/payload/server/public/assets/{init-DX7c5Edh.js → init-Bx0S6pkp.js} +0 -0
- /package/payload/server/public/assets/{katex-B2dtGfSp.js → katex-BsiH_a6d.js} +0 -0
- /package/payload/server/public/assets/{path-CnSyroar.js → path-BLSgTy3w.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-DqboRNgS.js → preload-helper-ClBMtM1g.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-eLccZ4OJ.js → rough.esm-BMOtDaaS.js} +0 -0
- /package/payload/server/public/assets/{src-Dqs1wlnb.js → src-DV4LKv2E.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -127,8 +127,10 @@ var require_dist = __commonJS({
|
|
|
127
127
|
exports.cosine = cosine;
|
|
128
128
|
exports.deconflictBySubject = deconflictBySubject;
|
|
129
129
|
exports.formatStandingRulesBlock = formatStandingRulesBlock2;
|
|
130
|
+
exports.resolveOwnerUserId = resolveOwnerUserId;
|
|
130
131
|
exports.queryActiveRuleCandidates = queryActiveRuleCandidates;
|
|
131
|
-
exports.
|
|
132
|
+
exports.resolveActiveRules = resolveActiveRules2;
|
|
133
|
+
exports.activeRuleSet = activeRuleSet;
|
|
132
134
|
exports.SAME_SUBJECT_COSINE = 0.85;
|
|
133
135
|
exports.INJECTION_RULE_CAP = 12;
|
|
134
136
|
exports.ACTIVE_CANDIDATE_FLOOR = 0.4;
|
|
@@ -165,9 +167,20 @@ var require_dist = __commonJS({
|
|
|
165
167
|
return `## Standing rules
|
|
166
168
|
${lines.join("\n")}`;
|
|
167
169
|
}
|
|
168
|
-
async function
|
|
170
|
+
async function resolveOwnerUserId(session, accountId) {
|
|
171
|
+
const res = await session.run(`
|
|
172
|
+
MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
173
|
+
RETURN au.userId AS userId
|
|
174
|
+
ORDER BY au.createdAt ASC
|
|
175
|
+
LIMIT 1
|
|
176
|
+
`, { accountId });
|
|
177
|
+
const rec = res.records[0];
|
|
178
|
+
const userId = rec ? rec.get("userId") : null;
|
|
179
|
+
return typeof userId === "string" && userId.length > 0 ? userId : null;
|
|
180
|
+
}
|
|
181
|
+
async function queryOwnerCandidates(session, accountId, ownerUserId) {
|
|
169
182
|
const result = await session.run(`
|
|
170
|
-
MATCH (
|
|
183
|
+
MATCH (up:UserProfile {accountId: $accountId, userId: $ownerUserId})-[:HAS_PREFERENCE]->(pref:Preference {scope: 'admin'})
|
|
171
184
|
WHERE NOT pref:Trashed AND pref.deletedAt IS NULL
|
|
172
185
|
AND coalesce(pref.notApplicable, false) = false
|
|
173
186
|
AND pref.confidence >= $floor
|
|
@@ -176,7 +189,7 @@ ${lines.join("\n")}`;
|
|
|
176
189
|
pref.observedAt AS observedAt, pref.embedding AS embedding
|
|
177
190
|
ORDER BY pref.confidence DESC, pref.observedAt DESC
|
|
178
191
|
LIMIT ${exports.ACTIVE_CANDIDATE_LIMIT}
|
|
179
|
-
`, { accountId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
192
|
+
`, { accountId, ownerUserId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
180
193
|
return result.records.map((r) => ({
|
|
181
194
|
preferenceId: r.get("preferenceId"),
|
|
182
195
|
category: r.get("category"),
|
|
@@ -187,9 +200,27 @@ ${lines.join("\n")}`;
|
|
|
187
200
|
embedding: r.get("embedding") ?? null
|
|
188
201
|
}));
|
|
189
202
|
}
|
|
190
|
-
async function
|
|
191
|
-
|
|
192
|
-
|
|
203
|
+
async function resolveCandidates(session, accountId) {
|
|
204
|
+
let ownerUserId;
|
|
205
|
+
try {
|
|
206
|
+
ownerUserId = await resolveOwnerUserId(session, accountId);
|
|
207
|
+
} catch {
|
|
208
|
+
return { candidates: [], ownerUserId: null, source: "owner-error" };
|
|
209
|
+
}
|
|
210
|
+
if (!ownerUserId)
|
|
211
|
+
return { candidates: [], ownerUserId: null, source: "no-owner" };
|
|
212
|
+
const candidates = await queryOwnerCandidates(session, accountId, ownerUserId);
|
|
213
|
+
return { candidates, ownerUserId, source: "owner" };
|
|
214
|
+
}
|
|
215
|
+
async function queryActiveRuleCandidates(session, accountId) {
|
|
216
|
+
return (await resolveCandidates(session, accountId)).candidates;
|
|
217
|
+
}
|
|
218
|
+
async function resolveActiveRules2(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
219
|
+
const { candidates, ownerUserId, source } = await resolveCandidates(session, accountId);
|
|
220
|
+
return { rules: deconflictBySubject(candidates).slice(0, cap), ownerUserId, source };
|
|
221
|
+
}
|
|
222
|
+
async function activeRuleSet(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
223
|
+
return (await resolveActiveRules2(session, accountId, cap)).rules;
|
|
193
224
|
}
|
|
194
225
|
}
|
|
195
226
|
});
|
|
@@ -1384,11 +1415,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1384
1415
|
};
|
|
1385
1416
|
|
|
1386
1417
|
// server/index.ts
|
|
1387
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
1418
|
+
import { readFileSync as readFileSync35, existsSync as existsSync35, watchFile } from "fs";
|
|
1388
1419
|
import { spawn as spawn3 } from "child_process";
|
|
1389
1420
|
import { createHash as createHash7 } from "crypto";
|
|
1390
|
-
import { resolve as resolve33, join as
|
|
1391
|
-
import { homedir as
|
|
1421
|
+
import { resolve as resolve33, join as join36, basename as basename12 } from "path";
|
|
1422
|
+
import { homedir as homedir4 } from "os";
|
|
1392
1423
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1393
1424
|
|
|
1394
1425
|
// app/lib/pwa.ts
|
|
@@ -6137,8 +6168,8 @@ function webchatTurnTimeoutMs() {
|
|
|
6137
6168
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
6138
6169
|
}
|
|
6139
6170
|
function createChatRoutes(deps) {
|
|
6140
|
-
const
|
|
6141
|
-
|
|
6171
|
+
const app62 = new Hono();
|
|
6172
|
+
app62.post("/", async (c) => {
|
|
6142
6173
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
6143
6174
|
const contentType = c.req.header("content-type") ?? "";
|
|
6144
6175
|
const account = resolveAccount();
|
|
@@ -6401,7 +6432,7 @@ ${result.result.text}` : result.result.text;
|
|
|
6401
6432
|
}
|
|
6402
6433
|
});
|
|
6403
6434
|
});
|
|
6404
|
-
return
|
|
6435
|
+
return app62;
|
|
6405
6436
|
}
|
|
6406
6437
|
|
|
6407
6438
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -6436,8 +6467,8 @@ function isLoopbackAddr(addr) {
|
|
|
6436
6467
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
6437
6468
|
}
|
|
6438
6469
|
function createScheduleInjectRoutes(deps) {
|
|
6439
|
-
const
|
|
6440
|
-
|
|
6470
|
+
const app62 = new Hono();
|
|
6471
|
+
app62.post("/", async (c) => {
|
|
6441
6472
|
const env = c.env;
|
|
6442
6473
|
const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
|
|
6443
6474
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
@@ -6541,7 +6572,7 @@ function createScheduleInjectRoutes(deps) {
|
|
|
6541
6572
|
console.error(`${TAG16} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
|
|
6542
6573
|
return c.json({ ok: true }, 200);
|
|
6543
6574
|
});
|
|
6544
|
-
return
|
|
6575
|
+
return app62;
|
|
6545
6576
|
}
|
|
6546
6577
|
|
|
6547
6578
|
// server/index.ts
|
|
@@ -7562,6 +7593,9 @@ function reconcileCredsOnDisk(opts) {
|
|
|
7562
7593
|
function isReaderChannelSession(role, channel) {
|
|
7563
7594
|
return role === "admin" && (channel === "whatsapp" || channel === "telegram") || role === "public" && (channel === "whatsapp" || channel === "webchat");
|
|
7564
7595
|
}
|
|
7596
|
+
function isSessionListExcluded(role, channel) {
|
|
7597
|
+
return role === "public" && channel === "webchat";
|
|
7598
|
+
}
|
|
7565
7599
|
function selectReaderChannelSessions(rows) {
|
|
7566
7600
|
return rows.filter((r) => isReaderChannelSession(r.role, r.channel)).sort((a, b) => b.startedAt.localeCompare(a.startedAt)).map((r) => ({
|
|
7567
7601
|
sessionId: r.sessionId,
|
|
@@ -8162,12 +8196,37 @@ app2.get("/group-info", async (c) => {
|
|
|
8162
8196
|
var whatsapp_default = app2;
|
|
8163
8197
|
|
|
8164
8198
|
// server/routes/whatsapp-reader.ts
|
|
8165
|
-
import { readFileSync as readFileSync15, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as
|
|
8166
|
-
import { basename as
|
|
8199
|
+
import { readFileSync as readFileSync15, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as existsSync10, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
|
|
8200
|
+
import { basename as basename4, dirname as dirname4, isAbsolute, join as join15, relative as relative2, resolve as resolve12, sep as sep3 } from "path";
|
|
8201
|
+
|
|
8202
|
+
// server/routes/admin/sidebar-sessions.ts
|
|
8203
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync3 } from "fs";
|
|
8204
|
+
import { dirname as dirname3, join as join12, resolve as resolve11 } from "path";
|
|
8205
|
+
|
|
8206
|
+
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
8207
|
+
import { existsSync as existsSync8, readdirSync as readdirSync5 } from "fs";
|
|
8208
|
+
import { homedir } from "os";
|
|
8209
|
+
import { join as join11 } from "path";
|
|
8210
|
+
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
8211
|
+
const projectsRoot = join11(claudeConfigDir2, "projects");
|
|
8212
|
+
if (!existsSync8(projectsRoot)) return null;
|
|
8213
|
+
let slugs;
|
|
8214
|
+
try {
|
|
8215
|
+
slugs = readdirSync5(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8216
|
+
} catch {
|
|
8217
|
+
return null;
|
|
8218
|
+
}
|
|
8219
|
+
const basename13 = `${sessionId}.jsonl`;
|
|
8220
|
+
for (const slug of slugs) {
|
|
8221
|
+
const live = join11(projectsRoot, slug, basename13);
|
|
8222
|
+
if (existsSync8(live)) return live;
|
|
8223
|
+
const archived = join11(projectsRoot, slug, "archive", basename13);
|
|
8224
|
+
if (existsSync8(archived)) return archived;
|
|
8225
|
+
}
|
|
8226
|
+
return null;
|
|
8227
|
+
}
|
|
8167
8228
|
|
|
8168
8229
|
// server/routes/admin/sidebar-sessions.ts
|
|
8169
|
-
import { readdirSync as readdirSync5, readFileSync as readFileSync12, statSync as statSync3 } from "fs";
|
|
8170
|
-
import { basename as basename4, dirname as dirname3, join as join11, resolve as resolve11 } from "path";
|
|
8171
8230
|
var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
|
|
8172
8231
|
function lastAssistantModel(body) {
|
|
8173
8232
|
const lines = body.split("\n");
|
|
@@ -8196,25 +8255,23 @@ function claudeConfigDir() {
|
|
|
8196
8255
|
function findSessionProjectDir(sessionId) {
|
|
8197
8256
|
const cfg = claudeConfigDir();
|
|
8198
8257
|
if (!cfg) return null;
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
}
|
|
8202
|
-
return null;
|
|
8258
|
+
const jsonlPath = findExistingJsonlForSessionId(cfg, sessionId);
|
|
8259
|
+
return jsonlPath ? dirname3(jsonlPath) : null;
|
|
8203
8260
|
}
|
|
8204
8261
|
function enumerateJsonls(projectsRoot) {
|
|
8205
8262
|
const out = [];
|
|
8206
8263
|
let slugs;
|
|
8207
8264
|
try {
|
|
8208
|
-
slugs =
|
|
8265
|
+
slugs = readdirSync6(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8209
8266
|
} catch (err) {
|
|
8210
8267
|
if (err.code === "ENOENT") return out;
|
|
8211
8268
|
throw err;
|
|
8212
8269
|
}
|
|
8213
8270
|
for (const slug of slugs) {
|
|
8214
|
-
const slugDir =
|
|
8271
|
+
const slugDir = join12(projectsRoot, slug);
|
|
8215
8272
|
let entries;
|
|
8216
8273
|
try {
|
|
8217
|
-
entries =
|
|
8274
|
+
entries = readdirSync6(slugDir, { withFileTypes: true });
|
|
8218
8275
|
} catch (err) {
|
|
8219
8276
|
const code = err.code ?? "unknown";
|
|
8220
8277
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -8222,12 +8279,12 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8222
8279
|
}
|
|
8223
8280
|
for (const entry of entries) {
|
|
8224
8281
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
8225
|
-
out.push({ path:
|
|
8282
|
+
out.push({ path: join12(slugDir, entry.name), isSubagent: false, archived: false });
|
|
8226
8283
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
8227
|
-
const subDir =
|
|
8284
|
+
const subDir = join12(slugDir, entry.name);
|
|
8228
8285
|
let subEntries;
|
|
8229
8286
|
try {
|
|
8230
|
-
subEntries =
|
|
8287
|
+
subEntries = readdirSync6(subDir, { withFileTypes: true });
|
|
8231
8288
|
} catch (err) {
|
|
8232
8289
|
const code = err.code ?? "unknown";
|
|
8233
8290
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -8235,14 +8292,14 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8235
8292
|
}
|
|
8236
8293
|
for (const sub of subEntries) {
|
|
8237
8294
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
8238
|
-
out.push({ path:
|
|
8295
|
+
out.push({ path: join12(subDir, sub.name), isSubagent: true, archived: false });
|
|
8239
8296
|
}
|
|
8240
8297
|
}
|
|
8241
8298
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
8242
|
-
const archiveDir =
|
|
8299
|
+
const archiveDir = join12(slugDir, entry.name);
|
|
8243
8300
|
let archiveEntries;
|
|
8244
8301
|
try {
|
|
8245
|
-
archiveEntries =
|
|
8302
|
+
archiveEntries = readdirSync6(archiveDir, { withFileTypes: true });
|
|
8246
8303
|
} catch (err) {
|
|
8247
8304
|
const code = err.code ?? "unknown";
|
|
8248
8305
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -8250,7 +8307,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8250
8307
|
}
|
|
8251
8308
|
for (const arc of archiveEntries) {
|
|
8252
8309
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
8253
|
-
out.push({ path:
|
|
8310
|
+
out.push({ path: join12(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
8254
8311
|
}
|
|
8255
8312
|
}
|
|
8256
8313
|
}
|
|
@@ -8283,7 +8340,7 @@ async function fetchLiveSessions() {
|
|
|
8283
8340
|
function loadUserTitles(accountDir) {
|
|
8284
8341
|
const out = /* @__PURE__ */ new Map();
|
|
8285
8342
|
if (!accountDir) return out;
|
|
8286
|
-
const path2 =
|
|
8343
|
+
const path2 = join12(accountDir, "session-titles.json");
|
|
8287
8344
|
let raw;
|
|
8288
8345
|
try {
|
|
8289
8346
|
raw = readFileSync12(path2, "utf8");
|
|
@@ -8410,7 +8467,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8410
8467
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
8411
8468
|
return c.json({ sessions: [], accountId: scopeAccountId });
|
|
8412
8469
|
}
|
|
8413
|
-
const projectsRoot =
|
|
8470
|
+
const projectsRoot = join12(configDir2, "projects");
|
|
8414
8471
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
8415
8472
|
const liveSessions = await fetchLiveSessions();
|
|
8416
8473
|
const accountDir = scopeAccountId ? resolve11(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -8420,7 +8477,10 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8420
8477
|
let liveCount = 0;
|
|
8421
8478
|
let subagentCount = 0;
|
|
8422
8479
|
let archivedCount = 0;
|
|
8423
|
-
let
|
|
8480
|
+
let excludedPublicWebchatCount = 0;
|
|
8481
|
+
const channelInList = { whatsapp: 0, telegram: 0, webchat: 0 };
|
|
8482
|
+
const KNOWN_CHANNELS = /* @__PURE__ */ new Set(["browser", "whatsapp", "telegram", "webchat", "email"]);
|
|
8483
|
+
let unknownChannelCount = 0;
|
|
8424
8484
|
let untaggedCount = 0;
|
|
8425
8485
|
const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
|
|
8426
8486
|
const personIdBySession = /* @__PURE__ */ new Map();
|
|
@@ -8447,14 +8507,14 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8447
8507
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
8448
8508
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
8449
8509
|
titleSourceCounts[resolved.source] += 1;
|
|
8450
|
-
const metaPath =
|
|
8510
|
+
const metaPath = join12(projectDir, `${sessionId}.meta.json`);
|
|
8451
8511
|
const { bridgeIds, role, channel: sidecarChannel, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
8452
8512
|
if (multiAccount) {
|
|
8453
8513
|
if (rowAccountId === null) untaggedCount += 1;
|
|
8454
8514
|
if (rowAccountId !== scopeAccountId) continue;
|
|
8455
8515
|
}
|
|
8456
|
-
if (
|
|
8457
|
-
|
|
8516
|
+
if (isSessionListExcluded(role, sidecarChannel)) {
|
|
8517
|
+
excludedPublicWebchatCount += 1;
|
|
8458
8518
|
continue;
|
|
8459
8519
|
}
|
|
8460
8520
|
if (personId) personIdBySession.set(sessionId, personId);
|
|
@@ -8472,11 +8532,20 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8472
8532
|
projectDir,
|
|
8473
8533
|
bridgeIds,
|
|
8474
8534
|
archived,
|
|
8475
|
-
channel
|
|
8535
|
+
// Task 1566 — the row's channel is the authoritative `.meta.json` sidecar
|
|
8536
|
+
// value (whatsapp/telegram/webchat/browser/null), which drives the client
|
|
8537
|
+
// row colour and glyph. The JSONL-envelope channel (`resolved.channel`) is
|
|
8538
|
+
// no longer the row channel: it is null for browser/CLI rows and can
|
|
8539
|
+
// diverge from the sidecar (e.g. an ai-titled channel row).
|
|
8540
|
+
channel: sidecarChannel,
|
|
8476
8541
|
personName: null,
|
|
8477
8542
|
model: lastAssistantModel(body),
|
|
8478
8543
|
accountId: rowAccountId
|
|
8479
8544
|
});
|
|
8545
|
+
if (sidecarChannel === "whatsapp") channelInList.whatsapp += 1;
|
|
8546
|
+
else if (sidecarChannel === "telegram") channelInList.telegram += 1;
|
|
8547
|
+
else if (sidecarChannel === "webchat") channelInList.webchat += 1;
|
|
8548
|
+
if (sidecarChannel !== null && !KNOWN_CHANNELS.has(sidecarChannel)) unknownChannelCount += 1;
|
|
8480
8549
|
if (live) liveCount += 1;
|
|
8481
8550
|
if (isSubagent) subagentCount += 1;
|
|
8482
8551
|
if (archived) archivedCount += 1;
|
|
@@ -8509,7 +8578,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8509
8578
|
}
|
|
8510
8579
|
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
8511
8580
|
console.log(
|
|
8512
|
-
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount}
|
|
8581
|
+
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} channelInList=whatsapp:${channelInList.whatsapp},telegram:${channelInList.telegram},webchat:${channelInList.webchat} unknownChannel=${unknownChannelCount} excludedPublicWebchat=${excludedPublicWebchatCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"}`
|
|
8513
8582
|
);
|
|
8514
8583
|
console.log(
|
|
8515
8584
|
`[admin-sessions-list] accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"} scope=${multiAccount ? "scoped" : "all"} rows=${rows.length}`
|
|
@@ -8523,13 +8592,13 @@ var sidebar_sessions_default = app3;
|
|
|
8523
8592
|
|
|
8524
8593
|
// app/lib/admin-identity/pin-validator.ts
|
|
8525
8594
|
import { createHash as createHash3 } from "crypto";
|
|
8526
|
-
import { existsSync as
|
|
8527
|
-
import { join as
|
|
8595
|
+
import { existsSync as existsSync9, readFileSync as readFileSync13, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
8596
|
+
import { join as join13 } from "path";
|
|
8528
8597
|
function hashPin(pin) {
|
|
8529
8598
|
return createHash3("sha256").update(pin).digest("hex");
|
|
8530
8599
|
}
|
|
8531
8600
|
function readUsersFile(usersFilePath) {
|
|
8532
|
-
if (!
|
|
8601
|
+
if (!existsSync9(usersFilePath)) return null;
|
|
8533
8602
|
const raw = readFileSync13(usersFilePath, "utf-8").trim();
|
|
8534
8603
|
if (!raw) return [];
|
|
8535
8604
|
return JSON.parse(raw);
|
|
@@ -8829,8 +8898,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
8829
8898
|
}
|
|
8830
8899
|
|
|
8831
8900
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
8832
|
-
import { readFileSync as readFileSync14, readdirSync as
|
|
8833
|
-
import { join as
|
|
8901
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync8 } from "fs";
|
|
8902
|
+
import { join as join14 } from "path";
|
|
8834
8903
|
var ADMIN_UPLOAD_PATH = /\/uploads\/(?!public\/)([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})\//gi;
|
|
8835
8904
|
function adminAttachmentIds(text) {
|
|
8836
8905
|
const ids = [];
|
|
@@ -8843,7 +8912,7 @@ function adminAttachmentIds(text) {
|
|
|
8843
8912
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
8844
8913
|
const out = [];
|
|
8845
8914
|
for (const id of adminAttachmentIds(text)) {
|
|
8846
|
-
const meta = readAttachmentMeta(
|
|
8915
|
+
const meta = readAttachmentMeta(join14(uploadsBase, id));
|
|
8847
8916
|
if (meta) out.push(meta);
|
|
8848
8917
|
}
|
|
8849
8918
|
return out;
|
|
@@ -8851,7 +8920,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
8851
8920
|
function readSidecar(dir, attachmentId) {
|
|
8852
8921
|
let parsed;
|
|
8853
8922
|
try {
|
|
8854
|
-
parsed = JSON.parse(readFileSync14(
|
|
8923
|
+
parsed = JSON.parse(readFileSync14(join14(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
8855
8924
|
} catch {
|
|
8856
8925
|
return null;
|
|
8857
8926
|
}
|
|
@@ -8874,13 +8943,13 @@ function readAttachmentMeta(dir) {
|
|
|
8874
8943
|
function listSessionAttachmentsInDir(dir) {
|
|
8875
8944
|
let entries;
|
|
8876
8945
|
try {
|
|
8877
|
-
entries =
|
|
8946
|
+
entries = readdirSync8(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8878
8947
|
} catch {
|
|
8879
8948
|
return [];
|
|
8880
8949
|
}
|
|
8881
8950
|
const sidecars = [];
|
|
8882
8951
|
for (const name of entries) {
|
|
8883
|
-
const sidecar = readSidecar(
|
|
8952
|
+
const sidecar = readSidecar(join14(dir, name), name);
|
|
8884
8953
|
if (sidecar) sidecars.push(sidecar);
|
|
8885
8954
|
}
|
|
8886
8955
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -8945,14 +9014,14 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
8945
9014
|
}
|
|
8946
9015
|
const cfg = claudeConfigDir();
|
|
8947
9016
|
if (!cfg) return c.json({ conversations: [] });
|
|
8948
|
-
const projectsRoot =
|
|
9017
|
+
const projectsRoot = join15(cfg, "projects");
|
|
8949
9018
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
8950
9019
|
const rows = [];
|
|
8951
9020
|
let sessionRowsExcludedUntagged = 0;
|
|
8952
9021
|
for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
|
|
8953
|
-
const sessionId =
|
|
9022
|
+
const sessionId = basename4(path2).replace(/\.jsonl$/, "");
|
|
8954
9023
|
const projectDir = dirname4(path2);
|
|
8955
|
-
const meta = readSidecarMeta(
|
|
9024
|
+
const meta = readSidecarMeta(join15(projectDir, `${sessionId}.meta.json`));
|
|
8956
9025
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
8957
9026
|
if (multiAccount) {
|
|
8958
9027
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -9132,7 +9201,7 @@ function openTaskKey(turns) {
|
|
|
9132
9201
|
}
|
|
9133
9202
|
function readSubagentMeta(dir, hex) {
|
|
9134
9203
|
try {
|
|
9135
|
-
const m = JSON.parse(readFileSync15(
|
|
9204
|
+
const m = JSON.parse(readFileSync15(join15(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
9136
9205
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
9137
9206
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
9138
9207
|
}
|
|
@@ -9155,7 +9224,7 @@ function runActivityTick(c) {
|
|
|
9155
9224
|
c.parentGrewThisTick = false;
|
|
9156
9225
|
let names = [];
|
|
9157
9226
|
try {
|
|
9158
|
-
names =
|
|
9227
|
+
names = readdirSync9(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
9159
9228
|
} catch {
|
|
9160
9229
|
}
|
|
9161
9230
|
const entries = [];
|
|
@@ -9164,7 +9233,7 @@ function runActivityTick(c) {
|
|
|
9164
9233
|
let size = 0;
|
|
9165
9234
|
let mtimeMs = 0;
|
|
9166
9235
|
try {
|
|
9167
|
-
const st = statSync5(
|
|
9236
|
+
const st = statSync5(join15(c.subagentsDir, name));
|
|
9168
9237
|
size = st.size;
|
|
9169
9238
|
mtimeMs = st.mtimeMs;
|
|
9170
9239
|
} catch {
|
|
@@ -9209,11 +9278,11 @@ app4.get("/stream", requireAdminSession, (c) => {
|
|
|
9209
9278
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9210
9279
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
9211
9280
|
const cfg = claudeConfigDir();
|
|
9212
|
-
const projectsRoot = cfg ? resolve12(
|
|
9281
|
+
const projectsRoot = cfg ? resolve12(join15(cfg, "projects")) : null;
|
|
9213
9282
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
9214
9283
|
return c.json({ error: "bad session reference" }, 400);
|
|
9215
9284
|
}
|
|
9216
|
-
const jsonlPath = resolve12(
|
|
9285
|
+
const jsonlPath = resolve12(join15(projectDir, `${sessionId}.jsonl`));
|
|
9217
9286
|
if (!jsonlPath.startsWith(projectsRoot + sep3)) {
|
|
9218
9287
|
return c.json({ error: "bad session reference" }, 400);
|
|
9219
9288
|
}
|
|
@@ -9238,9 +9307,9 @@ data: ${JSON.stringify(turn)}
|
|
|
9238
9307
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
9239
9308
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
9240
9309
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
9241
|
-
const subagentsDir = resolve12(
|
|
9310
|
+
const subagentsDir = resolve12(join15(projectDir, sessionId, "subagents"));
|
|
9242
9311
|
console.log(
|
|
9243
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
9312
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync10(subagentsDir)}`
|
|
9244
9313
|
);
|
|
9245
9314
|
const actx = makeActivityCtx({
|
|
9246
9315
|
subagentsDir,
|
|
@@ -9347,10 +9416,10 @@ app4.get("/directives", requireAdminSession, (c) => {
|
|
|
9347
9416
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9348
9417
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
9349
9418
|
const dir = directiveStoreDir(sessionId);
|
|
9350
|
-
if (!dir || !
|
|
9419
|
+
if (!dir || !existsSync10(dir)) return c.json({ entries: [] });
|
|
9351
9420
|
let names;
|
|
9352
9421
|
try {
|
|
9353
|
-
names =
|
|
9422
|
+
names = readdirSync9(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
9354
9423
|
} catch {
|
|
9355
9424
|
return c.json({ entries: [] });
|
|
9356
9425
|
}
|
|
@@ -9360,7 +9429,7 @@ app4.get("/directives", requireAdminSession, (c) => {
|
|
|
9360
9429
|
const pid = Number(pidPart);
|
|
9361
9430
|
let len = 0;
|
|
9362
9431
|
try {
|
|
9363
|
-
len = statSync5(
|
|
9432
|
+
len = statSync5(join15(dir, name)).size;
|
|
9364
9433
|
} catch {
|
|
9365
9434
|
}
|
|
9366
9435
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -9375,7 +9444,7 @@ app4.get("/directive", requireAdminSession, (c) => {
|
|
|
9375
9444
|
}
|
|
9376
9445
|
const dir = directiveStoreDir(sessionId);
|
|
9377
9446
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
9378
|
-
const path2 = resolve12(
|
|
9447
|
+
const path2 = resolve12(join15(dir, name));
|
|
9379
9448
|
if (!path2.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
9380
9449
|
let body;
|
|
9381
9450
|
try {
|
|
@@ -9429,7 +9498,7 @@ app4.get("/store-stream", requireAdminSession, (c) => {
|
|
|
9429
9498
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
|
|
9430
9499
|
}
|
|
9431
9500
|
if (r.attachmentId) {
|
|
9432
|
-
const meta = readAttachmentMeta(
|
|
9501
|
+
const meta = readAttachmentMeta(join15(uploadsBase, r.attachmentId));
|
|
9433
9502
|
if (meta) return { ...turn, attachments: [meta] };
|
|
9434
9503
|
}
|
|
9435
9504
|
return turn;
|
|
@@ -9644,7 +9713,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9644
9713
|
}
|
|
9645
9714
|
if (size > MAX_FILE_BYTES) {
|
|
9646
9715
|
exit("rejected");
|
|
9647
|
-
return c.json({ error: `"${
|
|
9716
|
+
return c.json({ error: `"${basename4(absolute)}" exceeds the 50 MB limit` }, 400);
|
|
9648
9717
|
}
|
|
9649
9718
|
const mime = detectMimeType(absolute);
|
|
9650
9719
|
if (!isMimeAdmitted(mime, SUPPORTED_MIME_SET)) {
|
|
@@ -9736,7 +9805,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9736
9805
|
}
|
|
9737
9806
|
for (let i = 0; i < resolvedRefs.length; i++) {
|
|
9738
9807
|
const { absolute, mime } = resolvedRefs[i];
|
|
9739
|
-
const file = new File([readFileSync15(absolute)],
|
|
9808
|
+
const file = new File([readFileSync15(absolute)], basename4(absolute), { type: mime });
|
|
9740
9809
|
const out = await sendStagedFile(file, `ref=${i}`);
|
|
9741
9810
|
if (!out.ok) {
|
|
9742
9811
|
exit("error");
|
|
@@ -9755,8 +9824,8 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9755
9824
|
var whatsapp_reader_default = app4;
|
|
9756
9825
|
|
|
9757
9826
|
// server/routes/public-reader.ts
|
|
9758
|
-
import { statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync16, readdirSync as
|
|
9759
|
-
import { basename as
|
|
9827
|
+
import { statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync16, readdirSync as readdirSync10 } from "fs";
|
|
9828
|
+
import { basename as basename5, dirname as dirname5, join as join16, resolve as resolve13, sep as sep4 } from "path";
|
|
9760
9829
|
|
|
9761
9830
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
9762
9831
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -9830,10 +9899,10 @@ function enumeratePublicRows() {
|
|
|
9830
9899
|
const cfg = claudeConfigDir();
|
|
9831
9900
|
if (!cfg) return [];
|
|
9832
9901
|
const rows = [];
|
|
9833
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
9834
|
-
const sessionId =
|
|
9902
|
+
for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
|
|
9903
|
+
const sessionId = basename5(path2).replace(/\.jsonl$/, "");
|
|
9835
9904
|
const projectDir = dirname5(path2);
|
|
9836
|
-
const meta = readSidecarMeta(
|
|
9905
|
+
const meta = readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`));
|
|
9837
9906
|
rows.push({
|
|
9838
9907
|
sessionId,
|
|
9839
9908
|
projectDir,
|
|
@@ -9909,15 +9978,15 @@ app5.get("/stream", (c) => {
|
|
|
9909
9978
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9910
9979
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
9911
9980
|
const cfg = claudeConfigDir();
|
|
9912
|
-
const projectsRoot = cfg ? resolve13(
|
|
9981
|
+
const projectsRoot = cfg ? resolve13(join16(cfg, "projects")) : null;
|
|
9913
9982
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
9914
9983
|
return c.json({ error: "bad session reference" }, 400);
|
|
9915
9984
|
}
|
|
9916
|
-
const jsonlPath = resolve13(
|
|
9985
|
+
const jsonlPath = resolve13(join16(projectDir, `${sessionId}.jsonl`));
|
|
9917
9986
|
if (!jsonlPath.startsWith(projectsRoot + sep4)) {
|
|
9918
9987
|
return c.json({ error: "bad session reference" }, 400);
|
|
9919
9988
|
}
|
|
9920
|
-
const meta = readSidecarMeta(
|
|
9989
|
+
const meta = readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`));
|
|
9921
9990
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
9922
9991
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
9923
9992
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -10030,7 +10099,7 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10030
10099
|
let dataFile;
|
|
10031
10100
|
let buffer;
|
|
10032
10101
|
try {
|
|
10033
|
-
dataFile =
|
|
10102
|
+
dataFile = readdirSync10(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
10034
10103
|
if (!dataFile) throw new Error("no data file");
|
|
10035
10104
|
buffer = readFileSync16(resolve13(dir, dataFile));
|
|
10036
10105
|
} catch {
|
|
@@ -10050,17 +10119,17 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10050
10119
|
var public_reader_default = app5;
|
|
10051
10120
|
|
|
10052
10121
|
// server/routes/webchat.ts
|
|
10053
|
-
import { basename as
|
|
10054
|
-
import { join as
|
|
10055
|
-
import { existsSync as
|
|
10122
|
+
import { basename as basename6, dirname as dirname6 } from "path";
|
|
10123
|
+
import { join as join19 } from "path";
|
|
10124
|
+
import { existsSync as existsSync12, readdirSync as readdirSync12, readFileSync as readFileSync19, renameSync as renameSync4, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
10056
10125
|
|
|
10057
10126
|
// server/canonical-webchat-override.ts
|
|
10058
10127
|
import { readFileSync as readFileSync17, writeFileSync as writeFileSync5, renameSync as renameSync2 } from "fs";
|
|
10059
|
-
import { join as
|
|
10128
|
+
import { join as join17 } from "path";
|
|
10060
10129
|
var FILE = "canonical-webchat-session.json";
|
|
10061
10130
|
var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
10062
10131
|
function canonicalOverridePath(accountDir) {
|
|
10063
|
-
return
|
|
10132
|
+
return join17(accountDir, FILE);
|
|
10064
10133
|
}
|
|
10065
10134
|
function readRaw(accountDir) {
|
|
10066
10135
|
try {
|
|
@@ -10139,8 +10208,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
10139
10208
|
}
|
|
10140
10209
|
|
|
10141
10210
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
10142
|
-
import { existsSync as
|
|
10143
|
-
import { join as
|
|
10211
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as readdirSync11, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
10212
|
+
import { join as join18 } from "path";
|
|
10144
10213
|
function escapeRegExp(s) {
|
|
10145
10214
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10146
10215
|
}
|
|
@@ -10148,7 +10217,7 @@ function createSidecarStore(config) {
|
|
|
10148
10217
|
const { suffix, validate: validate2 } = config;
|
|
10149
10218
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
10150
10219
|
function pathFor(sessionsDir, id) {
|
|
10151
|
-
return
|
|
10220
|
+
return join18(sessionsDir, `${id}${suffix}`);
|
|
10152
10221
|
}
|
|
10153
10222
|
function write(sessionsDir, id, record) {
|
|
10154
10223
|
mkdirSync3(sessionsDir, { recursive: true });
|
|
@@ -10160,7 +10229,7 @@ function createSidecarStore(config) {
|
|
|
10160
10229
|
return { ok: true };
|
|
10161
10230
|
} catch (error) {
|
|
10162
10231
|
try {
|
|
10163
|
-
if (
|
|
10232
|
+
if (existsSync11(tmp)) unlinkSync2(tmp);
|
|
10164
10233
|
} catch {
|
|
10165
10234
|
}
|
|
10166
10235
|
return { ok: false, error };
|
|
@@ -10185,14 +10254,14 @@ function createSidecarStore(config) {
|
|
|
10185
10254
|
function readAll(sessionsDir, onSkip) {
|
|
10186
10255
|
let names;
|
|
10187
10256
|
try {
|
|
10188
|
-
names =
|
|
10257
|
+
names = readdirSync11(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
10189
10258
|
} catch {
|
|
10190
10259
|
return [];
|
|
10191
10260
|
}
|
|
10192
10261
|
const out = [];
|
|
10193
10262
|
for (const name of names) {
|
|
10194
10263
|
if (!suffixRe.test(name)) continue;
|
|
10195
|
-
const path2 =
|
|
10264
|
+
const path2 = join18(sessionsDir, name);
|
|
10196
10265
|
let raw;
|
|
10197
10266
|
try {
|
|
10198
10267
|
raw = readFileSync18(path2, "utf8");
|
|
@@ -10216,7 +10285,7 @@ function createSidecarStore(config) {
|
|
|
10216
10285
|
function clear(sessionsDir, id) {
|
|
10217
10286
|
const path2 = pathFor(sessionsDir, id);
|
|
10218
10287
|
try {
|
|
10219
|
-
if (
|
|
10288
|
+
if (existsSync11(path2)) {
|
|
10220
10289
|
unlinkSync2(path2);
|
|
10221
10290
|
return { ok: true, removed: true };
|
|
10222
10291
|
}
|
|
@@ -10269,22 +10338,22 @@ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9
|
|
|
10269
10338
|
function locateSession(sessionId) {
|
|
10270
10339
|
const dir = findSessionProjectDir(sessionId);
|
|
10271
10340
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
10272
|
-
const meta = readSidecarMeta(
|
|
10341
|
+
const meta = readSidecarMeta(join19(dir, `${sessionId}.meta.json`));
|
|
10273
10342
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
10274
10343
|
}
|
|
10275
10344
|
function locateSidecar(sessionId) {
|
|
10276
10345
|
const cfg = claudeConfigDir();
|
|
10277
10346
|
if (!cfg) return null;
|
|
10278
|
-
const projectsRoot =
|
|
10347
|
+
const projectsRoot = join19(cfg, "projects");
|
|
10279
10348
|
let slugs;
|
|
10280
10349
|
try {
|
|
10281
|
-
slugs =
|
|
10350
|
+
slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10282
10351
|
} catch {
|
|
10283
10352
|
return null;
|
|
10284
10353
|
}
|
|
10285
10354
|
for (const slug of slugs) {
|
|
10286
|
-
const metaPath =
|
|
10287
|
-
if (
|
|
10355
|
+
const metaPath = join19(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
10356
|
+
if (existsSync12(metaPath)) {
|
|
10288
10357
|
const meta = readSidecarMeta(metaPath);
|
|
10289
10358
|
return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
|
|
10290
10359
|
}
|
|
@@ -10296,7 +10365,7 @@ function readTargetOwner(sessionId) {
|
|
|
10296
10365
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
10297
10366
|
const { projectDir } = locateSession(sessionId);
|
|
10298
10367
|
if (projectDir !== null) {
|
|
10299
|
-
return { found: true, owner: readSidecarMeta(
|
|
10368
|
+
return { found: true, owner: readSidecarMeta(join19(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
10300
10369
|
}
|
|
10301
10370
|
return { found: false, owner: null };
|
|
10302
10371
|
}
|
|
@@ -10310,7 +10379,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
10310
10379
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
10311
10380
|
if (projectDir === null) return null;
|
|
10312
10381
|
try {
|
|
10313
|
-
return statSync7(
|
|
10382
|
+
return statSync7(join19(projectDir, `${sessionId}.jsonl`)).size;
|
|
10314
10383
|
} catch {
|
|
10315
10384
|
return null;
|
|
10316
10385
|
}
|
|
@@ -10446,10 +10515,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
10446
10515
|
const cfg = claudeConfigDir();
|
|
10447
10516
|
if (!cfg) return null;
|
|
10448
10517
|
let best = null;
|
|
10449
|
-
for (const { path: path2, isSubagent, archived } of enumerateJsonls(
|
|
10518
|
+
for (const { path: path2, isSubagent, archived } of enumerateJsonls(join19(cfg, "projects"))) {
|
|
10450
10519
|
if (isSubagent || archived) continue;
|
|
10451
|
-
const id =
|
|
10452
|
-
const meta = readSidecarMeta(
|
|
10520
|
+
const id = basename6(path2).slice(0, -".jsonl".length);
|
|
10521
|
+
const meta = readSidecarMeta(join19(dirname6(path2), `${id}.meta.json`));
|
|
10453
10522
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
10454
10523
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
10455
10524
|
let mtimeMs;
|
|
@@ -10472,7 +10541,7 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
10472
10541
|
function overrideKnownNonArchived(id) {
|
|
10473
10542
|
const { projectDir } = locateSession(id);
|
|
10474
10543
|
if (projectDir === null) return sessionSidecarExists(id);
|
|
10475
|
-
return
|
|
10544
|
+
return basename6(projectDir) !== "archive";
|
|
10476
10545
|
}
|
|
10477
10546
|
function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId, scopeAccountId, multiAccount) {
|
|
10478
10547
|
const bootstrapAccountId = scopeAccountId ?? accountId;
|
|
@@ -10508,8 +10577,8 @@ async function reapplyLeversViaManager() {
|
|
|
10508
10577
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
10509
10578
|
var sendSeq = 0;
|
|
10510
10579
|
function createWebchatRoutes(deps) {
|
|
10511
|
-
const
|
|
10512
|
-
|
|
10580
|
+
const app62 = new Hono();
|
|
10581
|
+
app62.post("/send", requireAdminSession, async (c) => {
|
|
10513
10582
|
let accountId;
|
|
10514
10583
|
try {
|
|
10515
10584
|
accountId = resolvePlatformAccountId();
|
|
@@ -10709,7 +10778,7 @@ ${note}` : note;
|
|
|
10709
10778
|
if (turnTimer.unref) turnTimer.unref();
|
|
10710
10779
|
return c.json({ ok: true });
|
|
10711
10780
|
});
|
|
10712
|
-
|
|
10781
|
+
app62.post("/interrupt", requireAdminSession, async (c) => {
|
|
10713
10782
|
const cacheKey = c.get("cacheKey");
|
|
10714
10783
|
const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
|
|
10715
10784
|
const primaryUserId = resolvePrimaryAdminUserId();
|
|
@@ -10737,7 +10806,7 @@ ${note}` : note;
|
|
|
10737
10806
|
}
|
|
10738
10807
|
return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
|
|
10739
10808
|
});
|
|
10740
|
-
|
|
10809
|
+
app62.post("/settings", requireAdminSession, async (c) => {
|
|
10741
10810
|
const body = await c.req.json().catch(() => null);
|
|
10742
10811
|
const op = body?.op;
|
|
10743
10812
|
const value = body?.value;
|
|
@@ -10759,7 +10828,7 @@ ${note}` : note;
|
|
|
10759
10828
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
10760
10829
|
return c.json({ error: "account unresolved" }, 503);
|
|
10761
10830
|
}
|
|
10762
|
-
const accountJsonPath =
|
|
10831
|
+
const accountJsonPath = join19(account.accountDir, "account.json");
|
|
10763
10832
|
try {
|
|
10764
10833
|
const parsed = JSON.parse(readFileSync19(accountJsonPath, "utf8"));
|
|
10765
10834
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -10777,7 +10846,7 @@ ${note}` : note;
|
|
|
10777
10846
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
10778
10847
|
return c.json({ ok: true, settingsApplied });
|
|
10779
10848
|
});
|
|
10780
|
-
|
|
10849
|
+
app62.get("/session", requireAdminSession, async (c) => {
|
|
10781
10850
|
let accountId;
|
|
10782
10851
|
try {
|
|
10783
10852
|
accountId = resolvePlatformAccountId();
|
|
@@ -10807,7 +10876,7 @@ ${note}` : note;
|
|
|
10807
10876
|
const cfg2 = claudeConfigDir();
|
|
10808
10877
|
if (cfg2) {
|
|
10809
10878
|
const source2 = resolveBridgeSource(
|
|
10810
|
-
|
|
10879
|
+
join19(cfg2, "sessions"),
|
|
10811
10880
|
target,
|
|
10812
10881
|
(id) => locateSession(id).projectDir !== null
|
|
10813
10882
|
);
|
|
@@ -10839,15 +10908,15 @@ ${note}` : note;
|
|
|
10839
10908
|
const cfg = claudeConfigDir();
|
|
10840
10909
|
let projectDir = null;
|
|
10841
10910
|
if (cfg) {
|
|
10842
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
10843
|
-
if (
|
|
10911
|
+
for (const { path: path2 } of enumerateJsonls(join19(cfg, "projects"))) {
|
|
10912
|
+
if (basename6(path2) === `${sessionId}.jsonl`) {
|
|
10844
10913
|
projectDir = dirname6(path2);
|
|
10845
10914
|
break;
|
|
10846
10915
|
}
|
|
10847
10916
|
}
|
|
10848
10917
|
}
|
|
10849
10918
|
if (source === "latest" && requesterUserId !== null) {
|
|
10850
|
-
const owner = readSidecarMeta(
|
|
10919
|
+
const owner = readSidecarMeta(join19(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
10851
10920
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
10852
10921
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
10853
10922
|
}
|
|
@@ -10855,7 +10924,7 @@ ${note}` : note;
|
|
|
10855
10924
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
10856
10925
|
return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
|
|
10857
10926
|
});
|
|
10858
|
-
|
|
10927
|
+
app62.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
10859
10928
|
const body = await c.req.json().catch(() => null);
|
|
10860
10929
|
const sessionId = body?.sessionId;
|
|
10861
10930
|
const requestId = body?.request_id;
|
|
@@ -10872,15 +10941,15 @@ ${note}` : note;
|
|
|
10872
10941
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
10873
10942
|
return c.json({ ok });
|
|
10874
10943
|
});
|
|
10875
|
-
return
|
|
10944
|
+
return app62;
|
|
10876
10945
|
}
|
|
10877
10946
|
|
|
10878
10947
|
// server/routes/webchat-greeting.ts
|
|
10879
10948
|
import { resolve as resolve14 } from "path";
|
|
10880
10949
|
|
|
10881
10950
|
// app/lib/claude-agent/specialist-roster.ts
|
|
10882
|
-
import { existsSync as
|
|
10883
|
-
import { join as
|
|
10951
|
+
import { existsSync as existsSync13, readFileSync as readFileSync20, readdirSync as readdirSync13 } from "fs";
|
|
10952
|
+
import { join as join20 } from "path";
|
|
10884
10953
|
function field(fm, name) {
|
|
10885
10954
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
10886
10955
|
if (!m) return null;
|
|
@@ -10891,15 +10960,15 @@ function field(fm, name) {
|
|
|
10891
10960
|
return value || null;
|
|
10892
10961
|
}
|
|
10893
10962
|
function readSpecialistRoster(specialistsDir) {
|
|
10894
|
-
if (!
|
|
10895
|
-
const entries =
|
|
10963
|
+
if (!existsSync13(specialistsDir)) return { specialists: [], skipped: [] };
|
|
10964
|
+
const entries = readdirSync13(specialistsDir);
|
|
10896
10965
|
const specialists = [];
|
|
10897
10966
|
const skipped = [];
|
|
10898
10967
|
for (const file of entries.sort()) {
|
|
10899
10968
|
if (!file.endsWith(".md")) continue;
|
|
10900
10969
|
let raw;
|
|
10901
10970
|
try {
|
|
10902
|
-
raw = readFileSync20(
|
|
10971
|
+
raw = readFileSync20(join20(specialistsDir, file), "utf-8");
|
|
10903
10972
|
} catch (err) {
|
|
10904
10973
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
10905
10974
|
continue;
|
|
@@ -11015,9 +11084,9 @@ function r2n(value) {
|
|
|
11015
11084
|
var webchat_greeting_default = app6;
|
|
11016
11085
|
|
|
11017
11086
|
// server/routes/telegram.ts
|
|
11018
|
-
import { homedir } from "os";
|
|
11019
|
-
import { resolve as resolve15, join as
|
|
11020
|
-
import { existsSync as
|
|
11087
|
+
import { homedir as homedir2 } from "os";
|
|
11088
|
+
import { resolve as resolve15, join as join21 } from "path";
|
|
11089
|
+
import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
|
|
11021
11090
|
|
|
11022
11091
|
// app/lib/telegram/gateway/instance.ts
|
|
11023
11092
|
var instance = null;
|
|
@@ -11076,8 +11145,8 @@ function routeTelegramUpdate(input) {
|
|
|
11076
11145
|
var TAG23 = "[telegram-inbound]";
|
|
11077
11146
|
function configDirName() {
|
|
11078
11147
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT ?? resolve15(process.cwd(), "..");
|
|
11079
|
-
const brandPath =
|
|
11080
|
-
if (
|
|
11148
|
+
const brandPath = join21(platformRoot3, "config", "brand.json");
|
|
11149
|
+
if (existsSync14(brandPath)) {
|
|
11081
11150
|
try {
|
|
11082
11151
|
return JSON.parse(readFileSync21(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
11083
11152
|
} catch {
|
|
@@ -11087,7 +11156,7 @@ function configDirName() {
|
|
|
11087
11156
|
}
|
|
11088
11157
|
function secretPath(botType) {
|
|
11089
11158
|
const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
|
|
11090
|
-
return resolve15(
|
|
11159
|
+
return resolve15(homedir2(), configDirName(), filename);
|
|
11091
11160
|
}
|
|
11092
11161
|
var app7 = new Hono();
|
|
11093
11162
|
app7.post("/", async (c) => {
|
|
@@ -11098,7 +11167,7 @@ app7.post("/", async (c) => {
|
|
|
11098
11167
|
return c.json({ ok: false }, 400);
|
|
11099
11168
|
}
|
|
11100
11169
|
const sp = secretPath(botType);
|
|
11101
|
-
if (!
|
|
11170
|
+
if (!existsSync14(sp)) {
|
|
11102
11171
|
console.error(`${TAG23} op=reject reason=no-secret-file botType=${botType}`);
|
|
11103
11172
|
return c.json({ ok: false }, 401);
|
|
11104
11173
|
}
|
|
@@ -11165,21 +11234,21 @@ app7.post("/", async (c) => {
|
|
|
11165
11234
|
var telegram_default = app7;
|
|
11166
11235
|
|
|
11167
11236
|
// server/routes/quickbooks.ts
|
|
11168
|
-
import { join as
|
|
11169
|
-
import { existsSync as
|
|
11237
|
+
import { join as join22 } from "path";
|
|
11238
|
+
import { existsSync as existsSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync5 } from "fs";
|
|
11170
11239
|
var TAG24 = "[quickbooks]";
|
|
11171
11240
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
11172
11241
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
11173
11242
|
function pendingPath(accountDir, state) {
|
|
11174
|
-
return
|
|
11243
|
+
return join22(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
11175
11244
|
}
|
|
11176
11245
|
function storePath(accountDir) {
|
|
11177
|
-
return
|
|
11246
|
+
return join22(accountDir, "secrets", "quickbooks.json");
|
|
11178
11247
|
}
|
|
11179
11248
|
async function completeConsent(args) {
|
|
11180
11249
|
const { accountDir, code, realmId } = args;
|
|
11181
11250
|
const state = args.state;
|
|
11182
|
-
if (!state || !STATE_RE.test(state) || !
|
|
11251
|
+
if (!state || !STATE_RE.test(state) || !existsSync15(pendingPath(accountDir, state))) {
|
|
11183
11252
|
console.error(`${TAG24} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
11184
11253
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
11185
11254
|
}
|
|
@@ -11206,7 +11275,7 @@ async function completeConsent(args) {
|
|
|
11206
11275
|
if (!code || !realmId) {
|
|
11207
11276
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
11208
11277
|
}
|
|
11209
|
-
if (!
|
|
11278
|
+
if (!existsSync15(storePath(accountDir))) {
|
|
11210
11279
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
11211
11280
|
}
|
|
11212
11281
|
const store2 = JSON.parse(readFileSync22(storePath(accountDir), "utf-8"));
|
|
@@ -11241,7 +11310,7 @@ async function completeConsent(args) {
|
|
|
11241
11310
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
11242
11311
|
lastRefresh: now
|
|
11243
11312
|
};
|
|
11244
|
-
mkdirSync4(
|
|
11313
|
+
mkdirSync4(join22(accountDir, "secrets"), { recursive: true });
|
|
11245
11314
|
writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
11246
11315
|
const persisted = JSON.parse(readFileSync22(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
11247
11316
|
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -11274,7 +11343,7 @@ var quickbooks_default = app8;
|
|
|
11274
11343
|
|
|
11275
11344
|
// server/routes/onboarding.ts
|
|
11276
11345
|
import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
|
|
11277
|
-
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as
|
|
11346
|
+
import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync17, readFileSync as readFileSync24, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
|
|
11278
11347
|
import { createHash as createHash4, randomUUID as randomUUID7 } from "crypto";
|
|
11279
11348
|
|
|
11280
11349
|
// app/lib/claude-spawn-env.ts
|
|
@@ -11283,7 +11352,7 @@ function claudeBin() {
|
|
|
11283
11352
|
}
|
|
11284
11353
|
|
|
11285
11354
|
// server/routes/onboarding.ts
|
|
11286
|
-
import { dirname as dirname8, join as
|
|
11355
|
+
import { dirname as dirname8, join as join24 } from "path";
|
|
11287
11356
|
|
|
11288
11357
|
// app/lib/claude-keychain.ts
|
|
11289
11358
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -11412,8 +11481,8 @@ function readHostCredsBlob(service) {
|
|
|
11412
11481
|
}
|
|
11413
11482
|
|
|
11414
11483
|
// ../lib/admins-write/src/index.ts
|
|
11415
|
-
import { existsSync as
|
|
11416
|
-
import { dirname as dirname7, join as
|
|
11484
|
+
import { existsSync as existsSync16, readFileSync as readFileSync23, writeFileSync as writeFileSync9, renameSync as renameSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync14, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
|
|
11485
|
+
import { dirname as dirname7, join as join23 } from "path";
|
|
11417
11486
|
function id8(value) {
|
|
11418
11487
|
return value.slice(0, 8);
|
|
11419
11488
|
}
|
|
@@ -11453,7 +11522,7 @@ function writeAdminEntry(input) {
|
|
|
11453
11522
|
const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
|
|
11454
11523
|
try {
|
|
11455
11524
|
let users = [];
|
|
11456
|
-
if (
|
|
11525
|
+
if (existsSync16(input.usersFile)) {
|
|
11457
11526
|
const raw = readFileSync23(input.usersFile, "utf-8").trim();
|
|
11458
11527
|
if (raw) {
|
|
11459
11528
|
const parsed = JSON.parse(raw);
|
|
@@ -11485,8 +11554,8 @@ function writeAdminEntry(input) {
|
|
|
11485
11554
|
return result;
|
|
11486
11555
|
}
|
|
11487
11556
|
try {
|
|
11488
|
-
const accountJsonPath =
|
|
11489
|
-
if (!
|
|
11557
|
+
const accountJsonPath = join23(input.accountDir, "account.json");
|
|
11558
|
+
if (!existsSync16(accountJsonPath)) {
|
|
11490
11559
|
throw new Error(`account.json not found at ${accountJsonPath}`);
|
|
11491
11560
|
}
|
|
11492
11561
|
const config = JSON.parse(readFileSync23(accountJsonPath, "utf-8"));
|
|
@@ -11509,7 +11578,7 @@ function writeAdminEntry(input) {
|
|
|
11509
11578
|
function computeAdminStoreDivergence(input) {
|
|
11510
11579
|
const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
|
|
11511
11580
|
const usersUserIds = /* @__PURE__ */ new Set();
|
|
11512
|
-
if (
|
|
11581
|
+
if (existsSync16(input.usersFile)) {
|
|
11513
11582
|
try {
|
|
11514
11583
|
const raw = readFileSync23(input.usersFile, "utf-8").trim();
|
|
11515
11584
|
if (raw) {
|
|
@@ -11523,24 +11592,24 @@ function computeAdminStoreDivergence(input) {
|
|
|
11523
11592
|
}
|
|
11524
11593
|
}
|
|
11525
11594
|
const accountUserIds = /* @__PURE__ */ new Set();
|
|
11526
|
-
if (
|
|
11595
|
+
if (existsSync16(input.accountsDir)) {
|
|
11527
11596
|
let entries;
|
|
11528
11597
|
try {
|
|
11529
|
-
entries =
|
|
11598
|
+
entries = readdirSync14(input.accountsDir);
|
|
11530
11599
|
} catch (err) {
|
|
11531
11600
|
result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
|
|
11532
11601
|
return result;
|
|
11533
11602
|
}
|
|
11534
11603
|
for (const entry of entries) {
|
|
11535
11604
|
if (entry.startsWith(".")) continue;
|
|
11536
|
-
const accountDir =
|
|
11605
|
+
const accountDir = join23(input.accountsDir, entry);
|
|
11537
11606
|
try {
|
|
11538
11607
|
if (!statSync8(accountDir).isDirectory()) continue;
|
|
11539
11608
|
} catch {
|
|
11540
11609
|
continue;
|
|
11541
11610
|
}
|
|
11542
|
-
const accountJsonPath =
|
|
11543
|
-
if (!
|
|
11611
|
+
const accountJsonPath = join23(accountDir, "account.json");
|
|
11612
|
+
if (!existsSync16(accountJsonPath)) continue;
|
|
11544
11613
|
let admins = [];
|
|
11545
11614
|
try {
|
|
11546
11615
|
const config = JSON.parse(readFileSync23(accountJsonPath, "utf-8"));
|
|
@@ -11591,7 +11660,7 @@ function hashPin2(pin) {
|
|
|
11591
11660
|
return createHash4("sha256").update(pin).digest("hex");
|
|
11592
11661
|
}
|
|
11593
11662
|
function readUsersFile2() {
|
|
11594
|
-
if (!
|
|
11663
|
+
if (!existsSync17(USERS_FILE)) return null;
|
|
11595
11664
|
const raw = readFileSync24(USERS_FILE, "utf-8").trim();
|
|
11596
11665
|
if (!raw) return [];
|
|
11597
11666
|
return JSON.parse(raw);
|
|
@@ -11651,7 +11720,7 @@ app9.post("/claude-auth", async (c) => {
|
|
|
11651
11720
|
} catch (err) {
|
|
11652
11721
|
logoutError = err instanceof Error ? err.message : String(err);
|
|
11653
11722
|
}
|
|
11654
|
-
const credentialsPresent =
|
|
11723
|
+
const credentialsPresent = existsSync17(CLAUDE_CREDENTIALS_FILE);
|
|
11655
11724
|
const ranMs = Date.now() - start;
|
|
11656
11725
|
console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
|
|
11657
11726
|
return c.json({ logged_out: !credentialsPresent });
|
|
@@ -11717,7 +11786,7 @@ app9.post("/claude-auth", async (c) => {
|
|
|
11717
11786
|
});
|
|
11718
11787
|
persistKeychainService(
|
|
11719
11788
|
writebackResult,
|
|
11720
|
-
(service) => writeFileSync10(
|
|
11789
|
+
(service) => writeFileSync10(join24(dirname8(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
|
|
11721
11790
|
(line) => console.log(line)
|
|
11722
11791
|
);
|
|
11723
11792
|
if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
|
|
@@ -11800,7 +11869,7 @@ app9.post("/set-pin", async (c) => {
|
|
|
11800
11869
|
console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
|
|
11801
11870
|
if (process.platform === "linux") {
|
|
11802
11871
|
let installOwner = null;
|
|
11803
|
-
if (
|
|
11872
|
+
if (existsSync17(INSTALL_OWNER_FILE)) {
|
|
11804
11873
|
try {
|
|
11805
11874
|
const raw = readFileSync24(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
11806
11875
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -11948,7 +12017,7 @@ app9.put("/set-pin", requireAdminSession, async (c) => {
|
|
|
11948
12017
|
console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
|
|
11949
12018
|
if (process.platform === "linux") {
|
|
11950
12019
|
let installOwner = null;
|
|
11951
|
-
if (
|
|
12020
|
+
if (existsSync17(INSTALL_OWNER_FILE)) {
|
|
11952
12021
|
try {
|
|
11953
12022
|
const raw = readFileSync24(INSTALL_OWNER_FILE, "utf-8").trim();
|
|
11954
12023
|
if (raw.length > 0) installOwner = raw;
|
|
@@ -11982,9 +12051,9 @@ ${body.newPin}
|
|
|
11982
12051
|
var onboarding_default = app9;
|
|
11983
12052
|
|
|
11984
12053
|
// server/routes/client-error.ts
|
|
11985
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
11986
|
-
import { join as
|
|
11987
|
-
var CLIENT_ERRORS_LOG =
|
|
12054
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync18, renameSync as renameSync8, statSync as statSync9 } from "fs";
|
|
12055
|
+
import { join as join25 } from "path";
|
|
12056
|
+
var CLIENT_ERRORS_LOG = join25(LOG_DIR, "client-errors.log");
|
|
11988
12057
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
11989
12058
|
var MAX_BODY_SIZE = 8 * 1024;
|
|
11990
12059
|
var MAX_STACK_LEN = 2e3;
|
|
@@ -12032,7 +12101,7 @@ function stackHead(stack) {
|
|
|
12032
12101
|
}
|
|
12033
12102
|
function rotateIfNeeded() {
|
|
12034
12103
|
try {
|
|
12035
|
-
if (!
|
|
12104
|
+
if (!existsSync18(CLIENT_ERRORS_LOG)) return;
|
|
12036
12105
|
const stats = statSync9(CLIENT_ERRORS_LOG);
|
|
12037
12106
|
if (stats.size < MAX_LOG_SIZE) return;
|
|
12038
12107
|
renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
|
|
@@ -12352,18 +12421,18 @@ app12.get("/", requireAdminSession, async (c) => {
|
|
|
12352
12421
|
var accounts_default = app12;
|
|
12353
12422
|
|
|
12354
12423
|
// server/routes/admin/logs.ts
|
|
12355
|
-
import { existsSync as
|
|
12356
|
-
import { resolve as resolve16, basename as
|
|
12424
|
+
import { existsSync as existsSync20, readdirSync as readdirSync15, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
|
|
12425
|
+
import { resolve as resolve16, basename as basename7 } from "path";
|
|
12357
12426
|
|
|
12358
12427
|
// app/lib/logs-read-resolve.ts
|
|
12359
|
-
import { existsSync as
|
|
12360
|
-
import { join as
|
|
12428
|
+
import { existsSync as existsSync19 } from "fs";
|
|
12429
|
+
import { join as join26 } from "path";
|
|
12361
12430
|
function resolveSessionLogPaths(filename, logDirs) {
|
|
12362
12431
|
const tried = [filename];
|
|
12363
12432
|
const hits = [];
|
|
12364
12433
|
for (const dir of logDirs) {
|
|
12365
|
-
const fullPath =
|
|
12366
|
-
if (
|
|
12434
|
+
const fullPath = join26(dir, filename);
|
|
12435
|
+
if (existsSync19(fullPath)) {
|
|
12367
12436
|
hits.push({ path: fullPath, dir });
|
|
12368
12437
|
}
|
|
12369
12438
|
}
|
|
@@ -12385,7 +12454,7 @@ app13.get("/", async (c) => {
|
|
|
12385
12454
|
if (accountLogDir) logDirs.push(accountLogDir);
|
|
12386
12455
|
logDirs.push(LOG_DIR);
|
|
12387
12456
|
if (fileParam) {
|
|
12388
|
-
const safe =
|
|
12457
|
+
const safe = basename7(fileParam);
|
|
12389
12458
|
const searched = [];
|
|
12390
12459
|
for (const dir of logDirs) {
|
|
12391
12460
|
const filePath = resolve16(dir, safe);
|
|
@@ -12455,7 +12524,7 @@ app13.get("/", async (c) => {
|
|
|
12455
12524
|
if (hit) {
|
|
12456
12525
|
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
|
|
12457
12526
|
try {
|
|
12458
|
-
const filename =
|
|
12527
|
+
const filename = basename7(hit.path);
|
|
12459
12528
|
const buffer = readFileSync25(hit.path);
|
|
12460
12529
|
const onDiskBytes = statSync10(hit.path).size;
|
|
12461
12530
|
const headers = {
|
|
@@ -12491,10 +12560,10 @@ app13.get("/", async (c) => {
|
|
|
12491
12560
|
const seen = /* @__PURE__ */ new Set();
|
|
12492
12561
|
const logs = {};
|
|
12493
12562
|
for (const dir of logDirs) {
|
|
12494
|
-
if (!
|
|
12563
|
+
if (!existsSync20(dir)) continue;
|
|
12495
12564
|
let files;
|
|
12496
12565
|
try {
|
|
12497
|
-
files =
|
|
12566
|
+
files = readdirSync15(dir).filter((f) => f.endsWith(".log"));
|
|
12498
12567
|
} catch (err) {
|
|
12499
12568
|
const reason = err instanceof Error ? err.message : String(err);
|
|
12500
12569
|
console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
|
|
@@ -12543,7 +12612,7 @@ var claude_info_default = app14;
|
|
|
12543
12612
|
|
|
12544
12613
|
// server/routes/admin/attachment.ts
|
|
12545
12614
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
12546
|
-
import { existsSync as
|
|
12615
|
+
import { existsSync as existsSync21 } from "fs";
|
|
12547
12616
|
import { resolve as resolve17 } from "path";
|
|
12548
12617
|
var app15 = new Hono();
|
|
12549
12618
|
var ATTACHMENT_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -12566,12 +12635,12 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
12566
12635
|
}
|
|
12567
12636
|
let accountId = pinnedAccountId;
|
|
12568
12637
|
let dir = uploadsDirFor2(accountId, attachmentId);
|
|
12569
|
-
let found =
|
|
12638
|
+
let found = existsSync21(dir);
|
|
12570
12639
|
if (!found) {
|
|
12571
12640
|
for (const candidate of listValidAccounts()) {
|
|
12572
12641
|
if (candidate.accountId === pinnedAccountId) continue;
|
|
12573
12642
|
const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
|
|
12574
|
-
if (
|
|
12643
|
+
if (existsSync21(candidateDir)) {
|
|
12575
12644
|
accountId = candidate.accountId;
|
|
12576
12645
|
dir = candidateDir;
|
|
12577
12646
|
found = true;
|
|
@@ -12586,7 +12655,7 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
12586
12655
|
return new Response("Not found", { status: 404 });
|
|
12587
12656
|
}
|
|
12588
12657
|
const metaPath = resolve17(dir, `${attachmentId}.meta.json`);
|
|
12589
|
-
if (!
|
|
12658
|
+
if (!existsSync21(metaPath)) {
|
|
12590
12659
|
return new Response("Not found", { status: 404 });
|
|
12591
12660
|
}
|
|
12592
12661
|
let meta;
|
|
@@ -12614,21 +12683,21 @@ var attachment_default = app15;
|
|
|
12614
12683
|
|
|
12615
12684
|
// server/routes/admin/agents.ts
|
|
12616
12685
|
import { resolve as resolve18 } from "path";
|
|
12617
|
-
import { readdirSync as
|
|
12686
|
+
import { readdirSync as readdirSync16, readFileSync as readFileSync26, existsSync as existsSync22, rmSync as rmSync2 } from "fs";
|
|
12618
12687
|
var app16 = new Hono();
|
|
12619
12688
|
app16.get("/", (c) => {
|
|
12620
12689
|
const account = resolveAccount();
|
|
12621
12690
|
if (!account) return c.json({ agents: [] });
|
|
12622
12691
|
const agentsDir = resolve18(account.accountDir, "agents");
|
|
12623
|
-
if (!
|
|
12692
|
+
if (!existsSync22(agentsDir)) return c.json({ agents: [] });
|
|
12624
12693
|
const agents = [];
|
|
12625
12694
|
try {
|
|
12626
|
-
const entries =
|
|
12695
|
+
const entries = readdirSync16(agentsDir, { withFileTypes: true });
|
|
12627
12696
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
12628
12697
|
if (!entry.isDirectory()) continue;
|
|
12629
12698
|
if (entry.name === "admin") continue;
|
|
12630
12699
|
const configPath2 = resolve18(agentsDir, entry.name, "config.json");
|
|
12631
|
-
if (!
|
|
12700
|
+
if (!existsSync22(configPath2)) continue;
|
|
12632
12701
|
try {
|
|
12633
12702
|
const config = JSON.parse(readFileSync26(configPath2, "utf-8"));
|
|
12634
12703
|
agents.push({
|
|
@@ -12657,7 +12726,7 @@ app16.delete("/:slug", async (c) => {
|
|
|
12657
12726
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
12658
12727
|
}
|
|
12659
12728
|
const agentDir = resolve18(account.accountDir, "agents", slug);
|
|
12660
|
-
if (!
|
|
12729
|
+
if (!existsSync22(agentDir)) {
|
|
12661
12730
|
return c.json({ error: "Agent not found" }, 404);
|
|
12662
12731
|
}
|
|
12663
12732
|
try {
|
|
@@ -12687,7 +12756,7 @@ app16.post("/:slug/project", async (c) => {
|
|
|
12687
12756
|
return c.json({ error: "Invalid agent slug" }, 400);
|
|
12688
12757
|
}
|
|
12689
12758
|
const agentDir = resolve18(account.accountDir, "agents", slug);
|
|
12690
|
-
if (!
|
|
12759
|
+
if (!existsSync22(agentDir)) {
|
|
12691
12760
|
return c.json({ error: "Agent not found on disk" }, 404);
|
|
12692
12761
|
}
|
|
12693
12762
|
try {
|
|
@@ -12703,7 +12772,7 @@ var agents_default = app16;
|
|
|
12703
12772
|
// server/routes/admin/sessions.ts
|
|
12704
12773
|
import crypto2 from "crypto";
|
|
12705
12774
|
import { resolve as resolvePath } from "path";
|
|
12706
|
-
import { existsSync as
|
|
12775
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync6, createWriteStream } from "fs";
|
|
12707
12776
|
|
|
12708
12777
|
// ../lib/admin-conversation-purge/src/index.ts
|
|
12709
12778
|
async function purgeAdminConversationJsonls(args) {
|
|
@@ -12841,7 +12910,7 @@ var replayJsonl = (..._args) => null;
|
|
|
12841
12910
|
var resolveJsonlPath = (..._args) => null;
|
|
12842
12911
|
|
|
12843
12912
|
// server/routes/admin/sessions.ts
|
|
12844
|
-
import { homedir as
|
|
12913
|
+
import { homedir as homedir3 } from "os";
|
|
12845
12914
|
|
|
12846
12915
|
// app/lib/claude-agent/component-attachment.ts
|
|
12847
12916
|
var pickComponentBytes = (..._args) => null;
|
|
@@ -12863,7 +12932,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
|
|
|
12863
12932
|
let reason = null;
|
|
12864
12933
|
if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
|
|
12865
12934
|
else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
|
|
12866
|
-
else if (!
|
|
12935
|
+
else if (!existsSync23(a.storagePath)) reason = "missing-file";
|
|
12867
12936
|
if (reason) {
|
|
12868
12937
|
invalid++;
|
|
12869
12938
|
try {
|
|
@@ -13156,7 +13225,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
13156
13225
|
return c.json({ error: "Failed to load conversation messages" }, 500);
|
|
13157
13226
|
}
|
|
13158
13227
|
if (persistedAgentSessionId) {
|
|
13159
|
-
const jsonlPath = resolveJsonlPath(
|
|
13228
|
+
const jsonlPath = resolveJsonlPath(homedir3(), resolvePath(ACCOUNTS_DIR, accountId), persistedAgentSessionId);
|
|
13160
13229
|
const replay = replayJsonl(jsonlPath);
|
|
13161
13230
|
jsonlMissing = replay.jsonlMissing;
|
|
13162
13231
|
jsonlMalformedLines = replay.malformedLines;
|
|
@@ -13389,8 +13458,8 @@ app17.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
13389
13458
|
var sessions_default = app17;
|
|
13390
13459
|
|
|
13391
13460
|
// app/lib/claude-agent/spawn-context.ts
|
|
13392
|
-
import { existsSync as
|
|
13393
|
-
import { dirname as dirname9, resolve as resolve19, join as
|
|
13461
|
+
import { existsSync as existsSync24, readFileSync as readFileSync27, readdirSync as readdirSync17, statSync as statSync11 } from "fs";
|
|
13462
|
+
import { dirname as dirname9, resolve as resolve19, join as join27 } from "path";
|
|
13394
13463
|
async function resolveOwnerProfileBlock(accountId, userId) {
|
|
13395
13464
|
if (!userId) return { ok: false, reason: "missing-user-id" };
|
|
13396
13465
|
try {
|
|
@@ -13431,12 +13500,12 @@ function frontmatterField(manifest, field2) {
|
|
|
13431
13500
|
function extractPluginToolDescriptions(pluginDir) {
|
|
13432
13501
|
const out = /* @__PURE__ */ new Map();
|
|
13433
13502
|
const candidates = [
|
|
13434
|
-
|
|
13435
|
-
|
|
13503
|
+
join27(pluginDir, "mcp/dist/index.js"),
|
|
13504
|
+
join27(pluginDir, "mcp/src/index.ts")
|
|
13436
13505
|
];
|
|
13437
13506
|
let raw = null;
|
|
13438
13507
|
for (const path2 of candidates) {
|
|
13439
|
-
if (!
|
|
13508
|
+
if (!existsSync24(path2)) continue;
|
|
13440
13509
|
try {
|
|
13441
13510
|
raw = readFileSync27(path2, "utf-8");
|
|
13442
13511
|
break;
|
|
@@ -13488,9 +13557,9 @@ function parseSkillPathsFromFrontmatter(fm) {
|
|
|
13488
13557
|
function listPluginDirs() {
|
|
13489
13558
|
const out = /* @__PURE__ */ new Map();
|
|
13490
13559
|
const platformPlugins = resolve19(PLATFORM_ROOT, "plugins");
|
|
13491
|
-
if (
|
|
13492
|
-
for (const name of
|
|
13493
|
-
const dir =
|
|
13560
|
+
if (existsSync24(platformPlugins)) {
|
|
13561
|
+
for (const name of readdirSync17(platformPlugins)) {
|
|
13562
|
+
const dir = join27(platformPlugins, name);
|
|
13494
13563
|
try {
|
|
13495
13564
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
13496
13565
|
} catch {
|
|
@@ -13498,13 +13567,13 @@ function listPluginDirs() {
|
|
|
13498
13567
|
}
|
|
13499
13568
|
}
|
|
13500
13569
|
const premiumRoot = resolve19(dirname9(PLATFORM_ROOT), "premium-plugins");
|
|
13501
|
-
if (
|
|
13502
|
-
for (const bundle of
|
|
13503
|
-
const bundlePlugins =
|
|
13504
|
-
if (!
|
|
13570
|
+
if (existsSync24(premiumRoot)) {
|
|
13571
|
+
for (const bundle of readdirSync17(premiumRoot)) {
|
|
13572
|
+
const bundlePlugins = join27(premiumRoot, bundle, "plugins");
|
|
13573
|
+
if (!existsSync24(bundlePlugins)) continue;
|
|
13505
13574
|
try {
|
|
13506
|
-
for (const name of
|
|
13507
|
-
const dir =
|
|
13575
|
+
for (const name of readdirSync17(bundlePlugins)) {
|
|
13576
|
+
const dir = join27(bundlePlugins, name);
|
|
13508
13577
|
try {
|
|
13509
13578
|
if (statSync11(dir).isDirectory()) out.set(name, dir);
|
|
13510
13579
|
} catch {
|
|
@@ -13518,7 +13587,7 @@ function listPluginDirs() {
|
|
|
13518
13587
|
}
|
|
13519
13588
|
function readEnabledPlugins(accountId) {
|
|
13520
13589
|
const accountFile = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
13521
|
-
if (!
|
|
13590
|
+
if (!existsSync24(accountFile)) return /* @__PURE__ */ new Set();
|
|
13522
13591
|
try {
|
|
13523
13592
|
const parsed = JSON.parse(readFileSync27(accountFile, "utf-8"));
|
|
13524
13593
|
return new Set(
|
|
@@ -13529,7 +13598,7 @@ function readEnabledPlugins(accountId) {
|
|
|
13529
13598
|
}
|
|
13530
13599
|
}
|
|
13531
13600
|
function readFrontmatter(path2) {
|
|
13532
|
-
if (!
|
|
13601
|
+
if (!existsSync24(path2)) return null;
|
|
13533
13602
|
let raw;
|
|
13534
13603
|
try {
|
|
13535
13604
|
raw = readFileSync27(path2, "utf-8");
|
|
@@ -13547,7 +13616,7 @@ function computeActivePlugins(accountId) {
|
|
|
13547
13616
|
for (const name of Array.from(enabled).sort()) {
|
|
13548
13617
|
const dir = pluginDirs.get(name);
|
|
13549
13618
|
if (!dir) continue;
|
|
13550
|
-
const fm = readFrontmatter(
|
|
13619
|
+
const fm = readFrontmatter(join27(dir, "PLUGIN.md"));
|
|
13551
13620
|
if (!fm) continue;
|
|
13552
13621
|
const description = frontmatterField(`---
|
|
13553
13622
|
${fm}
|
|
@@ -13564,7 +13633,7 @@ ${fm}
|
|
|
13564
13633
|
`plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
|
|
13565
13634
|
);
|
|
13566
13635
|
if (toolNames.length > 0 && descMap.size === 0) {
|
|
13567
|
-
const hasSource =
|
|
13636
|
+
const hasSource = existsSync24(join27(dir, "mcp/dist/index.js")) || existsSync24(join27(dir, "mcp/src/index.ts"));
|
|
13568
13637
|
if (hasSource) {
|
|
13569
13638
|
console.warn(
|
|
13570
13639
|
`[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
|
|
@@ -13574,7 +13643,7 @@ ${fm}
|
|
|
13574
13643
|
const skillPaths = parseSkillPathsFromFrontmatter(fm);
|
|
13575
13644
|
const skills = [];
|
|
13576
13645
|
for (const relPath of skillPaths) {
|
|
13577
|
-
const skillPath =
|
|
13646
|
+
const skillPath = join27(dir, relPath);
|
|
13578
13647
|
const skillFm = readFrontmatter(skillPath);
|
|
13579
13648
|
if (!skillFm) continue;
|
|
13580
13649
|
const skillName = frontmatterField(`---
|
|
@@ -13591,10 +13660,10 @@ ${skillFm}
|
|
|
13591
13660
|
}
|
|
13592
13661
|
function computeSpecialistDomains(accountId) {
|
|
13593
13662
|
const specialistsDir = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
|
|
13594
|
-
if (!
|
|
13663
|
+
if (!existsSync24(specialistsDir)) return [];
|
|
13595
13664
|
let entries;
|
|
13596
13665
|
try {
|
|
13597
|
-
entries =
|
|
13666
|
+
entries = readdirSync17(specialistsDir);
|
|
13598
13667
|
} catch {
|
|
13599
13668
|
return [];
|
|
13600
13669
|
}
|
|
@@ -13618,7 +13687,7 @@ function computeSpecialistDomains(accountId) {
|
|
|
13618
13687
|
const out = [];
|
|
13619
13688
|
for (const file of entries.sort()) {
|
|
13620
13689
|
if (!file.endsWith(".md")) continue;
|
|
13621
|
-
const fm = readFrontmatter(
|
|
13690
|
+
const fm = readFrontmatter(join27(specialistsDir, file));
|
|
13622
13691
|
if (!fm) continue;
|
|
13623
13692
|
const wrapped = `---
|
|
13624
13693
|
${fm}
|
|
@@ -13637,7 +13706,7 @@ ${fm}
|
|
|
13637
13706
|
}
|
|
13638
13707
|
function computeDormantPlugins(accountId) {
|
|
13639
13708
|
const accountFile = resolve19(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
|
|
13640
|
-
if (!
|
|
13709
|
+
if (!existsSync24(accountFile)) return [];
|
|
13641
13710
|
let enabled;
|
|
13642
13711
|
try {
|
|
13643
13712
|
const raw = readFileSync27(accountFile, "utf-8");
|
|
@@ -13652,10 +13721,10 @@ function computeDormantPlugins(accountId) {
|
|
|
13652
13721
|
return [];
|
|
13653
13722
|
}
|
|
13654
13723
|
const pluginsDir = resolve19(PLATFORM_ROOT, "plugins");
|
|
13655
|
-
if (!
|
|
13724
|
+
if (!existsSync24(pluginsDir)) return [];
|
|
13656
13725
|
let entries;
|
|
13657
13726
|
try {
|
|
13658
|
-
entries =
|
|
13727
|
+
entries = readdirSync17(pluginsDir);
|
|
13659
13728
|
} catch {
|
|
13660
13729
|
return [];
|
|
13661
13730
|
}
|
|
@@ -13663,7 +13732,7 @@ function computeDormantPlugins(accountId) {
|
|
|
13663
13732
|
for (const name of entries) {
|
|
13664
13733
|
if (enabled.has(name)) continue;
|
|
13665
13734
|
const manifestPath = resolve19(pluginsDir, name, "PLUGIN.md");
|
|
13666
|
-
if (!
|
|
13735
|
+
if (!existsSync24(manifestPath)) continue;
|
|
13667
13736
|
let manifest;
|
|
13668
13737
|
try {
|
|
13669
13738
|
manifest = readFileSync27(manifestPath, "utf-8");
|
|
@@ -13680,11 +13749,11 @@ function computeDormantPlugins(accountId) {
|
|
|
13680
13749
|
}
|
|
13681
13750
|
|
|
13682
13751
|
// server/routes/admin/claude-sessions.ts
|
|
13683
|
-
import { existsSync as
|
|
13752
|
+
import { existsSync as existsSync25, readFileSync as readFileSync28 } from "fs";
|
|
13684
13753
|
import { resolve as resolve20 } from "path";
|
|
13685
13754
|
function readTunnelState(brandConfigDir) {
|
|
13686
13755
|
const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
|
|
13687
|
-
if (!
|
|
13756
|
+
if (!existsSync25(statePath)) return null;
|
|
13688
13757
|
try {
|
|
13689
13758
|
const parsed = JSON.parse(readFileSync28(statePath, "utf-8"));
|
|
13690
13759
|
const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
|
|
@@ -13909,18 +13978,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
13909
13978
|
]);
|
|
13910
13979
|
var app20 = new Hono();
|
|
13911
13980
|
app20.post("/", async (c) => {
|
|
13912
|
-
const
|
|
13981
|
+
const TAG45 = "[admin:events]";
|
|
13913
13982
|
let body;
|
|
13914
13983
|
try {
|
|
13915
13984
|
body = await c.req.json();
|
|
13916
13985
|
} catch (err) {
|
|
13917
13986
|
const detail = err instanceof Error ? err.message : String(err);
|
|
13918
|
-
console.error(`${
|
|
13987
|
+
console.error(`${TAG45} reject reason=body-not-json detail=${detail}`);
|
|
13919
13988
|
return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
|
|
13920
13989
|
}
|
|
13921
13990
|
const event = typeof body.event === "string" ? body.event : "";
|
|
13922
13991
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
13923
|
-
console.error(`${
|
|
13992
|
+
console.error(`${TAG45} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
|
|
13924
13993
|
return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
|
|
13925
13994
|
}
|
|
13926
13995
|
const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
|
|
@@ -13942,11 +14011,11 @@ app20.post("/", async (c) => {
|
|
|
13942
14011
|
var events_default = app20;
|
|
13943
14012
|
|
|
13944
14013
|
// server/routes/admin/files.ts
|
|
13945
|
-
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as
|
|
14014
|
+
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync26 } from "fs";
|
|
13946
14015
|
import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename } from "fs/promises";
|
|
13947
14016
|
import { realpathSync as realpathSync5 } from "fs";
|
|
13948
14017
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
13949
|
-
import { basename as
|
|
14018
|
+
import { basename as basename9, dirname as dirname10, join as join29, relative as relative4, resolve as resolve22, sep as sep6 } from "path";
|
|
13950
14019
|
import { Readable as Readable2 } from "stream";
|
|
13951
14020
|
|
|
13952
14021
|
// ../lib/graph-trash/src/index.ts
|
|
@@ -14264,7 +14333,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
14264
14333
|
|
|
14265
14334
|
// app/lib/file-index.ts
|
|
14266
14335
|
import * as fsp from "fs/promises";
|
|
14267
|
-
import { resolve as resolve21, relative as relative3, join as
|
|
14336
|
+
import { resolve as resolve21, relative as relative3, join as join28, basename as basename8, extname as extname2, sep as sep5 } from "path";
|
|
14268
14337
|
import { tmpdir as tmpdir2 } from "os";
|
|
14269
14338
|
import { execFile as execFile2 } from "child_process";
|
|
14270
14339
|
import { promisify as promisify2 } from "util";
|
|
@@ -14346,7 +14415,7 @@ async function extractPdf(absolute) {
|
|
|
14346
14415
|
return stdout.trim();
|
|
14347
14416
|
}
|
|
14348
14417
|
async function ocrPdf(absolute) {
|
|
14349
|
-
const outPdf =
|
|
14418
|
+
const outPdf = join28(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
|
|
14350
14419
|
try {
|
|
14351
14420
|
await execFileAsync2(
|
|
14352
14421
|
"ocrmypdf",
|
|
@@ -14402,13 +14471,13 @@ async function extractFileContent(absolute) {
|
|
|
14402
14471
|
}
|
|
14403
14472
|
}
|
|
14404
14473
|
async function readDisplayName(absolute) {
|
|
14405
|
-
const dir = absolute.slice(0, absolute.length -
|
|
14406
|
-
const base =
|
|
14474
|
+
const dir = absolute.slice(0, absolute.length - basename8(absolute).length);
|
|
14475
|
+
const base = basename8(absolute);
|
|
14407
14476
|
const dot = base.lastIndexOf(".");
|
|
14408
14477
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
14409
14478
|
if (base === `${stem}.meta.json`) return null;
|
|
14410
14479
|
try {
|
|
14411
|
-
const raw = await fsp.readFile(
|
|
14480
|
+
const raw = await fsp.readFile(join28(dir, `${stem}.meta.json`), "utf-8");
|
|
14412
14481
|
const meta = JSON.parse(raw);
|
|
14413
14482
|
const dn = meta.displayName ?? meta.filename;
|
|
14414
14483
|
return typeof dn === "string" && dn.length > 0 ? dn : null;
|
|
@@ -14429,7 +14498,7 @@ async function walkSubtree(root, dataRoot, out) {
|
|
|
14429
14498
|
for (const entry of entries) {
|
|
14430
14499
|
if (entry.isSymbolicLink()) continue;
|
|
14431
14500
|
if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
|
|
14432
|
-
const abs =
|
|
14501
|
+
const abs = join28(root, entry.name);
|
|
14433
14502
|
if (entry.isDirectory()) {
|
|
14434
14503
|
const sub = await walkSubtree(abs, dataRoot, out);
|
|
14435
14504
|
if (!sub.clean) clean = false;
|
|
@@ -14541,7 +14610,7 @@ async function cascadeTrashLinkedKnowledgeDocs(session, accountId, relativePaths
|
|
|
14541
14610
|
return { kds, sections, chunks };
|
|
14542
14611
|
}
|
|
14543
14612
|
async function buildArtifact(accountId, wf, embed2) {
|
|
14544
|
-
const name =
|
|
14613
|
+
const name = basename8(wf.absolute);
|
|
14545
14614
|
const { content, route } = await extractFileContent(wf.absolute);
|
|
14546
14615
|
const displayName = await readDisplayName(wf.absolute);
|
|
14547
14616
|
const embedInput = `${name}
|
|
@@ -14785,7 +14854,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
|
|
|
14785
14854
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14786
14855
|
async function readMeta(absDir, baseName) {
|
|
14787
14856
|
try {
|
|
14788
|
-
const raw = await readFile4(
|
|
14857
|
+
const raw = await readFile4(join29(absDir, `${baseName}.meta.json`), "utf8");
|
|
14789
14858
|
const parsed = JSON.parse(raw);
|
|
14790
14859
|
if (typeof parsed?.filename === "string") {
|
|
14791
14860
|
return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
|
|
@@ -14823,7 +14892,7 @@ async function readAccountNames() {
|
|
|
14823
14892
|
}
|
|
14824
14893
|
async function enrich(absolute, entry, accountNames) {
|
|
14825
14894
|
if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
|
|
14826
|
-
const meta = await readMeta(
|
|
14895
|
+
const meta = await readMeta(join29(absolute, entry.name), entry.name);
|
|
14827
14896
|
if (meta?.filename) {
|
|
14828
14897
|
entry.displayName = meta.filename;
|
|
14829
14898
|
entry.mimeType = meta.mimeType;
|
|
@@ -14987,7 +15056,7 @@ app21.get("/", requireAdminSession, async (c) => {
|
|
|
14987
15056
|
const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
|
|
14988
15057
|
const protectedEntry = isProtectedFromDeletion(childRel).protected;
|
|
14989
15058
|
try {
|
|
14990
|
-
const entryPath =
|
|
15059
|
+
const entryPath = join29(absolute, name);
|
|
14991
15060
|
const s = await stat4(entryPath);
|
|
14992
15061
|
entries.push({
|
|
14993
15062
|
name,
|
|
@@ -15040,7 +15109,7 @@ app21.get("/download", requireAdminSession, async (c) => {
|
|
|
15040
15109
|
console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
|
|
15041
15110
|
return c.json({ error: "Not found" }, 404);
|
|
15042
15111
|
}
|
|
15043
|
-
const meta = readSidecarMeta(
|
|
15112
|
+
const meta = readSidecarMeta(join29(projectDir, `${sessionId}.meta.json`));
|
|
15044
15113
|
if (!meta.accountId || meta.accountId !== accountId) {
|
|
15045
15114
|
console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
|
|
15046
15115
|
return c.json({ error: "Not found" }, 404);
|
|
@@ -15071,7 +15140,7 @@ app21.get("/download", requireAdminSession, async (c) => {
|
|
|
15071
15140
|
if (!info.isFile()) {
|
|
15072
15141
|
return c.json({ error: "Path is not a file" }, 400);
|
|
15073
15142
|
}
|
|
15074
|
-
const filename =
|
|
15143
|
+
const filename = basename9(absolute);
|
|
15075
15144
|
const mimeType = detectMimeType(absolute);
|
|
15076
15145
|
const nodeStream = createReadStream2(absolute);
|
|
15077
15146
|
const webStream = Readable2.toWeb(nodeStream);
|
|
@@ -15127,7 +15196,7 @@ async function* walkRegularFiles(dirAbsolute) {
|
|
|
15127
15196
|
const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
|
|
15128
15197
|
for (const d of dirents) {
|
|
15129
15198
|
if (d.isSymbolicLink()) continue;
|
|
15130
|
-
const child =
|
|
15199
|
+
const child = join29(dirAbsolute, d.name);
|
|
15131
15200
|
if (d.isDirectory()) {
|
|
15132
15201
|
yield* walkRegularFiles(child);
|
|
15133
15202
|
continue;
|
|
@@ -15187,7 +15256,7 @@ app21.get("/download-zip", requireAdminSession, async (c) => {
|
|
|
15187
15256
|
if (over) return over;
|
|
15188
15257
|
}
|
|
15189
15258
|
} else if (info.isFile()) {
|
|
15190
|
-
const over = await addFile(absolute, info.size,
|
|
15259
|
+
const over = await addFile(absolute, info.size, basename9(absolute));
|
|
15191
15260
|
if (over) return over;
|
|
15192
15261
|
} else {
|
|
15193
15262
|
return c.json({ error: "Path is not a file or directory" }, 400);
|
|
@@ -15216,12 +15285,12 @@ function dataUploadCeiling() {
|
|
|
15216
15285
|
}
|
|
15217
15286
|
async function resolveUploadTarget(c, accountId, uid) {
|
|
15218
15287
|
const rawName = c.req.query("filename") ?? "";
|
|
15219
|
-
const safeName =
|
|
15288
|
+
const safeName = basename9(rawName).replace(/[\0/\\]/g, "_");
|
|
15220
15289
|
if (!safeName) return { ok: false, status: 400, error: "filename query param required" };
|
|
15221
15290
|
const rawRelpath = c.req.query("relpath") ?? "";
|
|
15222
15291
|
const relpath = rawRelpath !== "" ? rawRelpath : null;
|
|
15223
15292
|
const token = c.req.query("token") ?? "";
|
|
15224
|
-
const finalName = relpath ?
|
|
15293
|
+
const finalName = relpath ? basename9(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
|
|
15225
15294
|
const mimeType = (c.req.header("content-type") ?? "").split(";")[0].trim();
|
|
15226
15295
|
if (!SUPPORTED_MIME_TYPES.has(mimeType)) {
|
|
15227
15296
|
console.error(`[data-upload] op=reject-mime uid=${uid} mime="${mimeType}" token=${token} rel="${relpath ?? ""}"`);
|
|
@@ -15231,7 +15300,7 @@ async function resolveUploadTarget(c, accountId, uid) {
|
|
|
15231
15300
|
const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
|
|
15232
15301
|
if (!base.ok) return { ok: false, status: base.status, error: base.error };
|
|
15233
15302
|
const relDir = relpath ? dirname10(relpath) : ".";
|
|
15234
|
-
const destRel = relDir === "." ? base.relative :
|
|
15303
|
+
const destRel = relDir === "." ? base.relative : join29(base.relative, relDir);
|
|
15235
15304
|
if (crossesForeignAccountPartition(destRel, accountId)) {
|
|
15236
15305
|
console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
|
|
15237
15306
|
return { ok: false, status: 404, error: "Not found" };
|
|
@@ -15305,7 +15374,7 @@ app21.post("/upload", requireAdminSession, async (c) => {
|
|
|
15305
15374
|
});
|
|
15306
15375
|
await unlink2(tmpPath).catch(() => {
|
|
15307
15376
|
});
|
|
15308
|
-
const tempRemoved = !
|
|
15377
|
+
const tempRemoved = !existsSync26(tmpPath);
|
|
15309
15378
|
console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
|
|
15310
15379
|
};
|
|
15311
15380
|
const reader = body.getReader();
|
|
@@ -15379,7 +15448,7 @@ async function discardChunkUpload(uploadId, state) {
|
|
|
15379
15448
|
});
|
|
15380
15449
|
await unlink2(state.tmpPath).catch(() => {
|
|
15381
15450
|
});
|
|
15382
|
-
const tempRemoved = !
|
|
15451
|
+
const tempRemoved = !existsSync26(state.tmpPath);
|
|
15383
15452
|
console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
|
|
15384
15453
|
}
|
|
15385
15454
|
async function writeChunkBody(body, out, alreadyReceived, ceiling) {
|
|
@@ -15591,7 +15660,7 @@ app21.delete("/", requireAdminSession, async (c) => {
|
|
|
15591
15660
|
console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
|
|
15592
15661
|
return c.json({ error: "Not found" }, 404);
|
|
15593
15662
|
}
|
|
15594
|
-
const base =
|
|
15663
|
+
const base = basename9(absolute);
|
|
15595
15664
|
const protection = isProtectedFromDeletion(relPath);
|
|
15596
15665
|
if (protection.protected) {
|
|
15597
15666
|
console.error(`[data] file-delete blocked path="${relPath}" reason="protected" rule="${protection.rule}"`);
|
|
@@ -15607,7 +15676,7 @@ app21.delete("/", requireAdminSession, async (c) => {
|
|
|
15607
15676
|
}
|
|
15608
15677
|
const dot = base.lastIndexOf(".");
|
|
15609
15678
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
15610
|
-
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ?
|
|
15679
|
+
const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join29(dirname10(absolute), `${stem}.meta.json`) : null;
|
|
15611
15680
|
await unlink2(absolute);
|
|
15612
15681
|
if (sidecarPath) {
|
|
15613
15682
|
try {
|
|
@@ -17835,8 +17904,8 @@ var graph_default_view_default = app27;
|
|
|
17835
17904
|
|
|
17836
17905
|
// server/routes/admin/sidebar-artefacts.ts
|
|
17837
17906
|
import { readdir as readdir4, stat as stat5 } from "fs/promises";
|
|
17838
|
-
import { resolve as resolve23, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as
|
|
17839
|
-
import { existsSync as
|
|
17907
|
+
import { resolve as resolve23, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
|
|
17908
|
+
import { existsSync as existsSync27 } from "fs";
|
|
17840
17909
|
var LIMIT = 50;
|
|
17841
17910
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
17842
17911
|
function toDataRootRelPath(absPath) {
|
|
@@ -17888,7 +17957,7 @@ async function fetchAccountFileArtefacts(accountId) {
|
|
|
17888
17957
|
const modifiedAt = r.get("modifiedAt") ?? "";
|
|
17889
17958
|
return {
|
|
17890
17959
|
id: `account-file:${relativePath}`,
|
|
17891
|
-
name: displayName ??
|
|
17960
|
+
name: displayName ?? basename10(relativePath),
|
|
17892
17961
|
kind: "account-file",
|
|
17893
17962
|
updatedAt: modifiedAt,
|
|
17894
17963
|
mimeType,
|
|
@@ -17943,7 +18012,7 @@ async function fetchAgentTemplateRows(accountDir) {
|
|
|
17943
18012
|
async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
17944
18013
|
const names = /* @__PURE__ */ new Set();
|
|
17945
18014
|
for (const dir of [overrideDir, bundledDir]) {
|
|
17946
|
-
if (!
|
|
18015
|
+
if (!existsSync27(dir)) continue;
|
|
17947
18016
|
try {
|
|
17948
18017
|
const entries = await readdir4(dir);
|
|
17949
18018
|
for (const entry of entries) {
|
|
@@ -17958,7 +18027,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
|
|
|
17958
18027
|
}
|
|
17959
18028
|
async function readAgentTemplateRow(inp) {
|
|
17960
18029
|
let chosenPath = null;
|
|
17961
|
-
if (
|
|
18030
|
+
if (existsSync27(inp.overridePath)) {
|
|
17962
18031
|
try {
|
|
17963
18032
|
validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
|
|
17964
18033
|
chosenPath = inp.overridePath;
|
|
@@ -17969,7 +18038,7 @@ async function readAgentTemplateRow(inp) {
|
|
|
17969
18038
|
);
|
|
17970
18039
|
return null;
|
|
17971
18040
|
}
|
|
17972
|
-
} else if (
|
|
18041
|
+
} else if (existsSync27(inp.bundledPath)) {
|
|
17973
18042
|
if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
|
|
17974
18043
|
console.error(
|
|
17975
18044
|
`[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
|
|
@@ -18572,12 +18641,12 @@ app36.get("/", async (c) => {
|
|
|
18572
18641
|
var system_stats_default = app36;
|
|
18573
18642
|
|
|
18574
18643
|
// server/routes/admin/health.ts
|
|
18575
|
-
import { existsSync as
|
|
18576
|
-
import { resolve as resolve24, join as
|
|
18644
|
+
import { existsSync as existsSync28, readFileSync as readFileSync29 } from "fs";
|
|
18645
|
+
import { resolve as resolve24, join as join30 } from "path";
|
|
18577
18646
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
18578
18647
|
var brandHostname = "maxy";
|
|
18579
|
-
var brandJsonPath =
|
|
18580
|
-
if (
|
|
18648
|
+
var brandJsonPath = join30(PLATFORM_ROOT6, "config", "brand.json");
|
|
18649
|
+
if (existsSync28(brandJsonPath)) {
|
|
18581
18650
|
try {
|
|
18582
18651
|
const brand = JSON.parse(readFileSync29(brandJsonPath, "utf-8"));
|
|
18583
18652
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -18588,7 +18657,7 @@ var VERSION_FILE = resolve24(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
18588
18657
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
18589
18658
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
18590
18659
|
function readVersion() {
|
|
18591
|
-
if (!
|
|
18660
|
+
if (!existsSync28(VERSION_FILE)) return "unknown";
|
|
18592
18661
|
return readFileSync29(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
18593
18662
|
}
|
|
18594
18663
|
async function probeConversationDb() {
|
|
@@ -19365,8 +19434,8 @@ app44.post("/launch", requireAdminSession, async (c) => {
|
|
|
19365
19434
|
var browser_default = app44;
|
|
19366
19435
|
|
|
19367
19436
|
// server/routes/admin/calendar.ts
|
|
19368
|
-
import { existsSync as
|
|
19369
|
-
import { join as
|
|
19437
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19438
|
+
import { join as join32 } from "path";
|
|
19370
19439
|
|
|
19371
19440
|
// server/lib/calendar-ics.ts
|
|
19372
19441
|
var CRLF = "\r\n";
|
|
@@ -19466,7 +19535,7 @@ function countVEvents(ics) {
|
|
|
19466
19535
|
|
|
19467
19536
|
// server/lib/calendar-availability.ts
|
|
19468
19537
|
import { readFileSync as readFileSync30 } from "fs";
|
|
19469
|
-
import { join as
|
|
19538
|
+
import { join as join31 } from "path";
|
|
19470
19539
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
19471
19540
|
var REQUIRED_KEYS = [
|
|
19472
19541
|
"timezone",
|
|
@@ -19475,7 +19544,7 @@ var REQUIRED_KEYS = [
|
|
|
19475
19544
|
"weekly"
|
|
19476
19545
|
];
|
|
19477
19546
|
function readAvailabilityConfig(accountDir) {
|
|
19478
|
-
const path2 =
|
|
19547
|
+
const path2 = join31(accountDir, AVAILABILITY_FILENAME);
|
|
19479
19548
|
let raw;
|
|
19480
19549
|
try {
|
|
19481
19550
|
raw = readFileSync30(path2, "utf-8");
|
|
@@ -19837,7 +19906,7 @@ app45.get("/booking-link", requireAdminSession, (c) => {
|
|
|
19837
19906
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
19838
19907
|
return c.json({ bookingDomain: null });
|
|
19839
19908
|
}
|
|
19840
|
-
if (!
|
|
19909
|
+
if (!existsSync29(join32(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
19841
19910
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
19842
19911
|
return c.json({ bookingDomain: null });
|
|
19843
19912
|
}
|
|
@@ -19932,7 +20001,6 @@ var tasks_list_default = app46;
|
|
|
19932
20001
|
|
|
19933
20002
|
// server/routes/admin/task-timer-start.ts
|
|
19934
20003
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
19935
|
-
import neo4j5 from "neo4j-driver";
|
|
19936
20004
|
var TAG34 = "[task-timer]";
|
|
19937
20005
|
var app47 = new Hono();
|
|
19938
20006
|
app47.post("/", requireAdminSession, async (c) => {
|
|
@@ -19959,30 +20027,17 @@ app47.post("/", requireAdminSession, async (c) => {
|
|
|
19959
20027
|
return c.json({ error: "task-not-found" }, 404);
|
|
19960
20028
|
}
|
|
19961
20029
|
const open = await session.run(
|
|
19962
|
-
`MATCH (te:TimeEntry {accountId: $accountId}) WHERE te.endedAt IS NULL
|
|
19963
|
-
RETURN te.entryId AS entryId, te.
|
|
20030
|
+
`MATCH (te:TimeEntry {accountId: $accountId, taskId: $taskId}) WHERE te.endedAt IS NULL
|
|
20031
|
+
RETURN te.entryId AS entryId, te.startedAt AS startedAt
|
|
19964
20032
|
ORDER BY te.startedAt LIMIT 1`,
|
|
19965
|
-
{ accountId }
|
|
20033
|
+
{ accountId, taskId }
|
|
19966
20034
|
);
|
|
19967
20035
|
const priorEntryId = open.records[0]?.get("entryId");
|
|
19968
|
-
const priorTaskId = open.records[0]?.get("taskId");
|
|
19969
20036
|
const priorStartedAt = open.records[0]?.get("startedAt");
|
|
19970
|
-
|
|
19971
|
-
|
|
20037
|
+
if (priorEntryId) {
|
|
20038
|
+
console.log(`${TAG34} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
|
|
19972
20039
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
19973
20040
|
}
|
|
19974
|
-
if (priorEntryId && priorStartedAt && priorTaskId) {
|
|
19975
|
-
const seconds = secondsBetween(priorStartedAt, now);
|
|
19976
|
-
await session.run(
|
|
19977
|
-
`MATCH (te:TimeEntry {entryId: $priorEntryId}) WHERE te.endedAt IS NULL
|
|
19978
|
-
SET te.endedAt = $now, te.seconds = $seconds
|
|
19979
|
-
WITH te
|
|
19980
|
-
MATCH (t:Task {taskId: $priorTaskId, accountId: $accountId})
|
|
19981
|
-
SET t.secondsLogged = coalesce(t.secondsLogged, 0) + $seconds`,
|
|
19982
|
-
{ priorEntryId, priorTaskId, accountId, now, seconds: neo4j5.int(seconds) }
|
|
19983
|
-
);
|
|
19984
|
-
console.log(`${TAG34} op=autostop taskId=${priorTaskId} entryId=${priorEntryId} seconds=${seconds}`);
|
|
19985
|
-
}
|
|
19986
20041
|
const entryId = randomUUID13();
|
|
19987
20042
|
await session.run(
|
|
19988
20043
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
@@ -20002,7 +20057,7 @@ app47.post("/", requireAdminSession, async (c) => {
|
|
|
20002
20057
|
var task_timer_start_default = app47;
|
|
20003
20058
|
|
|
20004
20059
|
// server/routes/admin/task-timer-stop.ts
|
|
20005
|
-
import
|
|
20060
|
+
import neo4j5 from "neo4j-driver";
|
|
20006
20061
|
var TAG35 = "[task-timer]";
|
|
20007
20062
|
var app48 = new Hono();
|
|
20008
20063
|
app48.post("/", requireAdminSession, async (c) => {
|
|
@@ -20045,18 +20100,21 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
20045
20100
|
WITH te
|
|
20046
20101
|
MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20047
20102
|
SET t.secondsLogged = coalesce(t.secondsLogged, 0) + $seconds`,
|
|
20048
|
-
{ entryId, taskId, accountId, now, seconds:
|
|
20103
|
+
{ entryId, taskId, accountId, now, seconds: neo4j5.int(seconds) }
|
|
20049
20104
|
);
|
|
20050
20105
|
const verify = await session.run(
|
|
20051
20106
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20052
20107
|
OPTIONAL MATCH (te:TimeEntry {taskId: $taskId, accountId: $accountId}) WHERE te.endedAt IS NOT NULL
|
|
20053
|
-
|
|
20108
|
+
WITH t, coalesce(sum(te.seconds), 0) AS sumEntries
|
|
20109
|
+
OPTIONAL MATCH (ta:TimeAdjustment {taskId: $taskId, accountId: $accountId})
|
|
20110
|
+
RETURN sumEntries, coalesce(sum(ta.delta), 0) AS sumAdjustments, coalesce(t.secondsLogged, 0) AS secondsLogged`,
|
|
20054
20111
|
{ taskId, accountId }
|
|
20055
20112
|
);
|
|
20056
20113
|
const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
|
|
20114
|
+
const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
|
|
20057
20115
|
const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
|
|
20058
20116
|
console.log(`${TAG35} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
|
|
20059
|
-
console.log(`${TAG35} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} secondsLogged=${secondsLogged}`);
|
|
20117
|
+
console.log(`${TAG35} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
|
|
20060
20118
|
return c.json({ ok: true, running: false, seconds, secondsLogged });
|
|
20061
20119
|
} catch (err) {
|
|
20062
20120
|
console.error(`${TAG35} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -20106,56 +20164,137 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
20106
20164
|
});
|
|
20107
20165
|
var task_complete_default = app49;
|
|
20108
20166
|
|
|
20109
|
-
// server/routes/admin/
|
|
20167
|
+
// server/routes/admin/task-time-adjust.ts
|
|
20168
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
20169
|
+
import neo4j6 from "neo4j-driver";
|
|
20170
|
+
var TAG37 = "[task-time-adjust]";
|
|
20110
20171
|
var app50 = new Hono();
|
|
20111
|
-
app50.
|
|
20112
|
-
|
|
20113
|
-
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20121
|
-
|
|
20122
|
-
|
|
20123
|
-
|
|
20124
|
-
|
|
20125
|
-
|
|
20126
|
-
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20130
|
-
|
|
20131
|
-
|
|
20132
|
-
|
|
20133
|
-
|
|
20134
|
-
|
|
20135
|
-
|
|
20136
|
-
|
|
20137
|
-
|
|
20138
|
-
|
|
20139
|
-
|
|
20140
|
-
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20172
|
+
app50.post("/", requireAdminSession, async (c) => {
|
|
20173
|
+
const cacheKey = c.var.cacheKey;
|
|
20174
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
20175
|
+
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
20176
|
+
let body;
|
|
20177
|
+
try {
|
|
20178
|
+
body = await c.req.json();
|
|
20179
|
+
} catch {
|
|
20180
|
+
console.error(`${TAG37} op=reject reason=bad-json`);
|
|
20181
|
+
return c.json({ error: "invalid-json" }, 400);
|
|
20182
|
+
}
|
|
20183
|
+
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
20184
|
+
if (!taskId) {
|
|
20185
|
+
console.error(`${TAG37} op=reject reason=no-task`);
|
|
20186
|
+
return c.json({ error: "taskId required" }, 400);
|
|
20187
|
+
}
|
|
20188
|
+
const newSeconds = body.newSeconds;
|
|
20189
|
+
if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
|
|
20190
|
+
console.error(`${TAG37} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
20191
|
+
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
20192
|
+
}
|
|
20193
|
+
const adjustmentId = randomUUID14();
|
|
20194
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20195
|
+
console.log(`${TAG37} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
20196
|
+
const session = getSession();
|
|
20197
|
+
try {
|
|
20198
|
+
const guard = await session.run(
|
|
20199
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20200
|
+
OPTIONAL MATCH (te:TimeEntry {taskId: $taskId, accountId: $accountId}) WHERE te.endedAt IS NULL
|
|
20201
|
+
RETURN t.taskId AS taskId, count(te) AS openCount, coalesce(t.secondsLogged, 0) AS previousSeconds`,
|
|
20202
|
+
{ taskId, accountId }
|
|
20203
|
+
);
|
|
20204
|
+
if (guard.records.length === 0) {
|
|
20205
|
+
console.error(`${TAG37} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
20206
|
+
return c.json({ error: "task-not-found" }, 404);
|
|
20207
|
+
}
|
|
20208
|
+
const openCount = toNum(guard.records[0].get("openCount"));
|
|
20209
|
+
if (openCount > 0) {
|
|
20210
|
+
console.error(`${TAG37} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
20211
|
+
return c.json({ error: "task-timer-running" }, 409);
|
|
20212
|
+
}
|
|
20213
|
+
const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
|
|
20214
|
+
const delta = newSeconds - previousSeconds;
|
|
20215
|
+
const write = await session.run(
|
|
20216
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20217
|
+
CREATE (ta:TimeAdjustment {
|
|
20218
|
+
adjustmentId: $adjustmentId, taskId: $taskId, accountId: $accountId, at: $now,
|
|
20219
|
+
previousSeconds: $previousSeconds, newSeconds: $newSeconds, delta: $delta,
|
|
20220
|
+
sourceSessionKey: $sourceSessionKey
|
|
20221
|
+
})
|
|
20222
|
+
SET t.secondsLogged = $newSeconds
|
|
20223
|
+
RETURN coalesce(t.secondsLogged, 0) AS secondsLoggedAfter`,
|
|
20224
|
+
{
|
|
20225
|
+
taskId,
|
|
20226
|
+
accountId,
|
|
20227
|
+
adjustmentId,
|
|
20228
|
+
now,
|
|
20229
|
+
previousSeconds: neo4j6.int(previousSeconds),
|
|
20230
|
+
newSeconds: neo4j6.int(newSeconds),
|
|
20231
|
+
delta: neo4j6.int(delta),
|
|
20232
|
+
sourceSessionKey: cacheKey
|
|
20233
|
+
}
|
|
20234
|
+
);
|
|
20235
|
+
const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
|
|
20236
|
+
console.log(`${TAG37} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
|
|
20237
|
+
return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
|
|
20238
|
+
} catch (err) {
|
|
20239
|
+
console.error(`${TAG37} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
20240
|
+
return c.json({ error: "task-time-adjust-failed" }, 500);
|
|
20241
|
+
} finally {
|
|
20242
|
+
await session.close();
|
|
20243
|
+
}
|
|
20244
|
+
});
|
|
20245
|
+
var task_time_adjust_default = app50;
|
|
20246
|
+
|
|
20247
|
+
// server/routes/admin/index.ts
|
|
20248
|
+
var app51 = new Hono();
|
|
20249
|
+
app51.route("/session", session_default);
|
|
20250
|
+
app51.route("/accounts", accounts_default);
|
|
20251
|
+
app51.route("/logs", logs_default);
|
|
20252
|
+
app51.route("/claude-info", claude_info_default);
|
|
20253
|
+
app51.route("/attachment", attachment_default);
|
|
20254
|
+
app51.route("/agents", agents_default);
|
|
20255
|
+
app51.route("/sessions", sessions_default);
|
|
20256
|
+
app51.route("/claude-sessions", claude_sessions_default);
|
|
20257
|
+
app51.route("/log-ingest", log_ingest_default);
|
|
20258
|
+
app51.route("/events", events_default);
|
|
20259
|
+
app51.route("/files", files_default);
|
|
20260
|
+
app51.route("/graph-search", graph_search_default);
|
|
20261
|
+
app51.route("/graph-subgraph", graph_subgraph_default);
|
|
20262
|
+
app51.route("/graph-delete", graph_delete_default);
|
|
20263
|
+
app51.route("/graph-restore", graph_restore_default);
|
|
20264
|
+
app51.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
20265
|
+
app51.route("/graph-default-view", graph_default_view_default);
|
|
20266
|
+
app51.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
20267
|
+
app51.route("/sidebar-sessions", sidebar_sessions_default);
|
|
20268
|
+
app51.route("/session-delete", session_delete_default);
|
|
20269
|
+
app51.route("/session-stop", session_stop_default);
|
|
20270
|
+
app51.route("/session-archive", session_archive_default);
|
|
20271
|
+
app51.route("/session-rename", session_rename_default);
|
|
20272
|
+
app51.route("/session-usage", session_usage_default);
|
|
20273
|
+
app51.route("/browser", browser_default);
|
|
20274
|
+
app51.route("/session-rc-spawn", session_rc_spawn_default);
|
|
20275
|
+
app51.route("/session-reseat", session_reseat_default);
|
|
20276
|
+
app51.route("/system-stats", system_stats_default);
|
|
20277
|
+
app51.route("/health-brand", health_default2);
|
|
20278
|
+
app51.route("/linkedin-ingest", linkedin_ingest_default);
|
|
20279
|
+
app51.route("/post-turn-context", post_turn_context_default);
|
|
20280
|
+
app51.route("/public-session-context", public_session_context_default);
|
|
20281
|
+
app51.route("/public-session-exit", public_session_exit_default);
|
|
20282
|
+
app51.route("/access-session-evict", access_session_evict_default);
|
|
20283
|
+
app51.route("/enrol-person", enrol_person_default);
|
|
20284
|
+
app51.route("/calendar", calendar_default);
|
|
20285
|
+
app51.route("/tasks-list", tasks_list_default);
|
|
20286
|
+
app51.route("/task-timer-start", task_timer_start_default);
|
|
20287
|
+
app51.route("/task-timer-stop", task_timer_stop_default);
|
|
20288
|
+
app51.route("/task-complete", task_complete_default);
|
|
20289
|
+
app51.route("/task-time-adjust", task_time_adjust_default);
|
|
20290
|
+
var admin_default = app51;
|
|
20152
20291
|
|
|
20153
20292
|
// server/routes/access/verify-token.ts
|
|
20154
|
-
var
|
|
20293
|
+
var TAG38 = "[access-verify]";
|
|
20155
20294
|
var MINT_TAG = "[access-session-mint]";
|
|
20156
20295
|
var COOKIE_NAME = "__access_session";
|
|
20157
|
-
var
|
|
20158
|
-
|
|
20296
|
+
var app52 = new Hono();
|
|
20297
|
+
app52.post("/", async (c) => {
|
|
20159
20298
|
const ip = c.var.clientIp || "unknown";
|
|
20160
20299
|
let body;
|
|
20161
20300
|
try {
|
|
@@ -20170,39 +20309,39 @@ app51.post("/", async (c) => {
|
|
|
20170
20309
|
}
|
|
20171
20310
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
20172
20311
|
if (rateMsg) {
|
|
20173
|
-
console.error(`${
|
|
20312
|
+
console.error(`${TAG38} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
20174
20313
|
return c.json({ error: rateMsg }, 429);
|
|
20175
20314
|
}
|
|
20176
20315
|
const grant = await findGrantByMagicToken(token);
|
|
20177
20316
|
if (!grant) {
|
|
20178
20317
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20179
|
-
console.error(`${
|
|
20318
|
+
console.error(`${TAG38} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
20180
20319
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
20181
20320
|
}
|
|
20182
20321
|
if (grant.agentSlug !== agentSlug) {
|
|
20183
20322
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20184
20323
|
console.error(
|
|
20185
|
-
`${
|
|
20324
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
20186
20325
|
);
|
|
20187
20326
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
20188
20327
|
}
|
|
20189
20328
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
20190
20329
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20191
20330
|
console.error(
|
|
20192
|
-
`${
|
|
20331
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
20193
20332
|
);
|
|
20194
20333
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
20195
20334
|
}
|
|
20196
20335
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
20197
20336
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20198
20337
|
console.error(
|
|
20199
|
-
`${
|
|
20338
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
20200
20339
|
);
|
|
20201
20340
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
20202
20341
|
}
|
|
20203
20342
|
if (!grant.sliceToken) {
|
|
20204
20343
|
console.error(
|
|
20205
|
-
`${
|
|
20344
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
20206
20345
|
);
|
|
20207
20346
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
20208
20347
|
}
|
|
@@ -20218,12 +20357,12 @@ app51.post("/", async (c) => {
|
|
|
20218
20357
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
20219
20358
|
} catch (err) {
|
|
20220
20359
|
console.error(
|
|
20221
|
-
`${
|
|
20360
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
20222
20361
|
);
|
|
20223
20362
|
return c.json({ error: "verification-failed" }, 500);
|
|
20224
20363
|
}
|
|
20225
20364
|
clearAccessRateLimit(ip, agentSlug);
|
|
20226
|
-
console.log(`${
|
|
20365
|
+
console.log(`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
20227
20366
|
console.log(
|
|
20228
20367
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
20229
20368
|
);
|
|
@@ -20237,7 +20376,7 @@ app51.post("/", async (c) => {
|
|
|
20237
20376
|
displayName: grant.displayName
|
|
20238
20377
|
});
|
|
20239
20378
|
});
|
|
20240
|
-
var verify_token_default =
|
|
20379
|
+
var verify_token_default = app52;
|
|
20241
20380
|
|
|
20242
20381
|
// app/lib/access-email.ts
|
|
20243
20382
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -20299,10 +20438,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
20299
20438
|
}
|
|
20300
20439
|
|
|
20301
20440
|
// server/routes/access/request-magic-link.ts
|
|
20302
|
-
var
|
|
20303
|
-
var
|
|
20441
|
+
var TAG39 = "[access-request-link]";
|
|
20442
|
+
var app53 = new Hono();
|
|
20304
20443
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
20305
|
-
|
|
20444
|
+
app53.post("/", async (c) => {
|
|
20306
20445
|
let body;
|
|
20307
20446
|
try {
|
|
20308
20447
|
body = await c.req.json();
|
|
@@ -20316,18 +20455,18 @@ app52.post("/", async (c) => {
|
|
|
20316
20455
|
}
|
|
20317
20456
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
20318
20457
|
if (rateMsg) {
|
|
20319
|
-
console.error(`${
|
|
20458
|
+
console.error(`${TAG39} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
20320
20459
|
return c.json({ error: rateMsg }, 429);
|
|
20321
20460
|
}
|
|
20322
20461
|
recordRequestLinkAttempt(contactValue);
|
|
20323
20462
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
20324
20463
|
if (!accountId) {
|
|
20325
|
-
console.error(`${
|
|
20464
|
+
console.error(`${TAG39} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
20326
20465
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20327
20466
|
}
|
|
20328
20467
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
20329
20468
|
if (!grant) {
|
|
20330
|
-
console.log(`${
|
|
20469
|
+
console.log(`${TAG39} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
20331
20470
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20332
20471
|
}
|
|
20333
20472
|
let token;
|
|
@@ -20335,7 +20474,7 @@ app52.post("/", async (c) => {
|
|
|
20335
20474
|
token = await generateNewMagicToken(grant.grantId);
|
|
20336
20475
|
} catch (err) {
|
|
20337
20476
|
console.error(
|
|
20338
|
-
`${
|
|
20477
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
20339
20478
|
);
|
|
20340
20479
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20341
20480
|
}
|
|
@@ -20367,25 +20506,25 @@ app52.post("/", async (c) => {
|
|
|
20367
20506
|
});
|
|
20368
20507
|
if (!sendResult.ok) {
|
|
20369
20508
|
console.error(
|
|
20370
|
-
`${
|
|
20509
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
20371
20510
|
);
|
|
20372
20511
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20373
20512
|
}
|
|
20374
20513
|
console.log(
|
|
20375
|
-
`${
|
|
20514
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
20376
20515
|
);
|
|
20377
20516
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20378
20517
|
});
|
|
20379
|
-
var request_magic_link_default =
|
|
20518
|
+
var request_magic_link_default = app53;
|
|
20380
20519
|
|
|
20381
20520
|
// server/routes/access/index.ts
|
|
20382
|
-
var
|
|
20383
|
-
|
|
20384
|
-
|
|
20385
|
-
var access_default =
|
|
20521
|
+
var app54 = new Hono();
|
|
20522
|
+
app54.route("/verify-token", verify_token_default);
|
|
20523
|
+
app54.route("/request-magic-link", request_magic_link_default);
|
|
20524
|
+
var access_default = app54;
|
|
20386
20525
|
|
|
20387
20526
|
// server/routes/sites.ts
|
|
20388
|
-
import { existsSync as
|
|
20527
|
+
import { existsSync as existsSync30, readFileSync as readFileSync31, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
|
|
20389
20528
|
import { resolve as resolve26 } from "path";
|
|
20390
20529
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
20391
20530
|
var MIME = {
|
|
@@ -20417,8 +20556,8 @@ function getExt(p) {
|
|
|
20417
20556
|
if (idx < p.lastIndexOf("/")) return "";
|
|
20418
20557
|
return p.slice(idx).toLowerCase();
|
|
20419
20558
|
}
|
|
20420
|
-
var
|
|
20421
|
-
|
|
20559
|
+
var app55 = new Hono();
|
|
20560
|
+
app55.get("/:rel{.*}", (c) => {
|
|
20422
20561
|
const reqPath = c.req.path;
|
|
20423
20562
|
const rawRel = c.req.param("rel") ?? "";
|
|
20424
20563
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -20451,7 +20590,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20451
20590
|
}
|
|
20452
20591
|
let stat8;
|
|
20453
20592
|
try {
|
|
20454
|
-
stat8 =
|
|
20593
|
+
stat8 = existsSync30(filePath) ? statSync12(filePath) : null;
|
|
20455
20594
|
} catch {
|
|
20456
20595
|
stat8 = null;
|
|
20457
20596
|
}
|
|
@@ -20470,7 +20609,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20470
20609
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
20471
20610
|
return c.text("Forbidden", 403);
|
|
20472
20611
|
}
|
|
20473
|
-
if (!
|
|
20612
|
+
if (!existsSync30(filePath)) {
|
|
20474
20613
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
20475
20614
|
return c.text("Not found", 404);
|
|
20476
20615
|
}
|
|
@@ -20521,7 +20660,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20521
20660
|
"X-Content-Type-Options": "nosniff"
|
|
20522
20661
|
});
|
|
20523
20662
|
});
|
|
20524
|
-
var sites_default =
|
|
20663
|
+
var sites_default = app55;
|
|
20525
20664
|
|
|
20526
20665
|
// app/lib/visitor-token.ts
|
|
20527
20666
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -20601,8 +20740,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
20601
20740
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
20602
20741
|
|
|
20603
20742
|
// app/lib/brand-config.ts
|
|
20604
|
-
import { existsSync as
|
|
20605
|
-
import { join as
|
|
20743
|
+
import { existsSync as existsSync31, readFileSync as readFileSync33 } from "fs";
|
|
20744
|
+
import { join as join33 } from "path";
|
|
20606
20745
|
var cached = null;
|
|
20607
20746
|
var cachedAttempted = false;
|
|
20608
20747
|
function readBrandConfig() {
|
|
@@ -20610,8 +20749,8 @@ function readBrandConfig() {
|
|
|
20610
20749
|
cachedAttempted = true;
|
|
20611
20750
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
|
|
20612
20751
|
if (!platformRoot3) return null;
|
|
20613
|
-
const brandPath =
|
|
20614
|
-
if (!
|
|
20752
|
+
const brandPath = join33(platformRoot3, "config", "brand.json");
|
|
20753
|
+
if (!existsSync31(brandPath)) return null;
|
|
20615
20754
|
try {
|
|
20616
20755
|
cached = JSON.parse(readFileSync33(brandPath, "utf-8"));
|
|
20617
20756
|
return cached;
|
|
@@ -20621,7 +20760,7 @@ function readBrandConfig() {
|
|
|
20621
20760
|
}
|
|
20622
20761
|
|
|
20623
20762
|
// server/routes/visitor-consent.ts
|
|
20624
|
-
var
|
|
20763
|
+
var app56 = new Hono();
|
|
20625
20764
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
20626
20765
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
20627
20766
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -20666,17 +20805,17 @@ function siteSlugFromReferer(referer) {
|
|
|
20666
20805
|
return "";
|
|
20667
20806
|
}
|
|
20668
20807
|
}
|
|
20669
|
-
|
|
20808
|
+
app56.options("/consent", (c) => {
|
|
20670
20809
|
const origin = getOrigin(c);
|
|
20671
20810
|
setCorsHeaders(c, origin);
|
|
20672
20811
|
return c.body(null, 204);
|
|
20673
20812
|
});
|
|
20674
|
-
|
|
20813
|
+
app56.options("/brand-config", (c) => {
|
|
20675
20814
|
const origin = getOrigin(c);
|
|
20676
20815
|
setCorsHeaders(c, origin);
|
|
20677
20816
|
return c.body(null, 204);
|
|
20678
20817
|
});
|
|
20679
|
-
|
|
20818
|
+
app56.post("/consent", async (c) => {
|
|
20680
20819
|
const origin = getOrigin(c);
|
|
20681
20820
|
setCorsHeaders(c, origin);
|
|
20682
20821
|
let raw;
|
|
@@ -20716,7 +20855,7 @@ app55.post("/consent", async (c) => {
|
|
|
20716
20855
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
20717
20856
|
return c.body(null, 204);
|
|
20718
20857
|
});
|
|
20719
|
-
|
|
20858
|
+
app56.get("/brand-config", (c) => {
|
|
20720
20859
|
const origin = getOrigin(c);
|
|
20721
20860
|
setCorsHeaders(c, origin);
|
|
20722
20861
|
const brand = readBrandConfig();
|
|
@@ -20726,7 +20865,7 @@ app55.get("/brand-config", (c) => {
|
|
|
20726
20865
|
c.header("Cache-Control", "public, max-age=300");
|
|
20727
20866
|
return c.json({ consent: { copy, palette } });
|
|
20728
20867
|
});
|
|
20729
|
-
var visitor_consent_default =
|
|
20868
|
+
var visitor_consent_default = app56;
|
|
20730
20869
|
|
|
20731
20870
|
// server/routes/listings.ts
|
|
20732
20871
|
function getCookie(headerValue, name) {
|
|
@@ -20753,8 +20892,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
20753
20892
|
}
|
|
20754
20893
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
20755
20894
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
20756
|
-
var
|
|
20757
|
-
|
|
20895
|
+
var app57 = new Hono();
|
|
20896
|
+
app57.get("/:slug/click", async (c) => {
|
|
20758
20897
|
const slug = c.req.param("slug") ?? "";
|
|
20759
20898
|
const rawSession = c.req.query("session") ?? "";
|
|
20760
20899
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -20818,10 +20957,10 @@ app56.get("/:slug/click", async (c) => {
|
|
|
20818
20957
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
20819
20958
|
return c.redirect(redirectUrl, 302);
|
|
20820
20959
|
});
|
|
20821
|
-
var listings_default =
|
|
20960
|
+
var listings_default = app57;
|
|
20822
20961
|
|
|
20823
20962
|
// server/routes/visitor-event.ts
|
|
20824
|
-
var
|
|
20963
|
+
var app58 = new Hono();
|
|
20825
20964
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
20826
20965
|
var buckets = /* @__PURE__ */ new Map();
|
|
20827
20966
|
var RATE_LIMIT = 60;
|
|
@@ -20888,12 +21027,12 @@ function originAllowed(origin, allowlist) {
|
|
|
20888
21027
|
return false;
|
|
20889
21028
|
}
|
|
20890
21029
|
}
|
|
20891
|
-
|
|
21030
|
+
app58.options("/event", (c) => {
|
|
20892
21031
|
const origin = getOrigin2(c);
|
|
20893
21032
|
setCorsHeaders2(c, origin);
|
|
20894
21033
|
return c.body(null, 204);
|
|
20895
21034
|
});
|
|
20896
|
-
|
|
21035
|
+
app58.post("/event", async (c) => {
|
|
20897
21036
|
const origin = getOrigin2(c);
|
|
20898
21037
|
setCorsHeaders2(c, origin);
|
|
20899
21038
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -21098,11 +21237,11 @@ async function writeEvent(opts) {
|
|
|
21098
21237
|
);
|
|
21099
21238
|
}
|
|
21100
21239
|
}
|
|
21101
|
-
var visitor_event_default =
|
|
21240
|
+
var visitor_event_default = app58;
|
|
21102
21241
|
|
|
21103
21242
|
// server/routes/session.ts
|
|
21104
21243
|
import { resolve as resolve27 } from "path";
|
|
21105
|
-
import { existsSync as
|
|
21244
|
+
import { existsSync as existsSync32, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
|
|
21106
21245
|
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21107
21246
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
21108
21247
|
try {
|
|
@@ -21144,8 +21283,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
21144
21283
|
headers
|
|
21145
21284
|
});
|
|
21146
21285
|
}
|
|
21147
|
-
var
|
|
21148
|
-
|
|
21286
|
+
var app59 = new Hono();
|
|
21287
|
+
app59.post("/", async (c) => {
|
|
21149
21288
|
let body;
|
|
21150
21289
|
try {
|
|
21151
21290
|
body = await c.req.json();
|
|
@@ -21186,7 +21325,7 @@ app58.post("/", async (c) => {
|
|
|
21186
21325
|
let agentConfig = null;
|
|
21187
21326
|
if (account) {
|
|
21188
21327
|
const agentDir = resolve27(account.accountDir, "agents", agentSlug);
|
|
21189
|
-
if (!
|
|
21328
|
+
if (!existsSync32(agentDir) || !existsSync32(resolve27(agentDir, "config.json"))) {
|
|
21190
21329
|
return c.json({ error: "Agent not found" }, 404);
|
|
21191
21330
|
}
|
|
21192
21331
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -21292,7 +21431,7 @@ app58.post("/", async (c) => {
|
|
|
21292
21431
|
newVisitorId
|
|
21293
21432
|
);
|
|
21294
21433
|
});
|
|
21295
|
-
var session_default2 =
|
|
21434
|
+
var session_default2 = app59;
|
|
21296
21435
|
|
|
21297
21436
|
// server/lib/calendar-slots.ts
|
|
21298
21437
|
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
@@ -21375,17 +21514,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
|
21375
21514
|
}
|
|
21376
21515
|
|
|
21377
21516
|
// server/routes/calendar-public.ts
|
|
21378
|
-
var
|
|
21517
|
+
var app60 = new Hono();
|
|
21379
21518
|
function setCors(c) {
|
|
21380
21519
|
c.header("Access-Control-Allow-Origin", "*");
|
|
21381
21520
|
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
21382
21521
|
c.header("Access-Control-Allow-Headers", "content-type");
|
|
21383
21522
|
}
|
|
21384
|
-
|
|
21523
|
+
app60.options("/free-busy", (c) => {
|
|
21385
21524
|
setCors(c);
|
|
21386
21525
|
return c.body(null, 204);
|
|
21387
21526
|
});
|
|
21388
|
-
|
|
21527
|
+
app60.get("/free-busy", async (c) => {
|
|
21389
21528
|
setCors(c);
|
|
21390
21529
|
const from = c.req.query("from");
|
|
21391
21530
|
const to = c.req.query("to");
|
|
@@ -21427,10 +21566,10 @@ app59.get("/free-busy", async (c) => {
|
|
|
21427
21566
|
await session.close();
|
|
21428
21567
|
}
|
|
21429
21568
|
});
|
|
21430
|
-
var calendar_public_default =
|
|
21569
|
+
var calendar_public_default = app60;
|
|
21431
21570
|
|
|
21432
21571
|
// app/lib/timeentry-census.ts
|
|
21433
|
-
var
|
|
21572
|
+
var TAG40 = "[timeentry-census]";
|
|
21434
21573
|
function reconcileTimeEntries(rows, now, horizonMs) {
|
|
21435
21574
|
const openEntries = rows.openEntries.length;
|
|
21436
21575
|
let oldestOpenAgeMs = 0;
|
|
@@ -21440,9 +21579,9 @@ function reconcileTimeEntries(rows, now, horizonMs) {
|
|
|
21440
21579
|
perAccount.set(e.accountId, (perAccount.get(e.accountId) ?? 0) + 1);
|
|
21441
21580
|
}
|
|
21442
21581
|
const maxOpenPerAccount = perAccount.size === 0 ? 0 : Math.max(...perAccount.values());
|
|
21443
|
-
const driftTasks = rows.taskSums.filter((t) => t.secondsLogged !== t.sumEntries).length;
|
|
21582
|
+
const driftTasks = rows.taskSums.filter((t) => t.secondsLogged !== t.sumEntries + (t.sumAdjustments ?? 0)).length;
|
|
21444
21583
|
const oldestOpenAgeMin = Math.floor(oldestOpenAgeMs / 6e4);
|
|
21445
|
-
const alarm = oldestOpenAgeMs > horizonMs ||
|
|
21584
|
+
const alarm = oldestOpenAgeMs > horizonMs || driftTasks > 0;
|
|
21446
21585
|
return { openEntries, oldestOpenAgeMin, maxOpenPerAccount, driftTasks, alarm };
|
|
21447
21586
|
}
|
|
21448
21587
|
async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
@@ -21458,20 +21597,24 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
|
21458
21597
|
const sumRes = await session.run(
|
|
21459
21598
|
`MATCH (t:Task) WHERE t.secondsLogged IS NOT NULL
|
|
21460
21599
|
OPTIONAL MATCH (te:TimeEntry {taskId: t.taskId}) WHERE te.endedAt IS NOT NULL
|
|
21461
|
-
|
|
21600
|
+
WITH t, coalesce(sum(te.seconds), 0) AS sumEntries
|
|
21601
|
+
OPTIONAL MATCH (ta:TimeAdjustment {taskId: t.taskId})
|
|
21602
|
+
RETURN t.taskId AS taskId, coalesce(t.secondsLogged, 0) AS secondsLogged,
|
|
21603
|
+
sumEntries, coalesce(sum(ta.delta), 0) AS sumAdjustments`
|
|
21462
21604
|
);
|
|
21463
21605
|
const taskSums = sumRes.records.map((r) => ({
|
|
21464
21606
|
taskId: r.get("taskId") ?? "",
|
|
21465
21607
|
secondsLogged: toNum(r.get("secondsLogged")),
|
|
21466
|
-
sumEntries: toNum(r.get("sumEntries"))
|
|
21608
|
+
sumEntries: toNum(r.get("sumEntries")),
|
|
21609
|
+
sumAdjustments: toNum(r.get("sumAdjustments"))
|
|
21467
21610
|
}));
|
|
21468
21611
|
const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
|
|
21469
|
-
const line = `${
|
|
21612
|
+
const line = `${TAG40} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
|
|
21470
21613
|
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
21471
21614
|
else console.log(line);
|
|
21472
21615
|
return finding;
|
|
21473
21616
|
} catch (err) {
|
|
21474
|
-
console.error(`${
|
|
21617
|
+
console.error(`${TAG40} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21475
21618
|
return null;
|
|
21476
21619
|
}
|
|
21477
21620
|
}
|
|
@@ -21485,13 +21628,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
21485
21628
|
try {
|
|
21486
21629
|
session = openSession();
|
|
21487
21630
|
} catch (err) {
|
|
21488
|
-
console.error(`${
|
|
21631
|
+
console.error(`${TAG40} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21489
21632
|
return;
|
|
21490
21633
|
}
|
|
21491
21634
|
try {
|
|
21492
21635
|
await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
|
|
21493
21636
|
} catch (err) {
|
|
21494
|
-
console.error(`${
|
|
21637
|
+
console.error(`${TAG40} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21495
21638
|
} finally {
|
|
21496
21639
|
try {
|
|
21497
21640
|
await session.close();
|
|
@@ -21854,8 +21997,8 @@ async function migrateUploads(opts = {}) {
|
|
|
21854
21997
|
|
|
21855
21998
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
21856
21999
|
import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
|
|
21857
|
-
import { existsSync as
|
|
21858
|
-
import { join as
|
|
22000
|
+
import { existsSync as existsSync33 } from "fs";
|
|
22001
|
+
import { join as join34 } from "path";
|
|
21859
22002
|
var ADMIN_ROLE2 = "admin";
|
|
21860
22003
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
21861
22004
|
var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
|
|
@@ -21884,7 +22027,7 @@ async function writeRaw(path2, obj) {
|
|
|
21884
22027
|
await rename3(tmp, path2);
|
|
21885
22028
|
} catch (err) {
|
|
21886
22029
|
try {
|
|
21887
|
-
if (
|
|
22030
|
+
if (existsSync33(tmp)) await unlink3(tmp);
|
|
21888
22031
|
} catch {
|
|
21889
22032
|
}
|
|
21890
22033
|
throw err;
|
|
@@ -21900,7 +22043,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21900
22043
|
}
|
|
21901
22044
|
for (const slug of slugs) {
|
|
21902
22045
|
if (!slug.isDirectory()) continue;
|
|
21903
|
-
const slugDir =
|
|
22046
|
+
const slugDir = join34(projectsRoot, slug.name);
|
|
21904
22047
|
let entries;
|
|
21905
22048
|
try {
|
|
21906
22049
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -21909,9 +22052,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21909
22052
|
}
|
|
21910
22053
|
for (const entry of entries) {
|
|
21911
22054
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
21912
|
-
out.push(
|
|
22055
|
+
out.push(join34(slugDir, entry.name));
|
|
21913
22056
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
21914
|
-
const subDir =
|
|
22057
|
+
const subDir = join34(slugDir, entry.name);
|
|
21915
22058
|
let subs;
|
|
21916
22059
|
try {
|
|
21917
22060
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -21919,7 +22062,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21919
22062
|
continue;
|
|
21920
22063
|
}
|
|
21921
22064
|
for (const s of subs) {
|
|
21922
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
22065
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join34(subDir, s.name));
|
|
21923
22066
|
}
|
|
21924
22067
|
}
|
|
21925
22068
|
}
|
|
@@ -21931,7 +22074,7 @@ function shortId(path2) {
|
|
|
21931
22074
|
return base.slice(0, 8);
|
|
21932
22075
|
}
|
|
21933
22076
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
21934
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
22077
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join34(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
21935
22078
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
21936
22079
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
21937
22080
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -22276,8 +22419,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
22276
22419
|
|
|
22277
22420
|
// app/lib/whatsapp/gateway/routes.ts
|
|
22278
22421
|
function createWaChannelRoutes(deps) {
|
|
22279
|
-
const
|
|
22280
|
-
|
|
22422
|
+
const app62 = new Hono();
|
|
22423
|
+
app62.get("/wa-channel/inbound", (c) => {
|
|
22281
22424
|
const senderId = c.req.query("senderId");
|
|
22282
22425
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
22283
22426
|
return streamSSE(c, async (stream2) => {
|
|
@@ -22295,7 +22438,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22295
22438
|
}
|
|
22296
22439
|
});
|
|
22297
22440
|
});
|
|
22298
|
-
|
|
22441
|
+
app62.post("/wa-channel/reply", async (c) => {
|
|
22299
22442
|
const body = await c.req.json().catch(() => null);
|
|
22300
22443
|
const senderId = body?.senderId;
|
|
22301
22444
|
const text = body?.text;
|
|
@@ -22316,7 +22459,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22316
22459
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
22317
22460
|
return c.json({ ok: true });
|
|
22318
22461
|
});
|
|
22319
|
-
|
|
22462
|
+
app62.post("/wa-channel/reply-document", async (c) => {
|
|
22320
22463
|
const body = await c.req.json().catch(() => null);
|
|
22321
22464
|
const senderId = body?.senderId;
|
|
22322
22465
|
const files = body?.files;
|
|
@@ -22355,7 +22498,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22355
22498
|
}
|
|
22356
22499
|
return c.json({ ok: true, results });
|
|
22357
22500
|
});
|
|
22358
|
-
|
|
22501
|
+
app62.post("/wa-channel/ready", async (c) => {
|
|
22359
22502
|
const body = await c.req.json().catch(() => null);
|
|
22360
22503
|
const senderId = body?.senderId;
|
|
22361
22504
|
if (typeof senderId !== "string") {
|
|
@@ -22364,7 +22507,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22364
22507
|
deps.onReady?.(senderId);
|
|
22365
22508
|
return c.json({ ok: true });
|
|
22366
22509
|
});
|
|
22367
|
-
|
|
22510
|
+
app62.post("/wa-channel/received", async (c) => {
|
|
22368
22511
|
const body = await c.req.json().catch(() => null);
|
|
22369
22512
|
const senderId = body?.senderId;
|
|
22370
22513
|
const waMessageId = body?.waMessageId;
|
|
@@ -22374,7 +22517,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22374
22517
|
deps.onReceived?.(senderId, waMessageId);
|
|
22375
22518
|
return c.json({ ok: true });
|
|
22376
22519
|
});
|
|
22377
|
-
|
|
22520
|
+
app62.post("/wa-channel/turn-end", async (c) => {
|
|
22378
22521
|
const body = await c.req.json().catch(() => null);
|
|
22379
22522
|
const senderId = body?.senderId;
|
|
22380
22523
|
const sessionId = body?.sessionId;
|
|
@@ -22407,7 +22550,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22407
22550
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
|
|
22408
22551
|
return c.json({ ok: true, delivered: "none" });
|
|
22409
22552
|
});
|
|
22410
|
-
return
|
|
22553
|
+
return app62;
|
|
22411
22554
|
}
|
|
22412
22555
|
|
|
22413
22556
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -22499,10 +22642,12 @@ var WaGateway = class {
|
|
|
22499
22642
|
this.docContexts.set(input.senderId, { accountId: input.accountId, maxyAccountId: input.effectiveAccountId });
|
|
22500
22643
|
let standingRules;
|
|
22501
22644
|
if (this.deps.fetchStandingRules) {
|
|
22502
|
-
|
|
22503
|
-
|
|
22645
|
+
const res = await this.deps.fetchStandingRules(input.effectiveAccountId);
|
|
22646
|
+
standingRules = res.block || void 0;
|
|
22647
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
22648
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
22504
22649
|
console.error(
|
|
22505
|
-
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} capped=${injected >= import_dist5.INJECTION_RULE_CAP}`
|
|
22650
|
+
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist5.INJECTION_RULE_CAP}`
|
|
22506
22651
|
);
|
|
22507
22652
|
}
|
|
22508
22653
|
this.hub.deliver(
|
|
@@ -22748,8 +22893,8 @@ var import_dist6 = __toESM(require_dist(), 1);
|
|
|
22748
22893
|
|
|
22749
22894
|
// app/lib/webchat/gateway/routes.ts
|
|
22750
22895
|
function createWebchatChannelRoutes(deps) {
|
|
22751
|
-
const
|
|
22752
|
-
|
|
22896
|
+
const app62 = new Hono();
|
|
22897
|
+
app62.get("/webchat-channel/inbound", (c) => {
|
|
22753
22898
|
const key = c.req.query("key");
|
|
22754
22899
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
22755
22900
|
return streamSSE(c, async (stream2) => {
|
|
@@ -22767,7 +22912,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22767
22912
|
}
|
|
22768
22913
|
});
|
|
22769
22914
|
});
|
|
22770
|
-
|
|
22915
|
+
app62.post("/webchat-channel/reply", async (c) => {
|
|
22771
22916
|
const body = await c.req.json().catch(() => null);
|
|
22772
22917
|
const key = body?.key;
|
|
22773
22918
|
const text = body?.text;
|
|
@@ -22777,7 +22922,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22777
22922
|
deps.onReply?.(key, text);
|
|
22778
22923
|
return c.json({ ok: true });
|
|
22779
22924
|
});
|
|
22780
|
-
|
|
22925
|
+
app62.post("/webchat-channel/connector-auth", async (c) => {
|
|
22781
22926
|
const body = await c.req.json().catch(() => null);
|
|
22782
22927
|
const key = body?.key;
|
|
22783
22928
|
const sessionId = body?.sessionId;
|
|
@@ -22790,7 +22935,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22790
22935
|
const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
|
|
22791
22936
|
return c.json(result);
|
|
22792
22937
|
});
|
|
22793
|
-
|
|
22938
|
+
app62.post("/webchat-channel/ready", async (c) => {
|
|
22794
22939
|
const body = await c.req.json().catch(() => null);
|
|
22795
22940
|
const key = body?.key;
|
|
22796
22941
|
if (typeof key !== "string") {
|
|
@@ -22799,7 +22944,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22799
22944
|
deps.onReady?.(key);
|
|
22800
22945
|
return c.json({ ok: true });
|
|
22801
22946
|
});
|
|
22802
|
-
|
|
22947
|
+
app62.post("/webchat-channel/permission-request", async (c) => {
|
|
22803
22948
|
const body = await c.req.json().catch(() => null);
|
|
22804
22949
|
const key = body?.key;
|
|
22805
22950
|
const requestId = body?.request_id;
|
|
@@ -22813,7 +22958,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22813
22958
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
22814
22959
|
return c.json(verdict);
|
|
22815
22960
|
});
|
|
22816
|
-
|
|
22961
|
+
app62.post("/webchat-channel/received", async (c) => {
|
|
22817
22962
|
const body = await c.req.json().catch(() => null);
|
|
22818
22963
|
const key = body?.key;
|
|
22819
22964
|
const messageId = body?.messageId;
|
|
@@ -22823,7 +22968,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22823
22968
|
deps.onReceived?.(key, messageId);
|
|
22824
22969
|
return c.json({ ok: true });
|
|
22825
22970
|
});
|
|
22826
|
-
|
|
22971
|
+
app62.post("/webchat-channel/turn-end", async (c) => {
|
|
22827
22972
|
const body = await c.req.json().catch(() => null);
|
|
22828
22973
|
const key = body?.key;
|
|
22829
22974
|
const sessionId = body?.sessionId;
|
|
@@ -22846,7 +22991,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22846
22991
|
console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} delivered=none`);
|
|
22847
22992
|
return c.json({ ok: true, delivered: "none" });
|
|
22848
22993
|
});
|
|
22849
|
-
return
|
|
22994
|
+
return app62;
|
|
22850
22995
|
}
|
|
22851
22996
|
|
|
22852
22997
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -23185,10 +23330,12 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
23185
23330
|
const willDeliverNow = this.hub.isReady(input.key);
|
|
23186
23331
|
let standingRules;
|
|
23187
23332
|
if (input.role === "admin" && this.deps.fetchStandingRules) {
|
|
23188
|
-
|
|
23189
|
-
|
|
23333
|
+
const res = await this.deps.fetchStandingRules(input.accountId);
|
|
23334
|
+
standingRules = res.block || void 0;
|
|
23335
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
23336
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
23190
23337
|
console.error(
|
|
23191
|
-
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
|
|
23338
|
+
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
|
|
23192
23339
|
);
|
|
23193
23340
|
}
|
|
23194
23341
|
this.hub.deliver(
|
|
@@ -23477,7 +23624,7 @@ function makeFileDelivery(opts) {
|
|
|
23477
23624
|
}
|
|
23478
23625
|
|
|
23479
23626
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
23480
|
-
var
|
|
23627
|
+
var TAG41 = "[whatsapp-adaptor]";
|
|
23481
23628
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
23482
23629
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
23483
23630
|
function platformRoot() {
|
|
@@ -23495,7 +23642,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
23495
23642
|
});
|
|
23496
23643
|
if (result.ok) return { ok: true };
|
|
23497
23644
|
console.error(
|
|
23498
|
-
`${
|
|
23645
|
+
`${TAG41} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
23499
23646
|
);
|
|
23500
23647
|
return { ok: false, error: result.error };
|
|
23501
23648
|
};
|
|
@@ -23503,7 +23650,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
23503
23650
|
function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
23504
23651
|
const shared = makeFileDelivery({
|
|
23505
23652
|
entry,
|
|
23506
|
-
tag:
|
|
23653
|
+
tag: TAG41,
|
|
23507
23654
|
channel: "whatsapp",
|
|
23508
23655
|
sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
|
|
23509
23656
|
});
|
|
@@ -23538,7 +23685,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
|
23538
23685
|
if (!delivered) {
|
|
23539
23686
|
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
23540
23687
|
console.error(
|
|
23541
|
-
`${
|
|
23688
|
+
`${TAG41} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
23542
23689
|
);
|
|
23543
23690
|
}
|
|
23544
23691
|
}
|
|
@@ -23715,8 +23862,8 @@ var import_dist7 = __toESM(require_dist(), 1);
|
|
|
23715
23862
|
|
|
23716
23863
|
// app/lib/telegram/gateway/routes.ts
|
|
23717
23864
|
function createTelegramChannelRoutes(deps) {
|
|
23718
|
-
const
|
|
23719
|
-
|
|
23865
|
+
const app62 = new Hono();
|
|
23866
|
+
app62.get("/tg-channel/inbound", (c) => {
|
|
23720
23867
|
const key = c.req.query("key");
|
|
23721
23868
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
23722
23869
|
return streamSSE(c, async (stream2) => {
|
|
@@ -23734,7 +23881,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23734
23881
|
}
|
|
23735
23882
|
});
|
|
23736
23883
|
});
|
|
23737
|
-
|
|
23884
|
+
app62.post("/tg-channel/reply", async (c) => {
|
|
23738
23885
|
const body = await c.req.json().catch(() => null);
|
|
23739
23886
|
const key = body?.key;
|
|
23740
23887
|
const text = body?.text;
|
|
@@ -23750,7 +23897,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23750
23897
|
console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
23751
23898
|
return c.json({ ok: true });
|
|
23752
23899
|
});
|
|
23753
|
-
|
|
23900
|
+
app62.post("/tg-channel/ready", async (c) => {
|
|
23754
23901
|
const body = await c.req.json().catch(() => null);
|
|
23755
23902
|
const key = body?.key;
|
|
23756
23903
|
if (typeof key !== "string") {
|
|
@@ -23759,7 +23906,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23759
23906
|
deps.onReady?.(key);
|
|
23760
23907
|
return c.json({ ok: true });
|
|
23761
23908
|
});
|
|
23762
|
-
|
|
23909
|
+
app62.post("/tg-channel/received", async (c) => {
|
|
23763
23910
|
const body = await c.req.json().catch(() => null);
|
|
23764
23911
|
const key = body?.key;
|
|
23765
23912
|
const messageId = body?.messageId;
|
|
@@ -23769,7 +23916,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23769
23916
|
deps.onReceived?.(key, messageId);
|
|
23770
23917
|
return c.json({ ok: true });
|
|
23771
23918
|
});
|
|
23772
|
-
|
|
23919
|
+
app62.post("/tg-channel/turn-end", async (c) => {
|
|
23773
23920
|
const body = await c.req.json().catch(() => null);
|
|
23774
23921
|
const key = body?.key;
|
|
23775
23922
|
const sessionId = body?.sessionId;
|
|
@@ -23802,7 +23949,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23802
23949
|
console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
|
|
23803
23950
|
return c.json({ ok: true, delivered: "none" });
|
|
23804
23951
|
});
|
|
23805
|
-
return
|
|
23952
|
+
return app62;
|
|
23806
23953
|
}
|
|
23807
23954
|
|
|
23808
23955
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
@@ -23862,10 +24009,12 @@ var TelegramGateway = class {
|
|
|
23862
24009
|
this.replies.set(input.senderId, input.reply);
|
|
23863
24010
|
let standingRules;
|
|
23864
24011
|
if (input.role === "admin" && this.deps.fetchStandingRules) {
|
|
23865
|
-
|
|
23866
|
-
|
|
24012
|
+
const res = await this.deps.fetchStandingRules(input.accountId);
|
|
24013
|
+
standingRules = res.block || void 0;
|
|
24014
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
24015
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
23867
24016
|
console.error(
|
|
23868
|
-
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
|
|
24017
|
+
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
|
|
23869
24018
|
);
|
|
23870
24019
|
}
|
|
23871
24020
|
this.hub.deliver(
|
|
@@ -23929,8 +24078,8 @@ function buildTelegramSpawnRequest(input) {
|
|
|
23929
24078
|
// app/lib/telegram/outbound/send-document.ts
|
|
23930
24079
|
import { realpathSync as realpathSync7 } from "fs";
|
|
23931
24080
|
import { readFile as readFile7, stat as stat7 } from "fs/promises";
|
|
23932
|
-
import { resolve as resolve30, basename as
|
|
23933
|
-
var
|
|
24081
|
+
import { resolve as resolve30, basename as basename11 } from "path";
|
|
24082
|
+
var TAG42 = "[telegram:outbound]";
|
|
23934
24083
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
23935
24084
|
async function sendTelegramDocument(input) {
|
|
23936
24085
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot3 } = input;
|
|
@@ -23946,16 +24095,16 @@ async function sendTelegramDocument(input) {
|
|
|
23946
24095
|
resolvedPath = realpathSync7(filePath);
|
|
23947
24096
|
const accountResolved = realpathSync7(accountDir);
|
|
23948
24097
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
23949
|
-
console.error(`${
|
|
24098
|
+
console.error(`${TAG42} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
23950
24099
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
23951
24100
|
}
|
|
23952
24101
|
} catch (err) {
|
|
23953
24102
|
const code = err.code;
|
|
23954
24103
|
if (code === "ENOENT") {
|
|
23955
|
-
console.error(`${
|
|
24104
|
+
console.error(`${TAG42} document ENOENT path=${filePath}`);
|
|
23956
24105
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
23957
24106
|
}
|
|
23958
|
-
console.error(`${
|
|
24107
|
+
console.error(`${TAG42} document path error: ${String(err)}`);
|
|
23959
24108
|
return { ok: false, status: 500, error: String(err) };
|
|
23960
24109
|
}
|
|
23961
24110
|
const fileStat = await stat7(resolvedPath);
|
|
@@ -23966,7 +24115,7 @@ async function sendTelegramDocument(input) {
|
|
|
23966
24115
|
error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
|
|
23967
24116
|
};
|
|
23968
24117
|
}
|
|
23969
|
-
const filename =
|
|
24118
|
+
const filename = basename11(resolvedPath);
|
|
23970
24119
|
const buffer = Buffer.from(await readFile7(resolvedPath));
|
|
23971
24120
|
const form = new FormData();
|
|
23972
24121
|
form.append("chat_id", String(chatId));
|
|
@@ -23988,13 +24137,13 @@ async function sendTelegramDocument(input) {
|
|
|
23988
24137
|
error = e instanceof Error ? e.message : String(e);
|
|
23989
24138
|
}
|
|
23990
24139
|
console.error(
|
|
23991
|
-
`${
|
|
24140
|
+
`${TAG42} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
23992
24141
|
);
|
|
23993
24142
|
return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
23994
24143
|
}
|
|
23995
24144
|
|
|
23996
24145
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
23997
|
-
var
|
|
24146
|
+
var TAG43 = "[telegram:outbound]";
|
|
23998
24147
|
function platformRoot2() {
|
|
23999
24148
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
24000
24149
|
}
|
|
@@ -24006,11 +24155,11 @@ function makeTelegramSendFile(entry) {
|
|
|
24006
24155
|
botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
|
|
24007
24156
|
}
|
|
24008
24157
|
if (!botToken) {
|
|
24009
|
-
console.error(`${
|
|
24158
|
+
console.error(`${TAG43} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
|
|
24010
24159
|
return { ok: false, error: "no-bot-token" };
|
|
24011
24160
|
}
|
|
24012
24161
|
if (entry.replyTarget == null) {
|
|
24013
|
-
console.error(`${
|
|
24162
|
+
console.error(`${TAG43} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
|
|
24014
24163
|
return { ok: false, error: "no-reply-target" };
|
|
24015
24164
|
}
|
|
24016
24165
|
const result = await sendTelegramDocument({
|
|
@@ -24027,7 +24176,7 @@ function makeTelegramSendFile(entry) {
|
|
|
24027
24176
|
function makeTelegramFileDelivery(entry) {
|
|
24028
24177
|
return makeFileDelivery({
|
|
24029
24178
|
entry,
|
|
24030
|
-
tag:
|
|
24179
|
+
tag: TAG43,
|
|
24031
24180
|
channel: "telegram",
|
|
24032
24181
|
sendFile: makeTelegramSendFile(entry)
|
|
24033
24182
|
});
|
|
@@ -24067,17 +24216,17 @@ function startTelegramNativeFileFollower(input) {
|
|
|
24067
24216
|
}
|
|
24068
24217
|
|
|
24069
24218
|
// server/telegram-descriptor.ts
|
|
24070
|
-
import { resolve as resolve31, join as
|
|
24219
|
+
import { resolve as resolve31, join as join35 } from "path";
|
|
24071
24220
|
function telegramGatewayUrl() {
|
|
24072
24221
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
24073
24222
|
}
|
|
24074
24223
|
function telegramServerPath() {
|
|
24075
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
24224
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
24076
24225
|
}
|
|
24077
24226
|
|
|
24078
24227
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
24079
|
-
import { randomUUID as
|
|
24080
|
-
var
|
|
24228
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
24229
|
+
var TAG44 = "[public-session-review]";
|
|
24081
24230
|
var CONSUMED_CAP = 500;
|
|
24082
24231
|
var consumed = /* @__PURE__ */ new Set();
|
|
24083
24232
|
function consumeOnce(sessionId) {
|
|
@@ -24104,7 +24253,7 @@ async function fetchJsonl(sessionId) {
|
|
|
24104
24253
|
return await res.text();
|
|
24105
24254
|
} catch (err) {
|
|
24106
24255
|
console.error(
|
|
24107
|
-
`${
|
|
24256
|
+
`${TAG44} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
24108
24257
|
);
|
|
24109
24258
|
return null;
|
|
24110
24259
|
}
|
|
@@ -24128,7 +24277,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
24128
24277
|
const res = await fetch(url);
|
|
24129
24278
|
if (!res.ok) {
|
|
24130
24279
|
console.error(
|
|
24131
|
-
`${
|
|
24280
|
+
`${TAG44} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
24132
24281
|
);
|
|
24133
24282
|
return [];
|
|
24134
24283
|
}
|
|
@@ -24136,7 +24285,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
24136
24285
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
24137
24286
|
} catch (err) {
|
|
24138
24287
|
console.error(
|
|
24139
|
-
`${
|
|
24288
|
+
`${TAG44} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
24140
24289
|
);
|
|
24141
24290
|
return [];
|
|
24142
24291
|
}
|
|
@@ -24164,8 +24313,8 @@ function composeInitialMessage(input) {
|
|
|
24164
24313
|
].join("\n");
|
|
24165
24314
|
}
|
|
24166
24315
|
async function dispatchReviewer(input, initialMessage) {
|
|
24167
|
-
const sessionId =
|
|
24168
|
-
console.log(`${
|
|
24316
|
+
const sessionId = randomUUID15();
|
|
24317
|
+
console.log(`${TAG44} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
24169
24318
|
const spawned = await managerRcSpawn({
|
|
24170
24319
|
sessionId,
|
|
24171
24320
|
initialMessage,
|
|
@@ -24185,21 +24334,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
24185
24334
|
const dispatchedAt = Date.now();
|
|
24186
24335
|
if (consumed.has(input.sessionId)) {
|
|
24187
24336
|
console.log(
|
|
24188
|
-
`${
|
|
24337
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
24189
24338
|
);
|
|
24190
24339
|
return;
|
|
24191
24340
|
}
|
|
24192
24341
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
24193
24342
|
if (!jsonl) {
|
|
24194
24343
|
console.log(
|
|
24195
|
-
`${
|
|
24344
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
24196
24345
|
);
|
|
24197
24346
|
return;
|
|
24198
24347
|
}
|
|
24199
24348
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
24200
24349
|
if (operatorTurns === 0) {
|
|
24201
24350
|
console.log(
|
|
24202
|
-
`${
|
|
24351
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
24203
24352
|
);
|
|
24204
24353
|
return;
|
|
24205
24354
|
}
|
|
@@ -24213,19 +24362,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
24213
24362
|
});
|
|
24214
24363
|
if (!consumeOnce(input.sessionId)) {
|
|
24215
24364
|
console.log(
|
|
24216
|
-
`${
|
|
24365
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
24217
24366
|
);
|
|
24218
24367
|
return;
|
|
24219
24368
|
}
|
|
24220
24369
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
24221
24370
|
if (!dispatched.ok) {
|
|
24222
24371
|
console.error(
|
|
24223
|
-
`${
|
|
24372
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
24224
24373
|
);
|
|
24225
24374
|
return;
|
|
24226
24375
|
}
|
|
24227
24376
|
console.log(
|
|
24228
|
-
`${
|
|
24377
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
|
|
24229
24378
|
);
|
|
24230
24379
|
}
|
|
24231
24380
|
|
|
@@ -24334,7 +24483,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
24334
24483
|
|
|
24335
24484
|
// ../lib/entitlement/src/index.ts
|
|
24336
24485
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
24337
|
-
import { existsSync as
|
|
24486
|
+
import { existsSync as existsSync34, readFileSync as readFileSync34, statSync as statSync13 } from "fs";
|
|
24338
24487
|
import { resolve as resolve32 } from "path";
|
|
24339
24488
|
|
|
24340
24489
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -24383,7 +24532,7 @@ function resolveEntitlement(brand, account) {
|
|
|
24383
24532
|
return logResolved(implicitTrust(account), null);
|
|
24384
24533
|
}
|
|
24385
24534
|
const entitlementPath = resolve32(brand.configDir, "entitlement.json");
|
|
24386
|
-
if (!
|
|
24535
|
+
if (!existsSync34(entitlementPath)) {
|
|
24387
24536
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
24388
24537
|
}
|
|
24389
24538
|
const stat8 = statSync13(entitlementPath);
|
|
@@ -24573,12 +24722,12 @@ function clientFrom(c) {
|
|
|
24573
24722
|
);
|
|
24574
24723
|
}
|
|
24575
24724
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
24576
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
24725
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join36(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
24577
24726
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
24578
|
-
if (BRAND_JSON_PATH && !
|
|
24727
|
+
if (BRAND_JSON_PATH && !existsSync35(BRAND_JSON_PATH)) {
|
|
24579
24728
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
24580
24729
|
}
|
|
24581
|
-
if (BRAND_JSON_PATH &&
|
|
24730
|
+
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
24582
24731
|
try {
|
|
24583
24732
|
const parsed = JSON.parse(readFileSync35(BRAND_JSON_PATH, "utf-8"));
|
|
24584
24733
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -24612,10 +24761,10 @@ var brandLoginOpts = {
|
|
|
24612
24761
|
appleTouchIconPath: brandAppIcon512Path,
|
|
24613
24762
|
themeColor: BRAND.defaultColors?.primary
|
|
24614
24763
|
};
|
|
24615
|
-
var ALIAS_DOMAINS_PATH =
|
|
24764
|
+
var ALIAS_DOMAINS_PATH = join36(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
24616
24765
|
function loadAliasDomains() {
|
|
24617
24766
|
try {
|
|
24618
|
-
if (!
|
|
24767
|
+
if (!existsSync35(ALIAS_DOMAINS_PATH)) return null;
|
|
24619
24768
|
const parsed = JSON.parse(readFileSync35(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
24620
24769
|
if (!Array.isArray(parsed)) {
|
|
24621
24770
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -24640,18 +24789,18 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
24640
24789
|
function isPublicHost(host) {
|
|
24641
24790
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
24642
24791
|
}
|
|
24643
|
-
var
|
|
24792
|
+
var app61 = new Hono();
|
|
24644
24793
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
24645
24794
|
async function fetchAccountStandingRules(accountId) {
|
|
24646
24795
|
const session = getSession();
|
|
24647
24796
|
try {
|
|
24648
|
-
const
|
|
24649
|
-
return (0, import_dist8.formatStandingRulesBlock)(rules);
|
|
24797
|
+
const res = await (0, import_dist8.resolveActiveRules)(session, accountId);
|
|
24798
|
+
return { block: (0, import_dist8.formatStandingRulesBlock)(res.rules), ownerUserId: res.ownerUserId, source: res.source };
|
|
24650
24799
|
} catch (err) {
|
|
24651
24800
|
console.error(
|
|
24652
24801
|
`[preference-inject] op=fetch-failed accountId=${accountId} error=${err instanceof Error ? err.message : String(err)}`
|
|
24653
24802
|
);
|
|
24654
|
-
return "";
|
|
24803
|
+
return { block: "", ownerUserId: null, source: "fetch-error" };
|
|
24655
24804
|
} finally {
|
|
24656
24805
|
await session.close();
|
|
24657
24806
|
}
|
|
@@ -24679,7 +24828,7 @@ async function recordPassiveDispatch(input) {
|
|
|
24679
24828
|
var waGateway = new WaGateway({
|
|
24680
24829
|
fetchStandingRules: fetchAccountStandingRules,
|
|
24681
24830
|
gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
|
|
24682
|
-
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
24831
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
24683
24832
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
24684
24833
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
24685
24834
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -24694,7 +24843,7 @@ var waGateway = new WaGateway({
|
|
|
24694
24843
|
caption,
|
|
24695
24844
|
accountId,
|
|
24696
24845
|
maxyAccountId,
|
|
24697
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
24846
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."))
|
|
24698
24847
|
});
|
|
24699
24848
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
24700
24849
|
},
|
|
@@ -24775,7 +24924,7 @@ var waGateway = new WaGateway({
|
|
|
24775
24924
|
nativeFileFollowers.set(senderId, ac);
|
|
24776
24925
|
}
|
|
24777
24926
|
});
|
|
24778
|
-
|
|
24927
|
+
app61.route("/", waGateway.routes());
|
|
24779
24928
|
waGateway.startSweeper();
|
|
24780
24929
|
var webchatGateway = new WebchatGateway({
|
|
24781
24930
|
fetchStandingRules: fetchAccountStandingRules,
|
|
@@ -24859,7 +25008,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
24859
25008
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
24860
25009
|
});
|
|
24861
25010
|
setWebchatGateway(webchatGateway);
|
|
24862
|
-
|
|
25011
|
+
app61.route("/", webchatGateway.routes());
|
|
24863
25012
|
webchatGateway.startSweeper();
|
|
24864
25013
|
webchatGateway.startPublicReaper();
|
|
24865
25014
|
var telegramFileFollowers = /* @__PURE__ */ new Map();
|
|
@@ -24893,7 +25042,7 @@ var telegramGateway = new TelegramGateway({
|
|
|
24893
25042
|
}
|
|
24894
25043
|
});
|
|
24895
25044
|
setTelegramGateway(telegramGateway);
|
|
24896
|
-
|
|
25045
|
+
app61.route("/", telegramGateway.routes());
|
|
24897
25046
|
telegramGateway.startSweeper();
|
|
24898
25047
|
var chatRoutes = createChatRoutes({
|
|
24899
25048
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
@@ -24926,19 +25075,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
24926
25075
|
return managed.account;
|
|
24927
25076
|
}
|
|
24928
25077
|
});
|
|
24929
|
-
|
|
24930
|
-
|
|
25078
|
+
app61.route("/api/channel/schedule-inject", scheduleInjectRoutes);
|
|
25079
|
+
app61.use("*", clientIpMiddleware);
|
|
24931
25080
|
function allowsSameOriginFraming(path2) {
|
|
24932
25081
|
return path2 === "/vnc-viewer.html" || path2.startsWith("/api/admin/attachment/") || path2.startsWith("/api/public-reader/attachment/") || path2 === "/api/admin/files/download";
|
|
24933
25082
|
}
|
|
24934
|
-
|
|
25083
|
+
app61.use("*", async (c, next) => {
|
|
24935
25084
|
await next();
|
|
24936
25085
|
c.header("X-Content-Type-Options", "nosniff");
|
|
24937
25086
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
24938
25087
|
c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
|
|
24939
25088
|
});
|
|
24940
25089
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
24941
|
-
|
|
25090
|
+
app61.use("*", async (c, next) => {
|
|
24942
25091
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
24943
25092
|
await next();
|
|
24944
25093
|
return;
|
|
@@ -24956,7 +25105,7 @@ app60.use("*", async (c, next) => {
|
|
|
24956
25105
|
});
|
|
24957
25106
|
}
|
|
24958
25107
|
});
|
|
24959
|
-
|
|
25108
|
+
app61.use("*", async (c, next) => {
|
|
24960
25109
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
24961
25110
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
24962
25111
|
await next();
|
|
@@ -24994,7 +25143,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
24994
25143
|
return { ...brandLoginOpts, origin };
|
|
24995
25144
|
}
|
|
24996
25145
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
24997
|
-
|
|
25146
|
+
app61.post("/__remote-auth/login", async (c) => {
|
|
24998
25147
|
const client = clientFrom(c);
|
|
24999
25148
|
const clientIp = client.ip || "unknown";
|
|
25000
25149
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -25039,7 +25188,7 @@ app60.post("/__remote-auth/login", async (c) => {
|
|
|
25039
25188
|
}
|
|
25040
25189
|
});
|
|
25041
25190
|
});
|
|
25042
|
-
|
|
25191
|
+
app61.get("/__remote-auth/logout", (c) => {
|
|
25043
25192
|
const client = clientFrom(c);
|
|
25044
25193
|
const clientIp = client.ip || "unknown";
|
|
25045
25194
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -25052,7 +25201,7 @@ app60.get("/__remote-auth/logout", (c) => {
|
|
|
25052
25201
|
}
|
|
25053
25202
|
});
|
|
25054
25203
|
});
|
|
25055
|
-
|
|
25204
|
+
app61.post("/__remote-auth/change-password", async (c) => {
|
|
25056
25205
|
const client = clientFrom(c);
|
|
25057
25206
|
const clientIp = client.ip || "unknown";
|
|
25058
25207
|
const rateLimited = checkRateLimit(client);
|
|
@@ -25111,13 +25260,13 @@ app60.post("/__remote-auth/change-password", async (c) => {
|
|
|
25111
25260
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
25112
25261
|
}
|
|
25113
25262
|
});
|
|
25114
|
-
|
|
25263
|
+
app61.get("/__remote-auth/setup", (c) => {
|
|
25115
25264
|
if (isRemoteAuthConfigured()) {
|
|
25116
25265
|
return c.redirect("/");
|
|
25117
25266
|
}
|
|
25118
25267
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
25119
25268
|
});
|
|
25120
|
-
|
|
25269
|
+
app61.post("/__remote-auth/set-initial-password", async (c) => {
|
|
25121
25270
|
if (isRemoteAuthConfigured()) {
|
|
25122
25271
|
return c.redirect("/");
|
|
25123
25272
|
}
|
|
@@ -25155,10 +25304,10 @@ app60.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
25155
25304
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
25156
25305
|
}
|
|
25157
25306
|
});
|
|
25158
|
-
|
|
25307
|
+
app61.get("/api/remote-auth/status", (c) => {
|
|
25159
25308
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
25160
25309
|
});
|
|
25161
|
-
|
|
25310
|
+
app61.post("/api/remote-auth/set-password", async (c) => {
|
|
25162
25311
|
let body;
|
|
25163
25312
|
try {
|
|
25164
25313
|
body = await c.req.json();
|
|
@@ -25197,10 +25346,10 @@ app60.post("/api/remote-auth/set-password", async (c) => {
|
|
|
25197
25346
|
return c.json({ error: "Failed to save password" }, 500);
|
|
25198
25347
|
}
|
|
25199
25348
|
});
|
|
25200
|
-
|
|
25349
|
+
app61.route("/api/_client-error", client_error_default);
|
|
25201
25350
|
console.log("[client-error-route] mounted");
|
|
25202
25351
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
25203
|
-
|
|
25352
|
+
app61.use("*", async (c, next) => {
|
|
25204
25353
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25205
25354
|
const path2 = c.req.path;
|
|
25206
25355
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
|
|
@@ -25244,26 +25393,26 @@ app60.use("*", async (c, next) => {
|
|
|
25244
25393
|
}
|
|
25245
25394
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path2 }), 200);
|
|
25246
25395
|
});
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25396
|
+
app61.route("/api/health", health_default);
|
|
25397
|
+
app61.route("/api/chat", chatRoutes);
|
|
25398
|
+
app61.route("/api/whatsapp", whatsapp_default);
|
|
25399
|
+
app61.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
25400
|
+
app61.route("/api/public-reader", public_reader_default);
|
|
25401
|
+
app61.route("/api/webchat", createWebchatRoutes({
|
|
25253
25402
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
25254
25403
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
25255
25404
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
25256
25405
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
25257
25406
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
25258
25407
|
}));
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
|
|
25408
|
+
app61.route("/api/webchat/greeting", webchat_greeting_default);
|
|
25409
|
+
app61.route("/api/telegram", telegram_default);
|
|
25410
|
+
app61.route("/api/quickbooks", quickbooks_default);
|
|
25411
|
+
app61.route("/api/onboarding", onboarding_default);
|
|
25412
|
+
app61.route("/api/admin", admin_default);
|
|
25413
|
+
app61.route("/api/access", access_default);
|
|
25414
|
+
app61.route("/api/session", session_default2);
|
|
25415
|
+
app61.route("/api/calendar", calendar_public_default);
|
|
25267
25416
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
25268
25417
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
25269
25418
|
var IMAGE_MIME = {
|
|
@@ -25275,7 +25424,7 @@ var IMAGE_MIME = {
|
|
|
25275
25424
|
".svg": "image/svg+xml",
|
|
25276
25425
|
".ico": "image/x-icon"
|
|
25277
25426
|
};
|
|
25278
|
-
|
|
25427
|
+
app61.get("/agent-assets/:slug/:filename", (c) => {
|
|
25279
25428
|
const slug = c.req.param("slug");
|
|
25280
25429
|
const filename = c.req.param("filename");
|
|
25281
25430
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -25297,7 +25446,7 @@ app60.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25297
25446
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
25298
25447
|
return c.text("Forbidden", 403);
|
|
25299
25448
|
}
|
|
25300
|
-
if (!
|
|
25449
|
+
if (!existsSync35(filePath)) {
|
|
25301
25450
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
25302
25451
|
return c.text("Not found", 404);
|
|
25303
25452
|
}
|
|
@@ -25310,7 +25459,7 @@ app60.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25310
25459
|
"Cache-Control": "public, max-age=3600"
|
|
25311
25460
|
});
|
|
25312
25461
|
});
|
|
25313
|
-
|
|
25462
|
+
app61.get("/generated/:filename", (c) => {
|
|
25314
25463
|
const filename = c.req.param("filename");
|
|
25315
25464
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
25316
25465
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -25327,7 +25476,7 @@ app60.get("/generated/:filename", (c) => {
|
|
|
25327
25476
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
25328
25477
|
return c.text("Forbidden", 403);
|
|
25329
25478
|
}
|
|
25330
|
-
if (!
|
|
25479
|
+
if (!existsSync35(filePath)) {
|
|
25331
25480
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
25332
25481
|
return c.text("Not found", 404);
|
|
25333
25482
|
}
|
|
@@ -25340,14 +25489,14 @@ app60.get("/generated/:filename", (c) => {
|
|
|
25340
25489
|
"Cache-Control": "public, max-age=86400"
|
|
25341
25490
|
});
|
|
25342
25491
|
});
|
|
25343
|
-
|
|
25344
|
-
|
|
25345
|
-
|
|
25346
|
-
|
|
25492
|
+
app61.route("/sites", sites_default);
|
|
25493
|
+
app61.route("/listings", listings_default);
|
|
25494
|
+
app61.route("/v", visitor_event_default);
|
|
25495
|
+
app61.route("/v", visitor_consent_default);
|
|
25347
25496
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
25348
25497
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
25349
25498
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
25350
|
-
if (BRAND_JSON_PATH &&
|
|
25499
|
+
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
25351
25500
|
try {
|
|
25352
25501
|
const fullBrand = JSON.parse(readFileSync35(BRAND_JSON_PATH, "utf-8"));
|
|
25353
25502
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -25376,7 +25525,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
25376
25525
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
25377
25526
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
25378
25527
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
25379
|
-
(p) =>
|
|
25528
|
+
(p) => existsSync35(resolve33(process.cwd(), "public", p.replace(/^\//, "")))
|
|
25380
25529
|
);
|
|
25381
25530
|
var SW_SOURCE = (() => {
|
|
25382
25531
|
try {
|
|
@@ -25388,8 +25537,8 @@ var SW_SOURCE = (() => {
|
|
|
25388
25537
|
function readInstalledVersion() {
|
|
25389
25538
|
try {
|
|
25390
25539
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
25391
|
-
const versionFile =
|
|
25392
|
-
if (!
|
|
25540
|
+
const versionFile = join36(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
25541
|
+
if (!existsSync35(versionFile)) return "unknown";
|
|
25393
25542
|
const content = readFileSync35(versionFile, "utf-8").trim();
|
|
25394
25543
|
return content || "unknown";
|
|
25395
25544
|
} catch {
|
|
@@ -25448,12 +25597,12 @@ ${clientErrorReporterScript}
|
|
|
25448
25597
|
return html;
|
|
25449
25598
|
}
|
|
25450
25599
|
function loadBrandingCache(agentSlug) {
|
|
25451
|
-
const configDir2 =
|
|
25600
|
+
const configDir2 = join36(homedir4(), BRAND.configDir);
|
|
25452
25601
|
try {
|
|
25453
25602
|
const accountId = getDefaultAccountId();
|
|
25454
25603
|
if (!accountId) return null;
|
|
25455
|
-
const cachePath =
|
|
25456
|
-
if (!
|
|
25604
|
+
const cachePath = join36(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
25605
|
+
if (!existsSync35(cachePath)) return null;
|
|
25457
25606
|
return JSON.parse(readFileSync35(cachePath, "utf-8"));
|
|
25458
25607
|
} catch {
|
|
25459
25608
|
return null;
|
|
@@ -25498,7 +25647,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
25498
25647
|
function agentUnavailableHtml() {
|
|
25499
25648
|
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>`;
|
|
25500
25649
|
}
|
|
25501
|
-
|
|
25650
|
+
app61.get("/", (c) => {
|
|
25502
25651
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25503
25652
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
25504
25653
|
if (klass === "operator") {
|
|
@@ -25520,12 +25669,12 @@ app60.get("/", (c) => {
|
|
|
25520
25669
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
25521
25670
|
return c.html(cachedHtml("index.html"));
|
|
25522
25671
|
});
|
|
25523
|
-
|
|
25672
|
+
app61.get("/public", (c) => {
|
|
25524
25673
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25525
25674
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25526
25675
|
return c.html(cachedHtml("public.html"));
|
|
25527
25676
|
});
|
|
25528
|
-
|
|
25677
|
+
app61.get("/public-chat", (c) => {
|
|
25529
25678
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25530
25679
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25531
25680
|
return c.html(cachedHtml("public.html"));
|
|
@@ -25544,9 +25693,9 @@ async function logViewerFetch(c, next) {
|
|
|
25544
25693
|
duration_ms: Date.now() - start
|
|
25545
25694
|
});
|
|
25546
25695
|
}
|
|
25547
|
-
|
|
25548
|
-
|
|
25549
|
-
|
|
25696
|
+
app61.use("/vnc-viewer.html", logViewerFetch);
|
|
25697
|
+
app61.use("/vnc-popout.html", logViewerFetch);
|
|
25698
|
+
app61.get("/vnc-popout.html", (c) => {
|
|
25550
25699
|
let html = htmlCache.get("vnc-popout.html");
|
|
25551
25700
|
if (!html) {
|
|
25552
25701
|
html = readFileSync35(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -25559,7 +25708,7 @@ app60.get("/vnc-popout.html", (c) => {
|
|
|
25559
25708
|
}
|
|
25560
25709
|
return c.html(html);
|
|
25561
25710
|
});
|
|
25562
|
-
|
|
25711
|
+
app61.post("/api/vnc/client-event", async (c) => {
|
|
25563
25712
|
let body;
|
|
25564
25713
|
try {
|
|
25565
25714
|
body = await c.req.json();
|
|
@@ -25580,11 +25729,11 @@ app60.post("/api/vnc/client-event", async (c) => {
|
|
|
25580
25729
|
});
|
|
25581
25730
|
return c.json({ ok: true });
|
|
25582
25731
|
});
|
|
25583
|
-
|
|
25732
|
+
app61.get("/g/:slug", (c) => {
|
|
25584
25733
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
25585
25734
|
});
|
|
25586
25735
|
for (const pwa of PWA_SURFACES) {
|
|
25587
|
-
|
|
25736
|
+
app61.get(pwa.manifestPath, (c) => {
|
|
25588
25737
|
const manifest = buildManifest(pwa, {
|
|
25589
25738
|
productName: BRAND.productName,
|
|
25590
25739
|
appIcon192: brandAppIcon192Path,
|
|
@@ -25600,7 +25749,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
25600
25749
|
return c.body(JSON.stringify(manifest));
|
|
25601
25750
|
});
|
|
25602
25751
|
}
|
|
25603
|
-
|
|
25752
|
+
app61.get("/sw.js", (c) => {
|
|
25604
25753
|
if (SW_SOURCE == null) {
|
|
25605
25754
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
25606
25755
|
return c.text("Service worker unavailable", 500);
|
|
@@ -25609,12 +25758,12 @@ app60.get("/sw.js", (c) => {
|
|
|
25609
25758
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
25610
25759
|
return c.body(SW_SOURCE);
|
|
25611
25760
|
});
|
|
25612
|
-
|
|
25761
|
+
app61.get("/graph", (c) => {
|
|
25613
25762
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25614
25763
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
25615
25764
|
return c.html(cachedHtml("graph.html"));
|
|
25616
25765
|
});
|
|
25617
|
-
|
|
25766
|
+
app61.get("/chat", (c) => {
|
|
25618
25767
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25619
25768
|
if (isOperatorHost(host, getOperatorDomains())) {
|
|
25620
25769
|
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
@@ -25623,27 +25772,27 @@ app60.get("/chat", (c) => {
|
|
|
25623
25772
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25624
25773
|
return c.html(cachedHtml("chat.html"));
|
|
25625
25774
|
});
|
|
25626
|
-
|
|
25775
|
+
app61.get("/data", (c) => {
|
|
25627
25776
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25628
25777
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25629
25778
|
return c.html(cachedHtml("data.html"));
|
|
25630
25779
|
});
|
|
25631
|
-
|
|
25780
|
+
app61.get("/tasks", (c) => {
|
|
25632
25781
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25633
25782
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25634
25783
|
return c.html(cachedHtml("tasks.html"));
|
|
25635
25784
|
});
|
|
25636
|
-
|
|
25785
|
+
app61.get("/calendar", (c) => {
|
|
25637
25786
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25638
25787
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25639
25788
|
return c.html(cachedHtml("calendar.html"));
|
|
25640
25789
|
});
|
|
25641
|
-
|
|
25790
|
+
app61.get("/browser", (c) => {
|
|
25642
25791
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25643
25792
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
25644
25793
|
return c.html(cachedHtml("browser.html"));
|
|
25645
25794
|
});
|
|
25646
|
-
|
|
25795
|
+
app61.get("/:slug", async (c, next) => {
|
|
25647
25796
|
const slug = c.req.param("slug");
|
|
25648
25797
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
25649
25798
|
const account = resolveAccount();
|
|
@@ -25658,13 +25807,13 @@ app60.get("/:slug", async (c, next) => {
|
|
|
25658
25807
|
await next();
|
|
25659
25808
|
});
|
|
25660
25809
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
25661
|
-
|
|
25810
|
+
app61.get("/favicon.ico", (c) => {
|
|
25662
25811
|
c.header("Cache-Control", "public, max-age=300");
|
|
25663
25812
|
return c.redirect(brandFaviconPath, 302);
|
|
25664
25813
|
});
|
|
25665
25814
|
}
|
|
25666
|
-
|
|
25667
|
-
|
|
25815
|
+
app61.use("/*", serveStatic({ root: "./public" }));
|
|
25816
|
+
app61.all("*", (c) => {
|
|
25668
25817
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25669
25818
|
const path2 = c.req.path;
|
|
25670
25819
|
if (isPublicHost(host)) {
|
|
@@ -25678,14 +25827,14 @@ app60.all("*", (c) => {
|
|
|
25678
25827
|
});
|
|
25679
25828
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
25680
25829
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
25681
|
-
var httpServer = serve({ fetch:
|
|
25830
|
+
var httpServer = serve({ fetch: app61.fetch, port, hostname });
|
|
25682
25831
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
25683
25832
|
{
|
|
25684
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
25833
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
|
|
25685
25834
|
const reconcileScript = resolve33(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
25686
25835
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
25687
25836
|
const runReconcile = () => {
|
|
25688
|
-
if (!
|
|
25837
|
+
if (!existsSync35(reconcileScript)) return;
|
|
25689
25838
|
try {
|
|
25690
25839
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
25691
25840
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -25704,12 +25853,12 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
25704
25853
|
}
|
|
25705
25854
|
startTimeEntryCensus(() => getSession());
|
|
25706
25855
|
{
|
|
25707
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
25856
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
|
|
25708
25857
|
const auditScript = resolve33(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
25709
25858
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
25710
25859
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
25711
25860
|
const runConnectorAudit = () => {
|
|
25712
|
-
if (!
|
|
25861
|
+
if (!existsSync35(auditScript)) return;
|
|
25713
25862
|
try {
|
|
25714
25863
|
const child = spawn3(process.execPath, [auditScript], {
|
|
25715
25864
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -25779,7 +25928,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
25779
25928
|
}
|
|
25780
25929
|
try {
|
|
25781
25930
|
const registered = [];
|
|
25782
|
-
for (const r of
|
|
25931
|
+
for (const r of app61.routes ?? []) {
|
|
25783
25932
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
25784
25933
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
25785
25934
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -25819,7 +25968,7 @@ try {
|
|
|
25819
25968
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
25820
25969
|
async function runAdminUserReconcileTick() {
|
|
25821
25970
|
try {
|
|
25822
|
-
if (!
|
|
25971
|
+
if (!existsSync35(USERS_FILE)) {
|
|
25823
25972
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
25824
25973
|
return;
|
|
25825
25974
|
}
|
|
@@ -25852,7 +26001,7 @@ var adminUserReconcileTimer = setInterval(() => {
|
|
|
25852
26001
|
if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer.unref();
|
|
25853
26002
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
25854
26003
|
function countUsersRows() {
|
|
25855
|
-
if (!
|
|
26004
|
+
if (!existsSync35(USERS_FILE)) return 0;
|
|
25856
26005
|
const raw = readFileSync35(USERS_FILE, "utf-8").trim();
|
|
25857
26006
|
if (!raw) return 0;
|
|
25858
26007
|
const users = JSON.parse(raw);
|
|
@@ -25909,7 +26058,7 @@ try {
|
|
|
25909
26058
|
} catch (err) {
|
|
25910
26059
|
console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
|
|
25911
26060
|
}
|
|
25912
|
-
var configDirForWhatsApp =
|
|
26061
|
+
var configDirForWhatsApp = basename12(MAXY_DIR) || ".maxy";
|
|
25913
26062
|
var bootAccount = resolveAccount();
|
|
25914
26063
|
if (bootAccount) {
|
|
25915
26064
|
migrateRemovedConfigKeys(bootAccount.accountDir);
|
|
@@ -25973,7 +26122,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
25973
26122
|
}
|
|
25974
26123
|
init({
|
|
25975
26124
|
configDir: configDirForWhatsApp,
|
|
25976
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
26125
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..")),
|
|
25977
26126
|
accountConfig: bootAccountConfig,
|
|
25978
26127
|
onMessage: async (msg) => {
|
|
25979
26128
|
if (msg.isOwnerMirror) {
|