@rubytech/create-maxy-code 0.1.436 → 0.1.438
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/lib/admin-access-password/__tests__/index.test.ts +31 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts +8 -0
- package/payload/platform/lib/admin-access-password/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admin-access-password/dist/index.js +5 -1
- package/payload/platform/lib/admin-access-password/dist/index.js.map +1 -1
- package/payload/platform/lib/admin-access-password/src/index.ts +14 -1
- package/payload/platform/lib/admins-write/__tests__/index.test.ts +27 -0
- package/payload/platform/lib/admins-write/dist/index.d.ts +8 -0
- package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admins-write/dist/index.js +5 -1
- package/payload/platform/lib/admins-write/dist/index.js.map +1 -1
- package/payload/platform/lib/admins-write/src/index.ts +14 -1
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +4 -2
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts +23 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.js +35 -0
- package/payload/platform/plugins/admin/mcp/dist/credential-identity.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +110 -57
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +22 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +62 -2
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +6 -6
- package/payload/platform/plugins/docs/references/admin-identity-gate.md +40 -0
- 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/linkedin-import/skills/linkedin-import/references/profile.md +1 -1
- 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/scripts/remediate-glsmith-identity.sh +500 -0
- package/payload/platform/scripts/seed-neo4j.sh +77 -12
- 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 +36 -10
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts +51 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.js +103 -0
- package/payload/platform/services/claude-session-manager/dist/identity-audit.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +33 -0
- package/payload/platform/services/claude-session-manager/dist/index.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/mcp-user-binding.d.ts +25 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js +42 -0
- package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js.map +1 -0
- 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/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts +44 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js +127 -0
- package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js.map +1 -0
- package/payload/server/{chunk-LMLVOZ6G.js → chunk-UGPQCVIW.js} +11 -38
- package/payload/server/maxy-edge.js +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 +703 -555
- 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
|
@@ -70,7 +70,6 @@ import {
|
|
|
70
70
|
linkConversationTranscript,
|
|
71
71
|
listAdminSessions,
|
|
72
72
|
listValidAccounts,
|
|
73
|
-
loadAdminDisplayIdentity,
|
|
74
73
|
loadAdminUserName,
|
|
75
74
|
loadPersonNameByElementId,
|
|
76
75
|
loadUserProfile,
|
|
@@ -112,7 +111,7 @@ import {
|
|
|
112
111
|
vncLog,
|
|
113
112
|
walkPremiumBundles,
|
|
114
113
|
writeAdminUserAndPerson
|
|
115
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-UGPQCVIW.js";
|
|
116
115
|
import {
|
|
117
116
|
__commonJS,
|
|
118
117
|
__toESM
|
|
@@ -127,8 +126,10 @@ var require_dist = __commonJS({
|
|
|
127
126
|
exports.cosine = cosine;
|
|
128
127
|
exports.deconflictBySubject = deconflictBySubject;
|
|
129
128
|
exports.formatStandingRulesBlock = formatStandingRulesBlock2;
|
|
129
|
+
exports.resolveOwnerUserId = resolveOwnerUserId;
|
|
130
130
|
exports.queryActiveRuleCandidates = queryActiveRuleCandidates;
|
|
131
|
-
exports.
|
|
131
|
+
exports.resolveActiveRules = resolveActiveRules2;
|
|
132
|
+
exports.activeRuleSet = activeRuleSet;
|
|
132
133
|
exports.SAME_SUBJECT_COSINE = 0.85;
|
|
133
134
|
exports.INJECTION_RULE_CAP = 12;
|
|
134
135
|
exports.ACTIVE_CANDIDATE_FLOOR = 0.4;
|
|
@@ -165,9 +166,20 @@ var require_dist = __commonJS({
|
|
|
165
166
|
return `## Standing rules
|
|
166
167
|
${lines.join("\n")}`;
|
|
167
168
|
}
|
|
168
|
-
async function
|
|
169
|
+
async function resolveOwnerUserId(session, accountId) {
|
|
170
|
+
const res = await session.run(`
|
|
171
|
+
MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
|
|
172
|
+
RETURN au.userId AS userId
|
|
173
|
+
ORDER BY au.createdAt ASC
|
|
174
|
+
LIMIT 1
|
|
175
|
+
`, { accountId });
|
|
176
|
+
const rec = res.records[0];
|
|
177
|
+
const userId = rec ? rec.get("userId") : null;
|
|
178
|
+
return typeof userId === "string" && userId.length > 0 ? userId : null;
|
|
179
|
+
}
|
|
180
|
+
async function queryOwnerCandidates(session, accountId, ownerUserId) {
|
|
169
181
|
const result = await session.run(`
|
|
170
|
-
MATCH (
|
|
182
|
+
MATCH (up:UserProfile {accountId: $accountId, userId: $ownerUserId})-[:HAS_PREFERENCE]->(pref:Preference {scope: 'admin'})
|
|
171
183
|
WHERE NOT pref:Trashed AND pref.deletedAt IS NULL
|
|
172
184
|
AND coalesce(pref.notApplicable, false) = false
|
|
173
185
|
AND pref.confidence >= $floor
|
|
@@ -176,7 +188,7 @@ ${lines.join("\n")}`;
|
|
|
176
188
|
pref.observedAt AS observedAt, pref.embedding AS embedding
|
|
177
189
|
ORDER BY pref.confidence DESC, pref.observedAt DESC
|
|
178
190
|
LIMIT ${exports.ACTIVE_CANDIDATE_LIMIT}
|
|
179
|
-
`, { accountId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
191
|
+
`, { accountId, ownerUserId, floor: exports.ACTIVE_CANDIDATE_FLOOR });
|
|
180
192
|
return result.records.map((r) => ({
|
|
181
193
|
preferenceId: r.get("preferenceId"),
|
|
182
194
|
category: r.get("category"),
|
|
@@ -187,9 +199,27 @@ ${lines.join("\n")}`;
|
|
|
187
199
|
embedding: r.get("embedding") ?? null
|
|
188
200
|
}));
|
|
189
201
|
}
|
|
190
|
-
async function
|
|
191
|
-
|
|
192
|
-
|
|
202
|
+
async function resolveCandidates(session, accountId) {
|
|
203
|
+
let ownerUserId;
|
|
204
|
+
try {
|
|
205
|
+
ownerUserId = await resolveOwnerUserId(session, accountId);
|
|
206
|
+
} catch {
|
|
207
|
+
return { candidates: [], ownerUserId: null, source: "owner-error" };
|
|
208
|
+
}
|
|
209
|
+
if (!ownerUserId)
|
|
210
|
+
return { candidates: [], ownerUserId: null, source: "no-owner" };
|
|
211
|
+
const candidates = await queryOwnerCandidates(session, accountId, ownerUserId);
|
|
212
|
+
return { candidates, ownerUserId, source: "owner" };
|
|
213
|
+
}
|
|
214
|
+
async function queryActiveRuleCandidates(session, accountId) {
|
|
215
|
+
return (await resolveCandidates(session, accountId)).candidates;
|
|
216
|
+
}
|
|
217
|
+
async function resolveActiveRules2(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
218
|
+
const { candidates, ownerUserId, source } = await resolveCandidates(session, accountId);
|
|
219
|
+
return { rules: deconflictBySubject(candidates).slice(0, cap), ownerUserId, source };
|
|
220
|
+
}
|
|
221
|
+
async function activeRuleSet(session, accountId, cap = exports.INJECTION_RULE_CAP) {
|
|
222
|
+
return (await resolveActiveRules2(session, accountId, cap)).rules;
|
|
193
223
|
}
|
|
194
224
|
}
|
|
195
225
|
});
|
|
@@ -1384,11 +1414,11 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
1384
1414
|
};
|
|
1385
1415
|
|
|
1386
1416
|
// server/index.ts
|
|
1387
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
1417
|
+
import { readFileSync as readFileSync35, existsSync as existsSync35, watchFile } from "fs";
|
|
1388
1418
|
import { spawn as spawn3 } from "child_process";
|
|
1389
1419
|
import { createHash as createHash7 } from "crypto";
|
|
1390
|
-
import { resolve as resolve33, join as
|
|
1391
|
-
import { homedir as
|
|
1420
|
+
import { resolve as resolve33, join as join36, basename as basename12 } from "path";
|
|
1421
|
+
import { homedir as homedir4 } from "os";
|
|
1392
1422
|
import { monitorEventLoopDelay } from "perf_hooks";
|
|
1393
1423
|
|
|
1394
1424
|
// app/lib/pwa.ts
|
|
@@ -6137,8 +6167,8 @@ function webchatTurnTimeoutMs() {
|
|
|
6137
6167
|
return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
|
|
6138
6168
|
}
|
|
6139
6169
|
function createChatRoutes(deps) {
|
|
6140
|
-
const
|
|
6141
|
-
|
|
6170
|
+
const app62 = new Hono();
|
|
6171
|
+
app62.post("/", async (c) => {
|
|
6142
6172
|
console.log(`[chat-route] entered route=public method=POST`);
|
|
6143
6173
|
const contentType = c.req.header("content-type") ?? "";
|
|
6144
6174
|
const account = resolveAccount();
|
|
@@ -6401,7 +6431,7 @@ ${result.result.text}` : result.result.text;
|
|
|
6401
6431
|
}
|
|
6402
6432
|
});
|
|
6403
6433
|
});
|
|
6404
|
-
return
|
|
6434
|
+
return app62;
|
|
6405
6435
|
}
|
|
6406
6436
|
|
|
6407
6437
|
// app/lib/channel-pty-bridge/admin-session-id.ts
|
|
@@ -6436,8 +6466,8 @@ function isLoopbackAddr(addr) {
|
|
|
6436
6466
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
|
|
6437
6467
|
}
|
|
6438
6468
|
function createScheduleInjectRoutes(deps) {
|
|
6439
|
-
const
|
|
6440
|
-
|
|
6469
|
+
const app62 = new Hono();
|
|
6470
|
+
app62.post("/", async (c) => {
|
|
6441
6471
|
const env = c.env;
|
|
6442
6472
|
const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
|
|
6443
6473
|
if (!isLoopbackAddr(remoteAddr)) {
|
|
@@ -6541,7 +6571,7 @@ function createScheduleInjectRoutes(deps) {
|
|
|
6541
6571
|
console.error(`${TAG16} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
|
|
6542
6572
|
return c.json({ ok: true }, 200);
|
|
6543
6573
|
});
|
|
6544
|
-
return
|
|
6574
|
+
return app62;
|
|
6545
6575
|
}
|
|
6546
6576
|
|
|
6547
6577
|
// server/index.ts
|
|
@@ -7562,6 +7592,9 @@ function reconcileCredsOnDisk(opts) {
|
|
|
7562
7592
|
function isReaderChannelSession(role, channel) {
|
|
7563
7593
|
return role === "admin" && (channel === "whatsapp" || channel === "telegram") || role === "public" && (channel === "whatsapp" || channel === "webchat");
|
|
7564
7594
|
}
|
|
7595
|
+
function isSessionListExcluded(role, channel) {
|
|
7596
|
+
return role === "public" && channel === "webchat";
|
|
7597
|
+
}
|
|
7565
7598
|
function selectReaderChannelSessions(rows) {
|
|
7566
7599
|
return rows.filter((r) => isReaderChannelSession(r.role, r.channel)).sort((a, b) => b.startedAt.localeCompare(a.startedAt)).map((r) => ({
|
|
7567
7600
|
sessionId: r.sessionId,
|
|
@@ -8162,12 +8195,37 @@ app2.get("/group-info", async (c) => {
|
|
|
8162
8195
|
var whatsapp_default = app2;
|
|
8163
8196
|
|
|
8164
8197
|
// server/routes/whatsapp-reader.ts
|
|
8165
|
-
import { readFileSync as readFileSync15, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as
|
|
8166
|
-
import { basename as
|
|
8198
|
+
import { readFileSync as readFileSync15, watch, statSync as statSync5, openSync, readSync, closeSync, existsSync as existsSync10, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
|
|
8199
|
+
import { basename as basename4, dirname as dirname4, isAbsolute, join as join15, relative as relative2, resolve as resolve12, sep as sep3 } from "path";
|
|
8200
|
+
|
|
8201
|
+
// server/routes/admin/sidebar-sessions.ts
|
|
8202
|
+
import { readdirSync as readdirSync6, readFileSync as readFileSync12, statSync as statSync3 } from "fs";
|
|
8203
|
+
import { dirname as dirname3, join as join12, resolve as resolve11 } from "path";
|
|
8204
|
+
|
|
8205
|
+
// ../services/claude-session-manager/src/jsonl-path.ts
|
|
8206
|
+
import { existsSync as existsSync8, readdirSync as readdirSync5 } from "fs";
|
|
8207
|
+
import { homedir } from "os";
|
|
8208
|
+
import { join as join11 } from "path";
|
|
8209
|
+
function findExistingJsonlForSessionId(claudeConfigDir2, sessionId) {
|
|
8210
|
+
const projectsRoot = join11(claudeConfigDir2, "projects");
|
|
8211
|
+
if (!existsSync8(projectsRoot)) return null;
|
|
8212
|
+
let slugs;
|
|
8213
|
+
try {
|
|
8214
|
+
slugs = readdirSync5(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8215
|
+
} catch {
|
|
8216
|
+
return null;
|
|
8217
|
+
}
|
|
8218
|
+
const basename13 = `${sessionId}.jsonl`;
|
|
8219
|
+
for (const slug of slugs) {
|
|
8220
|
+
const live = join11(projectsRoot, slug, basename13);
|
|
8221
|
+
if (existsSync8(live)) return live;
|
|
8222
|
+
const archived = join11(projectsRoot, slug, "archive", basename13);
|
|
8223
|
+
if (existsSync8(archived)) return archived;
|
|
8224
|
+
}
|
|
8225
|
+
return null;
|
|
8226
|
+
}
|
|
8167
8227
|
|
|
8168
8228
|
// 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
8229
|
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
8230
|
function lastAssistantModel(body) {
|
|
8173
8231
|
const lines = body.split("\n");
|
|
@@ -8196,25 +8254,23 @@ function claudeConfigDir() {
|
|
|
8196
8254
|
function findSessionProjectDir(sessionId) {
|
|
8197
8255
|
const cfg = claudeConfigDir();
|
|
8198
8256
|
if (!cfg) return null;
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
}
|
|
8202
|
-
return null;
|
|
8257
|
+
const jsonlPath = findExistingJsonlForSessionId(cfg, sessionId);
|
|
8258
|
+
return jsonlPath ? dirname3(jsonlPath) : null;
|
|
8203
8259
|
}
|
|
8204
8260
|
function enumerateJsonls(projectsRoot) {
|
|
8205
8261
|
const out = [];
|
|
8206
8262
|
let slugs;
|
|
8207
8263
|
try {
|
|
8208
|
-
slugs =
|
|
8264
|
+
slugs = readdirSync6(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8209
8265
|
} catch (err) {
|
|
8210
8266
|
if (err.code === "ENOENT") return out;
|
|
8211
8267
|
throw err;
|
|
8212
8268
|
}
|
|
8213
8269
|
for (const slug of slugs) {
|
|
8214
|
-
const slugDir =
|
|
8270
|
+
const slugDir = join12(projectsRoot, slug);
|
|
8215
8271
|
let entries;
|
|
8216
8272
|
try {
|
|
8217
|
-
entries =
|
|
8273
|
+
entries = readdirSync6(slugDir, { withFileTypes: true });
|
|
8218
8274
|
} catch (err) {
|
|
8219
8275
|
const code = err.code ?? "unknown";
|
|
8220
8276
|
console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
|
|
@@ -8222,12 +8278,12 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8222
8278
|
}
|
|
8223
8279
|
for (const entry of entries) {
|
|
8224
8280
|
if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
|
|
8225
|
-
out.push({ path:
|
|
8281
|
+
out.push({ path: join12(slugDir, entry.name), isSubagent: false, archived: false });
|
|
8226
8282
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
8227
|
-
const subDir =
|
|
8283
|
+
const subDir = join12(slugDir, entry.name);
|
|
8228
8284
|
let subEntries;
|
|
8229
8285
|
try {
|
|
8230
|
-
subEntries =
|
|
8286
|
+
subEntries = readdirSync6(subDir, { withFileTypes: true });
|
|
8231
8287
|
} catch (err) {
|
|
8232
8288
|
const code = err.code ?? "unknown";
|
|
8233
8289
|
console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
|
|
@@ -8235,14 +8291,14 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8235
8291
|
}
|
|
8236
8292
|
for (const sub of subEntries) {
|
|
8237
8293
|
if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
|
|
8238
|
-
out.push({ path:
|
|
8294
|
+
out.push({ path: join12(subDir, sub.name), isSubagent: true, archived: false });
|
|
8239
8295
|
}
|
|
8240
8296
|
}
|
|
8241
8297
|
} else if (entry.isDirectory() && entry.name === "archive") {
|
|
8242
|
-
const archiveDir =
|
|
8298
|
+
const archiveDir = join12(slugDir, entry.name);
|
|
8243
8299
|
let archiveEntries;
|
|
8244
8300
|
try {
|
|
8245
|
-
archiveEntries =
|
|
8301
|
+
archiveEntries = readdirSync6(archiveDir, { withFileTypes: true });
|
|
8246
8302
|
} catch (err) {
|
|
8247
8303
|
const code = err.code ?? "unknown";
|
|
8248
8304
|
console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
|
|
@@ -8250,7 +8306,7 @@ function enumerateJsonls(projectsRoot) {
|
|
|
8250
8306
|
}
|
|
8251
8307
|
for (const arc of archiveEntries) {
|
|
8252
8308
|
if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
|
|
8253
|
-
out.push({ path:
|
|
8309
|
+
out.push({ path: join12(archiveDir, arc.name), isSubagent: false, archived: true });
|
|
8254
8310
|
}
|
|
8255
8311
|
}
|
|
8256
8312
|
}
|
|
@@ -8283,7 +8339,7 @@ async function fetchLiveSessions() {
|
|
|
8283
8339
|
function loadUserTitles(accountDir) {
|
|
8284
8340
|
const out = /* @__PURE__ */ new Map();
|
|
8285
8341
|
if (!accountDir) return out;
|
|
8286
|
-
const path2 =
|
|
8342
|
+
const path2 = join12(accountDir, "session-titles.json");
|
|
8287
8343
|
let raw;
|
|
8288
8344
|
try {
|
|
8289
8345
|
raw = readFileSync12(path2, "utf8");
|
|
@@ -8410,7 +8466,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8410
8466
|
console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
|
|
8411
8467
|
return c.json({ sessions: [], accountId: scopeAccountId });
|
|
8412
8468
|
}
|
|
8413
|
-
const projectsRoot =
|
|
8469
|
+
const projectsRoot = join12(configDir2, "projects");
|
|
8414
8470
|
const jsonls = enumerateJsonls(projectsRoot);
|
|
8415
8471
|
const liveSessions = await fetchLiveSessions();
|
|
8416
8472
|
const accountDir = scopeAccountId ? resolve11(ACCOUNTS_DIR, scopeAccountId) : null;
|
|
@@ -8420,7 +8476,10 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8420
8476
|
let liveCount = 0;
|
|
8421
8477
|
let subagentCount = 0;
|
|
8422
8478
|
let archivedCount = 0;
|
|
8423
|
-
let
|
|
8479
|
+
let excludedPublicWebchatCount = 0;
|
|
8480
|
+
const channelInList = { whatsapp: 0, telegram: 0, webchat: 0 };
|
|
8481
|
+
const KNOWN_CHANNELS = /* @__PURE__ */ new Set(["browser", "whatsapp", "telegram", "webchat", "email"]);
|
|
8482
|
+
let unknownChannelCount = 0;
|
|
8424
8483
|
let untaggedCount = 0;
|
|
8425
8484
|
const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
|
|
8426
8485
|
const personIdBySession = /* @__PURE__ */ new Map();
|
|
@@ -8447,14 +8506,14 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8447
8506
|
const pid = live ? liveSessions.get(sessionId) ?? null : null;
|
|
8448
8507
|
const resolved = resolveTitle(body, sessionId, userTitles);
|
|
8449
8508
|
titleSourceCounts[resolved.source] += 1;
|
|
8450
|
-
const metaPath =
|
|
8509
|
+
const metaPath = join12(projectDir, `${sessionId}.meta.json`);
|
|
8451
8510
|
const { bridgeIds, role, channel: sidecarChannel, personId, adminUserId, accountId: rowAccountId } = readSidecarMeta(metaPath);
|
|
8452
8511
|
if (multiAccount) {
|
|
8453
8512
|
if (rowAccountId === null) untaggedCount += 1;
|
|
8454
8513
|
if (rowAccountId !== scopeAccountId) continue;
|
|
8455
8514
|
}
|
|
8456
|
-
if (
|
|
8457
|
-
|
|
8515
|
+
if (isSessionListExcluded(role, sidecarChannel)) {
|
|
8516
|
+
excludedPublicWebchatCount += 1;
|
|
8458
8517
|
continue;
|
|
8459
8518
|
}
|
|
8460
8519
|
if (personId) personIdBySession.set(sessionId, personId);
|
|
@@ -8472,11 +8531,20 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8472
8531
|
projectDir,
|
|
8473
8532
|
bridgeIds,
|
|
8474
8533
|
archived,
|
|
8475
|
-
channel
|
|
8534
|
+
// Task 1566 — the row's channel is the authoritative `.meta.json` sidecar
|
|
8535
|
+
// value (whatsapp/telegram/webchat/browser/null), which drives the client
|
|
8536
|
+
// row colour and glyph. The JSONL-envelope channel (`resolved.channel`) is
|
|
8537
|
+
// no longer the row channel: it is null for browser/CLI rows and can
|
|
8538
|
+
// diverge from the sidecar (e.g. an ai-titled channel row).
|
|
8539
|
+
channel: sidecarChannel,
|
|
8476
8540
|
personName: null,
|
|
8477
8541
|
model: lastAssistantModel(body),
|
|
8478
8542
|
accountId: rowAccountId
|
|
8479
8543
|
});
|
|
8544
|
+
if (sidecarChannel === "whatsapp") channelInList.whatsapp += 1;
|
|
8545
|
+
else if (sidecarChannel === "telegram") channelInList.telegram += 1;
|
|
8546
|
+
else if (sidecarChannel === "webchat") channelInList.webchat += 1;
|
|
8547
|
+
if (sidecarChannel !== null && !KNOWN_CHANNELS.has(sidecarChannel)) unknownChannelCount += 1;
|
|
8480
8548
|
if (live) liveCount += 1;
|
|
8481
8549
|
if (isSubagent) subagentCount += 1;
|
|
8482
8550
|
if (archived) archivedCount += 1;
|
|
@@ -8498,7 +8566,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8498
8566
|
}
|
|
8499
8567
|
const auid = adminUserIdBySession.get(row.sessionId);
|
|
8500
8568
|
if (auid) {
|
|
8501
|
-
const resolved = await loadAdminUserName(
|
|
8569
|
+
const resolved = await loadAdminUserName(auid);
|
|
8502
8570
|
if (resolved.source === "neo4j") {
|
|
8503
8571
|
row.personName = resolved.joined;
|
|
8504
8572
|
adminNameCount += 1;
|
|
@@ -8509,7 +8577,7 @@ app3.get("/", requireAdminSession, async (c) => {
|
|
|
8509
8577
|
}
|
|
8510
8578
|
rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
|
|
8511
8579
|
console.log(
|
|
8512
|
-
`[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount}
|
|
8580
|
+
`[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
8581
|
);
|
|
8514
8582
|
console.log(
|
|
8515
8583
|
`[admin-sessions-list] accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"} scope=${multiAccount ? "scoped" : "all"} rows=${rows.length}`
|
|
@@ -8523,13 +8591,13 @@ var sidebar_sessions_default = app3;
|
|
|
8523
8591
|
|
|
8524
8592
|
// app/lib/admin-identity/pin-validator.ts
|
|
8525
8593
|
import { createHash as createHash3 } from "crypto";
|
|
8526
|
-
import { existsSync as
|
|
8527
|
-
import { join as
|
|
8594
|
+
import { existsSync as existsSync9, readFileSync as readFileSync13, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
8595
|
+
import { join as join13 } from "path";
|
|
8528
8596
|
function hashPin(pin) {
|
|
8529
8597
|
return createHash3("sha256").update(pin).digest("hex");
|
|
8530
8598
|
}
|
|
8531
8599
|
function readUsersFile(usersFilePath) {
|
|
8532
|
-
if (!
|
|
8600
|
+
if (!existsSync9(usersFilePath)) return null;
|
|
8533
8601
|
const raw = readFileSync13(usersFilePath, "utf-8").trim();
|
|
8534
8602
|
if (!raw) return [];
|
|
8535
8603
|
return JSON.parse(raw);
|
|
@@ -8829,8 +8897,8 @@ function parseTranscript(lines, queuedPendingSuppress = /* @__PURE__ */ new Map(
|
|
|
8829
8897
|
}
|
|
8830
8898
|
|
|
8831
8899
|
// app/lib/whatsapp-reader/enrich-attachments.ts
|
|
8832
|
-
import { readFileSync as readFileSync14, readdirSync as
|
|
8833
|
-
import { join as
|
|
8900
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync8 } from "fs";
|
|
8901
|
+
import { join as join14 } from "path";
|
|
8834
8902
|
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
8903
|
function adminAttachmentIds(text) {
|
|
8836
8904
|
const ids = [];
|
|
@@ -8843,7 +8911,7 @@ function adminAttachmentIds(text) {
|
|
|
8843
8911
|
function adminAttachmentsFromText(text, uploadsBase) {
|
|
8844
8912
|
const out = [];
|
|
8845
8913
|
for (const id of adminAttachmentIds(text)) {
|
|
8846
|
-
const meta = readAttachmentMeta(
|
|
8914
|
+
const meta = readAttachmentMeta(join14(uploadsBase, id));
|
|
8847
8915
|
if (meta) out.push(meta);
|
|
8848
8916
|
}
|
|
8849
8917
|
return out;
|
|
@@ -8851,7 +8919,7 @@ function adminAttachmentsFromText(text, uploadsBase) {
|
|
|
8851
8919
|
function readSidecar(dir, attachmentId) {
|
|
8852
8920
|
let parsed;
|
|
8853
8921
|
try {
|
|
8854
|
-
parsed = JSON.parse(readFileSync14(
|
|
8922
|
+
parsed = JSON.parse(readFileSync14(join14(dir, `${attachmentId}.meta.json`), "utf8"));
|
|
8855
8923
|
} catch {
|
|
8856
8924
|
return null;
|
|
8857
8925
|
}
|
|
@@ -8874,13 +8942,13 @@ function readAttachmentMeta(dir) {
|
|
|
8874
8942
|
function listSessionAttachmentsInDir(dir) {
|
|
8875
8943
|
let entries;
|
|
8876
8944
|
try {
|
|
8877
|
-
entries =
|
|
8945
|
+
entries = readdirSync8(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
8878
8946
|
} catch {
|
|
8879
8947
|
return [];
|
|
8880
8948
|
}
|
|
8881
8949
|
const sidecars = [];
|
|
8882
8950
|
for (const name of entries) {
|
|
8883
|
-
const sidecar = readSidecar(
|
|
8951
|
+
const sidecar = readSidecar(join14(dir, name), name);
|
|
8884
8952
|
if (sidecar) sidecars.push(sidecar);
|
|
8885
8953
|
}
|
|
8886
8954
|
sidecars.sort((a, b) => a.storedAt.localeCompare(b.storedAt));
|
|
@@ -8945,14 +9013,14 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
8945
9013
|
}
|
|
8946
9014
|
const cfg = claudeConfigDir();
|
|
8947
9015
|
if (!cfg) return c.json({ conversations: [] });
|
|
8948
|
-
const projectsRoot =
|
|
9016
|
+
const projectsRoot = join15(cfg, "projects");
|
|
8949
9017
|
const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
|
|
8950
9018
|
const rows = [];
|
|
8951
9019
|
let sessionRowsExcludedUntagged = 0;
|
|
8952
9020
|
for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
|
|
8953
|
-
const sessionId =
|
|
9021
|
+
const sessionId = basename4(path2).replace(/\.jsonl$/, "");
|
|
8954
9022
|
const projectDir = dirname4(path2);
|
|
8955
|
-
const meta = readSidecarMeta(
|
|
9023
|
+
const meta = readSidecarMeta(join15(projectDir, `${sessionId}.meta.json`));
|
|
8956
9024
|
if (!isReaderChannelSession(meta.role, meta.channel)) continue;
|
|
8957
9025
|
if (multiAccount) {
|
|
8958
9026
|
if (meta.accountId === null) sessionRowsExcludedUntagged += 1;
|
|
@@ -9002,7 +9070,7 @@ app4.get("/conversations", requireAdminSession, async (c) => {
|
|
|
9002
9070
|
return;
|
|
9003
9071
|
}
|
|
9004
9072
|
const idRes = classifyAdminUserId(users, admins, senderId);
|
|
9005
|
-
const nameRes = idRes.kind === "resolved" ? await loadAdminUserName(
|
|
9073
|
+
const nameRes = idRes.kind === "resolved" ? await loadAdminUserName(idRes.userId) : null;
|
|
9006
9074
|
const { name, reason } = resolveOperatorDisplay(idRes, nameRes);
|
|
9007
9075
|
if (reason) console.error(`[wa-reader] op=operator-unresolved senderId=${senderId} reason=${reason}`);
|
|
9008
9076
|
nameBySender.set(senderId, name);
|
|
@@ -9132,7 +9200,7 @@ function openTaskKey(turns) {
|
|
|
9132
9200
|
}
|
|
9133
9201
|
function readSubagentMeta(dir, hex) {
|
|
9134
9202
|
try {
|
|
9135
|
-
const m = JSON.parse(readFileSync15(
|
|
9203
|
+
const m = JSON.parse(readFileSync15(join15(dir, `agent-${hex}.meta.json`), "utf8"));
|
|
9136
9204
|
if (typeof m.agentType === "string" && typeof m.description === "string" && typeof m.toolUseId === "string") {
|
|
9137
9205
|
return { agentType: m.agentType, description: m.description, toolUseId: m.toolUseId };
|
|
9138
9206
|
}
|
|
@@ -9155,7 +9223,7 @@ function runActivityTick(c) {
|
|
|
9155
9223
|
c.parentGrewThisTick = false;
|
|
9156
9224
|
let names = [];
|
|
9157
9225
|
try {
|
|
9158
|
-
names =
|
|
9226
|
+
names = readdirSync9(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
|
|
9159
9227
|
} catch {
|
|
9160
9228
|
}
|
|
9161
9229
|
const entries = [];
|
|
@@ -9164,7 +9232,7 @@ function runActivityTick(c) {
|
|
|
9164
9232
|
let size = 0;
|
|
9165
9233
|
let mtimeMs = 0;
|
|
9166
9234
|
try {
|
|
9167
|
-
const st = statSync5(
|
|
9235
|
+
const st = statSync5(join15(c.subagentsDir, name));
|
|
9168
9236
|
size = st.size;
|
|
9169
9237
|
mtimeMs = st.mtimeMs;
|
|
9170
9238
|
} catch {
|
|
@@ -9209,11 +9277,11 @@ app4.get("/stream", requireAdminSession, (c) => {
|
|
|
9209
9277
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9210
9278
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
9211
9279
|
const cfg = claudeConfigDir();
|
|
9212
|
-
const projectsRoot = cfg ? resolve12(
|
|
9280
|
+
const projectsRoot = cfg ? resolve12(join15(cfg, "projects")) : null;
|
|
9213
9281
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
9214
9282
|
return c.json({ error: "bad session reference" }, 400);
|
|
9215
9283
|
}
|
|
9216
|
-
const jsonlPath = resolve12(
|
|
9284
|
+
const jsonlPath = resolve12(join15(projectDir, `${sessionId}.jsonl`));
|
|
9217
9285
|
if (!jsonlPath.startsWith(projectsRoot + sep3)) {
|
|
9218
9286
|
return c.json({ error: "bad session reference" }, 400);
|
|
9219
9287
|
}
|
|
@@ -9238,9 +9306,9 @@ data: ${JSON.stringify(turn)}
|
|
|
9238
9306
|
let offset = resumeOffset(lastEventId, fileEnd0);
|
|
9239
9307
|
console.log(`[wa-stream] op=open conn=${connId} sessionId=${sessionId} channel=reader resume=${offset}`);
|
|
9240
9308
|
const sessionKey = c.req.query("session_key") ?? "";
|
|
9241
|
-
const subagentsDir = resolve12(
|
|
9309
|
+
const subagentsDir = resolve12(join15(projectDir, sessionId, "subagents"));
|
|
9242
9310
|
console.log(
|
|
9243
|
-
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${
|
|
9311
|
+
`[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync10(subagentsDir)}`
|
|
9244
9312
|
);
|
|
9245
9313
|
const actx = makeActivityCtx({
|
|
9246
9314
|
subagentsDir,
|
|
@@ -9347,10 +9415,10 @@ app4.get("/directives", requireAdminSession, (c) => {
|
|
|
9347
9415
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9348
9416
|
if (!SESSION_ID_RE2.test(sessionId)) return c.json({ error: "bad session reference" }, 400);
|
|
9349
9417
|
const dir = directiveStoreDir(sessionId);
|
|
9350
|
-
if (!dir || !
|
|
9418
|
+
if (!dir || !existsSync10(dir)) return c.json({ entries: [] });
|
|
9351
9419
|
let names;
|
|
9352
9420
|
try {
|
|
9353
|
-
names =
|
|
9421
|
+
names = readdirSync9(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
|
|
9354
9422
|
} catch {
|
|
9355
9423
|
return c.json({ entries: [] });
|
|
9356
9424
|
}
|
|
@@ -9360,7 +9428,7 @@ app4.get("/directives", requireAdminSession, (c) => {
|
|
|
9360
9428
|
const pid = Number(pidPart);
|
|
9361
9429
|
let len = 0;
|
|
9362
9430
|
try {
|
|
9363
|
-
len = statSync5(
|
|
9431
|
+
len = statSync5(join15(dir, name)).size;
|
|
9364
9432
|
} catch {
|
|
9365
9433
|
}
|
|
9366
9434
|
return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
|
|
@@ -9375,7 +9443,7 @@ app4.get("/directive", requireAdminSession, (c) => {
|
|
|
9375
9443
|
}
|
|
9376
9444
|
const dir = directiveStoreDir(sessionId);
|
|
9377
9445
|
if (!dir) return c.json({ error: "no account" }, 404);
|
|
9378
|
-
const path2 = resolve12(
|
|
9446
|
+
const path2 = resolve12(join15(dir, name));
|
|
9379
9447
|
if (!path2.startsWith(dir + sep3)) return c.json({ error: "bad reference" }, 400);
|
|
9380
9448
|
let body;
|
|
9381
9449
|
try {
|
|
@@ -9429,7 +9497,7 @@ app4.get("/store-stream", requireAdminSession, (c) => {
|
|
|
9429
9497
|
console.log(`[wa-reader] op=store-quote msgId=${r.msgKeyId} quoted=${!!q}`);
|
|
9430
9498
|
}
|
|
9431
9499
|
if (r.attachmentId) {
|
|
9432
|
-
const meta = readAttachmentMeta(
|
|
9500
|
+
const meta = readAttachmentMeta(join15(uploadsBase, r.attachmentId));
|
|
9433
9501
|
if (meta) return { ...turn, attachments: [meta] };
|
|
9434
9502
|
}
|
|
9435
9503
|
return turn;
|
|
@@ -9644,7 +9712,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9644
9712
|
}
|
|
9645
9713
|
if (size > MAX_FILE_BYTES) {
|
|
9646
9714
|
exit("rejected");
|
|
9647
|
-
return c.json({ error: `"${
|
|
9715
|
+
return c.json({ error: `"${basename4(absolute)}" exceeds the 50 MB limit` }, 400);
|
|
9648
9716
|
}
|
|
9649
9717
|
const mime = detectMimeType(absolute);
|
|
9650
9718
|
if (!isMimeAdmitted(mime, SUPPORTED_MIME_SET)) {
|
|
@@ -9736,7 +9804,7 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9736
9804
|
}
|
|
9737
9805
|
for (let i = 0; i < resolvedRefs.length; i++) {
|
|
9738
9806
|
const { absolute, mime } = resolvedRefs[i];
|
|
9739
|
-
const file = new File([readFileSync15(absolute)],
|
|
9807
|
+
const file = new File([readFileSync15(absolute)], basename4(absolute), { type: mime });
|
|
9740
9808
|
const out = await sendStagedFile(file, `ref=${i}`);
|
|
9741
9809
|
if (!out.ok) {
|
|
9742
9810
|
exit("error");
|
|
@@ -9755,8 +9823,8 @@ app4.post("/reply", requireAdminSession, async (c) => {
|
|
|
9755
9823
|
var whatsapp_reader_default = app4;
|
|
9756
9824
|
|
|
9757
9825
|
// 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
|
|
9826
|
+
import { statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2, watch as watch2, readFileSync as readFileSync16, readdirSync as readdirSync10 } from "fs";
|
|
9827
|
+
import { basename as basename5, dirname as dirname5, join as join16, resolve as resolve13, sep as sep4 } from "path";
|
|
9760
9828
|
|
|
9761
9829
|
// app/lib/whatsapp-reader/delivered-kinds.ts
|
|
9762
9830
|
var PUBLIC_DELIVERED_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -9830,10 +9898,10 @@ function enumeratePublicRows() {
|
|
|
9830
9898
|
const cfg = claudeConfigDir();
|
|
9831
9899
|
if (!cfg) return [];
|
|
9832
9900
|
const rows = [];
|
|
9833
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
9834
|
-
const sessionId =
|
|
9901
|
+
for (const { path: path2 } of enumerateJsonls(join16(cfg, "projects"))) {
|
|
9902
|
+
const sessionId = basename5(path2).replace(/\.jsonl$/, "");
|
|
9835
9903
|
const projectDir = dirname5(path2);
|
|
9836
|
-
const meta = readSidecarMeta(
|
|
9904
|
+
const meta = readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`));
|
|
9837
9905
|
rows.push({
|
|
9838
9906
|
sessionId,
|
|
9839
9907
|
projectDir,
|
|
@@ -9909,15 +9977,15 @@ app5.get("/stream", (c) => {
|
|
|
9909
9977
|
const sessionId = c.req.query("sessionId") ?? "";
|
|
9910
9978
|
const projectDir = c.req.query("projectDir") ?? "";
|
|
9911
9979
|
const cfg = claudeConfigDir();
|
|
9912
|
-
const projectsRoot = cfg ? resolve13(
|
|
9980
|
+
const projectsRoot = cfg ? resolve13(join16(cfg, "projects")) : null;
|
|
9913
9981
|
if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
|
|
9914
9982
|
return c.json({ error: "bad session reference" }, 400);
|
|
9915
9983
|
}
|
|
9916
|
-
const jsonlPath = resolve13(
|
|
9984
|
+
const jsonlPath = resolve13(join16(projectDir, `${sessionId}.jsonl`));
|
|
9917
9985
|
if (!jsonlPath.startsWith(projectsRoot + sep4)) {
|
|
9918
9986
|
return c.json({ error: "bad session reference" }, 400);
|
|
9919
9987
|
}
|
|
9920
|
-
const meta = readSidecarMeta(
|
|
9988
|
+
const meta = readSidecarMeta(join16(projectDir, `${sessionId}.meta.json`));
|
|
9921
9989
|
const isPublicWebchat = meta.role === "public" && meta.channel === "webchat";
|
|
9922
9990
|
const owns = visitor.kind === "person" ? meta.personId === visitor.personId : meta.personId === null && meta.visitorId === visitor.visitorId;
|
|
9923
9991
|
if (!(isPublicWebchat && owns)) {
|
|
@@ -10030,7 +10098,7 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10030
10098
|
let dataFile;
|
|
10031
10099
|
let buffer;
|
|
10032
10100
|
try {
|
|
10033
|
-
dataFile =
|
|
10101
|
+
dataFile = readdirSync10(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
|
|
10034
10102
|
if (!dataFile) throw new Error("no data file");
|
|
10035
10103
|
buffer = readFileSync16(resolve13(dir, dataFile));
|
|
10036
10104
|
} catch {
|
|
@@ -10050,17 +10118,17 @@ app5.get("/attachment/:attachmentId", (c) => {
|
|
|
10050
10118
|
var public_reader_default = app5;
|
|
10051
10119
|
|
|
10052
10120
|
// server/routes/webchat.ts
|
|
10053
|
-
import { basename as
|
|
10054
|
-
import { join as
|
|
10055
|
-
import { existsSync as
|
|
10121
|
+
import { basename as basename6, dirname as dirname6 } from "path";
|
|
10122
|
+
import { join as join19 } from "path";
|
|
10123
|
+
import { existsSync as existsSync12, readdirSync as readdirSync12, readFileSync as readFileSync19, renameSync as renameSync4, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
10056
10124
|
|
|
10057
10125
|
// server/canonical-webchat-override.ts
|
|
10058
10126
|
import { readFileSync as readFileSync17, writeFileSync as writeFileSync5, renameSync as renameSync2 } from "fs";
|
|
10059
|
-
import { join as
|
|
10127
|
+
import { join as join17 } from "path";
|
|
10060
10128
|
var FILE = "canonical-webchat-session.json";
|
|
10061
10129
|
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
10130
|
function canonicalOverridePath(accountDir) {
|
|
10063
|
-
return
|
|
10131
|
+
return join17(accountDir, FILE);
|
|
10064
10132
|
}
|
|
10065
10133
|
function readRaw(accountDir) {
|
|
10066
10134
|
try {
|
|
@@ -10139,8 +10207,8 @@ function isNewSessionEffortLevel(value) {
|
|
|
10139
10207
|
}
|
|
10140
10208
|
|
|
10141
10209
|
// ../services/claude-session-manager/src/sidecar-store.ts
|
|
10142
|
-
import { existsSync as
|
|
10143
|
-
import { join as
|
|
10210
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as readdirSync11, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
10211
|
+
import { join as join18 } from "path";
|
|
10144
10212
|
function escapeRegExp(s) {
|
|
10145
10213
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10146
10214
|
}
|
|
@@ -10148,7 +10216,7 @@ function createSidecarStore(config) {
|
|
|
10148
10216
|
const { suffix, validate: validate2 } = config;
|
|
10149
10217
|
const suffixRe = new RegExp(`${escapeRegExp(suffix)}$`);
|
|
10150
10218
|
function pathFor(sessionsDir, id) {
|
|
10151
|
-
return
|
|
10219
|
+
return join18(sessionsDir, `${id}${suffix}`);
|
|
10152
10220
|
}
|
|
10153
10221
|
function write(sessionsDir, id, record) {
|
|
10154
10222
|
mkdirSync3(sessionsDir, { recursive: true });
|
|
@@ -10160,7 +10228,7 @@ function createSidecarStore(config) {
|
|
|
10160
10228
|
return { ok: true };
|
|
10161
10229
|
} catch (error) {
|
|
10162
10230
|
try {
|
|
10163
|
-
if (
|
|
10231
|
+
if (existsSync11(tmp)) unlinkSync2(tmp);
|
|
10164
10232
|
} catch {
|
|
10165
10233
|
}
|
|
10166
10234
|
return { ok: false, error };
|
|
@@ -10185,14 +10253,14 @@ function createSidecarStore(config) {
|
|
|
10185
10253
|
function readAll(sessionsDir, onSkip) {
|
|
10186
10254
|
let names;
|
|
10187
10255
|
try {
|
|
10188
|
-
names =
|
|
10256
|
+
names = readdirSync11(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
|
|
10189
10257
|
} catch {
|
|
10190
10258
|
return [];
|
|
10191
10259
|
}
|
|
10192
10260
|
const out = [];
|
|
10193
10261
|
for (const name of names) {
|
|
10194
10262
|
if (!suffixRe.test(name)) continue;
|
|
10195
|
-
const path2 =
|
|
10263
|
+
const path2 = join18(sessionsDir, name);
|
|
10196
10264
|
let raw;
|
|
10197
10265
|
try {
|
|
10198
10266
|
raw = readFileSync18(path2, "utf8");
|
|
@@ -10216,7 +10284,7 @@ function createSidecarStore(config) {
|
|
|
10216
10284
|
function clear(sessionsDir, id) {
|
|
10217
10285
|
const path2 = pathFor(sessionsDir, id);
|
|
10218
10286
|
try {
|
|
10219
|
-
if (
|
|
10287
|
+
if (existsSync11(path2)) {
|
|
10220
10288
|
unlinkSync2(path2);
|
|
10221
10289
|
return { ok: true, removed: true };
|
|
10222
10290
|
}
|
|
@@ -10269,22 +10337,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
10337
|
function locateSession(sessionId) {
|
|
10270
10338
|
const dir = findSessionProjectDir(sessionId);
|
|
10271
10339
|
if (!dir) return { projectDir: null, channel: null, accountId: null };
|
|
10272
|
-
const meta = readSidecarMeta(
|
|
10340
|
+
const meta = readSidecarMeta(join19(dir, `${sessionId}.meta.json`));
|
|
10273
10341
|
return { projectDir: dir, channel: meta.channel, accountId: meta.accountId };
|
|
10274
10342
|
}
|
|
10275
10343
|
function locateSidecar(sessionId) {
|
|
10276
10344
|
const cfg = claudeConfigDir();
|
|
10277
10345
|
if (!cfg) return null;
|
|
10278
|
-
const projectsRoot =
|
|
10346
|
+
const projectsRoot = join19(cfg, "projects");
|
|
10279
10347
|
let slugs;
|
|
10280
10348
|
try {
|
|
10281
|
-
slugs =
|
|
10349
|
+
slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
10282
10350
|
} catch {
|
|
10283
10351
|
return null;
|
|
10284
10352
|
}
|
|
10285
10353
|
for (const slug of slugs) {
|
|
10286
|
-
const metaPath =
|
|
10287
|
-
if (
|
|
10354
|
+
const metaPath = join19(projectsRoot, slug, `${sessionId}.meta.json`);
|
|
10355
|
+
if (existsSync12(metaPath)) {
|
|
10288
10356
|
const meta = readSidecarMeta(metaPath);
|
|
10289
10357
|
return { channel: meta.channel, adminUserId: meta.adminUserId, accountId: meta.accountId };
|
|
10290
10358
|
}
|
|
@@ -10296,7 +10364,7 @@ function readTargetOwner(sessionId) {
|
|
|
10296
10364
|
if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
|
|
10297
10365
|
const { projectDir } = locateSession(sessionId);
|
|
10298
10366
|
if (projectDir !== null) {
|
|
10299
|
-
return { found: true, owner: readSidecarMeta(
|
|
10367
|
+
return { found: true, owner: readSidecarMeta(join19(projectDir, `${sessionId}.meta.json`)).adminUserId };
|
|
10300
10368
|
}
|
|
10301
10369
|
return { found: false, owner: null };
|
|
10302
10370
|
}
|
|
@@ -10310,7 +10378,7 @@ function sessionSidecarExists(sessionId) {
|
|
|
10310
10378
|
function jsonlSizeBytes(projectDir, sessionId) {
|
|
10311
10379
|
if (projectDir === null) return null;
|
|
10312
10380
|
try {
|
|
10313
|
-
return statSync7(
|
|
10381
|
+
return statSync7(join19(projectDir, `${sessionId}.jsonl`)).size;
|
|
10314
10382
|
} catch {
|
|
10315
10383
|
return null;
|
|
10316
10384
|
}
|
|
@@ -10446,10 +10514,10 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
10446
10514
|
const cfg = claudeConfigDir();
|
|
10447
10515
|
if (!cfg) return null;
|
|
10448
10516
|
let best = null;
|
|
10449
|
-
for (const { path: path2, isSubagent, archived } of enumerateJsonls(
|
|
10517
|
+
for (const { path: path2, isSubagent, archived } of enumerateJsonls(join19(cfg, "projects"))) {
|
|
10450
10518
|
if (isSubagent || archived) continue;
|
|
10451
|
-
const id =
|
|
10452
|
-
const meta = readSidecarMeta(
|
|
10519
|
+
const id = basename6(path2).slice(0, -".jsonl".length);
|
|
10520
|
+
const meta = readSidecarMeta(join19(dirname6(path2), `${id}.meta.json`));
|
|
10453
10521
|
if (meta.role !== "admin" || meta.channel !== "webchat") continue;
|
|
10454
10522
|
if (multiAccount && meta.accountId !== scopeAccountId) continue;
|
|
10455
10523
|
let mtimeMs;
|
|
@@ -10472,7 +10540,7 @@ function latestAdminWebchatSessionId(requesterUserId, primaryUserId, scopeAccoun
|
|
|
10472
10540
|
function overrideKnownNonArchived(id) {
|
|
10473
10541
|
const { projectDir } = locateSession(id);
|
|
10474
10542
|
if (projectDir === null) return sessionSidecarExists(id);
|
|
10475
|
-
return
|
|
10543
|
+
return basename6(projectDir) !== "archive";
|
|
10476
10544
|
}
|
|
10477
10545
|
function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId, scopeAccountId, multiAccount) {
|
|
10478
10546
|
const bootstrapAccountId = scopeAccountId ?? accountId;
|
|
@@ -10508,8 +10576,8 @@ async function reapplyLeversViaManager() {
|
|
|
10508
10576
|
var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
|
|
10509
10577
|
var sendSeq = 0;
|
|
10510
10578
|
function createWebchatRoutes(deps) {
|
|
10511
|
-
const
|
|
10512
|
-
|
|
10579
|
+
const app62 = new Hono();
|
|
10580
|
+
app62.post("/send", requireAdminSession, async (c) => {
|
|
10513
10581
|
let accountId;
|
|
10514
10582
|
try {
|
|
10515
10583
|
accountId = resolvePlatformAccountId();
|
|
@@ -10709,7 +10777,7 @@ ${note}` : note;
|
|
|
10709
10777
|
if (turnTimer.unref) turnTimer.unref();
|
|
10710
10778
|
return c.json({ ok: true });
|
|
10711
10779
|
});
|
|
10712
|
-
|
|
10780
|
+
app62.post("/interrupt", requireAdminSession, async (c) => {
|
|
10713
10781
|
const cacheKey = c.get("cacheKey");
|
|
10714
10782
|
const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
|
|
10715
10783
|
const primaryUserId = resolvePrimaryAdminUserId();
|
|
@@ -10737,7 +10805,7 @@ ${note}` : note;
|
|
|
10737
10805
|
}
|
|
10738
10806
|
return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
|
|
10739
10807
|
});
|
|
10740
|
-
|
|
10808
|
+
app62.post("/settings", requireAdminSession, async (c) => {
|
|
10741
10809
|
const body = await c.req.json().catch(() => null);
|
|
10742
10810
|
const op = body?.op;
|
|
10743
10811
|
const value = body?.value;
|
|
@@ -10759,7 +10827,7 @@ ${note}` : note;
|
|
|
10759
10827
|
console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
|
|
10760
10828
|
return c.json({ error: "account unresolved" }, 503);
|
|
10761
10829
|
}
|
|
10762
|
-
const accountJsonPath =
|
|
10830
|
+
const accountJsonPath = join19(account.accountDir, "account.json");
|
|
10763
10831
|
try {
|
|
10764
10832
|
const parsed = JSON.parse(readFileSync19(accountJsonPath, "utf8"));
|
|
10765
10833
|
if (op === "model") parsed.adminModel = value;
|
|
@@ -10777,7 +10845,7 @@ ${note}` : note;
|
|
|
10777
10845
|
console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
|
|
10778
10846
|
return c.json({ ok: true, settingsApplied });
|
|
10779
10847
|
});
|
|
10780
|
-
|
|
10848
|
+
app62.get("/session", requireAdminSession, async (c) => {
|
|
10781
10849
|
let accountId;
|
|
10782
10850
|
try {
|
|
10783
10851
|
accountId = resolvePlatformAccountId();
|
|
@@ -10807,7 +10875,7 @@ ${note}` : note;
|
|
|
10807
10875
|
const cfg2 = claudeConfigDir();
|
|
10808
10876
|
if (cfg2) {
|
|
10809
10877
|
const source2 = resolveBridgeSource(
|
|
10810
|
-
|
|
10878
|
+
join19(cfg2, "sessions"),
|
|
10811
10879
|
target,
|
|
10812
10880
|
(id) => locateSession(id).projectDir !== null
|
|
10813
10881
|
);
|
|
@@ -10839,15 +10907,15 @@ ${note}` : note;
|
|
|
10839
10907
|
const cfg = claudeConfigDir();
|
|
10840
10908
|
let projectDir = null;
|
|
10841
10909
|
if (cfg) {
|
|
10842
|
-
for (const { path: path2 } of enumerateJsonls(
|
|
10843
|
-
if (
|
|
10910
|
+
for (const { path: path2 } of enumerateJsonls(join19(cfg, "projects"))) {
|
|
10911
|
+
if (basename6(path2) === `${sessionId}.jsonl`) {
|
|
10844
10912
|
projectDir = dirname6(path2);
|
|
10845
10913
|
break;
|
|
10846
10914
|
}
|
|
10847
10915
|
}
|
|
10848
10916
|
}
|
|
10849
10917
|
if (source === "latest" && requesterUserId !== null) {
|
|
10850
|
-
const owner = readSidecarMeta(
|
|
10918
|
+
const owner = readSidecarMeta(join19(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
|
|
10851
10919
|
if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
|
|
10852
10920
|
console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
|
|
10853
10921
|
}
|
|
@@ -10855,7 +10923,7 @@ ${note}` : note;
|
|
|
10855
10923
|
const indicators = await fetchComposerIndicators(sessionId);
|
|
10856
10924
|
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
10925
|
});
|
|
10858
|
-
|
|
10926
|
+
app62.post("/permission-verdict", requireAdminSession, async (c) => {
|
|
10859
10927
|
const body = await c.req.json().catch(() => null);
|
|
10860
10928
|
const sessionId = body?.sessionId;
|
|
10861
10929
|
const requestId = body?.request_id;
|
|
@@ -10872,15 +10940,15 @@ ${note}` : note;
|
|
|
10872
10940
|
const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
|
|
10873
10941
|
return c.json({ ok });
|
|
10874
10942
|
});
|
|
10875
|
-
return
|
|
10943
|
+
return app62;
|
|
10876
10944
|
}
|
|
10877
10945
|
|
|
10878
10946
|
// server/routes/webchat-greeting.ts
|
|
10879
10947
|
import { resolve as resolve14 } from "path";
|
|
10880
10948
|
|
|
10881
10949
|
// app/lib/claude-agent/specialist-roster.ts
|
|
10882
|
-
import { existsSync as
|
|
10883
|
-
import { join as
|
|
10950
|
+
import { existsSync as existsSync13, readFileSync as readFileSync20, readdirSync as readdirSync13 } from "fs";
|
|
10951
|
+
import { join as join20 } from "path";
|
|
10884
10952
|
function field(fm, name) {
|
|
10885
10953
|
const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
|
|
10886
10954
|
if (!m) return null;
|
|
@@ -10891,15 +10959,15 @@ function field(fm, name) {
|
|
|
10891
10959
|
return value || null;
|
|
10892
10960
|
}
|
|
10893
10961
|
function readSpecialistRoster(specialistsDir) {
|
|
10894
|
-
if (!
|
|
10895
|
-
const entries =
|
|
10962
|
+
if (!existsSync13(specialistsDir)) return { specialists: [], skipped: [] };
|
|
10963
|
+
const entries = readdirSync13(specialistsDir);
|
|
10896
10964
|
const specialists = [];
|
|
10897
10965
|
const skipped = [];
|
|
10898
10966
|
for (const file of entries.sort()) {
|
|
10899
10967
|
if (!file.endsWith(".md")) continue;
|
|
10900
10968
|
let raw;
|
|
10901
10969
|
try {
|
|
10902
|
-
raw = readFileSync20(
|
|
10970
|
+
raw = readFileSync20(join20(specialistsDir, file), "utf-8");
|
|
10903
10971
|
} catch (err) {
|
|
10904
10972
|
skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
|
|
10905
10973
|
continue;
|
|
@@ -11015,9 +11083,9 @@ function r2n(value) {
|
|
|
11015
11083
|
var webchat_greeting_default = app6;
|
|
11016
11084
|
|
|
11017
11085
|
// server/routes/telegram.ts
|
|
11018
|
-
import { homedir } from "os";
|
|
11019
|
-
import { resolve as resolve15, join as
|
|
11020
|
-
import { existsSync as
|
|
11086
|
+
import { homedir as homedir2 } from "os";
|
|
11087
|
+
import { resolve as resolve15, join as join21 } from "path";
|
|
11088
|
+
import { existsSync as existsSync14, readFileSync as readFileSync21 } from "fs";
|
|
11021
11089
|
|
|
11022
11090
|
// app/lib/telegram/gateway/instance.ts
|
|
11023
11091
|
var instance = null;
|
|
@@ -11076,8 +11144,8 @@ function routeTelegramUpdate(input) {
|
|
|
11076
11144
|
var TAG23 = "[telegram-inbound]";
|
|
11077
11145
|
function configDirName() {
|
|
11078
11146
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT ?? resolve15(process.cwd(), "..");
|
|
11079
|
-
const brandPath =
|
|
11080
|
-
if (
|
|
11147
|
+
const brandPath = join21(platformRoot3, "config", "brand.json");
|
|
11148
|
+
if (existsSync14(brandPath)) {
|
|
11081
11149
|
try {
|
|
11082
11150
|
return JSON.parse(readFileSync21(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
11083
11151
|
} catch {
|
|
@@ -11087,7 +11155,7 @@ function configDirName() {
|
|
|
11087
11155
|
}
|
|
11088
11156
|
function secretPath(botType) {
|
|
11089
11157
|
const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
|
|
11090
|
-
return resolve15(
|
|
11158
|
+
return resolve15(homedir2(), configDirName(), filename);
|
|
11091
11159
|
}
|
|
11092
11160
|
var app7 = new Hono();
|
|
11093
11161
|
app7.post("/", async (c) => {
|
|
@@ -11098,7 +11166,7 @@ app7.post("/", async (c) => {
|
|
|
11098
11166
|
return c.json({ ok: false }, 400);
|
|
11099
11167
|
}
|
|
11100
11168
|
const sp = secretPath(botType);
|
|
11101
|
-
if (!
|
|
11169
|
+
if (!existsSync14(sp)) {
|
|
11102
11170
|
console.error(`${TAG23} op=reject reason=no-secret-file botType=${botType}`);
|
|
11103
11171
|
return c.json({ ok: false }, 401);
|
|
11104
11172
|
}
|
|
@@ -11165,21 +11233,21 @@ app7.post("/", async (c) => {
|
|
|
11165
11233
|
var telegram_default = app7;
|
|
11166
11234
|
|
|
11167
11235
|
// server/routes/quickbooks.ts
|
|
11168
|
-
import { join as
|
|
11169
|
-
import { existsSync as
|
|
11236
|
+
import { join as join22 } from "path";
|
|
11237
|
+
import { existsSync as existsSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync5 } from "fs";
|
|
11170
11238
|
var TAG24 = "[quickbooks]";
|
|
11171
11239
|
var INTUIT_TOKEN_URL = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
|
|
11172
11240
|
var STATE_RE = /^[A-Za-z0-9_-]+$/;
|
|
11173
11241
|
function pendingPath(accountDir, state) {
|
|
11174
|
-
return
|
|
11242
|
+
return join22(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
|
|
11175
11243
|
}
|
|
11176
11244
|
function storePath(accountDir) {
|
|
11177
|
-
return
|
|
11245
|
+
return join22(accountDir, "secrets", "quickbooks.json");
|
|
11178
11246
|
}
|
|
11179
11247
|
async function completeConsent(args) {
|
|
11180
11248
|
const { accountDir, code, realmId } = args;
|
|
11181
11249
|
const state = args.state;
|
|
11182
|
-
if (!state || !STATE_RE.test(state) || !
|
|
11250
|
+
if (!state || !STATE_RE.test(state) || !existsSync15(pendingPath(accountDir, state))) {
|
|
11183
11251
|
console.error(`${TAG24} op=callback state=${state ?? ""} stateValid=false realmId=${realmId ?? ""}`);
|
|
11184
11252
|
return { ok: false, status: 400, message: "Invalid or unknown authorization state.", stateValid: false };
|
|
11185
11253
|
}
|
|
@@ -11206,7 +11274,7 @@ async function completeConsent(args) {
|
|
|
11206
11274
|
if (!code || !realmId) {
|
|
11207
11275
|
return { ok: false, status: 400, message: "Missing code or realmId in the callback.", stateValid: true };
|
|
11208
11276
|
}
|
|
11209
|
-
if (!
|
|
11277
|
+
if (!existsSync15(storePath(accountDir))) {
|
|
11210
11278
|
return { ok: false, status: 500, message: "No QuickBooks credentials are stored for this account.", stateValid: true };
|
|
11211
11279
|
}
|
|
11212
11280
|
const store2 = JSON.parse(readFileSync22(storePath(accountDir), "utf-8"));
|
|
@@ -11241,7 +11309,7 @@ async function completeConsent(args) {
|
|
|
11241
11309
|
refreshTokenExpiry: now + (body.x_refresh_token_expires_in ?? 864e4) * 1e3,
|
|
11242
11310
|
lastRefresh: now
|
|
11243
11311
|
};
|
|
11244
|
-
mkdirSync4(
|
|
11312
|
+
mkdirSync4(join22(accountDir, "secrets"), { recursive: true });
|
|
11245
11313
|
writeFileSync8(storePath(accountDir), JSON.stringify(store2, null, 2), { mode: 384 });
|
|
11246
11314
|
const persisted = JSON.parse(readFileSync22(storePath(accountDir), "utf-8")).connections?.[realmId]?.refreshToken === body.refresh_token;
|
|
11247
11315
|
console.error(`${TAG24} op=token-exchange realmId=${realmId} persisted=${persisted}`);
|
|
@@ -11274,7 +11342,7 @@ var quickbooks_default = app8;
|
|
|
11274
11342
|
|
|
11275
11343
|
// server/routes/onboarding.ts
|
|
11276
11344
|
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
|
|
11345
|
+
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
11346
|
import { createHash as createHash4, randomUUID as randomUUID7 } from "crypto";
|
|
11279
11347
|
|
|
11280
11348
|
// app/lib/claude-spawn-env.ts
|
|
@@ -11283,7 +11351,7 @@ function claudeBin() {
|
|
|
11283
11351
|
}
|
|
11284
11352
|
|
|
11285
11353
|
// server/routes/onboarding.ts
|
|
11286
|
-
import { dirname as dirname8, join as
|
|
11354
|
+
import { dirname as dirname8, join as join24 } from "path";
|
|
11287
11355
|
|
|
11288
11356
|
// app/lib/claude-keychain.ts
|
|
11289
11357
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -11412,8 +11480,8 @@ function readHostCredsBlob(service) {
|
|
|
11412
11480
|
}
|
|
11413
11481
|
|
|
11414
11482
|
// ../lib/admins-write/src/index.ts
|
|
11415
|
-
import { existsSync as
|
|
11416
|
-
import { dirname as dirname7, join as
|
|
11483
|
+
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";
|
|
11484
|
+
import { dirname as dirname7, join as join23 } from "path";
|
|
11417
11485
|
function id8(value) {
|
|
11418
11486
|
return value.slice(0, 8);
|
|
11419
11487
|
}
|
|
@@ -11423,7 +11491,8 @@ function formatAuditRowIds(userIds) {
|
|
|
11423
11491
|
function appendUsersAuditLine(audit, fields) {
|
|
11424
11492
|
const sess = audit.session ? ` session=${id8(audit.session)}` : "";
|
|
11425
11493
|
const actor = audit.actor.includes("-") ? id8(audit.actor) : audit.actor;
|
|
11426
|
-
const
|
|
11494
|
+
const targetFields = audit.target !== void 0 ? ` target=${audit.target.includes("-") ? id8(audit.target) : audit.target} explicitUserId=${audit.explicitUserId ? "true" : "false"}` : "";
|
|
11495
|
+
const line = `[users-audit] action=${fields.action} actor=${actor}${targetFields}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
|
|
11427
11496
|
`;
|
|
11428
11497
|
try {
|
|
11429
11498
|
mkdirSync5(dirname7(audit.logFile), { recursive: true, mode: 448 });
|
|
@@ -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");
|
|
@@ -12164,13 +12233,13 @@ var client_error_default = app10;
|
|
|
12164
12233
|
// server/routes/admin/session.ts
|
|
12165
12234
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
12166
12235
|
async function resolveUserIdentity(accountId, userId) {
|
|
12167
|
-
const result = await
|
|
12168
|
-
if (result.source === "
|
|
12169
|
-
console.log(`[admin-identity] userName-source=
|
|
12170
|
-
return { userName: result.
|
|
12236
|
+
const result = await loadAdminUserName(userId);
|
|
12237
|
+
if (result.source === "neo4j") {
|
|
12238
|
+
console.log(`[admin-identity] userName-source=person userId=${userId.slice(0, 8)} accountId=${accountId.slice(0, 8)} name=${result.joined} avatar=${result.avatar ? "present" : "absent"}`);
|
|
12239
|
+
return { userName: result.joined, avatar: result.avatar };
|
|
12171
12240
|
}
|
|
12172
12241
|
console.log(`[admin-identity] userName-source=fallback reason=${result.reason} userId=${userId.slice(0, 8)} accountId=${accountId.slice(0, 8)}`);
|
|
12173
|
-
const userName = result.reason === "neo4j-unreachable" ?
|
|
12242
|
+
const userName = result.reason === "neo4j-unreachable" ? void 0 : null;
|
|
12174
12243
|
return { userName, avatar: null };
|
|
12175
12244
|
}
|
|
12176
12245
|
async function createAdminSession(accountId, thinkingView, userId, userName, role, avatar) {
|
|
@@ -12178,7 +12247,7 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
|
|
|
12178
12247
|
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
12179
12248
|
const signedSessionToken = randomUUID8();
|
|
12180
12249
|
const cacheKey = fingerprintSessionKey(signedSessionToken);
|
|
12181
|
-
registerSession(cacheKey, "admin", accountId, void 0, userId, userName, role);
|
|
12250
|
+
registerSession(cacheKey, "admin", accountId, void 0, userId, userName ?? void 0, role);
|
|
12182
12251
|
if (userId) setWantsPriorConversation(cacheKey);
|
|
12183
12252
|
const businessName = await fetchAccountName(accountId) || void 0;
|
|
12184
12253
|
let initialSessionId = null;
|
|
@@ -12255,7 +12324,7 @@ app11.get("/", async (c) => {
|
|
|
12255
12324
|
const resolved = await resolveUserIdentity(accountId, restoredUserId);
|
|
12256
12325
|
restoredUserName = resolved.userName;
|
|
12257
12326
|
restoredAvatar = resolved.avatar;
|
|
12258
|
-
if (resolved.userName
|
|
12327
|
+
if (typeof resolved.userName === "string") {
|
|
12259
12328
|
registerSession(cacheKey, "admin", accountId, void 0, restoredUserId, resolved.userName, role ?? void 0);
|
|
12260
12329
|
}
|
|
12261
12330
|
}
|
|
@@ -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 {
|
|
@@ -13407,7 +13476,7 @@ async function resolveOwnerProfileBlock(accountId, userId) {
|
|
|
13407
13476
|
async function resolveAuthenticatedName(accountId, userId) {
|
|
13408
13477
|
if (!userId) return void 0;
|
|
13409
13478
|
try {
|
|
13410
|
-
const res = await loadAdminUserName(
|
|
13479
|
+
const res = await loadAdminUserName(userId);
|
|
13411
13480
|
return res.source === "neo4j" ? res.joined : void 0;
|
|
13412
13481
|
} catch (err) {
|
|
13413
13482
|
console.error(
|
|
@@ -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"`
|
|
@@ -18312,7 +18381,6 @@ app34.post("/", requireAdminSession, async (c) => {
|
|
|
18312
18381
|
adminUserId,
|
|
18313
18382
|
convAccountId,
|
|
18314
18383
|
`session:${plan.sessionId}`,
|
|
18315
|
-
authenticatedName,
|
|
18316
18384
|
plan.sessionId
|
|
18317
18385
|
);
|
|
18318
18386
|
console.log(
|
|
@@ -18572,12 +18640,12 @@ app36.get("/", async (c) => {
|
|
|
18572
18640
|
var system_stats_default = app36;
|
|
18573
18641
|
|
|
18574
18642
|
// server/routes/admin/health.ts
|
|
18575
|
-
import { existsSync as
|
|
18576
|
-
import { resolve as resolve24, join as
|
|
18643
|
+
import { existsSync as existsSync28, readFileSync as readFileSync29 } from "fs";
|
|
18644
|
+
import { resolve as resolve24, join as join30 } from "path";
|
|
18577
18645
|
var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
|
|
18578
18646
|
var brandHostname = "maxy";
|
|
18579
|
-
var brandJsonPath =
|
|
18580
|
-
if (
|
|
18647
|
+
var brandJsonPath = join30(PLATFORM_ROOT6, "config", "brand.json");
|
|
18648
|
+
if (existsSync28(brandJsonPath)) {
|
|
18581
18649
|
try {
|
|
18582
18650
|
const brand = JSON.parse(readFileSync29(brandJsonPath, "utf-8"));
|
|
18583
18651
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
@@ -18588,7 +18656,7 @@ var VERSION_FILE = resolve24(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
|
|
|
18588
18656
|
var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
18589
18657
|
var PROBE_TIMEOUT_MS = 1e3;
|
|
18590
18658
|
function readVersion() {
|
|
18591
|
-
if (!
|
|
18659
|
+
if (!existsSync28(VERSION_FILE)) return "unknown";
|
|
18592
18660
|
return readFileSync29(VERSION_FILE, "utf-8").trim() || "unknown";
|
|
18593
18661
|
}
|
|
18594
18662
|
async function probeConversationDb() {
|
|
@@ -19365,8 +19433,8 @@ app44.post("/launch", requireAdminSession, async (c) => {
|
|
|
19365
19433
|
var browser_default = app44;
|
|
19366
19434
|
|
|
19367
19435
|
// server/routes/admin/calendar.ts
|
|
19368
|
-
import { existsSync as
|
|
19369
|
-
import { join as
|
|
19436
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19437
|
+
import { join as join32 } from "path";
|
|
19370
19438
|
|
|
19371
19439
|
// server/lib/calendar-ics.ts
|
|
19372
19440
|
var CRLF = "\r\n";
|
|
@@ -19466,7 +19534,7 @@ function countVEvents(ics) {
|
|
|
19466
19534
|
|
|
19467
19535
|
// server/lib/calendar-availability.ts
|
|
19468
19536
|
import { readFileSync as readFileSync30 } from "fs";
|
|
19469
|
-
import { join as
|
|
19537
|
+
import { join as join31 } from "path";
|
|
19470
19538
|
var AVAILABILITY_FILENAME = "calendar-availability.json";
|
|
19471
19539
|
var REQUIRED_KEYS = [
|
|
19472
19540
|
"timezone",
|
|
@@ -19475,7 +19543,7 @@ var REQUIRED_KEYS = [
|
|
|
19475
19543
|
"weekly"
|
|
19476
19544
|
];
|
|
19477
19545
|
function readAvailabilityConfig(accountDir) {
|
|
19478
|
-
const path2 =
|
|
19546
|
+
const path2 = join31(accountDir, AVAILABILITY_FILENAME);
|
|
19479
19547
|
let raw;
|
|
19480
19548
|
try {
|
|
19481
19549
|
raw = readFileSync30(path2, "utf-8");
|
|
@@ -19837,7 +19905,7 @@ app45.get("/booking-link", requireAdminSession, (c) => {
|
|
|
19837
19905
|
console.error('[calendar] op=booking-link-fail err="no account configured"');
|
|
19838
19906
|
return c.json({ bookingDomain: null });
|
|
19839
19907
|
}
|
|
19840
|
-
if (!
|
|
19908
|
+
if (!existsSync29(join32(account.accountDir, AVAILABILITY_FILENAME))) {
|
|
19841
19909
|
console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
|
|
19842
19910
|
return c.json({ bookingDomain: null });
|
|
19843
19911
|
}
|
|
@@ -19932,7 +20000,6 @@ var tasks_list_default = app46;
|
|
|
19932
20000
|
|
|
19933
20001
|
// server/routes/admin/task-timer-start.ts
|
|
19934
20002
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
19935
|
-
import neo4j5 from "neo4j-driver";
|
|
19936
20003
|
var TAG34 = "[task-timer]";
|
|
19937
20004
|
var app47 = new Hono();
|
|
19938
20005
|
app47.post("/", requireAdminSession, async (c) => {
|
|
@@ -19959,30 +20026,17 @@ app47.post("/", requireAdminSession, async (c) => {
|
|
|
19959
20026
|
return c.json({ error: "task-not-found" }, 404);
|
|
19960
20027
|
}
|
|
19961
20028
|
const open = await session.run(
|
|
19962
|
-
`MATCH (te:TimeEntry {accountId: $accountId}) WHERE te.endedAt IS NULL
|
|
19963
|
-
RETURN te.entryId AS entryId, te.
|
|
20029
|
+
`MATCH (te:TimeEntry {accountId: $accountId, taskId: $taskId}) WHERE te.endedAt IS NULL
|
|
20030
|
+
RETURN te.entryId AS entryId, te.startedAt AS startedAt
|
|
19964
20031
|
ORDER BY te.startedAt LIMIT 1`,
|
|
19965
|
-
{ accountId }
|
|
20032
|
+
{ accountId, taskId }
|
|
19966
20033
|
);
|
|
19967
20034
|
const priorEntryId = open.records[0]?.get("entryId");
|
|
19968
|
-
const priorTaskId = open.records[0]?.get("taskId");
|
|
19969
20035
|
const priorStartedAt = open.records[0]?.get("startedAt");
|
|
19970
|
-
|
|
19971
|
-
|
|
20036
|
+
if (priorEntryId) {
|
|
20037
|
+
console.log(`${TAG34} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
|
|
19972
20038
|
return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
|
|
19973
20039
|
}
|
|
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
20040
|
const entryId = randomUUID13();
|
|
19987
20041
|
await session.run(
|
|
19988
20042
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
@@ -20002,7 +20056,7 @@ app47.post("/", requireAdminSession, async (c) => {
|
|
|
20002
20056
|
var task_timer_start_default = app47;
|
|
20003
20057
|
|
|
20004
20058
|
// server/routes/admin/task-timer-stop.ts
|
|
20005
|
-
import
|
|
20059
|
+
import neo4j5 from "neo4j-driver";
|
|
20006
20060
|
var TAG35 = "[task-timer]";
|
|
20007
20061
|
var app48 = new Hono();
|
|
20008
20062
|
app48.post("/", requireAdminSession, async (c) => {
|
|
@@ -20045,18 +20099,21 @@ app48.post("/", requireAdminSession, async (c) => {
|
|
|
20045
20099
|
WITH te
|
|
20046
20100
|
MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20047
20101
|
SET t.secondsLogged = coalesce(t.secondsLogged, 0) + $seconds`,
|
|
20048
|
-
{ entryId, taskId, accountId, now, seconds:
|
|
20102
|
+
{ entryId, taskId, accountId, now, seconds: neo4j5.int(seconds) }
|
|
20049
20103
|
);
|
|
20050
20104
|
const verify = await session.run(
|
|
20051
20105
|
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20052
20106
|
OPTIONAL MATCH (te:TimeEntry {taskId: $taskId, accountId: $accountId}) WHERE te.endedAt IS NOT NULL
|
|
20053
|
-
|
|
20107
|
+
WITH t, coalesce(sum(te.seconds), 0) AS sumEntries
|
|
20108
|
+
OPTIONAL MATCH (ta:TimeAdjustment {taskId: $taskId, accountId: $accountId})
|
|
20109
|
+
RETURN sumEntries, coalesce(sum(ta.delta), 0) AS sumAdjustments, coalesce(t.secondsLogged, 0) AS secondsLogged`,
|
|
20054
20110
|
{ taskId, accountId }
|
|
20055
20111
|
);
|
|
20056
20112
|
const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
|
|
20113
|
+
const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
|
|
20057
20114
|
const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
|
|
20058
20115
|
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}`);
|
|
20116
|
+
console.log(`${TAG35} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
|
|
20060
20117
|
return c.json({ ok: true, running: false, seconds, secondsLogged });
|
|
20061
20118
|
} catch (err) {
|
|
20062
20119
|
console.error(`${TAG35} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
|
|
@@ -20106,56 +20163,137 @@ app49.post("/", requireAdminSession, async (c) => {
|
|
|
20106
20163
|
});
|
|
20107
20164
|
var task_complete_default = app49;
|
|
20108
20165
|
|
|
20109
|
-
// server/routes/admin/
|
|
20166
|
+
// server/routes/admin/task-time-adjust.ts
|
|
20167
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
20168
|
+
import neo4j6 from "neo4j-driver";
|
|
20169
|
+
var TAG37 = "[task-time-adjust]";
|
|
20110
20170
|
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
|
-
|
|
20171
|
+
app50.post("/", requireAdminSession, async (c) => {
|
|
20172
|
+
const cacheKey = c.var.cacheKey;
|
|
20173
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
20174
|
+
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
20175
|
+
let body;
|
|
20176
|
+
try {
|
|
20177
|
+
body = await c.req.json();
|
|
20178
|
+
} catch {
|
|
20179
|
+
console.error(`${TAG37} op=reject reason=bad-json`);
|
|
20180
|
+
return c.json({ error: "invalid-json" }, 400);
|
|
20181
|
+
}
|
|
20182
|
+
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
20183
|
+
if (!taskId) {
|
|
20184
|
+
console.error(`${TAG37} op=reject reason=no-task`);
|
|
20185
|
+
return c.json({ error: "taskId required" }, 400);
|
|
20186
|
+
}
|
|
20187
|
+
const newSeconds = body.newSeconds;
|
|
20188
|
+
if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
|
|
20189
|
+
console.error(`${TAG37} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
|
|
20190
|
+
return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
|
|
20191
|
+
}
|
|
20192
|
+
const adjustmentId = randomUUID14();
|
|
20193
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20194
|
+
console.log(`${TAG37} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
|
|
20195
|
+
const session = getSession();
|
|
20196
|
+
try {
|
|
20197
|
+
const guard = await session.run(
|
|
20198
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20199
|
+
OPTIONAL MATCH (te:TimeEntry {taskId: $taskId, accountId: $accountId}) WHERE te.endedAt IS NULL
|
|
20200
|
+
RETURN t.taskId AS taskId, count(te) AS openCount, coalesce(t.secondsLogged, 0) AS previousSeconds`,
|
|
20201
|
+
{ taskId, accountId }
|
|
20202
|
+
);
|
|
20203
|
+
if (guard.records.length === 0) {
|
|
20204
|
+
console.error(`${TAG37} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
20205
|
+
return c.json({ error: "task-not-found" }, 404);
|
|
20206
|
+
}
|
|
20207
|
+
const openCount = toNum(guard.records[0].get("openCount"));
|
|
20208
|
+
if (openCount > 0) {
|
|
20209
|
+
console.error(`${TAG37} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
|
|
20210
|
+
return c.json({ error: "task-timer-running" }, 409);
|
|
20211
|
+
}
|
|
20212
|
+
const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
|
|
20213
|
+
const delta = newSeconds - previousSeconds;
|
|
20214
|
+
const write = await session.run(
|
|
20215
|
+
`MATCH (t:Task {taskId: $taskId, accountId: $accountId})
|
|
20216
|
+
CREATE (ta:TimeAdjustment {
|
|
20217
|
+
adjustmentId: $adjustmentId, taskId: $taskId, accountId: $accountId, at: $now,
|
|
20218
|
+
previousSeconds: $previousSeconds, newSeconds: $newSeconds, delta: $delta,
|
|
20219
|
+
sourceSessionKey: $sourceSessionKey
|
|
20220
|
+
})
|
|
20221
|
+
SET t.secondsLogged = $newSeconds
|
|
20222
|
+
RETURN coalesce(t.secondsLogged, 0) AS secondsLoggedAfter`,
|
|
20223
|
+
{
|
|
20224
|
+
taskId,
|
|
20225
|
+
accountId,
|
|
20226
|
+
adjustmentId,
|
|
20227
|
+
now,
|
|
20228
|
+
previousSeconds: neo4j6.int(previousSeconds),
|
|
20229
|
+
newSeconds: neo4j6.int(newSeconds),
|
|
20230
|
+
delta: neo4j6.int(delta),
|
|
20231
|
+
sourceSessionKey: cacheKey
|
|
20232
|
+
}
|
|
20233
|
+
);
|
|
20234
|
+
const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
|
|
20235
|
+
console.log(`${TAG37} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
|
|
20236
|
+
return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
|
|
20237
|
+
} catch (err) {
|
|
20238
|
+
console.error(`${TAG37} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
20239
|
+
return c.json({ error: "task-time-adjust-failed" }, 500);
|
|
20240
|
+
} finally {
|
|
20241
|
+
await session.close();
|
|
20242
|
+
}
|
|
20243
|
+
});
|
|
20244
|
+
var task_time_adjust_default = app50;
|
|
20245
|
+
|
|
20246
|
+
// server/routes/admin/index.ts
|
|
20247
|
+
var app51 = new Hono();
|
|
20248
|
+
app51.route("/session", session_default);
|
|
20249
|
+
app51.route("/accounts", accounts_default);
|
|
20250
|
+
app51.route("/logs", logs_default);
|
|
20251
|
+
app51.route("/claude-info", claude_info_default);
|
|
20252
|
+
app51.route("/attachment", attachment_default);
|
|
20253
|
+
app51.route("/agents", agents_default);
|
|
20254
|
+
app51.route("/sessions", sessions_default);
|
|
20255
|
+
app51.route("/claude-sessions", claude_sessions_default);
|
|
20256
|
+
app51.route("/log-ingest", log_ingest_default);
|
|
20257
|
+
app51.route("/events", events_default);
|
|
20258
|
+
app51.route("/files", files_default);
|
|
20259
|
+
app51.route("/graph-search", graph_search_default);
|
|
20260
|
+
app51.route("/graph-subgraph", graph_subgraph_default);
|
|
20261
|
+
app51.route("/graph-delete", graph_delete_default);
|
|
20262
|
+
app51.route("/graph-restore", graph_restore_default);
|
|
20263
|
+
app51.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
20264
|
+
app51.route("/graph-default-view", graph_default_view_default);
|
|
20265
|
+
app51.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
20266
|
+
app51.route("/sidebar-sessions", sidebar_sessions_default);
|
|
20267
|
+
app51.route("/session-delete", session_delete_default);
|
|
20268
|
+
app51.route("/session-stop", session_stop_default);
|
|
20269
|
+
app51.route("/session-archive", session_archive_default);
|
|
20270
|
+
app51.route("/session-rename", session_rename_default);
|
|
20271
|
+
app51.route("/session-usage", session_usage_default);
|
|
20272
|
+
app51.route("/browser", browser_default);
|
|
20273
|
+
app51.route("/session-rc-spawn", session_rc_spawn_default);
|
|
20274
|
+
app51.route("/session-reseat", session_reseat_default);
|
|
20275
|
+
app51.route("/system-stats", system_stats_default);
|
|
20276
|
+
app51.route("/health-brand", health_default2);
|
|
20277
|
+
app51.route("/linkedin-ingest", linkedin_ingest_default);
|
|
20278
|
+
app51.route("/post-turn-context", post_turn_context_default);
|
|
20279
|
+
app51.route("/public-session-context", public_session_context_default);
|
|
20280
|
+
app51.route("/public-session-exit", public_session_exit_default);
|
|
20281
|
+
app51.route("/access-session-evict", access_session_evict_default);
|
|
20282
|
+
app51.route("/enrol-person", enrol_person_default);
|
|
20283
|
+
app51.route("/calendar", calendar_default);
|
|
20284
|
+
app51.route("/tasks-list", tasks_list_default);
|
|
20285
|
+
app51.route("/task-timer-start", task_timer_start_default);
|
|
20286
|
+
app51.route("/task-timer-stop", task_timer_stop_default);
|
|
20287
|
+
app51.route("/task-complete", task_complete_default);
|
|
20288
|
+
app51.route("/task-time-adjust", task_time_adjust_default);
|
|
20289
|
+
var admin_default = app51;
|
|
20152
20290
|
|
|
20153
20291
|
// server/routes/access/verify-token.ts
|
|
20154
|
-
var
|
|
20292
|
+
var TAG38 = "[access-verify]";
|
|
20155
20293
|
var MINT_TAG = "[access-session-mint]";
|
|
20156
20294
|
var COOKIE_NAME = "__access_session";
|
|
20157
|
-
var
|
|
20158
|
-
|
|
20295
|
+
var app52 = new Hono();
|
|
20296
|
+
app52.post("/", async (c) => {
|
|
20159
20297
|
const ip = c.var.clientIp || "unknown";
|
|
20160
20298
|
let body;
|
|
20161
20299
|
try {
|
|
@@ -20170,39 +20308,39 @@ app51.post("/", async (c) => {
|
|
|
20170
20308
|
}
|
|
20171
20309
|
const rateMsg = checkAccessRateLimit(ip, agentSlug);
|
|
20172
20310
|
if (rateMsg) {
|
|
20173
|
-
console.error(`${
|
|
20311
|
+
console.error(`${TAG38} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
|
|
20174
20312
|
return c.json({ error: rateMsg }, 429);
|
|
20175
20313
|
}
|
|
20176
20314
|
const grant = await findGrantByMagicToken(token);
|
|
20177
20315
|
if (!grant) {
|
|
20178
20316
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20179
|
-
console.error(`${
|
|
20317
|
+
console.error(`${TAG38} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
|
|
20180
20318
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
20181
20319
|
}
|
|
20182
20320
|
if (grant.agentSlug !== agentSlug) {
|
|
20183
20321
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20184
20322
|
console.error(
|
|
20185
|
-
`${
|
|
20323
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
|
|
20186
20324
|
);
|
|
20187
20325
|
return c.json({ error: "invalid-or-expired-link" }, 401);
|
|
20188
20326
|
}
|
|
20189
20327
|
if (grant.status === "expired" || grant.status === "revoked") {
|
|
20190
20328
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20191
20329
|
console.error(
|
|
20192
|
-
`${
|
|
20330
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
|
|
20193
20331
|
);
|
|
20194
20332
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
20195
20333
|
}
|
|
20196
20334
|
if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
|
|
20197
20335
|
recordAccessFailedAttempt(ip, agentSlug);
|
|
20198
20336
|
console.error(
|
|
20199
|
-
`${
|
|
20337
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
|
|
20200
20338
|
);
|
|
20201
20339
|
return c.json({ error: "access-no-longer-valid" }, 401);
|
|
20202
20340
|
}
|
|
20203
20341
|
if (!grant.sliceToken) {
|
|
20204
20342
|
console.error(
|
|
20205
|
-
`${
|
|
20343
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
|
|
20206
20344
|
);
|
|
20207
20345
|
return c.json({ error: "grant-misconfigured" }, 500);
|
|
20208
20346
|
}
|
|
@@ -20218,12 +20356,12 @@ app51.post("/", async (c) => {
|
|
|
20218
20356
|
await consumeMagicTokenAndActivate(grant.grantId);
|
|
20219
20357
|
} catch (err) {
|
|
20220
20358
|
console.error(
|
|
20221
|
-
`${
|
|
20359
|
+
`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
20222
20360
|
);
|
|
20223
20361
|
return c.json({ error: "verification-failed" }, 500);
|
|
20224
20362
|
}
|
|
20225
20363
|
clearAccessRateLimit(ip, agentSlug);
|
|
20226
|
-
console.log(`${
|
|
20364
|
+
console.log(`${TAG38} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
|
|
20227
20365
|
console.log(
|
|
20228
20366
|
`${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
|
|
20229
20367
|
);
|
|
@@ -20237,7 +20375,7 @@ app51.post("/", async (c) => {
|
|
|
20237
20375
|
displayName: grant.displayName
|
|
20238
20376
|
});
|
|
20239
20377
|
});
|
|
20240
|
-
var verify_token_default =
|
|
20378
|
+
var verify_token_default = app52;
|
|
20241
20379
|
|
|
20242
20380
|
// app/lib/access-email.ts
|
|
20243
20381
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -20299,10 +20437,10 @@ async function sendMagicLinkEmail(payload) {
|
|
|
20299
20437
|
}
|
|
20300
20438
|
|
|
20301
20439
|
// server/routes/access/request-magic-link.ts
|
|
20302
|
-
var
|
|
20303
|
-
var
|
|
20440
|
+
var TAG39 = "[access-request-link]";
|
|
20441
|
+
var app53 = new Hono();
|
|
20304
20442
|
var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
|
|
20305
|
-
|
|
20443
|
+
app53.post("/", async (c) => {
|
|
20306
20444
|
let body;
|
|
20307
20445
|
try {
|
|
20308
20446
|
body = await c.req.json();
|
|
@@ -20316,18 +20454,18 @@ app52.post("/", async (c) => {
|
|
|
20316
20454
|
}
|
|
20317
20455
|
const rateMsg = checkRequestLinkRateLimit(contactValue);
|
|
20318
20456
|
if (rateMsg) {
|
|
20319
|
-
console.error(`${
|
|
20457
|
+
console.error(`${TAG39} contactValue=${maskContact(contactValue)} result=rate-limited`);
|
|
20320
20458
|
return c.json({ error: rateMsg }, 429);
|
|
20321
20459
|
}
|
|
20322
20460
|
recordRequestLinkAttempt(contactValue);
|
|
20323
20461
|
const accountId = process.env.ACCOUNT_ID ?? "";
|
|
20324
20462
|
if (!accountId) {
|
|
20325
|
-
console.error(`${
|
|
20463
|
+
console.error(`${TAG39} contactValue=${maskContact(contactValue)} result=no-account-id`);
|
|
20326
20464
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20327
20465
|
}
|
|
20328
20466
|
const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
|
|
20329
20467
|
if (!grant) {
|
|
20330
|
-
console.log(`${
|
|
20468
|
+
console.log(`${TAG39} contactValue=${maskContact(contactValue)} result=notfound`);
|
|
20331
20469
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20332
20470
|
}
|
|
20333
20471
|
let token;
|
|
@@ -20335,7 +20473,7 @@ app52.post("/", async (c) => {
|
|
|
20335
20473
|
token = await generateNewMagicToken(grant.grantId);
|
|
20336
20474
|
} catch (err) {
|
|
20337
20475
|
console.error(
|
|
20338
|
-
`${
|
|
20476
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
|
|
20339
20477
|
);
|
|
20340
20478
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20341
20479
|
}
|
|
@@ -20367,25 +20505,25 @@ app52.post("/", async (c) => {
|
|
|
20367
20505
|
});
|
|
20368
20506
|
if (!sendResult.ok) {
|
|
20369
20507
|
console.error(
|
|
20370
|
-
`${
|
|
20508
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
|
|
20371
20509
|
);
|
|
20372
20510
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20373
20511
|
}
|
|
20374
20512
|
console.log(
|
|
20375
|
-
`${
|
|
20513
|
+
`${TAG39} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
|
|
20376
20514
|
);
|
|
20377
20515
|
return c.json({ message: VISITOR_MESSAGE }, 200);
|
|
20378
20516
|
});
|
|
20379
|
-
var request_magic_link_default =
|
|
20517
|
+
var request_magic_link_default = app53;
|
|
20380
20518
|
|
|
20381
20519
|
// server/routes/access/index.ts
|
|
20382
|
-
var
|
|
20383
|
-
|
|
20384
|
-
|
|
20385
|
-
var access_default =
|
|
20520
|
+
var app54 = new Hono();
|
|
20521
|
+
app54.route("/verify-token", verify_token_default);
|
|
20522
|
+
app54.route("/request-magic-link", request_magic_link_default);
|
|
20523
|
+
var access_default = app54;
|
|
20386
20524
|
|
|
20387
20525
|
// server/routes/sites.ts
|
|
20388
|
-
import { existsSync as
|
|
20526
|
+
import { existsSync as existsSync30, readFileSync as readFileSync31, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
|
|
20389
20527
|
import { resolve as resolve26 } from "path";
|
|
20390
20528
|
var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
20391
20529
|
var MIME = {
|
|
@@ -20417,8 +20555,8 @@ function getExt(p) {
|
|
|
20417
20555
|
if (idx < p.lastIndexOf("/")) return "";
|
|
20418
20556
|
return p.slice(idx).toLowerCase();
|
|
20419
20557
|
}
|
|
20420
|
-
var
|
|
20421
|
-
|
|
20558
|
+
var app55 = new Hono();
|
|
20559
|
+
app55.get("/:rel{.*}", (c) => {
|
|
20422
20560
|
const reqPath = c.req.path;
|
|
20423
20561
|
const rawRel = c.req.param("rel") ?? "";
|
|
20424
20562
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -20451,7 +20589,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20451
20589
|
}
|
|
20452
20590
|
let stat8;
|
|
20453
20591
|
try {
|
|
20454
|
-
stat8 =
|
|
20592
|
+
stat8 = existsSync30(filePath) ? statSync12(filePath) : null;
|
|
20455
20593
|
} catch {
|
|
20456
20594
|
stat8 = null;
|
|
20457
20595
|
}
|
|
@@ -20470,7 +20608,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20470
20608
|
console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
|
|
20471
20609
|
return c.text("Forbidden", 403);
|
|
20472
20610
|
}
|
|
20473
|
-
if (!
|
|
20611
|
+
if (!existsSync30(filePath)) {
|
|
20474
20612
|
console.error(`[sites] not-found path=${reqPath} status=404`);
|
|
20475
20613
|
return c.text("Not found", 404);
|
|
20476
20614
|
}
|
|
@@ -20521,7 +20659,7 @@ app54.get("/:rel{.*}", (c) => {
|
|
|
20521
20659
|
"X-Content-Type-Options": "nosniff"
|
|
20522
20660
|
});
|
|
20523
20661
|
});
|
|
20524
|
-
var sites_default =
|
|
20662
|
+
var sites_default = app55;
|
|
20525
20663
|
|
|
20526
20664
|
// app/lib/visitor-token.ts
|
|
20527
20665
|
import { createHmac, randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -20601,8 +20739,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
|
|
|
20601
20739
|
var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
|
|
20602
20740
|
|
|
20603
20741
|
// app/lib/brand-config.ts
|
|
20604
|
-
import { existsSync as
|
|
20605
|
-
import { join as
|
|
20742
|
+
import { existsSync as existsSync31, readFileSync as readFileSync33 } from "fs";
|
|
20743
|
+
import { join as join33 } from "path";
|
|
20606
20744
|
var cached = null;
|
|
20607
20745
|
var cachedAttempted = false;
|
|
20608
20746
|
function readBrandConfig() {
|
|
@@ -20610,8 +20748,8 @@ function readBrandConfig() {
|
|
|
20610
20748
|
cachedAttempted = true;
|
|
20611
20749
|
const platformRoot3 = process.env.MAXY_PLATFORM_ROOT;
|
|
20612
20750
|
if (!platformRoot3) return null;
|
|
20613
|
-
const brandPath =
|
|
20614
|
-
if (!
|
|
20751
|
+
const brandPath = join33(platformRoot3, "config", "brand.json");
|
|
20752
|
+
if (!existsSync31(brandPath)) return null;
|
|
20615
20753
|
try {
|
|
20616
20754
|
cached = JSON.parse(readFileSync33(brandPath, "utf-8"));
|
|
20617
20755
|
return cached;
|
|
@@ -20621,7 +20759,7 @@ function readBrandConfig() {
|
|
|
20621
20759
|
}
|
|
20622
20760
|
|
|
20623
20761
|
// server/routes/visitor-consent.ts
|
|
20624
|
-
var
|
|
20762
|
+
var app56 = new Hono();
|
|
20625
20763
|
var CONSENT_COOKIE_NAME = "mxy_consent";
|
|
20626
20764
|
var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
|
|
20627
20765
|
var DEFAULT_CONSENT_COPY = {
|
|
@@ -20666,17 +20804,17 @@ function siteSlugFromReferer(referer) {
|
|
|
20666
20804
|
return "";
|
|
20667
20805
|
}
|
|
20668
20806
|
}
|
|
20669
|
-
|
|
20807
|
+
app56.options("/consent", (c) => {
|
|
20670
20808
|
const origin = getOrigin(c);
|
|
20671
20809
|
setCorsHeaders(c, origin);
|
|
20672
20810
|
return c.body(null, 204);
|
|
20673
20811
|
});
|
|
20674
|
-
|
|
20812
|
+
app56.options("/brand-config", (c) => {
|
|
20675
20813
|
const origin = getOrigin(c);
|
|
20676
20814
|
setCorsHeaders(c, origin);
|
|
20677
20815
|
return c.body(null, 204);
|
|
20678
20816
|
});
|
|
20679
|
-
|
|
20817
|
+
app56.post("/consent", async (c) => {
|
|
20680
20818
|
const origin = getOrigin(c);
|
|
20681
20819
|
setCorsHeaders(c, origin);
|
|
20682
20820
|
let raw;
|
|
@@ -20716,7 +20854,7 @@ app55.post("/consent", async (c) => {
|
|
|
20716
20854
|
console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
|
|
20717
20855
|
return c.body(null, 204);
|
|
20718
20856
|
});
|
|
20719
|
-
|
|
20857
|
+
app56.get("/brand-config", (c) => {
|
|
20720
20858
|
const origin = getOrigin(c);
|
|
20721
20859
|
setCorsHeaders(c, origin);
|
|
20722
20860
|
const brand = readBrandConfig();
|
|
@@ -20726,7 +20864,7 @@ app55.get("/brand-config", (c) => {
|
|
|
20726
20864
|
c.header("Cache-Control", "public, max-age=300");
|
|
20727
20865
|
return c.json({ consent: { copy, palette } });
|
|
20728
20866
|
});
|
|
20729
|
-
var visitor_consent_default =
|
|
20867
|
+
var visitor_consent_default = app56;
|
|
20730
20868
|
|
|
20731
20869
|
// server/routes/listings.ts
|
|
20732
20870
|
function getCookie(headerValue, name) {
|
|
@@ -20753,8 +20891,8 @@ function appendConsentParams(pageUrl, token) {
|
|
|
20753
20891
|
}
|
|
20754
20892
|
var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
|
|
20755
20893
|
var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
|
|
20756
|
-
var
|
|
20757
|
-
|
|
20894
|
+
var app57 = new Hono();
|
|
20895
|
+
app57.get("/:slug/click", async (c) => {
|
|
20758
20896
|
const slug = c.req.param("slug") ?? "";
|
|
20759
20897
|
const rawSession = c.req.query("session") ?? "";
|
|
20760
20898
|
const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
|
|
@@ -20818,10 +20956,10 @@ app56.get("/:slug/click", async (c) => {
|
|
|
20818
20956
|
console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
20819
20957
|
return c.redirect(redirectUrl, 302);
|
|
20820
20958
|
});
|
|
20821
|
-
var listings_default =
|
|
20959
|
+
var listings_default = app57;
|
|
20822
20960
|
|
|
20823
20961
|
// server/routes/visitor-event.ts
|
|
20824
|
-
var
|
|
20962
|
+
var app58 = new Hono();
|
|
20825
20963
|
var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
|
|
20826
20964
|
var buckets = /* @__PURE__ */ new Map();
|
|
20827
20965
|
var RATE_LIMIT = 60;
|
|
@@ -20888,12 +21026,12 @@ function originAllowed(origin, allowlist) {
|
|
|
20888
21026
|
return false;
|
|
20889
21027
|
}
|
|
20890
21028
|
}
|
|
20891
|
-
|
|
21029
|
+
app58.options("/event", (c) => {
|
|
20892
21030
|
const origin = getOrigin2(c);
|
|
20893
21031
|
setCorsHeaders2(c, origin);
|
|
20894
21032
|
return c.body(null, 204);
|
|
20895
21033
|
});
|
|
20896
|
-
|
|
21034
|
+
app58.post("/event", async (c) => {
|
|
20897
21035
|
const origin = getOrigin2(c);
|
|
20898
21036
|
setCorsHeaders2(c, origin);
|
|
20899
21037
|
const ua = c.req.header("user-agent") ?? "";
|
|
@@ -21098,11 +21236,11 @@ async function writeEvent(opts) {
|
|
|
21098
21236
|
);
|
|
21099
21237
|
}
|
|
21100
21238
|
}
|
|
21101
|
-
var visitor_event_default =
|
|
21239
|
+
var visitor_event_default = app58;
|
|
21102
21240
|
|
|
21103
21241
|
// server/routes/session.ts
|
|
21104
21242
|
import { resolve as resolve27 } from "path";
|
|
21105
|
-
import { existsSync as
|
|
21243
|
+
import { existsSync as existsSync32, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
|
|
21106
21244
|
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
21245
|
function writeBrandingCache(accountId, agentSlug, branding) {
|
|
21108
21246
|
try {
|
|
@@ -21144,8 +21282,8 @@ function withVisitorCookie(response, visitorId) {
|
|
|
21144
21282
|
headers
|
|
21145
21283
|
});
|
|
21146
21284
|
}
|
|
21147
|
-
var
|
|
21148
|
-
|
|
21285
|
+
var app59 = new Hono();
|
|
21286
|
+
app59.post("/", async (c) => {
|
|
21149
21287
|
let body;
|
|
21150
21288
|
try {
|
|
21151
21289
|
body = await c.req.json();
|
|
@@ -21186,7 +21324,7 @@ app58.post("/", async (c) => {
|
|
|
21186
21324
|
let agentConfig = null;
|
|
21187
21325
|
if (account) {
|
|
21188
21326
|
const agentDir = resolve27(account.accountDir, "agents", agentSlug);
|
|
21189
|
-
if (!
|
|
21327
|
+
if (!existsSync32(agentDir) || !existsSync32(resolve27(agentDir, "config.json"))) {
|
|
21190
21328
|
return c.json({ error: "Agent not found" }, 404);
|
|
21191
21329
|
}
|
|
21192
21330
|
agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
|
|
@@ -21292,7 +21430,7 @@ app58.post("/", async (c) => {
|
|
|
21292
21430
|
newVisitorId
|
|
21293
21431
|
);
|
|
21294
21432
|
});
|
|
21295
|
-
var session_default2 =
|
|
21433
|
+
var session_default2 = app59;
|
|
21296
21434
|
|
|
21297
21435
|
// server/lib/calendar-slots.ts
|
|
21298
21436
|
var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
@@ -21375,17 +21513,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
|
|
|
21375
21513
|
}
|
|
21376
21514
|
|
|
21377
21515
|
// server/routes/calendar-public.ts
|
|
21378
|
-
var
|
|
21516
|
+
var app60 = new Hono();
|
|
21379
21517
|
function setCors(c) {
|
|
21380
21518
|
c.header("Access-Control-Allow-Origin", "*");
|
|
21381
21519
|
c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
21382
21520
|
c.header("Access-Control-Allow-Headers", "content-type");
|
|
21383
21521
|
}
|
|
21384
|
-
|
|
21522
|
+
app60.options("/free-busy", (c) => {
|
|
21385
21523
|
setCors(c);
|
|
21386
21524
|
return c.body(null, 204);
|
|
21387
21525
|
});
|
|
21388
|
-
|
|
21526
|
+
app60.get("/free-busy", async (c) => {
|
|
21389
21527
|
setCors(c);
|
|
21390
21528
|
const from = c.req.query("from");
|
|
21391
21529
|
const to = c.req.query("to");
|
|
@@ -21427,10 +21565,10 @@ app59.get("/free-busy", async (c) => {
|
|
|
21427
21565
|
await session.close();
|
|
21428
21566
|
}
|
|
21429
21567
|
});
|
|
21430
|
-
var calendar_public_default =
|
|
21568
|
+
var calendar_public_default = app60;
|
|
21431
21569
|
|
|
21432
21570
|
// app/lib/timeentry-census.ts
|
|
21433
|
-
var
|
|
21571
|
+
var TAG40 = "[timeentry-census]";
|
|
21434
21572
|
function reconcileTimeEntries(rows, now, horizonMs) {
|
|
21435
21573
|
const openEntries = rows.openEntries.length;
|
|
21436
21574
|
let oldestOpenAgeMs = 0;
|
|
@@ -21440,9 +21578,9 @@ function reconcileTimeEntries(rows, now, horizonMs) {
|
|
|
21440
21578
|
perAccount.set(e.accountId, (perAccount.get(e.accountId) ?? 0) + 1);
|
|
21441
21579
|
}
|
|
21442
21580
|
const maxOpenPerAccount = perAccount.size === 0 ? 0 : Math.max(...perAccount.values());
|
|
21443
|
-
const driftTasks = rows.taskSums.filter((t) => t.secondsLogged !== t.sumEntries).length;
|
|
21581
|
+
const driftTasks = rows.taskSums.filter((t) => t.secondsLogged !== t.sumEntries + (t.sumAdjustments ?? 0)).length;
|
|
21444
21582
|
const oldestOpenAgeMin = Math.floor(oldestOpenAgeMs / 6e4);
|
|
21445
|
-
const alarm = oldestOpenAgeMs > horizonMs ||
|
|
21583
|
+
const alarm = oldestOpenAgeMs > horizonMs || driftTasks > 0;
|
|
21446
21584
|
return { openEntries, oldestOpenAgeMin, maxOpenPerAccount, driftTasks, alarm };
|
|
21447
21585
|
}
|
|
21448
21586
|
async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
@@ -21458,20 +21596,24 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
|
|
|
21458
21596
|
const sumRes = await session.run(
|
|
21459
21597
|
`MATCH (t:Task) WHERE t.secondsLogged IS NOT NULL
|
|
21460
21598
|
OPTIONAL MATCH (te:TimeEntry {taskId: t.taskId}) WHERE te.endedAt IS NOT NULL
|
|
21461
|
-
|
|
21599
|
+
WITH t, coalesce(sum(te.seconds), 0) AS sumEntries
|
|
21600
|
+
OPTIONAL MATCH (ta:TimeAdjustment {taskId: t.taskId})
|
|
21601
|
+
RETURN t.taskId AS taskId, coalesce(t.secondsLogged, 0) AS secondsLogged,
|
|
21602
|
+
sumEntries, coalesce(sum(ta.delta), 0) AS sumAdjustments`
|
|
21462
21603
|
);
|
|
21463
21604
|
const taskSums = sumRes.records.map((r) => ({
|
|
21464
21605
|
taskId: r.get("taskId") ?? "",
|
|
21465
21606
|
secondsLogged: toNum(r.get("secondsLogged")),
|
|
21466
|
-
sumEntries: toNum(r.get("sumEntries"))
|
|
21607
|
+
sumEntries: toNum(r.get("sumEntries")),
|
|
21608
|
+
sumAdjustments: toNum(r.get("sumAdjustments"))
|
|
21467
21609
|
}));
|
|
21468
21610
|
const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
|
|
21469
|
-
const line = `${
|
|
21611
|
+
const line = `${TAG40} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
|
|
21470
21612
|
if (finding.alarm) console.error(`${line} alarm=true`);
|
|
21471
21613
|
else console.log(line);
|
|
21472
21614
|
return finding;
|
|
21473
21615
|
} catch (err) {
|
|
21474
|
-
console.error(`${
|
|
21616
|
+
console.error(`${TAG40} error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21475
21617
|
return null;
|
|
21476
21618
|
}
|
|
21477
21619
|
}
|
|
@@ -21485,13 +21627,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
|
|
|
21485
21627
|
try {
|
|
21486
21628
|
session = openSession();
|
|
21487
21629
|
} catch (err) {
|
|
21488
|
-
console.error(`${
|
|
21630
|
+
console.error(`${TAG40} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21489
21631
|
return;
|
|
21490
21632
|
}
|
|
21491
21633
|
try {
|
|
21492
21634
|
await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
|
|
21493
21635
|
} catch (err) {
|
|
21494
|
-
console.error(`${
|
|
21636
|
+
console.error(`${TAG40} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
|
|
21495
21637
|
} finally {
|
|
21496
21638
|
try {
|
|
21497
21639
|
await session.close();
|
|
@@ -21854,13 +21996,13 @@ async function migrateUploads(opts = {}) {
|
|
|
21854
21996
|
|
|
21855
21997
|
// app/lib/migrate-admin-webchat-sidecars.ts
|
|
21856
21998
|
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
|
|
21999
|
+
import { existsSync as existsSync33 } from "fs";
|
|
22000
|
+
import { join as join34 } from "path";
|
|
21859
22001
|
var ADMIN_ROLE2 = "admin";
|
|
21860
22002
|
var WEBCHAT_CHANNEL2 = "webchat";
|
|
21861
22003
|
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;
|
|
21862
|
-
var defaultResolveName = async (
|
|
21863
|
-
const res = await loadAdminUserName(
|
|
22004
|
+
var defaultResolveName = async (_accountId, userId) => {
|
|
22005
|
+
const res = await loadAdminUserName(userId);
|
|
21864
22006
|
return res.source === "neo4j" && res.joined.length > 0 ? res.joined : null;
|
|
21865
22007
|
};
|
|
21866
22008
|
async function readRaw2(path2) {
|
|
@@ -21884,7 +22026,7 @@ async function writeRaw(path2, obj) {
|
|
|
21884
22026
|
await rename3(tmp, path2);
|
|
21885
22027
|
} catch (err) {
|
|
21886
22028
|
try {
|
|
21887
|
-
if (
|
|
22029
|
+
if (existsSync33(tmp)) await unlink3(tmp);
|
|
21888
22030
|
} catch {
|
|
21889
22031
|
}
|
|
21890
22032
|
throw err;
|
|
@@ -21900,7 +22042,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21900
22042
|
}
|
|
21901
22043
|
for (const slug of slugs) {
|
|
21902
22044
|
if (!slug.isDirectory()) continue;
|
|
21903
|
-
const slugDir =
|
|
22045
|
+
const slugDir = join34(projectsRoot, slug.name);
|
|
21904
22046
|
let entries;
|
|
21905
22047
|
try {
|
|
21906
22048
|
entries = await readdir6(slugDir, { withFileTypes: true });
|
|
@@ -21909,9 +22051,9 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21909
22051
|
}
|
|
21910
22052
|
for (const entry of entries) {
|
|
21911
22053
|
if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
|
|
21912
|
-
out.push(
|
|
22054
|
+
out.push(join34(slugDir, entry.name));
|
|
21913
22055
|
} else if (entry.isDirectory() && entry.name === "subagents") {
|
|
21914
|
-
const subDir =
|
|
22056
|
+
const subDir = join34(slugDir, entry.name);
|
|
21915
22057
|
let subs;
|
|
21916
22058
|
try {
|
|
21917
22059
|
subs = await readdir6(subDir, { withFileTypes: true });
|
|
@@ -21919,7 +22061,7 @@ async function collectLiveSidecars(projectsRoot) {
|
|
|
21919
22061
|
continue;
|
|
21920
22062
|
}
|
|
21921
22063
|
for (const s of subs) {
|
|
21922
|
-
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(
|
|
22064
|
+
if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join34(subDir, s.name));
|
|
21923
22065
|
}
|
|
21924
22066
|
}
|
|
21925
22067
|
}
|
|
@@ -21931,7 +22073,7 @@ function shortId(path2) {
|
|
|
21931
22073
|
return base.slice(0, 8);
|
|
21932
22074
|
}
|
|
21933
22075
|
async function migrateAdminWebchatSidecars(opts = {}) {
|
|
21934
|
-
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ?
|
|
22076
|
+
const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join34(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
|
|
21935
22077
|
const usersFile = opts.usersFile ?? USERS_FILE;
|
|
21936
22078
|
const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
|
|
21937
22079
|
const resolveName = opts.resolveName ?? defaultResolveName;
|
|
@@ -22276,8 +22418,8 @@ var streamSSE = (c, cb, onError) => {
|
|
|
22276
22418
|
|
|
22277
22419
|
// app/lib/whatsapp/gateway/routes.ts
|
|
22278
22420
|
function createWaChannelRoutes(deps) {
|
|
22279
|
-
const
|
|
22280
|
-
|
|
22421
|
+
const app62 = new Hono();
|
|
22422
|
+
app62.get("/wa-channel/inbound", (c) => {
|
|
22281
22423
|
const senderId = c.req.query("senderId");
|
|
22282
22424
|
if (!senderId) return c.json({ error: "senderId required" }, 400);
|
|
22283
22425
|
return streamSSE(c, async (stream2) => {
|
|
@@ -22295,7 +22437,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22295
22437
|
}
|
|
22296
22438
|
});
|
|
22297
22439
|
});
|
|
22298
|
-
|
|
22440
|
+
app62.post("/wa-channel/reply", async (c) => {
|
|
22299
22441
|
const body = await c.req.json().catch(() => null);
|
|
22300
22442
|
const senderId = body?.senderId;
|
|
22301
22443
|
const text = body?.text;
|
|
@@ -22316,7 +22458,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22316
22458
|
console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
|
|
22317
22459
|
return c.json({ ok: true });
|
|
22318
22460
|
});
|
|
22319
|
-
|
|
22461
|
+
app62.post("/wa-channel/reply-document", async (c) => {
|
|
22320
22462
|
const body = await c.req.json().catch(() => null);
|
|
22321
22463
|
const senderId = body?.senderId;
|
|
22322
22464
|
const files = body?.files;
|
|
@@ -22355,7 +22497,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22355
22497
|
}
|
|
22356
22498
|
return c.json({ ok: true, results });
|
|
22357
22499
|
});
|
|
22358
|
-
|
|
22500
|
+
app62.post("/wa-channel/ready", async (c) => {
|
|
22359
22501
|
const body = await c.req.json().catch(() => null);
|
|
22360
22502
|
const senderId = body?.senderId;
|
|
22361
22503
|
if (typeof senderId !== "string") {
|
|
@@ -22364,7 +22506,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22364
22506
|
deps.onReady?.(senderId);
|
|
22365
22507
|
return c.json({ ok: true });
|
|
22366
22508
|
});
|
|
22367
|
-
|
|
22509
|
+
app62.post("/wa-channel/received", async (c) => {
|
|
22368
22510
|
const body = await c.req.json().catch(() => null);
|
|
22369
22511
|
const senderId = body?.senderId;
|
|
22370
22512
|
const waMessageId = body?.waMessageId;
|
|
@@ -22374,7 +22516,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22374
22516
|
deps.onReceived?.(senderId, waMessageId);
|
|
22375
22517
|
return c.json({ ok: true });
|
|
22376
22518
|
});
|
|
22377
|
-
|
|
22519
|
+
app62.post("/wa-channel/turn-end", async (c) => {
|
|
22378
22520
|
const body = await c.req.json().catch(() => null);
|
|
22379
22521
|
const senderId = body?.senderId;
|
|
22380
22522
|
const sessionId = body?.sessionId;
|
|
@@ -22407,7 +22549,7 @@ function createWaChannelRoutes(deps) {
|
|
|
22407
22549
|
console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
|
|
22408
22550
|
return c.json({ ok: true, delivered: "none" });
|
|
22409
22551
|
});
|
|
22410
|
-
return
|
|
22552
|
+
return app62;
|
|
22411
22553
|
}
|
|
22412
22554
|
|
|
22413
22555
|
// app/lib/whatsapp/gateway/wa-gateway.ts
|
|
@@ -22499,10 +22641,12 @@ var WaGateway = class {
|
|
|
22499
22641
|
this.docContexts.set(input.senderId, { accountId: input.accountId, maxyAccountId: input.effectiveAccountId });
|
|
22500
22642
|
let standingRules;
|
|
22501
22643
|
if (this.deps.fetchStandingRules) {
|
|
22502
|
-
|
|
22503
|
-
|
|
22644
|
+
const res = await this.deps.fetchStandingRules(input.effectiveAccountId);
|
|
22645
|
+
standingRules = res.block || void 0;
|
|
22646
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
22647
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
22504
22648
|
console.error(
|
|
22505
|
-
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} capped=${injected >= import_dist5.INJECTION_RULE_CAP}`
|
|
22649
|
+
`[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist5.INJECTION_RULE_CAP}`
|
|
22506
22650
|
);
|
|
22507
22651
|
}
|
|
22508
22652
|
this.hub.deliver(
|
|
@@ -22748,8 +22892,8 @@ var import_dist6 = __toESM(require_dist(), 1);
|
|
|
22748
22892
|
|
|
22749
22893
|
// app/lib/webchat/gateway/routes.ts
|
|
22750
22894
|
function createWebchatChannelRoutes(deps) {
|
|
22751
|
-
const
|
|
22752
|
-
|
|
22895
|
+
const app62 = new Hono();
|
|
22896
|
+
app62.get("/webchat-channel/inbound", (c) => {
|
|
22753
22897
|
const key = c.req.query("key");
|
|
22754
22898
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
22755
22899
|
return streamSSE(c, async (stream2) => {
|
|
@@ -22767,7 +22911,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22767
22911
|
}
|
|
22768
22912
|
});
|
|
22769
22913
|
});
|
|
22770
|
-
|
|
22914
|
+
app62.post("/webchat-channel/reply", async (c) => {
|
|
22771
22915
|
const body = await c.req.json().catch(() => null);
|
|
22772
22916
|
const key = body?.key;
|
|
22773
22917
|
const text = body?.text;
|
|
@@ -22777,7 +22921,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22777
22921
|
deps.onReply?.(key, text);
|
|
22778
22922
|
return c.json({ ok: true });
|
|
22779
22923
|
});
|
|
22780
|
-
|
|
22924
|
+
app62.post("/webchat-channel/connector-auth", async (c) => {
|
|
22781
22925
|
const body = await c.req.json().catch(() => null);
|
|
22782
22926
|
const key = body?.key;
|
|
22783
22927
|
const sessionId = body?.sessionId;
|
|
@@ -22790,7 +22934,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22790
22934
|
const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
|
|
22791
22935
|
return c.json(result);
|
|
22792
22936
|
});
|
|
22793
|
-
|
|
22937
|
+
app62.post("/webchat-channel/ready", async (c) => {
|
|
22794
22938
|
const body = await c.req.json().catch(() => null);
|
|
22795
22939
|
const key = body?.key;
|
|
22796
22940
|
if (typeof key !== "string") {
|
|
@@ -22799,7 +22943,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22799
22943
|
deps.onReady?.(key);
|
|
22800
22944
|
return c.json({ ok: true });
|
|
22801
22945
|
});
|
|
22802
|
-
|
|
22946
|
+
app62.post("/webchat-channel/permission-request", async (c) => {
|
|
22803
22947
|
const body = await c.req.json().catch(() => null);
|
|
22804
22948
|
const key = body?.key;
|
|
22805
22949
|
const requestId = body?.request_id;
|
|
@@ -22813,7 +22957,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22813
22957
|
const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
|
|
22814
22958
|
return c.json(verdict);
|
|
22815
22959
|
});
|
|
22816
|
-
|
|
22960
|
+
app62.post("/webchat-channel/received", async (c) => {
|
|
22817
22961
|
const body = await c.req.json().catch(() => null);
|
|
22818
22962
|
const key = body?.key;
|
|
22819
22963
|
const messageId = body?.messageId;
|
|
@@ -22823,7 +22967,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22823
22967
|
deps.onReceived?.(key, messageId);
|
|
22824
22968
|
return c.json({ ok: true });
|
|
22825
22969
|
});
|
|
22826
|
-
|
|
22970
|
+
app62.post("/webchat-channel/turn-end", async (c) => {
|
|
22827
22971
|
const body = await c.req.json().catch(() => null);
|
|
22828
22972
|
const key = body?.key;
|
|
22829
22973
|
const sessionId = body?.sessionId;
|
|
@@ -22846,7 +22990,7 @@ function createWebchatChannelRoutes(deps) {
|
|
|
22846
22990
|
console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} delivered=none`);
|
|
22847
22991
|
return c.json({ ok: true, delivered: "none" });
|
|
22848
22992
|
});
|
|
22849
|
-
return
|
|
22993
|
+
return app62;
|
|
22850
22994
|
}
|
|
22851
22995
|
|
|
22852
22996
|
// app/lib/webchat/gateway/webchat-gateway.ts
|
|
@@ -23185,10 +23329,12 @@ var WebchatGateway = class _WebchatGateway {
|
|
|
23185
23329
|
const willDeliverNow = this.hub.isReady(input.key);
|
|
23186
23330
|
let standingRules;
|
|
23187
23331
|
if (input.role === "admin" && this.deps.fetchStandingRules) {
|
|
23188
|
-
|
|
23189
|
-
|
|
23332
|
+
const res = await this.deps.fetchStandingRules(input.accountId);
|
|
23333
|
+
standingRules = res.block || void 0;
|
|
23334
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
23335
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
23190
23336
|
console.error(
|
|
23191
|
-
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
|
|
23337
|
+
`[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
|
|
23192
23338
|
);
|
|
23193
23339
|
}
|
|
23194
23340
|
this.hub.deliver(
|
|
@@ -23477,7 +23623,7 @@ function makeFileDelivery(opts) {
|
|
|
23477
23623
|
}
|
|
23478
23624
|
|
|
23479
23625
|
// app/lib/whatsapp/inbound/file-delivery-bridge.ts
|
|
23480
|
-
var
|
|
23626
|
+
var TAG41 = "[whatsapp-adaptor]";
|
|
23481
23627
|
var SEND_USER_FILE2 = "SendUserFile";
|
|
23482
23628
|
var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
|
|
23483
23629
|
function platformRoot() {
|
|
@@ -23495,7 +23641,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
23495
23641
|
});
|
|
23496
23642
|
if (result.ok) return { ok: true };
|
|
23497
23643
|
console.error(
|
|
23498
|
-
`${
|
|
23644
|
+
`${TAG41} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
|
|
23499
23645
|
);
|
|
23500
23646
|
return { ok: false, error: result.error };
|
|
23501
23647
|
};
|
|
@@ -23503,7 +23649,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
|
|
|
23503
23649
|
function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
23504
23650
|
const shared = makeFileDelivery({
|
|
23505
23651
|
entry,
|
|
23506
|
-
tag:
|
|
23652
|
+
tag: TAG41,
|
|
23507
23653
|
channel: "whatsapp",
|
|
23508
23654
|
sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
|
|
23509
23655
|
});
|
|
@@ -23538,7 +23684,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
|
|
|
23538
23684
|
if (!delivered) {
|
|
23539
23685
|
const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
|
|
23540
23686
|
console.error(
|
|
23541
|
-
`${
|
|
23687
|
+
`${TAG41} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
|
|
23542
23688
|
);
|
|
23543
23689
|
}
|
|
23544
23690
|
}
|
|
@@ -23715,8 +23861,8 @@ var import_dist7 = __toESM(require_dist(), 1);
|
|
|
23715
23861
|
|
|
23716
23862
|
// app/lib/telegram/gateway/routes.ts
|
|
23717
23863
|
function createTelegramChannelRoutes(deps) {
|
|
23718
|
-
const
|
|
23719
|
-
|
|
23864
|
+
const app62 = new Hono();
|
|
23865
|
+
app62.get("/tg-channel/inbound", (c) => {
|
|
23720
23866
|
const key = c.req.query("key");
|
|
23721
23867
|
if (!key) return c.json({ error: "key required" }, 400);
|
|
23722
23868
|
return streamSSE(c, async (stream2) => {
|
|
@@ -23734,7 +23880,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23734
23880
|
}
|
|
23735
23881
|
});
|
|
23736
23882
|
});
|
|
23737
|
-
|
|
23883
|
+
app62.post("/tg-channel/reply", async (c) => {
|
|
23738
23884
|
const body = await c.req.json().catch(() => null);
|
|
23739
23885
|
const key = body?.key;
|
|
23740
23886
|
const text = body?.text;
|
|
@@ -23750,7 +23896,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23750
23896
|
console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
|
|
23751
23897
|
return c.json({ ok: true });
|
|
23752
23898
|
});
|
|
23753
|
-
|
|
23899
|
+
app62.post("/tg-channel/ready", async (c) => {
|
|
23754
23900
|
const body = await c.req.json().catch(() => null);
|
|
23755
23901
|
const key = body?.key;
|
|
23756
23902
|
if (typeof key !== "string") {
|
|
@@ -23759,7 +23905,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23759
23905
|
deps.onReady?.(key);
|
|
23760
23906
|
return c.json({ ok: true });
|
|
23761
23907
|
});
|
|
23762
|
-
|
|
23908
|
+
app62.post("/tg-channel/received", async (c) => {
|
|
23763
23909
|
const body = await c.req.json().catch(() => null);
|
|
23764
23910
|
const key = body?.key;
|
|
23765
23911
|
const messageId = body?.messageId;
|
|
@@ -23769,7 +23915,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23769
23915
|
deps.onReceived?.(key, messageId);
|
|
23770
23916
|
return c.json({ ok: true });
|
|
23771
23917
|
});
|
|
23772
|
-
|
|
23918
|
+
app62.post("/tg-channel/turn-end", async (c) => {
|
|
23773
23919
|
const body = await c.req.json().catch(() => null);
|
|
23774
23920
|
const key = body?.key;
|
|
23775
23921
|
const sessionId = body?.sessionId;
|
|
@@ -23802,7 +23948,7 @@ function createTelegramChannelRoutes(deps) {
|
|
|
23802
23948
|
console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
|
|
23803
23949
|
return c.json({ ok: true, delivered: "none" });
|
|
23804
23950
|
});
|
|
23805
|
-
return
|
|
23951
|
+
return app62;
|
|
23806
23952
|
}
|
|
23807
23953
|
|
|
23808
23954
|
// app/lib/telegram/gateway/telegram-gateway.ts
|
|
@@ -23862,10 +24008,12 @@ var TelegramGateway = class {
|
|
|
23862
24008
|
this.replies.set(input.senderId, input.reply);
|
|
23863
24009
|
let standingRules;
|
|
23864
24010
|
if (input.role === "admin" && this.deps.fetchStandingRules) {
|
|
23865
|
-
|
|
23866
|
-
|
|
24011
|
+
const res = await this.deps.fetchStandingRules(input.accountId);
|
|
24012
|
+
standingRules = res.block || void 0;
|
|
24013
|
+
const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
|
|
24014
|
+
const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
|
|
23867
24015
|
console.error(
|
|
23868
|
-
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
|
|
24016
|
+
`[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
|
|
23869
24017
|
);
|
|
23870
24018
|
}
|
|
23871
24019
|
this.hub.deliver(
|
|
@@ -23929,8 +24077,8 @@ function buildTelegramSpawnRequest(input) {
|
|
|
23929
24077
|
// app/lib/telegram/outbound/send-document.ts
|
|
23930
24078
|
import { realpathSync as realpathSync7 } from "fs";
|
|
23931
24079
|
import { readFile as readFile7, stat as stat7 } from "fs/promises";
|
|
23932
|
-
import { resolve as resolve30, basename as
|
|
23933
|
-
var
|
|
24080
|
+
import { resolve as resolve30, basename as basename11 } from "path";
|
|
24081
|
+
var TAG42 = "[telegram:outbound]";
|
|
23934
24082
|
var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
|
|
23935
24083
|
async function sendTelegramDocument(input) {
|
|
23936
24084
|
const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot3 } = input;
|
|
@@ -23946,16 +24094,16 @@ async function sendTelegramDocument(input) {
|
|
|
23946
24094
|
resolvedPath = realpathSync7(filePath);
|
|
23947
24095
|
const accountResolved = realpathSync7(accountDir);
|
|
23948
24096
|
if (!resolvedPath.startsWith(accountResolved + "/")) {
|
|
23949
|
-
console.error(`${
|
|
24097
|
+
console.error(`${TAG42} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
|
|
23950
24098
|
return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
|
|
23951
24099
|
}
|
|
23952
24100
|
} catch (err) {
|
|
23953
24101
|
const code = err.code;
|
|
23954
24102
|
if (code === "ENOENT") {
|
|
23955
|
-
console.error(`${
|
|
24103
|
+
console.error(`${TAG42} document ENOENT path=${filePath}`);
|
|
23956
24104
|
return { ok: false, status: 404, error: `File not found: ${filePath}` };
|
|
23957
24105
|
}
|
|
23958
|
-
console.error(`${
|
|
24106
|
+
console.error(`${TAG42} document path error: ${String(err)}`);
|
|
23959
24107
|
return { ok: false, status: 500, error: String(err) };
|
|
23960
24108
|
}
|
|
23961
24109
|
const fileStat = await stat7(resolvedPath);
|
|
@@ -23966,7 +24114,7 @@ async function sendTelegramDocument(input) {
|
|
|
23966
24114
|
error: `File exceeds 50 MB limit (${(fileStat.size / 1024 / 1024).toFixed(1)} MB)`
|
|
23967
24115
|
};
|
|
23968
24116
|
}
|
|
23969
|
-
const filename =
|
|
24117
|
+
const filename = basename11(resolvedPath);
|
|
23970
24118
|
const buffer = Buffer.from(await readFile7(resolvedPath));
|
|
23971
24119
|
const form = new FormData();
|
|
23972
24120
|
form.append("chat_id", String(chatId));
|
|
@@ -23988,13 +24136,13 @@ async function sendTelegramDocument(input) {
|
|
|
23988
24136
|
error = e instanceof Error ? e.message : String(e);
|
|
23989
24137
|
}
|
|
23990
24138
|
console.error(
|
|
23991
|
-
`${
|
|
24139
|
+
`${TAG42} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
|
|
23992
24140
|
);
|
|
23993
24141
|
return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
|
|
23994
24142
|
}
|
|
23995
24143
|
|
|
23996
24144
|
// app/lib/telegram/outbound/file-delivery.ts
|
|
23997
|
-
var
|
|
24145
|
+
var TAG43 = "[telegram:outbound]";
|
|
23998
24146
|
function platformRoot2() {
|
|
23999
24147
|
return process.env.MAXY_PLATFORM_ROOT || "";
|
|
24000
24148
|
}
|
|
@@ -24006,11 +24154,11 @@ function makeTelegramSendFile(entry) {
|
|
|
24006
24154
|
botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
|
|
24007
24155
|
}
|
|
24008
24156
|
if (!botToken) {
|
|
24009
|
-
console.error(`${
|
|
24157
|
+
console.error(`${TAG43} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
|
|
24010
24158
|
return { ok: false, error: "no-bot-token" };
|
|
24011
24159
|
}
|
|
24012
24160
|
if (entry.replyTarget == null) {
|
|
24013
|
-
console.error(`${
|
|
24161
|
+
console.error(`${TAG43} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
|
|
24014
24162
|
return { ok: false, error: "no-reply-target" };
|
|
24015
24163
|
}
|
|
24016
24164
|
const result = await sendTelegramDocument({
|
|
@@ -24027,7 +24175,7 @@ function makeTelegramSendFile(entry) {
|
|
|
24027
24175
|
function makeTelegramFileDelivery(entry) {
|
|
24028
24176
|
return makeFileDelivery({
|
|
24029
24177
|
entry,
|
|
24030
|
-
tag:
|
|
24178
|
+
tag: TAG43,
|
|
24031
24179
|
channel: "telegram",
|
|
24032
24180
|
sendFile: makeTelegramSendFile(entry)
|
|
24033
24181
|
});
|
|
@@ -24067,17 +24215,17 @@ function startTelegramNativeFileFollower(input) {
|
|
|
24067
24215
|
}
|
|
24068
24216
|
|
|
24069
24217
|
// server/telegram-descriptor.ts
|
|
24070
|
-
import { resolve as resolve31, join as
|
|
24218
|
+
import { resolve as resolve31, join as join35 } from "path";
|
|
24071
24219
|
function telegramGatewayUrl() {
|
|
24072
24220
|
return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
|
|
24073
24221
|
}
|
|
24074
24222
|
function telegramServerPath() {
|
|
24075
|
-
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ??
|
|
24223
|
+
return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve31(process.env.MAXY_PLATFORM_ROOT ?? join35(__dirname, ".."), "services/telegram-channel/dist/server.js");
|
|
24076
24224
|
}
|
|
24077
24225
|
|
|
24078
24226
|
// app/lib/channel-pty-bridge/public-session-end-review.ts
|
|
24079
|
-
import { randomUUID as
|
|
24080
|
-
var
|
|
24227
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
24228
|
+
var TAG44 = "[public-session-review]";
|
|
24081
24229
|
var CONSUMED_CAP = 500;
|
|
24082
24230
|
var consumed = /* @__PURE__ */ new Set();
|
|
24083
24231
|
function consumeOnce(sessionId) {
|
|
@@ -24104,7 +24252,7 @@ async function fetchJsonl(sessionId) {
|
|
|
24104
24252
|
return await res.text();
|
|
24105
24253
|
} catch (err) {
|
|
24106
24254
|
console.error(
|
|
24107
|
-
`${
|
|
24255
|
+
`${TAG44} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
|
|
24108
24256
|
);
|
|
24109
24257
|
return null;
|
|
24110
24258
|
}
|
|
@@ -24128,7 +24276,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
24128
24276
|
const res = await fetch(url);
|
|
24129
24277
|
if (!res.ok) {
|
|
24130
24278
|
console.error(
|
|
24131
|
-
`${
|
|
24279
|
+
`${TAG44} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
|
|
24132
24280
|
);
|
|
24133
24281
|
return [];
|
|
24134
24282
|
}
|
|
@@ -24136,7 +24284,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
|
|
|
24136
24284
|
return Array.isArray(body.writes) ? body.writes : [];
|
|
24137
24285
|
} catch (err) {
|
|
24138
24286
|
console.error(
|
|
24139
|
-
`${
|
|
24287
|
+
`${TAG44} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
|
|
24140
24288
|
);
|
|
24141
24289
|
return [];
|
|
24142
24290
|
}
|
|
@@ -24164,8 +24312,8 @@ function composeInitialMessage(input) {
|
|
|
24164
24312
|
].join("\n");
|
|
24165
24313
|
}
|
|
24166
24314
|
async function dispatchReviewer(input, initialMessage) {
|
|
24167
|
-
const sessionId =
|
|
24168
|
-
console.log(`${
|
|
24315
|
+
const sessionId = randomUUID15();
|
|
24316
|
+
console.log(`${TAG44} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
|
|
24169
24317
|
const spawned = await managerRcSpawn({
|
|
24170
24318
|
sessionId,
|
|
24171
24319
|
initialMessage,
|
|
@@ -24185,21 +24333,21 @@ async function firePublicSessionEndReview(input) {
|
|
|
24185
24333
|
const dispatchedAt = Date.now();
|
|
24186
24334
|
if (consumed.has(input.sessionId)) {
|
|
24187
24335
|
console.log(
|
|
24188
|
-
`${
|
|
24336
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
24189
24337
|
);
|
|
24190
24338
|
return;
|
|
24191
24339
|
}
|
|
24192
24340
|
const jsonl = await fetchJsonl(input.sessionId);
|
|
24193
24341
|
if (!jsonl) {
|
|
24194
24342
|
console.log(
|
|
24195
|
-
`${
|
|
24343
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
|
|
24196
24344
|
);
|
|
24197
24345
|
return;
|
|
24198
24346
|
}
|
|
24199
24347
|
const operatorTurns = countOperatorTurns(jsonl);
|
|
24200
24348
|
if (operatorTurns === 0) {
|
|
24201
24349
|
console.log(
|
|
24202
|
-
`${
|
|
24350
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
|
|
24203
24351
|
);
|
|
24204
24352
|
return;
|
|
24205
24353
|
}
|
|
@@ -24213,19 +24361,19 @@ async function firePublicSessionEndReview(input) {
|
|
|
24213
24361
|
});
|
|
24214
24362
|
if (!consumeOnce(input.sessionId)) {
|
|
24215
24363
|
console.log(
|
|
24216
|
-
`${
|
|
24364
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
|
|
24217
24365
|
);
|
|
24218
24366
|
return;
|
|
24219
24367
|
}
|
|
24220
24368
|
const dispatched = await dispatchReviewer(input, initialMessage);
|
|
24221
24369
|
if (!dispatched.ok) {
|
|
24222
24370
|
console.error(
|
|
24223
|
-
`${
|
|
24371
|
+
`${TAG44} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
|
|
24224
24372
|
);
|
|
24225
24373
|
return;
|
|
24226
24374
|
}
|
|
24227
24375
|
console.log(
|
|
24228
|
-
`${
|
|
24376
|
+
`${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
24377
|
);
|
|
24230
24378
|
}
|
|
24231
24379
|
|
|
@@ -24334,7 +24482,7 @@ function broadcastAdminShutdown(reason) {
|
|
|
24334
24482
|
|
|
24335
24483
|
// ../lib/entitlement/src/index.ts
|
|
24336
24484
|
import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
|
|
24337
|
-
import { existsSync as
|
|
24485
|
+
import { existsSync as existsSync34, readFileSync as readFileSync34, statSync as statSync13 } from "fs";
|
|
24338
24486
|
import { resolve as resolve32 } from "path";
|
|
24339
24487
|
|
|
24340
24488
|
// ../lib/entitlement/src/canonicalize.ts
|
|
@@ -24383,7 +24531,7 @@ function resolveEntitlement(brand, account) {
|
|
|
24383
24531
|
return logResolved(implicitTrust(account), null);
|
|
24384
24532
|
}
|
|
24385
24533
|
const entitlementPath = resolve32(brand.configDir, "entitlement.json");
|
|
24386
|
-
if (!
|
|
24534
|
+
if (!existsSync34(entitlementPath)) {
|
|
24387
24535
|
return logResolved(anonymousFallback("missing"), { reason: "missing" });
|
|
24388
24536
|
}
|
|
24389
24537
|
const stat8 = statSync13(entitlementPath);
|
|
@@ -24573,12 +24721,12 @@ function clientFrom(c) {
|
|
|
24573
24721
|
);
|
|
24574
24722
|
}
|
|
24575
24723
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
24576
|
-
var BRAND_JSON_PATH = PLATFORM_ROOT8 ?
|
|
24724
|
+
var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join36(PLATFORM_ROOT8, "config", "brand.json") : "";
|
|
24577
24725
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
|
|
24578
|
-
if (BRAND_JSON_PATH && !
|
|
24726
|
+
if (BRAND_JSON_PATH && !existsSync35(BRAND_JSON_PATH)) {
|
|
24579
24727
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
24580
24728
|
}
|
|
24581
|
-
if (BRAND_JSON_PATH &&
|
|
24729
|
+
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
24582
24730
|
try {
|
|
24583
24731
|
const parsed = JSON.parse(readFileSync35(BRAND_JSON_PATH, "utf-8"));
|
|
24584
24732
|
BRAND = { ...BRAND, ...parsed };
|
|
@@ -24612,10 +24760,10 @@ var brandLoginOpts = {
|
|
|
24612
24760
|
appleTouchIconPath: brandAppIcon512Path,
|
|
24613
24761
|
themeColor: BRAND.defaultColors?.primary
|
|
24614
24762
|
};
|
|
24615
|
-
var ALIAS_DOMAINS_PATH =
|
|
24763
|
+
var ALIAS_DOMAINS_PATH = join36(homedir4(), BRAND.configDir, "alias-domains.json");
|
|
24616
24764
|
function loadAliasDomains() {
|
|
24617
24765
|
try {
|
|
24618
|
-
if (!
|
|
24766
|
+
if (!existsSync35(ALIAS_DOMAINS_PATH)) return null;
|
|
24619
24767
|
const parsed = JSON.parse(readFileSync35(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
24620
24768
|
if (!Array.isArray(parsed)) {
|
|
24621
24769
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
@@ -24640,18 +24788,18 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
|
|
|
24640
24788
|
function isPublicHost(host) {
|
|
24641
24789
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
24642
24790
|
}
|
|
24643
|
-
var
|
|
24791
|
+
var app61 = new Hono();
|
|
24644
24792
|
var nativeFileFollowers = /* @__PURE__ */ new Map();
|
|
24645
24793
|
async function fetchAccountStandingRules(accountId) {
|
|
24646
24794
|
const session = getSession();
|
|
24647
24795
|
try {
|
|
24648
|
-
const
|
|
24649
|
-
return (0, import_dist8.formatStandingRulesBlock)(rules);
|
|
24796
|
+
const res = await (0, import_dist8.resolveActiveRules)(session, accountId);
|
|
24797
|
+
return { block: (0, import_dist8.formatStandingRulesBlock)(res.rules), ownerUserId: res.ownerUserId, source: res.source };
|
|
24650
24798
|
} catch (err) {
|
|
24651
24799
|
console.error(
|
|
24652
24800
|
`[preference-inject] op=fetch-failed accountId=${accountId} error=${err instanceof Error ? err.message : String(err)}`
|
|
24653
24801
|
);
|
|
24654
|
-
return "";
|
|
24802
|
+
return { block: "", ownerUserId: null, source: "fetch-error" };
|
|
24655
24803
|
} finally {
|
|
24656
24804
|
await session.close();
|
|
24657
24805
|
}
|
|
@@ -24679,7 +24827,7 @@ async function recordPassiveDispatch(input) {
|
|
|
24679
24827
|
var waGateway = new WaGateway({
|
|
24680
24828
|
fetchStandingRules: fetchAccountStandingRules,
|
|
24681
24829
|
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 ??
|
|
24830
|
+
serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
|
|
24683
24831
|
// Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
|
|
24684
24832
|
// path-validation scope) is the sender's effective SESSION account, resolved
|
|
24685
24833
|
// once at the inbound gate and threaded here via the gateway's per-sender doc
|
|
@@ -24694,7 +24842,7 @@ var waGateway = new WaGateway({
|
|
|
24694
24842
|
caption,
|
|
24695
24843
|
accountId,
|
|
24696
24844
|
maxyAccountId,
|
|
24697
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
24845
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, ".."))
|
|
24698
24846
|
});
|
|
24699
24847
|
return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
|
|
24700
24848
|
},
|
|
@@ -24775,7 +24923,7 @@ var waGateway = new WaGateway({
|
|
|
24775
24923
|
nativeFileFollowers.set(senderId, ac);
|
|
24776
24924
|
}
|
|
24777
24925
|
});
|
|
24778
|
-
|
|
24926
|
+
app61.route("/", waGateway.routes());
|
|
24779
24927
|
waGateway.startSweeper();
|
|
24780
24928
|
var webchatGateway = new WebchatGateway({
|
|
24781
24929
|
fetchStandingRules: fetchAccountStandingRules,
|
|
@@ -24859,7 +25007,7 @@ var webchatGateway = new WebchatGateway({
|
|
|
24859
25007
|
firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
|
|
24860
25008
|
});
|
|
24861
25009
|
setWebchatGateway(webchatGateway);
|
|
24862
|
-
|
|
25010
|
+
app61.route("/", webchatGateway.routes());
|
|
24863
25011
|
webchatGateway.startSweeper();
|
|
24864
25012
|
webchatGateway.startPublicReaper();
|
|
24865
25013
|
var telegramFileFollowers = /* @__PURE__ */ new Map();
|
|
@@ -24893,7 +25041,7 @@ var telegramGateway = new TelegramGateway({
|
|
|
24893
25041
|
}
|
|
24894
25042
|
});
|
|
24895
25043
|
setTelegramGateway(telegramGateway);
|
|
24896
|
-
|
|
25044
|
+
app61.route("/", telegramGateway.routes());
|
|
24897
25045
|
telegramGateway.startSweeper();
|
|
24898
25046
|
var chatRoutes = createChatRoutes({
|
|
24899
25047
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
@@ -24926,19 +25074,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
|
|
|
24926
25074
|
return managed.account;
|
|
24927
25075
|
}
|
|
24928
25076
|
});
|
|
24929
|
-
|
|
24930
|
-
|
|
25077
|
+
app61.route("/api/channel/schedule-inject", scheduleInjectRoutes);
|
|
25078
|
+
app61.use("*", clientIpMiddleware);
|
|
24931
25079
|
function allowsSameOriginFraming(path2) {
|
|
24932
25080
|
return path2 === "/vnc-viewer.html" || path2.startsWith("/api/admin/attachment/") || path2.startsWith("/api/public-reader/attachment/") || path2 === "/api/admin/files/download";
|
|
24933
25081
|
}
|
|
24934
|
-
|
|
25082
|
+
app61.use("*", async (c, next) => {
|
|
24935
25083
|
await next();
|
|
24936
25084
|
c.header("X-Content-Type-Options", "nosniff");
|
|
24937
25085
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
24938
25086
|
c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
|
|
24939
25087
|
});
|
|
24940
25088
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
24941
|
-
|
|
25089
|
+
app61.use("*", async (c, next) => {
|
|
24942
25090
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
24943
25091
|
await next();
|
|
24944
25092
|
return;
|
|
@@ -24956,7 +25104,7 @@ app60.use("*", async (c, next) => {
|
|
|
24956
25104
|
});
|
|
24957
25105
|
}
|
|
24958
25106
|
});
|
|
24959
|
-
|
|
25107
|
+
app61.use("*", async (c, next) => {
|
|
24960
25108
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
24961
25109
|
if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
|
|
24962
25110
|
await next();
|
|
@@ -24994,7 +25142,7 @@ function resolveRemoteAuthOpts(c) {
|
|
|
24994
25142
|
return { ...brandLoginOpts, origin };
|
|
24995
25143
|
}
|
|
24996
25144
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
24997
|
-
|
|
25145
|
+
app61.post("/__remote-auth/login", async (c) => {
|
|
24998
25146
|
const client = clientFrom(c);
|
|
24999
25147
|
const clientIp = client.ip || "unknown";
|
|
25000
25148
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -25039,7 +25187,7 @@ app60.post("/__remote-auth/login", async (c) => {
|
|
|
25039
25187
|
}
|
|
25040
25188
|
});
|
|
25041
25189
|
});
|
|
25042
|
-
|
|
25190
|
+
app61.get("/__remote-auth/logout", (c) => {
|
|
25043
25191
|
const client = clientFrom(c);
|
|
25044
25192
|
const clientIp = client.ip || "unknown";
|
|
25045
25193
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -25052,7 +25200,7 @@ app60.get("/__remote-auth/logout", (c) => {
|
|
|
25052
25200
|
}
|
|
25053
25201
|
});
|
|
25054
25202
|
});
|
|
25055
|
-
|
|
25203
|
+
app61.post("/__remote-auth/change-password", async (c) => {
|
|
25056
25204
|
const client = clientFrom(c);
|
|
25057
25205
|
const clientIp = client.ip || "unknown";
|
|
25058
25206
|
const rateLimited = checkRateLimit(client);
|
|
@@ -25111,13 +25259,13 @@ app60.post("/__remote-auth/change-password", async (c) => {
|
|
|
25111
25259
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
25112
25260
|
}
|
|
25113
25261
|
});
|
|
25114
|
-
|
|
25262
|
+
app61.get("/__remote-auth/setup", (c) => {
|
|
25115
25263
|
if (isRemoteAuthConfigured()) {
|
|
25116
25264
|
return c.redirect("/");
|
|
25117
25265
|
}
|
|
25118
25266
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
|
|
25119
25267
|
});
|
|
25120
|
-
|
|
25268
|
+
app61.post("/__remote-auth/set-initial-password", async (c) => {
|
|
25121
25269
|
if (isRemoteAuthConfigured()) {
|
|
25122
25270
|
return c.redirect("/");
|
|
25123
25271
|
}
|
|
@@ -25155,10 +25303,10 @@ app60.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
25155
25303
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
25156
25304
|
}
|
|
25157
25305
|
});
|
|
25158
|
-
|
|
25306
|
+
app61.get("/api/remote-auth/status", (c) => {
|
|
25159
25307
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
25160
25308
|
});
|
|
25161
|
-
|
|
25309
|
+
app61.post("/api/remote-auth/set-password", async (c) => {
|
|
25162
25310
|
let body;
|
|
25163
25311
|
try {
|
|
25164
25312
|
body = await c.req.json();
|
|
@@ -25197,10 +25345,10 @@ app60.post("/api/remote-auth/set-password", async (c) => {
|
|
|
25197
25345
|
return c.json({ error: "Failed to save password" }, 500);
|
|
25198
25346
|
}
|
|
25199
25347
|
});
|
|
25200
|
-
|
|
25348
|
+
app61.route("/api/_client-error", client_error_default);
|
|
25201
25349
|
console.log("[client-error-route] mounted");
|
|
25202
25350
|
var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
|
|
25203
|
-
|
|
25351
|
+
app61.use("*", async (c, next) => {
|
|
25204
25352
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25205
25353
|
const path2 = c.req.path;
|
|
25206
25354
|
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 +25392,26 @@ app60.use("*", async (c, next) => {
|
|
|
25244
25392
|
}
|
|
25245
25393
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path2 }), 200);
|
|
25246
25394
|
});
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25395
|
+
app61.route("/api/health", health_default);
|
|
25396
|
+
app61.route("/api/chat", chatRoutes);
|
|
25397
|
+
app61.route("/api/whatsapp", whatsapp_default);
|
|
25398
|
+
app61.route("/api/whatsapp-reader", whatsapp_reader_default);
|
|
25399
|
+
app61.route("/api/public-reader", public_reader_default);
|
|
25400
|
+
app61.route("/api/webchat", createWebchatRoutes({
|
|
25253
25401
|
handleInbound: (input) => webchatGateway.handleInbound(input),
|
|
25254
25402
|
// Task 940 — the permission relay's pointer read + verdict write.
|
|
25255
25403
|
pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
|
|
25256
25404
|
deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
|
|
25257
25405
|
resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
|
|
25258
25406
|
}));
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
|
|
25407
|
+
app61.route("/api/webchat/greeting", webchat_greeting_default);
|
|
25408
|
+
app61.route("/api/telegram", telegram_default);
|
|
25409
|
+
app61.route("/api/quickbooks", quickbooks_default);
|
|
25410
|
+
app61.route("/api/onboarding", onboarding_default);
|
|
25411
|
+
app61.route("/api/admin", admin_default);
|
|
25412
|
+
app61.route("/api/access", access_default);
|
|
25413
|
+
app61.route("/api/session", session_default2);
|
|
25414
|
+
app61.route("/api/calendar", calendar_public_default);
|
|
25267
25415
|
var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
|
|
25268
25416
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
25269
25417
|
var IMAGE_MIME = {
|
|
@@ -25275,7 +25423,7 @@ var IMAGE_MIME = {
|
|
|
25275
25423
|
".svg": "image/svg+xml",
|
|
25276
25424
|
".ico": "image/x-icon"
|
|
25277
25425
|
};
|
|
25278
|
-
|
|
25426
|
+
app61.get("/agent-assets/:slug/:filename", (c) => {
|
|
25279
25427
|
const slug = c.req.param("slug");
|
|
25280
25428
|
const filename = c.req.param("filename");
|
|
25281
25429
|
if (!SAFE_SLUG_RE2.test(slug)) {
|
|
@@ -25297,7 +25445,7 @@ app60.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25297
25445
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
25298
25446
|
return c.text("Forbidden", 403);
|
|
25299
25447
|
}
|
|
25300
|
-
if (!
|
|
25448
|
+
if (!existsSync35(filePath)) {
|
|
25301
25449
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
25302
25450
|
return c.text("Not found", 404);
|
|
25303
25451
|
}
|
|
@@ -25310,7 +25458,7 @@ app60.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
25310
25458
|
"Cache-Control": "public, max-age=3600"
|
|
25311
25459
|
});
|
|
25312
25460
|
});
|
|
25313
|
-
|
|
25461
|
+
app61.get("/generated/:filename", (c) => {
|
|
25314
25462
|
const filename = c.req.param("filename");
|
|
25315
25463
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
25316
25464
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -25327,7 +25475,7 @@ app60.get("/generated/:filename", (c) => {
|
|
|
25327
25475
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
25328
25476
|
return c.text("Forbidden", 403);
|
|
25329
25477
|
}
|
|
25330
|
-
if (!
|
|
25478
|
+
if (!existsSync35(filePath)) {
|
|
25331
25479
|
console.error(`[generated] serve file=${filename} status=404`);
|
|
25332
25480
|
return c.text("Not found", 404);
|
|
25333
25481
|
}
|
|
@@ -25340,14 +25488,14 @@ app60.get("/generated/:filename", (c) => {
|
|
|
25340
25488
|
"Cache-Control": "public, max-age=86400"
|
|
25341
25489
|
});
|
|
25342
25490
|
});
|
|
25343
|
-
|
|
25344
|
-
|
|
25345
|
-
|
|
25346
|
-
|
|
25491
|
+
app61.route("/sites", sites_default);
|
|
25492
|
+
app61.route("/listings", listings_default);
|
|
25493
|
+
app61.route("/v", visitor_event_default);
|
|
25494
|
+
app61.route("/v", visitor_consent_default);
|
|
25347
25495
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
25348
25496
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
25349
25497
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
25350
|
-
if (BRAND_JSON_PATH &&
|
|
25498
|
+
if (BRAND_JSON_PATH && existsSync35(BRAND_JSON_PATH)) {
|
|
25351
25499
|
try {
|
|
25352
25500
|
const fullBrand = JSON.parse(readFileSync35(BRAND_JSON_PATH, "utf-8"));
|
|
25353
25501
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
@@ -25376,7 +25524,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
25376
25524
|
var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
|
|
25377
25525
|
var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
|
|
25378
25526
|
var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
|
|
25379
|
-
(p) =>
|
|
25527
|
+
(p) => existsSync35(resolve33(process.cwd(), "public", p.replace(/^\//, "")))
|
|
25380
25528
|
);
|
|
25381
25529
|
var SW_SOURCE = (() => {
|
|
25382
25530
|
try {
|
|
@@ -25388,8 +25536,8 @@ var SW_SOURCE = (() => {
|
|
|
25388
25536
|
function readInstalledVersion() {
|
|
25389
25537
|
try {
|
|
25390
25538
|
if (!PLATFORM_ROOT8) return "unknown";
|
|
25391
|
-
const versionFile =
|
|
25392
|
-
if (!
|
|
25539
|
+
const versionFile = join36(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
|
|
25540
|
+
if (!existsSync35(versionFile)) return "unknown";
|
|
25393
25541
|
const content = readFileSync35(versionFile, "utf-8").trim();
|
|
25394
25542
|
return content || "unknown";
|
|
25395
25543
|
} catch {
|
|
@@ -25448,12 +25596,12 @@ ${clientErrorReporterScript}
|
|
|
25448
25596
|
return html;
|
|
25449
25597
|
}
|
|
25450
25598
|
function loadBrandingCache(agentSlug) {
|
|
25451
|
-
const configDir2 =
|
|
25599
|
+
const configDir2 = join36(homedir4(), BRAND.configDir);
|
|
25452
25600
|
try {
|
|
25453
25601
|
const accountId = getDefaultAccountId();
|
|
25454
25602
|
if (!accountId) return null;
|
|
25455
|
-
const cachePath =
|
|
25456
|
-
if (!
|
|
25603
|
+
const cachePath = join36(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
25604
|
+
if (!existsSync35(cachePath)) return null;
|
|
25457
25605
|
return JSON.parse(readFileSync35(cachePath, "utf-8"));
|
|
25458
25606
|
} catch {
|
|
25459
25607
|
return null;
|
|
@@ -25498,7 +25646,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
25498
25646
|
function agentUnavailableHtml() {
|
|
25499
25647
|
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
25648
|
}
|
|
25501
|
-
|
|
25649
|
+
app61.get("/", (c) => {
|
|
25502
25650
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25503
25651
|
const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
|
|
25504
25652
|
if (klass === "operator") {
|
|
@@ -25520,12 +25668,12 @@ app60.get("/", (c) => {
|
|
|
25520
25668
|
console.log(`[host-class] host=${host} class=admin served=index.html`);
|
|
25521
25669
|
return c.html(cachedHtml("index.html"));
|
|
25522
25670
|
});
|
|
25523
|
-
|
|
25671
|
+
app61.get("/public", (c) => {
|
|
25524
25672
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25525
25673
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25526
25674
|
return c.html(cachedHtml("public.html"));
|
|
25527
25675
|
});
|
|
25528
|
-
|
|
25676
|
+
app61.get("/public-chat", (c) => {
|
|
25529
25677
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25530
25678
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25531
25679
|
return c.html(cachedHtml("public.html"));
|
|
@@ -25544,9 +25692,9 @@ async function logViewerFetch(c, next) {
|
|
|
25544
25692
|
duration_ms: Date.now() - start
|
|
25545
25693
|
});
|
|
25546
25694
|
}
|
|
25547
|
-
|
|
25548
|
-
|
|
25549
|
-
|
|
25695
|
+
app61.use("/vnc-viewer.html", logViewerFetch);
|
|
25696
|
+
app61.use("/vnc-popout.html", logViewerFetch);
|
|
25697
|
+
app61.get("/vnc-popout.html", (c) => {
|
|
25550
25698
|
let html = htmlCache.get("vnc-popout.html");
|
|
25551
25699
|
if (!html) {
|
|
25552
25700
|
html = readFileSync35(resolve33(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -25559,7 +25707,7 @@ app60.get("/vnc-popout.html", (c) => {
|
|
|
25559
25707
|
}
|
|
25560
25708
|
return c.html(html);
|
|
25561
25709
|
});
|
|
25562
|
-
|
|
25710
|
+
app61.post("/api/vnc/client-event", async (c) => {
|
|
25563
25711
|
let body;
|
|
25564
25712
|
try {
|
|
25565
25713
|
body = await c.req.json();
|
|
@@ -25580,11 +25728,11 @@ app60.post("/api/vnc/client-event", async (c) => {
|
|
|
25580
25728
|
});
|
|
25581
25729
|
return c.json({ ok: true });
|
|
25582
25730
|
});
|
|
25583
|
-
|
|
25731
|
+
app61.get("/g/:slug", (c) => {
|
|
25584
25732
|
return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
|
|
25585
25733
|
});
|
|
25586
25734
|
for (const pwa of PWA_SURFACES) {
|
|
25587
|
-
|
|
25735
|
+
app61.get(pwa.manifestPath, (c) => {
|
|
25588
25736
|
const manifest = buildManifest(pwa, {
|
|
25589
25737
|
productName: BRAND.productName,
|
|
25590
25738
|
appIcon192: brandAppIcon192Path,
|
|
@@ -25600,7 +25748,7 @@ for (const pwa of PWA_SURFACES) {
|
|
|
25600
25748
|
return c.body(JSON.stringify(manifest));
|
|
25601
25749
|
});
|
|
25602
25750
|
}
|
|
25603
|
-
|
|
25751
|
+
app61.get("/sw.js", (c) => {
|
|
25604
25752
|
if (SW_SOURCE == null) {
|
|
25605
25753
|
console.error("[pwa] op=sw status=500 reason=sw-source-missing");
|
|
25606
25754
|
return c.text("Service worker unavailable", 500);
|
|
@@ -25609,12 +25757,12 @@ app60.get("/sw.js", (c) => {
|
|
|
25609
25757
|
console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
|
|
25610
25758
|
return c.body(SW_SOURCE);
|
|
25611
25759
|
});
|
|
25612
|
-
|
|
25760
|
+
app61.get("/graph", (c) => {
|
|
25613
25761
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25614
25762
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
25615
25763
|
return c.html(cachedHtml("graph.html"));
|
|
25616
25764
|
});
|
|
25617
|
-
|
|
25765
|
+
app61.get("/chat", (c) => {
|
|
25618
25766
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25619
25767
|
if (isOperatorHost(host, getOperatorDomains())) {
|
|
25620
25768
|
console.log(`[host-class] host=${host} class=operator served=operator.html`);
|
|
@@ -25623,27 +25771,27 @@ app60.get("/chat", (c) => {
|
|
|
25623
25771
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25624
25772
|
return c.html(cachedHtml("chat.html"));
|
|
25625
25773
|
});
|
|
25626
|
-
|
|
25774
|
+
app61.get("/data", (c) => {
|
|
25627
25775
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25628
25776
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25629
25777
|
return c.html(cachedHtml("data.html"));
|
|
25630
25778
|
});
|
|
25631
|
-
|
|
25779
|
+
app61.get("/tasks", (c) => {
|
|
25632
25780
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25633
25781
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25634
25782
|
return c.html(cachedHtml("tasks.html"));
|
|
25635
25783
|
});
|
|
25636
|
-
|
|
25784
|
+
app61.get("/calendar", (c) => {
|
|
25637
25785
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25638
25786
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
25639
25787
|
return c.html(cachedHtml("calendar.html"));
|
|
25640
25788
|
});
|
|
25641
|
-
|
|
25789
|
+
app61.get("/browser", (c) => {
|
|
25642
25790
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25643
25791
|
if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
|
|
25644
25792
|
return c.html(cachedHtml("browser.html"));
|
|
25645
25793
|
});
|
|
25646
|
-
|
|
25794
|
+
app61.get("/:slug", async (c, next) => {
|
|
25647
25795
|
const slug = c.req.param("slug");
|
|
25648
25796
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
25649
25797
|
const account = resolveAccount();
|
|
@@ -25658,13 +25806,13 @@ app60.get("/:slug", async (c, next) => {
|
|
|
25658
25806
|
await next();
|
|
25659
25807
|
});
|
|
25660
25808
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
25661
|
-
|
|
25809
|
+
app61.get("/favicon.ico", (c) => {
|
|
25662
25810
|
c.header("Cache-Control", "public, max-age=300");
|
|
25663
25811
|
return c.redirect(brandFaviconPath, 302);
|
|
25664
25812
|
});
|
|
25665
25813
|
}
|
|
25666
|
-
|
|
25667
|
-
|
|
25814
|
+
app61.use("/*", serveStatic({ root: "./public" }));
|
|
25815
|
+
app61.all("*", (c) => {
|
|
25668
25816
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
25669
25817
|
const path2 = c.req.path;
|
|
25670
25818
|
if (isPublicHost(host)) {
|
|
@@ -25678,14 +25826,14 @@ app60.all("*", (c) => {
|
|
|
25678
25826
|
});
|
|
25679
25827
|
var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
|
|
25680
25828
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
25681
|
-
var httpServer = serve({ fetch:
|
|
25829
|
+
var httpServer = serve({ fetch: app61.fetch, port, hostname });
|
|
25682
25830
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
25683
25831
|
{
|
|
25684
|
-
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
25832
|
+
const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
|
|
25685
25833
|
const reconcileScript = resolve33(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
|
|
25686
25834
|
const RECONCILE_INTERVAL_MS = 12e4;
|
|
25687
25835
|
const runReconcile = () => {
|
|
25688
|
-
if (!
|
|
25836
|
+
if (!existsSync35(reconcileScript)) return;
|
|
25689
25837
|
try {
|
|
25690
25838
|
const child = spawn3(process.execPath, [reconcileScript], {
|
|
25691
25839
|
env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
|
|
@@ -25704,12 +25852,12 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
|
25704
25852
|
}
|
|
25705
25853
|
startTimeEntryCensus(() => getSession());
|
|
25706
25854
|
{
|
|
25707
|
-
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ??
|
|
25855
|
+
const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..");
|
|
25708
25856
|
const auditScript = resolve33(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
|
|
25709
25857
|
const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
|
|
25710
25858
|
const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
|
|
25711
25859
|
const runConnectorAudit = () => {
|
|
25712
|
-
if (!
|
|
25860
|
+
if (!existsSync35(auditScript)) return;
|
|
25713
25861
|
try {
|
|
25714
25862
|
const child = spawn3(process.execPath, [auditScript], {
|
|
25715
25863
|
env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
|
|
@@ -25779,7 +25927,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
25779
25927
|
}
|
|
25780
25928
|
try {
|
|
25781
25929
|
const registered = [];
|
|
25782
|
-
for (const r of
|
|
25930
|
+
for (const r of app61.routes ?? []) {
|
|
25783
25931
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
25784
25932
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
25785
25933
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -25819,7 +25967,7 @@ try {
|
|
|
25819
25967
|
var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
25820
25968
|
async function runAdminUserReconcileTick() {
|
|
25821
25969
|
try {
|
|
25822
|
-
if (!
|
|
25970
|
+
if (!existsSync35(USERS_FILE)) {
|
|
25823
25971
|
console.error("[adminuser-self-heal] skip reason=no-users-file");
|
|
25824
25972
|
return;
|
|
25825
25973
|
}
|
|
@@ -25852,7 +26000,7 @@ var adminUserReconcileTimer = setInterval(() => {
|
|
|
25852
26000
|
if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer.unref();
|
|
25853
26001
|
var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
25854
26002
|
function countUsersRows() {
|
|
25855
|
-
if (!
|
|
26003
|
+
if (!existsSync35(USERS_FILE)) return 0;
|
|
25856
26004
|
const raw = readFileSync35(USERS_FILE, "utf-8").trim();
|
|
25857
26005
|
if (!raw) return 0;
|
|
25858
26006
|
const users = JSON.parse(raw);
|
|
@@ -25909,7 +26057,7 @@ try {
|
|
|
25909
26057
|
} catch (err) {
|
|
25910
26058
|
console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
|
|
25911
26059
|
}
|
|
25912
|
-
var configDirForWhatsApp =
|
|
26060
|
+
var configDirForWhatsApp = basename12(MAXY_DIR) || ".maxy";
|
|
25913
26061
|
var bootAccount = resolveAccount();
|
|
25914
26062
|
if (bootAccount) {
|
|
25915
26063
|
migrateRemovedConfigKeys(bootAccount.accountDir);
|
|
@@ -25973,7 +26121,7 @@ if (bootAccountConfig?.whatsapp) {
|
|
|
25973
26121
|
}
|
|
25974
26122
|
init({
|
|
25975
26123
|
configDir: configDirForWhatsApp,
|
|
25976
|
-
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ??
|
|
26124
|
+
platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..")),
|
|
25977
26125
|
accountConfig: bootAccountConfig,
|
|
25978
26126
|
onMessage: async (msg) => {
|
|
25979
26127
|
if (msg.isOwnerMirror) {
|