@rubytech/create-maxy-code 0.1.503 → 0.1.504

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 (192) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +33 -1
  3. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
  4. package/payload/platform/plugins/docs/references/admin-ui.md +32 -0
  5. package/payload/platform/plugins/work/PLUGIN.md +3 -3
  6. package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.d.ts +2 -0
  7. package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.d.ts.map +1 -0
  8. package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.js +55 -0
  9. package/payload/platform/plugins/work/mcp/dist/__tests__/assignable-admins.test.js.map +1 -0
  10. package/payload/platform/plugins/work/mcp/dist/__tests__/work-create-assigned-admin-env.test.js +33 -1
  11. package/payload/platform/plugins/work/mcp/dist/__tests__/work-create-assigned-admin-env.test.js.map +1 -1
  12. package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.d.ts +2 -0
  13. package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.d.ts.map +1 -0
  14. package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.js +73 -0
  15. package/payload/platform/plugins/work/mcp/dist/__tests__/work-update-assign.test.js.map +1 -0
  16. package/payload/platform/plugins/work/mcp/dist/index.js +4 -1
  17. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.d.ts +13 -0
  19. package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.d.ts.map +1 -0
  20. package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.js +66 -0
  21. package/payload/platform/plugins/work/mcp/dist/lib/assignable-admins.js.map +1 -0
  22. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts +8 -0
  23. package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -1
  24. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +31 -13
  25. package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -1
  26. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts +4 -0
  27. package/payload/platform/plugins/work/mcp/dist/tools/work-list.d.ts.map +1 -1
  28. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js +3 -2
  29. package/payload/platform/plugins/work/mcp/dist/tools/work-list.js.map +1 -1
  30. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts +7 -0
  31. package/payload/platform/plugins/work/mcp/dist/tools/work-update.d.ts.map +1 -1
  32. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js +31 -0
  33. package/payload/platform/plugins/work/mcp/dist/tools/work-update.js.map +1 -1
  34. package/payload/server/public/activity.html +6 -6
  35. package/payload/server/public/agents.html +18 -0
  36. package/payload/server/public/assets/{AdminLoginScreens-Bv_bKKeL.js → AdminLoginScreens-DWMR4KtI.js} +1 -1
  37. package/payload/server/public/assets/AdminShell-C8hBpL9K.js +2 -0
  38. package/payload/server/public/assets/{activity-DZFYDHNA.js → activity-DH3z4cv3.js} +1 -1
  39. package/payload/server/public/assets/admin-aaGhd2Yh.js +1 -0
  40. package/payload/server/public/assets/agents-SPu-clsf.js +1 -0
  41. package/payload/server/public/assets/{arc-CvlzUHOf.js → arc-DaI5MLTq.js} +1 -1
  42. package/payload/server/public/assets/architecture-YZFGNWBL-DWZIX5aV.js +1 -0
  43. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-I1Hs0RJA.js → architectureDiagram-Q4EWVU46-CBGVUEN9.js} +1 -1
  44. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-Df5jTGtl.js → blockDiagram-DXYQGD6D-DS6dS4GZ.js} +1 -1
  45. package/payload/server/public/assets/{browser-Bt4-LKLU.js → browser-C_MJYN5k.js} +1 -1
  46. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B6WY5IDv.js → c4Diagram-AHTNJAMY-hBSBUZPt.js} +1 -1
  47. package/payload/server/public/assets/calendar-DA0h7dqW.js +1 -0
  48. package/payload/server/public/assets/channel-BEokjAeE.js +1 -0
  49. package/payload/server/public/assets/chat-Bg7dlM0I.js +1 -0
  50. package/payload/server/public/assets/chevron-left-BoDA12H8.js +1 -0
  51. package/payload/server/public/assets/chevron-right-DXjrO6qA.js +1 -0
  52. package/payload/server/public/assets/{chunk-2KRD3SAO-BsIIFDkc.js → chunk-2KRD3SAO-B6koUoB7.js} +1 -1
  53. package/payload/server/public/assets/{chunk-336JU56O-j9z1VtyC.js → chunk-336JU56O-BF6BRh8u.js} +2 -2
  54. package/payload/server/public/assets/chunk-426QAEUC-pbQ4PWBU.js +1 -0
  55. package/payload/server/public/assets/{chunk-4BX2VUAB-C9i7prxq.js → chunk-4BX2VUAB-7sO95xR2.js} +1 -1
  56. package/payload/server/public/assets/{chunk-4TB4RGXK-DH0QVGcv.js → chunk-4TB4RGXK-GCTndJYx.js} +1 -1
  57. package/payload/server/public/assets/{chunk-55IACEB6-Dnd_YCPA.js → chunk-55IACEB6-ggIJf_TC.js} +1 -1
  58. package/payload/server/public/assets/{chunk-5FUZZQ4R-D5sSz3yN.js → chunk-5FUZZQ4R-DeGmkimt.js} +1 -1
  59. package/payload/server/public/assets/{chunk-5PVQY5BW-CJrwWjAT.js → chunk-5PVQY5BW-aFIQKk_U.js} +1 -1
  60. package/payload/server/public/assets/{chunk-67CJDMHE-SjP6_hUw.js → chunk-67CJDMHE-LS8rUbii.js} +1 -1
  61. package/payload/server/public/assets/{chunk-7N4EOEYR-fAuhVJD0.js → chunk-7N4EOEYR-JKOVngS0.js} +1 -1
  62. package/payload/server/public/assets/{chunk-AA7GKIK3-DZxa7KVg.js → chunk-AA7GKIK3-CoXnTVK6.js} +1 -1
  63. package/payload/server/public/assets/{chunk-BSJP7CBP-DjeG3eQ-.js → chunk-BSJP7CBP-CcsqObFg.js} +1 -1
  64. package/payload/server/public/assets/{chunk-CIAEETIT-RYQULNJm.js → chunk-CIAEETIT-CpsybR7q.js} +1 -1
  65. package/payload/server/public/assets/{chunk-EDXVE4YY-Cahapnon.js → chunk-EDXVE4YY-BZ2I9PSq.js} +1 -1
  66. package/payload/server/public/assets/{chunk-ENJZ2VHE-1146X1L4.js → chunk-ENJZ2VHE-DbTwt6OZ.js} +1 -1
  67. package/payload/server/public/assets/{chunk-FMBD7UC4-BCFumtcP.js → chunk-FMBD7UC4-D27VnSCa.js} +1 -1
  68. package/payload/server/public/assets/{chunk-FOC6F5B3-CkrtX8Zt.js → chunk-FOC6F5B3-C0tU2UFl.js} +1 -1
  69. package/payload/server/public/assets/{chunk-ICPOFSXX-Ba1y3DaW.js → chunk-ICPOFSXX-UPPu2OIq.js} +1 -1
  70. package/payload/server/public/assets/{chunk-K5T4RW27-CF-PI3uQ.js → chunk-K5T4RW27-DIKxqyYw.js} +1 -1
  71. package/payload/server/public/assets/{chunk-KGLVRYIC-SFFC6ZC-.js → chunk-KGLVRYIC-CiL4YVLo.js} +1 -1
  72. package/payload/server/public/assets/{chunk-LIHQZDEY-DbOLEP4R.js → chunk-LIHQZDEY-ejKezVlD.js} +1 -1
  73. package/payload/server/public/assets/{chunk-ORNJ4GCN-VB963bkN.js → chunk-ORNJ4GCN-Cc0vqc-D.js} +1 -1
  74. package/payload/server/public/assets/{chunk-OYMX7WX6-DWYY1pQa.js → chunk-OYMX7WX6-Drxn1qG0.js} +1 -1
  75. package/payload/server/public/assets/chunk-QZHKN3VN-Dhlh7Pkk.js +1 -0
  76. package/payload/server/public/assets/{chunk-U2HBQHQK-DAH1diYP.js → chunk-U2HBQHQK-DnbQIkRP.js} +1 -1
  77. package/payload/server/public/assets/{chunk-X2U36JSP-Dmw9coXz.js → chunk-X2U36JSP-CauTSVWg.js} +1 -1
  78. package/payload/server/public/assets/{chunk-XPW4576I-DaAUON1-.js → chunk-XPW4576I-DZqqB9Zi.js} +1 -1
  79. package/payload/server/public/assets/{chunk-YZCP3GAM-BUcfkEef.js → chunk-YZCP3GAM-BGHo4Li-.js} +1 -1
  80. package/payload/server/public/assets/{chunk-ZZ45TVLE-BLD-vFRO.js → chunk-ZZ45TVLE-DWGJKPd7.js} +1 -1
  81. package/payload/server/public/assets/classDiagram-6PBFFD2Q-D2z_ZV1x.js +1 -0
  82. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BJwJoNEK.js +1 -0
  83. package/payload/server/public/assets/clock-BceBgZP1.js +1 -0
  84. package/payload/server/public/assets/clone-Bn7XXVhr.js +1 -0
  85. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-CoZX0uki.js → cose-bilkent-S5V4N54A-D-95BzXL.js} +1 -1
  86. package/payload/server/public/assets/{dagre-Bmjs8zJA.js → dagre-BZYNBHvT.js} +1 -1
  87. package/payload/server/public/assets/{dagre-KV5264BT-BZCP2wnq.js → dagre-KV5264BT-DyU4HQLQ.js} +1 -1
  88. package/payload/server/public/assets/data-rNLaurgY.js +1 -0
  89. package/payload/server/public/assets/{diagram-5BDNPKRD-8Nt9a4xX.js → diagram-5BDNPKRD-CCttJ9XA.js} +1 -1
  90. package/payload/server/public/assets/{diagram-G4DWMVQ6-vh5tcYqJ.js → diagram-G4DWMVQ6-DvkpgSLO.js} +1 -1
  91. package/payload/server/public/assets/{diagram-MMDJMWI5-DGf--jc8.js → diagram-MMDJMWI5-DHmW5Y9k.js} +1 -1
  92. package/payload/server/public/assets/{diagram-TYMM5635-CsO7TIdw.js → diagram-TYMM5635-C6T4hwzO.js} +1 -1
  93. package/payload/server/public/assets/{dist-cdnE4DqK.js → dist-QvbmK1IP.js} +1 -1
  94. package/payload/server/public/assets/{erDiagram-SMLLAGMA-4a78yV8_.js → erDiagram-SMLLAGMA-5v_o7s3T.js} +1 -1
  95. package/payload/server/public/assets/{file-text-BpLcZKld.js → file-text-RCoSeOpD.js} +1 -1
  96. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BoQBXs6t.js → flowDiagram-DWJPFMVM-3UhCDsjt.js} +1 -1
  97. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CvzqwCC8.js → ganttDiagram-T4ZO3ILL-F2zgHIIQ.js} +1 -1
  98. package/payload/server/public/assets/gitGraph-7Q5UKJZL-C-FvNTHZ.js +1 -0
  99. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-D_nBxay_.js → gitGraphDiagram-UUTBAWPF-oQc1N3dT.js} +1 -1
  100. package/payload/server/public/assets/{graph-HB0199x-.js → graph-Dm-YZeNP.js} +12 -12
  101. package/payload/server/public/assets/{graph-labels-Bx19ZYvJ.js → graph-labels-DJV0aIG5.js} +1 -1
  102. package/payload/server/public/assets/{graphlib-D0NdsKJI.js → graphlib-DY4-AT2Q.js} +1 -1
  103. package/payload/server/public/assets/info-OMHHGYJF-BjLPgHAC.js +1 -0
  104. package/payload/server/public/assets/infoDiagram-42DDH7IO-CXNKLTui.js +2 -0
  105. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-auW-s0i0.js → ishikawaDiagram-UXIWVN3A-wJhSOkuw.js} +1 -1
  106. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-3Q6AWK4A.js → journeyDiagram-VCZTEJTY-DgadC6Pz.js} +1 -1
  107. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-B4MPFp98.js → kanban-definition-6JOO6SKY-Bs4nQqXI.js} +1 -1
  108. package/payload/server/public/assets/{line-26MdeG5Z.js → line-Bnmxy1hO.js} +1 -1
  109. package/payload/server/public/assets/{linear-Dq9s_bDO.js → linear-RvwZxFzh.js} +1 -1
  110. package/payload/server/public/assets/{maximize-2-BhR-Ec21.js → maximize-2-DcESsKbu.js} +1 -1
  111. package/payload/server/public/assets/{mermaid-parser.core-vLEpOXgf.js → mermaid-parser.core-DeNV8RtA.js} +2 -2
  112. package/payload/server/public/assets/{mermaid.core-Durk4m6D.js → mermaid.core-BU9IiSCP.js} +3 -3
  113. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DOIg-TyG.js → mindmap-definition-QFDTVHPH-D1PMUxxm.js} +1 -1
  114. package/payload/server/public/assets/operator-Dlkw1sXJ.js +1 -0
  115. package/payload/server/public/assets/packet-4T2RLAQJ-BBAZASfb.js +1 -0
  116. package/payload/server/public/assets/page-Dl-mgQUu.js +32 -0
  117. package/payload/server/public/assets/page-DoyJrk8E.js +1 -0
  118. package/payload/server/public/assets/pie-ZZUOXDRM-CCJUnMeG.js +1 -0
  119. package/payload/server/public/assets/{pieDiagram-DEJITSTG-DtgBHZfi.js → pieDiagram-DEJITSTG-BzdNzoKA.js} +1 -1
  120. package/payload/server/public/assets/{public-DZHPsyKX.js → public-C-UHWk_S.js} +1 -1
  121. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BTc5Qn2y.js → quadrantDiagram-34T5L4WZ-oFr1MJRO.js} +1 -1
  122. package/payload/server/public/assets/radar-PYXPWWZC-BsRU8Aep.js +1 -0
  123. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BNgOO5YW.js → requirementDiagram-MS252O5E-C9QBQxDh.js} +1 -1
  124. package/payload/server/public/assets/{rotate-ccw-D9qOBLig.js → rotate-ccw-C1nRSAzP.js} +1 -1
  125. package/payload/server/public/assets/routines-qdAZ0sA4.js +1 -0
  126. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-MyUATmVt.js → sankeyDiagram-XADWPNL6-c_y3bvVv.js} +1 -1
  127. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-CBJrF5Vi.js → sequenceDiagram-FGHM5R23-YwlCBPHE.js} +1 -1
  128. package/payload/server/public/assets/skills-B78wr822.js +1 -0
  129. package/payload/server/public/assets/{src-DekKlUCp.js → src-C2WwTWSY.js} +1 -1
  130. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-6wbUjn1Q.js → stateDiagram-FHFEXIEX-BFE3e-FM.js} +1 -1
  131. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CpjB4ykI.js +1 -0
  132. package/payload/server/public/assets/tasks-DbIsS-vW.js +1 -0
  133. package/payload/server/public/assets/{time-entry-format-RkCW7hKu.js → time-entry-format-BhlltPP8.js} +1 -1
  134. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BHjTMCGY.js → timeline-definition-GMOUNBTQ-azqhmRwZ.js} +1 -1
  135. package/payload/server/public/assets/treeView-SZITEDCU-BDzhKA6v.js +1 -0
  136. package/payload/server/public/assets/treemap-W4RFUUIX-epHpdeWa.js +1 -0
  137. package/payload/server/public/assets/{triangle-alert-k8ulav-N.js → triangle-alert-rEVGyIhi.js} +1 -1
  138. package/payload/server/public/assets/{useCopyFeedback-DN1WA5vU.js → useCopyFeedback-DzpXjm9d.js} +1 -1
  139. package/payload/server/public/assets/useSubAccountSwitcher-DVmWZxar.js +9 -0
  140. package/payload/server/public/assets/{useSubAccountSwitcher-fvBunpOC.css → useSubAccountSwitcher-wP8cOzPj.css} +1 -1
  141. package/payload/server/public/assets/{useVoiceRecorder-v--TIxaM.js → useVoiceRecorder-CRRmPjYr.js} +1 -1
  142. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-yo3-cf0U.js → vennDiagram-DHZGUBPP-Da2RfFs8.js} +1 -1
  143. package/payload/server/public/assets/wardley-RL74JXVD-DNSZCrxV.js +1 -0
  144. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DZlyFzrg.js → wardleyDiagram-NUSXRM2D-HdrdBYES.js} +1 -1
  145. package/payload/server/public/assets/{wrench-CKhz8KnQ.js → wrench-oeLti270.js} +1 -1
  146. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-B5HV5h80.js → xychartDiagram-5P7HB3ND-DMk6rTcQ.js} +1 -1
  147. package/payload/server/public/browser.html +5 -5
  148. package/payload/server/public/calendar.html +8 -8
  149. package/payload/server/public/chat.html +14 -15
  150. package/payload/server/public/data.html +12 -12
  151. package/payload/server/public/graph.html +10 -10
  152. package/payload/server/public/index.html +15 -16
  153. package/payload/server/public/operator.html +15 -16
  154. package/payload/server/public/public.html +14 -15
  155. package/payload/server/public/routines.html +7 -7
  156. package/payload/server/public/skills.html +6 -6
  157. package/payload/server/public/tasks.html +7 -7
  158. package/payload/server/server.js +696 -430
  159. package/payload/server/public/assets/AdminShell-Gq8DU_ig.js +0 -2
  160. package/payload/server/public/assets/admin-DLUOixl6.js +0 -1
  161. package/payload/server/public/assets/architecture-YZFGNWBL-BQc779DH.js +0 -1
  162. package/payload/server/public/assets/bot-CrEhKW1l.js +0 -1
  163. package/payload/server/public/assets/calendar-B8ujkn_K.js +0 -1
  164. package/payload/server/public/assets/channel-AqnC3SHu.js +0 -1
  165. package/payload/server/public/assets/chat-lQXd6gsM.js +0 -1
  166. package/payload/server/public/assets/chevron-left-CQ8rcBoO.js +0 -1
  167. package/payload/server/public/assets/chevron-right-CSRSqblN.js +0 -1
  168. package/payload/server/public/assets/chunk-426QAEUC-CO02gU5d.js +0 -1
  169. package/payload/server/public/assets/chunk-QZHKN3VN-BiFMbK8t.js +0 -1
  170. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BdRqzScB.js +0 -1
  171. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-ChPLgHbS.js +0 -1
  172. package/payload/server/public/assets/clock-B7Ba8AZL.js +0 -1
  173. package/payload/server/public/assets/clone-TKtrjWBC.js +0 -1
  174. package/payload/server/public/assets/data-BdlGqjKM.js +0 -1
  175. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DfcaTE9L.js +0 -1
  176. package/payload/server/public/assets/info-OMHHGYJF-CD-u6gw9.js +0 -1
  177. package/payload/server/public/assets/infoDiagram-42DDH7IO-C6gPQCvO.js +0 -2
  178. package/payload/server/public/assets/operator-Bf3hP3qo.js +0 -1
  179. package/payload/server/public/assets/packet-4T2RLAQJ-BaLYeIrU.js +0 -1
  180. package/payload/server/public/assets/page-Bs24tO-C.js +0 -32
  181. package/payload/server/public/assets/page-FnCmAeHc.js +0 -1
  182. package/payload/server/public/assets/pie-ZZUOXDRM-CL-XJtk-.js +0 -1
  183. package/payload/server/public/assets/radar-PYXPWWZC-Cn-g6F_h.js +0 -1
  184. package/payload/server/public/assets/routines-lGiYaMiX.js +0 -1
  185. package/payload/server/public/assets/skills-y-h0P9rC.js +0 -1
  186. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BdMdfBeC.js +0 -1
  187. package/payload/server/public/assets/tasks-Cyc1EfLA.js +0 -1
  188. package/payload/server/public/assets/treeView-SZITEDCU-CmZoOGlC.js +0 -1
  189. package/payload/server/public/assets/treemap-W4RFUUIX-H27WFS-y.js +0 -1
  190. package/payload/server/public/assets/useSubAccountSwitcher-iQGqNJhI.js +0 -9
  191. package/payload/server/public/assets/wardley-RL74JXVD-DNpWIvU4.js +0 -1
  192. /package/payload/server/public/assets/{chunk-CCr-iYLO.js → chunk-CltuBf4Z.js} +0 -0
