@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.
Files changed (251) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/active-rules/dist/index.d.ts +14 -0
  3. package/payload/platform/lib/active-rules/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/active-rules/dist/index.js +56 -9
  5. package/payload/platform/lib/active-rules/dist/index.js.map +1 -1
  6. package/payload/platform/lib/active-rules/src/index.test.ts +106 -0
  7. package/payload/platform/lib/active-rules/src/index.ts +98 -9
  8. package/payload/platform/lib/admin-access-password/__tests__/index.test.ts +31 -0
  9. package/payload/platform/lib/admin-access-password/dist/index.d.ts +8 -0
  10. package/payload/platform/lib/admin-access-password/dist/index.d.ts.map +1 -1
  11. package/payload/platform/lib/admin-access-password/dist/index.js +5 -1
  12. package/payload/platform/lib/admin-access-password/dist/index.js.map +1 -1
  13. package/payload/platform/lib/admin-access-password/src/index.ts +14 -1
  14. package/payload/platform/lib/admins-write/__tests__/index.test.ts +27 -0
  15. package/payload/platform/lib/admins-write/dist/index.d.ts +8 -0
  16. package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -1
  17. package/payload/platform/lib/admins-write/dist/index.js +5 -1
  18. package/payload/platform/lib/admins-write/dist/index.js.map +1 -1
  19. package/payload/platform/lib/admins-write/src/index.ts +14 -1
  20. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  21. package/payload/platform/plugins/admin/PLUGIN.md +4 -2
  22. package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts +23 -0
  23. package/payload/platform/plugins/admin/mcp/dist/credential-identity.d.ts.map +1 -0
  24. package/payload/platform/plugins/admin/mcp/dist/credential-identity.js +35 -0
  25. package/payload/platform/plugins/admin/mcp/dist/credential-identity.js.map +1 -0
  26. package/payload/platform/plugins/admin/mcp/dist/index.js +110 -57
  27. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  28. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +22 -0
  29. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
  30. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +62 -2
  31. package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
  32. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +6 -6
  33. package/payload/platform/plugins/docs/references/admin-identity-gate.md +40 -0
  34. package/payload/platform/plugins/docs/references/admin-session.md +2 -0
  35. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  36. package/payload/platform/plugins/docs/references/internals.md +3 -3
  37. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/profile.md +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/index.js +12 -3
  39. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  40. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts +2 -0
  41. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.d.ts.map +1 -0
  42. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js +79 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-archive-write-progress.test.js.map +1 -0
  44. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts +2 -0
  45. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.d.ts.map +1 -0
  46. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js +50 -0
  47. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest-write-phase-progress.test.js.map +1 -0
  48. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts +2 -0
  49. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.d.ts.map +1 -0
  50. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js +114 -0
  51. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-reindex-progress.test.js.map +1 -0
  52. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js +5 -0
  53. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-read-active-rules.test.js.map +1 -1
  54. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts +15 -0
  55. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  56. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +17 -17
  57. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  58. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +21 -1
  59. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  60. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +1 -1
  61. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
  62. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +19 -4
  63. package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
  64. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
  65. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +4 -2
  66. package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
  67. package/payload/platform/scripts/remediate-glsmith-identity.sh +500 -0
  68. package/payload/platform/scripts/seed-neo4j.sh +77 -12
  69. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  70. package/payload/platform/services/claude-session-manager/dist/http-server.js +36 -10
  71. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  72. package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts +51 -0
  73. package/payload/platform/services/claude-session-manager/dist/identity-audit.d.ts.map +1 -0
  74. package/payload/platform/services/claude-session-manager/dist/identity-audit.js +103 -0
  75. package/payload/platform/services/claude-session-manager/dist/identity-audit.js.map +1 -0
  76. package/payload/platform/services/claude-session-manager/dist/index.js +33 -0
  77. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  78. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts +7 -0
  79. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.d.ts.map +1 -1
  80. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js +9 -0
  81. package/payload/platform/services/claude-session-manager/dist/jsonl-enumerator.js.map +1 -1
  82. package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.d.ts +25 -0
  83. package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.d.ts.map +1 -0
  84. package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js +42 -0
  85. package/payload/platform/services/claude-session-manager/dist/mcp-user-binding.js.map +1 -0
  86. package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts +4 -1
  87. package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.d.ts.map +1 -1
  88. package/payload/platform/services/claude-session-manager/dist/preference-reconciliation-audit.js.map +1 -1
  89. package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts +44 -0
  90. package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.d.ts.map +1 -0
  91. package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js +127 -0
  92. package/payload/platform/services/claude-session-manager/dist/redundant-operator-seat-audit.js.map +1 -0
  93. package/payload/server/{chunk-LMLVOZ6G.js → chunk-UGPQCVIW.js} +11 -38
  94. package/payload/server/maxy-edge.js +1 -1
  95. package/payload/server/public/assets/{AdminLoginScreens-CMh1pdOp.js → AdminLoginScreens-DeR71H29.js} +1 -1
  96. package/payload/server/public/assets/AdminShell-DlAVQUda.js +2 -0
  97. package/payload/server/public/assets/{Checkbox-OCfZCTCO.js → Checkbox-B629mOPp.js} +1 -1
  98. package/payload/server/public/assets/{admin-Bi2uYnAg.js → admin-C15h-NL0.js} +1 -1
  99. package/payload/server/public/assets/{arc-Bm9oSOth.js → arc-qKfXIt8v.js} +1 -1
  100. package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +1 -0
  101. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-C2dK88g3.js → architectureDiagram-Q4EWVU46-DkVrGn7G.js} +1 -1
  102. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DfLSsjCJ.js → blockDiagram-DXYQGD6D-DqavswGH.js} +1 -1
  103. package/payload/server/public/assets/browser-B7xQLIRK.js +1 -0
  104. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Bxkmp6OL.js → c4Diagram-AHTNJAMY-B7fyKiXe.js} +1 -1
  105. package/payload/server/public/assets/calendar-A-vGm6pL.js +1 -0
  106. package/payload/server/public/assets/channel-j70eMvcL.js +1 -0
  107. package/payload/server/public/assets/chat-DAae6Z51.js +1 -0
  108. package/payload/server/public/assets/chevron-left-u4tjq7fI.js +1 -0
  109. package/payload/server/public/assets/{chunk-2KRD3SAO-BVNDFwNH.js → chunk-2KRD3SAO-DsgMtGkv.js} +1 -1
  110. package/payload/server/public/assets/{chunk-336JU56O-Daz6nMta.js → chunk-336JU56O-CkdISfNt.js} +2 -2
  111. package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +1 -0
  112. package/payload/server/public/assets/{chunk-4BX2VUAB-DTldfvwP.js → chunk-4BX2VUAB-CYpiF2bl.js} +1 -1
  113. package/payload/server/public/assets/{chunk-4TB4RGXK-DhM8pwRG.js → chunk-4TB4RGXK-CWyc_F7v.js} +1 -1
  114. package/payload/server/public/assets/{chunk-55IACEB6-CzTsbIHo.js → chunk-55IACEB6-BbzKMw2Z.js} +1 -1
  115. package/payload/server/public/assets/{chunk-5FUZZQ4R-BrcObZhe.js → chunk-5FUZZQ4R-u19Nai9e.js} +1 -1
  116. package/payload/server/public/assets/{chunk-5PVQY5BW-SFqTuS11.js → chunk-5PVQY5BW-Ba8by6Uy.js} +1 -1
  117. package/payload/server/public/assets/{chunk-67CJDMHE-EIbrSGOo.js → chunk-67CJDMHE-BwUuxtyb.js} +1 -1
  118. package/payload/server/public/assets/{chunk-7N4EOEYR-B1D4Jorr.js → chunk-7N4EOEYR-BRH9iM9L.js} +1 -1
  119. package/payload/server/public/assets/{chunk-AA7GKIK3-BKHiX4cC.js → chunk-AA7GKIK3-BGoztgLL.js} +1 -1
  120. package/payload/server/public/assets/{chunk-BSJP7CBP-xBzu29m7.js → chunk-BSJP7CBP-C5GDAZTl.js} +1 -1
  121. package/payload/server/public/assets/{chunk-CIAEETIT-x2x0gMpL.js → chunk-CIAEETIT-ChY32VPS.js} +1 -1
  122. package/payload/server/public/assets/{chunk-EDXVE4YY-D5UkD28M.js → chunk-EDXVE4YY-CPSD3p6p.js} +1 -1
  123. package/payload/server/public/assets/{chunk-ENJZ2VHE-Dbz67a7E.js → chunk-ENJZ2VHE-D1oL-iUr.js} +1 -1
  124. package/payload/server/public/assets/{chunk-FMBD7UC4-XfWvuu2F.js → chunk-FMBD7UC4-CPvYEr54.js} +1 -1
  125. package/payload/server/public/assets/{chunk-FOC6F5B3-DfOEDS4q.js → chunk-FOC6F5B3-9Yyj7Vbz.js} +1 -1
  126. package/payload/server/public/assets/{chunk-ICPOFSXX-D_WEZZvg.js → chunk-ICPOFSXX-BaYgh8FR.js} +2 -2
  127. package/payload/server/public/assets/{chunk-K5T4RW27-7O627Xi1.js → chunk-K5T4RW27-5ucpeRvm.js} +1 -1
  128. package/payload/server/public/assets/{chunk-KGLVRYIC-BXI3XDP9.js → chunk-KGLVRYIC-DW-FHk7T.js} +1 -1
  129. package/payload/server/public/assets/{chunk-LIHQZDEY-B9cFNN0l.js → chunk-LIHQZDEY-CGGVfAyG.js} +1 -1
  130. package/payload/server/public/assets/{chunk-ORNJ4GCN-BR3UNDTn.js → chunk-ORNJ4GCN-Bv8EUa5d.js} +1 -1
  131. package/payload/server/public/assets/{chunk-OYMX7WX6-2wKIEtFZ.js → chunk-OYMX7WX6-C1mXJnyw.js} +1 -1
  132. package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +1 -0
  133. package/payload/server/public/assets/{chunk-U2HBQHQK-augM3AXB.js → chunk-U2HBQHQK-PwSQz6EP.js} +1 -1
  134. package/payload/server/public/assets/{chunk-X2U36JSP-BAM9q9ZQ.js → chunk-X2U36JSP--NPHTBlU.js} +1 -1
  135. package/payload/server/public/assets/{chunk-XPW4576I-DxPpji5P.js → chunk-XPW4576I-Bbc7Da32.js} +1 -1
  136. package/payload/server/public/assets/{chunk-YZCP3GAM-BD3ClFXP.js → chunk-YZCP3GAM-D-9v8e--.js} +1 -1
  137. package/payload/server/public/assets/{chunk-ZZ45TVLE-CqxhLPep.js → chunk-ZZ45TVLE-CMPg670Q.js} +1 -1
  138. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +1 -0
  139. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +1 -0
  140. package/payload/server/public/assets/clone-DjPWA_NH.js +1 -0
  141. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-xywWX-9i.js → cose-bilkent-S5V4N54A-NVSb1Bhy.js} +1 -1
  142. package/payload/server/public/assets/{dagre-KV5264BT-ChRpqqiH.js → dagre-KV5264BT-V2Ai1DFl.js} +1 -1
  143. package/payload/server/public/assets/{dagre-BaHjDQ-8.js → dagre-QfLcO-1j.js} +1 -1
  144. package/payload/server/public/assets/data-BNWpKx1d.js +1 -0
  145. package/payload/server/public/assets/{diagram-5BDNPKRD-KjwTpyBi.js → diagram-5BDNPKRD-Caw21693.js} +1 -1
  146. package/payload/server/public/assets/{diagram-G4DWMVQ6-DZO9njAF.js → diagram-G4DWMVQ6-CgwVkT2q.js} +1 -1
  147. package/payload/server/public/assets/{diagram-MMDJMWI5-Bus-U-TI.js → diagram-MMDJMWI5-DFUrLZhs.js} +1 -1
  148. package/payload/server/public/assets/{diagram-TYMM5635-CfJodFgq.js → diagram-TYMM5635-CEEiEuZJ.js} +1 -1
  149. package/payload/server/public/assets/{erDiagram-SMLLAGMA-Bt5zqWiW.js → erDiagram-SMLLAGMA-CG10NrT3.js} +1 -1
  150. package/payload/server/public/assets/file-download-4mKJxUi-.js +1 -0
  151. package/payload/server/public/assets/{flatten-Bpu1L63d.js → flatten-DAO0sfCM.js} +1 -1
  152. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B64Q590S.js → flowDiagram-DWJPFMVM-BqkV9Okv.js} +1 -1
  153. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-BWdgCEpH.js → ganttDiagram-T4ZO3ILL-DRiCDQF6.js} +1 -1
  154. package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +1 -0
  155. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-Djq2B0WT.js → gitGraphDiagram-UUTBAWPF-BZV2voyy.js} +1 -1
  156. package/payload/server/public/assets/{graph-CrJ-itbq.js → graph-D0orIRAh.js} +3 -3
  157. package/payload/server/public/assets/{graph-labels-CmCWaKJT.js → graph-labels-B8YAdo3Z.js} +1 -1
  158. package/payload/server/public/assets/{graphlib-CNJh9_lx.js → graphlib-DGPThX8M.js} +1 -1
  159. package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +1 -0
  160. package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +2 -0
  161. package/payload/server/public/assets/{isEmpty-DkDEVnMZ.js → isEmpty-Cb_U81C6.js} +1 -1
  162. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-V3ACkWCW.js → ishikawaDiagram-UXIWVN3A-BKsAxSvp.js} +1 -1
  163. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-9T0qZeH3.js → journeyDiagram-VCZTEJTY-CmliuOd-.js} +1 -1
  164. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CxZ0ukx3.js → kanban-definition-6JOO6SKY-DAlElMb-.js} +1 -1
  165. package/payload/server/public/assets/{line-DUHKCQZT.js → line-DKZqLKAC.js} +1 -1
  166. package/payload/server/public/assets/{linear-BgIBblun.js → linear-CbSGdh1x.js} +1 -1
  167. package/payload/server/public/assets/{maximize-2-_cJWIgx2.js → maximize-2-CxstTgoK.js} +1 -1
  168. package/payload/server/public/assets/{mermaid-parser.core-CyHygs0-.js → mermaid-parser.core-DFvbao9C.js} +2 -2
  169. package/payload/server/public/assets/{mermaid.core-L55fJBSx.js → mermaid.core-C0vEBxDm.js} +3 -3
  170. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DczaUX_E.js → mindmap-definition-QFDTVHPH-CShASUKd.js} +1 -1
  171. package/payload/server/public/assets/operator-DZzuotDB.js +1 -0
  172. package/payload/server/public/assets/{ordinal-DK3QISRR.js → ordinal-H0tVmBDP.js} +1 -1
  173. package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +1 -0
  174. package/payload/server/public/assets/{page-DbUaFfk6.js → page-3g0A19Rv.js} +6 -6
  175. package/payload/server/public/assets/page-Ck_pLhAk.js +1 -0
  176. package/payload/server/public/assets/{pdf-render-COLA4aPx.js → pdf-render-jAQU0nXt.js} +1 -1
  177. package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +1 -0
  178. package/payload/server/public/assets/{pieDiagram-DEJITSTG-Da5TdnNt.js → pieDiagram-DEJITSTG-CBZHpDAJ.js} +1 -1
  179. package/payload/server/public/assets/{public-CYhDdDJd.js → public-WFUQw9AD.js} +1 -1
  180. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DX7J81uh.js → quadrantDiagram-34T5L4WZ-n3bB3K91.js} +1 -1
  181. package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +1 -0
  182. package/payload/server/public/assets/{reduce-uzWdoyL7.js → reduce-DAvwat-a.js} +1 -1
  183. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DJQGrZPG.js → requirementDiagram-MS252O5E-DiDvQK3c.js} +1 -1
  184. package/payload/server/public/assets/rotate-ccw-COGQTi7n.js +1 -0
  185. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Ba8fGz96.js → sankeyDiagram-XADWPNL6-DWDQQZmd.js} +1 -1
  186. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BmDPC7qx.js → sequenceDiagram-FGHM5R23-DmAqRlBT.js} +1 -1
  187. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-1VkptYFz.js → stateDiagram-FHFEXIEX-D4R-n6bZ.js} +1 -1
  188. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +1 -0
  189. package/payload/server/public/assets/tasks-B97VpwEJ.js +1 -0
  190. package/payload/server/public/assets/{time-entry-format-D477WAes.js → time-entry-format-C09rDHo9.js} +1 -1
  191. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-B92U3T_f.js → timeline-definition-GMOUNBTQ-CjiHGP4l.js} +1 -1
  192. package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +1 -0
  193. package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +1 -0
  194. package/payload/server/public/assets/useCopyFeedback-CSk9KjhY.js +1 -0
  195. package/payload/server/public/assets/useSubAccountSwitcher-DLJFISqf.js +9 -0
  196. package/payload/server/public/assets/{useSubAccountSwitcher-BKCWKo97.css → useSubAccountSwitcher-Dzmd7Aip.css} +1 -1
  197. package/payload/server/public/assets/{useVoiceRecorder-CZPtVpM-.js → useVoiceRecorder-DCyJQkFK.js} +2 -2
  198. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-Y6Wkihrs.js → vennDiagram-DHZGUBPP-CBdDQ7c-.js} +1 -1
  199. package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +1 -0
  200. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-iJpfal2z.js → wardleyDiagram-NUSXRM2D-BlIQPKLb.js} +1 -1
  201. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-S0bv7oH0.js → xychartDiagram-5P7HB3ND-CslKgh9B.js} +1 -1
  202. package/payload/server/public/browser.html +5 -5
  203. package/payload/server/public/calendar.html +6 -6
  204. package/payload/server/public/chat.html +13 -12
  205. package/payload/server/public/data.html +11 -11
  206. package/payload/server/public/graph.html +11 -10
  207. package/payload/server/public/index.html +14 -14
  208. package/payload/server/public/operator.html +15 -14
  209. package/payload/server/public/public.html +13 -12
  210. package/payload/server/public/tasks.html +5 -4
  211. package/payload/server/server.js +703 -555
  212. package/payload/server/public/assets/AdminShell-X9Bg3AKc.js +0 -2
  213. package/payload/server/public/assets/architecture-YZFGNWBL-Bbnxm4F4.js +0 -1
  214. package/payload/server/public/assets/browser-B0ieZy-b.js +0 -1
  215. package/payload/server/public/assets/calendar-CRL2_9Fl.js +0 -1
  216. package/payload/server/public/assets/channel-CatPTq-5.js +0 -1
  217. package/payload/server/public/assets/chat-DUc7bt5W.js +0 -1
  218. package/payload/server/public/assets/chevron-left-B2DKUxLk.js +0 -1
  219. package/payload/server/public/assets/chunk-426QAEUC-CqLMwOdA.js +0 -1
  220. package/payload/server/public/assets/chunk-QZHKN3VN-CjWy8NJ7.js +0 -1
  221. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DHhR5rdN.js +0 -1
  222. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DH4pAdfu.js +0 -1
  223. package/payload/server/public/assets/clone-DCKzwjWW.js +0 -1
  224. package/payload/server/public/assets/data-C1ftMulP.js +0 -1
  225. package/payload/server/public/assets/file-download-CHTyUQqS.js +0 -1
  226. package/payload/server/public/assets/gitGraph-7Q5UKJZL-Ps5HDzLh.js +0 -1
  227. package/payload/server/public/assets/info-OMHHGYJF-gtlpwIig.js +0 -1
  228. package/payload/server/public/assets/infoDiagram-42DDH7IO-CPrWlrsa.js +0 -2
  229. package/payload/server/public/assets/operator-B3Mi3TW0.js +0 -1
  230. package/payload/server/public/assets/packet-4T2RLAQJ-DrSn1e0n.js +0 -1
  231. package/payload/server/public/assets/page-C1G57kPZ.js +0 -1
  232. package/payload/server/public/assets/pie-ZZUOXDRM-C09i6N-g.js +0 -1
  233. package/payload/server/public/assets/radar-PYXPWWZC-CMZN2KQH.js +0 -1
  234. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdgkPHuh.js +0 -1
  235. package/payload/server/public/assets/tasks-0OcRiBdQ.js +0 -1
  236. package/payload/server/public/assets/treeView-SZITEDCU-CeuUM5oL.js +0 -1
  237. package/payload/server/public/assets/treemap-W4RFUUIX-C--fAaJv.js +0 -1
  238. package/payload/server/public/assets/useCopyFeedback-CpfVOO26.js +0 -1
  239. package/payload/server/public/assets/useSubAccountSwitcher-Bo7bnFtC.js +0 -9
  240. package/payload/server/public/assets/wardley-RL74JXVD-4WPJ2UA9.js +0 -1
  241. /package/payload/server/public/assets/{_baseFor-Q4DeIqQC.js → _baseFor-D3BqAOBr.js} +0 -0
  242. /package/payload/server/public/assets/{array-WaOTgZu7.js → array-iYP9fzJp.js} +0 -0
  243. /package/payload/server/public/assets/{cytoscape.esm-CMmjo4hO.js → cytoscape.esm-BQSBzPsB.js} +0 -0
  244. /package/payload/server/public/assets/{defaultLocale-BxqJVxq5.js → defaultLocale-BrdA1gDi.js} +0 -0
  245. /package/payload/server/public/assets/{dist-Dx-cpU53.js → dist-Cvgxm7qv.js} +0 -0
  246. /package/payload/server/public/assets/{init-DX7c5Edh.js → init-Bx0S6pkp.js} +0 -0
  247. /package/payload/server/public/assets/{katex-B2dtGfSp.js → katex-BsiH_a6d.js} +0 -0
  248. /package/payload/server/public/assets/{path-CnSyroar.js → path-BLSgTy3w.js} +0 -0
  249. /package/payload/server/public/assets/{preload-helper-DqboRNgS.js → preload-helper-ClBMtM1g.js} +0 -0
  250. /package/payload/server/public/assets/{rough.esm-eLccZ4OJ.js → rough.esm-BMOtDaaS.js} +0 -0
  251. /package/payload/server/public/assets/{src-Dqs1wlnb.js → src-DV4LKv2E.js} +0 -0
