@rubytech/create-maxy-code 0.1.503 → 0.1.505

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