@@ -146,7 +146,7 @@ var require_dist = __commonJS({
146
146
  Object.defineProperty(exports, "__esModule", { value: true });
147
147
  exports.ACTIVE_CANDIDATE_FLOOR = exports.SAME_SUBJECT_COSINE = void 0;
148
148
  exports.formatStandingRulesBlock = formatStandingRulesBlock2;
149
- exports.resolveOwnerUserId = resolveOwnerUserId2;
149
+ exports.resolveOwnerUserId = resolveOwnerUserId3;
150
150
  exports.queryActiveRuleCandidates = queryActiveRuleCandidates;
151
151
  exports.resolveActiveRules = resolveActiveRules2;
152
152
  exports.activeRuleSet = activeRuleSet;
@@ -159,7 +159,7 @@ var require_dist = __commonJS({
159
159
  return `## Standing rules
160
160
  ${lines.join("\n")}`;
161
161
  }
162
- async function resolveOwnerUserId2(session, accountId) {
162
+ async function resolveOwnerUserId3(session, accountId) {
163
163
  const res = await session.run(`
164
164
  MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
165
165
  RETURN au.userId AS userId
@@ -194,7 +194,7 @@ ${lines.join("\n")}`;
194
194
  async function resolveCandidates(session, accountId) {
195
195
  let ownerUserId;
196
196
  try {
197
- ownerUserId = await resolveOwnerUserId2(session, accountId);
197
+ ownerUserId = await resolveOwnerUserId3(session, accountId);
198
198
  } catch {
199
199
  return { candidates: [], ownerUserId: null, source: "owner-error" };
200
200
  }
@@ -1753,10 +1753,10 @@ var serveStatic = (options = { root: "" }) => {
1753
1753
  };
1754
1754
 
1755
1755
  // server/index.ts
1756
- import { readFileSync as readFileSync46, existsSync as existsSync45, watchFile, readdirSync as readdirSync27, statSync as statSync20 } from "fs";
1756
+ import { readFileSync as readFileSync47, existsSync as existsSync46, watchFile, readdirSync as readdirSync28, statSync as statSync20 } from "fs";
1757
1757
  import { spawn as spawn3 } from "child_process";
1758
1758
  import { createHash as createHash7 } from "crypto";
1759
- import { resolve as resolve43, join as join47, basename as basename14 } from "path";
1759
+ import { resolve as resolve44, join as join47, basename as basename14 } from "path";
1760
1760
  import { homedir as homedir4 } from "os";
1761
1761
  import { monitorEventLoopDelay } from "perf_hooks";
1762
1762
 
@@ -3030,7 +3030,7 @@ var credsSaveQueue = Promise.resolve();
3030
3030
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
3031
3031
  console.error(`${TAG6} draining credential save queue\u2026`);
3032
3032
  const timer = new Promise(
3033
- (resolve44) => setTimeout(() => resolve44("timeout"), timeoutMs)
3033
+ (resolve45) => setTimeout(() => resolve45("timeout"), timeoutMs)
3034
3034
  );
3035
3035
  const result = await Promise.race([
3036
3036
  credsSaveQueue.then(() => "drained"),
@@ -3207,11 +3207,11 @@ async function createWaSocket(opts) {
3207
3207
  return sock;
3208
3208
  }
3209
3209
  async function waitForConnection(sock) {
3210
- return new Promise((resolve44, reject) => {
3210
+ return new Promise((resolve45, reject) => {
3211
3211
  const handler = (update) => {
3212
3212
  if (update.connection === "open") {
3213
3213
  sock.ev.off("connection.update", handler);
3214
- resolve44();
3214
+ resolve45();
3215
3215
  }
3216
3216
  if (update.connection === "close") {
3217
3217
  sock.ev.off("connection.update", handler);
@@ -3319,7 +3319,7 @@ function isTimeoutError(err) {
3319
3319
  return Boolean(err?.__maxyTimeout);
3320
3320
  }
3321
3321
  function withTimeout(label, promise, timeoutMs) {
3322
- return new Promise((resolve44, reject) => {
3322
+ return new Promise((resolve45, reject) => {
3323
3323
  const timer = setTimeout(() => {
3324
3324
  const err = new Error(`${label} timed out after ${timeoutMs}ms`);
3325
3325
  err.__maxyTimeout = true;
@@ -3329,7 +3329,7 @@ function withTimeout(label, promise, timeoutMs) {
3329
3329
  promise.then(
3330
3330
  (value) => {
3331
3331
  clearTimeout(timer);
3332
- resolve44(value);
3332
+ resolve45(value);
3333
3333
  },
3334
3334
  (err) => {
3335
3335
  clearTimeout(timer);
@@ -4394,8 +4394,8 @@ async function persistWhatsAppMessage(input) {
4394
4394
  const { givenName, familyName } = splitName(input.pushName);
4395
4395
  const prev = sessionWriteLocks.get(input.cacheKey);
4396
4396
  let release;
4397
- const mine = new Promise((resolve44) => {
4398
- release = resolve44;
4397
+ const mine = new Promise((resolve45) => {
4398
+ release = resolve45;
4399
4399
  });
4400
4400
  const chained = (prev ?? Promise.resolve()).then(() => mine);
4401
4401
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -6132,11 +6132,11 @@ async function connectWithReconnect(conn) {
6132
6132
  console.error(
6133
6133
  `${TAG17} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
6134
6134
  );
6135
- await new Promise((resolve44) => {
6136
- const timer = setTimeout(resolve44, delay);
6135
+ await new Promise((resolve45) => {
6136
+ const timer = setTimeout(resolve45, delay);
6137
6137
  conn.abortController.signal.addEventListener("abort", () => {
6138
6138
  clearTimeout(timer);
6139
- resolve44();
6139
+ resolve45();
6140
6140
  }, { once: true });
6141
6141
  });
6142
6142
  }
@@ -6144,16 +6144,16 @@ async function connectWithReconnect(conn) {
6144
6144
  }
6145
6145
  }
6146
6146
  function waitForDisconnectEvent(conn) {
6147
- return new Promise((resolve44) => {
6147
+ return new Promise((resolve45) => {
6148
6148
  if (!conn.sock) {
6149
- resolve44();
6149
+ resolve45();
6150
6150
  return;
6151
6151
  }
6152
6152
  const sock = conn.sock;
6153
6153
  const handler = (update) => {
6154
6154
  if (update.connection === "close") {
6155
6155
  sock.ev.off("connection.update", handler);
6156
- resolve44();
6156
+ resolve45();
6157
6157
  }
6158
6158
  };
6159
6159
  sock.ev.on("connection.update", handler);
@@ -6627,8 +6627,8 @@ async function handleInboundMessage(conn, msg) {
6627
6627
  const conversationKey = isGroup ? remoteJid : senderPhone;
6628
6628
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
6629
6629
  let resolvePending;
6630
- const sttPending = new Promise((resolve44) => {
6631
- resolvePending = resolve44;
6630
+ const sttPending = new Promise((resolve45) => {
6631
+ resolvePending = resolve45;
6632
6632
  });
6633
6633
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
6634
6634
  try {
@@ -7017,20 +7017,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
7017
7017
 
7018
7018
  // server/routes/health.ts
7019
7019
  function checkPort(port2, timeoutMs = 500) {
7020
- return new Promise((resolve44) => {
7020
+ return new Promise((resolve45) => {
7021
7021
  const socket = createConnection2(port2, "127.0.0.1");
7022
7022
  socket.setTimeout(timeoutMs);
7023
7023
  socket.once("connect", () => {
7024
7024
  socket.destroy();
7025
- resolve44(true);
7025
+ resolve45(true);
7026
7026
  });
7027
7027
  socket.once("error", () => {
7028
7028
  socket.destroy();
7029
- resolve44(false);
7029
+ resolve45(false);
7030
7030
  });
7031
7031
  socket.once("timeout", () => {
7032
7032
  socket.destroy();
7033
- resolve44(false);
7033
+ resolve45(false);
7034
7034
  });
7035
7035
  });
7036
7036
  }
@@ -7285,8 +7285,8 @@ function webchatTurnTimeoutMs() {
7285
7285
  return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
7286
7286
  }
7287
7287
  function createChatRoutes(deps) {
7288
- const app68 = new Hono();
7289
- app68.post("/", async (c) => {
7288
+ const app70 = new Hono();
7289
+ app70.post("/", async (c) => {
7290
7290
  console.log(`[chat-route] entered route=public method=POST`);
7291
7291
  const contentType = c.req.header("content-type") ?? "";
7292
7292
  const account = resolveAccount();
@@ -7550,7 +7550,7 @@ ${result.result.text}` : result.result.text;
7550
7550
  }
7551
7551
  });
7552
7552
  });
7553
- return app68;
7553
+ return app70;
7554
7554
  }
7555
7555
 
7556
7556
  // app/lib/channel-pty-bridge/admin-session-id.ts
@@ -7584,8 +7584,8 @@ function isLoopbackAddr(addr) {
7584
7584
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
7585
7585
  }
7586
7586
  function createScheduleInjectRoutes(deps) {
7587
- const app68 = new Hono();
7588
- app68.post("/", async (c) => {
7587
+ const app70 = new Hono();
7588
+ app70.post("/", async (c) => {
7589
7589
  const env = c.env;
7590
7590
  const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
7591
7591
  if (!isLoopbackAddr(remoteAddr)) {
@@ -7686,7 +7686,7 @@ function createScheduleInjectRoutes(deps) {
7686
7686
  console.error(`${TAG20} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
7687
7687
  return c.json({ ok: true }, 200);
7688
7688
  });
7689
- return app68;
7689
+ return app70;
7690
7690
  }
7691
7691
 
7692
7692
  // server/index.ts
@@ -8369,8 +8369,8 @@ async function startLogin(opts) {
8369
8369
  await clearAuth(authDir);
8370
8370
  let resolveCode = null;
8371
8371
  let rejectCode = null;
8372
- const codePromise = new Promise((resolve44, reject) => {
8373
- resolveCode = resolve44;
8372
+ const codePromise = new Promise((resolve45, reject) => {
8373
+ resolveCode = resolve45;
8374
8374
  rejectCode = reject;
8375
8375
  });
8376
8376
  const codeTimer = setTimeout(
@@ -13993,8 +13993,8 @@ async function reapplyLeversViaManager() {
13993
13993
  var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
13994
13994
  var sendSeq = 0;
13995
13995
  function createWebchatRoutes(deps) {
13996
- const app68 = new Hono();
13997
- app68.post("/send", requireAdminSession, async (c) => {
13996
+ const app70 = new Hono();
13997
+ app70.post("/send", requireAdminSession, async (c) => {
13998
13998
  let accountId;
13999
13999
  try {
14000
14000
  accountId = resolvePlatformAccountId();
@@ -14197,7 +14197,7 @@ ${note}` : note;
14197
14197
  if (turnTimer.unref) turnTimer.unref();
14198
14198
  return c.json({ ok: true });
14199
14199
  });
14200
- app68.post("/interrupt", requireAdminSession, async (c) => {
14200
+ app70.post("/interrupt", requireAdminSession, async (c) => {
14201
14201
  const cacheKey = c.get("cacheKey");
14202
14202
  const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
14203
14203
  const primaryUserId = resolvePrimaryAdminUserId();
@@ -14225,7 +14225,7 @@ ${note}` : note;
14225
14225
  }
14226
14226
  return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
14227
14227
  });
14228
- app68.post("/settings", requireAdminSession, async (c) => {
14228
+ app70.post("/settings", requireAdminSession, async (c) => {
14229
14229
  const body = await c.req.json().catch(() => null);
14230
14230
  const op = body?.op;
14231
14231
  const value = body?.value;
@@ -14265,7 +14265,7 @@ ${note}` : note;
14265
14265
  console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
14266
14266
  return c.json({ ok: true, settingsApplied });
14267
14267
  });
14268
- app68.get("/session", requireAdminSession, async (c) => {
14268
+ app70.get("/session", requireAdminSession, async (c) => {
14269
14269
  let accountId;
14270
14270
  try {
14271
14271
  accountId = resolvePlatformAccountId();
@@ -14343,7 +14343,7 @@ ${note}` : note;
14343
14343
  const indicators = await fetchComposerIndicators(sessionId);
14344
14344
  return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
14345
14345
  });
14346
- app68.post("/permission-verdict", requireAdminSession, async (c) => {
14346
+ app70.post("/permission-verdict", requireAdminSession, async (c) => {
14347
14347
  const body = await c.req.json().catch(() => null);
14348
14348
  const sessionId = body?.sessionId;
14349
14349
  const requestId = body?.request_id;
@@ -14360,7 +14360,7 @@ ${note}` : note;
14360
14360
  const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
14361
14361
  return c.json({ ok });
14362
14362
  });
14363
- return app68;
14363
+ return app70;
14364
14364
  }
14365
14365
 
14366
14366
  // server/routes/webchat-greeting.ts
@@ -15716,15 +15716,15 @@ function operatorRoleFor(config, userId) {
15716
15716
  async function buildAccountOptionList(accounts, userId) {
15717
15717
  const houseAccount = accounts.find((a) => a.config.role === "house");
15718
15718
  console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
15719
- const resolve44 = async (a) => {
15719
+ const resolve45 = async (a) => {
15720
15720
  const businessName = await fetchAccountName(a.accountId) || void 0;
15721
15721
  return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
15722
15722
  };
15723
15723
  const houseOptions = await Promise.all(
15724
- accounts.filter((a) => a.config.role === "house").map(resolve44)
15724
+ accounts.filter((a) => a.config.role === "house").map(resolve45)
15725
15725
  );
15726
15726
  const nonHouseOptions = await Promise.all(
15727
- accounts.filter((a) => a.config.role !== "house").map(resolve44)
15727
+ accounts.filter((a) => a.config.role !== "house").map(resolve45)
15728
15728
  );
15729
15729
  const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
15730
15730
  nonHouseOptions.sort((x, y) => {
@@ -16169,13 +16169,21 @@ var session_upload_default = app17;
16169
16169
  // server/routes/admin/agents.ts
16170
16170
  import { resolve as resolve22 } from "path";
16171
16171
  import { readdirSync as readdirSync21, readFileSync as readFileSync32, existsSync as existsSync30, rmSync as rmSync2 } from "fs";
16172
+ var SLUG_UNSAFE = (s) => s.includes("/") || s.includes("..") || s.includes("\\");
16173
+ var OWNED_DOCS = [
16174
+ { file: "IDENTITY.md", key: "identity" },
16175
+ { file: "SOUL.md", key: "soul" },
16176
+ { file: "KNOWLEDGE.md", key: "knowledge" },
16177
+ { file: "KNOWLEDGE-SUMMARY.md", key: "knowledgeSummary" }
16178
+ ];
16172
16179
  var app18 = new Hono();
16173
16180
  app18.get("/", (c) => {
16174
16181
  const account = resolveAccount();
16175
- if (!account) return c.json({ agents: [] });
16182
+ if (!account) return c.json({ agents: [], skipped: 0 });
16176
16183
  const agentsDir = resolve22(account.accountDir, "agents");
16177
- if (!existsSync30(agentsDir)) return c.json({ agents: [] });
16184
+ if (!existsSync30(agentsDir)) return c.json({ agents: [], skipped: 0 });
16178
16185
  const agents = [];
16186
+ let skipped = 0;
16179
16187
  try {
16180
16188
  const entries = readdirSync21(agentsDir, { withFileTypes: true });
16181
16189
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
@@ -16191,14 +16199,66 @@ app18.get("/", (c) => {
16191
16199
  status: config.status ?? "unknown"
16192
16200
  });
16193
16201
  } catch {
16202
+ skipped++;
16194
16203
  console.error(`[admin/agents] failed to parse config.json for agent "${entry.name}" \u2014 skipping`);
16195
16204
  }
16196
16205
  }
16197
16206
  } catch (err) {
16198
16207
  console.error(`[admin/agents] failed to scan agents directory: ${err}`);
16199
- return c.json({ agents: [] });
16208
+ return c.json({ agents: [], skipped: 0 });
16200
16209
  }
16201
- return c.json({ agents });
16210
+ console.log(`[admin/agents] op=list agents=${agents.length} skipped=${skipped}`);
16211
+ return c.json({ agents, skipped });
16212
+ });
16213
+ app18.get("/:slug", (c) => {
16214
+ const slug = c.req.param("slug");
16215
+ const account = resolveAccount();
16216
+ if (!account) return c.json({ error: "No account resolved" }, 400);
16217
+ if (SLUG_UNSAFE(slug)) return c.json({ error: "Invalid agent slug" }, 400);
16218
+ const agentDir = resolve22(account.accountDir, "agents", slug);
16219
+ const configPath2 = resolve22(agentDir, "config.json");
16220
+ if (!existsSync30(configPath2)) return c.json({ error: "Agent not found" }, 404);
16221
+ let config;
16222
+ try {
16223
+ config = JSON.parse(readFileSync32(configPath2, "utf-8"));
16224
+ } catch {
16225
+ console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
16226
+ return c.json({ error: "Agent config unreadable" }, 500);
16227
+ }
16228
+ const docs = {};
16229
+ const present = {};
16230
+ for (const { file, key } of OWNED_DOCS) {
16231
+ const p = resolve22(agentDir, file);
16232
+ try {
16233
+ if (existsSync30(p)) {
16234
+ docs[key] = readFileSync32(p, "utf-8");
16235
+ present[key] = true;
16236
+ } else {
16237
+ docs[key] = "";
16238
+ present[key] = false;
16239
+ }
16240
+ } catch {
16241
+ console.error(`[admin/agents] op=detail slug=${slug} doc=${file} error="read failed, treating as absent"`);
16242
+ docs[key] = "";
16243
+ present[key] = false;
16244
+ }
16245
+ }
16246
+ const found = Object.keys(present).filter((k) => present[k]);
16247
+ console.log(`[admin/agents] op=detail slug=${slug} present=${found.join(",") || "none"}`);
16248
+ return c.json({
16249
+ agent: {
16250
+ slug,
16251
+ displayName: config.displayName ?? slug,
16252
+ status: config.status ?? "unknown",
16253
+ model: config.model ?? null,
16254
+ knowledgeKeywords: config.knowledgeKeywords ?? [],
16255
+ identity: docs.identity,
16256
+ soul: docs.soul,
16257
+ knowledge: docs.knowledge,
16258
+ knowledgeSummary: docs.knowledgeSummary,
16259
+ present
16260
+ }
16261
+ });
16202
16262
  });
16203
16263
  app18.delete("/:slug", async (c) => {
16204
16264
  const slug = c.req.param("slug");
@@ -16207,7 +16267,7 @@ app18.delete("/:slug", async (c) => {
16207
16267
  if (slug === "admin") {
16208
16268
  return c.json({ error: "Cannot delete the admin agent" }, 403);
16209
16269
  }
16210
- if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
16270
+ if (SLUG_UNSAFE(slug)) {
16211
16271
  return c.json({ error: "Invalid agent slug" }, 400);
16212
16272
  }
16213
16273
  const agentDir = resolve22(account.accountDir, "agents", slug);
@@ -16237,7 +16297,7 @@ app18.post("/:slug/project", async (c) => {
16237
16297
  if (slug === "admin") {
16238
16298
  return c.json({ error: "Cannot project the admin agent" }, 403);
16239
16299
  }
16240
- if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
16300
+ if (SLUG_UNSAFE(slug)) {
16241
16301
  return c.json({ error: "Invalid agent slug" }, 400);
16242
16302
  }
16243
16303
  const agentDir = resolve22(account.accountDir, "agents", slug);
@@ -17496,18 +17556,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
17496
17556
  ]);
17497
17557
  var app22 = new Hono();
17498
17558
  app22.post("/", async (c) => {
17499
- const TAG56 = "[admin:events]";
17559
+ const TAG58 = "[admin:events]";
17500
17560
  let body;
17501
17561
  try {
17502
17562
  body = await c.req.json();
17503
17563
  } catch (err) {
17504
17564
  const detail = err instanceof Error ? err.message : String(err);
17505
- console.error(`${TAG56} reject reason=body-not-json detail=${detail}`);
17565
+ console.error(`${TAG58} reject reason=body-not-json detail=${detail}`);
17506
17566
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
17507
17567
  }
17508
17568
  const event = typeof body.event === "string" ? body.event : "";
17509
17569
  if (!ALLOWED_EVENTS.has(event)) {
17510
- console.error(`${TAG56} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
17570
+ console.error(`${TAG58} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
17511
17571
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
17512
17572
  }
17513
17573
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
@@ -24162,12 +24222,19 @@ app50.get("/", requireAdminSession, async (c) => {
24162
24222
  // it: a second ASSIGNED_TO edge would fan the row out, duplicating
24163
24223
  // rowKey and double-counting the assignee.
24164
24224
  WITH t, openTe, head(collect(a)) AS assignee
24225
+ // The AdminUser carries no name property (Task 1570); the name lives on
24226
+ // its owned Person. Resolve it here so an assigned task shows a real name
24227
+ // rather than a userId slice (Task 1982).
24228
+ OPTIONAL MATCH (assignee)-[:OWNS]->(ap:Person) WHERE ap.accountId = assignee.accountId
24229
+ WITH t, openTe, assignee, head(collect(ap)) AS assigneePerson
24165
24230
  RETURN t.taskId AS taskId, elementId(t) AS rowKey, t.name AS name, t.clientName AS clientName,
24166
24231
  t.propertyAddress AS propertyAddress, t.fee AS fee, t.status AS status,
24167
24232
  coalesce(t.secondsLogged, 0) AS secondsLogged,
24168
24233
  openTe.startedAt AS runningStartedAt,
24169
24234
  t.createdAt AS createdAt,
24170
- assignee.userId AS assigneeUserId, assignee.name AS assigneeName
24235
+ assignee.userId AS assigneeUserId,
24236
+ assigneePerson.givenName AS assigneeGivenName,
24237
+ assigneePerson.familyName AS assigneeFamilyName
24171
24238
  ORDER BY t.createdAt DESC`,
24172
24239
  { accountId }
24173
24240
  );
@@ -24192,6 +24259,9 @@ app50.get("/", requireAdminSession, async (c) => {
24192
24259
  if (createdAt === null) missingCreatedAt++;
24193
24260
  const assigneeUserId = rec.get("assigneeUserId") ?? null;
24194
24261
  if (assigneeUserId !== null) assigned++;
24262
+ const assigneeGivenName = rec.get("assigneeGivenName") ?? null;
24263
+ const assigneeFamilyName = rec.get("assigneeFamilyName") ?? null;
24264
+ const assigneeName = assigneeGivenName && assigneeGivenName.trim().length > 0 ? assigneeFamilyName && assigneeFamilyName.trim().length > 0 ? `${assigneeGivenName.trim()} ${assigneeFamilyName.trim()}` : assigneeGivenName.trim() : null;
24195
24265
  const row = {
24196
24266
  taskId,
24197
24267
  rowKey: rec.get("rowKey"),
@@ -24205,7 +24275,7 @@ app50.get("/", requireAdminSession, async (c) => {
24205
24275
  runningStartedAt,
24206
24276
  createdAt,
24207
24277
  assigneeUserId,
24208
- assigneeName: rec.get("assigneeName") ?? null
24278
+ assigneeName
24209
24279
  };
24210
24280
  if (COMPLETED.has(status)) completed.push(row);
24211
24281
  else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
@@ -24487,10 +24557,199 @@ app54.post("/", requireAdminSession, async (c) => {
24487
24557
  });
24488
24558
  var task_time_adjust_default = app54;
24489
24559
 
24490
- // server/routes/admin/activity.ts
24491
- import { readdirSync as readdirSync25 } from "fs";
24560
+ // app/lib/admin-roster.ts
24561
+ import { existsSync as existsSync39, readdirSync as readdirSync25, readFileSync as readFileSync40 } from "fs";
24562
+ import { resolve as resolve33 } from "path";
24563
+ function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
24564
+ let entries;
24565
+ try {
24566
+ entries = readdirSync25(accountsDir);
24567
+ } catch {
24568
+ return [];
24569
+ }
24570
+ for (const entry of entries) {
24571
+ const cfgPath = resolve33(accountsDir, entry, "account.json");
24572
+ if (!existsSync39(cfgPath)) continue;
24573
+ try {
24574
+ const cfg = JSON.parse(readFileSync40(cfgPath, "utf-8"));
24575
+ if (cfg.role !== "house") continue;
24576
+ if (!Array.isArray(cfg.admins)) return [];
24577
+ return cfg.admins.map(
24578
+ (a) => a && typeof a === "object" && typeof a.userId === "string" ? a.userId : null
24579
+ ).filter((u) => u !== null && u.length > 0);
24580
+ } catch {
24581
+ }
24582
+ }
24583
+ return [];
24584
+ }
24585
+ async function resolveOwnerUserId2(accountId) {
24586
+ const session = getSession();
24587
+ try {
24588
+ const r = await session.run(
24589
+ `MATCH (au:AdminUser {accountId: $accountId, role: 'owner'})
24590
+ RETURN au.userId AS userId ORDER BY au.createdAt ASC LIMIT 1`,
24591
+ { accountId }
24592
+ );
24593
+ return r.records.length > 0 ? r.records[0].get("userId") ?? null : null;
24594
+ } finally {
24595
+ await session.close();
24596
+ }
24597
+ }
24598
+ async function resolveAllowedAssigneeIds(accountId, accountsDir = ACCOUNTS_DIR) {
24599
+ const houseIds = readHouseAdminUserIds(accountsDir);
24600
+ const ownerId = await resolveOwnerUserId2(accountId);
24601
+ const ids = new Set(houseIds);
24602
+ if (ownerId) ids.add(ownerId);
24603
+ return { ids, ownerId, houseIds };
24604
+ }
24605
+ async function resolveAssignableAdmins(accountId, accountsDir = ACCOUNTS_DIR) {
24606
+ const { ownerId, houseIds } = await resolveAllowedAssigneeIds(accountId, accountsDir);
24607
+ const candidates = Array.from(/* @__PURE__ */ new Set([...ownerId ? [ownerId] : [], ...houseIds]));
24608
+ if (candidates.length === 0) return [];
24609
+ const session = getSession();
24610
+ try {
24611
+ const r = await session.run(
24612
+ `UNWIND $userIds AS uid
24613
+ MATCH (au:AdminUser {userId: uid})
24614
+ OPTIONAL MATCH (au)-[:OWNS]->(p:Person) WHERE p.accountId = au.accountId
24615
+ RETURN au.userId AS userId, p.givenName AS givenName, p.familyName AS familyName`,
24616
+ { userIds: candidates }
24617
+ );
24618
+ const present = /* @__PURE__ */ new Set();
24619
+ const out = [];
24620
+ for (const rec of r.records) {
24621
+ const userId = rec.get("userId");
24622
+ present.add(userId);
24623
+ const given = rec.get("givenName") ?? null;
24624
+ const family = rec.get("familyName") ?? null;
24625
+ const name = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
24626
+ out.push({ userId, name, kind: userId === ownerId ? "owner" : "house-admin" });
24627
+ }
24628
+ const dropped = candidates.filter((u) => !present.has(u));
24629
+ if (dropped.length > 0) {
24630
+ console.error(
24631
+ `[admin-roster] op=roster account=${accountId} dropped-no-adminuser=${dropped.length} ids=${dropped.map((u) => u.slice(0, 8)).join(",")}`
24632
+ );
24633
+ }
24634
+ out.sort((a, b) => {
24635
+ if (a.kind !== b.kind) return a.kind === "owner" ? -1 : 1;
24636
+ return (a.name ?? a.userId).localeCompare(b.name ?? b.userId);
24637
+ });
24638
+ return out;
24639
+ } finally {
24640
+ await session.close();
24641
+ }
24642
+ }
24643
+
24644
+ // server/routes/admin/task-assign.ts
24645
+ var TAG44 = "[task-assign]";
24492
24646
  var app55 = new Hono();
24493
- var TAG44 = "[activity]";
24647
+ app55.post("/", requireAdminSession, async (c) => {
24648
+ const cacheKey = c.var.cacheKey;
24649
+ const accountId = getAccountIdForSession(cacheKey);
24650
+ if (!accountId) return c.json({ error: "Account not found for session" }, 401);
24651
+ let body;
24652
+ try {
24653
+ body = await c.req.json();
24654
+ } catch {
24655
+ return c.json({ error: "invalid-json" }, 400);
24656
+ }
24657
+ const taskId = typeof body.taskId === "string" ? body.taskId : "";
24658
+ if (!taskId) {
24659
+ const reason = body.taskId === null ? "null-taskId" : "missing-taskId";
24660
+ console.error(`${TAG44} op=assign rejected reason=${reason} account=${accountId}`);
24661
+ return c.json({ error: "taskId required" }, 400);
24662
+ }
24663
+ const rawAssignee = body.assigneeUserId;
24664
+ if (rawAssignee !== null && rawAssignee !== void 0 && typeof rawAssignee !== "string") {
24665
+ return c.json({ error: "assigneeUserId must be a string or null" }, 400);
24666
+ }
24667
+ const assigneeUserId = typeof rawAssignee === "string" && rawAssignee.length > 0 ? rawAssignee : null;
24668
+ if (assigneeUserId !== null) {
24669
+ const { ids } = await resolveAllowedAssigneeIds(accountId);
24670
+ if (!ids.has(assigneeUserId)) {
24671
+ console.error(
24672
+ `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=not-in-roster`
24673
+ );
24674
+ return c.json({ error: "assignee-not-in-roster" }, 403);
24675
+ }
24676
+ }
24677
+ const now = (/* @__PURE__ */ new Date()).toISOString();
24678
+ const session = getSession();
24679
+ try {
24680
+ const cleared = await session.run(
24681
+ `MATCH (t:Task {taskId: $taskId, accountId: $accountId})
24682
+ OPTIONAL MATCH (t)-[r:ASSIGNED_TO]->(:AdminUser) DELETE r
24683
+ RETURN t.taskId AS taskId`,
24684
+ { taskId, accountId, now }
24685
+ );
24686
+ if (cleared.records.length === 0) {
24687
+ return c.json({ error: "task-not-found" }, 404);
24688
+ }
24689
+ if (assigneeUserId === null) {
24690
+ await session.run(
24691
+ `MATCH (t:Task {taskId: $taskId, accountId: $accountId}) SET t.updatedAt = $now`,
24692
+ { taskId, accountId, now }
24693
+ );
24694
+ console.log(`${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=none assigned=false source=route`);
24695
+ return c.json({ ok: true, assigneeUserId: null, assigneeName: null });
24696
+ }
24697
+ const set = await session.run(
24698
+ `MATCH (t:Task {taskId: $taskId, accountId: $accountId})
24699
+ MATCH (au:AdminUser {userId: $assigneeUserId})
24700
+ MERGE (t)-[:ASSIGNED_TO]->(au)
24701
+ SET t.updatedAt = $now
24702
+ OPTIONAL MATCH (au)-[:OWNS]->(p:Person) WHERE p.accountId = au.accountId
24703
+ RETURN au.userId AS userId, p.givenName AS givenName, p.familyName AS familyName`,
24704
+ { taskId, accountId, assigneeUserId, now }
24705
+ );
24706
+ if (set.records.length === 0) {
24707
+ console.error(
24708
+ `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=false source=route reason=no-adminuser-node`
24709
+ );
24710
+ return c.json({ error: "assignee-no-admin-node" }, 409);
24711
+ }
24712
+ const given = set.records[0].get("givenName") ?? null;
24713
+ const family = set.records[0].get("familyName") ?? null;
24714
+ const assigneeName = given && given.trim().length > 0 ? family && family.trim().length > 0 ? `${given.trim()} ${family.trim()}` : given.trim() : null;
24715
+ console.log(
24716
+ `${TAG44} op=assign taskId=${taskId.slice(0, 8)} assigneeUserId=${assigneeUserId.slice(0, 8)} assigned=true source=route`
24717
+ );
24718
+ return c.json({ ok: true, assigneeUserId, assigneeName });
24719
+ } catch (err) {
24720
+ console.error(`${TAG44} op=assign error="${err instanceof Error ? err.message : String(err)}"`);
24721
+ return c.json({ error: "task-assign-failed" }, 500);
24722
+ } finally {
24723
+ await session.close();
24724
+ }
24725
+ });
24726
+ var task_assign_default = app55;
24727
+
24728
+ // server/routes/admin/admin-users-list.ts
24729
+ var TAG45 = "[admin-users]";
24730
+ var app56 = new Hono();
24731
+ app56.get("/", requireAdminSession, async (c) => {
24732
+ const cacheKey = c.var.cacheKey;
24733
+ const accountId = getAccountIdForSession(cacheKey);
24734
+ if (!accountId) {
24735
+ console.error(`${TAG45} op=list auth-rejected reason="no account for session"`);
24736
+ return c.json({ error: "Account not found for session" }, 401);
24737
+ }
24738
+ try {
24739
+ const users = await resolveAssignableAdmins(accountId);
24740
+ console.log(`${TAG45} op=list account=${accountId} count=${users.length}`);
24741
+ return c.json({ ok: true, users });
24742
+ } catch (err) {
24743
+ console.error(`${TAG45} op=list error="${err instanceof Error ? err.message : String(err)}"`);
24744
+ return c.json({ error: "admin-users-list-failed" }, 500);
24745
+ }
24746
+ });
24747
+ var admin_users_list_default = app56;
24748
+
24749
+ // server/routes/admin/activity.ts
24750
+ import { readdirSync as readdirSync26 } from "fs";
24751
+ var app57 = new Hono();
24752
+ var TAG46 = "[activity]";
24494
24753
  function resolveHouseAccountId(accounts) {
24495
24754
  const houses = accounts.filter((a) => a.config.role === "house");
24496
24755
  if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
@@ -24504,14 +24763,14 @@ function requestToken() {
24504
24763
  var short = (id) => id ? id.slice(0, 8) : "unset";
24505
24764
  function countAccountDirsOnDisk() {
24506
24765
  try {
24507
- return readdirSync25(ACCOUNTS_DIR, { withFileTypes: true }).filter(
24766
+ return readdirSync26(ACCOUNTS_DIR, { withFileTypes: true }).filter(
24508
24767
  (e) => e.isDirectory() && !e.name.startsWith(".")
24509
24768
  ).length;
24510
24769
  } catch {
24511
24770
  return null;
24512
24771
  }
24513
24772
  }
24514
- app55.get("/", requireAdminSession, async (c) => {
24773
+ app57.get("/", requireAdminSession, async (c) => {
24515
24774
  const req = requestToken();
24516
24775
  const cacheKey = c.var.cacheKey;
24517
24776
  const caller2 = getAccountIdForSession(cacheKey) ?? null;
@@ -24519,19 +24778,19 @@ app55.get("/", requireAdminSession, async (c) => {
24519
24778
  const house = resolveHouseAccountId(valid);
24520
24779
  const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
24521
24780
  console.log(
24522
- `${TAG44} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
24781
+ `${TAG46} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
24523
24782
  );
24524
24783
  if (!isHouse) {
24525
24784
  const reason = house.accountId === null ? house.reason : "not-house";
24526
24785
  console.error(
24527
- `${TAG44} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
24786
+ `${TAG46} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
24528
24787
  );
24529
24788
  return c.json({ error: "house-only" }, 403);
24530
24789
  }
24531
- console.log(`${TAG44} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
24790
+ console.log(`${TAG46} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
24532
24791
  const onDisk = countAccountDirsOnDisk();
24533
24792
  console.log(
24534
- `${TAG44} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
24793
+ `${TAG46} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
24535
24794
  );
24536
24795
  const start = Date.now();
24537
24796
  let res;
@@ -24547,17 +24806,17 @@ app55.get("/", requireAdminSession, async (c) => {
24547
24806
  });
24548
24807
  } catch (err) {
24549
24808
  console.error(
24550
- `${TAG44} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
24809
+ `${TAG46} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
24551
24810
  );
24552
24811
  return c.json({ error: "manager-unreachable" }, 502);
24553
24812
  }
24554
24813
  if (res.status !== 200) {
24555
- console.error(`${TAG44} op=manager-fail req=${req} reason=status status=${res.status}`);
24814
+ console.error(`${TAG46} op=manager-fail req=${req} reason=status status=${res.status}`);
24556
24815
  return c.json({ error: `manager-status-${res.status}` }, 502);
24557
24816
  }
24558
24817
  const body = await res.json().catch(() => null);
24559
24818
  if (!body || !Array.isArray(body.rows)) {
24560
- console.error(`${TAG44} op=manager-fail req=${req} reason=bad-json`);
24819
+ console.error(`${TAG46} op=manager-fail req=${req} reason=bad-json`);
24561
24820
  return c.json({ error: "manager-bad-json" }, 502);
24562
24821
  }
24563
24822
  const rows = body.rows;
@@ -24568,10 +24827,10 @@ app55.get("/", requireAdminSession, async (c) => {
24568
24827
  const ageNull = rows.filter((r) => r.ageMs === null).length;
24569
24828
  const sidecarNull = rows.filter((r) => r.sidecarMissing).length;
24570
24829
  console.log(
24571
- `${TAG44} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
24830
+ `${TAG46} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"} rows=${rows.length} ageNull=${ageNull} sidecarNull=${sidecarNull}`
24572
24831
  );
24573
24832
  console.log(
24574
- `${TAG44} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
24833
+ `${TAG46} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
24575
24834
  );
24576
24835
  const names = {};
24577
24836
  await Promise.all(
@@ -24590,7 +24849,7 @@ app55.get("/", requireAdminSession, async (c) => {
24590
24849
  return acc;
24591
24850
  }, {});
24592
24851
  console.log(
24593
- `${TAG44} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
24852
+ `${TAG46} op=loops req=${req} armed=${armed2} rendered=${loopRows.length} procPct=${cpu.processPct?.toFixed(1) ?? "null"} attributedPct=${cpu.attributedPct?.toFixed(1) ?? "null"} ` + Object.entries(byState).map(([s, n]) => `${s}=${n}`).join(" ")
24594
24853
  );
24595
24854
  return c.json({
24596
24855
  rows,
@@ -24620,63 +24879,65 @@ app55.get("/", requireAdminSession, async (c) => {
24620
24879
  }
24621
24880
  });
24622
24881
  });
24623
- var activity_default = app55;
24882
+ var activity_default = app57;
24624
24883
 
24625
24884
  // server/routes/admin/index.ts
24626
- var app56 = new Hono();
24627
- app56.route("/session", session_default);
24628
- app56.route("/accounts", accounts_default);
24629
- app56.route("/logs", logs_default);
24630
- app56.route("/claude-info", claude_info_default);
24631
- app56.route("/attachment", attachment_default);
24632
- app56.route("/session-upload", session_upload_default);
24633
- app56.route("/agents", agents_default);
24634
- app56.route("/sessions", sessions_default);
24635
- app56.route("/claude-sessions", claude_sessions_default);
24636
- app56.route("/log-ingest", log_ingest_default);
24637
- app56.route("/events", events_default);
24638
- app56.route("/files", files_default);
24639
- app56.route("/graph-search", graph_search_default);
24640
- app56.route("/graph-subgraph", graph_subgraph_default);
24641
- app56.route("/graph-delete", graph_delete_default);
24642
- app56.route("/graph-restore", graph_restore_default);
24643
- app56.route("/graph-labels-in-graph", graph_labels_in_graph_default);
24644
- app56.route("/graph-default-view", graph_default_view_default);
24645
- app56.route("/sidebar-artefacts", sidebar_artefacts_default);
24646
- app56.route("/sidebar-sessions", sidebar_sessions_default);
24647
- app56.route("/session-delete", session_delete_default);
24648
- app56.route("/session-stop", session_stop_default);
24649
- app56.route("/session-archive", session_archive_default);
24650
- app56.route("/session-rename", session_rename_default);
24651
- app56.route("/session-usage", session_usage_default);
24652
- app56.route("/browser", browser_default);
24653
- app56.route("/session-rc-spawn", session_rc_spawn_default);
24654
- app56.route("/session-reseat", session_reseat_default);
24655
- app56.route("/system-stats", system_stats_default);
24656
- app56.route("/health-brand", health_default2);
24657
- app56.route("/linkedin-ingest", linkedin_ingest_default);
24658
- app56.route("/post-turn-context", post_turn_context_default);
24659
- app56.route("/public-session-context", public_session_context_default);
24660
- app56.route("/public-session-exit", public_session_exit_default);
24661
- app56.route("/access-session-evict", access_session_evict_default);
24662
- app56.route("/enrol-person", enrol_person_default);
24663
- app56.route("/calendar", calendar_default);
24664
- app56.route("/routines", routines_default);
24665
- app56.route("/skills", skills_default);
24666
- app56.route("/tasks-list", tasks_list_default);
24667
- app56.route("/task-timer-start", task_timer_start_default);
24668
- app56.route("/task-timer-stop", task_timer_stop_default);
24669
- app56.route("/task-complete", task_complete_default);
24670
- app56.route("/task-time-adjust", task_time_adjust_default);
24671
- app56.route("/activity", activity_default);
24672
- var admin_default = app56;
24885
+ var app58 = new Hono();
24886
+ app58.route("/session", session_default);
24887
+ app58.route("/accounts", accounts_default);
24888
+ app58.route("/logs", logs_default);
24889
+ app58.route("/claude-info", claude_info_default);
24890
+ app58.route("/attachment", attachment_default);
24891
+ app58.route("/session-upload", session_upload_default);
24892
+ app58.route("/agents", agents_default);
24893
+ app58.route("/sessions", sessions_default);
24894
+ app58.route("/claude-sessions", claude_sessions_default);
24895
+ app58.route("/log-ingest", log_ingest_default);
24896
+ app58.route("/events", events_default);
24897
+ app58.route("/files", files_default);
24898
+ app58.route("/graph-search", graph_search_default);
24899
+ app58.route("/graph-subgraph", graph_subgraph_default);
24900
+ app58.route("/graph-delete", graph_delete_default);
24901
+ app58.route("/graph-restore", graph_restore_default);
24902
+ app58.route("/graph-labels-in-graph", graph_labels_in_graph_default);
24903
+ app58.route("/graph-default-view", graph_default_view_default);
24904
+ app58.route("/sidebar-artefacts", sidebar_artefacts_default);
24905
+ app58.route("/sidebar-sessions", sidebar_sessions_default);
24906
+ app58.route("/session-delete", session_delete_default);
24907
+ app58.route("/session-stop", session_stop_default);
24908
+ app58.route("/session-archive", session_archive_default);
24909
+ app58.route("/session-rename", session_rename_default);
24910
+ app58.route("/session-usage", session_usage_default);
24911
+ app58.route("/browser", browser_default);
24912
+ app58.route("/session-rc-spawn", session_rc_spawn_default);
24913
+ app58.route("/session-reseat", session_reseat_default);
24914
+ app58.route("/system-stats", system_stats_default);
24915
+ app58.route("/health-brand", health_default2);
24916
+ app58.route("/linkedin-ingest", linkedin_ingest_default);
24917
+ app58.route("/post-turn-context", post_turn_context_default);
24918
+ app58.route("/public-session-context", public_session_context_default);
24919
+ app58.route("/public-session-exit", public_session_exit_default);
24920
+ app58.route("/access-session-evict", access_session_evict_default);
24921
+ app58.route("/enrol-person", enrol_person_default);
24922
+ app58.route("/calendar", calendar_default);
24923
+ app58.route("/routines", routines_default);
24924
+ app58.route("/skills", skills_default);
24925
+ app58.route("/tasks-list", tasks_list_default);
24926
+ app58.route("/task-timer-start", task_timer_start_default);
24927
+ app58.route("/task-timer-stop", task_timer_stop_default);
24928
+ app58.route("/task-complete", task_complete_default);
24929
+ app58.route("/task-time-adjust", task_time_adjust_default);
24930
+ app58.route("/task-assign", task_assign_default);
24931
+ app58.route("/admin-users-list", admin_users_list_default);
24932
+ app58.route("/activity", activity_default);
24933
+ var admin_default = app58;
24673
24934
 
24674
24935
  // server/routes/access/verify-token.ts
24675
- var TAG45 = "[access-verify]";
24936
+ var TAG47 = "[access-verify]";
24676
24937
  var MINT_TAG = "[access-session-mint]";
24677
24938
  var COOKIE_NAME = "__access_session";
24678
- var app57 = new Hono();
24679
- app57.post("/", async (c) => {
24939
+ var app59 = new Hono();
24940
+ app59.post("/", async (c) => {
24680
24941
  const ip = c.var.clientIp || "unknown";
24681
24942
  let body;
24682
24943
  try {
@@ -24691,39 +24952,39 @@ app57.post("/", async (c) => {
24691
24952
  }
24692
24953
  const rateMsg = checkAccessRateLimit(ip, agentSlug);
24693
24954
  if (rateMsg) {
24694
- console.error(`${TAG45} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
24955
+ console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
24695
24956
  return c.json({ error: rateMsg }, 429);
24696
24957
  }
24697
24958
  const grant = await findGrantByMagicToken(token);
24698
24959
  if (!grant) {
24699
24960
  recordAccessFailedAttempt(ip, agentSlug);
24700
- console.error(`${TAG45} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
24961
+ console.error(`${TAG47} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
24701
24962
  return c.json({ error: "invalid-or-expired-link" }, 401);
24702
24963
  }
24703
24964
  if (grant.agentSlug !== agentSlug) {
24704
24965
  recordAccessFailedAttempt(ip, agentSlug);
24705
24966
  console.error(
24706
- `${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
24967
+ `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
24707
24968
  );
24708
24969
  return c.json({ error: "invalid-or-expired-link" }, 401);
24709
24970
  }
24710
24971
  if (grant.status === "expired" || grant.status === "revoked") {
24711
24972
  recordAccessFailedAttempt(ip, agentSlug);
24712
24973
  console.error(
24713
- `${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
24974
+ `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
24714
24975
  );
24715
24976
  return c.json({ error: "access-no-longer-valid" }, 401);
24716
24977
  }
24717
24978
  if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
24718
24979
  recordAccessFailedAttempt(ip, agentSlug);
24719
24980
  console.error(
24720
- `${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
24981
+ `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
24721
24982
  );
24722
24983
  return c.json({ error: "access-no-longer-valid" }, 401);
24723
24984
  }
24724
24985
  if (!grant.sliceToken) {
24725
24986
  console.error(
24726
- `${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
24987
+ `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
24727
24988
  );
24728
24989
  return c.json({ error: "grant-misconfigured" }, 500);
24729
24990
  }
@@ -24739,12 +25000,12 @@ app57.post("/", async (c) => {
24739
25000
  await consumeMagicTokenAndActivate(grant.grantId);
24740
25001
  } catch (err) {
24741
25002
  console.error(
24742
- `${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
25003
+ `${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
24743
25004
  );
24744
25005
  return c.json({ error: "verification-failed" }, 500);
24745
25006
  }
24746
25007
  clearAccessRateLimit(ip, agentSlug);
24747
- console.log(`${TAG45} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
25008
+ console.log(`${TAG47} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
24748
25009
  console.log(
24749
25010
  `${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
24750
25011
  );
@@ -24758,13 +25019,13 @@ app57.post("/", async (c) => {
24758
25019
  displayName: grant.displayName
24759
25020
  });
24760
25021
  });
24761
- var verify_token_default = app57;
25022
+ var verify_token_default = app59;
24762
25023
 
24763
25024
  // app/lib/access-email.ts
24764
25025
  import { spawn as spawn2 } from "child_process";
24765
- import { resolve as resolve33 } from "path";
24766
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve33(process.cwd(), "..");
24767
- var SEND_SCRIPT = resolve33(
25026
+ import { resolve as resolve34 } from "path";
25027
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve34(process.cwd(), "..");
25028
+ var SEND_SCRIPT = resolve34(
24768
25029
  PLATFORM_ROOT7,
24769
25030
  "plugins",
24770
25031
  "email",
@@ -24820,10 +25081,10 @@ async function sendMagicLinkEmail(payload) {
24820
25081
  }
24821
25082
 
24822
25083
  // server/routes/access/request-magic-link.ts
24823
- var TAG46 = "[access-request-link]";
24824
- var app58 = new Hono();
25084
+ var TAG48 = "[access-request-link]";
25085
+ var app60 = new Hono();
24825
25086
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
24826
- app58.post("/", async (c) => {
25087
+ app60.post("/", async (c) => {
24827
25088
  let body;
24828
25089
  try {
24829
25090
  body = await c.req.json();
@@ -24837,18 +25098,18 @@ app58.post("/", async (c) => {
24837
25098
  }
24838
25099
  const rateMsg = checkRequestLinkRateLimit(contactValue);
24839
25100
  if (rateMsg) {
24840
- console.error(`${TAG46} contactValue=${maskContact(contactValue)} result=rate-limited`);
25101
+ console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=rate-limited`);
24841
25102
  return c.json({ error: rateMsg }, 429);
24842
25103
  }
24843
25104
  recordRequestLinkAttempt(contactValue);
24844
25105
  const accountId = process.env.ACCOUNT_ID ?? "";
24845
25106
  if (!accountId) {
24846
- console.error(`${TAG46} contactValue=${maskContact(contactValue)} result=no-account-id`);
25107
+ console.error(`${TAG48} contactValue=${maskContact(contactValue)} result=no-account-id`);
24847
25108
  return c.json({ message: VISITOR_MESSAGE }, 200);
24848
25109
  }
24849
25110
  const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
24850
25111
  if (!grant) {
24851
- console.log(`${TAG46} contactValue=${maskContact(contactValue)} result=notfound`);
25112
+ console.log(`${TAG48} contactValue=${maskContact(contactValue)} result=notfound`);
24852
25113
  return c.json({ message: VISITOR_MESSAGE }, 200);
24853
25114
  }
24854
25115
  let token;
@@ -24856,7 +25117,7 @@ app58.post("/", async (c) => {
24856
25117
  token = await generateNewMagicToken(grant.grantId);
24857
25118
  } catch (err) {
24858
25119
  console.error(
24859
- `${TAG46} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
25120
+ `${TAG48} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
24860
25121
  );
24861
25122
  return c.json({ message: VISITOR_MESSAGE }, 200);
24862
25123
  }
@@ -24888,26 +25149,26 @@ app58.post("/", async (c) => {
24888
25149
  });
24889
25150
  if (!sendResult.ok) {
24890
25151
  console.error(
24891
- `${TAG46} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
25152
+ `${TAG48} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
24892
25153
  );
24893
25154
  return c.json({ message: VISITOR_MESSAGE }, 200);
24894
25155
  }
24895
25156
  console.log(
24896
- `${TAG46} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
25157
+ `${TAG48} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
24897
25158
  );
24898
25159
  return c.json({ message: VISITOR_MESSAGE }, 200);
24899
25160
  });
24900
- var request_magic_link_default = app58;
25161
+ var request_magic_link_default = app60;
24901
25162
 
24902
25163
  // server/routes/access/index.ts
24903
- var app59 = new Hono();
24904
- app59.route("/verify-token", verify_token_default);
24905
- app59.route("/request-magic-link", request_magic_link_default);
24906
- var access_default = app59;
25164
+ var app61 = new Hono();
25165
+ app61.route("/verify-token", verify_token_default);
25166
+ app61.route("/request-magic-link", request_magic_link_default);
25167
+ var access_default = app61;
24907
25168
 
24908
25169
  // server/routes/sites.ts
24909
- import { existsSync as existsSync39, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync17 } from "fs";
24910
- import { resolve as resolve34 } from "path";
25170
+ import { existsSync as existsSync40, readFileSync as readFileSync41, realpathSync as realpathSync8, statSync as statSync17 } from "fs";
25171
+ import { resolve as resolve35 } from "path";
24911
25172
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
24912
25173
  var MIME = {
24913
25174
  ".html": "text/html; charset=utf-8",
@@ -24938,8 +25199,8 @@ function getExt(p) {
24938
25199
  if (idx < p.lastIndexOf("/")) return "";
24939
25200
  return p.slice(idx).toLowerCase();
24940
25201
  }
24941
- var app60 = new Hono();
24942
- app60.get("/:rel{.*}", (c) => {
25202
+ var app62 = new Hono();
25203
+ app62.get("/:rel{.*}", (c) => {
24943
25204
  const reqPath = c.req.path;
24944
25205
  const rawRel = c.req.param("rel") ?? "";
24945
25206
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -24964,15 +25225,15 @@ app60.get("/:rel{.*}", (c) => {
24964
25225
  }
24965
25226
  segments.push(seg);
24966
25227
  }
24967
- const rootDir = resolve34(account.accountDir, "sites");
24968
- let filePath = segments.length === 0 ? rootDir : resolve34(rootDir, ...segments);
25228
+ const rootDir = resolve35(account.accountDir, "sites");
25229
+ let filePath = segments.length === 0 ? rootDir : resolve35(rootDir, ...segments);
24969
25230
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
24970
25231
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24971
25232
  return c.text("Forbidden", 403);
24972
25233
  }
24973
25234
  let stat11;
24974
25235
  try {
24975
- stat11 = existsSync39(filePath) ? statSync17(filePath) : null;
25236
+ stat11 = existsSync40(filePath) ? statSync17(filePath) : null;
24976
25237
  } catch {
24977
25238
  stat11 = null;
24978
25239
  }
@@ -24985,13 +25246,13 @@ app60.get("/:rel{.*}", (c) => {
24985
25246
  return c.redirect(target, 301);
24986
25247
  }
24987
25248
  if (stat11?.isDirectory()) {
24988
- filePath = resolve34(filePath, "index.html");
25249
+ filePath = resolve35(filePath, "index.html");
24989
25250
  }
24990
25251
  if (!filePath.startsWith(rootDir + "/")) {
24991
25252
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24992
25253
  return c.text("Forbidden", 403);
24993
25254
  }
24994
- if (!existsSync39(filePath)) {
25255
+ if (!existsSync40(filePath)) {
24995
25256
  console.error(`[sites] not-found path=${reqPath} status=404`);
24996
25257
  return c.text("Not found", 404);
24997
25258
  }
@@ -25010,7 +25271,7 @@ app60.get("/:rel{.*}", (c) => {
25010
25271
  }
25011
25272
  let body;
25012
25273
  try {
25013
- body = readFileSync40(realPath);
25274
+ body = readFileSync41(realPath);
25014
25275
  } catch (err) {
25015
25276
  const code = err?.code;
25016
25277
  if (code === "EISDIR") {
@@ -25042,11 +25303,11 @@ app60.get("/:rel{.*}", (c) => {
25042
25303
  "X-Content-Type-Options": "nosniff"
25043
25304
  });
25044
25305
  });
25045
- var sites_default = app60;
25306
+ var sites_default = app62;
25046
25307
 
25047
25308
  // app/lib/visitor-token.ts
25048
25309
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
25049
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync14 } from "fs";
25310
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync42, writeFileSync as writeFileSync14 } from "fs";
25050
25311
  import { dirname as dirname14 } from "path";
25051
25312
  var TOKEN_PREFIX = "v1.";
25052
25313
  var SECRET_BYTES = 32;
@@ -25055,7 +25316,7 @@ var cachedSecret = null;
25055
25316
  function getSecret() {
25056
25317
  if (cachedSecret) return cachedSecret;
25057
25318
  try {
25058
- const hex2 = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
25319
+ const hex2 = readFileSync42(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
25059
25320
  if (hex2.length === SECRET_BYTES * 2) {
25060
25321
  cachedSecret = Buffer.from(hex2, "hex");
25061
25322
  return cachedSecret;
@@ -25069,7 +25330,7 @@ function getSecret() {
25069
25330
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
25070
25331
  } catch {
25071
25332
  }
25072
- const hex = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
25333
+ const hex = readFileSync42(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
25073
25334
  cachedSecret = Buffer.from(hex, "hex");
25074
25335
  return cachedSecret;
25075
25336
  }
@@ -25122,7 +25383,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
25122
25383
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
25123
25384
 
25124
25385
  // app/lib/brand-config.ts
25125
- import { existsSync as existsSync40, readFileSync as readFileSync42 } from "fs";
25386
+ import { existsSync as existsSync41, readFileSync as readFileSync43 } from "fs";
25126
25387
  import { join as join43 } from "path";
25127
25388
  var cached2 = null;
25128
25389
  var cachedAttempted = false;
@@ -25132,9 +25393,9 @@ function readBrandConfig() {
25132
25393
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
25133
25394
  if (!platformRoot5) return null;
25134
25395
  const brandPath = join43(platformRoot5, "config", "brand.json");
25135
- if (!existsSync40(brandPath)) return null;
25396
+ if (!existsSync41(brandPath)) return null;
25136
25397
  try {
25137
- cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
25398
+ cached2 = JSON.parse(readFileSync43(brandPath, "utf-8"));
25138
25399
  return cached2;
25139
25400
  } catch {
25140
25401
  return null;
@@ -25142,7 +25403,7 @@ function readBrandConfig() {
25142
25403
  }
25143
25404
 
25144
25405
  // server/routes/visitor-consent.ts
25145
- var app61 = new Hono();
25406
+ var app63 = new Hono();
25146
25407
  var CONSENT_COOKIE_NAME = "mxy_consent";
25147
25408
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
25148
25409
  var DEFAULT_CONSENT_COPY = {
@@ -25187,17 +25448,17 @@ function siteSlugFromReferer(referer) {
25187
25448
  return "";
25188
25449
  }
25189
25450
  }
25190
- app61.options("/consent", (c) => {
25451
+ app63.options("/consent", (c) => {
25191
25452
  const origin = getOrigin(c);
25192
25453
  setCorsHeaders(c, origin);
25193
25454
  return c.body(null, 204);
25194
25455
  });
25195
- app61.options("/brand-config", (c) => {
25456
+ app63.options("/brand-config", (c) => {
25196
25457
  const origin = getOrigin(c);
25197
25458
  setCorsHeaders(c, origin);
25198
25459
  return c.body(null, 204);
25199
25460
  });
25200
- app61.post("/consent", async (c) => {
25461
+ app63.post("/consent", async (c) => {
25201
25462
  const origin = getOrigin(c);
25202
25463
  setCorsHeaders(c, origin);
25203
25464
  let raw;
@@ -25237,7 +25498,7 @@ app61.post("/consent", async (c) => {
25237
25498
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
25238
25499
  return c.body(null, 204);
25239
25500
  });
25240
- app61.get("/brand-config", (c) => {
25501
+ app63.get("/brand-config", (c) => {
25241
25502
  const origin = getOrigin(c);
25242
25503
  setCorsHeaders(c, origin);
25243
25504
  const brand = readBrandConfig();
@@ -25247,7 +25508,7 @@ app61.get("/brand-config", (c) => {
25247
25508
  c.header("Cache-Control", "public, max-age=300");
25248
25509
  return c.json({ consent: { copy, palette } });
25249
25510
  });
25250
- var visitor_consent_default = app61;
25511
+ var visitor_consent_default = app63;
25251
25512
 
25252
25513
  // server/routes/listings.ts
25253
25514
  function getCookie(headerValue, name) {
@@ -25274,8 +25535,8 @@ function appendConsentParams(pageUrl, token) {
25274
25535
  }
25275
25536
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
25276
25537
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
25277
- var app62 = new Hono();
25278
- app62.get("/:slug/click", async (c) => {
25538
+ var app64 = new Hono();
25539
+ app64.get("/:slug/click", async (c) => {
25279
25540
  const slug = c.req.param("slug") ?? "";
25280
25541
  const rawSession = c.req.query("session") ?? "";
25281
25542
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -25339,10 +25600,10 @@ app62.get("/:slug/click", async (c) => {
25339
25600
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
25340
25601
  return c.redirect(redirectUrl, 302);
25341
25602
  });
25342
- var listings_default = app62;
25603
+ var listings_default = app64;
25343
25604
 
25344
25605
  // server/routes/visitor-event.ts
25345
- var app63 = new Hono();
25606
+ var app65 = new Hono();
25346
25607
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
25347
25608
  var buckets = /* @__PURE__ */ new Map();
25348
25609
  var RATE_LIMIT = 60;
@@ -25418,12 +25679,12 @@ function originAllowed(origin, allowlist) {
25418
25679
  return false;
25419
25680
  }
25420
25681
  }
25421
- app63.options("/event", (c) => {
25682
+ app65.options("/event", (c) => {
25422
25683
  const origin = getOrigin2(c);
25423
25684
  setCorsHeaders2(c, origin);
25424
25685
  return c.body(null, 204);
25425
25686
  });
25426
- app63.post("/event", async (c) => {
25687
+ app65.post("/event", async (c) => {
25427
25688
  const origin = getOrigin2(c);
25428
25689
  setCorsHeaders2(c, origin);
25429
25690
  const ua = c.req.header("user-agent") ?? "";
@@ -25628,17 +25889,17 @@ async function writeEvent(opts) {
25628
25889
  );
25629
25890
  }
25630
25891
  }
25631
- var visitor_event_default = app63;
25892
+ var visitor_event_default = app65;
25632
25893
 
25633
25894
  // server/routes/session.ts
25634
- import { resolve as resolve35 } from "path";
25635
- import { existsSync as existsSync41, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
25895
+ import { resolve as resolve36 } from "path";
25896
+ import { existsSync as existsSync42, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
25636
25897
  var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
25637
25898
  function writeBrandingCache(accountId, agentSlug, branding) {
25638
25899
  try {
25639
- const cacheDir = resolve35(MAXY_DIR, "branding-cache", accountId);
25900
+ const cacheDir = resolve36(MAXY_DIR, "branding-cache", accountId);
25640
25901
  mkdirSync9(cacheDir, { recursive: true });
25641
- writeFileSync15(resolve35(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25902
+ writeFileSync15(resolve36(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25642
25903
  } catch (err) {
25643
25904
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
25644
25905
  }
@@ -25674,8 +25935,8 @@ function withVisitorCookie(response, visitorId) {
25674
25935
  headers
25675
25936
  });
25676
25937
  }
25677
- var app64 = new Hono();
25678
- app64.post("/", async (c) => {
25938
+ var app66 = new Hono();
25939
+ app66.post("/", async (c) => {
25679
25940
  let body;
25680
25941
  try {
25681
25942
  body = await c.req.json();
@@ -25715,8 +25976,8 @@ app64.post("/", async (c) => {
25715
25976
  }
25716
25977
  let agentConfig = null;
25717
25978
  if (account) {
25718
- const agentDir = resolve35(account.accountDir, "agents", agentSlug);
25719
- if (!existsSync41(agentDir) || !existsSync41(resolve35(agentDir, "config.json"))) {
25979
+ const agentDir = resolve36(account.accountDir, "agents", agentSlug);
25980
+ if (!existsSync42(agentDir) || !existsSync42(resolve36(agentDir, "config.json"))) {
25720
25981
  return c.json({ error: "Agent not found" }, 404);
25721
25982
  }
25722
25983
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -25822,7 +26083,7 @@ app64.post("/", async (c) => {
25822
26083
  newVisitorId
25823
26084
  );
25824
26085
  });
25825
- var session_default2 = app64;
26086
+ var session_default2 = app66;
25826
26087
 
25827
26088
  // server/lib/calendar-slots.ts
25828
26089
  var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
@@ -25905,17 +26166,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
25905
26166
  }
25906
26167
 
25907
26168
  // server/routes/calendar-public.ts
25908
- var app65 = new Hono();
26169
+ var app67 = new Hono();
25909
26170
  function setCors(c) {
25910
26171
  c.header("Access-Control-Allow-Origin", "*");
25911
26172
  c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
25912
26173
  c.header("Access-Control-Allow-Headers", "content-type");
25913
26174
  }
25914
- app65.options("/free-busy", (c) => {
26175
+ app67.options("/free-busy", (c) => {
25915
26176
  setCors(c);
25916
26177
  return c.body(null, 204);
25917
26178
  });
25918
- app65.get("/free-busy", async (c) => {
26179
+ app67.get("/free-busy", async (c) => {
25919
26180
  setCors(c);
25920
26181
  const from = c.req.query("from");
25921
26182
  const to = c.req.query("to");
@@ -25971,15 +26232,15 @@ app65.get("/free-busy", async (c) => {
25971
26232
  await session.close();
25972
26233
  }
25973
26234
  });
25974
- var calendar_public_default = app65;
26235
+ var calendar_public_default = app67;
25975
26236
 
25976
26237
  // server/routes/portal-fetch.ts
25977
26238
  import { createReadStream as createReadStream3 } from "fs";
25978
26239
  import { stat as stat8, readFile as readFile9, realpath } from "fs/promises";
25979
- import { join as join44, resolve as resolve36, sep as sep10 } from "path";
26240
+ import { join as join44, resolve as resolve37, sep as sep10 } from "path";
25980
26241
  import { Readable as Readable3 } from "stream";
25981
- var app66 = new Hono();
25982
- var TAG47 = "[portal-fetch]";
26242
+ var app68 = new Hono();
26243
+ var TAG49 = "[portal-fetch]";
25983
26244
  async function verifySignature(secret, accountId, relPath, expiresAtMs, signature, nowMs) {
25984
26245
  if (!secret || !signature) return false;
25985
26246
  if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) return false;
@@ -26029,19 +26290,19 @@ ${expiresAtMs}`)
26029
26290
  return diff === 0;
26030
26291
  }
26031
26292
  async function readAccountSecret(accountId) {
26032
- const path3 = resolve36(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
26293
+ const path3 = resolve37(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
26033
26294
  let text;
26034
26295
  try {
26035
26296
  text = await readFile9(path3, "utf8");
26036
26297
  } catch {
26037
- console.error(`${TAG47} op=no-secret account="${accountId}" path="${path3}"`);
26298
+ console.error(`${TAG49} op=no-secret account="${accountId}" path="${path3}"`);
26038
26299
  return "";
26039
26300
  }
26040
26301
  for (const line of text.split("\n")) {
26041
26302
  const m = line.match(/^PORTAL_FETCH_SECRET=(.*)$/);
26042
26303
  if (m) return m[1].trim();
26043
26304
  }
26044
- console.error(`${TAG47} op=no-secret account="${accountId}" reason=key-absent path="${path3}"`);
26305
+ console.error(`${TAG49} op=no-secret account="${accountId}" reason=key-absent path="${path3}"`);
26045
26306
  return "";
26046
26307
  }
26047
26308
  function isValidAccountId2(value) {
@@ -26065,7 +26326,7 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
26065
26326
  const exposeFolders = await readExposeFolders2(accountDir);
26066
26327
  const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
26067
26328
  if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
26068
- const lexical = resolve36(accountDir, relPath);
26329
+ const lexical = resolve37(accountDir, relPath);
26069
26330
  let root;
26070
26331
  let absolute;
26071
26332
  try {
@@ -26101,33 +26362,33 @@ async function handle(c, headOnly) {
26101
26362
  const sig = c.req.query("sig") ?? "";
26102
26363
  const owner = c.req.query("owner") ?? "";
26103
26364
  console.log(
26104
- `${TAG47} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
26365
+ `${TAG49} op=request account=${q(accountId)} path=${q(relPath)} owner=${q(owner)} head=${headOnly}`
26105
26366
  );
26106
26367
  if (!isValidAccountId2(accountId)) {
26107
- console.error(`${TAG47} op=denied account=${q(accountId)} reason=account-id`);
26368
+ console.error(`${TAG49} op=denied account=${q(accountId)} reason=account-id`);
26108
26369
  return c.json({ ok: false, error: "denied" }, 401);
26109
26370
  }
26110
26371
  const secret = await readAccountSecret(accountId);
26111
26372
  const verified = owner ? await verifyOwnUploadSignature(secret, accountId, owner, relPath, exp, sig, Date.now()) : await verifySignature(secret, accountId, relPath, exp, sig, Date.now());
26112
26373
  if (!verified) {
26113
- console.error(`${TAG47} op=denied account=${q(accountId)} reason=secret`);
26374
+ console.error(`${TAG49} op=denied account=${q(accountId)} reason=secret`);
26114
26375
  return c.json({ ok: false, error: "denied" }, 401);
26115
26376
  }
26116
26377
  const target = await resolveFetchTarget(
26117
- resolve36(DATA_ROOT, "accounts", accountId),
26378
+ resolve37(DATA_ROOT, "accounts", accountId),
26118
26379
  relPath,
26119
26380
  owner || void 0
26120
26381
  );
26121
26382
  if (!target.ok) {
26122
26383
  const op = target.reason === "enoent" ? "miss" : "denied";
26123
- console.error(`${TAG47} op=${op} account=${accountId} reason=${target.reason}`);
26384
+ console.error(`${TAG49} op=${op} account=${accountId} reason=${target.reason}`);
26124
26385
  return c.json({ ok: false, error: "not found" }, 404);
26125
26386
  }
26126
26387
  if (headOnly) {
26127
- console.log(`${TAG47} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
26388
+ console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes} head=true`);
26128
26389
  return c.body(null, 200);
26129
26390
  }
26130
- console.log(`${TAG47} op=served account=${accountId} bytes=${target.sizeBytes}`);
26391
+ console.log(`${TAG49} op=served account=${accountId} bytes=${target.sizeBytes}`);
26131
26392
  return new Response(Readable3.toWeb(createReadStream3(target.absolute)), {
26132
26393
  status: 200,
26133
26394
  headers: {
@@ -26141,12 +26402,12 @@ async function handle(c, headOnly) {
26141
26402
  }
26142
26403
  });
26143
26404
  }
26144
- app66.get("/fetch", (c) => handle(c, false));
26145
- app66.on("HEAD", "/fetch", (c) => handle(c, true));
26146
- var portal_fetch_default = app66;
26405
+ app68.get("/fetch", (c) => handle(c, false));
26406
+ app68.on("HEAD", "/fetch", (c) => handle(c, true));
26407
+ var portal_fetch_default = app68;
26147
26408
 
26148
26409
  // app/lib/timeentry-census.ts
26149
- var TAG48 = "[timeentry-census]";
26410
+ var TAG50 = "[timeentry-census]";
26150
26411
  function reconcileTimeEntries(rows, now, horizonMs) {
26151
26412
  const openEntries = rows.openEntries.length;
26152
26413
  let oldestOpenAgeMs = 0;
@@ -26186,12 +26447,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
26186
26447
  sumAdjustments: toNum(r.get("sumAdjustments"))
26187
26448
  }));
26188
26449
  const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
26189
- const line = `${TAG48} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
26450
+ const line = `${TAG50} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
26190
26451
  if (finding.alarm) console.error(`${line} alarm=true`);
26191
26452
  else console.log(line);
26192
26453
  return finding;
26193
26454
  } catch (err) {
26194
- console.error(`${TAG48} error="${err instanceof Error ? err.message : String(err)}"`);
26455
+ console.error(`${TAG50} error="${err instanceof Error ? err.message : String(err)}"`);
26195
26456
  return null;
26196
26457
  }
26197
26458
  }
@@ -26205,13 +26466,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
26205
26466
  try {
26206
26467
  session = openSession();
26207
26468
  } catch (err) {
26208
- console.error(`${TAG48} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
26469
+ console.error(`${TAG50} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
26209
26470
  return;
26210
26471
  }
26211
26472
  try {
26212
26473
  await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
26213
26474
  } catch (err) {
26214
- console.error(`${TAG48} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
26475
+ console.error(`${TAG50} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
26215
26476
  } finally {
26216
26477
  try {
26217
26478
  await session.close();
@@ -26228,7 +26489,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
26228
26489
  }
26229
26490
 
26230
26491
  // app/lib/ledger-census.ts
26231
- import { readdirSync as readdirSync26, readFileSync as readFileSync43, statSync as statSync18 } from "fs";
26492
+ import { readdirSync as readdirSync27, readFileSync as readFileSync44, statSync as statSync18 } from "fs";
26232
26493
  import { join as join45 } from "path";
26233
26494
 
26234
26495
  // ../lib/ledger-core/dist/reconcile.js
@@ -26272,12 +26533,12 @@ function formatCensusLine(f) {
26272
26533
  }
26273
26534
 
26274
26535
  // app/lib/ledger-census.ts
26275
- var TAG49 = "[ledger-census]";
26536
+ var TAG51 = "[ledger-census]";
26276
26537
  var DAY_MS = 864e5;
26277
26538
  function countWriteRejects24h(logDir, now) {
26278
26539
  let entries;
26279
26540
  try {
26280
- entries = readdirSync26(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
26541
+ entries = readdirSync27(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
26281
26542
  } catch {
26282
26543
  return 0;
26283
26544
  }
@@ -26286,7 +26547,7 @@ function countWriteRejects24h(logDir, now) {
26286
26547
  const path3 = join45(logDir, name);
26287
26548
  try {
26288
26549
  if (now - statSync18(path3).mtimeMs > DAY_MS) continue;
26289
- for (const line of readFileSync43(path3, "utf8").split("\n")) {
26550
+ for (const line of readFileSync44(path3, "utf8").split("\n")) {
26290
26551
  if (line.includes("[graph-write] reject")) total += 1;
26291
26552
  }
26292
26553
  } catch {
@@ -26348,7 +26609,7 @@ async function runLedgerCensusOnce(session, now) {
26348
26609
  else console.log(line);
26349
26610
  return finding;
26350
26611
  } catch (err) {
26351
- console.error(`${TAG49} error="${err instanceof Error ? err.message : String(err)}"`);
26612
+ console.error(`${TAG51} error="${err instanceof Error ? err.message : String(err)}"`);
26352
26613
  return null;
26353
26614
  }
26354
26615
  }
@@ -26361,7 +26622,7 @@ function startLedgerCensus(openSession, opts = {}) {
26361
26622
  session = openSession();
26362
26623
  } catch (err) {
26363
26624
  console.error(
26364
- `${TAG49} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
26625
+ `${TAG51} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
26365
26626
  );
26366
26627
  return;
26367
26628
  }
@@ -26369,7 +26630,7 @@ function startLedgerCensus(openSession, opts = {}) {
26369
26630
  await runLedgerCensusOnce(session, Date.now());
26370
26631
  } catch (err) {
26371
26632
  console.error(
26372
- `${TAG49} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
26633
+ `${TAG51} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
26373
26634
  );
26374
26635
  } finally {
26375
26636
  try {
@@ -26387,7 +26648,7 @@ function startLedgerCensus(openSession, opts = {}) {
26387
26648
  }
26388
26649
 
26389
26650
  // app/lib/conversation-audit.ts
26390
- var TAG50 = "[conversation-audit]";
26651
+ var TAG52 = "[conversation-audit]";
26391
26652
  async function runConversationAudit() {
26392
26653
  const session = getSession();
26393
26654
  try {
@@ -26424,12 +26685,12 @@ async function runConversationAudit() {
26424
26685
  multiAnchored: Number(multiRec?.get("multiAnchored") ?? 0)
26425
26686
  };
26426
26687
  console.error(
26427
- `${TAG50} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
26688
+ `${TAG52} channel=whatsapp total=${result.total} senders=${result.senders} multiAnchored=${result.multiAnchored} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
26428
26689
  );
26429
26690
  return result;
26430
26691
  } catch (err) {
26431
26692
  const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
26432
- console.error(`${TAG50} op=failed reason=${reason}`);
26693
+ console.error(`${TAG52} op=failed reason=${reason}`);
26433
26694
  return null;
26434
26695
  } finally {
26435
26696
  await session.close();
@@ -26555,7 +26816,7 @@ function startGraphHealthTimer() {
26555
26816
 
26556
26817
  // app/lib/file-watcher.ts
26557
26818
  import * as fsp2 from "fs/promises";
26558
- import { resolve as resolve37, sep as sep11 } from "path";
26819
+ import { resolve as resolve38, sep as sep11 } from "path";
26559
26820
  var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26560
26821
  var DEFAULT_COALESCE_MS = 500;
26561
26822
  var ROOTS = ["accounts"];
@@ -26574,7 +26835,7 @@ async function startFileWatcher(opts = {}) {
26574
26835
  const dropFn = opts.drop ?? dropFileIndex;
26575
26836
  for (const r of ROOTS) {
26576
26837
  try {
26577
- await fsp2.mkdir(resolve37(dataRoot, r), { recursive: true });
26838
+ await fsp2.mkdir(resolve38(dataRoot, r), { recursive: true });
26578
26839
  } catch (err) {
26579
26840
  console.error(
26580
26841
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -26595,7 +26856,7 @@ async function startFileWatcher(opts = {}) {
26595
26856
  timers.set(relativePath, t);
26596
26857
  }
26597
26858
  async function runHook(relativePath, accountId) {
26598
- const absolute = resolve37(dataRoot, relativePath);
26859
+ const absolute = resolve38(dataRoot, relativePath);
26599
26860
  let exists = false;
26600
26861
  try {
26601
26862
  const st = await fsp2.stat(absolute);
@@ -26619,7 +26880,7 @@ async function startFileWatcher(opts = {}) {
26619
26880
  }
26620
26881
  }
26621
26882
  async function watchRoot(rootName) {
26622
- const absRoot = resolve37(dataRoot, rootName);
26883
+ const absRoot = resolve38(dataRoot, rootName);
26623
26884
  try {
26624
26885
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
26625
26886
  for await (const event of iter) {
@@ -26658,7 +26919,7 @@ async function startFileWatcher(opts = {}) {
26658
26919
 
26659
26920
  // app/lib/migrate-uploads.ts
26660
26921
  import { mkdir as mkdir6, readdir as readdir6, rename as rename3, rm as rm3 } from "fs/promises";
26661
- import { dirname as dirname15, relative as relative7, resolve as resolve38 } from "path";
26922
+ import { dirname as dirname15, relative as relative7, resolve as resolve39 } from "path";
26662
26923
  var ACCOUNT_UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26663
26924
  async function walkFiles(dir) {
26664
26925
  const out = [];
@@ -26669,7 +26930,7 @@ async function walkFiles(dir) {
26669
26930
  return out;
26670
26931
  }
26671
26932
  for (const e of entries) {
26672
- const abs = resolve38(dir, e.name);
26933
+ const abs = resolve39(dir, e.name);
26673
26934
  if (e.isDirectory()) {
26674
26935
  out.push(...await walkFiles(abs));
26675
26936
  } else if (e.isFile()) {
@@ -26689,7 +26950,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26689
26950
  let moved = 0;
26690
26951
  for (const oldAbs of files) {
26691
26952
  const suffix = relative7(srcDir, oldAbs);
26692
- const newAbs = resolve38(destDir, suffix);
26953
+ const newAbs = resolve39(destDir, suffix);
26693
26954
  await mkdir6(dirname15(newAbs), { recursive: true });
26694
26955
  await rename3(oldAbs, newAbs);
26695
26956
  moved++;
@@ -26716,7 +26977,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26716
26977
  }
26717
26978
  async function migrateUploads(opts = {}) {
26718
26979
  const dataRoot = opts.dataRoot ?? DATA_ROOT;
26719
- const oldRoot = resolve38(dataRoot, "uploads");
26980
+ const oldRoot = resolve39(dataRoot, "uploads");
26720
26981
  let topEntries;
26721
26982
  try {
26722
26983
  topEntries = await readdir6(oldRoot, { withFileTypes: true });
@@ -26737,8 +26998,8 @@ async function migrateUploads(opts = {}) {
26737
26998
  const name = entry.name;
26738
26999
  if (ACCOUNT_UUID_RE5.test(name)) {
26739
27000
  moved += await relocateTree(
26740
- resolve38(oldRoot, name),
26741
- resolve38(dataRoot, "accounts", name, "uploads"),
27001
+ resolve39(oldRoot, name),
27002
+ resolve39(dataRoot, "accounts", name, "uploads"),
26742
27003
  dataRoot,
26743
27004
  name,
26744
27005
  session
@@ -26750,8 +27011,8 @@ async function migrateUploads(opts = {}) {
26750
27011
  continue;
26751
27012
  }
26752
27013
  moved += await relocateTree(
26753
- resolve38(oldRoot, "public"),
26754
- resolve38(dataRoot, "accounts", installAccountId, "uploads", "public"),
27014
+ resolve39(oldRoot, "public"),
27015
+ resolve39(dataRoot, "accounts", installAccountId, "uploads", "public"),
26755
27016
  dataRoot,
26756
27017
  null,
26757
27018
  // public uploads carry no graph nodes
@@ -26781,7 +27042,7 @@ async function migrateUploads(opts = {}) {
26781
27042
 
26782
27043
  // app/lib/migrate-admin-webchat-sidecars.ts
26783
27044
  import { readdir as readdir7, readFile as readFile10, rename as rename4, writeFile as writeFile5, unlink as unlink4 } from "fs/promises";
26784
- import { existsSync as existsSync42 } from "fs";
27045
+ import { existsSync as existsSync43 } from "fs";
26785
27046
  import { join as join46 } from "path";
26786
27047
  var ADMIN_ROLE2 = "admin";
26787
27048
  var WEBCHAT_CHANNEL2 = "webchat";
@@ -26811,7 +27072,7 @@ async function writeRaw(path3, obj) {
26811
27072
  await rename4(tmp, path3);
26812
27073
  } catch (err) {
26813
27074
  try {
26814
- if (existsSync42(tmp)) await unlink4(tmp);
27075
+ if (existsSync43(tmp)) await unlink4(tmp);
26815
27076
  } catch {
26816
27077
  }
26817
27078
  throw err;
@@ -27200,8 +27461,8 @@ var streamSSE = (c, cb, onError) => {
27200
27461
 
27201
27462
  // app/lib/whatsapp/gateway/routes.ts
27202
27463
  function createWaChannelRoutes(deps) {
27203
- const app68 = new Hono();
27204
- app68.get("/wa-channel/inbound", (c) => {
27464
+ const app70 = new Hono();
27465
+ app70.get("/wa-channel/inbound", (c) => {
27205
27466
  const senderId = c.req.query("senderId");
27206
27467
  if (!senderId) return c.json({ error: "senderId required" }, 400);
27207
27468
  return streamSSE(c, async (stream2) => {
@@ -27219,7 +27480,7 @@ function createWaChannelRoutes(deps) {
27219
27480
  }
27220
27481
  });
27221
27482
  });
27222
- app68.post("/wa-channel/reply", async (c) => {
27483
+ app70.post("/wa-channel/reply", async (c) => {
27223
27484
  const body = await c.req.json().catch(() => null);
27224
27485
  const senderId = body?.senderId;
27225
27486
  const text = body?.text;
@@ -27240,7 +27501,7 @@ function createWaChannelRoutes(deps) {
27240
27501
  console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
27241
27502
  return c.json({ ok: true });
27242
27503
  });
27243
- app68.post("/wa-channel/reply-document", async (c) => {
27504
+ app70.post("/wa-channel/reply-document", async (c) => {
27244
27505
  const body = await c.req.json().catch(() => null);
27245
27506
  const senderId = body?.senderId;
27246
27507
  const files = body?.files;
@@ -27279,7 +27540,7 @@ function createWaChannelRoutes(deps) {
27279
27540
  }
27280
27541
  return c.json({ ok: true, results });
27281
27542
  });
27282
- app68.post("/wa-channel/ready", async (c) => {
27543
+ app70.post("/wa-channel/ready", async (c) => {
27283
27544
  const body = await c.req.json().catch(() => null);
27284
27545
  const senderId = body?.senderId;
27285
27546
  if (typeof senderId !== "string") {
@@ -27288,7 +27549,7 @@ function createWaChannelRoutes(deps) {
27288
27549
  deps.onReady?.(senderId);
27289
27550
  return c.json({ ok: true });
27290
27551
  });
27291
- app68.post("/wa-channel/received", async (c) => {
27552
+ app70.post("/wa-channel/received", async (c) => {
27292
27553
  const body = await c.req.json().catch(() => null);
27293
27554
  const senderId = body?.senderId;
27294
27555
  const waMessageId = body?.waMessageId;
@@ -27298,7 +27559,7 @@ function createWaChannelRoutes(deps) {
27298
27559
  deps.onReceived?.(senderId, waMessageId);
27299
27560
  return c.json({ ok: true });
27300
27561
  });
27301
- app68.post("/wa-channel/turn-end", async (c) => {
27562
+ app70.post("/wa-channel/turn-end", async (c) => {
27302
27563
  const body = await c.req.json().catch(() => null);
27303
27564
  const senderId = body?.senderId;
27304
27565
  const sessionId = body?.sessionId;
@@ -27331,7 +27592,7 @@ function createWaChannelRoutes(deps) {
27331
27592
  console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
27332
27593
  return c.json({ ok: true, delivered: "none" });
27333
27594
  });
27334
- return app68;
27595
+ return app70;
27335
27596
  }
27336
27597
 
27337
27598
  // app/lib/whatsapp/gateway/wa-gateway.ts
@@ -27746,8 +28007,8 @@ var InboundHub2 = class {
27746
28007
 
27747
28008
  // app/lib/webchat/gateway/routes.ts
27748
28009
  function createWebchatChannelRoutes(deps) {
27749
- const app68 = new Hono();
27750
- app68.get("/webchat-channel/inbound", (c) => {
28010
+ const app70 = new Hono();
28011
+ app70.get("/webchat-channel/inbound", (c) => {
27751
28012
  const key = c.req.query("key");
27752
28013
  if (!key) return c.json({ error: "key required" }, 400);
27753
28014
  return streamSSE(c, async (stream2) => {
@@ -27765,7 +28026,7 @@ function createWebchatChannelRoutes(deps) {
27765
28026
  }
27766
28027
  });
27767
28028
  });
27768
- app68.post("/webchat-channel/reply", async (c) => {
28029
+ app70.post("/webchat-channel/reply", async (c) => {
27769
28030
  const body = await c.req.json().catch(() => null);
27770
28031
  const key = body?.key;
27771
28032
  const text = body?.text;
@@ -27775,7 +28036,7 @@ function createWebchatChannelRoutes(deps) {
27775
28036
  deps.onReply?.(key, text);
27776
28037
  return c.json({ ok: true });
27777
28038
  });
27778
- app68.post("/webchat-channel/connector-auth", async (c) => {
28039
+ app70.post("/webchat-channel/connector-auth", async (c) => {
27779
28040
  const body = await c.req.json().catch(() => null);
27780
28041
  const key = body?.key;
27781
28042
  const sessionId = body?.sessionId;
@@ -27788,7 +28049,7 @@ function createWebchatChannelRoutes(deps) {
27788
28049
  const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
27789
28050
  return c.json(result);
27790
28051
  });
27791
- app68.post("/webchat-channel/ready", async (c) => {
28052
+ app70.post("/webchat-channel/ready", async (c) => {
27792
28053
  const body = await c.req.json().catch(() => null);
27793
28054
  const key = body?.key;
27794
28055
  if (typeof key !== "string") {
@@ -27797,7 +28058,7 @@ function createWebchatChannelRoutes(deps) {
27797
28058
  deps.onReady?.(key);
27798
28059
  return c.json({ ok: true });
27799
28060
  });
27800
- app68.post("/webchat-channel/permission-request", async (c) => {
28061
+ app70.post("/webchat-channel/permission-request", async (c) => {
27801
28062
  const body = await c.req.json().catch(() => null);
27802
28063
  const key = body?.key;
27803
28064
  const requestId = body?.request_id;
@@ -27811,7 +28072,7 @@ function createWebchatChannelRoutes(deps) {
27811
28072
  const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
27812
28073
  return c.json(verdict);
27813
28074
  });
27814
- app68.post("/webchat-channel/received", async (c) => {
28075
+ app70.post("/webchat-channel/received", async (c) => {
27815
28076
  const body = await c.req.json().catch(() => null);
27816
28077
  const key = body?.key;
27817
28078
  const messageId = body?.messageId;
@@ -27821,7 +28082,7 @@ function createWebchatChannelRoutes(deps) {
27821
28082
  deps.onReceived?.(key, messageId);
27822
28083
  return c.json({ ok: true });
27823
28084
  });
27824
- app68.post("/webchat-channel/turn-end", async (c) => {
28085
+ app70.post("/webchat-channel/turn-end", async (c) => {
27825
28086
  const body = await c.req.json().catch(() => null);
27826
28087
  const key = body?.key;
27827
28088
  const sessionId = body?.sessionId;
@@ -27835,7 +28096,7 @@ function createWebchatChannelRoutes(deps) {
27835
28096
  console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=${replied ? "yes" : "no"} trailing=${finalBytes}`);
27836
28097
  return c.json({ ok: true });
27837
28098
  });
27838
- return app68;
28099
+ return app70;
27839
28100
  }
27840
28101
 
27841
28102
  // app/lib/webchat/gateway/webchat-gateway.ts
@@ -27893,16 +28154,16 @@ var WebchatGateway = class _WebchatGateway {
27893
28154
  * The public /api/chat route awaits this to return the reply on the same SSE
27894
28155
  * response, preserving the pre-756 POST→single-blob browser contract. */
27895
28156
  awaitReply(key, timeoutMs) {
27896
- return new Promise((resolve44) => {
28157
+ return new Promise((resolve45) => {
27897
28158
  const timer = setTimeout(() => {
27898
28159
  this.replyAwaiters.delete(key);
27899
- resolve44({ timeout: true });
28160
+ resolve45({ timeout: true });
27900
28161
  }, timeoutMs);
27901
28162
  if (timer.unref) timer.unref();
27902
28163
  this.replyAwaiters.set(key, (r) => {
27903
28164
  clearTimeout(timer);
27904
28165
  this.replyAwaiters.delete(key);
27905
- resolve44(r);
28166
+ resolve45(r);
27906
28167
  });
27907
28168
  });
27908
28169
  }
@@ -27913,11 +28174,11 @@ var WebchatGateway = class _WebchatGateway {
27913
28174
  * terminal dialog stays answerable). */
27914
28175
  awaitPermissionVerdict(p, timeoutMs) {
27915
28176
  const k = _WebchatGateway.promptKey(p.key, p.requestId);
27916
- return new Promise((resolve44) => {
28177
+ return new Promise((resolve45) => {
27917
28178
  this.pendingPrompts.get(k)?.resolve({ timeout: true });
27918
28179
  const timer = setTimeout(() => {
27919
28180
  this.pendingPrompts.delete(k);
27920
- resolve44({ timeout: true });
28181
+ resolve45({ timeout: true });
27921
28182
  }, timeoutMs);
27922
28183
  if (timer.unref) timer.unref();
27923
28184
  this.pendingPrompts.set(k, {
@@ -27926,7 +28187,7 @@ var WebchatGateway = class _WebchatGateway {
27926
28187
  resolve: (r) => {
27927
28188
  clearTimeout(timer);
27928
28189
  this.pendingPrompts.delete(k);
27929
- resolve44(r);
28190
+ resolve45(r);
27930
28191
  }
27931
28192
  });
27932
28193
  console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
@@ -28491,7 +28752,7 @@ async function fanOut(subscribers, text, onError, tag) {
28491
28752
 
28492
28753
  // app/lib/webchat/file-delivery.ts
28493
28754
  import { realpathSync as realpathSync9 } from "fs";
28494
- import { resolve as resolve39 } from "path";
28755
+ import { resolve as resolve40 } from "path";
28495
28756
 
28496
28757
  // app/lib/channel-pty-bridge/file-delivery.ts
28497
28758
  var SEND_USER_FILE = "SendUserFile";
@@ -28582,29 +28843,29 @@ function makeFileDelivery(opts) {
28582
28843
  }
28583
28844
 
28584
28845
  // app/lib/webchat/file-delivery.ts
28585
- var TAG51 = "[webchat-adaptor]";
28846
+ var TAG53 = "[webchat-adaptor]";
28586
28847
  function platformRoot2() {
28587
28848
  return process.env.MAXY_PLATFORM_ROOT || "";
28588
28849
  }
28589
28850
  function makeWebchatSendFile(entry) {
28590
28851
  return async (filePath) => {
28591
28852
  if (!entry.accountId) {
28592
- console.error(`${TAG51} file-delivery reject reason=no-account sender=${entry.senderId}`);
28853
+ console.error(`${TAG53} file-delivery reject reason=no-account sender=${entry.senderId}`);
28593
28854
  return { ok: false, error: "no-account" };
28594
28855
  }
28595
- const accountDir = resolve39(platformRoot2(), "..", "data/accounts", entry.accountId);
28856
+ const accountDir = resolve40(platformRoot2(), "..", "data/accounts", entry.accountId);
28596
28857
  try {
28597
28858
  const resolved = realpathSync9(filePath);
28598
28859
  const accountResolved = realpathSync9(accountDir);
28599
28860
  if (!resolved.startsWith(accountResolved + "/")) {
28600
- console.error(`${TAG51} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
28861
+ console.error(`${TAG53} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
28601
28862
  return { ok: false, error: "outside-account" };
28602
28863
  }
28603
28864
  return { ok: true };
28604
28865
  } catch (err) {
28605
28866
  const code = err.code;
28606
28867
  console.error(
28607
- `${TAG51} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
28868
+ `${TAG53} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
28608
28869
  );
28609
28870
  return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
28610
28871
  }
@@ -28613,7 +28874,7 @@ function makeWebchatSendFile(entry) {
28613
28874
  function makeWebchatFileDelivery(entry) {
28614
28875
  return makeFileDelivery({
28615
28876
  entry,
28616
- tag: TAG51,
28877
+ tag: TAG53,
28617
28878
  channel: "webchat",
28618
28879
  sendFile: makeWebchatSendFile(entry),
28619
28880
  deferUntilVerdict: true
@@ -28675,7 +28936,7 @@ function buildPublicWebchatSpawnRequest(input) {
28675
28936
  }
28676
28937
 
28677
28938
  // app/lib/whatsapp/inbound/file-delivery-bridge.ts
28678
- var TAG52 = "[whatsapp-adaptor]";
28939
+ var TAG54 = "[whatsapp-adaptor]";
28679
28940
  var SEND_USER_FILE2 = "SendUserFile";
28680
28941
  var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
28681
28942
  function platformRoot3() {
@@ -28693,7 +28954,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
28693
28954
  });
28694
28955
  if (result.ok) return { ok: true };
28695
28956
  console.error(
28696
- `${TAG52} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
28957
+ `${TAG54} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
28697
28958
  );
28698
28959
  return { ok: false, error: result.error };
28699
28960
  };
@@ -28701,7 +28962,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
28701
28962
  function makeWhatsAppFileDelivery(entry, maxyAccountId) {
28702
28963
  const shared = makeFileDelivery({
28703
28964
  entry,
28704
- tag: TAG52,
28965
+ tag: TAG54,
28705
28966
  channel: "whatsapp",
28706
28967
  sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
28707
28968
  });
@@ -28736,7 +28997,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
28736
28997
  if (!delivered) {
28737
28998
  const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
28738
28999
  console.error(
28739
- `${TAG52} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
29000
+ `${TAG54} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
28740
29001
  );
28741
29002
  }
28742
29003
  }
@@ -28919,8 +29180,8 @@ var InboundHub3 = class {
28919
29180
 
28920
29181
  // app/lib/telegram/gateway/routes.ts
28921
29182
  function createTelegramChannelRoutes(deps) {
28922
- const app68 = new Hono();
28923
- app68.get("/tg-channel/inbound", (c) => {
29183
+ const app70 = new Hono();
29184
+ app70.get("/tg-channel/inbound", (c) => {
28924
29185
  const key = c.req.query("key");
28925
29186
  if (!key) return c.json({ error: "key required" }, 400);
28926
29187
  return streamSSE(c, async (stream2) => {
@@ -28938,7 +29199,7 @@ function createTelegramChannelRoutes(deps) {
28938
29199
  }
28939
29200
  });
28940
29201
  });
28941
- app68.post("/tg-channel/reply", async (c) => {
29202
+ app70.post("/tg-channel/reply", async (c) => {
28942
29203
  const body = await c.req.json().catch(() => null);
28943
29204
  const key = body?.key;
28944
29205
  const text = body?.text;
@@ -28954,7 +29215,7 @@ function createTelegramChannelRoutes(deps) {
28954
29215
  console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
28955
29216
  return c.json({ ok: true });
28956
29217
  });
28957
- app68.post("/tg-channel/ready", async (c) => {
29218
+ app70.post("/tg-channel/ready", async (c) => {
28958
29219
  const body = await c.req.json().catch(() => null);
28959
29220
  const key = body?.key;
28960
29221
  if (typeof key !== "string") {
@@ -28963,7 +29224,7 @@ function createTelegramChannelRoutes(deps) {
28963
29224
  deps.onReady?.(key);
28964
29225
  return c.json({ ok: true });
28965
29226
  });
28966
- app68.post("/tg-channel/received", async (c) => {
29227
+ app70.post("/tg-channel/received", async (c) => {
28967
29228
  const body = await c.req.json().catch(() => null);
28968
29229
  const key = body?.key;
28969
29230
  const messageId = body?.messageId;
@@ -28973,7 +29234,7 @@ function createTelegramChannelRoutes(deps) {
28973
29234
  deps.onReceived?.(key, messageId);
28974
29235
  return c.json({ ok: true });
28975
29236
  });
28976
- app68.post("/tg-channel/turn-end", async (c) => {
29237
+ app70.post("/tg-channel/turn-end", async (c) => {
28977
29238
  const body = await c.req.json().catch(() => null);
28978
29239
  const key = body?.key;
28979
29240
  const sessionId = body?.sessionId;
@@ -29006,7 +29267,7 @@ function createTelegramChannelRoutes(deps) {
29006
29267
  console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
29007
29268
  return c.json({ ok: true, delivered: "none" });
29008
29269
  });
29009
- return app68;
29270
+ return app70;
29010
29271
  }
29011
29272
 
29012
29273
  // app/lib/telegram/gateway/telegram-gateway.ts
@@ -29156,8 +29417,8 @@ function buildTelegramSpawnRequest(input) {
29156
29417
  // app/lib/telegram/outbound/send-document.ts
29157
29418
  import { realpathSync as realpathSync10 } from "fs";
29158
29419
  import { readFile as readFile11, stat as stat10 } from "fs/promises";
29159
- import { resolve as resolve40, basename as basename13 } from "path";
29160
- var TAG53 = "[telegram:outbound]";
29420
+ import { resolve as resolve41, basename as basename13 } from "path";
29421
+ var TAG55 = "[telegram:outbound]";
29161
29422
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
29162
29423
  async function sendTelegramDocument(input) {
29163
29424
  const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
@@ -29167,17 +29428,17 @@ async function sendTelegramDocument(input) {
29167
29428
  if (!maxyAccountId || !platformRoot5) {
29168
29429
  return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
29169
29430
  }
29170
- const accountDir = resolve40(platformRoot5, "..", "data/accounts", maxyAccountId);
29431
+ const accountDir = resolve41(platformRoot5, "..", "data/accounts", maxyAccountId);
29171
29432
  let accountResolved;
29172
29433
  try {
29173
29434
  accountResolved = realpathSync10(accountDir);
29174
29435
  } catch (err) {
29175
29436
  const code = err.code;
29176
29437
  if (code === "ENOENT") {
29177
- console.error(`${TAG53} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
29438
+ console.error(`${TAG55} document ENOENT scope=account-dir accountDir=${accountDir} maxyAccountId=${maxyAccountId}`);
29178
29439
  return { ok: false, status: 500, error: `Account directory not resolvable for ${maxyAccountId}` };
29179
29440
  }
29180
- console.error(`${TAG53} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
29441
+ console.error(`${TAG55} document path error scope=account-dir maxyAccountId=${maxyAccountId}: ${String(err)}`);
29181
29442
  return { ok: false, status: 500, error: String(err) };
29182
29443
  }
29183
29444
  let resolvedPath;
@@ -29186,14 +29447,14 @@ async function sendTelegramDocument(input) {
29186
29447
  } catch (err) {
29187
29448
  const code = err.code;
29188
29449
  if (code === "ENOENT") {
29189
- console.error(`${TAG53} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
29450
+ console.error(`${TAG55} document ENOENT scope=file path=${filePath} maxyAccountId=${maxyAccountId}`);
29190
29451
  return { ok: false, status: 404, error: `File not found: ${filePath}` };
29191
29452
  }
29192
- console.error(`${TAG53} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
29453
+ console.error(`${TAG55} document path error scope=file maxyAccountId=${maxyAccountId}: ${String(err)}`);
29193
29454
  return { ok: false, status: 500, error: String(err) };
29194
29455
  }
29195
29456
  if (!resolvedPath.startsWith(accountResolved + "/")) {
29196
- console.error(`${TAG53} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
29457
+ console.error(`${TAG55} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
29197
29458
  return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
29198
29459
  }
29199
29460
  const fileStat = await stat10(resolvedPath);
@@ -29226,13 +29487,13 @@ async function sendTelegramDocument(input) {
29226
29487
  error = e instanceof Error ? e.message : String(e);
29227
29488
  }
29228
29489
  console.error(
29229
- `${TAG53} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
29490
+ `${TAG55} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
29230
29491
  );
29231
29492
  return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
29232
29493
  }
29233
29494
 
29234
29495
  // app/lib/telegram/outbound/file-delivery.ts
29235
- var TAG54 = "[telegram:outbound]";
29496
+ var TAG56 = "[telegram:outbound]";
29236
29497
  function platformRoot4() {
29237
29498
  return process.env.MAXY_PLATFORM_ROOT || "";
29238
29499
  }
@@ -29244,11 +29505,11 @@ function makeTelegramSendFile(entry) {
29244
29505
  botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
29245
29506
  }
29246
29507
  if (!botToken) {
29247
- console.error(`${TAG54} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
29508
+ console.error(`${TAG56} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
29248
29509
  return { ok: false, error: "no-bot-token" };
29249
29510
  }
29250
29511
  if (entry.replyTarget == null) {
29251
- console.error(`${TAG54} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
29512
+ console.error(`${TAG56} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
29252
29513
  return { ok: false, error: "no-reply-target" };
29253
29514
  }
29254
29515
  const result = await sendTelegramDocument({
@@ -29265,7 +29526,7 @@ function makeTelegramSendFile(entry) {
29265
29526
  function makeTelegramFileDelivery(entry) {
29266
29527
  return makeFileDelivery({
29267
29528
  entry,
29268
- tag: TAG54,
29529
+ tag: TAG56,
29269
29530
  channel: "telegram",
29270
29531
  sendFile: makeTelegramSendFile(entry)
29271
29532
  });
@@ -29306,7 +29567,7 @@ function startTelegramNativeFileFollower(input) {
29306
29567
 
29307
29568
  // app/lib/channel-pty-bridge/public-session-end-review.ts
29308
29569
  import { randomUUID as randomUUID16 } from "crypto";
29309
- var TAG55 = "[public-session-review]";
29570
+ var TAG57 = "[public-session-review]";
29310
29571
  var CONSUMED_CAP = 500;
29311
29572
  var consumed = /* @__PURE__ */ new Set();
29312
29573
  function consumeOnce(sessionId) {
@@ -29333,7 +29594,7 @@ async function fetchJsonl(sessionId) {
29333
29594
  return await res.text();
29334
29595
  } catch (err) {
29335
29596
  console.error(
29336
- `${TAG55} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
29597
+ `${TAG57} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
29337
29598
  );
29338
29599
  return null;
29339
29600
  }
@@ -29357,7 +29618,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
29357
29618
  const res = await fetch(url);
29358
29619
  if (!res.ok) {
29359
29620
  console.error(
29360
- `${TAG55} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
29621
+ `${TAG57} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
29361
29622
  );
29362
29623
  return [];
29363
29624
  }
@@ -29365,7 +29626,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
29365
29626
  return Array.isArray(body.writes) ? body.writes : [];
29366
29627
  } catch (err) {
29367
29628
  console.error(
29368
- `${TAG55} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
29629
+ `${TAG57} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
29369
29630
  );
29370
29631
  return [];
29371
29632
  }
@@ -29394,7 +29655,7 @@ function composeInitialMessage(input) {
29394
29655
  }
29395
29656
  async function dispatchReviewer(input, initialMessage) {
29396
29657
  const sessionId = randomUUID16();
29397
- console.log(`${TAG55} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
29658
+ console.log(`${TAG57} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
29398
29659
  const spawned = await managerRcSpawn({
29399
29660
  sessionId,
29400
29661
  initialMessage,
@@ -29414,21 +29675,21 @@ async function firePublicSessionEndReview(input) {
29414
29675
  const dispatchedAt = Date.now();
29415
29676
  if (consumed.has(input.sessionId)) {
29416
29677
  console.log(
29417
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
29678
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
29418
29679
  );
29419
29680
  return;
29420
29681
  }
29421
29682
  const jsonl = await fetchJsonl(input.sessionId);
29422
29683
  if (!jsonl) {
29423
29684
  console.log(
29424
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
29685
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
29425
29686
  );
29426
29687
  return;
29427
29688
  }
29428
29689
  const operatorTurns = countOperatorTurns(jsonl);
29429
29690
  if (operatorTurns === 0) {
29430
29691
  console.log(
29431
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
29692
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
29432
29693
  );
29433
29694
  return;
29434
29695
  }
@@ -29442,19 +29703,19 @@ async function firePublicSessionEndReview(input) {
29442
29703
  });
29443
29704
  if (!consumeOnce(input.sessionId)) {
29444
29705
  console.log(
29445
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
29706
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
29446
29707
  );
29447
29708
  return;
29448
29709
  }
29449
29710
  const dispatched = await dispatchReviewer(input, initialMessage);
29450
29711
  if (!dispatched.ok) {
29451
29712
  console.error(
29452
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
29713
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
29453
29714
  );
29454
29715
  return;
29455
29716
  }
29456
29717
  console.log(
29457
- `${TAG55} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
29718
+ `${TAG57} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
29458
29719
  );
29459
29720
  }
29460
29721
 
@@ -29559,14 +29820,14 @@ function warnOnChannelAdminBindingDrift() {
29559
29820
  }
29560
29821
 
29561
29822
  // server/lib/booking-site-accounts.ts
29562
- import { existsSync as existsSync43, readFileSync as readFileSync44 } from "fs";
29563
- import { resolve as resolve41 } from "path";
29823
+ import { existsSync as existsSync44, readFileSync as readFileSync45 } from "fs";
29824
+ import { resolve as resolve42 } from "path";
29564
29825
  function listBookingSiteAccounts(accounts) {
29565
29826
  return accounts.filter((a) => {
29566
- const availPath = resolve41(a.accountDir, "calendar-availability.json");
29567
- if (!existsSync43(availPath)) return false;
29827
+ const availPath = resolve42(a.accountDir, "calendar-availability.json");
29828
+ if (!existsSync44(availPath)) return false;
29568
29829
  try {
29569
- const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
29830
+ const cfg = JSON.parse(readFileSync45(availPath, "utf-8"));
29570
29831
  return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
29571
29832
  } catch {
29572
29833
  return false;
@@ -29604,8 +29865,8 @@ function broadcastAdminShutdown(reason) {
29604
29865
 
29605
29866
  // ../lib/entitlement/src/index.ts
29606
29867
  import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
29607
- import { existsSync as existsSync44, readFileSync as readFileSync45, statSync as statSync19 } from "fs";
29608
- import { resolve as resolve42 } from "path";
29868
+ import { existsSync as existsSync45, readFileSync as readFileSync46, statSync as statSync19 } from "fs";
29869
+ import { resolve as resolve43 } from "path";
29609
29870
 
29610
29871
  // ../lib/entitlement/src/canonicalize.ts
29611
29872
  function canonicalize(value) {
@@ -29640,7 +29901,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
29640
29901
  var GRACE_DAYS = 7;
29641
29902
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
29642
29903
  function pubkeyPath(brand) {
29643
- return resolve42(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29904
+ return resolve43(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29644
29905
  }
29645
29906
  var memo = null;
29646
29907
  function memoKey(mtimeMs, account) {
@@ -29652,8 +29913,8 @@ function resolveEntitlement(brand, account) {
29652
29913
  if (brand.commercialMode !== true) {
29653
29914
  return logResolved(implicitTrust(account), null);
29654
29915
  }
29655
- const entitlementPath = resolve42(brand.configDir, "entitlement.json");
29656
- if (!existsSync44(entitlementPath)) {
29916
+ const entitlementPath = resolve43(brand.configDir, "entitlement.json");
29917
+ if (!existsSync45(entitlementPath)) {
29657
29918
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
29658
29919
  }
29659
29920
  const stat11 = statSync19(entitlementPath);
@@ -29668,7 +29929,7 @@ function resolveEntitlement(brand, account) {
29668
29929
  function verifyAndResolve(brand, entitlementPath, account) {
29669
29930
  let pubkeyPem;
29670
29931
  try {
29671
- pubkeyPem = readFileSync45(pubkeyPath(brand), "utf-8");
29932
+ pubkeyPem = readFileSync46(pubkeyPath(brand), "utf-8");
29672
29933
  } catch (err) {
29673
29934
  return logResolved(anonymousFallback("pubkey-missing"), {
29674
29935
  reason: "pubkey-missing"
@@ -29682,7 +29943,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
29682
29943
  }
29683
29944
  let envelope;
29684
29945
  try {
29685
- envelope = JSON.parse(readFileSync45(entitlementPath, "utf-8"));
29946
+ envelope = JSON.parse(readFileSync46(entitlementPath, "utf-8"));
29686
29947
  } catch {
29687
29948
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
29688
29949
  }
@@ -29846,12 +30107,12 @@ installMediaDownloadGuard();
29846
30107
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
29847
30108
  var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join47(PLATFORM_ROOT8, "config", "brand.json") : "";
29848
30109
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
29849
- if (BRAND_JSON_PATH && !existsSync45(BRAND_JSON_PATH)) {
30110
+ if (BRAND_JSON_PATH && !existsSync46(BRAND_JSON_PATH)) {
29850
30111
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
29851
30112
  }
29852
- if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
30113
+ if (BRAND_JSON_PATH && existsSync46(BRAND_JSON_PATH)) {
29853
30114
  try {
29854
- const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
30115
+ const parsed = JSON.parse(readFileSync47(BRAND_JSON_PATH, "utf-8"));
29855
30116
  BRAND = { ...BRAND, ...parsed };
29856
30117
  } catch (err) {
29857
30118
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -29886,8 +30147,8 @@ var brandLoginOpts = {
29886
30147
  var ALIAS_DOMAINS_PATH = join47(homedir4(), BRAND.configDir, "alias-domains.json");
29887
30148
  function loadAliasDomains() {
29888
30149
  try {
29889
- if (!existsSync45(ALIAS_DOMAINS_PATH)) return null;
29890
- const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
30150
+ if (!existsSync46(ALIAS_DOMAINS_PATH)) return null;
30151
+ const parsed = JSON.parse(readFileSync47(ALIAS_DOMAINS_PATH, "utf-8"));
29891
30152
  if (!Array.isArray(parsed)) {
29892
30153
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
29893
30154
  return null;
@@ -29911,7 +30172,7 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
29911
30172
  function isPublicHost(host) {
29912
30173
  return host.startsWith("public.") || aliasDomains.has(host);
29913
30174
  }
29914
- var app67 = new Hono();
30175
+ var app69 = new Hono();
29915
30176
  function resolveChannelOverride(accountId, channel, senderId) {
29916
30177
  try {
29917
30178
  const dir = listValidAccounts().find((a) => a.accountId === accountId)?.accountDir;
@@ -29960,7 +30221,7 @@ var waGateway = new WaGateway({
29960
30221
  fetchStandingRules: fetchAccountStandingRules,
29961
30222
  resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
29962
30223
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
29963
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
30224
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
29964
30225
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
29965
30226
  // path-validation scope) is the sender's effective SESSION account, resolved
29966
30227
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -29975,7 +30236,7 @@ var waGateway = new WaGateway({
29975
30236
  caption,
29976
30237
  accountId,
29977
30238
  maxyAccountId,
29978
- platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
30239
+ platformRoot: resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, ".."))
29979
30240
  });
29980
30241
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
29981
30242
  },
@@ -30087,7 +30348,7 @@ var waGateway = new WaGateway({
30087
30348
  nativeFileFollowers.set(senderId, ac);
30088
30349
  }
30089
30350
  });
30090
- app67.route("/", waGateway.routes());
30351
+ app69.route("/", waGateway.routes());
30091
30352
  waGateway.startSweeper();
30092
30353
  function runDuplicateSenderAudit() {
30093
30354
  try {
@@ -30210,7 +30471,7 @@ var webchatGateway = new WebchatGateway({
30210
30471
  firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
30211
30472
  });
30212
30473
  setWebchatGateway(webchatGateway);
30213
- app67.route("/", webchatGateway.routes());
30474
+ app69.route("/", webchatGateway.routes());
30214
30475
  webchatGateway.startSweeper();
30215
30476
  webchatGateway.startPublicReaper();
30216
30477
  var telegramFileFollowers = /* @__PURE__ */ new Map();
@@ -30254,7 +30515,7 @@ var telegramGateway = new TelegramGateway({
30254
30515
  }
30255
30516
  });
30256
30517
  setTelegramGateway(telegramGateway);
30257
- app67.route("/", telegramGateway.routes());
30518
+ app69.route("/", telegramGateway.routes());
30258
30519
  telegramGateway.startSweeper();
30259
30520
  var chatRoutes = createChatRoutes({
30260
30521
  handleInbound: (input) => webchatGateway.handleInbound(input),
@@ -30288,19 +30549,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
30288
30549
  return managed.account;
30289
30550
  }
30290
30551
  });
30291
- app67.route("/api/channel/schedule-inject", scheduleInjectRoutes);
30292
- app67.use("*", clientIpMiddleware);
30552
+ app69.route("/api/channel/schedule-inject", scheduleInjectRoutes);
30553
+ app69.use("*", clientIpMiddleware);
30293
30554
  function allowsSameOriginFraming(path3) {
30294
30555
  return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download" || path3 === "/api/admin/session-upload";
30295
30556
  }
30296
- app67.use("*", async (c, next) => {
30557
+ app69.use("*", async (c, next) => {
30297
30558
  await next();
30298
30559
  c.header("X-Content-Type-Options", "nosniff");
30299
30560
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
30300
30561
  c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
30301
30562
  });
30302
30563
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
30303
- app67.use("*", async (c, next) => {
30564
+ app69.use("*", async (c, next) => {
30304
30565
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
30305
30566
  await next();
30306
30567
  return;
@@ -30318,7 +30579,7 @@ app67.use("*", async (c, next) => {
30318
30579
  });
30319
30580
  }
30320
30581
  });
30321
- app67.use("*", async (c, next) => {
30582
+ app69.use("*", async (c, next) => {
30322
30583
  const host = (c.req.header("host") ?? "").split(":")[0];
30323
30584
  if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
30324
30585
  await next();
@@ -30356,7 +30617,7 @@ function resolveRemoteAuthOpts(c) {
30356
30617
  return { ...brandLoginOpts, origin };
30357
30618
  }
30358
30619
  var MAX_LOGIN_BODY = 8 * 1024;
30359
- app67.post("/__remote-auth/login", async (c) => {
30620
+ app69.post("/__remote-auth/login", async (c) => {
30360
30621
  const client = clientFrom(c);
30361
30622
  const clientIp = client.ip || "unknown";
30362
30623
  if (!requestIsTlsTerminated(c)) {
@@ -30401,7 +30662,7 @@ app67.post("/__remote-auth/login", async (c) => {
30401
30662
  }
30402
30663
  });
30403
30664
  });
30404
- app67.get("/__remote-auth/logout", (c) => {
30665
+ app69.get("/__remote-auth/logout", (c) => {
30405
30666
  const client = clientFrom(c);
30406
30667
  const clientIp = client.ip || "unknown";
30407
30668
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -30414,7 +30675,7 @@ app67.get("/__remote-auth/logout", (c) => {
30414
30675
  }
30415
30676
  });
30416
30677
  });
30417
- app67.post("/__remote-auth/change-password", async (c) => {
30678
+ app69.post("/__remote-auth/change-password", async (c) => {
30418
30679
  const client = clientFrom(c);
30419
30680
  const clientIp = client.ip || "unknown";
30420
30681
  const rateLimited = checkRateLimit(client);
@@ -30473,13 +30734,13 @@ app67.post("/__remote-auth/change-password", async (c) => {
30473
30734
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
30474
30735
  }
30475
30736
  });
30476
- app67.get("/__remote-auth/setup", (c) => {
30737
+ app69.get("/__remote-auth/setup", (c) => {
30477
30738
  if (isRemoteAuthConfigured()) {
30478
30739
  return c.redirect("/");
30479
30740
  }
30480
30741
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
30481
30742
  });
30482
- app67.post("/__remote-auth/set-initial-password", async (c) => {
30743
+ app69.post("/__remote-auth/set-initial-password", async (c) => {
30483
30744
  if (isRemoteAuthConfigured()) {
30484
30745
  return c.redirect("/");
30485
30746
  }
@@ -30517,10 +30778,10 @@ app67.post("/__remote-auth/set-initial-password", async (c) => {
30517
30778
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
30518
30779
  }
30519
30780
  });
30520
- app67.get("/api/remote-auth/status", (c) => {
30781
+ app69.get("/api/remote-auth/status", (c) => {
30521
30782
  return c.json({ configured: isRemoteAuthConfigured() });
30522
30783
  });
30523
- app67.post("/api/remote-auth/set-password", async (c) => {
30784
+ app69.post("/api/remote-auth/set-password", async (c) => {
30524
30785
  let body;
30525
30786
  try {
30526
30787
  body = await c.req.json();
@@ -30559,10 +30820,10 @@ app67.post("/api/remote-auth/set-password", async (c) => {
30559
30820
  return c.json({ error: "Failed to save password" }, 500);
30560
30821
  }
30561
30822
  });
30562
- app67.route("/api/_client-error", client_error_default);
30823
+ app69.route("/api/_client-error", client_error_default);
30563
30824
  console.log("[client-error-route] mounted");
30564
30825
  var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
30565
- app67.use("*", async (c, next) => {
30826
+ app69.use("*", async (c, next) => {
30566
30827
  const host = (c.req.header("host") ?? "").split(":")[0];
30567
30828
  const path3 = c.req.path;
30568
30829
  if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
@@ -30606,28 +30867,28 @@ app67.use("*", async (c, next) => {
30606
30867
  }
30607
30868
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
30608
30869
  });
30609
- app67.route("/api/health", health_default);
30610
- app67.route("/api/chat", chatRoutes);
30611
- app67.route("/api/whatsapp", whatsapp_default);
30612
- app67.route("/api/storage", storage_broker_default);
30613
- app67.route("/api/whatsapp-reader", whatsapp_reader_default);
30614
- app67.route("/api/public-reader", public_reader_default);
30615
- app67.route("/api/webchat", createWebchatRoutes({
30870
+ app69.route("/api/health", health_default);
30871
+ app69.route("/api/chat", chatRoutes);
30872
+ app69.route("/api/whatsapp", whatsapp_default);
30873
+ app69.route("/api/storage", storage_broker_default);
30874
+ app69.route("/api/whatsapp-reader", whatsapp_reader_default);
30875
+ app69.route("/api/public-reader", public_reader_default);
30876
+ app69.route("/api/webchat", createWebchatRoutes({
30616
30877
  handleInbound: (input) => webchatGateway.handleInbound(input),
30617
30878
  // Task 940 — the permission relay's pointer read + verdict write.
30618
30879
  pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
30619
30880
  deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
30620
30881
  resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
30621
30882
  }));
30622
- app67.route("/api/webchat/greeting", webchat_greeting_default);
30623
- app67.route("/api/telegram", telegram_default);
30624
- app67.route("/api/quickbooks", quickbooks_default);
30625
- app67.route("/api/onboarding", onboarding_default);
30626
- app67.route("/api/admin", admin_default);
30627
- app67.route("/api/access", access_default);
30628
- app67.route("/api/session", session_default2);
30629
- app67.route("/api/calendar", calendar_public_default);
30630
- app67.route("/api/portal", portal_fetch_default);
30883
+ app69.route("/api/webchat/greeting", webchat_greeting_default);
30884
+ app69.route("/api/telegram", telegram_default);
30885
+ app69.route("/api/quickbooks", quickbooks_default);
30886
+ app69.route("/api/onboarding", onboarding_default);
30887
+ app69.route("/api/admin", admin_default);
30888
+ app69.route("/api/access", access_default);
30889
+ app69.route("/api/session", session_default2);
30890
+ app69.route("/api/calendar", calendar_public_default);
30891
+ app69.route("/api/portal", portal_fetch_default);
30631
30892
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
30632
30893
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
30633
30894
  var IMAGE_MIME = {
@@ -30639,7 +30900,7 @@ var IMAGE_MIME = {
30639
30900
  ".svg": "image/svg+xml",
30640
30901
  ".ico": "image/x-icon"
30641
30902
  };
30642
- app67.get("/agent-assets/:slug/:filename", (c) => {
30903
+ app69.get("/agent-assets/:slug/:filename", (c) => {
30643
30904
  const slug = c.req.param("slug");
30644
30905
  const filename = c.req.param("filename");
30645
30906
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -30655,26 +30916,26 @@ app67.get("/agent-assets/:slug/:filename", (c) => {
30655
30916
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
30656
30917
  return c.text("Not found", 404);
30657
30918
  }
30658
- const filePath = resolve43(account.accountDir, "agents", slug, "assets", filename);
30659
- const expectedDir = resolve43(account.accountDir, "agents", slug, "assets");
30919
+ const filePath = resolve44(account.accountDir, "agents", slug, "assets", filename);
30920
+ const expectedDir = resolve44(account.accountDir, "agents", slug, "assets");
30660
30921
  if (!filePath.startsWith(expectedDir + "/")) {
30661
30922
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
30662
30923
  return c.text("Forbidden", 403);
30663
30924
  }
30664
- if (!existsSync45(filePath)) {
30925
+ if (!existsSync46(filePath)) {
30665
30926
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
30666
30927
  return c.text("Not found", 404);
30667
30928
  }
30668
30929
  const ext = "." + filename.split(".").pop()?.toLowerCase();
30669
30930
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
30670
30931
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
30671
- const body = readFileSync46(filePath);
30932
+ const body = readFileSync47(filePath);
30672
30933
  return c.body(body, 200, {
30673
30934
  "Content-Type": contentType,
30674
30935
  "Cache-Control": "public, max-age=3600"
30675
30936
  });
30676
30937
  });
30677
- app67.get("/generated/:filename", (c) => {
30938
+ app69.get("/generated/:filename", (c) => {
30678
30939
  const filename = c.req.param("filename");
30679
30940
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
30680
30941
  console.error(`[generated] serve file=${filename} status=403`);
@@ -30685,35 +30946,35 @@ app67.get("/generated/:filename", (c) => {
30685
30946
  console.error(`[generated] serve file=${filename} status=404`);
30686
30947
  return c.text("Not found", 404);
30687
30948
  }
30688
- const filePath = resolve43(account.accountDir, "generated", filename);
30689
- const expectedDir = resolve43(account.accountDir, "generated");
30949
+ const filePath = resolve44(account.accountDir, "generated", filename);
30950
+ const expectedDir = resolve44(account.accountDir, "generated");
30690
30951
  if (!filePath.startsWith(expectedDir + "/")) {
30691
30952
  console.error(`[generated] serve file=${filename} status=403`);
30692
30953
  return c.text("Forbidden", 403);
30693
30954
  }
30694
- if (!existsSync45(filePath)) {
30955
+ if (!existsSync46(filePath)) {
30695
30956
  console.error(`[generated] serve file=${filename} status=404`);
30696
30957
  return c.text("Not found", 404);
30697
30958
  }
30698
30959
  const ext = "." + filename.split(".").pop()?.toLowerCase();
30699
30960
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
30700
30961
  console.log(`[generated] serve file=${filename} status=200`);
30701
- const body = readFileSync46(filePath);
30962
+ const body = readFileSync47(filePath);
30702
30963
  return c.body(body, 200, {
30703
30964
  "Content-Type": contentType,
30704
30965
  "Cache-Control": "public, max-age=86400"
30705
30966
  });
30706
30967
  });
30707
- app67.route("/sites", sites_default);
30708
- app67.route("/listings", listings_default);
30709
- app67.route("/v", visitor_event_default);
30710
- app67.route("/v", visitor_consent_default);
30968
+ app69.route("/sites", sites_default);
30969
+ app69.route("/listings", listings_default);
30970
+ app69.route("/v", visitor_event_default);
30971
+ app69.route("/v", visitor_consent_default);
30711
30972
  var htmlCache = /* @__PURE__ */ new Map();
30712
30973
  var brandLogoPath = "/brand/maxy-monochrome.png";
30713
30974
  var brandIconPath = "/brand/maxy-monochrome.png";
30714
- if (BRAND_JSON_PATH && existsSync45(BRAND_JSON_PATH)) {
30975
+ if (BRAND_JSON_PATH && existsSync46(BRAND_JSON_PATH)) {
30715
30976
  try {
30716
- const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
30977
+ const fullBrand = JSON.parse(readFileSync47(BRAND_JSON_PATH, "utf-8"));
30717
30978
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
30718
30979
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
30719
30980
  } catch {
@@ -30740,11 +31001,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
30740
31001
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
30741
31002
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
30742
31003
  var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
30743
- (p) => existsSync45(resolve43(process.cwd(), "public", p.replace(/^\//, "")))
31004
+ (p) => existsSync46(resolve44(process.cwd(), "public", p.replace(/^\//, "")))
30744
31005
  );
30745
31006
  var SW_SOURCE = (() => {
30746
31007
  try {
30747
- return readFileSync46(resolve43(process.cwd(), "public", "sw.js"), "utf-8");
31008
+ return readFileSync47(resolve44(process.cwd(), "public", "sw.js"), "utf-8");
30748
31009
  } catch {
30749
31010
  return null;
30750
31011
  }
@@ -30753,8 +31014,8 @@ function readInstalledVersion() {
30753
31014
  try {
30754
31015
  if (!PLATFORM_ROOT8) return "unknown";
30755
31016
  const versionFile = join47(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
30756
- if (!existsSync45(versionFile)) return "unknown";
30757
- const content = readFileSync46(versionFile, "utf-8").trim();
31017
+ if (!existsSync46(versionFile)) return "unknown";
31018
+ const content = readFileSync47(versionFile, "utf-8").trim();
30758
31019
  return content || "unknown";
30759
31020
  } catch {
30760
31021
  return "unknown";
@@ -30795,7 +31056,7 @@ var clientErrorReporterScript = `<script>
30795
31056
  function cachedHtml(file) {
30796
31057
  let html = htmlCache.get(file);
30797
31058
  if (!html) {
30798
- html = readFileSync46(resolve43(process.cwd(), "public", file), "utf-8");
31059
+ html = readFileSync47(resolve44(process.cwd(), "public", file), "utf-8");
30799
31060
  const productNameEsc = escapeHtml(BRAND.productName);
30800
31061
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
30801
31062
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -30817,8 +31078,8 @@ function loadBrandingCache(agentSlug) {
30817
31078
  const accountId = getDefaultAccountId();
30818
31079
  if (!accountId) return null;
30819
31080
  const cachePath = join47(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
30820
- if (!existsSync45(cachePath)) return null;
30821
- return JSON.parse(readFileSync46(cachePath, "utf-8"));
31081
+ if (!existsSync46(cachePath)) return null;
31082
+ return JSON.parse(readFileSync47(cachePath, "utf-8"));
30822
31083
  } catch {
30823
31084
  return null;
30824
31085
  }
@@ -30862,7 +31123,7 @@ function brandedPublicHtml(agentSlug) {
30862
31123
  function agentUnavailableHtml() {
30863
31124
  return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
30864
31125
  }
30865
- app67.get("/", (c) => {
31126
+ app69.get("/", (c) => {
30866
31127
  const host = (c.req.header("host") ?? "").split(":")[0];
30867
31128
  const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
30868
31129
  if (klass === "operator") {
@@ -30884,12 +31145,12 @@ app67.get("/", (c) => {
30884
31145
  console.log(`[host-class] host=${host} class=admin served=index.html`);
30885
31146
  return c.html(cachedHtml("index.html"));
30886
31147
  });
30887
- app67.get("/public", (c) => {
31148
+ app69.get("/public", (c) => {
30888
31149
  const host = (c.req.header("host") ?? "").split(":")[0];
30889
31150
  if (isPublicHost(host)) return c.text("Not found", 404);
30890
31151
  return c.html(cachedHtml("public.html"));
30891
31152
  });
30892
- app67.get("/public-chat", (c) => {
31153
+ app69.get("/public-chat", (c) => {
30893
31154
  const host = (c.req.header("host") ?? "").split(":")[0];
30894
31155
  if (isPublicHost(host)) return c.text("Not found", 404);
30895
31156
  return c.html(cachedHtml("public.html"));
@@ -30908,12 +31169,12 @@ async function logViewerFetch(c, next) {
30908
31169
  duration_ms: Date.now() - start
30909
31170
  });
30910
31171
  }
30911
- app67.use("/vnc-viewer.html", logViewerFetch);
30912
- app67.use("/vnc-popout.html", logViewerFetch);
30913
- app67.get("/vnc-popout.html", (c) => {
31172
+ app69.use("/vnc-viewer.html", logViewerFetch);
31173
+ app69.use("/vnc-popout.html", logViewerFetch);
31174
+ app69.get("/vnc-popout.html", (c) => {
30914
31175
  let html = htmlCache.get("vnc-popout.html");
30915
31176
  if (!html) {
30916
- html = readFileSync46(resolve43(process.cwd(), "public", "vnc-popout.html"), "utf-8");
31177
+ html = readFileSync47(resolve44(process.cwd(), "public", "vnc-popout.html"), "utf-8");
30917
31178
  const name = escapeHtml(BRAND.productName);
30918
31179
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
30919
31180
  html = html.replace("</head>", ` ${brandScript}
@@ -30923,7 +31184,7 @@ app67.get("/vnc-popout.html", (c) => {
30923
31184
  }
30924
31185
  return c.html(html);
30925
31186
  });
30926
- app67.post("/api/vnc/client-event", async (c) => {
31187
+ app69.post("/api/vnc/client-event", async (c) => {
30927
31188
  let body;
30928
31189
  try {
30929
31190
  body = await c.req.json();
@@ -30944,11 +31205,11 @@ app67.post("/api/vnc/client-event", async (c) => {
30944
31205
  });
30945
31206
  return c.json({ ok: true });
30946
31207
  });
30947
- app67.get("/g/:slug", (c) => {
31208
+ app69.get("/g/:slug", (c) => {
30948
31209
  return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
30949
31210
  });
30950
31211
  for (const pwa of PWA_SURFACES) {
30951
- app67.get(pwa.manifestPath, (c) => {
31212
+ app69.get(pwa.manifestPath, (c) => {
30952
31213
  const manifest = buildManifest(pwa, {
30953
31214
  productName: BRAND.productName,
30954
31215
  appIcon192: brandAppIcon192Path,
@@ -30964,7 +31225,7 @@ for (const pwa of PWA_SURFACES) {
30964
31225
  return c.body(JSON.stringify(manifest));
30965
31226
  });
30966
31227
  }
30967
- app67.get("/sw.js", (c) => {
31228
+ app69.get("/sw.js", (c) => {
30968
31229
  if (SW_SOURCE == null) {
30969
31230
  console.error("[pwa] op=sw status=500 reason=sw-source-missing");
30970
31231
  return c.text("Service worker unavailable", 500);
@@ -30973,12 +31234,12 @@ app67.get("/sw.js", (c) => {
30973
31234
  console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
30974
31235
  return c.body(SW_SOURCE);
30975
31236
  });
30976
- app67.get("/graph", (c) => {
31237
+ app69.get("/graph", (c) => {
30977
31238
  const host = (c.req.header("host") ?? "").split(":")[0];
30978
31239
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
30979
31240
  return c.html(cachedHtml("graph.html"));
30980
31241
  });
30981
- app67.get("/chat", (c) => {
31242
+ app69.get("/chat", (c) => {
30982
31243
  const host = (c.req.header("host") ?? "").split(":")[0];
30983
31244
  if (isOperatorHost(host, getOperatorDomains())) {
30984
31245
  console.log(`[host-class] host=${host} class=operator served=operator.html`);
@@ -30987,42 +31248,47 @@ app67.get("/chat", (c) => {
30987
31248
  if (isPublicHost(host)) return c.text("Not found", 404);
30988
31249
  return c.html(cachedHtml("chat.html"));
30989
31250
  });
30990
- app67.get("/data", (c) => {
31251
+ app69.get("/data", (c) => {
30991
31252
  const host = (c.req.header("host") ?? "").split(":")[0];
30992
31253
  if (isPublicHost(host)) return c.text("Not found", 404);
30993
31254
  return c.html(cachedHtml("data.html"));
30994
31255
  });
30995
- app67.get("/tasks", (c) => {
31256
+ app69.get("/tasks", (c) => {
30996
31257
  const host = (c.req.header("host") ?? "").split(":")[0];
30997
31258
  if (isPublicHost(host)) return c.text("Not found", 404);
30998
31259
  return c.html(cachedHtml("tasks.html"));
30999
31260
  });
31000
- app67.get("/activity", (c) => {
31261
+ app69.get("/activity", (c) => {
31001
31262
  const host = (c.req.header("host") ?? "").split(":")[0];
31002
31263
  if (isPublicHost(host)) return c.text("Not found", 404);
31003
31264
  return c.html(cachedHtml("activity.html"));
31004
31265
  });
31005
- app67.get("/calendar", (c) => {
31266
+ app69.get("/calendar", (c) => {
31006
31267
  const host = (c.req.header("host") ?? "").split(":")[0];
31007
31268
  if (isPublicHost(host)) return c.text("Not found", 404);
31008
31269
  return c.html(cachedHtml("calendar.html"));
31009
31270
  });
31010
- app67.get("/routines", (c) => {
31271
+ app69.get("/routines", (c) => {
31011
31272
  const host = (c.req.header("host") ?? "").split(":")[0];
31012
31273
  if (isPublicHost(host)) return c.text("Not found", 404);
31013
31274
  return c.html(cachedHtml("routines.html"));
31014
31275
  });
31015
- app67.get("/skills", (c) => {
31276
+ app69.get("/skills", (c) => {
31016
31277
  const host = (c.req.header("host") ?? "").split(":")[0];
31017
31278
  if (isPublicHost(host)) return c.text("Not found", 404);
31018
31279
  return c.html(cachedHtml("skills.html"));
31019
31280
  });
31020
- app67.get("/browser", (c) => {
31281
+ app69.get("/agents", (c) => {
31282
+ const host = (c.req.header("host") ?? "").split(":")[0];
31283
+ if (isPublicHost(host)) return c.text("Not found", 404);
31284
+ return c.html(cachedHtml("agents.html"));
31285
+ });
31286
+ app69.get("/browser", (c) => {
31021
31287
  const host = (c.req.header("host") ?? "").split(":")[0];
31022
31288
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
31023
31289
  return c.html(cachedHtml("browser.html"));
31024
31290
  });
31025
- app67.get("/:slug", async (c, next) => {
31291
+ app69.get("/:slug", async (c, next) => {
31026
31292
  const slug = c.req.param("slug");
31027
31293
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
31028
31294
  const account = resolveAccount();
@@ -31037,13 +31303,13 @@ app67.get("/:slug", async (c, next) => {
31037
31303
  await next();
31038
31304
  });
31039
31305
  if (brandFaviconPath !== "/favicon.ico") {
31040
- app67.get("/favicon.ico", (c) => {
31306
+ app69.get("/favicon.ico", (c) => {
31041
31307
  c.header("Cache-Control", "public, max-age=300");
31042
31308
  return c.redirect(brandFaviconPath, 302);
31043
31309
  });
31044
31310
  }
31045
- app67.use("/*", serveStatic({ root: "./public" }));
31046
- app67.all("*", (c) => {
31311
+ app69.use("/*", serveStatic({ root: "./public" }));
31312
+ app69.all("*", (c) => {
31047
31313
  const host = (c.req.header("host") ?? "").split(":")[0];
31048
31314
  const path3 = c.req.path;
31049
31315
  if (isPublicHost(host)) {
@@ -31057,13 +31323,13 @@ app67.all("*", (c) => {
31057
31323
  });
31058
31324
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
31059
31325
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
31060
- var httpServer = serve({ fetch: app67.fetch, port, hostname });
31326
+ var httpServer = serve({ fetch: app69.fetch, port, hostname });
31061
31327
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31062
31328
  {
31063
31329
  const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31064
- const reconcileScript = resolve43(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
31330
+ const reconcileScript = resolve44(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
31065
31331
  const runReconcile = (ctx) => {
31066
- if (!existsSync45(reconcileScript)) return;
31332
+ if (!existsSync46(reconcileScript)) return;
31067
31333
  try {
31068
31334
  const child = spawn3(process.execPath, [reconcileScript], {
31069
31335
  env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
@@ -31102,14 +31368,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31102
31368
  {
31103
31369
  const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
31104
31370
  const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31105
- const dreamSweepScript = resolve43(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31371
+ const dreamSweepScript = resolve44(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31106
31372
  registerLoop({
31107
31373
  name: "dream-cycle-sweep",
31108
31374
  intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
31109
31375
  firstRunDelayMs: 3e4,
31110
31376
  detached: true,
31111
31377
  run: (ctx) => {
31112
- if (!existsSync45(dreamSweepScript)) return;
31378
+ if (!existsSync46(dreamSweepScript)) return;
31113
31379
  try {
31114
31380
  const child = spawn3(process.execPath, [dreamSweepScript], {
31115
31381
  env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
@@ -31126,10 +31392,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31126
31392
  }
31127
31393
  {
31128
31394
  const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31129
- const outlookScript = resolve43(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31395
+ const outlookScript = resolve44(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31130
31396
  const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
31131
31397
  const runOutlookComplete = (ctx) => {
31132
- if (!existsSync45(outlookScript)) return;
31398
+ if (!existsSync46(outlookScript)) return;
31133
31399
  try {
31134
31400
  const child = spawn3(process.execPath, [outlookScript], {
31135
31401
  env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
@@ -31152,18 +31418,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31152
31418
  }
31153
31419
  {
31154
31420
  const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31155
- const strandedAccountsDir = resolve43(auditRoot, "..", "data/accounts");
31421
+ const strandedAccountsDir = resolve44(auditRoot, "..", "data/accounts");
31156
31422
  const STRANDED_AUDIT_INTERVAL_MS = 3e5;
31157
31423
  const STRANDED_AGE_MS = 16 * 6e4;
31158
31424
  const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31159
31425
  const runStrandedAudit = () => {
31160
31426
  try {
31161
- if (!existsSync45(strandedAccountsDir)) return;
31427
+ if (!existsSync46(strandedAccountsDir)) return;
31162
31428
  const now = Date.now();
31163
- for (const name of readdirSync27(strandedAccountsDir)) {
31429
+ for (const name of readdirSync28(strandedAccountsDir)) {
31164
31430
  if (!STRANDED_UUID_RE.test(name)) continue;
31165
- const pendingPath2 = resolve43(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31166
- if (!existsSync45(pendingPath2)) continue;
31431
+ const pendingPath2 = resolve44(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31432
+ if (!existsSync46(pendingPath2)) continue;
31167
31433
  const ageMs2 = now - statSync20(pendingPath2).mtimeMs;
31168
31434
  if (ageMs2 > STRANDED_AGE_MS) {
31169
31435
  console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
@@ -31182,7 +31448,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31182
31448
  }
31183
31449
  {
31184
31450
  const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31185
- const googleAccountsDir = resolve43(googleRoot, "..", "data/accounts");
31451
+ const googleAccountsDir = resolve44(googleRoot, "..", "data/accounts");
31186
31452
  const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
31187
31453
  const runGooglePendingAuditSafe = () => {
31188
31454
  try {
@@ -31197,10 +31463,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31197
31463
  firstRunDelayMs: 27e3,
31198
31464
  run: runGooglePendingAuditSafe
31199
31465
  });
31200
- const googleAuditScript = resolve43(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31466
+ const googleAuditScript = resolve44(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31201
31467
  const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
31202
31468
  const runGoogleAccountAudit = (ctx) => {
31203
- if (!existsSync45(googleAuditScript)) return;
31469
+ if (!existsSync46(googleAuditScript)) return;
31204
31470
  try {
31205
31471
  const child = spawn3(process.execPath, [googleAuditScript], {
31206
31472
  env: { ...process.env, PLATFORM_ROOT: googleRoot },
@@ -31272,7 +31538,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31272
31538
  }
31273
31539
  {
31274
31540
  const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31275
- const publishScript = resolve43(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31541
+ const publishScript = resolve44(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31276
31542
  const PUBLISH_INTERVAL_MS = 3e5;
31277
31543
  const bookingAccounts = () => {
31278
31544
  try {
@@ -31283,7 +31549,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31283
31549
  }
31284
31550
  };
31285
31551
  const spawnPublish = (account, ctx) => {
31286
- if (!existsSync45(publishScript)) return;
31552
+ if (!existsSync46(publishScript)) return;
31287
31553
  try {
31288
31554
  const child = spawn3(process.execPath, [publishScript], {
31289
31555
  env: {
@@ -31302,21 +31568,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31302
31568
  }
31303
31569
  };
31304
31570
  const auditSnapshotAge = (account) => {
31305
- const availPath = resolve43(account.accountDir, "calendar-availability.json");
31571
+ const availPath = resolve44(account.accountDir, "calendar-availability.json");
31306
31572
  let hasBookingSite = false;
31307
31573
  try {
31308
- if (existsSync45(availPath)) {
31309
- const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
31574
+ if (existsSync46(availPath)) {
31575
+ const cfg = JSON.parse(readFileSync47(availPath, "utf-8"));
31310
31576
  hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
31311
31577
  }
31312
31578
  } catch {
31313
31579
  }
31314
31580
  if (!hasBookingSite) return;
31315
- const statePath = resolve43(account.accountDir, "state", "booking-availability", "last-publish.json");
31581
+ const statePath = resolve44(account.accountDir, "state", "booking-availability", "last-publish.json");
31316
31582
  let lastSuccessAt = null;
31317
- if (existsSync45(statePath)) {
31583
+ if (existsSync46(statePath)) {
31318
31584
  try {
31319
- const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
31585
+ const rec = JSON.parse(readFileSync47(statePath, "utf-8"));
31320
31586
  lastSuccessAt = rec.lastSuccessAt ?? null;
31321
31587
  } catch {
31322
31588
  console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
@@ -31349,11 +31615,11 @@ startTimeEntryCensus(() => getSession());
31349
31615
  startLedgerCensus(() => getSession());
31350
31616
  {
31351
31617
  const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..");
31352
- const auditScript = resolve43(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31618
+ const auditScript = resolve44(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31353
31619
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
31354
31620
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
31355
31621
  const runConnectorAudit = (ctx) => {
31356
- if (!existsSync45(auditScript)) return;
31622
+ if (!existsSync46(auditScript)) return;
31357
31623
  try {
31358
31624
  const child = spawn3(process.execPath, [auditScript], {
31359
31625
  env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
@@ -31433,7 +31699,7 @@ for (const m of SUBAPP_MANIFEST) {
31433
31699
  }
31434
31700
  try {
31435
31701
  const registered = [];
31436
- for (const r of app67.routes ?? []) {
31702
+ for (const r of app69.routes ?? []) {
31437
31703
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
31438
31704
  if (AGENT_SLUG_PATTERN.test(r.path)) {
31439
31705
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -31473,11 +31739,11 @@ try {
31473
31739
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31474
31740
  async function runAdminUserReconcileTick() {
31475
31741
  try {
31476
- if (!existsSync45(USERS_FILE)) {
31742
+ if (!existsSync46(USERS_FILE)) {
31477
31743
  console.error("[adminuser-self-heal] skip reason=no-users-file");
31478
31744
  return;
31479
31745
  }
31480
- const usersRaw = readFileSync46(USERS_FILE, "utf-8").trim();
31746
+ const usersRaw = readFileSync47(USERS_FILE, "utf-8").trim();
31481
31747
  if (!usersRaw) {
31482
31748
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
31483
31749
  return;
@@ -31524,8 +31790,8 @@ registerLoop({
31524
31790
  });
31525
31791
  var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31526
31792
  function countUsersRows() {
31527
- if (!existsSync45(USERS_FILE)) return 0;
31528
- const raw = readFileSync46(USERS_FILE, "utf-8").trim();
31793
+ if (!existsSync46(USERS_FILE)) return 0;
31794
+ const raw = readFileSync47(USERS_FILE, "utf-8").trim();
31529
31795
  if (!raw) return 0;
31530
31796
  const users = JSON.parse(raw);
31531
31797
  return users.filter((u) => typeof u.userId === "string").length;
@@ -31658,7 +31924,7 @@ if (bootAccountConfig?.whatsapp) {
31658
31924
  }
31659
31925
  init({
31660
31926
  configDir: configDirForWhatsApp,
31661
- platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
31927
+ platformRoot: resolve44(process.env.MAXY_PLATFORM_ROOT ?? join47(__dirname, "..")),
31662
31928
  accountConfig: bootAccountConfig,
31663
31929
  onMessage: async (msg) => {
31664
31930
  if (isObserveAccount(msg.accountId)) {