@@ -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-LMLVOZ6G.js";
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.activeRuleSet = activeRuleSet2;
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 queryActiveRuleCandidates(session, accountId) {
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 (pref:Preference {accountId: $accountId, scope: 'admin'})
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 activeRuleSet2(session, accountId, cap = exports.INJECTION_RULE_CAP) {
191
- const candidates = await queryActiveRuleCandidates(session, accountId);
192
- return deconflictBySubject(candidates).slice(0, cap);
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 existsSync34, watchFile } from "fs";
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 join35, basename as basename13 } from "path";
1391
- import { homedir as homedir3 } from "os";
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 app61 = new Hono();
6141
- app61.post("/", async (c) => {
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 app61;
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 app61 = new Hono();
6440
- app61.post("/", async (c) => {
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 app61;
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 existsSync9, readdirSync as readdirSync8, realpathSync as realpathSync4 } from "fs";
8166
- import { basename as basename5, dirname as dirname4, isAbsolute, join as join14, relative as relative2, resolve as resolve12, sep as sep3 } from "path";
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
- for (const { path: path2 } of enumerateJsonls(join11(cfg, "projects"))) {
8200
- if (basename4(path2) === `${sessionId}.jsonl`) return dirname3(path2);
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 = readdirSync5(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
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 = join11(projectsRoot, slug);
8270
+ const slugDir = join12(projectsRoot, slug);
8215
8271
  let entries;
8216
8272
  try {
8217
- entries = readdirSync5(slugDir, { withFileTypes: true });
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: join11(slugDir, entry.name), isSubagent: false, archived: false });
8281
+ out.push({ path: join12(slugDir, entry.name), isSubagent: false, archived: false });
8226
8282
  } else if (entry.isDirectory() && entry.name === "subagents") {
8227
- const subDir = join11(slugDir, entry.name);
8283
+ const subDir = join12(slugDir, entry.name);
8228
8284
  let subEntries;
8229
8285
  try {
8230
- subEntries = readdirSync5(subDir, { withFileTypes: true });
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: join11(subDir, sub.name), isSubagent: true, archived: false });
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 = join11(slugDir, entry.name);
8298
+ const archiveDir = join12(slugDir, entry.name);
8243
8299
  let archiveEntries;
8244
8300
  try {
8245
- archiveEntries = readdirSync5(archiveDir, { withFileTypes: true });
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: join11(archiveDir, arc.name), isSubagent: false, archived: true });
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 = join11(accountDir, "session-titles.json");
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 = join11(configDir2, "projects");
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 excludedChannelCount = 0;
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 = join11(projectDir, `${sessionId}.meta.json`);
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 (isReaderChannelSession(role, sidecarChannel)) {
8457
- excludedChannelCount += 1;
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: resolved.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(scopeAccountId, auid);
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} excludedChannel=${excludedChannelCount} 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"}`
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 existsSync8, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
8527
- import { join as join12 } from "path";
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 (!existsSync8(usersFilePath)) return null;
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 readdirSync7 } from "fs";
8833
- import { join as join13 } from "path";
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(join13(uploadsBase, id));
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(join13(dir, `${attachmentId}.meta.json`), "utf8"));
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 = readdirSync7(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
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(join13(dir, name), name);
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 = join14(cfg, "projects");
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 = basename5(path2).replace(/\.jsonl$/, "");
9021
+ const sessionId = basename4(path2).replace(/\.jsonl$/, "");
8954
9022
  const projectDir = dirname4(path2);
8955
- const meta = readSidecarMeta(join14(projectDir, `${sessionId}.meta.json`));
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(account.accountId, idRes.userId) : null;
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(join14(dir, `agent-${hex}.meta.json`), "utf8"));
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 = readdirSync8(c.subagentsDir).filter((n) => AGENT_JSONL_RE.test(n));
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(join14(c.subagentsDir, name));
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(join14(cfg, "projects")) : null;
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(join14(projectDir, `${sessionId}.jsonl`));
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(join14(projectDir, sessionId, "subagents"));
9309
+ const subagentsDir = resolve12(join15(projectDir, sessionId, "subagents"));
9242
9310
  console.log(
9243
- `[webchat-activity] op=watch-subagents key=${sessionKey} dir=${subagentsDir} exists=${existsSync9(subagentsDir)}`
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 || !existsSync9(dir)) return c.json({ entries: [] });
9418
+ if (!dir || !existsSync10(dir)) return c.json({ entries: [] });
9351
9419
  let names;
