@rubytech/create-maxy-code 0.1.294 → 0.1.296

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 (194) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/models/dist/index.d.ts +1 -0
  3. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/models/dist/index.js +4 -2
  5. package/payload/platform/lib/models/dist/index.js.map +1 -1
  6. package/payload/platform/lib/models/src/index.ts +3 -1
  7. package/payload/platform/neo4j/schema.cypher +10 -2
  8. package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +27 -0
  9. package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +24 -5
  10. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +22 -4
  11. package/payload/platform/plugins/docs/references/admin-ui.md +19 -2
  12. package/payload/platform/plugins/docs/references/platform.md +2 -1
  13. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts +2 -0
  14. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts.map +1 -0
  15. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js +214 -0
  16. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js.map +1 -0
  17. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +1 -0
  18. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  19. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts +2 -0
  20. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts.map +1 -0
  21. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js +113 -0
  22. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js.map +1 -0
  23. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +52 -2
  24. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +90 -4
  26. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
  27. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +1 -0
  28. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -1
  29. package/payload/platform/plugins/memory/mcp/vitest.config.ts +3 -0
  30. package/payload/platform/plugins/memory/references/schema-base.md +6 -2
  31. package/payload/platform/plugins/memory/references/schema-construction.md +8 -6
  32. package/payload/platform/plugins/memory/references/schema-estate-agent.md +1 -1
  33. package/payload/platform/scripts/smoke-boot-services.sh +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  35. package/payload/platform/services/claude-session-manager/dist/http-server.js +23 -3
  36. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +9 -0
  38. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  39. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +14 -0
  40. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  41. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -4
  42. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +7 -4
  44. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  45. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts +3 -0
  46. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts.map +1 -0
  47. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js +28 -0
  48. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js.map +1 -0
  49. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +10 -0
  50. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  51. package/payload/platform/services/whatsapp-channel/dist/notification.js +15 -0
  52. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  53. package/payload/platform/templates/account.json +1 -1
  54. package/payload/platform/templates/specialists/agents/data-manager.md +27 -0
  55. package/payload/server/public/assets/AdminShell-DDieHnzi.js +1 -0
  56. package/payload/server/public/assets/{Checkbox-DxOCnNT7.js → Checkbox-DTrIyIFP.js} +1 -1
  57. package/payload/server/public/assets/{Transcript-BIhFafaZ.js → Transcript-C3aDVJ-n.js} +1 -1
  58. package/payload/server/public/assets/{admin-CGjBmQRF.js → admin-DVdyV-Q6.js} +1 -1
  59. package/payload/server/public/assets/{arc-CL2g6wtE.js → arc-DmR-LPIx.js} +1 -1
  60. package/payload/server/public/assets/architecture-YZFGNWBL-CjF2k79a.js +1 -0
  61. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-B6pI_4kf.js → architectureDiagram-Q4EWVU46-DR9W0q1P.js} +1 -1
  62. package/payload/server/public/assets/audio-attachment-mime-DGEfApkA.js +1 -0
  63. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-OTjX8onE.js → blockDiagram-DXYQGD6D-C3uwaI7p.js} +1 -1
  64. package/payload/server/public/assets/{browser-Bf0v--kb.js → browser-DrJReVEG.js} +1 -1
  65. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-d3BJbhwh.js → c4Diagram-AHTNJAMY-C8hmUDdd.js} +1 -1
  66. package/payload/server/public/assets/channel-drVqp11B.js +1 -0
  67. package/payload/server/public/assets/chat-rJYaCD6C.js +1 -0
  68. package/payload/server/public/assets/{chunk-2KRD3SAO-CjdgBkCI.js → chunk-2KRD3SAO-BYqpHDvA.js} +1 -1
  69. package/payload/server/public/assets/{chunk-336JU56O-77Kuo1_M.js → chunk-336JU56O-BRCubMCb.js} +2 -2
  70. package/payload/server/public/assets/chunk-426QAEUC-BNINkVsL.js +1 -0
  71. package/payload/server/public/assets/{chunk-4BX2VUAB-CJ-bacvW.js → chunk-4BX2VUAB-BeDVr5Tb.js} +1 -1
  72. package/payload/server/public/assets/{chunk-4TB4RGXK-C7oTm4E0.js → chunk-4TB4RGXK-DSMj_AZh.js} +1 -1
  73. package/payload/server/public/assets/{chunk-55IACEB6-BGVu8gHm.js → chunk-55IACEB6-DB18cH4S.js} +1 -1
  74. package/payload/server/public/assets/{chunk-5FUZZQ4R-BBHRG4DD.js → chunk-5FUZZQ4R-6DNGaUkf.js} +1 -1
  75. package/payload/server/public/assets/{chunk-5PVQY5BW-BbxYk0vN.js → chunk-5PVQY5BW-DPhkkS4p.js} +1 -1
  76. package/payload/server/public/assets/{chunk-67CJDMHE-DCXRVLld.js → chunk-67CJDMHE-Ca9KwdQm.js} +1 -1
  77. package/payload/server/public/assets/{chunk-7N4EOEYR-Cb8gnv2L.js → chunk-7N4EOEYR-BDpzHOmv.js} +1 -1
  78. package/payload/server/public/assets/{chunk-AA7GKIK3-BDKd8RHS.js → chunk-AA7GKIK3-DXo9fZho.js} +1 -1
  79. package/payload/server/public/assets/{chunk-BSJP7CBP-C-a5U7hf.js → chunk-BSJP7CBP-CTqmM6qI.js} +1 -1
  80. package/payload/server/public/assets/{chunk-CIAEETIT-C2s4AWWp.js → chunk-CIAEETIT-NufEId2j.js} +1 -1
  81. package/payload/server/public/assets/{chunk-EDXVE4YY-C_NxZc3q.js → chunk-EDXVE4YY-BjWSqn7_.js} +1 -1
  82. package/payload/server/public/assets/{chunk-ENJZ2VHE-CP-iwXd0.js → chunk-ENJZ2VHE-BX1ZnU4A.js} +1 -1
  83. package/payload/server/public/assets/{chunk-FMBD7UC4-Cb04mvB7.js → chunk-FMBD7UC4-_4wtKsfc.js} +1 -1
  84. package/payload/server/public/assets/{chunk-FOC6F5B3-B1tHdg5H.js → chunk-FOC6F5B3-565zaYb3.js} +1 -1
  85. package/payload/server/public/assets/{chunk-ICPOFSXX-BlGsRet_.js → chunk-ICPOFSXX-DvYSWH7x.js} +2 -2
  86. package/payload/server/public/assets/{chunk-K5T4RW27-I1-reqf9.js → chunk-K5T4RW27-CTZnA5fq.js} +1 -1
  87. package/payload/server/public/assets/{chunk-KGLVRYIC-Dz5VoWZh.js → chunk-KGLVRYIC-CeuKp7uR.js} +1 -1
  88. package/payload/server/public/assets/{chunk-LIHQZDEY-CJVhgo59.js → chunk-LIHQZDEY-DXkzlh3_.js} +1 -1
  89. package/payload/server/public/assets/{chunk-ORNJ4GCN-B236VjaQ.js → chunk-ORNJ4GCN-DcZUCmgM.js} +1 -1
  90. package/payload/server/public/assets/{chunk-OYMX7WX6-CqSmIaQf.js → chunk-OYMX7WX6-7_m3mEOK.js} +1 -1
  91. package/payload/server/public/assets/chunk-QZHKN3VN-CBWmDBHe.js +1 -0
  92. package/payload/server/public/assets/{chunk-U2HBQHQK-CeMKC3D0.js → chunk-U2HBQHQK-Bl1a895I.js} +1 -1
  93. package/payload/server/public/assets/{chunk-X2U36JSP-DK30THxZ.js → chunk-X2U36JSP-WkSpBPYx.js} +1 -1
  94. package/payload/server/public/assets/{chunk-XPW4576I-DVW18Ukl.js → chunk-XPW4576I-CnU6DVpC.js} +1 -1
  95. package/payload/server/public/assets/{chunk-YZCP3GAM-DxfWX7Ap.js → chunk-YZCP3GAM-DpWRmPUo.js} +1 -1
  96. package/payload/server/public/assets/{chunk-ZZ45TVLE-BEQSVm39.js → chunk-ZZ45TVLE-D9Dgmeso.js} +1 -1
  97. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Dplkw_pj.js +1 -0
  98. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sJXv1Ihp.js +1 -0
  99. package/payload/server/public/assets/clone-Q_B6oO0c.js +1 -0
  100. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-BcEd1xsZ.js → cose-bilkent-S5V4N54A-C04wkJr7.js} +1 -1
  101. package/payload/server/public/assets/{dagre-KV5264BT-BBzAnJNh.js → dagre-KV5264BT-DPq3dcLH.js} +1 -1
  102. package/payload/server/public/assets/{dagre-Ch3nCevh.js → dagre-PrVfCcSt.js} +1 -1
  103. package/payload/server/public/assets/data-CYyR2m_B.js +1 -0
  104. package/payload/server/public/assets/{diagram-5BDNPKRD-BG13t9mu.js → diagram-5BDNPKRD-DoszElKb.js} +1 -1
  105. package/payload/server/public/assets/{diagram-G4DWMVQ6-DYh2zRvB.js → diagram-G4DWMVQ6-BRuqosix.js} +1 -1
  106. package/payload/server/public/assets/{diagram-MMDJMWI5-CNMjDPoP.js → diagram-MMDJMWI5-CpigG1d_.js} +1 -1
  107. package/payload/server/public/assets/{diagram-TYMM5635-BAb8gFOW.js → diagram-TYMM5635-BS0eYiq9.js} +1 -1
  108. package/payload/server/public/assets/{erDiagram-SMLLAGMA-Dy4ADi6A.js → erDiagram-SMLLAGMA-VEQyXCFl.js} +1 -1
  109. package/payload/server/public/assets/file-download-C3pBZjt9.js +1 -0
  110. package/payload/server/public/assets/{flatten-E2Sr0FeD.js → flatten-DeFkSYLU.js} +1 -1
  111. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-DSMf9IO0.js → flowDiagram-DWJPFMVM-2NYMfqHX.js} +1 -1
  112. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRj0wip6.js → ganttDiagram-T4ZO3ILL-AAAa2sqE.js} +1 -1
  113. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DsUTwRUb.js +1 -0
  114. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-D5s87wIr.js → gitGraphDiagram-UUTBAWPF-d8NUAIz5.js} +1 -1
  115. package/payload/server/public/assets/graph-Bx9_2qbJ.js +51 -0
  116. package/payload/server/public/assets/{graph-labels-DsXyfwKP.js → graph-labels-Cc1nU1_f.js} +1 -1
  117. package/payload/server/public/assets/{graphlib-DBueCu-j.js → graphlib-DUlqr2mr.js} +1 -1
  118. package/payload/server/public/assets/info-OMHHGYJF-BV9FyUXQ.js +1 -0
  119. package/payload/server/public/assets/infoDiagram-42DDH7IO-D4dh4-0g.js +2 -0
  120. package/payload/server/public/assets/{isEmpty-CLz-UprQ.js → isEmpty-Bn-Se8yT.js} +1 -1
  121. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BoMwv4cD.js → ishikawaDiagram-UXIWVN3A-DPTmm2IE.js} +1 -1
  122. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-BkKxK7iC.js → journeyDiagram-VCZTEJTY-B85vjqkE.js} +1 -1
  123. package/payload/server/public/assets/jsx-runtime-D3PZpOAF.css +1 -0
  124. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BSrkzXlb.js → kanban-definition-6JOO6SKY-C2Lfb5Xh.js} +1 -1
  125. package/payload/server/public/assets/{line-CMDTDopn.js → line-CODKFpwO.js} +1 -1
  126. package/payload/server/public/assets/{linear-CKifLODy.js → linear-CgbkJiu6.js} +1 -1
  127. package/payload/server/public/assets/{mermaid-parser.core-CEH6m0Lv.js → mermaid-parser.core-DYdFZnXH.js} +2 -2
  128. package/payload/server/public/assets/{mermaid.core-DyAGyaJG.js → mermaid.core-Bamjzahu.js} +3 -3
  129. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DLZa0d69.js → mindmap-definition-QFDTVHPH-CLK90bKJ.js} +1 -1
  130. package/payload/server/public/assets/{ordinal-5RtyPJVt.js → ordinal-C-EimP2j.js} +1 -1
  131. package/payload/server/public/assets/packet-4T2RLAQJ-SXjQ83Vr.js +1 -0
  132. package/payload/server/public/assets/pie-ZZUOXDRM-q7TXebDD.js +1 -0
  133. package/payload/server/public/assets/{pieDiagram-DEJITSTG-zTOJvniq.js → pieDiagram-DEJITSTG-DEsnxhqP.js} +1 -1
  134. package/payload/server/public/assets/public-BFMu-jux.js +35 -0
  135. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CHzDGI4U.js → quadrantDiagram-34T5L4WZ-uIP9V2jZ.js} +1 -1
  136. package/payload/server/public/assets/radar-PYXPWWZC-CXKUHVMS.js +1 -0
  137. package/payload/server/public/assets/{reduce-B3Mw_0s1.js → reduce-B0wq8DtH.js} +1 -1
  138. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CrrYBRTT.js → requirementDiagram-MS252O5E-CVS6t5tv.js} +1 -1
  139. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-EEi77dbS.js → sankeyDiagram-XADWPNL6-BIsmtyZA.js} +1 -1
  140. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BNeO1Hdg.js → sequenceDiagram-FGHM5R23-Cu8TfQiW.js} +1 -1
  141. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-9Zyf6fFj.js → stateDiagram-FHFEXIEX-ax4vYGft.js} +1 -1
  142. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BRv1By5g.js +1 -0
  143. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-DRCVn4rg.js → timeline-definition-GMOUNBTQ-3l7ojkMA.js} +1 -1
  144. package/payload/server/public/assets/treeView-SZITEDCU-CWuFgUeJ.js +1 -0
  145. package/payload/server/public/assets/treemap-W4RFUUIX-gKO4rbgo.js +1 -0
  146. package/payload/server/public/assets/{useSelectionMode-CVoG6qb0.js → useSelectionMode-C_EBRd2k.js} +1 -1
  147. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CNaA1Bcg.js → vennDiagram-DHZGUBPP-C_sv0qMD.js} +1 -1
  148. package/payload/server/public/assets/wardley-RL74JXVD-hDEw8pJN.js +1 -0
  149. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-9BoBW3Oo.js → wardleyDiagram-NUSXRM2D-C7u4IHMB.js} +1 -1
  150. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CAXyPTsj.js → xychartDiagram-5P7HB3ND-A-uLXr1a.js} +1 -1
  151. package/payload/server/public/browser.html +6 -6
  152. package/payload/server/public/chat.html +8 -9
  153. package/payload/server/public/data.html +5 -5
  154. package/payload/server/public/graph.html +8 -9
  155. package/payload/server/public/index.html +8 -8
  156. package/payload/server/public/public.html +6 -6
  157. package/payload/server/server.js +558 -275
  158. package/payload/server/public/assets/AdminShell-t3IuI7JZ.js +0 -1
  159. package/payload/server/public/assets/architecture-YZFGNWBL-DLCnSHk9.js +0 -1
  160. package/payload/server/public/assets/channel-BEqls8-f.js +0 -1
  161. package/payload/server/public/assets/chat-DJ3nvES3.js +0 -1
  162. package/payload/server/public/assets/chunk-426QAEUC-TEFdhIy5.js +0 -1
  163. package/payload/server/public/assets/chunk-QZHKN3VN-CcHV2DdO.js +0 -1
  164. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CtuzQYGd.js +0 -1
  165. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CnyF9bus.js +0 -1
  166. package/payload/server/public/assets/clone-HKYySpjZ.js +0 -1
  167. package/payload/server/public/assets/data-BNqGUTEs.js +0 -1
  168. package/payload/server/public/assets/file-download-BUeQHzJD.js +0 -1
  169. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DOHzO_KB.js +0 -1
  170. package/payload/server/public/assets/graph-C4FX88ML.js +0 -51
  171. package/payload/server/public/assets/info-OMHHGYJF-CgstATO5.js +0 -1
  172. package/payload/server/public/assets/infoDiagram-42DDH7IO--6bwMJZM.js +0 -2
  173. package/payload/server/public/assets/jsx-runtime-61OZ_8PV.css +0 -1
  174. package/payload/server/public/assets/mic-BXINsrwF.js +0 -1
  175. package/payload/server/public/assets/packet-4T2RLAQJ-BRSJpaWt.js +0 -1
  176. package/payload/server/public/assets/pie-ZZUOXDRM-B5VBvTzX.js +0 -1
  177. package/payload/server/public/assets/public-Cya9ie76.js +0 -35
  178. package/payload/server/public/assets/radar-PYXPWWZC-CWBqEfap.js +0 -1
  179. package/payload/server/public/assets/sliders-horizontal-CUmlgKbR.js +0 -1
  180. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-PeqMIgxs.js +0 -1
  181. package/payload/server/public/assets/treeView-SZITEDCU-D8zjIvCq.js +0 -1
  182. package/payload/server/public/assets/treemap-W4RFUUIX-DQW69zQK.js +0 -1
  183. package/payload/server/public/assets/wardley-RL74JXVD-CDTm6Cdu.js +0 -1
  184. /package/payload/server/public/assets/{_baseFor-DVaNaTfF.js → _baseFor-BV-TyLWt.js} +0 -0
  185. /package/payload/server/public/assets/{array-8_H1156C.js → array-lqrvkwy7.js} +0 -0
  186. /package/payload/server/public/assets/{cytoscape.esm-h10p_6j-.js → cytoscape.esm-SmEOayFS.js} +0 -0
  187. /package/payload/server/public/assets/{defaultLocale-pD7tFa1r.js → defaultLocale-Dl3Sud5K.js} +0 -0
  188. /package/payload/server/public/assets/{dist-DHQbMi0P.js → dist-Pgmncqde.js} +0 -0
  189. /package/payload/server/public/assets/{init-CwJ4b81e.js → init-BukMwkmL.js} +0 -0
  190. /package/payload/server/public/assets/{jsx-runtime-GpAtq6d8.js → jsx-runtime-5auA0FEj.js} +0 -0
  191. /package/payload/server/public/assets/{katex-DJPjIBAI.js → katex-jl-BtNZi.js} +0 -0
  192. /package/payload/server/public/assets/{path-CK8wrAxY.js → path-DPTRcLku.js} +0 -0
  193. /package/payload/server/public/assets/{rough.esm-Dwml_la6.js → rough.esm-VLpapkIG.js} +0 -0
  194. /package/payload/server/public/assets/{src-CglFLxOI.js → src-CozP7LCe.js} +0 -0