9352
9420
  try {
9353
- names = readdirSync8(dir).filter((n) => DIRECTIVE_NAME_RE.test(n));
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(join14(dir, name)).size;
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(join14(dir, name));
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(join14(uploadsBase, r.attachmentId));
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: `"${basename5(absolute)}" exceeds the 50 MB limit` }, 400);
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)], basename5(absolute), { type: mime });
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 readdirSync9 } from "fs";
9759
- import { basename as basename6, dirname as dirname5, join as join15, resolve as resolve13, sep as sep4 } from "path";
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(join15(cfg, "projects"))) {
9834
- const sessionId = basename6(path2).replace(/\.jsonl$/, "");
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(join15(projectDir, `${sessionId}.meta.json`));
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(join15(cfg, "projects")) : null;
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(join15(projectDir, `${sessionId}.jsonl`));
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(join15(projectDir, `${sessionId}.meta.json`));
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 = readdirSync9(dir).find((f) => !f.endsWith(".meta.json") && !f.endsWith(EXTRACTED_TEXT_SUFFIX));
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 basename7, dirname as dirname6 } from "path";
10054
- import { join as join18 } from "path";
10055
- import { existsSync as existsSync11, readdirSync as readdirSync11, readFileSync as readFileSync19, renameSync as renameSync4, statSync as statSync7, writeFileSync as writeFileSync7 } from "fs";
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 join16 } from "path";
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 join16(accountDir, FILE);
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 existsSync10, mkdirSync as mkdirSync3, readdirSync as readdirSync10, readFileSync as readFileSync18, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
10143
- import { join as join17 } from "path";
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 join17(sessionsDir, `${id}${suffix}`);
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 (existsSync10(tmp)) unlinkSync2(tmp);
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 = readdirSync10(sessionsDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
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 = join17(sessionsDir, name);
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 (existsSync10(path2)) {
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(join18(dir, `${sessionId}.meta.json`));
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 = join18(cfg, "projects");
10346
+ const projectsRoot = join19(cfg, "projects");
10279
10347
  let slugs;
10280
10348
  try {
10281
- slugs = readdirSync11(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
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 = join18(projectsRoot, slug, `${sessionId}.meta.json`);
10287
- if (existsSync11(metaPath)) {
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(join18(projectDir, `${sessionId}.meta.json`)).adminUserId };
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(join18(projectDir, `${sessionId}.jsonl`)).size;
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(join18(cfg, "projects"))) {
10517
+ for (const { path: path2, isSubagent, archived } of enumerateJsonls(join19(cfg, "projects"))) {
10450
10518
  if (isSubagent || archived) continue;
10451
- const id = basename7(path2).slice(0, -".jsonl".length);
10452
- const meta = readSidecarMeta(join18(dirname6(path2), `${id}.meta.json`));
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 basename7(projectDir) !== "archive";
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 app61 = new Hono();
10512
- app61.post("/send", requireAdminSession, async (c) => {
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
- app61.post("/interrupt", requireAdminSession, async (c) => {
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
- app61.post("/settings", requireAdminSession, async (c) => {
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 = join18(account.accountDir, "account.json");
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
- app61.get("/session", requireAdminSession, async (c) => {
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
- join18(cfg2, "sessions"),
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(join18(cfg, "projects"))) {
10843
- if (basename7(path2) === `${sessionId}.jsonl`) {
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(join18(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
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
- app61.post("/permission-verdict", requireAdminSession, async (c) => {
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 app61;
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 existsSync12, readFileSync as readFileSync20, readdirSync as readdirSync12 } from "fs";
10883
- import { join as join19 } from "path";
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 (!existsSync12(specialistsDir)) return { specialists: [], skipped: [] };
10895
- const entries = readdirSync12(specialistsDir);
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(join19(specialistsDir, file), "utf-8");
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 join20 } from "path";
11020
- import { existsSync as existsSync13, readFileSync as readFileSync21 } from "fs";
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 = join20(platformRoot3, "config", "brand.json");
11080
- if (existsSync13(brandPath)) {
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(homedir(), configDirName(), filename);
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 (!existsSync13(sp)) {
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 join21 } from "path";
11169
- import { existsSync as existsSync14, readFileSync as readFileSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, rmSync, renameSync as renameSync5 } from "fs";
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 join21(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
11242
+ return join22(accountDir, "secrets", "quickbooks-pending", `${state}.json`);
11175
11243
  }
11176
11244
  function storePath(accountDir) {
11177
- return join21(accountDir, "secrets", "quickbooks.json");
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) || !existsSync14(pendingPath(accountDir, 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 (!existsSync14(storePath(accountDir))) {
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(join21(accountDir, "secrets"), { recursive: true });
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 existsSync16, readFileSync as readFileSync24, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
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 join23 } from "path";
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 existsSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync9, renameSync as renameSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync13, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
11416
- import { dirname as dirname7, join as join22 } from "path";
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 line = `[users-audit] action=${fields.action} actor=${actor}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
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 (existsSync15(input.usersFile)) {
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 = join22(input.accountDir, "account.json");
11489
- if (!existsSync15(accountJsonPath)) {
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 (existsSync15(input.usersFile)) {
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 (existsSync15(input.accountsDir)) {
11595
+ if (existsSync16(input.accountsDir)) {
11527
11596
  let entries;
11528
11597
  try {
11529
- entries = readdirSync13(input.accountsDir);
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 = join22(input.accountsDir, entry);
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 = join22(accountDir, "account.json");
11543
- if (!existsSync15(accountJsonPath)) continue;
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 (!existsSync16(USERS_FILE)) return null;
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 = existsSync16(CLAUDE_CREDENTIALS_FILE);
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(join23(dirname8(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
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 (existsSync16(INSTALL_OWNER_FILE)) {
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 (existsSync16(INSTALL_OWNER_FILE)) {
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 existsSync17, renameSync as renameSync8, statSync as statSync9 } from "fs";
11986
- import { join as join24 } from "path";
11987
- var CLIENT_ERRORS_LOG = join24(LOG_DIR, "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 (!existsSync17(CLIENT_ERRORS_LOG)) return;
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 loadAdminDisplayIdentity(accountId, userId);
12168
- if (result.source === "admin-user") {
12169
- console.log(`[admin-identity] userName-source=admin-user userId=${userId.slice(0, 8)} accountId=${accountId.slice(0, 8)} name=${result.name} avatar=${result.avatar ? "present" : "absent"}`);
12170
- return { userName: result.name, avatar: result.avatar };
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" ? "Owner" : void 0;
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 !== void 0) {
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 existsSync19, readdirSync as readdirSync14, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
12356
- import { resolve as resolve16, basename as basename8 } from "path";
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 existsSync18 } from "fs";
12360
- import { join as join25 } from "path";
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 = join25(dir, filename);
12366
- if (existsSync18(fullPath)) {
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 = basename8(fileParam);
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 = basename8(hit.path);
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 (!existsSync19(dir)) continue;
12563
+ if (!existsSync20(dir)) continue;
12495
12564
  let files;
12496
12565
  try {
12497
- files = readdirSync14(dir).filter((f) => f.endsWith(".log"));
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 existsSync20 } from "fs";
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 = existsSync20(dir);
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 (existsSync20(candidateDir)) {
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 (!existsSync20(metaPath)) {
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 readdirSync15, readFileSync as readFileSync26, existsSync as existsSync21, rmSync as rmSync2 } from "fs";
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 (!existsSync21(agentsDir)) return c.json({ agents: [] });
12692
+ if (!existsSync22(agentsDir)) return c.json({ agents: [] });
12624
12693
  const agents = [];
12625
12694
  try {
12626
- const entries = readdirSync15(agentsDir, { withFileTypes: true });
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 (!existsSync21(configPath2)) continue;
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 (!existsSync21(agentDir)) {
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 (!existsSync21(agentDir)) {
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 existsSync22, mkdirSync as mkdirSync6, createWriteStream } from "fs";
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 homedir2 } from "os";
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 (!existsSync22(a.storagePath)) reason = "missing-file";
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(homedir2(), resolvePath(ACCOUNTS_DIR, accountId), persistedAgentSessionId);
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 existsSync23, readFileSync as readFileSync27, readdirSync as readdirSync16, statSync as statSync11 } from "fs";
13393
- import { dirname as dirname9, resolve as resolve19, join as join26 } from "path";
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(accountId, userId);
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
- join26(pluginDir, "mcp/dist/index.js"),
13435
- join26(pluginDir, "mcp/src/index.ts")
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 (!existsSync23(path2)) continue;
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 (existsSync23(platformPlugins)) {
13492
- for (const name of readdirSync16(platformPlugins)) {
13493
- const dir = join26(platformPlugins, name);
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 (existsSync23(premiumRoot)) {
13502
- for (const bundle of readdirSync16(premiumRoot)) {
13503
- const bundlePlugins = join26(premiumRoot, bundle, "plugins");
13504
- if (!existsSync23(bundlePlugins)) continue;
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 readdirSync16(bundlePlugins)) {
13507
- const dir = join26(bundlePlugins, name);
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 (!existsSync23(accountFile)) return /* @__PURE__ */ new Set();
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 (!existsSync23(path2)) return null;
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(join26(dir, "PLUGIN.md"));
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 = existsSync23(join26(dir, "mcp/dist/index.js")) || existsSync23(join26(dir, "mcp/src/index.ts"));
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 = join26(dir, relPath);
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 (!existsSync23(specialistsDir)) return [];
13663
+ if (!existsSync24(specialistsDir)) return [];
13595
13664
  let entries;
13596
13665
  try {
13597
- entries = readdirSync16(specialistsDir);
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(join26(specialistsDir, file));
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 (!existsSync23(accountFile)) return [];
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 (!existsSync23(pluginsDir)) return [];
13724
+ if (!existsSync24(pluginsDir)) return [];
13656
13725
  let entries;
13657
13726
  try {
13658
- entries = readdirSync16(pluginsDir);
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 (!existsSync23(manifestPath)) continue;
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 existsSync24, readFileSync as readFileSync28 } from "fs";
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 (!existsSync24(statePath)) return null;
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 TAG44 = "[admin:events]";
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(`${TAG44} reject reason=body-not-json detail=${detail}`);
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(`${TAG44} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
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 existsSync25 } from "fs";
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 basename10, dirname as dirname10, join as join28, relative as relative4, resolve as resolve22, sep as sep6 } from "path";
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 join27, basename as basename9, extname as extname2, sep as sep5 } from "path";
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 = join27(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
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 - basename9(absolute).length);
14406
- const base = basename9(absolute);
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(join27(dir, `${stem}.meta.json`), "utf-8");
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 = join27(root, entry.name);
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 = basename9(wf.absolute);
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(join28(absDir, `${baseName}.meta.json`), "utf8");
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(join28(absolute, entry.name), entry.name);
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 = join28(absolute, name);
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(join28(projectDir, `${sessionId}.meta.json`));
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 = basename10(absolute);
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 = join28(dirAbsolute, d.name);
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, basename10(absolute));
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 = basename10(rawName).replace(/[\0/\\]/g, "_");
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 ? basename10(relpath).replace(/[\0/\\]/g, "_") : `${Date.now()}-${safeName}`;
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 : join28(base.relative, relDir);
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 = !existsSync25(tmpPath);
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 = !existsSync25(state.tmpPath);
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 = basename10(absolute);
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` ? join28(dirname10(absolute), `${stem}.meta.json`) : null;
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 basename11 } from "path";
17839
- import { existsSync as existsSync26 } from "fs";
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 ?? basename11(relativePath),
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 (!existsSync26(dir)) continue;
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 (existsSync26(inp.overridePath)) {
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 (existsSync26(inp.bundledPath)) {
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 existsSync27, readFileSync as readFileSync29 } from "fs";
18576
- import { resolve as resolve24, join as join29 } from "path";
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 = join29(PLATFORM_ROOT6, "config", "brand.json");
18580
- if (existsSync27(brandJsonPath)) {
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 (!existsSync27(VERSION_FILE)) return "unknown";
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 existsSync28 } from "fs";
19369
- import { join as join31 } from "path";
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 join30 } from "path";
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 = join30(accountDir, AVAILABILITY_FILENAME);
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 (!existsSync28(join31(account.accountDir, AVAILABILITY_FILENAME))) {
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.taskId AS taskId, te.startedAt AS startedAt
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
- console.log(`${TAG34} op=start taskId=${taskId} accountId=${accountId} priorOpen=${priorTaskId ?? "none"}`);
19971
- if (priorEntryId && priorTaskId === taskId) {
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 neo4j6 from "neo4j-driver";
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: neo4j6.int(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
- RETURN coalesce(sum(te.seconds), 0) AS sumEntries, coalesce(t.secondsLogged, 0) AS secondsLogged`,
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/index.ts
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.route("/session", session_default);
20112
- app50.route("/accounts", accounts_default);
20113
- app50.route("/logs", logs_default);
20114
- app50.route("/claude-info", claude_info_default);
20115
- app50.route("/attachment", attachment_default);
20116
- app50.route("/agents", agents_default);
20117
- app50.route("/sessions", sessions_default);
20118
- app50.route("/claude-sessions", claude_sessions_default);
20119
- app50.route("/log-ingest", log_ingest_default);
20120
- app50.route("/events", events_default);
20121
- app50.route("/files", files_default);
20122
- app50.route("/graph-search", graph_search_default);
20123
- app50.route("/graph-subgraph", graph_subgraph_default);
20124
- app50.route("/graph-delete", graph_delete_default);
20125
- app50.route("/graph-restore", graph_restore_default);
20126
- app50.route("/graph-labels-in-graph", graph_labels_in_graph_default);
20127
- app50.route("/graph-default-view", graph_default_view_default);
20128
- app50.route("/sidebar-artefacts", sidebar_artefacts_default);
20129
- app50.route("/sidebar-sessions", sidebar_sessions_default);
20130
- app50.route("/session-delete", session_delete_default);
20131
- app50.route("/session-stop", session_stop_default);
20132
- app50.route("/session-archive", session_archive_default);
20133
- app50.route("/session-rename", session_rename_default);
20134
- app50.route("/session-usage", session_usage_default);
20135
- app50.route("/browser", browser_default);
20136
- app50.route("/session-rc-spawn", session_rc_spawn_default);
20137
- app50.route("/session-reseat", session_reseat_default);
20138
- app50.route("/system-stats", system_stats_default);
20139
- app50.route("/health-brand", health_default2);
20140
- app50.route("/linkedin-ingest", linkedin_ingest_default);
20141
- app50.route("/post-turn-context", post_turn_context_default);
20142
- app50.route("/public-session-context", public_session_context_default);
20143
- app50.route("/public-session-exit", public_session_exit_default);
20144
- app50.route("/access-session-evict", access_session_evict_default);
20145
- app50.route("/enrol-person", enrol_person_default);
20146
- app50.route("/calendar", calendar_default);
20147
- app50.route("/tasks-list", tasks_list_default);
20148
- app50.route("/task-timer-start", task_timer_start_default);
20149
- app50.route("/task-timer-stop", task_timer_stop_default);
20150
- app50.route("/task-complete", task_complete_default);
20151
- var admin_default = app50;
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 TAG37 = "[access-verify]";
20292
+ var TAG38 = "[access-verify]";
20155
20293
  var MINT_TAG = "[access-session-mint]";
20156
20294
  var COOKIE_NAME = "__access_session";
20157
- var app51 = new Hono();
20158
- app51.post("/", async (c) => {
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(`${TAG37} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
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(`${TAG37} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
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
- `${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
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
- `${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
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
- `${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
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
- `${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
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
- `${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
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(`${TAG37} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
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 = app51;
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 TAG38 = "[access-request-link]";
20303
- var app52 = new Hono();
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
- app52.post("/", async (c) => {
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(`${TAG38} contactValue=${maskContact(contactValue)} result=rate-limited`);
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(`${TAG38} contactValue=${maskContact(contactValue)} result=no-account-id`);
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(`${TAG38} contactValue=${maskContact(contactValue)} result=notfound`);
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
- `${TAG38} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
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
- `${TAG38} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
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
- `${TAG38} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
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 = app52;
20517
+ var request_magic_link_default = app53;
20380
20518
 
20381
20519
  // server/routes/access/index.ts
20382
- var app53 = new Hono();
20383
- app53.route("/verify-token", verify_token_default);
20384
- app53.route("/request-magic-link", request_magic_link_default);
20385
- var access_default = app53;
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 existsSync29, readFileSync as readFileSync31, realpathSync as realpathSync6, statSync as statSync12 } from "fs";
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 app54 = new Hono();
20421
- app54.get("/:rel{.*}", (c) => {
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 = existsSync29(filePath) ? statSync12(filePath) : null;
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 (!existsSync29(filePath)) {
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 = app54;
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 existsSync30, readFileSync as readFileSync33 } from "fs";
20605
- import { join as join32 } from "path";
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 = join32(platformRoot3, "config", "brand.json");
20614
- if (!existsSync30(brandPath)) return null;
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 app55 = new Hono();
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
- app55.options("/consent", (c) => {
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
- app55.options("/brand-config", (c) => {
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
- app55.post("/consent", async (c) => {
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
- app55.get("/brand-config", (c) => {
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 = app55;
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 app56 = new Hono();
20757
- app56.get("/:slug/click", async (c) => {
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 = app56;
20959
+ var listings_default = app57;
20822
20960
 
20823
20961
  // server/routes/visitor-event.ts
20824
- var app57 = new Hono();
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
- app57.options("/event", (c) => {
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
- app57.post("/event", async (c) => {
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 = app57;
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 existsSync31, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
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 app58 = new Hono();
21148
- app58.post("/", async (c) => {
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 (!existsSync31(agentDir) || !existsSync31(resolve27(agentDir, "config.json"))) {
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 = app58;
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 app59 = new Hono();
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
- app59.options("/free-busy", (c) => {
21522
+ app60.options("/free-busy", (c) => {
21385
21523
  setCors(c);
21386
21524
  return c.body(null, 204);
21387
21525
  });
21388
- app59.get("/free-busy", async (c) => {
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 = app59;
21568
+ var calendar_public_default = app60;
21431
21569
 
21432
21570
  // app/lib/timeentry-census.ts
21433
- var TAG39 = "[timeentry-census]";
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 || maxOpenPerAccount > 1 || driftTasks > 0;
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
- RETURN t.taskId AS taskId, coalesce(t.secondsLogged, 0) AS secondsLogged, coalesce(sum(te.seconds), 0) AS sumEntries`
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 = `${TAG39} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
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(`${TAG39} error="${err instanceof Error ? err.message : String(err)}"`);
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(`${TAG39} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
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(`${TAG39} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
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 existsSync32 } from "fs";
21858
- import { join as join33 } from "path";
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 (accountId, userId) => {
21863
- const res = await loadAdminUserName(accountId, userId);
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 (existsSync32(tmp)) await unlink3(tmp);
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 = join33(projectsRoot, slug.name);
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(join33(slugDir, entry.name));
22054
+ out.push(join34(slugDir, entry.name));
21913
22055
  } else if (entry.isDirectory() && entry.name === "subagents") {
21914
- const subDir = join33(slugDir, entry.name);
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(join33(subDir, s.name));
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 ? join33(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
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 app61 = new Hono();
22280
- app61.get("/wa-channel/inbound", (c) => {
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
- app61.post("/wa-channel/reply", async (c) => {
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
- app61.post("/wa-channel/reply-document", async (c) => {
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
- app61.post("/wa-channel/ready", async (c) => {
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
- app61.post("/wa-channel/received", async (c) => {
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
- app61.post("/wa-channel/turn-end", async (c) => {
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 app61;
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
- standingRules = await this.deps.fetchStandingRules(input.effectiveAccountId) || void 0;
22503
- const injected = standingRules ? (standingRules.match(/^- /gm) ?? []).length : 0;
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 app61 = new Hono();
22752
- app61.get("/webchat-channel/inbound", (c) => {
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
- app61.post("/webchat-channel/reply", async (c) => {
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
- app61.post("/webchat-channel/connector-auth", async (c) => {
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
- app61.post("/webchat-channel/ready", async (c) => {
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
- app61.post("/webchat-channel/permission-request", async (c) => {
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
- app61.post("/webchat-channel/received", async (c) => {
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
- app61.post("/webchat-channel/turn-end", async (c) => {
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 app61;
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
- standingRules = await this.deps.fetchStandingRules(input.accountId) || void 0;
23189
- const injected = standingRules ? (standingRules.match(/^- /gm) ?? []).length : 0;
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 TAG40 = "[whatsapp-adaptor]";
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
- `${TAG40} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
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: TAG40,
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
- `${TAG40} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
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 app61 = new Hono();
23719
- app61.get("/tg-channel/inbound", (c) => {
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
- app61.post("/tg-channel/reply", async (c) => {
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
- app61.post("/tg-channel/ready", async (c) => {
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
- app61.post("/tg-channel/received", async (c) => {
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
- app61.post("/tg-channel/turn-end", async (c) => {
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 app61;
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
- standingRules = await this.deps.fetchStandingRules(input.accountId) || void 0;
23866
- const injected = standingRules ? (standingRules.match(/^- /gm) ?? []).length : 0;
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 basename12 } from "path";
23933
- var TAG41 = "[telegram:outbound]";
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(`${TAG41} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
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(`${TAG41} document ENOENT path=${filePath}`);
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(`${TAG41} document path error: ${String(err)}`);
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 = basename12(resolvedPath);
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
- `${TAG41} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
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 TAG42 = "[telegram:outbound]";
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(`${TAG42} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
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(`${TAG42} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
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: TAG42,
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 join34 } from "path";
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 ?? join34(__dirname, ".."), "services/telegram-channel/dist/server.js");
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 randomUUID14 } from "crypto";
24080
- var TAG43 = "[public-session-review]";
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
- `${TAG43} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
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
- `${TAG43} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
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
- `${TAG43} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
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 = randomUUID14();
24168
- console.log(`${TAG43} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
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
- `${TAG43} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
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 existsSync33, readFileSync as readFileSync34, statSync as statSync13 } from "fs";
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 (!existsSync33(entitlementPath)) {
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 ? join35(PLATFORM_ROOT8, "config", "brand.json") : "";
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 && !existsSync34(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 && existsSync34(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 = join35(homedir3(), BRAND.configDir, "alias-domains.json");
24763
+ var ALIAS_DOMAINS_PATH = join36(homedir4(), BRAND.configDir, "alias-domains.json");
24616
24764
  function loadAliasDomains() {
24617
24765
  try {
24618
- if (!existsSync34(ALIAS_DOMAINS_PATH)) return null;
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 app60 = new Hono();
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 rules = await (0, import_dist8.activeRuleSet)(session, accountId);
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 ?? join35(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
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 ?? join35(__dirname, ".."))
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
- app60.route("/", waGateway.routes());
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
- app60.route("/", webchatGateway.routes());
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
- app60.route("/", telegramGateway.routes());
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
- app60.route("/api/channel/schedule-inject", scheduleInjectRoutes);
24930
- app60.use("*", clientIpMiddleware);
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
- app60.use("*", async (c, next) => {
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
- app60.use("*", async (c, next) => {
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
- app60.use("*", async (c, next) => {
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
- app60.post("/__remote-auth/login", async (c) => {
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
- app60.get("/__remote-auth/logout", (c) => {
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
- app60.post("/__remote-auth/change-password", async (c) => {
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
- app60.get("/__remote-auth/setup", (c) => {
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
- app60.post("/__remote-auth/set-initial-password", async (c) => {
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
- app60.get("/api/remote-auth/status", (c) => {
25306
+ app61.get("/api/remote-auth/status", (c) => {
25159
25307
  return c.json({ configured: isRemoteAuthConfigured() });
25160
25308
  });
25161
- app60.post("/api/remote-auth/set-password", async (c) => {
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
- app60.route("/api/_client-error", client_error_default);
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
- app60.use("*", async (c, next) => {
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
- app60.route("/api/health", health_default);
25248
- app60.route("/api/chat", chatRoutes);
25249
- app60.route("/api/whatsapp", whatsapp_default);
25250
- app60.route("/api/whatsapp-reader", whatsapp_reader_default);
25251
- app60.route("/api/public-reader", public_reader_default);
25252
- app60.route("/api/webchat", createWebchatRoutes({
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
- app60.route("/api/webchat/greeting", webchat_greeting_default);
25260
- app60.route("/api/telegram", telegram_default);
25261
- app60.route("/api/quickbooks", quickbooks_default);
25262
- app60.route("/api/onboarding", onboarding_default);
25263
- app60.route("/api/admin", admin_default);
25264
- app60.route("/api/access", access_default);
25265
- app60.route("/api/session", session_default2);
25266
- app60.route("/api/calendar", calendar_public_default);
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
- app60.get("/agent-assets/:slug/:filename", (c) => {
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 (!existsSync34(filePath)) {
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
- app60.get("/generated/:filename", (c) => {
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 (!existsSync34(filePath)) {
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
- app60.route("/sites", sites_default);
25344
- app60.route("/listings", listings_default);
25345
- app60.route("/v", visitor_event_default);
25346
- app60.route("/v", visitor_consent_default);
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 && existsSync34(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) => existsSync34(resolve33(process.cwd(), "public", p.replace(/^\//, "")))
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 = join35(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
25392
- if (!existsSync34(versionFile)) return "unknown";
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 = join35(homedir3(), BRAND.configDir);
25599
+ const configDir2 = join36(homedir4(), BRAND.configDir);
25452
25600
  try {
25453
25601
  const accountId = getDefaultAccountId();
25454
25602
  if (!accountId) return null;
25455
- const cachePath = join35(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
25456
- if (!existsSync34(cachePath)) return null;
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
- app60.get("/", (c) => {
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
- app60.get("/public", (c) => {
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
- app60.get("/public-chat", (c) => {
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
- app60.use("/vnc-viewer.html", logViewerFetch);
25548
- app60.use("/vnc-popout.html", logViewerFetch);
25549
- app60.get("/vnc-popout.html", (c) => {
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
- app60.post("/api/vnc/client-event", async (c) => {
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
- app60.get("/g/:slug", (c) => {
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
- app60.get(pwa.manifestPath, (c) => {
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
- app60.get("/sw.js", (c) => {
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
- app60.get("/graph", (c) => {
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
- app60.get("/chat", (c) => {
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
- app60.get("/data", (c) => {
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
- app60.get("/tasks", (c) => {
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
- app60.get("/calendar", (c) => {
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
- app60.get("/browser", (c) => {
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
- app60.get("/:slug", async (c, next) => {
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
- app60.get("/favicon.ico", (c) => {
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
- app60.use("/*", serveStatic({ root: "./public" }));
25667
- app60.all("*", (c) => {
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: app60.fetch, port, hostname });
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 ?? join35(__dirname, "..");
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 (!existsSync34(reconcileScript)) return;
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 ?? join35(__dirname, "..");
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 (!existsSync34(auditScript)) return;
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 app60.routes ?? []) {
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 (!existsSync34(USERS_FILE)) {
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 (!existsSync34(USERS_FILE)) return 0;
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 = basename13(MAXY_DIR) || ".maxy";
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 ?? join35(__dirname, "..")),
26124
+ platformRoot: resolve33(process.env.MAXY_PLATFORM_ROOT ?? join36(__dirname, "..")),
25977
26125
  accountConfig: bootAccountConfig,
25978
26126
  onMessage: async (msg) => {
25979
26127
  if (msg.isOwnerMirror) {