@@ -1214,8 +1214,8 @@ var serveStatic = (options = { root: "" }) => {
1214
1214
  };
1215
1215
 
1216
1216
  // server/index.ts
1217
- import { readFileSync as readFileSync24, existsSync as existsSync25, watchFile } from "fs";
1218
- import { resolve as resolve27, join as join20, basename as basename8 } from "path";
1217
+ import { readFileSync as readFileSync26, existsSync as existsSync26, watchFile } from "fs";
1218
+ import { resolve as resolve28, join as join21, basename as basename8 } from "path";
1219
1219
  import { homedir as homedir3 } from "os";
1220
1220
  import { monitorEventLoopDelay } from "perf_hooks";
1221
1221
 
@@ -1794,7 +1794,7 @@ var credsSaveQueue = Promise.resolve();
1794
1794
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1795
1795
  console.error(`${TAG2} draining credential save queue\u2026`);
1796
1796
  const timer2 = new Promise(
1797
- (resolve28) => setTimeout(() => resolve28("timeout"), timeoutMs)
1797
+ (resolve29) => setTimeout(() => resolve29("timeout"), timeoutMs)
1798
1798
  );
1799
1799
  const result = await Promise.race([
1800
1800
  credsSaveQueue.then(() => "drained"),
@@ -1922,11 +1922,11 @@ async function createWaSocket(opts) {
1922
1922
  return sock;
1923
1923
  }
1924
1924
  async function waitForConnection(sock) {
1925
- return new Promise((resolve28, reject) => {
1925
+ return new Promise((resolve29, reject) => {
1926
1926
  const handler = (update) => {
1927
1927
  if (update.connection === "open") {
1928
1928
  sock.ev.off("connection.update", handler);
1929
- resolve28();
1929
+ resolve29();
1930
1930
  }
1931
1931
  if (update.connection === "close") {
1932
1932
  sock.ev.off("connection.update", handler);
@@ -2040,14 +2040,14 @@ ${inspected}`;
2040
2040
  return inspect2(err, INSPECT_OPTS2);
2041
2041
  }
2042
2042
  function withTimeout(label, promise, timeoutMs) {
2043
- return new Promise((resolve28, reject) => {
2043
+ return new Promise((resolve29, reject) => {
2044
2044
  const timer2 = setTimeout(() => {
2045
2045
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2046
2046
  }, timeoutMs);
2047
2047
  promise.then(
2048
2048
  (value) => {
2049
2049
  clearTimeout(timer2);
2050
- resolve28(value);
2050
+ resolve29(value);
2051
2051
  },
2052
2052
  (err) => {
2053
2053
  clearTimeout(timer2);
@@ -2646,8 +2646,8 @@ async function persistWhatsAppMessage(input) {
2646
2646
  const { givenName, familyName } = splitName(input.pushName);
2647
2647
  const prev = sessionWriteLocks.get(input.cacheKey);
2648
2648
  let release;
2649
- const mine = new Promise((resolve28) => {
2650
- release = resolve28;
2649
+ const mine = new Promise((resolve29) => {
2650
+ release = resolve29;
2651
2651
  });
2652
2652
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2653
2653
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3727,11 +3727,11 @@ async function connectWithReconnect(conn) {
3727
3727
  console.error(
3728
3728
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3729
3729
  );
3730
- await new Promise((resolve28) => {
3731
- const timer2 = setTimeout(resolve28, delay);
3730
+ await new Promise((resolve29) => {
3731
+ const timer2 = setTimeout(resolve29, delay);
3732
3732
  conn.abortController.signal.addEventListener("abort", () => {
3733
3733
  clearTimeout(timer2);
3734
- resolve28();
3734
+ resolve29();
3735
3735
  }, { once: true });
3736
3736
  });
3737
3737
  }
@@ -3739,16 +3739,16 @@ async function connectWithReconnect(conn) {
3739
3739
  }
3740
3740
  }
3741
3741
  function waitForDisconnectEvent(conn) {
3742
- return new Promise((resolve28) => {
3742
+ return new Promise((resolve29) => {
3743
3743
  if (!conn.sock) {
3744
- resolve28();
3744
+ resolve29();
3745
3745
  return;
3746
3746
  }
3747
3747
  const sock = conn.sock;
3748
3748
  const handler = (update) => {
3749
3749
  if (update.connection === "close") {
3750
3750
  sock.ev.off("connection.update", handler);
3751
- resolve28();
3751
+ resolve29();
3752
3752
  }
3753
3753
  };
3754
3754
  sock.ev.on("connection.update", handler);
@@ -4008,8 +4008,8 @@ async function handleInboundMessage(conn, msg) {
4008
4008
  const conversationKey = isGroup ? remoteJid : senderPhone;
4009
4009
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
4010
4010
  let resolvePending;
4011
- const sttPending = new Promise((resolve28) => {
4012
- resolvePending = resolve28;
4011
+ const sttPending = new Promise((resolve29) => {
4012
+ resolvePending = resolve29;
4013
4013
  });
4014
4014
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
4015
4015
  try {
@@ -4400,20 +4400,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
4400
4400
 
4401
4401
  // server/routes/health.ts
4402
4402
  function checkPort(port2, timeoutMs = 500) {
4403
- return new Promise((resolve28) => {
4403
+ return new Promise((resolve29) => {
4404
4404
  const socket = createConnection2(port2, "127.0.0.1");
4405
4405
  socket.setTimeout(timeoutMs);
4406
4406
  socket.once("connect", () => {
4407
4407
  socket.destroy();
4408
- resolve28(true);
4408
+ resolve29(true);
4409
4409
  });
4410
4410
  socket.once("error", () => {
4411
4411
  socket.destroy();
4412
- resolve28(false);
4412
+ resolve29(false);
4413
4413
  });
4414
4414
  socket.once("timeout", () => {
4415
4415
  socket.destroy();
4416
- resolve28(false);
4416
+ resolve29(false);
4417
4417
  });
4418
4418
  });
4419
4419
  }
@@ -4529,6 +4529,16 @@ async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
4529
4529
  await writeFile2(metaPath, JSON.stringify(meta, null, 2));
4530
4530
  return { attachmentId, filename, storagePath, metaPath, mimeType, sizeBytes };
4531
4531
  }
4532
+ async function storeAttachment(accountId, file) {
4533
+ assertSupportedMime(file.type);
4534
+ if (file.size > MAX_FILE_SIZE_BYTES) {
4535
+ throw new Error(
4536
+ `File "${file.name}" exceeds the 50 MB limit (${(file.size / 1024 / 1024).toFixed(1)} MB).`
4537
+ );
4538
+ }
4539
+ const buffer = Buffer.from(await file.arrayBuffer());
4540
+ return writeAttachment(accountId, file.name, file.type, file.size, buffer);
4541
+ }
4532
4542
  async function storePublicAttachment(sessionId, file, buffer) {
4533
4543
  assertSupportedMime(file.type);
4534
4544
  if (file.size > MAX_FILE_SIZE_BYTES) {
@@ -5510,12 +5520,12 @@ async function dispatchOnce(input) {
5510
5520
  });
5511
5521
  if (!entry) return { error: "spawn-failed" };
5512
5522
  entry.lastInboundAt = Date.now();
5513
- let resolve28;
5523
+ let resolve29;
5514
5524
  const turnPromise = new Promise((r) => {
5515
- resolve28 = r;
5525
+ resolve29 = r;
5516
5526
  });
5517
5527
  const listener = (text) => {
5518
- resolve28(text);
5528
+ resolve29(text);
5519
5529
  };
5520
5530
  entry.subscribers.add(listener);
5521
5531
  const writeAtMs = Date.now();
@@ -6301,8 +6311,8 @@ async function startLogin(opts) {
6301
6311
  await clearAuth(authDir);
6302
6312
  let resolveCode = null;
6303
6313
  let rejectCode = null;
6304
- const codePromise = new Promise((resolve28, reject) => {
6305
- resolveCode = resolve28;
6314
+ const codePromise = new Promise((resolve29, reject) => {
6315
+ resolveCode = resolve29;
6306
6316
  rejectCode = reject;
6307
6317
  });
6308
6318
  const codeTimer = setTimeout(
@@ -7705,7 +7715,24 @@ var whatsapp_reader_default = app5;
7705
7715
  // server/routes/webchat.ts
7706
7716
  import { basename as basename3, dirname as dirname2 } from "path";
7707
7717
  import { join as join10 } from "path";
7718
+ import { readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync5 } from "fs";
7708
7719
  var WEBCHAT_ADMIN_KEY = "webchat-admin";
7720
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
7721
+ function locateSession(sessionId) {
7722
+ const cfg = claudeConfigDir();
7723
+ if (!cfg) return { projectDir: null, channel: null };
7724
+ for (const { path: path2 } of enumerateJsonls(join10(cfg, "projects"))) {
7725
+ if (basename3(path2) === `${sessionId}.jsonl`) {
7726
+ const dir = dirname2(path2);
7727
+ const meta = readSidecarMeta(join10(dir, `${sessionId}.meta.json`));
7728
+ return { projectDir: dir, channel: meta.channel };
7729
+ }
7730
+ }
7731
+ return { projectDir: null, channel: null };
7732
+ }
7733
+ function conflictingBinding(channel) {
7734
+ return channel !== null && channel !== "webchat" ? channel : null;
7735
+ }
7709
7736
  var NO_INDICATORS = {
7710
7737
  activity: null,
7711
7738
  permissionMode: null,
@@ -7741,14 +7768,44 @@ async function fetchComposerIndicators(sessionId) {
7741
7768
  return NO_INDICATORS;
7742
7769
  }
7743
7770
  }
7771
+ var MODEL_ID_PATTERN = /^claude-[a-z0-9][a-z0-9.-]*(\[1m\])?$/;
7772
+ var EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
7773
+ function readLevers() {
7774
+ let account;
7775
+ try {
7776
+ account = resolveAccount();
7777
+ } catch {
7778
+ return { leverModel: null, leverEffort: null };
7779
+ }
7780
+ if (!account) return { leverModel: null, leverEffort: null };
7781
+ const model = account.config.adminModel;
7782
+ const effort = account.config.effort;
7783
+ return {
7784
+ leverModel: typeof model === "string" && MODEL_ID_PATTERN.test(model) ? model : null,
7785
+ leverEffort: typeof effort === "string" && EFFORT_LEVELS.has(effort) ? effort : null
7786
+ };
7787
+ }
7788
+ var REAPPLY_TIMEOUT_MS = 1500;
7789
+ async function reapplyLeversViaManager() {
7790
+ let port2;
7791
+ try {
7792
+ port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "webchat:settings" });
7793
+ } catch {
7794
+ return false;
7795
+ }
7796
+ try {
7797
+ const res = await fetch(`http://127.0.0.1:${port2}/reapply-levers`, {
7798
+ method: "POST",
7799
+ signal: AbortSignal.timeout(REAPPLY_TIMEOUT_MS)
7800
+ });
7801
+ return res.ok;
7802
+ } catch {
7803
+ return false;
7804
+ }
7805
+ }
7744
7806
  function createWebchatRoutes(deps) {
7745
7807
  const app49 = new Hono();
7746
7808
  app49.post("/send", requireAdminSession, async (c) => {
7747
- const body = await c.req.json().catch(() => null);
7748
- const text = body?.text;
7749
- if (typeof text !== "string" || text.length === 0) {
7750
- return c.json({ error: "text required" }, 400);
7751
- }
7752
7809
  let accountId;
7753
7810
  try {
7754
7811
  accountId = resolvePlatformAccountId();
@@ -7757,9 +7814,160 @@ function createWebchatRoutes(deps) {
7757
7814
  console.error(`[webchat:inbound] op=send-refused reason=account-unresolved detail=${detail}`);
7758
7815
  return c.json({ error: "account unresolved" }, 503);
7759
7816
  }
7760
- await deps.handleInbound({ role: "admin", accountId, key: WEBCHAT_ADMIN_KEY, text });
7817
+ let text;
7818
+ let target;
7819
+ let files = [];
7820
+ const contentType = c.req.header("content-type") ?? "";
7821
+ const isMultipart = contentType.startsWith("multipart/form-data");
7822
+ if (isMultipart) {
7823
+ let formData;
7824
+ try {
7825
+ formData = await c.req.formData();
7826
+ } catch {
7827
+ console.error("[webchat:inbound] op=send-refused kind=multipart reason=invalid-body");
7828
+ return c.json({ error: "invalid multipart body" }, 400);
7829
+ }
7830
+ const typed = formData.get("text");
7831
+ text = typeof typed === "string" ? typed : "";
7832
+ files = formData.getAll("attachments").filter((f) => f instanceof File);
7833
+ const rawTarget = formData.get("session");
7834
+ if (rawTarget !== null) {
7835
+ if (typeof rawTarget !== "string" || !UUID_PATTERN.test(rawTarget)) {
7836
+ return c.json({ error: "invalid session id" }, 400);
7837
+ }
7838
+ target = rawTarget;
7839
+ }
7840
+ } else {
7841
+ const body = await c.req.json().catch(() => null);
7842
+ const typed = body?.text;
7843
+ if (typeof typed !== "string" || typed.length === 0) {
7844
+ return c.json({ error: "text required" }, 400);
7845
+ }
7846
+ text = typed;
7847
+ const rawTarget = body?.session;
7848
+ if (rawTarget !== void 0) {
7849
+ if (typeof rawTarget !== "string" || !UUID_PATTERN.test(rawTarget)) {
7850
+ return c.json({ error: "invalid session id" }, 400);
7851
+ }
7852
+ target = rawTarget;
7853
+ }
7854
+ }
7855
+ let deliveryKey = WEBCHAT_ADMIN_KEY;
7856
+ let deliverySessionId;
7857
+ if (target !== void 0) {
7858
+ const { projectDir, channel } = locateSession(target);
7859
+ if (projectDir === null) {
7860
+ return c.json({ error: "session not found" }, 404);
7861
+ }
7862
+ const binding = conflictingBinding(channel);
7863
+ if (binding !== null) {
7864
+ console.error(`[webchat:inbound] op=send-refused key=session:${target.slice(0, 8)} reason=channel-conflict binding=${binding}`);
7865
+ return c.json({ error: "channel-conflict", binding }, 409);
7866
+ }
7867
+ deliveryKey = `session:${target}`;
7868
+ deliverySessionId = target;
7869
+ }
7870
+ if (isMultipart) {
7871
+ const kind = files.some((f) => isAudioMime(f.type)) ? "voice" : "files";
7872
+ if (files.length > MAX_FILES_PER_MESSAGE) {
7873
+ console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=too-many-files count=${files.length}`);
7874
+ return c.json({ error: `Maximum ${MAX_FILES_PER_MESSAGE} files per message.` }, 422);
7875
+ }
7876
+ const audioFile = files.find((f) => isAudioMime(f.type));
7877
+ const regularFiles = files.filter((f) => !isAudioMime(f.type));
7878
+ if (audioFile) {
7879
+ if (audioFile.size > MAX_FILE_SIZE_BYTES) {
7880
+ console.error(`[webchat:inbound] op=send-refused kind=voice reason=oversize bytes=${audioFile.size}`);
7881
+ return c.json({ error: "Recording too long. Try a shorter voice note." }, 422);
7882
+ }
7883
+ const result = await transcribeVoiceNote(audioFile, "admin");
7884
+ if (!result.ok) {
7885
+ console.error(`[webchat:inbound] op=send-refused kind=voice reason=stt-failed detail=${result.error}`);
7886
+ return c.json({ error: result.error }, 422);
7887
+ }
7888
+ text = result.result.text;
7889
+ }
7890
+ for (const file of regularFiles) {
7891
+ try {
7892
+ assertSupportedMime(file.type);
7893
+ if (file.size > MAX_FILE_SIZE_BYTES) {
7894
+ throw new Error(`File "${file.name}" exceeds the 50 MB limit (${(file.size / 1024 / 1024).toFixed(1)} MB).`);
7895
+ }
7896
+ } catch (err) {
7897
+ const detail = err instanceof Error ? err.message : "invalid file";
7898
+ console.error(`[webchat:inbound] op=send-refused kind=files reason=file-rejected detail=${detail}`);
7899
+ return c.json({ error: detail }, 422);
7900
+ }
7901
+ }
7902
+ const stored = [];
7903
+ try {
7904
+ for (const file of regularFiles) {
7905
+ stored.push(await storeAttachment(accountId, file));
7906
+ }
7907
+ } catch (err) {
7908
+ const detail = err instanceof Error ? err.message : String(err);
7909
+ console.error(`[webchat:inbound] op=send-refused kind=files reason=store-failed detail=${detail}`);
7910
+ return c.json({ error: "failed to store attachment" }, 500);
7911
+ }
7912
+ if (stored.length > 0) {
7913
+ const listing = stored.map((s) => `${s.filename} (${s.storagePath})`).join(", ");
7914
+ const note = `[The operator uploaded ${stored.length} file(s): ${listing}]`;
7915
+ text = text.length > 0 ? `${text}
7916
+
7917
+ ${note}` : note;
7918
+ }
7919
+ if (text.length === 0) {
7920
+ console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=empty-text`);
7921
+ return c.json({ error: "text required" }, 400);
7922
+ }
7923
+ console.log(`[webchat:inbound] op=send-accepted kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
7924
+ }
7925
+ if (deliverySessionId !== void 0) {
7926
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId });
7927
+ } else {
7928
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text });
7929
+ }
7761
7930
  return c.json({ ok: true });
7762
7931
  });
7932
+ app49.post("/settings", requireAdminSession, async (c) => {
7933
+ const body = await c.req.json().catch(() => null);
7934
+ const op = body?.op;
7935
+ const value = body?.value;
7936
+ if (op !== "model" && op !== "effort") {
7937
+ console.error(`[webchat:settings] op=${String(op)} outcome=refused reason=unknown-op`);
7938
+ return c.json({ error: "op must be model or effort" }, 400);
7939
+ }
7940
+ if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !EFFORT_LEVELS.has(value)) {
7941
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${JSON.stringify(value)} reason=invalid-value`);
7942
+ return c.json({ error: `invalid ${op} value` }, 400);
7943
+ }
7944
+ let account;
7945
+ try {
7946
+ account = resolveAccount();
7947
+ } catch {
7948
+ account = null;
7949
+ }
7950
+ if (!account) {
7951
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
7952
+ return c.json({ error: "account unresolved" }, 503);
7953
+ }
7954
+ const accountJsonPath = join10(account.accountDir, "account.json");
7955
+ try {
7956
+ const parsed = JSON.parse(readFileSync11(accountJsonPath, "utf8"));
7957
+ if (op === "model") parsed.adminModel = value;
7958
+ else parsed.effort = value;
7959
+ const tmp = `${accountJsonPath}.${process.pid}.tmp`;
7960
+ writeFileSync5(tmp, JSON.stringify(parsed, null, 2), "utf8");
7961
+ renameSync(tmp, accountJsonPath);
7962
+ } catch (err) {
7963
+ const detail = err instanceof Error ? err.message : String(err);
7964
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=write-failed detail=${detail}`);
7965
+ return c.json({ error: "persist failed" }, 500);
7966
+ }
7967
+ const settingsApplied = await reapplyLeversViaManager();
7968
+ console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
7969
+ return c.json({ ok: true, settingsApplied });
7970
+ });
7763
7971
  app49.get("/session", requireAdminSession, async (c) => {
7764
7972
  let accountId;
7765
7973
  try {
@@ -7769,6 +7977,15 @@ function createWebchatRoutes(deps) {
7769
7977
  console.error(`[webchat:inbound] op=session-refused reason=account-unresolved detail=${detail}`);
7770
7978
  return c.json({ error: "account unresolved" }, 503);
7771
7979
  }
7980
+ const target = c.req.query("session");
7981
+ if (target !== void 0) {
7982
+ if (!UUID_PATTERN.test(target)) {
7983
+ return c.json({ error: "invalid session id" }, 400);
7984
+ }
7985
+ const { projectDir: projectDir2, channel } = locateSession(target);
7986
+ const indicators2 = await fetchComposerIndicators(target);
7987
+ return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), ...indicators2 });
7988
+ }
7772
7989
  const sessionId = adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY);
7773
7990
  const cfg = claudeConfigDir();
7774
7991
  let projectDir = null;
@@ -7781,11 +7998,56 @@ function createWebchatRoutes(deps) {
7781
7998
  }
7782
7999
  }
7783
8000
  const indicators = await fetchComposerIndicators(sessionId);
7784
- return c.json({ sessionId, projectDir, ...indicators });
8001
+ return c.json({ sessionId, projectDir, ...indicators, ...readLevers() });
7785
8002
  });
7786
8003
  return app49;
7787
8004
  }
7788
8005
 
8006
+ // server/routes/webchat-greeting.ts
8007
+ import { resolve as resolve10 } from "path";
8008
+
8009
+ // app/lib/claude-agent/specialist-roster.ts
8010
+ import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
8011
+ import { join as join11 } from "path";
8012
+ function field(fm, name) {
8013
+ const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
8014
+ if (!m) return null;
8015
+ let value = m[1].trim();
8016
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
8017
+ value = value.slice(1, -1);
8018
+ }
8019
+ return value || null;
8020
+ }
8021
+ function readSpecialistRoster(specialistsDir) {
8022
+ if (!existsSync8(specialistsDir)) return { specialists: [], skipped: [] };
8023
+ const entries = readdirSync7(specialistsDir);
8024
+ const specialists = [];
8025
+ const skipped = [];
8026
+ for (const file of entries.sort()) {
8027
+ if (!file.endsWith(".md")) continue;
8028
+ let raw;
8029
+ try {
8030
+ raw = readFileSync12(join11(specialistsDir, file), "utf-8");
8031
+ } catch (err) {
8032
+ skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
8033
+ continue;
8034
+ }
8035
+ const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
8036
+ if (!fm) {
8037
+ skipped.push({ file, reason: "no-frontmatter" });
8038
+ continue;
8039
+ }
8040
+ const name = field(fm[1], "name");
8041
+ if (!name) {
8042
+ skipped.push({ file, reason: "missing-name" });
8043
+ continue;
8044
+ }
8045
+ const summary = field(fm[1], "summary") ?? field(fm[1], "description") ?? "";
8046
+ specialists.push({ name, summary });
8047
+ }
8048
+ return { specialists, skipped };
8049
+ }
8050
+
7789
8051
  // server/routes/webchat-greeting.ts
7790
8052
  var OUTSTANDING_TASK_STATUSES = ["pending", "active", "running"];
7791
8053
  var UPCOMING_EVENT_STATUSES = ["scheduled", "due"];
@@ -7844,10 +8106,25 @@ app6.get("/", requireAdminSession, async (c) => {
7844
8106
  return { events: events2, tasks: tasks2 };
7845
8107
  }
7846
8108
  );
8109
+ let specialists = [];
8110
+ try {
8111
+ const roster = readSpecialistRoster(
8112
+ resolve10(ACCOUNTS_DIR, accountId, "specialists", "agents")
8113
+ );
8114
+ specialists = roster.specialists;
8115
+ for (const s of roster.skipped) {
8116
+ console.warn(
8117
+ `[webchat:greeting] op=specialist-skipped file=${s.file} reason=${s.reason}`
8118
+ );
8119
+ }
8120
+ } catch (err) {
8121
+ const detail = err instanceof Error ? err.message : String(err);
8122
+ console.error(`[webchat:greeting] op=specialists-read-failed reason=${detail}`);
8123
+ }
7847
8124
  console.log(
7848
- `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} ms=${Date.now() - started}`
8125
+ `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} specialists=${specialists.length} ms=${Date.now() - started}`
7849
8126
  );
7850
- return c.json({ ok: true, events, tasks });
8127
+ return c.json({ ok: true, events, tasks, specialists });
7851
8128
  } catch (err) {
7852
8129
  const detail = err instanceof Error ? err.message : String(err);
7853
8130
  console.error(`[webchat:greeting] op=read-failed reason=${detail}`);
@@ -7867,8 +8144,8 @@ var webchat_greeting_default = app6;
7867
8144
 
7868
8145
  // server/routes/telegram.ts
7869
8146
  import { homedir } from "os";
7870
- import { resolve as resolve10, join as join11 } from "path";
7871
- import { existsSync as existsSync8, readFileSync as readFileSync11 } from "fs";
8147
+ import { resolve as resolve11, join as join12 } from "path";
8148
+ import { existsSync as existsSync9, readFileSync as readFileSync13 } from "fs";
7872
8149
 
7873
8150
  // app/lib/telegram/access-control.ts
7874
8151
  function checkTelegramAccess(params) {
@@ -7918,11 +8195,11 @@ function routeTelegramUpdate(input) {
7918
8195
  var TAG22 = "[telegram-inbound]";
7919
8196
  var DISPATCH_TIMEOUT_MS = 12e4;
7920
8197
  function configDirName() {
7921
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve10(process.cwd(), "..");
7922
- const brandPath = join11(platformRoot2, "config", "brand.json");
7923
- if (existsSync8(brandPath)) {
8198
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve11(process.cwd(), "..");
8199
+ const brandPath = join12(platformRoot2, "config", "brand.json");
8200
+ if (existsSync9(brandPath)) {
7924
8201
  try {
7925
- return JSON.parse(readFileSync11(brandPath, "utf-8")).configDir ?? ".maxy";
8202
+ return JSON.parse(readFileSync13(brandPath, "utf-8")).configDir ?? ".maxy";
7926
8203
  } catch {
7927
8204
  }
7928
8205
  }
@@ -7930,7 +8207,7 @@ function configDirName() {
7930
8207
  }
7931
8208
  function secretPath(botType) {
7932
8209
  const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
7933
- return resolve10(homedir(), configDirName(), filename);
8210
+ return resolve11(homedir(), configDirName(), filename);
7934
8211
  }
7935
8212
  async function sendTelegram(botToken, chatId, text) {
7936
8213
  try {
@@ -7954,11 +8231,11 @@ app7.post("/", async (c) => {
7954
8231
  return c.json({ ok: false }, 400);
7955
8232
  }
7956
8233
  const sp = secretPath(botType);
7957
- if (!existsSync8(sp)) {
8234
+ if (!existsSync9(sp)) {
7958
8235
  console.error(`${TAG22} op=reject reason=no-secret-file botType=${botType}`);
7959
8236
  return c.json({ ok: false }, 401);
7960
8237
  }
7961
- const expected = readFileSync11(sp, "utf-8").trim();
8238
+ const expected = readFileSync13(sp, "utf-8").trim();
7962
8239
  const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
7963
8240
  if (got !== expected) {
7964
8241
  console.error(`${TAG22} op=reject reason=bad-secret botType=${botType}`);
@@ -8021,12 +8298,12 @@ var telegram_default = app7;
8021
8298
 
8022
8299
  // server/routes/onboarding.ts
8023
8300
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
8024
- import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync10, readFileSync as readFileSync13, unlinkSync } from "fs";
8301
+ import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, readFileSync as readFileSync15, unlinkSync } from "fs";
8025
8302
  import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
8026
8303
 
8027
8304
  // ../lib/admins-write/src/index.ts
8028
- import { existsSync as existsSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
8029
- import { dirname as dirname3, join as join12 } from "path";
8305
+ import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync6, renameSync as renameSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
8306
+ import { dirname as dirname3, join as join13 } from "path";
8030
8307
  function logLine(input, result) {
8031
8308
  const userIdShort = input.userId.slice(0, 8);
8032
8309
  console.error(
@@ -8036,15 +8313,15 @@ function logLine(input, result) {
8036
8313
  function writeFileAtomic(filePath, contents, mode) {
8037
8314
  mkdirSync2(dirname3(filePath), { recursive: true });
8038
8315
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
8039
- writeFileSync5(tempPath, contents, mode !== void 0 ? { mode } : void 0);
8040
- renameSync(tempPath, filePath);
8316
+ writeFileSync6(tempPath, contents, mode !== void 0 ? { mode } : void 0);
8317
+ renameSync2(tempPath, filePath);
8041
8318
  }
8042
8319
  function writeAdminEntry(input) {
8043
8320
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
8044
8321
  try {
8045
8322
  let users = [];
8046
- if (existsSync9(input.usersFile)) {
8047
- const raw = readFileSync12(input.usersFile, "utf-8").trim();
8323
+ if (existsSync10(input.usersFile)) {
8324
+ const raw = readFileSync14(input.usersFile, "utf-8").trim();
8048
8325
  if (raw) {
8049
8326
  const parsed = JSON.parse(raw);
8050
8327
  if (!Array.isArray(parsed)) {
@@ -8068,11 +8345,11 @@ function writeAdminEntry(input) {
8068
8345
  return result;
8069
8346
  }
8070
8347
  try {
8071
- const accountJsonPath = join12(input.accountDir, "account.json");
8072
- if (!existsSync9(accountJsonPath)) {
8348
+ const accountJsonPath = join13(input.accountDir, "account.json");
8349
+ if (!existsSync10(accountJsonPath)) {
8073
8350
  throw new Error(`account.json not found at ${accountJsonPath}`);
8074
8351
  }
8075
- const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
8352
+ const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
8076
8353
  const admins = config.admins ?? [];
8077
8354
  if (admins.some((a) => a.userId === input.userId)) {
8078
8355
  result.accountJsonResult = "noop";
@@ -8096,9 +8373,9 @@ function checkAdminAuthInvariant(input) {
8096
8373
  usersWithoutAccount: []
8097
8374
  };
8098
8375
  const usersUserIds = /* @__PURE__ */ new Set();
8099
- if (existsSync9(input.usersFile)) {
8376
+ if (existsSync10(input.usersFile)) {
8100
8377
  try {
8101
- const raw = readFileSync12(input.usersFile, "utf-8").trim();
8378
+ const raw = readFileSync14(input.usersFile, "utf-8").trim();
8102
8379
  if (raw) {
8103
8380
  const users = JSON.parse(raw);
8104
8381
  for (const u of users) {
@@ -8111,10 +8388,10 @@ function checkAdminAuthInvariant(input) {
8111
8388
  }
8112
8389
  }
8113
8390
  const accountUserIds = /* @__PURE__ */ new Set();
8114
- if (existsSync9(input.accountsDir)) {
8391
+ if (existsSync10(input.accountsDir)) {
8115
8392
  let entries;
8116
8393
  try {
8117
- entries = readdirSync7(input.accountsDir);
8394
+ entries = readdirSync8(input.accountsDir);
8118
8395
  } catch (err) {
8119
8396
  const msg = err instanceof Error ? err.message : String(err);
8120
8397
  console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
@@ -8123,17 +8400,17 @@ function checkAdminAuthInvariant(input) {
8123
8400
  }
8124
8401
  for (const entry of entries) {
8125
8402
  if (entry.startsWith(".")) continue;
8126
- const accountDir = join12(input.accountsDir, entry);
8403
+ const accountDir = join13(input.accountsDir, entry);
8127
8404
  try {
8128
8405
  if (!statSync5(accountDir).isDirectory()) continue;
8129
8406
  } catch {
8130
8407
  continue;
8131
8408
  }
8132
- const accountJsonPath = join12(accountDir, "account.json");
8133
- if (!existsSync9(accountJsonPath)) continue;
8409
+ const accountJsonPath = join13(accountDir, "account.json");
8410
+ if (!existsSync10(accountJsonPath)) continue;
8134
8411
  let admins = [];
8135
8412
  try {
8136
- const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
8413
+ const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
8137
8414
  admins = config.admins ?? [];
8138
8415
  } catch (err) {
8139
8416
  const msg = err instanceof Error ? err.message : String(err);
@@ -8173,8 +8450,8 @@ function hashPin2(pin) {
8173
8450
  return createHash3("sha256").update(pin).digest("hex");
8174
8451
  }
8175
8452
  function readUsersFile2() {
8176
- if (!existsSync10(USERS_FILE)) return null;
8177
- const raw = readFileSync13(USERS_FILE, "utf-8").trim();
8453
+ if (!existsSync11(USERS_FILE)) return null;
8454
+ const raw = readFileSync15(USERS_FILE, "utf-8").trim();
8178
8455
  if (!raw) return [];
8179
8456
  return JSON.parse(raw);
8180
8457
  }
@@ -8227,7 +8504,7 @@ app8.post("/claude-auth", async (c) => {
8227
8504
  } catch (err) {
8228
8505
  logoutError = err instanceof Error ? err.message : String(err);
8229
8506
  }
8230
- const credentialsPresent = existsSync10(CLAUDE_CREDENTIALS_FILE);
8507
+ const credentialsPresent = existsSync11(CLAUDE_CREDENTIALS_FILE);
8231
8508
  const ranMs = Date.now() - start;
8232
8509
  console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
8233
8510
  return c.json({ logged_out: !credentialsPresent });
@@ -8245,7 +8522,7 @@ app8.post("/claude-auth", async (c) => {
8245
8522
  return c.json({ launched: cdpReady });
8246
8523
  }
8247
8524
  ensureLogDir();
8248
- writeFileSync6(logPath("claude-auth"), "");
8525
+ writeFileSync7(logPath("claude-auth"), "");
8249
8526
  const claudeAuthLogFd = openSync2(logPath("claude-auth"), "a");
8250
8527
  const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
8251
8528
  if (process.platform === "darwin") {
@@ -8334,9 +8611,9 @@ app8.post("/set-pin", async (c) => {
8334
8611
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
8335
8612
  if (process.platform === "linux") {
8336
8613
  let installOwner = null;
8337
- if (existsSync10(INSTALL_OWNER_FILE)) {
8614
+ if (existsSync11(INSTALL_OWNER_FILE)) {
8338
8615
  try {
8339
- const raw = readFileSync13(INSTALL_OWNER_FILE, "utf-8").trim();
8616
+ const raw = readFileSync15(INSTALL_OWNER_FILE, "utf-8").trim();
8340
8617
  if (raw.length > 0) installOwner = raw;
8341
8618
  } catch (err) {
8342
8619
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -8409,7 +8686,7 @@ app8.delete("/set-pin", async (c) => {
8409
8686
  unlinkSync(USERS_FILE);
8410
8687
  console.log(`[set-pin] cleared users.json (last entry removed): userId=${matchedUser.userId.slice(0, 8)}\u2026`);
8411
8688
  } else {
8412
- writeFileSync6(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
8689
+ writeFileSync7(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
8413
8690
  console.log(`[set-pin] removed entry from users.json: userId=${matchedUser.userId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
8414
8691
  }
8415
8692
  return c.json({ ok: true });
@@ -8417,9 +8694,9 @@ app8.delete("/set-pin", async (c) => {
8417
8694
  var onboarding_default = app8;
8418
8695
 
8419
8696
  // server/routes/client-error.ts
8420
- import { appendFileSync, existsSync as existsSync11, renameSync as renameSync2, statSync as statSync6 } from "fs";
8421
- import { join as join13 } from "path";
8422
- var CLIENT_ERRORS_LOG = join13(LOG_DIR, "client-errors.log");
8697
+ import { appendFileSync, existsSync as existsSync12, renameSync as renameSync3, statSync as statSync6 } from "fs";
8698
+ import { join as join14 } from "path";
8699
+ var CLIENT_ERRORS_LOG = join14(LOG_DIR, "client-errors.log");
8423
8700
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
8424
8701
  var MAX_BODY_SIZE = 8 * 1024;
8425
8702
  var MAX_STACK_LEN = 2e3;
@@ -8462,10 +8739,10 @@ function stackHead(stack) {
8462
8739
  }
8463
8740
  function rotateIfNeeded() {
8464
8741
  try {
8465
- if (!existsSync11(CLIENT_ERRORS_LOG)) return;
8742
+ if (!existsSync12(CLIENT_ERRORS_LOG)) return;
8466
8743
  const stats = statSync6(CLIENT_ERRORS_LOG);
8467
8744
  if (stats.size < MAX_LOG_SIZE) return;
8468
- renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
8745
+ renameSync3(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
8469
8746
  } catch (err) {
8470
8747
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
8471
8748
  }
@@ -8744,18 +9021,18 @@ app10.post("/", async (c) => {
8744
9021
  var session_default = app10;
8745
9022
 
8746
9023
  // server/routes/admin/logs.ts
8747
- import { existsSync as existsSync13, readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
8748
- import { resolve as resolve11, basename as basename4 } from "path";
9024
+ import { existsSync as existsSync14, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
9025
+ import { resolve as resolve12, basename as basename4 } from "path";
8749
9026
 
8750
9027
  // app/lib/logs-read-resolve.ts
8751
- import { existsSync as existsSync12 } from "fs";
8752
- import { join as join14 } from "path";
9028
+ import { existsSync as existsSync13 } from "fs";
9029
+ import { join as join15 } from "path";
8753
9030
  function resolveSessionLogPaths(filename, logDirs) {
8754
9031
  const tried = [filename];
8755
9032
  const hits = [];
8756
9033
  for (const dir of logDirs) {
8757
- const fullPath = join14(dir, filename);
8758
- if (existsSync12(fullPath)) {
9034
+ const fullPath = join15(dir, filename);
9035
+ if (existsSync13(fullPath)) {
8759
9036
  hits.push({ path: fullPath, dir });
8760
9037
  }
8761
9038
  }
@@ -8772,7 +9049,7 @@ app11.get("/", async (c) => {
8772
9049
  const cacheKeyParam = c.req.query("cacheKey");
8773
9050
  const download = c.req.query("download") === "1";
8774
9051
  const account = resolveAccount();
8775
- const accountLogDir = account ? resolve11(account.accountDir, "logs") : null;
9052
+ const accountLogDir = account ? resolve12(account.accountDir, "logs") : null;
8776
9053
  const logDirs = [];
8777
9054
  if (accountLogDir) logDirs.push(accountLogDir);
8778
9055
  logDirs.push(LOG_DIR);
@@ -8780,10 +9057,10 @@ app11.get("/", async (c) => {
8780
9057
  const safe = basename4(fileParam);
8781
9058
  const searched = [];
8782
9059
  for (const dir of logDirs) {
8783
- const filePath = resolve11(dir, safe);
9060
+ const filePath = resolve12(dir, safe);
8784
9061
  searched.push(filePath);
8785
9062
  try {
8786
- const buffer = readFileSync14(filePath);
9063
+ const buffer = readFileSync16(filePath);
8787
9064
  const onDiskBytes = statSync7(filePath).size;
8788
9065
  const headers = {
8789
9066
  "Content-Type": "text/plain; charset=utf-8",
@@ -8848,7 +9125,7 @@ app11.get("/", async (c) => {
8848
9125
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
8849
9126
  try {
8850
9127
  const filename = basename4(hit.path);
8851
- const buffer = readFileSync14(hit.path);
9128
+ const buffer = readFileSync16(hit.path);
8852
9129
  const onDiskBytes = statSync7(hit.path).size;
8853
9130
  const headers = {
8854
9131
  "Content-Type": "text/plain; charset=utf-8",
@@ -8883,19 +9160,19 @@ app11.get("/", async (c) => {
8883
9160
  const seen = /* @__PURE__ */ new Set();
8884
9161
  const logs = {};
8885
9162
  for (const dir of logDirs) {
8886
- if (!existsSync13(dir)) continue;
9163
+ if (!existsSync14(dir)) continue;
8887
9164
  let files;
8888
9165
  try {
8889
- files = readdirSync8(dir).filter((f) => f.endsWith(".log"));
9166
+ files = readdirSync9(dir).filter((f) => f.endsWith(".log"));
8890
9167
  } catch (err) {
8891
9168
  const reason = err instanceof Error ? err.message : String(err);
8892
9169
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
8893
9170
  continue;
8894
9171
  }
8895
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve11(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9172
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve12(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
8896
9173
  seen.add(name);
8897
9174
  try {
8898
- const content = readFileSync14(resolve11(dir, name));
9175
+ const content = readFileSync16(resolve12(dir, name));
8899
9176
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
8900
9177
  logs[name] = tail.trim() || "(empty)";
8901
9178
  } catch (err) {
@@ -8934,8 +9211,8 @@ var claude_info_default = app12;
8934
9211
 
8935
9212
  // server/routes/admin/attachment.ts
8936
9213
  import { readFile as readFile2, readdir } from "fs/promises";
8937
- import { existsSync as existsSync14 } from "fs";
8938
- import { resolve as resolve12 } from "path";
9214
+ import { existsSync as existsSync15 } from "fs";
9215
+ import { resolve as resolve13 } from "path";
8939
9216
  var app13 = new Hono();
8940
9217
  app13.get("/:attachmentId", requireAdminSession, async (c) => {
8941
9218
  const attachmentId = c.req.param("attachmentId");
@@ -8947,12 +9224,12 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8947
9224
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
8948
9225
  return new Response("Not found", { status: 404 });
8949
9226
  }
8950
- const dir = resolve12(ATTACHMENTS_ROOT, accountId, attachmentId);
8951
- if (!existsSync14(dir)) {
9227
+ const dir = resolve13(ATTACHMENTS_ROOT, accountId, attachmentId);
9228
+ if (!existsSync15(dir)) {
8952
9229
  return new Response("Not found", { status: 404 });
8953
9230
  }
8954
- const metaPath = resolve12(dir, `${attachmentId}.meta.json`);
8955
- if (!existsSync14(metaPath)) {
9231
+ const metaPath = resolve13(dir, `${attachmentId}.meta.json`);
9232
+ if (!existsSync15(metaPath)) {
8956
9233
  return new Response("Not found", { status: 404 });
8957
9234
  }
8958
9235
  let meta;
@@ -8966,7 +9243,7 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8966
9243
  if (!dataFile) {
8967
9244
  return new Response("Not found", { status: 404 });
8968
9245
  }
8969
- const filePath = resolve12(dir, dataFile);
9246
+ const filePath = resolve13(dir, dataFile);
8970
9247
  const buffer = await readFile2(filePath);
8971
9248
  return new Response(new Uint8Array(buffer), {
8972
9249
  headers: {
@@ -8979,24 +9256,24 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8979
9256
  var attachment_default = app13;
8980
9257
 
8981
9258
  // server/routes/admin/agents.ts
8982
- import { resolve as resolve13 } from "path";
8983
- import { readdirSync as readdirSync9, readFileSync as readFileSync15, existsSync as existsSync15, rmSync } from "fs";
9259
+ import { resolve as resolve14 } from "path";
9260
+ import { readdirSync as readdirSync10, readFileSync as readFileSync17, existsSync as existsSync16, rmSync } from "fs";
8984
9261
  var app14 = new Hono();
8985
9262
  app14.get("/", (c) => {
8986
9263
  const account = resolveAccount();
8987
9264
  if (!account) return c.json({ agents: [] });
8988
- const agentsDir = resolve13(account.accountDir, "agents");
8989
- if (!existsSync15(agentsDir)) return c.json({ agents: [] });
9265
+ const agentsDir = resolve14(account.accountDir, "agents");
9266
+ if (!existsSync16(agentsDir)) return c.json({ agents: [] });
8990
9267
  const agents = [];
8991
9268
  try {
8992
- const entries = readdirSync9(agentsDir, { withFileTypes: true });
9269
+ const entries = readdirSync10(agentsDir, { withFileTypes: true });
8993
9270
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
8994
9271
  if (!entry.isDirectory()) continue;
8995
9272
  if (entry.name === "admin") continue;
8996
- const configPath2 = resolve13(agentsDir, entry.name, "config.json");
8997
- if (!existsSync15(configPath2)) continue;
9273
+ const configPath2 = resolve14(agentsDir, entry.name, "config.json");
9274
+ if (!existsSync16(configPath2)) continue;
8998
9275
  try {
8999
- const config = JSON.parse(readFileSync15(configPath2, "utf-8"));
9276
+ const config = JSON.parse(readFileSync17(configPath2, "utf-8"));
9000
9277
  agents.push({
9001
9278
  slug: entry.name,
9002
9279
  displayName: config.displayName ?? entry.name,
@@ -9022,8 +9299,8 @@ app14.delete("/:slug", async (c) => {
9022
9299
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9023
9300
  return c.json({ error: "Invalid agent slug" }, 400);
9024
9301
  }
9025
- const agentDir = resolve13(account.accountDir, "agents", slug);
9026
- if (!existsSync15(agentDir)) {
9302
+ const agentDir = resolve14(account.accountDir, "agents", slug);
9303
+ if (!existsSync16(agentDir)) {
9027
9304
  return c.json({ error: "Agent not found" }, 404);
9028
9305
  }
9029
9306
  try {
@@ -9052,8 +9329,8 @@ app14.post("/:slug/project", async (c) => {
9052
9329
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9053
9330
  return c.json({ error: "Invalid agent slug" }, 400);
9054
9331
  }
9055
- const agentDir = resolve13(account.accountDir, "agents", slug);
9056
- if (!existsSync15(agentDir)) {
9332
+ const agentDir = resolve14(account.accountDir, "agents", slug);
9333
+ if (!existsSync16(agentDir)) {
9057
9334
  return c.json({ error: "Agent not found on disk" }, 404);
9058
9335
  }
9059
9336
  try {
@@ -9069,7 +9346,7 @@ var agents_default = app14;
9069
9346
  // server/routes/admin/sessions.ts
9070
9347
  import crypto2 from "crypto";
9071
9348
  import { resolve as resolvePath } from "path";
9072
- import { existsSync as existsSync16, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9349
+ import { existsSync as existsSync17, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9073
9350
 
9074
9351
  // ../lib/admin-conversation-purge/src/index.ts
9075
9352
  async function purgeAdminConversationJsonls(args) {
@@ -9229,7 +9506,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
9229
9506
  let reason = null;
9230
9507
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
9231
9508
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
9232
- else if (!existsSync16(a.storagePath)) reason = "missing-file";
9509
+ else if (!existsSync17(a.storagePath)) reason = "missing-file";
9233
9510
  if (reason) {
9234
9511
  invalid++;
9235
9512
  try {
@@ -9755,8 +10032,8 @@ app15.put("/:id/label", requireAdminSession, async (c) => {
9755
10032
  var sessions_default = app15;
9756
10033
 
9757
10034
  // app/lib/claude-agent/spawn-context.ts
9758
- import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
9759
- import { dirname as dirname4, resolve as resolve14, join as join15 } from "path";
10035
+ import { existsSync as existsSync18, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync8 } from "fs";
10036
+ import { dirname as dirname4, resolve as resolve15, join as join16 } from "path";
9760
10037
  async function resolveOwnerProfileBlock(accountId, userId) {
9761
10038
  if (!userId) return { ok: false, reason: "missing-user-id" };
9762
10039
  try {
@@ -9770,10 +10047,10 @@ async function resolveOwnerProfileBlock(accountId, userId) {
9770
10047
  return { ok: false, reason: "neo4j-unreachable" };
9771
10048
  }
9772
10049
  }
9773
- function frontmatterField(manifest, field) {
10050
+ function frontmatterField(manifest, field2) {
9774
10051
  const fm = manifest.match(/^---\r?\n([\s\S]*?)\r?\n---/);
9775
10052
  if (!fm) return null;
9776
- const re = new RegExp(`^${field}:\\s*(.*?)\\r?$`, "m");
10053
+ const re = new RegExp(`^${field2}:\\s*(.*?)\\r?$`, "m");
9777
10054
  const m = fm[1].match(re);
9778
10055
  if (!m) return null;
9779
10056
  let value = m[1].trim();
@@ -9785,14 +10062,14 @@ function frontmatterField(manifest, field) {
9785
10062
  function extractPluginToolDescriptions(pluginDir) {
9786
10063
  const out = /* @__PURE__ */ new Map();
9787
10064
  const candidates = [
9788
- join15(pluginDir, "mcp/dist/index.js"),
9789
- join15(pluginDir, "mcp/src/index.ts")
10065
+ join16(pluginDir, "mcp/dist/index.js"),
10066
+ join16(pluginDir, "mcp/src/index.ts")
9790
10067
  ];
9791
10068
  let raw = null;
9792
10069
  for (const path2 of candidates) {
9793
- if (!existsSync17(path2)) continue;
10070
+ if (!existsSync18(path2)) continue;
9794
10071
  try {
9795
- raw = readFileSync16(path2, "utf-8");
10072
+ raw = readFileSync18(path2, "utf-8");
9796
10073
  break;
9797
10074
  } catch {
9798
10075
  }
@@ -9841,24 +10118,24 @@ function parseSkillPathsFromFrontmatter(fm) {
9841
10118
  }
9842
10119
  function listPluginDirs() {
9843
10120
  const out = /* @__PURE__ */ new Map();
9844
- const platformPlugins = resolve14(PLATFORM_ROOT, "plugins");
9845
- if (existsSync17(platformPlugins)) {
9846
- for (const name of readdirSync10(platformPlugins)) {
9847
- const dir = join15(platformPlugins, name);
10121
+ const platformPlugins = resolve15(PLATFORM_ROOT, "plugins");
10122
+ if (existsSync18(platformPlugins)) {
10123
+ for (const name of readdirSync11(platformPlugins)) {
10124
+ const dir = join16(platformPlugins, name);
9848
10125
  try {
9849
10126
  if (statSync8(dir).isDirectory()) out.set(name, dir);
9850
10127
  } catch {
9851
10128
  }
9852
10129
  }
9853
10130
  }
9854
- const premiumRoot = resolve14(dirname4(PLATFORM_ROOT), "premium-plugins");
9855
- if (existsSync17(premiumRoot)) {
9856
- for (const bundle of readdirSync10(premiumRoot)) {
9857
- const bundlePlugins = join15(premiumRoot, bundle, "plugins");
9858
- if (!existsSync17(bundlePlugins)) continue;
10131
+ const premiumRoot = resolve15(dirname4(PLATFORM_ROOT), "premium-plugins");
10132
+ if (existsSync18(premiumRoot)) {
10133
+ for (const bundle of readdirSync11(premiumRoot)) {
10134
+ const bundlePlugins = join16(premiumRoot, bundle, "plugins");
10135
+ if (!existsSync18(bundlePlugins)) continue;
9859
10136
  try {
9860
- for (const name of readdirSync10(bundlePlugins)) {
9861
- const dir = join15(bundlePlugins, name);
10137
+ for (const name of readdirSync11(bundlePlugins)) {
10138
+ const dir = join16(bundlePlugins, name);
9862
10139
  try {
9863
10140
  if (statSync8(dir).isDirectory()) out.set(name, dir);
9864
10141
  } catch {
@@ -9871,10 +10148,10 @@ function listPluginDirs() {
9871
10148
  return out;
9872
10149
  }
9873
10150
  function readEnabledPlugins(accountId) {
9874
- const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9875
- if (!existsSync17(accountFile)) return /* @__PURE__ */ new Set();
10151
+ const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10152
+ if (!existsSync18(accountFile)) return /* @__PURE__ */ new Set();
9876
10153
  try {
9877
- const parsed = JSON.parse(readFileSync16(accountFile, "utf-8"));
10154
+ const parsed = JSON.parse(readFileSync18(accountFile, "utf-8"));
9878
10155
  return new Set(
9879
10156
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
9880
10157
  );
@@ -9883,10 +10160,10 @@ function readEnabledPlugins(accountId) {
9883
10160
  }
9884
10161
  }
9885
10162
  function readFrontmatter(path2) {
9886
- if (!existsSync17(path2)) return null;
10163
+ if (!existsSync18(path2)) return null;
9887
10164
  let raw;
9888
10165
  try {
9889
- raw = readFileSync16(path2, "utf-8");
10166
+ raw = readFileSync18(path2, "utf-8");
9890
10167
  } catch {
9891
10168
  return null;
9892
10169
  }
@@ -9901,7 +10178,7 @@ function computeActivePlugins(accountId) {
9901
10178
  for (const name of Array.from(enabled).sort()) {
9902
10179
  const dir = pluginDirs.get(name);
9903
10180
  if (!dir) continue;
9904
- const fm = readFrontmatter(join15(dir, "PLUGIN.md"));
10181
+ const fm = readFrontmatter(join16(dir, "PLUGIN.md"));
9905
10182
  if (!fm) continue;
9906
10183
  const description = frontmatterField(`---
9907
10184
  ${fm}
@@ -9918,7 +10195,7 @@ ${fm}
9918
10195
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
9919
10196
  );
9920
10197
  if (toolNames.length > 0 && descMap.size === 0) {
9921
- const hasSource = existsSync17(join15(dir, "mcp/dist/index.js")) || existsSync17(join15(dir, "mcp/src/index.ts"));
10198
+ const hasSource = existsSync18(join16(dir, "mcp/dist/index.js")) || existsSync18(join16(dir, "mcp/src/index.ts"));
9922
10199
  if (hasSource) {
9923
10200
  console.warn(
9924
10201
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -9928,7 +10205,7 @@ ${fm}
9928
10205
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
9929
10206
  const skills = [];
9930
10207
  for (const relPath of skillPaths) {
9931
- const skillPath = join15(dir, relPath);
10208
+ const skillPath = join16(dir, relPath);
9932
10209
  const skillFm = readFrontmatter(skillPath);
9933
10210
  if (!skillFm) continue;
9934
10211
  const skillName = frontmatterField(`---
@@ -9944,11 +10221,11 @@ ${skillFm}
9944
10221
  return out;
9945
10222
  }
9946
10223
  function computeSpecialistDomains(accountId) {
9947
- const specialistsDir = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
9948
- if (!existsSync17(specialistsDir)) return [];
10224
+ const specialistsDir = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
10225
+ if (!existsSync18(specialistsDir)) return [];
9949
10226
  let entries;
9950
10227
  try {
9951
- entries = readdirSync10(specialistsDir);
10228
+ entries = readdirSync11(specialistsDir);
9952
10229
  } catch {
9953
10230
  return [];
9954
10231
  }
@@ -9972,7 +10249,7 @@ function computeSpecialistDomains(accountId) {
9972
10249
  const out = [];
9973
10250
  for (const file of entries.sort()) {
9974
10251
  if (!file.endsWith(".md")) continue;
9975
- const fm = readFrontmatter(join15(specialistsDir, file));
10252
+ const fm = readFrontmatter(join16(specialistsDir, file));
9976
10253
  if (!fm) continue;
9977
10254
  const wrapped = `---
9978
10255
  ${fm}
@@ -9990,11 +10267,11 @@ ${fm}
9990
10267
  return out;
9991
10268
  }
9992
10269
  function computeDormantPlugins(accountId) {
9993
- const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9994
- if (!existsSync17(accountFile)) return [];
10270
+ const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10271
+ if (!existsSync18(accountFile)) return [];
9995
10272
  let enabled;
9996
10273
  try {
9997
- const raw = readFileSync16(accountFile, "utf-8");
10274
+ const raw = readFileSync18(accountFile, "utf-8");
9998
10275
  const parsed = JSON.parse(raw);
9999
10276
  enabled = new Set(
10000
10277
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
@@ -10005,22 +10282,22 @@ function computeDormantPlugins(accountId) {
10005
10282
  );
10006
10283
  return [];
10007
10284
  }
10008
- const pluginsDir = resolve14(PLATFORM_ROOT, "plugins");
10009
- if (!existsSync17(pluginsDir)) return [];
10285
+ const pluginsDir = resolve15(PLATFORM_ROOT, "plugins");
10286
+ if (!existsSync18(pluginsDir)) return [];
10010
10287
  let entries;
10011
10288
  try {
10012
- entries = readdirSync10(pluginsDir);
10289
+ entries = readdirSync11(pluginsDir);
10013
10290
  } catch {
10014
10291
  return [];
10015
10292
  }
10016
10293
  const out = [];
10017
10294
  for (const name of entries) {
10018
10295
  if (enabled.has(name)) continue;
10019
- const manifestPath = resolve14(pluginsDir, name, "PLUGIN.md");
10020
- if (!existsSync17(manifestPath)) continue;
10296
+ const manifestPath = resolve15(pluginsDir, name, "PLUGIN.md");
10297
+ if (!existsSync18(manifestPath)) continue;
10021
10298
  let manifest;
10022
10299
  try {
10023
- manifest = readFileSync16(manifestPath, "utf-8");
10300
+ manifest = readFileSync18(manifestPath, "utf-8");
10024
10301
  } catch {
10025
10302
  continue;
10026
10303
  }
@@ -10034,13 +10311,13 @@ function computeDormantPlugins(accountId) {
10034
10311
  }
10035
10312
 
10036
10313
  // server/routes/admin/claude-sessions.ts
10037
- import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
10038
- import { resolve as resolve15 } from "path";
10314
+ import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
10315
+ import { resolve as resolve16 } from "path";
10039
10316
  function readTunnelState(brandConfigDir) {
10040
10317
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
10041
- if (!existsSync18(statePath)) return null;
10318
+ if (!existsSync19(statePath)) return null;
10042
10319
  try {
10043
- const parsed = JSON.parse(readFileSync17(statePath, "utf-8"));
10320
+ const parsed = JSON.parse(readFileSync19(statePath, "utf-8"));
10044
10321
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
10045
10322
  const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
10046
10323
  const domain = typeof parsed.domain === "string" ? parsed.domain : null;
@@ -10051,10 +10328,10 @@ function readTunnelState(brandConfigDir) {
10051
10328
  }
10052
10329
  }
10053
10330
  function resolveTunnelUrl() {
10054
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve15(process.cwd(), "..");
10331
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
10055
10332
  let brand;
10056
10333
  try {
10057
- brand = JSON.parse(readFileSync17(resolve15(platformRoot2, "config", "brand.json"), "utf-8"));
10334
+ brand = JSON.parse(readFileSync19(resolve16(platformRoot2, "config", "brand.json"), "utf-8"));
10058
10335
  } catch {
10059
10336
  return null;
10060
10337
  }
@@ -10299,15 +10576,15 @@ var events_default = app18;
10299
10576
  import { createReadStream as createReadStream2 } from "fs";
10300
10577
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
10301
10578
  import { realpathSync as realpathSync4 } from "fs";
10302
- import { basename as basename6, dirname as dirname5, join as join17, resolve as resolve18, sep as sep5 } from "path";
10579
+ import { basename as basename6, dirname as dirname5, join as join18, resolve as resolve19, sep as sep5 } from "path";
10303
10580
  import { Readable as Readable2 } from "stream";
10304
10581
 
10305
10582
  // app/lib/data-path.ts
10306
10583
  import { realpathSync as realpathSync3 } from "fs";
10307
- import { resolve as resolve16, normalize, sep as sep3, relative } from "path";
10308
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "../platform");
10309
- var DATA_ROOT = resolve16(PLATFORM_ROOT5, "..", "data");
10310
- var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve16(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10584
+ import { resolve as resolve17, normalize, sep as sep3, relative } from "path";
10585
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "../platform");
10586
+ var DATA_ROOT = resolve17(PLATFORM_ROOT5, "..", "data");
10587
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve17(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10311
10588
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
10312
10589
  var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10313
10590
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -10320,7 +10597,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
10320
10597
  }
10321
10598
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
10322
10599
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
10323
- const absolute = resolve16(rootAbs, cleaned);
10600
+ const absolute = resolve17(rootAbs, cleaned);
10324
10601
  let rootReal;
10325
10602
  try {
10326
10603
  rootReal = realpathSync3(rootAbs);
@@ -10679,7 +10956,7 @@ async function cascadeDeleteDocument(params) {
10679
10956
 
10680
10957
  // app/lib/file-index.ts
10681
10958
  import * as fsp from "fs/promises";
10682
- import { resolve as resolve17, relative as relative2, join as join16, basename as basename5, extname as extname2, sep as sep4 } from "path";
10959
+ import { resolve as resolve18, relative as relative2, join as join17, basename as basename5, extname as extname2, sep as sep4 } from "path";
10683
10960
  import { tmpdir as tmpdir2 } from "os";
10684
10961
  import { execFile as execFile2 } from "child_process";
10685
10962
  import { promisify as promisify2 } from "util";
@@ -10750,7 +11027,7 @@ async function extractPdf(absolute) {
10750
11027
  return stdout.trim();
10751
11028
  }
10752
11029
  async function ocrPdf(absolute) {
10753
- const outPdf = join16(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
11030
+ const outPdf = join17(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
10754
11031
  try {
10755
11032
  await execFileAsync2(
10756
11033
  "ocrmypdf",
@@ -10812,7 +11089,7 @@ async function readDisplayName(absolute) {
10812
11089
  const stem = dot === -1 ? base : base.slice(0, dot);
10813
11090
  if (base === `${stem}.meta.json`) return null;
10814
11091
  try {
10815
- const raw = await fsp.readFile(join16(dir, `${stem}.meta.json`), "utf-8");
11092
+ const raw = await fsp.readFile(join17(dir, `${stem}.meta.json`), "utf-8");
10816
11093
  const meta = JSON.parse(raw);
10817
11094
  const dn = meta.displayName ?? meta.filename;
10818
11095
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -10832,7 +11109,7 @@ async function walkSubtree(root, dataRoot, out) {
10832
11109
  let clean = true;
10833
11110
  for (const entry of entries) {
10834
11111
  if (entry.isSymbolicLink()) continue;
10835
- const abs = join16(root, entry.name);
11112
+ const abs = join17(root, entry.name);
10836
11113
  if (entry.isDirectory()) {
10837
11114
  const sub = await walkSubtree(abs, dataRoot, out);
10838
11115
  if (!sub.clean) clean = false;
@@ -10987,8 +11264,8 @@ async function reconcileFileIndex(accountId, opts) {
10987
11264
  return withSession(opts, async (session) => {
10988
11265
  const walked = [];
10989
11266
  const subtreeRoots = [
10990
- resolve17(dataRoot, "uploads", accountId),
10991
- resolve17(dataRoot, "accounts", accountId)
11267
+ resolve18(dataRoot, "uploads", accountId),
11268
+ resolve18(dataRoot, "accounts", accountId)
10992
11269
  ];
10993
11270
  let clean = true;
10994
11271
  for (const root of subtreeRoots) {
@@ -11069,7 +11346,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
11069
11346
  async function indexFile(accountId, relativePath, opts) {
11070
11347
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
11071
11348
  const embed2 = opts?.embed ?? embed;
11072
- const absolute = resolve17(dataRoot, relativePath);
11349
+ const absolute = resolve18(dataRoot, relativePath);
11073
11350
  await withSession(opts, async (session) => {
11074
11351
  const st = await fsp.stat(absolute);
11075
11352
  const wf = {
@@ -11103,7 +11380,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
11103
11380
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11104
11381
  async function readMeta(absDir, baseName) {
11105
11382
  try {
11106
- const raw = await readFile4(join17(absDir, `${baseName}.meta.json`), "utf8");
11383
+ const raw = await readFile4(join18(absDir, `${baseName}.meta.json`), "utf8");
11107
11384
  const parsed = JSON.parse(raw);
11108
11385
  if (typeof parsed?.filename === "string") {
11109
11386
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -11114,7 +11391,7 @@ async function readMeta(absDir, baseName) {
11114
11391
  }
11115
11392
  async function readAccountNames() {
11116
11393
  const map = /* @__PURE__ */ new Map();
11117
- const accountsDir = resolve18(DATA_ROOT, "accounts");
11394
+ const accountsDir = resolve19(DATA_ROOT, "accounts");
11118
11395
  let names;
11119
11396
  try {
11120
11397
  names = await readdir3(accountsDir);
@@ -11123,7 +11400,7 @@ async function readAccountNames() {
11123
11400
  }
11124
11401
  for (const name of names) {
11125
11402
  if (!UUID_RE3.test(name)) continue;
11126
- const configPath2 = resolve18(accountsDir, name, "account.json");
11403
+ const configPath2 = resolve19(accountsDir, name, "account.json");
11127
11404
  try {
11128
11405
  const raw = await readFile4(configPath2, "utf8");
11129
11406
  const parsed = JSON.parse(raw);
@@ -11141,7 +11418,7 @@ async function readAccountNames() {
11141
11418
  }
11142
11419
  async function enrich(absolute, entry, accountNames) {
11143
11420
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
11144
- const meta = await readMeta(join17(absolute, entry.name), entry.name);
11421
+ const meta = await readMeta(join18(absolute, entry.name), entry.name);
11145
11422
  if (meta?.filename) {
11146
11423
  entry.displayName = meta.filename;
11147
11424
  entry.mimeType = meta.mimeType;
@@ -11239,7 +11516,7 @@ app19.get("/", requireAdminSession, async (c) => {
11239
11516
  continue;
11240
11517
  }
11241
11518
  try {
11242
- const entryPath = join17(absolute, name);
11519
+ const entryPath = join18(absolute, name);
11243
11520
  const s = await stat4(entryPath);
11244
11521
  entries.push({
11245
11522
  name,
@@ -11364,8 +11641,8 @@ app19.post("/upload", requireAdminSession, async (c) => {
11364
11641
  }
11365
11642
  const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
11366
11643
  const finalName = `${Date.now()}-${safeName}`;
11367
- const destDir = resolve18(DATA_ROOT, "uploads", accountId);
11368
- const destPath = resolve18(destDir, finalName);
11644
+ const destDir = resolve19(DATA_ROOT, "uploads", accountId);
11645
+ const destPath = resolve19(destDir, finalName);
11369
11646
  try {
11370
11647
  await mkdir3(destDir, { recursive: true });
11371
11648
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11430,7 +11707,7 @@ app19.delete("/", requireAdminSession, async (c) => {
11430
11707
  }
11431
11708
  const dot = base.lastIndexOf(".");
11432
11709
  const stem = dot === -1 ? base : base.slice(0, dot);
11433
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join17(dirname5(absolute), `${stem}.meta.json`) : null;
11710
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join18(dirname5(absolute), `${stem}.meta.json`) : null;
11434
11711
  await unlink2(absolute);
11435
11712
  if (sidecarPath) {
11436
11713
  try {
@@ -13479,8 +13756,8 @@ var graph_default_view_default = app25;
13479
13756
 
13480
13757
  // server/routes/admin/sidebar-artefacts.ts
13481
13758
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
13482
- import { resolve as resolve19, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13483
- import { existsSync as existsSync19 } from "fs";
13759
+ import { resolve as resolve20, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13760
+ import { existsSync as existsSync20 } from "fs";
13484
13761
  var LIMIT = 50;
13485
13762
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
13486
13763
  function toDataRootRelPath(absPath) {
@@ -13499,7 +13776,7 @@ app26.get("/", requireAdminSession, async (c) => {
13499
13776
  if (accountFiles === null) {
13500
13777
  return c.json({ error: "Failed to load artefacts" }, 500);
13501
13778
  }
13502
- const accountDir = resolve19(ACCOUNTS_DIR, accountId);
13779
+ const accountDir = resolve20(ACCOUNTS_DIR, accountId);
13503
13780
  const agents = await fetchAgentTemplateRows(accountDir);
13504
13781
  const artefacts = [...accountFiles, ...agents].sort(
13505
13782
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -13550,8 +13827,8 @@ async function fetchAccountFileArtefacts(accountId) {
13550
13827
  async function fetchAgentTemplateRows(accountDir) {
13551
13828
  const rows = [];
13552
13829
  for (const filename of ADMIN_AGENT_FILES) {
13553
- const overridePath = resolve19(accountDir, "agents", "admin", filename);
13554
- const bundledPath = resolve19(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13830
+ const overridePath = resolve20(accountDir, "agents", "admin", filename);
13831
+ const bundledPath = resolve20(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13555
13832
  const labelStem = filename.replace(/\.md$/, "");
13556
13833
  const row = await readAgentTemplateRow({
13557
13834
  id: `agent-template:admin:${filename}`,
@@ -13564,12 +13841,12 @@ async function fetchAgentTemplateRows(accountDir) {
13564
13841
  });
13565
13842
  if (row) rows.push(row);
13566
13843
  }
13567
- const overrideDir = resolve19(accountDir, "specialists", "agents");
13568
- const bundledDir = resolve19(PLATFORM_ROOT, "templates", "specialists", "agents");
13844
+ const overrideDir = resolve20(accountDir, "specialists", "agents");
13845
+ const bundledDir = resolve20(PLATFORM_ROOT, "templates", "specialists", "agents");
13569
13846
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
13570
13847
  for (const filename of specialistNames) {
13571
- const overridePath = resolve19(overrideDir, filename);
13572
- const bundledPath = resolve19(bundledDir, filename);
13848
+ const overridePath = resolve20(overrideDir, filename);
13849
+ const bundledPath = resolve20(bundledDir, filename);
13573
13850
  const row = await readAgentTemplateRow({
13574
13851
  id: `agent-template:specialist:${filename}`,
13575
13852
  displayName: filename.replace(/\.md$/, ""),
@@ -13586,7 +13863,7 @@ async function fetchAgentTemplateRows(accountDir) {
13586
13863
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
13587
13864
  const names = /* @__PURE__ */ new Set();
13588
13865
  for (const dir of [overrideDir, bundledDir]) {
13589
- if (!existsSync19(dir)) continue;
13866
+ if (!existsSync20(dir)) continue;
13590
13867
  try {
13591
13868
  const entries = await readdir4(dir);
13592
13869
  for (const entry of entries) {
@@ -13601,7 +13878,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
13601
13878
  }
13602
13879
  async function readAgentTemplateRow(inp) {
13603
13880
  let chosenPath = null;
13604
- if (existsSync19(inp.overridePath)) {
13881
+ if (existsSync20(inp.overridePath)) {
13605
13882
  try {
13606
13883
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
13607
13884
  chosenPath = inp.overridePath;
@@ -13612,7 +13889,7 @@ async function readAgentTemplateRow(inp) {
13612
13889
  );
13613
13890
  return null;
13614
13891
  }
13615
- } else if (existsSync19(inp.bundledPath)) {
13892
+ } else if (existsSync20(inp.bundledPath)) {
13616
13893
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
13617
13894
  console.error(
13618
13895
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -13936,24 +14213,24 @@ app31.get("/", async (c) => {
13936
14213
  var system_stats_default = app31;
13937
14214
 
13938
14215
  // server/routes/admin/health.ts
13939
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
13940
- import { resolve as resolve20, join as join18 } from "path";
13941
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
14216
+ import { existsSync as existsSync21, readFileSync as readFileSync20 } from "fs";
14217
+ import { resolve as resolve21, join as join19 } from "path";
14218
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
13942
14219
  var brandHostname = "maxy";
13943
- var brandJsonPath = join18(PLATFORM_ROOT6, "config", "brand.json");
13944
- if (existsSync20(brandJsonPath)) {
14220
+ var brandJsonPath = join19(PLATFORM_ROOT6, "config", "brand.json");
14221
+ if (existsSync21(brandJsonPath)) {
13945
14222
  try {
13946
- const brand = JSON.parse(readFileSync18(brandJsonPath, "utf-8"));
14223
+ const brand = JSON.parse(readFileSync20(brandJsonPath, "utf-8"));
13947
14224
  if (brand.hostname) brandHostname = brand.hostname;
13948
14225
  } catch {
13949
14226
  }
13950
14227
  }
13951
- var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
14228
+ var VERSION_FILE = resolve21(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
13952
14229
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
13953
14230
  var PROBE_TIMEOUT_MS = 1e3;
13954
14231
  function readVersion() {
13955
- if (!existsSync20(VERSION_FILE)) return "unknown";
13956
- return readFileSync18(VERSION_FILE, "utf-8").trim() || "unknown";
14232
+ if (!existsSync21(VERSION_FILE)) return "unknown";
14233
+ return readFileSync20(VERSION_FILE, "utf-8").trim() || "unknown";
13957
14234
  }
13958
14235
  async function probeConversationDb() {
13959
14236
  let session;
@@ -14495,16 +14772,16 @@ var admin_default = app39;
14495
14772
 
14496
14773
  // app/lib/access-gate.ts
14497
14774
  import neo4j4 from "neo4j-driver";
14498
- import { readFileSync as readFileSync19 } from "fs";
14499
- import { resolve as resolve21 } from "path";
14775
+ import { readFileSync as readFileSync21 } from "fs";
14776
+ import { resolve as resolve22 } from "path";
14500
14777
  import { randomUUID as randomUUID10 } from "crypto";
14501
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
14778
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14502
14779
  var driver = null;
14503
14780
  function readPassword() {
14504
14781
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
14505
- const passwordFile = resolve21(PLATFORM_ROOT7, "config/.neo4j-password");
14782
+ const passwordFile = resolve22(PLATFORM_ROOT7, "config/.neo4j-password");
14506
14783
  try {
14507
- return readFileSync19(passwordFile, "utf-8").trim();
14784
+ return readFileSync21(passwordFile, "utf-8").trim();
14508
14785
  } catch {
14509
14786
  throw new Error(
14510
14787
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -14792,9 +15069,9 @@ var verify_token_default = app40;
14792
15069
 
14793
15070
  // app/lib/access-email.ts
14794
15071
  import { spawn as spawn2 } from "child_process";
14795
- import { resolve as resolve22 } from "path";
14796
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14797
- var SEND_SCRIPT = resolve22(
15072
+ import { resolve as resolve23 } from "path";
15073
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
15074
+ var SEND_SCRIPT = resolve23(
14798
15075
  PLATFORM_ROOT8,
14799
15076
  "plugins",
14800
15077
  "email",
@@ -14936,8 +15213,8 @@ app42.route("/request-magic-link", request_magic_link_default);
14936
15213
  var access_default = app42;
14937
15214
 
14938
15215
  // server/routes/sites.ts
14939
- import { existsSync as existsSync21, readFileSync as readFileSync20, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
14940
- import { resolve as resolve23 } from "path";
15216
+ import { existsSync as existsSync22, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
15217
+ import { resolve as resolve24 } from "path";
14941
15218
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
14942
15219
  var MIME = {
14943
15220
  ".html": "text/html; charset=utf-8",
@@ -14994,15 +15271,15 @@ app43.get("/:rel{.*}", (c) => {
14994
15271
  }
14995
15272
  segments.push(seg);
14996
15273
  }
14997
- const rootDir = resolve23(account.accountDir, "sites");
14998
- let filePath = segments.length === 0 ? rootDir : resolve23(rootDir, ...segments);
15274
+ const rootDir = resolve24(account.accountDir, "sites");
15275
+ let filePath = segments.length === 0 ? rootDir : resolve24(rootDir, ...segments);
14999
15276
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
15000
15277
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
15001
15278
  return c.text("Forbidden", 403);
15002
15279
  }
15003
15280
  let stat7;
15004
15281
  try {
15005
- stat7 = existsSync21(filePath) ? statSync9(filePath) : null;
15282
+ stat7 = existsSync22(filePath) ? statSync9(filePath) : null;
15006
15283
  } catch {
15007
15284
  stat7 = null;
15008
15285
  }
@@ -15015,13 +15292,13 @@ app43.get("/:rel{.*}", (c) => {
15015
15292
  return c.redirect(target, 301);
15016
15293
  }
15017
15294
  if (stat7?.isDirectory()) {
15018
- filePath = resolve23(filePath, "index.html");
15295
+ filePath = resolve24(filePath, "index.html");
15019
15296
  }
15020
15297
  if (!filePath.startsWith(rootDir + "/")) {
15021
15298
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
15022
15299
  return c.text("Forbidden", 403);
15023
15300
  }
15024
- if (!existsSync21(filePath)) {
15301
+ if (!existsSync22(filePath)) {
15025
15302
  console.error(`[sites] not-found path=${reqPath} status=404`);
15026
15303
  return c.text("Not found", 404);
15027
15304
  }
@@ -15040,7 +15317,7 @@ app43.get("/:rel{.*}", (c) => {
15040
15317
  }
15041
15318
  let body;
15042
15319
  try {
15043
- body = readFileSync20(realPath);
15320
+ body = readFileSync22(realPath);
15044
15321
  } catch (err) {
15045
15322
  const code = err?.code;
15046
15323
  if (code === "EISDIR") {
@@ -15076,7 +15353,7 @@ var sites_default = app43;
15076
15353
 
15077
15354
  // app/lib/visitor-token.ts
15078
15355
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
15079
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync21, writeFileSync as writeFileSync7 } from "fs";
15356
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync23, writeFileSync as writeFileSync8 } from "fs";
15080
15357
  import { dirname as dirname6 } from "path";
15081
15358
  var TOKEN_PREFIX = "v1.";
15082
15359
  var SECRET_BYTES = 32;
@@ -15085,7 +15362,7 @@ var cachedSecret = null;
15085
15362
  function getSecret() {
15086
15363
  if (cachedSecret) return cachedSecret;
15087
15364
  try {
15088
- const hex2 = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15365
+ const hex2 = readFileSync23(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15089
15366
  if (hex2.length === SECRET_BYTES * 2) {
15090
15367
  cachedSecret = Buffer.from(hex2, "hex");
15091
15368
  return cachedSecret;
@@ -15095,11 +15372,11 @@ function getSecret() {
15095
15372
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
15096
15373
  try {
15097
15374
  mkdirSync4(dirname6(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
15098
- writeFileSync7(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
15375
+ writeFileSync8(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
15099
15376
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
15100
15377
  } catch {
15101
15378
  }
15102
- const hex = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15379
+ const hex = readFileSync23(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15103
15380
  cachedSecret = Buffer.from(hex, "hex");
15104
15381
  return cachedSecret;
15105
15382
  }
@@ -15152,8 +15429,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
15152
15429
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
15153
15430
 
15154
15431
  // app/lib/brand-config.ts
15155
- import { existsSync as existsSync22, readFileSync as readFileSync22 } from "fs";
15156
- import { join as join19 } from "path";
15432
+ import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
15433
+ import { join as join20 } from "path";
15157
15434
  var cached2 = null;
15158
15435
  var cachedAttempted = false;
15159
15436
  function readBrandConfig() {
@@ -15161,10 +15438,10 @@ function readBrandConfig() {
15161
15438
  cachedAttempted = true;
15162
15439
  const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
15163
15440
  if (!platformRoot2) return null;
15164
- const brandPath = join19(platformRoot2, "config", "brand.json");
15165
- if (!existsSync22(brandPath)) return null;
15441
+ const brandPath = join20(platformRoot2, "config", "brand.json");
15442
+ if (!existsSync23(brandPath)) return null;
15166
15443
  try {
15167
- cached2 = JSON.parse(readFileSync22(brandPath, "utf-8"));
15444
+ cached2 = JSON.parse(readFileSync24(brandPath, "utf-8"));
15168
15445
  return cached2;
15169
15446
  } catch {
15170
15447
  return null;
@@ -15652,14 +15929,14 @@ async function writeEvent(opts) {
15652
15929
  var visitor_event_default = app46;
15653
15930
 
15654
15931
  // server/routes/session.ts
15655
- import { resolve as resolve24 } from "path";
15656
- import { existsSync as existsSync23, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
15932
+ import { resolve as resolve25 } from "path";
15933
+ import { existsSync as existsSync24, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
15657
15934
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
15658
15935
  function writeBrandingCache(accountId, agentSlug, branding) {
15659
15936
  try {
15660
- const cacheDir = resolve24(MAXY_DIR, "branding-cache", accountId);
15937
+ const cacheDir = resolve25(MAXY_DIR, "branding-cache", accountId);
15661
15938
  mkdirSync5(cacheDir, { recursive: true });
15662
- writeFileSync8(resolve24(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15939
+ writeFileSync9(resolve25(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15663
15940
  } catch (err) {
15664
15941
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
15665
15942
  }
@@ -15747,8 +16024,8 @@ app47.post("/", async (c) => {
15747
16024
  }
15748
16025
  let agentConfig = null;
15749
16026
  if (account) {
15750
- const agentDir = resolve24(account.accountDir, "agents", agentSlug);
15751
- if (!existsSync23(agentDir) || !existsSync23(resolve24(agentDir, "config.json"))) {
16027
+ const agentDir = resolve25(account.accountDir, "agents", agentSlug);
16028
+ if (!existsSync24(agentDir) || !existsSync24(resolve25(agentDir, "config.json"))) {
15752
16029
  return c.json({ error: "Agent not found" }, 404);
15753
16030
  }
15754
16031
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -16028,7 +16305,7 @@ function startGraphHealthTimer() {
16028
16305
 
16029
16306
  // app/lib/file-watcher.ts
16030
16307
  import * as fsp2 from "fs/promises";
16031
- import { resolve as resolve25, sep as sep7 } from "path";
16308
+ import { resolve as resolve26, sep as sep7 } from "path";
16032
16309
  var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
16033
16310
  var DEFAULT_COALESCE_MS = 500;
16034
16311
  var ROOTS = ["uploads", "accounts"];
@@ -16047,7 +16324,7 @@ async function startFileWatcher(opts = {}) {
16047
16324
  const dropFn = opts.drop ?? dropFileIndex;
16048
16325
  for (const r of ROOTS) {
16049
16326
  try {
16050
- await fsp2.mkdir(resolve25(dataRoot, r), { recursive: true });
16327
+ await fsp2.mkdir(resolve26(dataRoot, r), { recursive: true });
16051
16328
  } catch (err) {
16052
16329
  console.error(
16053
16330
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -16068,7 +16345,7 @@ async function startFileWatcher(opts = {}) {
16068
16345
  timers.set(relativePath, t);
16069
16346
  }
16070
16347
  async function runHook(relativePath, accountId) {
16071
- const absolute = resolve25(dataRoot, relativePath);
16348
+ const absolute = resolve26(dataRoot, relativePath);
16072
16349
  let exists = false;
16073
16350
  try {
16074
16351
  const st = await fsp2.stat(absolute);
@@ -16092,7 +16369,7 @@ async function startFileWatcher(opts = {}) {
16092
16369
  }
16093
16370
  }
16094
16371
  async function watchRoot(rootName) {
16095
- const absRoot = resolve25(dataRoot, rootName);
16372
+ const absRoot = resolve26(dataRoot, rootName);
16096
16373
  try {
16097
16374
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
16098
16375
  for await (const event of iter) {
@@ -16781,6 +17058,9 @@ function createWebchatChannelRoutes(deps) {
16781
17058
  var QUEUED_THRESHOLD_MS2 = 3e4;
16782
17059
  var ACK_THRESHOLD_MS2 = 3e4;
16783
17060
  var SWEEP_INTERVAL_MS2 = 15e3;
17061
+ function keyDisplay(key) {
17062
+ return key.startsWith("session:") ? key.slice(0, "session:".length + 8) : key.slice(0, 8);
17063
+ }
16784
17064
  var WebchatGateway = class {
16785
17065
  constructor(deps) {
16786
17066
  this.deps = deps;
@@ -16843,7 +17123,7 @@ var WebchatGateway = class {
16843
17123
  );
16844
17124
  if (willDeliverNow) this.lastDeliveredAt.set(input.key, Date.now());
16845
17125
  console.error(
16846
- `[webchat:inbound] op=received key=${input.key.slice(0, 8)} role=${input.role} bytes=${bytes} delivery=${willDeliverNow ? "immediate" : "queued"}`
17126
+ `[webchat:inbound] op=received key=${keyDisplay(input.key)} role=${input.role} bytes=${bytes} delivery=${willDeliverNow ? "immediate" : "queued"}`
16847
17127
  );
16848
17128
  if (!hadSubscriber && !this.spawning.has(input.key)) {
16849
17129
  this.spawning.add(input.key);
@@ -16854,7 +17134,10 @@ var WebchatGateway = class {
16854
17134
  key: input.key,
16855
17135
  role: input.role,
16856
17136
  gatewayUrl: this.deps.gatewayUrl,
16857
- serverPath: this.deps.serverPath
17137
+ serverPath: this.deps.serverPath,
17138
+ // Task 800 — only present on a session-targeted launch, so the
17139
+ // default-path call shape stays byte-identical.
17140
+ ...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {}
16858
17141
  });
16859
17142
  } finally {
16860
17143
  this.spawning.delete(input.key);
@@ -16980,8 +17263,8 @@ function broadcastAdminShutdown(reason) {
16980
17263
 
16981
17264
  // ../lib/entitlement/src/index.ts
16982
17265
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
16983
- import { existsSync as existsSync24, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
16984
- import { resolve as resolve26 } from "path";
17266
+ import { existsSync as existsSync25, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
17267
+ import { resolve as resolve27 } from "path";
16985
17268
 
16986
17269
  // ../lib/entitlement/src/canonicalize.ts
16987
17270
  function canonicalize(value) {
@@ -17016,7 +17299,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
17016
17299
  var GRACE_DAYS = 7;
17017
17300
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
17018
17301
  function pubkeyPath(brand) {
17019
- return resolve26(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
17302
+ return resolve27(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
17020
17303
  }
17021
17304
  var memo = null;
17022
17305
  function memoKey(mtimeMs, account) {
@@ -17028,8 +17311,8 @@ function resolveEntitlement(brand, account) {
17028
17311
  if (brand.commercialMode !== true) {
17029
17312
  return logResolved(implicitTrust(account), null);
17030
17313
  }
17031
- const entitlementPath = resolve26(brand.configDir, "entitlement.json");
17032
- if (!existsSync24(entitlementPath)) {
17314
+ const entitlementPath = resolve27(brand.configDir, "entitlement.json");
17315
+ if (!existsSync25(entitlementPath)) {
17033
17316
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
17034
17317
  }
17035
17318
  const stat7 = statSync10(entitlementPath);
@@ -17044,7 +17327,7 @@ function resolveEntitlement(brand, account) {
17044
17327
  function verifyAndResolve(brand, entitlementPath, account) {
17045
17328
  let pubkeyPem;
17046
17329
  try {
17047
- pubkeyPem = readFileSync23(pubkeyPath(brand), "utf-8");
17330
+ pubkeyPem = readFileSync25(pubkeyPath(brand), "utf-8");
17048
17331
  } catch (err) {
17049
17332
  return logResolved(anonymousFallback("pubkey-missing"), {
17050
17333
  reason: "pubkey-missing"
@@ -17058,7 +17341,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
17058
17341
  }
17059
17342
  let envelope;
17060
17343
  try {
17061
- envelope = JSON.parse(readFileSync23(entitlementPath, "utf-8"));
17344
+ envelope = JSON.parse(readFileSync25(entitlementPath, "utf-8"));
17062
17345
  } catch {
17063
17346
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
17064
17347
  }
@@ -17219,14 +17502,14 @@ function clientFrom(c) {
17219
17502
  );
17220
17503
  }
17221
17504
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
17222
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join20(PLATFORM_ROOT9, "config", "brand.json") : "";
17505
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join21(PLATFORM_ROOT9, "config", "brand.json") : "";
17223
17506
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
17224
- if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
17507
+ if (BRAND_JSON_PATH && !existsSync26(BRAND_JSON_PATH)) {
17225
17508
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
17226
17509
  }
17227
- if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
17510
+ if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
17228
17511
  try {
17229
- const parsed = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
17512
+ const parsed = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
17230
17513
  BRAND = { ...BRAND, ...parsed };
17231
17514
  } catch (err) {
17232
17515
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -17245,11 +17528,11 @@ var brandLoginOpts = {
17245
17528
  bodyFont: BRAND.defaultFonts?.body,
17246
17529
  logoContainsName: !!BRAND.logoContainsName
17247
17530
  };
17248
- var ALIAS_DOMAINS_PATH = join20(homedir3(), BRAND.configDir, "alias-domains.json");
17531
+ var ALIAS_DOMAINS_PATH = join21(homedir3(), BRAND.configDir, "alias-domains.json");
17249
17532
  function loadAliasDomains() {
17250
17533
  try {
17251
- if (!existsSync25(ALIAS_DOMAINS_PATH)) return null;
17252
- const parsed = JSON.parse(readFileSync24(ALIAS_DOMAINS_PATH, "utf-8"));
17534
+ if (!existsSync26(ALIAS_DOMAINS_PATH)) return null;
17535
+ const parsed = JSON.parse(readFileSync26(ALIAS_DOMAINS_PATH, "utf-8"));
17253
17536
  if (!Array.isArray(parsed)) {
17254
17537
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
17255
17538
  return null;
@@ -17277,7 +17560,7 @@ var app48 = new Hono();
17277
17560
  var nativeFileFollowers = /* @__PURE__ */ new Map();
17278
17561
  var waGateway = new WaGateway({
17279
17562
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17280
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17563
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17281
17564
  // Task 751 — file delivery on the native channel: resolve the platform
17282
17565
  // account + path validation here and funnel through the shared send core.
17283
17566
  sendDocument: async ({ senderId, accountId, filePath, caption }) => {
@@ -17293,7 +17576,7 @@ var waGateway = new WaGateway({
17293
17576
  caption,
17294
17577
  accountId,
17295
17578
  maxyAccountId,
17296
- platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."))
17579
+ platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."))
17297
17580
  });
17298
17581
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
17299
17582
  },
@@ -17333,14 +17616,14 @@ app48.route("/", waGateway.routes());
17333
17616
  waGateway.startSweeper();
17334
17617
  var webchatGateway = new WebchatGateway({
17335
17618
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17336
- serverPath: process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."), "services/webchat-channel/dist/server.js"),
17337
- ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath }) => {
17619
+ serverPath: process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/webchat-channel/dist/server.js"),
17620
+ ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId }) => {
17338
17621
  if (role !== "admin") {
17339
17622
  console.error(`[webchat:inbound] op=spawn-refused key=${key} role=${role} reason=public-path-not-wired`);
17340
17623
  return;
17341
17624
  }
17342
17625
  const result = await managerRcSpawn({
17343
- sessionId: adminSessionIdFor(accountId, key),
17626
+ sessionId: sessionId ?? adminSessionIdFor(accountId, key),
17344
17627
  role: "admin",
17345
17628
  channel: "webchat",
17346
17629
  senderId: key,
@@ -17674,20 +17957,20 @@ app48.get("/agent-assets/:slug/:filename", (c) => {
17674
17957
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
17675
17958
  return c.text("Not found", 404);
17676
17959
  }
17677
- const filePath = resolve27(account.accountDir, "agents", slug, "assets", filename);
17678
- const expectedDir = resolve27(account.accountDir, "agents", slug, "assets");
17960
+ const filePath = resolve28(account.accountDir, "agents", slug, "assets", filename);
17961
+ const expectedDir = resolve28(account.accountDir, "agents", slug, "assets");
17679
17962
  if (!filePath.startsWith(expectedDir + "/")) {
17680
17963
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
17681
17964
  return c.text("Forbidden", 403);
17682
17965
  }
17683
- if (!existsSync25(filePath)) {
17966
+ if (!existsSync26(filePath)) {
17684
17967
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
17685
17968
  return c.text("Not found", 404);
17686
17969
  }
17687
17970
  const ext = "." + filename.split(".").pop()?.toLowerCase();
17688
17971
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
17689
17972
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
17690
- const body = readFileSync24(filePath);
17973
+ const body = readFileSync26(filePath);
17691
17974
  return c.body(body, 200, {
17692
17975
  "Content-Type": contentType,
17693
17976
  "Cache-Control": "public, max-age=3600"
@@ -17704,20 +17987,20 @@ app48.get("/generated/:filename", (c) => {
17704
17987
  console.error(`[generated] serve file=${filename} status=404`);
17705
17988
  return c.text("Not found", 404);
17706
17989
  }
17707
- const filePath = resolve27(account.accountDir, "generated", filename);
17708
- const expectedDir = resolve27(account.accountDir, "generated");
17990
+ const filePath = resolve28(account.accountDir, "generated", filename);
17991
+ const expectedDir = resolve28(account.accountDir, "generated");
17709
17992
  if (!filePath.startsWith(expectedDir + "/")) {
17710
17993
  console.error(`[generated] serve file=${filename} status=403`);
17711
17994
  return c.text("Forbidden", 403);
17712
17995
  }
17713
- if (!existsSync25(filePath)) {
17996
+ if (!existsSync26(filePath)) {
17714
17997
  console.error(`[generated] serve file=${filename} status=404`);
17715
17998
  return c.text("Not found", 404);
17716
17999
  }
17717
18000
  const ext = "." + filename.split(".").pop()?.toLowerCase();
17718
18001
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
17719
18002
  console.log(`[generated] serve file=${filename} status=200`);
17720
- const body = readFileSync24(filePath);
18003
+ const body = readFileSync26(filePath);
17721
18004
  return c.body(body, 200, {
17722
18005
  "Content-Type": contentType,
17723
18006
  "Cache-Control": "public, max-age=86400"
@@ -17730,9 +18013,9 @@ app48.route("/v", visitor_consent_default);
17730
18013
  var htmlCache = /* @__PURE__ */ new Map();
17731
18014
  var brandLogoPath = "/brand/maxy-monochrome.png";
17732
18015
  var brandIconPath = "/brand/maxy-monochrome.png";
17733
- if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
18016
+ if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
17734
18017
  try {
17735
- const fullBrand = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
18018
+ const fullBrand = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
17736
18019
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
17737
18020
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
17738
18021
  } catch {
@@ -17749,9 +18032,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
17749
18032
  function readInstalledVersion() {
17750
18033
  try {
17751
18034
  if (!PLATFORM_ROOT9) return "unknown";
17752
- const versionFile = join20(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
17753
- if (!existsSync25(versionFile)) return "unknown";
17754
- const content = readFileSync24(versionFile, "utf-8").trim();
18035
+ const versionFile = join21(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
18036
+ if (!existsSync26(versionFile)) return "unknown";
18037
+ const content = readFileSync26(versionFile, "utf-8").trim();
17755
18038
  return content || "unknown";
17756
18039
  } catch {
17757
18040
  return "unknown";
@@ -17792,7 +18075,7 @@ var clientErrorReporterScript = `<script>
17792
18075
  function cachedHtml(file) {
17793
18076
  let html = htmlCache.get(file);
17794
18077
  if (!html) {
17795
- html = readFileSync24(resolve27(process.cwd(), "public", file), "utf-8");
18078
+ html = readFileSync26(resolve28(process.cwd(), "public", file), "utf-8");
17796
18079
  const productNameEsc = escapeHtml(BRAND.productName);
17797
18080
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
17798
18081
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -17808,13 +18091,13 @@ ${clientErrorReporterScript}
17808
18091
  }
17809
18092
  var brandedHtmlCache = /* @__PURE__ */ new Map();
17810
18093
  function loadBrandingCache(agentSlug) {
17811
- const configDir2 = join20(homedir3(), BRAND.configDir);
18094
+ const configDir2 = join21(homedir3(), BRAND.configDir);
17812
18095
  try {
17813
18096
  const accountId = getDefaultAccountId();
17814
18097
  if (!accountId) return null;
17815
- const cachePath = join20(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
17816
- if (!existsSync25(cachePath)) return null;
17817
- return JSON.parse(readFileSync24(cachePath, "utf-8"));
18098
+ const cachePath = join21(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
18099
+ if (!existsSync26(cachePath)) return null;
18100
+ return JSON.parse(readFileSync26(cachePath, "utf-8"));
17818
18101
  } catch {
17819
18102
  return null;
17820
18103
  }
@@ -17902,7 +18185,7 @@ app48.use("/vnc-popout.html", logViewerFetch);
17902
18185
  app48.get("/vnc-popout.html", (c) => {
17903
18186
  let html = htmlCache.get("vnc-popout.html");
17904
18187
  if (!html) {
17905
- html = readFileSync24(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
18188
+ html = readFileSync26(resolve28(process.cwd(), "public", "vnc-popout.html"), "utf-8");
17906
18189
  const name = escapeHtml(BRAND.productName);
17907
18190
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
17908
18191
  html = html.replace("</head>", ` ${brandScript}
@@ -18058,11 +18341,11 @@ try {
18058
18341
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
18059
18342
  async function runAdminUserReconcileTick() {
18060
18343
  try {
18061
- if (!existsSync25(USERS_FILE)) {
18344
+ if (!existsSync26(USERS_FILE)) {
18062
18345
  console.error("[adminuser-self-heal] skip reason=no-users-file");
18063
18346
  return;
18064
18347
  }
18065
- const usersRaw = readFileSync24(USERS_FILE, "utf-8").trim();
18348
+ const usersRaw = readFileSync26(USERS_FILE, "utf-8").trim();
18066
18349
  if (!usersRaw) {
18067
18350
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
18068
18351
  return;
@@ -18172,7 +18455,7 @@ if (bootAccountConfig?.whatsapp) {
18172
18455
  }
18173
18456
  init({
18174
18457
  configDir: configDirForWhatsApp,
18175
- platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, "..")),
18458
+ platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, "..")),
18176
18459
  accountConfig: bootAccountConfig,
18177
18460
  onMessage: async (msg) => {
18178
18461
  if (msg.isOwnerMirror) {