@rubytech/create-maxy-code 0.1.277 → 0.1.279

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 (173) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/config/brand.json +1 -1
  3. package/payload/platform/plugins/admin/skills/plainly/SKILL.md +33 -16
  4. package/payload/platform/plugins/admin/skills/plainly/references/worked-examples.md +51 -238
  5. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -1
  6. package/payload/platform/plugins/business-assistant/PLUGIN.md +4 -0
  7. package/payload/platform/plugins/business-assistant/references/crm.md +6 -0
  8. package/payload/platform/plugins/business-assistant/references/e-sign.md +302 -0
  9. package/payload/platform/plugins/business-assistant/references/site-lead-intake.md +52 -0
  10. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -0
  11. package/payload/platform/plugins/cloudflare/references/api.md +17 -3
  12. package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +10 -0
  13. package/payload/platform/plugins/cloudflare/references/web-analytics.md +64 -0
  14. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +1 -0
  15. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -0
  16. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +7 -0
  17. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  18. package/payload/platform/services/whatsapp-channel/dist/notification.js +22 -1
  19. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  20. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
  21. package/payload/premium-plugins/.claude-plugin/marketplace.json +5 -0
  22. package/payload/premium-plugins/management-consulting/.claude-plugin/plugin.json +8 -0
  23. package/payload/premium-plugins/management-consulting/PLUGIN.md +92 -0
  24. package/payload/premium-plugins/management-consulting/skills/assumption-audit/SKILL.md +54 -0
  25. package/payload/premium-plugins/management-consulting/skills/business-case-builder/SKILL.md +56 -0
  26. package/payload/premium-plugins/management-consulting/skills/competitive-intel/SKILL.md +51 -0
  27. package/payload/premium-plugins/management-consulting/skills/customer-segmentation/SKILL.md +50 -0
  28. package/payload/premium-plugins/management-consulting/skills/decision-memo/SKILL.md +53 -0
  29. package/payload/premium-plugins/management-consulting/skills/growth-barriers/SKILL.md +54 -0
  30. package/payload/premium-plugins/management-consulting/skills/initiative-prioritizer/SKILL.md +51 -0
  31. package/payload/premium-plugins/management-consulting/skills/kpi-architect/SKILL.md +53 -0
  32. package/payload/premium-plugins/management-consulting/skills/market-mapping/SKILL.md +56 -0
  33. package/payload/premium-plugins/management-consulting/skills/narrative-builder/SKILL.md +53 -0
  34. package/payload/premium-plugins/management-consulting/skills/operating-model-design/SKILL.md +54 -0
  35. package/payload/premium-plugins/management-consulting/skills/portfolio-review/SKILL.md +52 -0
  36. package/payload/premium-plugins/management-consulting/skills/pricing-strategy/SKILL.md +55 -0
  37. package/payload/premium-plugins/management-consulting/skills/profit-pool-analysis/SKILL.md +52 -0
  38. package/payload/premium-plugins/management-consulting/skills/risk-and-mitigation/SKILL.md +49 -0
  39. package/payload/premium-plugins/management-consulting/skills/situation-assessment/SKILL.md +55 -0
  40. package/payload/premium-plugins/management-consulting/skills/stakeholder-alignment/SKILL.md +51 -0
  41. package/payload/premium-plugins/management-consulting/skills/strategic-options/SKILL.md +53 -0
  42. package/payload/premium-plugins/management-consulting/skills/transformation-roadmap/SKILL.md +53 -0
  43. package/payload/premium-plugins/management-consulting/skills/value-realization/SKILL.md +50 -0
  44. package/payload/premium-plugins/management-consulting/skills/war-gaming/SKILL.md +51 -0
  45. package/payload/server/public/assets/AdminShell-DnH3kou-.js +1 -0
  46. package/payload/server/public/assets/{Checkbox-BY2lndUH.js → Checkbox-2reCESkb.js} +1 -1
  47. package/payload/server/public/assets/{admin-C364q_-g.js → admin-xRCXEFNW.js} +1 -1
  48. package/payload/server/public/assets/{arc-BW1WhwmV.js → arc-BgelqC_3.js} +1 -1
  49. package/payload/server/public/assets/architecture-YZFGNWBL-YM-TtgPY.js +1 -0
  50. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CLhiy6Rc.js → architectureDiagram-Q4EWVU46-BabnAZJm.js} +1 -1
  51. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-ue7Vkc-Q.js → blockDiagram-DXYQGD6D-BJzZqNsy.js} +1 -1
  52. package/payload/server/public/assets/{browser-D66JrDpx.js → browser-DT2XfRpL.js} +1 -1
  53. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-dVjuUU_p.js → c4Diagram-AHTNJAMY-By-xuh9F.js} +1 -1
  54. package/payload/server/public/assets/channel-BRPH0atd.js +1 -0
  55. package/payload/server/public/assets/{chunk-2KRD3SAO-CKn-bEkI.js → chunk-2KRD3SAO-Gj2dSpBl.js} +1 -1
  56. package/payload/server/public/assets/{chunk-336JU56O-DLBJaAyL.js → chunk-336JU56O-2PXVPCUA.js} +2 -2
  57. package/payload/server/public/assets/chunk-426QAEUC-QhauxjvK.js +1 -0
  58. package/payload/server/public/assets/{chunk-4BX2VUAB-B2mSmC97.js → chunk-4BX2VUAB-9XIBlnC2.js} +1 -1
  59. package/payload/server/public/assets/{chunk-4TB4RGXK-DPHoq8nE.js → chunk-4TB4RGXK-Cr3mXPnI.js} +1 -1
  60. package/payload/server/public/assets/{chunk-55IACEB6-JLT9m7Hd.js → chunk-55IACEB6-Ccg46J3A.js} +1 -1
  61. package/payload/server/public/assets/{chunk-5FUZZQ4R-DjxdZ8WO.js → chunk-5FUZZQ4R-Cz9MvPKc.js} +1 -1
  62. package/payload/server/public/assets/{chunk-5PVQY5BW-BujJUZqf.js → chunk-5PVQY5BW-BleOdlgO.js} +1 -1
  63. package/payload/server/public/assets/{chunk-67CJDMHE-CCdP3Pdx.js → chunk-67CJDMHE-CyCYCQWy.js} +1 -1
  64. package/payload/server/public/assets/{chunk-7N4EOEYR-bXgVzdM9.js → chunk-7N4EOEYR-KpT3uHzH.js} +1 -1
  65. package/payload/server/public/assets/{chunk-AA7GKIK3-CYeDvY8B.js → chunk-AA7GKIK3-BfOzbuxq.js} +1 -1
  66. package/payload/server/public/assets/{chunk-BSJP7CBP-U0Fi-Ers.js → chunk-BSJP7CBP-Bq0M3wlv.js} +1 -1
  67. package/payload/server/public/assets/{chunk-CIAEETIT-C8QrV6Gg.js → chunk-CIAEETIT-CR-2dNaL.js} +1 -1
  68. package/payload/server/public/assets/{chunk-EDXVE4YY-DF2EBXie.js → chunk-EDXVE4YY-egUGMTOS.js} +1 -1
  69. package/payload/server/public/assets/{chunk-ENJZ2VHE-CoTooXpM.js → chunk-ENJZ2VHE-CQohBEFw.js} +1 -1
  70. package/payload/server/public/assets/{chunk-FMBD7UC4-DxAQS3UB.js → chunk-FMBD7UC4-DIxBUbLP.js} +1 -1
  71. package/payload/server/public/assets/{chunk-FOC6F5B3-CyIK3zeY.js → chunk-FOC6F5B3-C2694Zoq.js} +1 -1
  72. package/payload/server/public/assets/{chunk-ICPOFSXX-D8F-S9Bk.js → chunk-ICPOFSXX-DpXZKHyn.js} +2 -2
  73. package/payload/server/public/assets/{chunk-K5T4RW27-7GcDzjyJ.js → chunk-K5T4RW27-CUicG0Rp.js} +1 -1
  74. package/payload/server/public/assets/{chunk-KGLVRYIC-B7pAr9hf.js → chunk-KGLVRYIC-B5mPJhOr.js} +1 -1
  75. package/payload/server/public/assets/{chunk-LIHQZDEY-DEoU2jrz.js → chunk-LIHQZDEY-q81QhuMs.js} +1 -1
  76. package/payload/server/public/assets/{chunk-ORNJ4GCN-BwMFuN24.js → chunk-ORNJ4GCN-DgurdFZs.js} +1 -1
  77. package/payload/server/public/assets/{chunk-OYMX7WX6-C15Ps-tC.js → chunk-OYMX7WX6-CxqMRu2d.js} +1 -1
  78. package/payload/server/public/assets/chunk-QZHKN3VN-BDAQvtxz.js +1 -0
  79. package/payload/server/public/assets/{chunk-U2HBQHQK-BBPMxdAI.js → chunk-U2HBQHQK-BSLctJC9.js} +1 -1
  80. package/payload/server/public/assets/{chunk-X2U36JSP-xwRszlfe.js → chunk-X2U36JSP--0AUeeFl.js} +1 -1
  81. package/payload/server/public/assets/{chunk-XPW4576I-BA0a8Ygs.js → chunk-XPW4576I-D-hf9Bcn.js} +1 -1
  82. package/payload/server/public/assets/{chunk-YZCP3GAM-C4liAf7D.js → chunk-YZCP3GAM-PvOhSwI9.js} +1 -1
  83. package/payload/server/public/assets/{chunk-ZZ45TVLE-Cy3If_Rl.js → chunk-ZZ45TVLE-1zPUlNWz.js} +1 -1
  84. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BJv89PB6.js +1 -0
  85. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DNUszH5M.js +1 -0
  86. package/payload/server/public/assets/clone-CREg9jLM.js +1 -0
  87. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-Df_JmB8E.js → cose-bilkent-S5V4N54A-Cvo-gkBd.js} +1 -1
  88. package/payload/server/public/assets/{dagre-DKCdgCLD.js → dagre-CMHsNfjP.js} +1 -1
  89. package/payload/server/public/assets/{dagre-KV5264BT-DHZ3rA0O.js → dagre-KV5264BT-CM1DSx4E.js} +1 -1
  90. package/payload/server/public/assets/{data-uiOcPh8T.js → data-Dr7XUvAx.js} +1 -1
  91. package/payload/server/public/assets/{diagram-5BDNPKRD-XAci8Krv.js → diagram-5BDNPKRD-VDHiHwEI.js} +1 -1
  92. package/payload/server/public/assets/{diagram-G4DWMVQ6-DI6g5YJH.js → diagram-G4DWMVQ6-OKdufoeW.js} +1 -1
  93. package/payload/server/public/assets/{diagram-MMDJMWI5-D94oS42o.js → diagram-MMDJMWI5-Yg6QdCA1.js} +1 -1
  94. package/payload/server/public/assets/{diagram-TYMM5635-D_j5_oj_.js → diagram-TYMM5635-CpEMZQDu.js} +1 -1
  95. package/payload/server/public/assets/{dist-BmvZ8OaX.js → dist-811BIK0R.js} +1 -1
  96. package/payload/server/public/assets/{erDiagram-SMLLAGMA-DPx8cHxF.js → erDiagram-SMLLAGMA-Dw5gAkFM.js} +1 -1
  97. package/payload/server/public/assets/{flatten-Bo6YRmWl.js → flatten-BsWEYbBB.js} +1 -1
  98. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-Cdfxz2_5.js → flowDiagram-DWJPFMVM-Cy_R1XHz.js} +1 -1
  99. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-oregwFNl.js → ganttDiagram-T4ZO3ILL-BYARP_eH.js} +1 -1
  100. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CtOPqykB.js +1 -0
  101. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZI26T0o.js → gitGraphDiagram-UUTBAWPF-BGOe0unY.js} +1 -1
  102. package/payload/server/public/assets/{graph-BSHyF267.js → graph-DOEjjQHD.js} +2 -2
  103. package/payload/server/public/assets/{graph-labels-D5ecmK-Z.js → graph-labels-eOrWYy0R.js} +1 -1
  104. package/payload/server/public/assets/{graphlib-BuiXJGQr.js → graphlib-DaefxCga.js} +1 -1
  105. package/payload/server/public/assets/info-OMHHGYJF-Jba5enA8.js +1 -0
  106. package/payload/server/public/assets/infoDiagram-42DDH7IO-Df9BlkPA.js +2 -0
  107. package/payload/server/public/assets/{isEmpty-D6Kr-M1M.js → isEmpty-BWl67LAZ.js} +1 -1
  108. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DnBy6cze.js → ishikawaDiagram-UXIWVN3A-YrGuzpiI.js} +1 -1
  109. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DeYkJsvd.js → journeyDiagram-VCZTEJTY-EIykOcqg.js} +1 -1
  110. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BHuZmXiA.js → kanban-definition-6JOO6SKY-BR0TC6Je.js} +1 -1
  111. package/payload/server/public/assets/{line-BAjS0lyG.js → line-DPGcT5IM.js} +1 -1
  112. package/payload/server/public/assets/{linear-COm19-p7.js → linear-CPN03uSh.js} +1 -1
  113. package/payload/server/public/assets/{mermaid-parser.core-Cg06vNXY.js → mermaid-parser.core-D7Iu4c9M.js} +2 -2
  114. package/payload/server/public/assets/{mermaid.core-DkUCZA6N.js → mermaid.core-krXRpXn9.js} +3 -3
  115. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Gbaa7NRj.js → mindmap-definition-QFDTVHPH-HwiCtPzN.js} +1 -1
  116. package/payload/server/public/assets/{ordinal-BDi6f4xk.js → ordinal-krseTxxN.js} +1 -1
  117. package/payload/server/public/assets/packet-4T2RLAQJ-D_eWzeAP.js +1 -0
  118. package/payload/server/public/assets/pie-ZZUOXDRM-BDiy1Ob2.js +1 -0
  119. package/payload/server/public/assets/{pieDiagram-DEJITSTG-v7yUgLoq.js → pieDiagram-DEJITSTG-xodxyWLe.js} +1 -1
  120. package/payload/server/public/assets/{public-CTkj6UYK.js → public-xVaPcg6i.js} +3 -3
  121. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BpVlNbru.js → quadrantDiagram-34T5L4WZ-DuYYY4ZZ.js} +1 -1
  122. package/payload/server/public/assets/radar-PYXPWWZC-C5mlfmtg.js +1 -0
  123. package/payload/server/public/assets/{reduce-CGi9ik8i.js → reduce-tk-xY6Fv.js} +1 -1
  124. package/payload/server/public/assets/{requirementDiagram-MS252O5E-QrSZzaxF.js → requirementDiagram-MS252O5E-D0ta3kru.js} +1 -1
  125. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-IVgJCKl1.js → sankeyDiagram-XADWPNL6-KdHdlzvT.js} +1 -1
  126. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DsN4J_nq.js → sequenceDiagram-FGHM5R23-DoSFUTQZ.js} +1 -1
  127. package/payload/server/public/assets/{src-DLEIsjER.js → src-Cpl1JzME.js} +1 -1
  128. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DN0-8ZrI.js → stateDiagram-FHFEXIEX-BLW0KiSA.js} +1 -1
  129. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-C5zlCV4X.js +1 -0
  130. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BLYu380r.js → timeline-definition-GMOUNBTQ-8QAzhYz1.js} +1 -1
  131. package/payload/server/public/assets/treeView-SZITEDCU-CM-9m-cS.js +1 -0
  132. package/payload/server/public/assets/treemap-W4RFUUIX-DDHPB-Xh.js +1 -0
  133. package/payload/server/public/assets/{useSelectionMode-98jrB9kD.css → useSelectionMode-BnRcJeg2.css} +1 -1
  134. package/payload/server/public/assets/{useSelectionMode-80iYuGPa.js → useSelectionMode-DlJsX-_X.js} +1 -1
  135. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-Tfn8qVAB.js → vennDiagram-DHZGUBPP-BKvfScOi.js} +1 -1
  136. package/payload/server/public/assets/wardley-RL74JXVD-CUb3Br4q.js +1 -0
  137. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CeQNnKpT.js → wardleyDiagram-NUSXRM2D-DaMfDpJ3.js} +1 -1
  138. package/payload/server/public/assets/whatsapp-cDxgZkbM.js +1 -0
  139. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-H-IatOB_.js → xychartDiagram-5P7HB3ND-BIkNQlLa.js} +1 -1
  140. package/payload/server/public/browser.html +5 -5
  141. package/payload/server/public/data.html +6 -6
  142. package/payload/server/public/graph.html +7 -7
  143. package/payload/server/public/index.html +6 -6
  144. package/payload/server/public/public.html +5 -5
  145. package/payload/server/public/whatsapp.html +18 -0
  146. package/payload/server/server.js +1022 -800
  147. package/payload/server/public/assets/AdminShell-BcHJy_Y2.js +0 -1
  148. package/payload/server/public/assets/architecture-YZFGNWBL-xHbVjatf.js +0 -1
  149. package/payload/server/public/assets/channel-1FBBBcz1.js +0 -1
  150. package/payload/server/public/assets/chunk-426QAEUC-CfdaOTNb.js +0 -1
  151. package/payload/server/public/assets/chunk-QZHKN3VN-CHE_iZO7.js +0 -1
  152. package/payload/server/public/assets/classDiagram-6PBFFD2Q--mLJq--t.js +0 -1
  153. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C8TJtMFc.js +0 -1
  154. package/payload/server/public/assets/clone-UUs4PDQ1.js +0 -1
  155. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CmHdoS27.js +0 -1
  156. package/payload/server/public/assets/info-OMHHGYJF-DTA9msO-.js +0 -1
  157. package/payload/server/public/assets/infoDiagram-42DDH7IO-C9cKcMg3.js +0 -2
  158. package/payload/server/public/assets/packet-4T2RLAQJ-6GjqIKgu.js +0 -1
  159. package/payload/server/public/assets/pie-ZZUOXDRM-T72DJ5JR.js +0 -1
  160. package/payload/server/public/assets/radar-PYXPWWZC-x-6xW1dE.js +0 -1
  161. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DGDGYxGd.js +0 -1
  162. package/payload/server/public/assets/treeView-SZITEDCU-5-6wEryJ.js +0 -1
  163. package/payload/server/public/assets/treemap-W4RFUUIX-DF48Cc86.js +0 -1
  164. package/payload/server/public/assets/wardley-RL74JXVD-duKIa6Hq.js +0 -1
  165. /package/payload/server/public/assets/{_baseFor-Cam2PbSt.js → _baseFor-BHtDrjIo.js} +0 -0
  166. /package/payload/server/public/assets/{array-DYRGGQae.js → array-DetWRiSa.js} +0 -0
  167. /package/payload/server/public/assets/{chunk-CnGqDkHZ.js → chunk-CWOGyPgy.js} +0 -0
  168. /package/payload/server/public/assets/{cytoscape.esm-nWsJMTNI.js → cytoscape.esm-C9yNhe1u.js} +0 -0
  169. /package/payload/server/public/assets/{defaultLocale-Du1XY3Dp.js → defaultLocale-_WRwicXn.js} +0 -0
  170. /package/payload/server/public/assets/{init-B5BXBRcm.js → init-sTEcj9YX.js} +0 -0
  171. /package/payload/server/public/assets/{katex-HOUACuRw.js → katex-s61Rgv6l.js} +0 -0
  172. /package/payload/server/public/assets/{path-CNO468J-.js → path-B0Ik7Tu9.js} +0 -0
  173. /package/payload/server/public/assets/{rough.esm-DRO6hWPh.js → rough.esm-DKRO8IF-.js} +0 -0
@@ -1201,8 +1201,8 @@ var serveStatic = (options = { root: "" }) => {
1201
1201
  };
1202
1202
 
1203
1203
  // server/index.ts
1204
- import { readFileSync as readFileSync23, existsSync as existsSync24, watchFile } from "fs";
1205
- import { resolve as resolve26, join as join18, basename as basename6 } from "path";
1204
+ import { readFileSync as readFileSync24, existsSync as existsSync24, watchFile } from "fs";
1205
+ import { resolve as resolve27, join as join19, basename as basename7 } from "path";
1206
1206
  import { homedir as homedir2 } from "os";
1207
1207
  import { monitorEventLoopDelay } from "perf_hooks";
1208
1208
 
@@ -1763,7 +1763,7 @@ var credsSaveQueue = Promise.resolve();
1763
1763
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1764
1764
  console.error(`${TAG2} draining credential save queue\u2026`);
1765
1765
  const timer2 = new Promise(
1766
- (resolve27) => setTimeout(() => resolve27("timeout"), timeoutMs)
1766
+ (resolve28) => setTimeout(() => resolve28("timeout"), timeoutMs)
1767
1767
  );
1768
1768
  const result = await Promise.race([
1769
1769
  credsSaveQueue.then(() => "drained"),
@@ -1891,11 +1891,11 @@ async function createWaSocket(opts) {
1891
1891
  return sock;
1892
1892
  }
1893
1893
  async function waitForConnection(sock) {
1894
- return new Promise((resolve27, reject) => {
1894
+ return new Promise((resolve28, reject) => {
1895
1895
  const handler = (update) => {
1896
1896
  if (update.connection === "open") {
1897
1897
  sock.ev.off("connection.update", handler);
1898
- resolve27();
1898
+ resolve28();
1899
1899
  }
1900
1900
  if (update.connection === "close") {
1901
1901
  sock.ev.off("connection.update", handler);
@@ -2009,14 +2009,14 @@ ${inspected}`;
2009
2009
  return inspect2(err, INSPECT_OPTS2);
2010
2010
  }
2011
2011
  function withTimeout(label, promise, timeoutMs) {
2012
- return new Promise((resolve27, reject) => {
2012
+ return new Promise((resolve28, reject) => {
2013
2013
  const timer2 = setTimeout(() => {
2014
2014
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2015
2015
  }, timeoutMs);
2016
2016
  promise.then(
2017
2017
  (value) => {
2018
2018
  clearTimeout(timer2);
2019
- resolve27(value);
2019
+ resolve28(value);
2020
2020
  },
2021
2021
  (err) => {
2022
2022
  clearTimeout(timer2);
@@ -2601,8 +2601,8 @@ async function persistWhatsAppMessage(input) {
2601
2601
  const { givenName, familyName } = splitName(input.pushName);
2602
2602
  const prev = sessionWriteLocks.get(input.cacheKey);
2603
2603
  let release;
2604
- const mine = new Promise((resolve27) => {
2605
- release = resolve27;
2604
+ const mine = new Promise((resolve28) => {
2605
+ release = resolve28;
2606
2606
  });
2607
2607
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2608
2608
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3638,11 +3638,11 @@ async function connectWithReconnect(conn) {
3638
3638
  console.error(
3639
3639
  `${TAG12} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3640
3640
  );
3641
- await new Promise((resolve27) => {
3642
- const timer2 = setTimeout(resolve27, delay);
3641
+ await new Promise((resolve28) => {
3642
+ const timer2 = setTimeout(resolve28, delay);
3643
3643
  conn.abortController.signal.addEventListener("abort", () => {
3644
3644
  clearTimeout(timer2);
3645
- resolve27();
3645
+ resolve28();
3646
3646
  }, { once: true });
3647
3647
  });
3648
3648
  }
@@ -3650,16 +3650,16 @@ async function connectWithReconnect(conn) {
3650
3650
  }
3651
3651
  }
3652
3652
  function waitForDisconnectEvent(conn) {
3653
- return new Promise((resolve27) => {
3653
+ return new Promise((resolve28) => {
3654
3654
  if (!conn.sock) {
3655
- resolve27();
3655
+ resolve28();
3656
3656
  return;
3657
3657
  }
3658
3658
  const sock = conn.sock;
3659
3659
  const handler = (update) => {
3660
3660
  if (update.connection === "close") {
3661
3661
  sock.ev.off("connection.update", handler);
3662
- resolve27();
3662
+ resolve28();
3663
3663
  }
3664
3664
  };
3665
3665
  sock.ev.on("connection.update", handler);
@@ -3928,8 +3928,8 @@ async function handleInboundMessage(conn, msg) {
3928
3928
  const conversationKey = isGroup ? remoteJid : senderPhone;
3929
3929
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
3930
3930
  let resolvePending;
3931
- const sttPending = new Promise((resolve27) => {
3932
- resolvePending = resolve27;
3931
+ const sttPending = new Promise((resolve28) => {
3932
+ resolvePending = resolve28;
3933
3933
  });
3934
3934
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
3935
3935
  try {
@@ -4338,20 +4338,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
4338
4338
 
4339
4339
  // server/routes/health.ts
4340
4340
  function checkPort(port2, timeoutMs = 500) {
4341
- return new Promise((resolve27) => {
4341
+ return new Promise((resolve28) => {
4342
4342
  const socket = createConnection2(port2, "127.0.0.1");
4343
4343
  socket.setTimeout(timeoutMs);
4344
4344
  socket.once("connect", () => {
4345
4345
  socket.destroy();
4346
- resolve27(true);
4346
+ resolve28(true);
4347
4347
  });
4348
4348
  socket.once("error", () => {
4349
4349
  socket.destroy();
4350
- resolve27(false);
4350
+ resolve28(false);
4351
4351
  });
4352
4352
  socket.once("timeout", () => {
4353
4353
  socket.destroy();
4354
- resolve27(false);
4354
+ resolve28(false);
4355
4355
  });
4356
4356
  });
4357
4357
  }
@@ -5426,12 +5426,12 @@ async function dispatchOnce(input) {
5426
5426
  });
5427
5427
  if (!entry) return { error: "spawn-failed" };
5428
5428
  entry.lastInboundAt = Date.now();
5429
- let resolve27;
5429
+ let resolve28;
5430
5430
  const turnPromise = new Promise((r) => {
5431
- resolve27 = r;
5431
+ resolve28 = r;
5432
5432
  });
5433
5433
  const listener = (text) => {
5434
- resolve27(text);
5434
+ resolve28(text);
5435
5435
  };
5436
5436
  entry.subscribers.add(listener);
5437
5437
  const writeAtMs = Date.now();
@@ -6269,8 +6269,8 @@ async function startLogin(opts) {
6269
6269
  await clearAuth(authDir);
6270
6270
  let resolveCode = null;
6271
6271
  let rejectCode = null;
6272
- const codePromise = new Promise((resolve27, reject) => {
6273
- resolveCode = resolve27;
6272
+ const codePromise = new Promise((resolve28, reject) => {
6273
+ resolveCode = resolve28;
6274
6274
  rejectCode = reject;
6275
6275
  });
6276
6276
  const codeTimer = setTimeout(
@@ -6986,14 +6986,465 @@ app3.get("/group-info", async (c) => {
6986
6986
  });
6987
6987
  var whatsapp_default = app3;
6988
6988
 
6989
+ // server/routes/whatsapp-reader.ts
6990
+ import { readFileSync as readFileSync9, watch, statSync as statSync3, openSync, readSync, closeSync } from "fs";
6991
+ import { basename as basename2, dirname, join as join8, resolve as resolve9, sep as sep2 } from "path";
6992
+
6993
+ // server/routes/admin/sidebar-sessions.ts
6994
+ import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
6995
+ import { join as join7, resolve as resolve8 } from "path";
6996
+ var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
6997
+ var PID_FILE_RE = /^([0-9]+)\.json$/;
6998
+ var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
6999
+ var PUBLIC_ROLE = "public";
7000
+ var WEBCHAT_CHANNEL = "webchat";
7001
+ var app4 = new Hono();
7002
+ function claudeConfigDir() {
7003
+ return process.env.CLAUDE_CONFIG_DIR ?? null;
7004
+ }
7005
+ function enumerateJsonls(projectsRoot) {
7006
+ const out = [];
7007
+ let slugs;
7008
+ try {
7009
+ slugs = readdirSync4(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
7010
+ } catch (err) {
7011
+ if (err.code === "ENOENT") return out;
7012
+ throw err;
7013
+ }
7014
+ for (const slug of slugs) {
7015
+ const slugDir = join7(projectsRoot, slug);
7016
+ let entries;
7017
+ try {
7018
+ entries = readdirSync4(slugDir, { withFileTypes: true });
7019
+ } catch (err) {
7020
+ const code = err.code ?? "unknown";
7021
+ console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
7022
+ continue;
7023
+ }
7024
+ for (const entry of entries) {
7025
+ if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
7026
+ out.push({ path: join7(slugDir, entry.name), isSubagent: false });
7027
+ } else if (entry.isDirectory() && entry.name === "subagents") {
7028
+ const subDir = join7(slugDir, entry.name);
7029
+ let subEntries;
7030
+ try {
7031
+ subEntries = readdirSync4(subDir, { withFileTypes: true });
7032
+ } catch (err) {
7033
+ const code = err.code ?? "unknown";
7034
+ console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
7035
+ continue;
7036
+ }
7037
+ for (const sub of subEntries) {
7038
+ if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
7039
+ out.push({ path: join7(subDir, sub.name), isSubagent: true });
7040
+ }
7041
+ }
7042
+ }
7043
+ }
7044
+ }
7045
+ return out;
7046
+ }
7047
+ function sessionIdToPidMap(configDir2) {
7048
+ const out = /* @__PURE__ */ new Map();
7049
+ const sessionsDir = join7(configDir2, "sessions");
7050
+ let entries;
7051
+ try {
7052
+ entries = readdirSync4(sessionsDir, { withFileTypes: true });
7053
+ } catch {
7054
+ return out;
7055
+ }
7056
+ for (const entry of entries) {
7057
+ if (!entry.isFile()) continue;
7058
+ const m = entry.name.match(PID_FILE_RE);
7059
+ if (!m) continue;
7060
+ const pid = Number(m[1]);
7061
+ if (!Number.isFinite(pid) || pid <= 0) continue;
7062
+ let body;
7063
+ try {
7064
+ body = readFileSync8(join7(sessionsDir, entry.name), "utf8");
7065
+ } catch {
7066
+ continue;
7067
+ }
7068
+ let parsed;
7069
+ try {
7070
+ parsed = JSON.parse(body);
7071
+ } catch {
7072
+ continue;
7073
+ }
7074
+ if (!parsed || typeof parsed !== "object") continue;
7075
+ const sid = parsed.sessionId;
7076
+ if (typeof sid === "string" && sid.length > 0) out.set(sid, pid);
7077
+ }
7078
+ return out;
7079
+ }
7080
+ function loadUserTitles(accountDir) {
7081
+ const out = /* @__PURE__ */ new Map();
7082
+ if (!accountDir) return out;
7083
+ const path2 = join7(accountDir, "session-titles.json");
7084
+ let raw;
7085
+ try {
7086
+ raw = readFileSync8(path2, "utf8");
7087
+ } catch {
7088
+ return out;
7089
+ }
7090
+ let parsed;
7091
+ try {
7092
+ parsed = JSON.parse(raw);
7093
+ } catch {
7094
+ return out;
7095
+ }
7096
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return out;
7097
+ for (const [sessionId, value] of Object.entries(parsed)) {
7098
+ if (!sessionId) continue;
7099
+ if (!value || typeof value !== "object") continue;
7100
+ const v = value;
7101
+ if (typeof v.title !== "string") continue;
7102
+ const trimmed = v.title.trim();
7103
+ if (!trimmed) continue;
7104
+ out.set(sessionId, trimmed);
7105
+ }
7106
+ return out;
7107
+ }
7108
+ function readSidecarMeta(metaPath) {
7109
+ const empty = { bridgeIds: [], role: null, channel: null, senderId: null, startedAt: null };
7110
+ let raw;
7111
+ try {
7112
+ raw = readFileSync8(metaPath, "utf8");
7113
+ } catch {
7114
+ return empty;
7115
+ }
7116
+ let parsed;
7117
+ try {
7118
+ parsed = JSON.parse(raw);
7119
+ } catch {
7120
+ return empty;
7121
+ }
7122
+ if (!parsed || typeof parsed !== "object") return empty;
7123
+ const r = parsed;
7124
+ const bridgeIds = Array.isArray(r.bridgeIds) ? r.bridgeIds.filter((b) => typeof b === "string" && b.length > 0) : [];
7125
+ return {
7126
+ bridgeIds,
7127
+ role: typeof r.role === "string" ? r.role : null,
7128
+ channel: typeof r.channel === "string" ? r.channel : null,
7129
+ senderId: typeof r.senderId === "string" ? r.senderId : null,
7130
+ startedAt: typeof r.startedAt === "string" ? r.startedAt : null
7131
+ };
7132
+ }
7133
+ function startsWithCliMarker(s) {
7134
+ for (const p of CLI_MARKER_PREFIXES) if (s.startsWith(p)) return true;
7135
+ return false;
7136
+ }
7137
+ function trimToTitle(raw) {
7138
+ return raw.trim().replace(/\s+/g, " ");
7139
+ }
7140
+ function resolveTitle(body, sessionId, userTitles) {
7141
+ const userTitle = userTitles.get(sessionId);
7142
+ if (userTitle) return { title: trimToTitle(userTitle), source: "user" };
7143
+ let aiTitle = null;
7144
+ let firstUserMessage = null;
7145
+ for (const line of body.split("\n")) {
7146
+ if (!line || line[0] !== "{") continue;
7147
+ let parsed;
7148
+ try {
7149
+ parsed = JSON.parse(line);
7150
+ } catch {
7151
+ continue;
7152
+ }
7153
+ if (!parsed || typeof parsed !== "object") continue;
7154
+ const row = parsed;
7155
+ if (row.type === "ai-title" && typeof row.aiTitle === "string") {
7156
+ const t = row.aiTitle.trim();
7157
+ if (t) aiTitle = t;
7158
+ continue;
7159
+ }
7160
+ if (firstUserMessage === null && row.type === "user" && row.message && row.message.role === "user") {
7161
+ const content = row.message.content;
7162
+ if (typeof content !== "string") continue;
7163
+ const trimmed = content.trim();
7164
+ if (!trimmed) continue;
7165
+ if (startsWithCliMarker(trimmed)) continue;
7166
+ firstUserMessage = trimmed;
7167
+ }
7168
+ }
7169
+ if (aiTitle) return { title: trimToTitle(aiTitle), source: "ai" };
7170
+ if (firstUserMessage) return { title: trimToTitle(firstUserMessage), source: "first-message" };
7171
+ return { title: sessionId.slice(0, 8), source: "prefix" };
7172
+ }
7173
+ app4.get("/", requireAdminSession, async (c) => {
7174
+ const accountId = process.env.ACCOUNT_ID ?? null;
7175
+ const configDir2 = claudeConfigDir();
7176
+ if (!configDir2) {
7177
+ console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
7178
+ return c.json({ sessions: [], accountId });
7179
+ }
7180
+ const projectsRoot = join7(configDir2, "projects");
7181
+ const jsonls = enumerateJsonls(projectsRoot);
7182
+ const pidsBySession = sessionIdToPidMap(configDir2);
7183
+ const accountDir = accountId ? resolve8(ACCOUNTS_DIR, accountId) : null;
7184
+ const userTitles = loadUserTitles(accountDir);
7185
+ const rows = [];
7186
+ const seenIds = /* @__PURE__ */ new Set();
7187
+ let liveCount = 0;
7188
+ let subagentCount = 0;
7189
+ let nonResumableCount = 0;
7190
+ const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
7191
+ for (const { path: path2, isSubagent } of jsonls) {
7192
+ const lastSlash = path2.lastIndexOf("/");
7193
+ const base = path2.slice(lastSlash + 1);
7194
+ const projectDir = path2.slice(0, lastSlash);
7195
+ const sessionId = base.slice(0, -".jsonl".length);
7196
+ if (seenIds.has(sessionId)) {
7197
+ console.error(`[admin-sessions-list] duplicate-sessionId sessionId=${sessionId} path=${path2}`);
7198
+ continue;
7199
+ }
7200
+ seenIds.add(sessionId);
7201
+ let body;
7202
+ let mtimeMs;
7203
+ try {
7204
+ body = readFileSync8(path2, "utf8");
7205
+ mtimeMs = statSync2(path2).mtimeMs;
7206
+ } catch {
7207
+ continue;
7208
+ }
7209
+ const pid = pidsBySession.get(sessionId) ?? null;
7210
+ const live = pid !== null;
7211
+ const resolved = resolveTitle(body, sessionId, userTitles);
7212
+ titleSourceCounts[resolved.source] += 1;
7213
+ const metaPath = join7(projectDir, `${sessionId}.meta.json`);
7214
+ const { bridgeIds, role, channel } = readSidecarMeta(metaPath);
7215
+ const resumable = !(role === PUBLIC_ROLE && channel === WEBCHAT_CHANNEL);
7216
+ rows.push({
7217
+ sessionId,
7218
+ title: resolved.title,
7219
+ titleSource: resolved.source,
7220
+ startedAt: new Date(mtimeMs).toISOString(),
7221
+ live,
7222
+ isSubagent,
7223
+ pid,
7224
+ projectDir,
7225
+ bridgeIds,
7226
+ resumable
7227
+ });
7228
+ if (live) liveCount += 1;
7229
+ if (isSubagent) subagentCount += 1;
7230
+ if (!resumable) nonResumableCount += 1;
7231
+ }
7232
+ rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
7233
+ console.log(
7234
+ `[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} nonResumable=${nonResumableCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
7235
+ );
7236
+ return c.json({ sessions: rows, accountId });
7237
+ });
7238
+ var sidebar_sessions_default = app4;
7239
+
7240
+ // app/lib/whatsapp-reader/select-sessions.ts
7241
+ function selectAdminWhatsappSessions(rows) {
7242
+ return rows.filter((r) => r.role === "admin" && r.channel === "whatsapp").sort((a, b) => b.startedAt.localeCompare(a.startedAt)).map((r) => ({
7243
+ sessionId: r.sessionId,
7244
+ projectDir: r.projectDir,
7245
+ title: r.title,
7246
+ senderId: r.senderId,
7247
+ startedAt: r.startedAt
7248
+ }));
7249
+ }
7250
+
7251
+ // app/lib/whatsapp-reader/parse-transcript.ts
7252
+ var CLI_MARKER_PREFIXES2 = ["<local-command-", "<command-name>", "<command-message>"];
7253
+ var CHANNEL_WRAPPER = /^<channel\b[^>]*>\n?([\s\S]*?)\n?<\/channel>$/;
7254
+ function asString(content) {
7255
+ return typeof content === "string" ? content : null;
7256
+ }
7257
+ function tsOf(row) {
7258
+ return typeof row.timestamp === "string" ? row.timestamp : null;
7259
+ }
7260
+ function assistantTurns(content, ts) {
7261
+ if (!Array.isArray(content)) return [];
7262
+ const out = [];
7263
+ for (const block of content) {
7264
+ if (!block || typeof block !== "object") continue;
7265
+ const b = block;
7266
+ if (b.type === "text" && typeof b.text === "string") {
7267
+ out.push({ kind: "agent-text", text: b.text, ts });
7268
+ } else if (b.type === "tool_use" && typeof b.name === "string") {
7269
+ out.push({ kind: "tool-call", name: b.name, input: b.input ?? null, ts });
7270
+ }
7271
+ }
7272
+ return out;
7273
+ }
7274
+ function toolResultTurns(content, ts) {
7275
+ if (!Array.isArray(content)) return [];
7276
+ const out = [];
7277
+ for (const block of content) {
7278
+ if (!block || typeof block !== "object") continue;
7279
+ const b = block;
7280
+ if (b.type !== "tool_result") continue;
7281
+ const text = typeof b.content === "string" ? b.content : Array.isArray(b.content) ? b.content.map(
7282
+ (c) => c && typeof c === "object" && typeof c.text === "string" ? c.text : ""
7283
+ ).join("") : "";
7284
+ out.push({ kind: "tool-result", text, isError: b.is_error === true, ts });
7285
+ }
7286
+ return out;
7287
+ }
7288
+ function parseTranscript(lines) {
7289
+ const out = [];
7290
+ for (const line of lines) {
7291
+ if (!line || line[0] !== "{") continue;
7292
+ let row;
7293
+ try {
7294
+ const parsed = JSON.parse(line);
7295
+ if (!parsed || typeof parsed !== "object") continue;
7296
+ row = parsed;
7297
+ } catch {
7298
+ continue;
7299
+ }
7300
+ const ts = tsOf(row);
7301
+ const msg = row.message;
7302
+ if (row.type === "assistant") {
7303
+ out.push(...assistantTurns(msg?.content, ts));
7304
+ continue;
7305
+ }
7306
+ if (row.type !== "user" || !msg) continue;
7307
+ if (Array.isArray(msg.content)) {
7308
+ out.push(...toolResultTurns(msg.content, ts));
7309
+ continue;
7310
+ }
7311
+ const text = asString(msg.content);
7312
+ if (text === null) continue;
7313
+ if (CLI_MARKER_PREFIXES2.some((p) => text.startsWith(p))) continue;
7314
+ const isChannel = row.isMeta === true && typeof row.origin === "object" && row.origin !== null && row.origin.kind === "channel";
7315
+ if (isChannel) {
7316
+ const m = text.match(CHANNEL_WRAPPER);
7317
+ out.push({ kind: "operator-inbound", text: m ? m[1] : text, ts });
7318
+ } else {
7319
+ out.push({ kind: "operator-typed", text, ts });
7320
+ }
7321
+ }
7322
+ return out;
7323
+ }
7324
+
7325
+ // app/lib/whatsapp-reader/tail.ts
7326
+ function splitNewLines(buf, baseOffset) {
7327
+ const text = buf.toString("utf8");
7328
+ const lastNl = text.lastIndexOf("\n");
7329
+ if (lastNl === -1) return { lines: [], nextOffset: baseOffset };
7330
+ const complete = text.slice(0, lastNl);
7331
+ const consumedBytes = Buffer.byteLength(text.slice(0, lastNl + 1), "utf8");
7332
+ return {
7333
+ lines: complete.split("\n").filter((l) => l.length > 0),
7334
+ nextOffset: baseOffset + consumedBytes
7335
+ };
7336
+ }
7337
+
7338
+ // server/routes/whatsapp-reader.ts
7339
+ var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7340
+ var app5 = new Hono();
7341
+ app5.get("/conversations", requireAdminSession, async (c) => {
7342
+ const cfg = claudeConfigDir();
7343
+ if (!cfg) return c.json({ conversations: [] });
7344
+ const projectsRoot = join8(cfg, "projects");
7345
+ const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
7346
+ const rows = [];
7347
+ for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
7348
+ const sessionId = basename2(path2).replace(/\.jsonl$/, "");
7349
+ const projectDir = dirname(path2);
7350
+ const meta = readSidecarMeta(join8(projectDir, `${sessionId}.meta.json`));
7351
+ if (meta.role !== "admin" || meta.channel !== "whatsapp") continue;
7352
+ let body = "";
7353
+ try {
7354
+ body = readFileSync9(path2, "utf8");
7355
+ } catch {
7356
+ }
7357
+ const { title } = resolveTitle(body, sessionId, userTitles);
7358
+ rows.push({
7359
+ sessionId,
7360
+ projectDir,
7361
+ title,
7362
+ startedAt: meta.startedAt ?? "",
7363
+ role: meta.role,
7364
+ channel: meta.channel,
7365
+ senderId: meta.senderId
7366
+ });
7367
+ }
7368
+ return c.json({ conversations: selectAdminWhatsappSessions(rows) });
7369
+ });
7370
+ function readFrom(path2, from) {
7371
+ const end = statSync3(path2).size;
7372
+ if (end <= from) return { buf: Buffer.alloc(0), end: from };
7373
+ const fd = openSync(path2, "r");
7374
+ try {
7375
+ const buf = Buffer.alloc(end - from);
7376
+ readSync(fd, buf, 0, buf.length, from);
7377
+ return { buf, end };
7378
+ } finally {
7379
+ closeSync(fd);
7380
+ }
7381
+ }
7382
+ app5.get("/stream", requireAdminSession, (c) => {
7383
+ const sessionId = c.req.query("sessionId") ?? "";
7384
+ const projectDir = c.req.query("projectDir") ?? "";
7385
+ const cfg = claudeConfigDir();
7386
+ const projectsRoot = cfg ? resolve9(join8(cfg, "projects")) : null;
7387
+ if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
7388
+ return c.json({ error: "bad session reference" }, 400);
7389
+ }
7390
+ const jsonlPath = resolve9(join8(projectDir, `${sessionId}.jsonl`));
7391
+ if (!jsonlPath.startsWith(projectsRoot + sep2)) {
7392
+ return c.json({ error: "bad session reference" }, 400);
7393
+ }
7394
+ const encoder = new TextEncoder();
7395
+ const send = (controller, turn) => controller.enqueue(encoder.encode(`data: ${JSON.stringify(turn)}
7396
+
7397
+ `));
7398
+ const readable = new ReadableStream({
7399
+ start(controller) {
7400
+ let offset = 0;
7401
+ const drain = () => {
7402
+ try {
7403
+ const { buf, end } = readFrom(jsonlPath, offset);
7404
+ if (end <= offset) return;
7405
+ const { lines, nextOffset } = splitNewLines(buf, offset);
7406
+ offset = nextOffset;
7407
+ for (const turn of parseTranscript(lines)) send(controller, turn);
7408
+ } catch {
7409
+ }
7410
+ };
7411
+ try {
7412
+ const { buf, end } = readFrom(jsonlPath, 0);
7413
+ offset = end;
7414
+ for (const turn of parseTranscript(buf.toString("utf8").split("\n"))) send(controller, turn);
7415
+ } catch {
7416
+ controller.enqueue(encoder.encode('event: error\ndata: "read-failed"\n\n'));
7417
+ }
7418
+ let watcher = null;
7419
+ try {
7420
+ watcher = watch(jsonlPath, drain);
7421
+ } catch {
7422
+ }
7423
+ const poll = setInterval(drain, 1e3);
7424
+ c.req.raw.signal.addEventListener("abort", () => {
7425
+ watcher?.close();
7426
+ clearInterval(poll);
7427
+ try {
7428
+ controller.close();
7429
+ } catch {
7430
+ }
7431
+ });
7432
+ }
7433
+ });
7434
+ return new Response(readable, {
7435
+ headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" }
7436
+ });
7437
+ });
7438
+ var whatsapp_reader_default = app5;
7439
+
6989
7440
  // server/routes/onboarding.ts
6990
7441
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
6991
- import { openSync, closeSync, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync7, readFileSync as readFileSync9, unlinkSync } from "fs";
7442
+ import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync7, readFileSync as readFileSync11, unlinkSync } from "fs";
6992
7443
  import { createHash as createHash2, randomUUID as randomUUID7 } from "crypto";
6993
7444
 
6994
7445
  // ../lib/admins-write/src/index.ts
6995
- import { existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync4, statSync as statSync2 } from "fs";
6996
- import { dirname, join as join7 } from "path";
7446
+ import { existsSync as existsSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
7447
+ import { dirname as dirname2, join as join9 } from "path";
6997
7448
  function logLine(input, result) {
6998
7449
  const userIdShort = input.userId.slice(0, 8);
6999
7450
  console.error(
@@ -7001,7 +7452,7 @@ function logLine(input, result) {
7001
7452
  );
7002
7453
  }
7003
7454
  function writeFileAtomic(filePath, contents, mode) {
7004
- mkdirSync2(dirname(filePath), { recursive: true });
7455
+ mkdirSync2(dirname2(filePath), { recursive: true });
7005
7456
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
7006
7457
  writeFileSync5(tempPath, contents, mode !== void 0 ? { mode } : void 0);
7007
7458
  renameSync(tempPath, filePath);
@@ -7011,7 +7462,7 @@ function writeAdminEntry(input) {
7011
7462
  try {
7012
7463
  let users = [];
7013
7464
  if (existsSync6(input.usersFile)) {
7014
- const raw = readFileSync8(input.usersFile, "utf-8").trim();
7465
+ const raw = readFileSync10(input.usersFile, "utf-8").trim();
7015
7466
  if (raw) {
7016
7467
  const parsed = JSON.parse(raw);
7017
7468
  if (!Array.isArray(parsed)) {
@@ -7035,11 +7486,11 @@ function writeAdminEntry(input) {
7035
7486
  return result;
7036
7487
  }
7037
7488
  try {
7038
- const accountJsonPath = join7(input.accountDir, "account.json");
7489
+ const accountJsonPath = join9(input.accountDir, "account.json");
7039
7490
  if (!existsSync6(accountJsonPath)) {
7040
7491
  throw new Error(`account.json not found at ${accountJsonPath}`);
7041
7492
  }
7042
- const config = JSON.parse(readFileSync8(accountJsonPath, "utf-8"));
7493
+ const config = JSON.parse(readFileSync10(accountJsonPath, "utf-8"));
7043
7494
  const admins = config.admins ?? [];
7044
7495
  if (admins.some((a) => a.userId === input.userId)) {
7045
7496
  result.accountJsonResult = "noop";
@@ -7065,7 +7516,7 @@ function checkAdminAuthInvariant(input) {
7065
7516
  const usersUserIds = /* @__PURE__ */ new Set();
7066
7517
  if (existsSync6(input.usersFile)) {
7067
7518
  try {
7068
- const raw = readFileSync8(input.usersFile, "utf-8").trim();
7519
+ const raw = readFileSync10(input.usersFile, "utf-8").trim();
7069
7520
  if (raw) {
7070
7521
  const users = JSON.parse(raw);
7071
7522
  for (const u of users) {
@@ -7081,7 +7532,7 @@ function checkAdminAuthInvariant(input) {
7081
7532
  if (existsSync6(input.accountsDir)) {
7082
7533
  let entries;
7083
7534
  try {
7084
- entries = readdirSync4(input.accountsDir);
7535
+ entries = readdirSync5(input.accountsDir);
7085
7536
  } catch (err) {
7086
7537
  const msg = err instanceof Error ? err.message : String(err);
7087
7538
  console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
@@ -7090,17 +7541,17 @@ function checkAdminAuthInvariant(input) {
7090
7541
  }
7091
7542
  for (const entry of entries) {
7092
7543
  if (entry.startsWith(".")) continue;
7093
- const accountDir = join7(input.accountsDir, entry);
7544
+ const accountDir = join9(input.accountsDir, entry);
7094
7545
  try {
7095
- if (!statSync2(accountDir).isDirectory()) continue;
7546
+ if (!statSync4(accountDir).isDirectory()) continue;
7096
7547
  } catch {
7097
7548
  continue;
7098
7549
  }
7099
- const accountJsonPath = join7(accountDir, "account.json");
7550
+ const accountJsonPath = join9(accountDir, "account.json");
7100
7551
  if (!existsSync6(accountJsonPath)) continue;
7101
7552
  let admins = [];
7102
7553
  try {
7103
- const config = JSON.parse(readFileSync8(accountJsonPath, "utf-8"));
7554
+ const config = JSON.parse(readFileSync10(accountJsonPath, "utf-8"));
7104
7555
  admins = config.admins ?? [];
7105
7556
  } catch (err) {
7106
7557
  const msg = err instanceof Error ? err.message : String(err);
@@ -7141,7 +7592,7 @@ function hashPin(pin) {
7141
7592
  }
7142
7593
  function readUsersFile() {
7143
7594
  if (!existsSync7(USERS_FILE)) return null;
7144
- const raw = readFileSync9(USERS_FILE, "utf-8").trim();
7595
+ const raw = readFileSync11(USERS_FILE, "utf-8").trim();
7145
7596
  if (!raw) return [];
7146
7597
  return JSON.parse(raw);
7147
7598
  }
@@ -7171,11 +7622,11 @@ async function waitForAuthPage(timeoutMs = 2e4) {
7171
7622
  }
7172
7623
  return false;
7173
7624
  }
7174
- var app4 = new Hono();
7175
- app4.get("/claude-auth", async (c) => {
7625
+ var app6 = new Hono();
7626
+ app6.get("/claude-auth", async (c) => {
7176
7627
  return c.json({ authenticated: await checkAuthStatus() });
7177
7628
  });
7178
- app4.post("/claude-auth", async (c) => {
7629
+ app6.post("/claude-auth", async (c) => {
7179
7630
  let body = {};
7180
7631
  try {
7181
7632
  body = await c.req.json();
@@ -7207,7 +7658,7 @@ app4.post("/claude-auth", async (c) => {
7207
7658
  }
7208
7659
  ensureLogDir();
7209
7660
  writeFileSync6(logPath("claude-auth"), "");
7210
- const claudeAuthLogFd = openSync(logPath("claude-auth"), "a");
7661
+ const claudeAuthLogFd = openSync2(logPath("claude-auth"), "a");
7211
7662
  const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
7212
7663
  if (process.platform === "darwin") {
7213
7664
  vncLog("claude-auth", { action: "start", transport: "native", platform: "darwin" });
@@ -7217,7 +7668,7 @@ app4.post("/claude-auth", async (c) => {
7217
7668
  claudeProc2.unref();
7218
7669
  claudeProc2.stdout?.on("data", onClaudeOutput);
7219
7670
  claudeProc2.stderr?.on("data", onClaudeOutput);
7220
- claudeProc2.once("close", () => closeSync(claudeAuthLogFd));
7671
+ claudeProc2.once("close", () => closeSync2(claudeAuthLogFd));
7221
7672
  return c.json({ started: true, transport: "native" });
7222
7673
  }
7223
7674
  if (transport === "vnc") {
@@ -7235,11 +7686,11 @@ app4.post("/claude-auth", async (c) => {
7235
7686
  claudeProc.unref();
7236
7687
  claudeProc.stdout?.on("data", onClaudeOutput);
7237
7688
  claudeProc.stderr?.on("data", onClaudeOutput);
7238
- claudeProc.once("close", () => closeSync(claudeAuthLogFd));
7689
+ claudeProc.once("close", () => closeSync2(claudeAuthLogFd));
7239
7690
  await waitForAuthPage(2e4);
7240
7691
  return c.json({ started: true, transport });
7241
7692
  });
7242
- app4.post("/set-pin", async (c) => {
7693
+ app6.post("/set-pin", async (c) => {
7243
7694
  let existingUsers = null;
7244
7695
  try {
7245
7696
  existingUsers = readUsersFile();
@@ -7297,7 +7748,7 @@ app4.post("/set-pin", async (c) => {
7297
7748
  let installOwner = null;
7298
7749
  if (existsSync7(INSTALL_OWNER_FILE)) {
7299
7750
  try {
7300
- const raw = readFileSync9(INSTALL_OWNER_FILE, "utf-8").trim();
7751
+ const raw = readFileSync11(INSTALL_OWNER_FILE, "utf-8").trim();
7301
7752
  if (raw.length > 0) installOwner = raw;
7302
7753
  } catch (err) {
7303
7754
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -7341,7 +7792,7 @@ ${body.pin}
7341
7792
  }
7342
7793
  return c.json({ ok: true });
7343
7794
  });
7344
- app4.delete("/set-pin", async (c) => {
7795
+ app6.delete("/set-pin", async (c) => {
7345
7796
  let users = null;
7346
7797
  try {
7347
7798
  users = readUsersFile();
@@ -7375,12 +7826,12 @@ app4.delete("/set-pin", async (c) => {
7375
7826
  }
7376
7827
  return c.json({ ok: true });
7377
7828
  });
7378
- var onboarding_default = app4;
7829
+ var onboarding_default = app6;
7379
7830
 
7380
7831
  // server/routes/client-error.ts
7381
- import { appendFileSync, existsSync as existsSync8, renameSync as renameSync2, statSync as statSync3 } from "fs";
7382
- import { join as join8 } from "path";
7383
- var CLIENT_ERRORS_LOG = join8(LOG_DIR, "client-errors.log");
7832
+ import { appendFileSync, existsSync as existsSync8, renameSync as renameSync2, statSync as statSync5 } from "fs";
7833
+ import { join as join10 } from "path";
7834
+ var CLIENT_ERRORS_LOG = join10(LOG_DIR, "client-errors.log");
7384
7835
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
7385
7836
  var MAX_BODY_SIZE = 8 * 1024;
7386
7837
  var MAX_STACK_LEN = 2e3;
@@ -7424,15 +7875,15 @@ function stackHead(stack) {
7424
7875
  function rotateIfNeeded() {
7425
7876
  try {
7426
7877
  if (!existsSync8(CLIENT_ERRORS_LOG)) return;
7427
- const stats = statSync3(CLIENT_ERRORS_LOG);
7878
+ const stats = statSync5(CLIENT_ERRORS_LOG);
7428
7879
  if (stats.size < MAX_LOG_SIZE) return;
7429
7880
  renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
7430
7881
  } catch (err) {
7431
7882
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
7432
7883
  }
7433
7884
  }
7434
- var app5 = new Hono();
7435
- app5.post("/", async (c) => {
7885
+ var app7 = new Hono();
7886
+ app7.post("/", async (c) => {
7436
7887
  const client = resolveClientIp(
7437
7888
  c.env?.incoming?.socket?.remoteAddress,
7438
7889
  c.req.header("x-forwarded-for")
@@ -7534,21 +7985,21 @@ app5.post("/", async (c) => {
7534
7985
  }
7535
7986
  return c.json({ ok: true });
7536
7987
  });
7537
- var client_error_default = app5;
7988
+ var client_error_default = app7;
7538
7989
 
7539
7990
  // server/routes/admin/session.ts
7540
7991
  import { randomUUID as randomUUID8 } from "crypto";
7541
7992
 
7542
7993
  // app/lib/admin-identity/pin-validator.ts
7543
7994
  import { createHash as createHash3 } from "crypto";
7544
- import { existsSync as existsSync9, readFileSync as readFileSync10, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
7545
- import { join as join9 } from "path";
7995
+ import { existsSync as existsSync9, readFileSync as readFileSync12, readdirSync as readdirSync6, statSync as statSync6 } from "fs";
7996
+ import { join as join11 } from "path";
7546
7997
  function hashPin2(pin) {
7547
7998
  return createHash3("sha256").update(pin).digest("hex");
7548
7999
  }
7549
8000
  function readUsersFile2(usersFilePath) {
7550
8001
  if (!existsSync9(usersFilePath)) return null;
7551
- const raw = readFileSync10(usersFilePath, "utf-8").trim();
8002
+ const raw = readFileSync12(usersFilePath, "utf-8").trim();
7552
8003
  if (!raw) return [];
7553
8004
  return JSON.parse(raw);
7554
8005
  }
@@ -7570,22 +8021,22 @@ function scanForOrphanedAccountAdmins(users, accountsDir) {
7570
8021
  if (!existsSync9(accountsDir)) return orphans;
7571
8022
  let entries;
7572
8023
  try {
7573
- entries = readdirSync5(accountsDir);
8024
+ entries = readdirSync6(accountsDir);
7574
8025
  } catch {
7575
8026
  return orphans;
7576
8027
  }
7577
8028
  for (const entry of entries) {
7578
8029
  if (entry.startsWith(".")) continue;
7579
- const accountDir = join9(accountsDir, entry);
8030
+ const accountDir = join11(accountsDir, entry);
7580
8031
  try {
7581
- if (!statSync4(accountDir).isDirectory()) continue;
8032
+ if (!statSync6(accountDir).isDirectory()) continue;
7582
8033
  } catch {
7583
8034
  continue;
7584
8035
  }
7585
- const accountJsonPath = join9(accountDir, "account.json");
8036
+ const accountJsonPath = join11(accountDir, "account.json");
7586
8037
  if (!existsSync9(accountJsonPath)) continue;
7587
8038
  try {
7588
- const config = JSON.parse(readFileSync10(accountJsonPath, "utf-8"));
8039
+ const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
7589
8040
  const admins = config.admins ?? [];
7590
8041
  for (const a of admins) {
7591
8042
  if (typeof a.userId === "string" && !known.has(a.userId)) orphans.push(a.userId);
@@ -7652,8 +8103,8 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
7652
8103
  sessionId: initialSessionId
7653
8104
  };
7654
8105
  }
7655
- var app6 = new Hono();
7656
- app6.get("/", async (c) => {
8106
+ var app8 = new Hono();
8107
+ app8.get("/", async (c) => {
7657
8108
  const signedSessionToken = c.req.query("session_key");
7658
8109
  if (!signedSessionToken) {
7659
8110
  return c.json({ error: "Invalid or expired admin session" }, 401);
@@ -7699,7 +8150,7 @@ app6.get("/", async (c) => {
7699
8150
  sessionId: getSessionIdForSession(cacheKey) ?? null
7700
8151
  });
7701
8152
  });
7702
- app6.post("/", async (c) => {
8153
+ app8.post("/", async (c) => {
7703
8154
  let body;
7704
8155
  try {
7705
8156
  body = await c.req.json();
@@ -7762,20 +8213,20 @@ app6.post("/", async (c) => {
7762
8213
  const payload = await createAdminSession(selected.accountId, selected.config.thinkingView, userId, userName, selected.role, avatar);
7763
8214
  return c.json(payload);
7764
8215
  });
7765
- var session_default = app6;
8216
+ var session_default = app8;
7766
8217
 
7767
8218
  // server/routes/admin/logs.ts
7768
- import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync11, statSync as statSync5 } from "fs";
7769
- import { resolve as resolve8, basename as basename2 } from "path";
8219
+ import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync13, statSync as statSync7 } from "fs";
8220
+ import { resolve as resolve10, basename as basename3 } from "path";
7770
8221
 
7771
8222
  // app/lib/logs-read-resolve.ts
7772
8223
  import { existsSync as existsSync10 } from "fs";
7773
- import { join as join10 } from "path";
8224
+ import { join as join12 } from "path";
7774
8225
  function resolveSessionLogPaths(filename, logDirs) {
7775
8226
  const tried = [filename];
7776
8227
  const hits = [];
7777
8228
  for (const dir of logDirs) {
7778
- const fullPath = join10(dir, filename);
8229
+ const fullPath = join12(dir, filename);
7779
8230
  if (existsSync10(fullPath)) {
7780
8231
  hits.push({ path: fullPath, dir });
7781
8232
  }
@@ -7785,27 +8236,27 @@ function resolveSessionLogPaths(filename, logDirs) {
7785
8236
 
7786
8237
  // server/routes/admin/logs.ts
7787
8238
  var TAIL_BYTES = 8192;
7788
- var app7 = new Hono();
7789
- app7.get("/", async (c) => {
8239
+ var app9 = new Hono();
8240
+ app9.get("/", async (c) => {
7790
8241
  const fileParam = c.req.query("file");
7791
8242
  const typeParam = c.req.query("type");
7792
8243
  const sessionIdParam = c.req.query("sessionId");
7793
8244
  const cacheKeyParam = c.req.query("cacheKey");
7794
8245
  const download = c.req.query("download") === "1";
7795
8246
  const account = resolveAccount();
7796
- const accountLogDir = account ? resolve8(account.accountDir, "logs") : null;
8247
+ const accountLogDir = account ? resolve10(account.accountDir, "logs") : null;
7797
8248
  const logDirs = [];
7798
8249
  if (accountLogDir) logDirs.push(accountLogDir);
7799
8250
  logDirs.push(LOG_DIR);
7800
8251
  if (fileParam) {
7801
- const safe = basename2(fileParam);
8252
+ const safe = basename3(fileParam);
7802
8253
  const searched = [];
7803
8254
  for (const dir of logDirs) {
7804
- const filePath = resolve8(dir, safe);
8255
+ const filePath = resolve10(dir, safe);
7805
8256
  searched.push(filePath);
7806
8257
  try {
7807
- const buffer = readFileSync11(filePath);
7808
- const onDiskBytes = statSync5(filePath).size;
8258
+ const buffer = readFileSync13(filePath);
8259
+ const onDiskBytes = statSync7(filePath).size;
7809
8260
  const headers = {
7810
8261
  "Content-Type": "text/plain; charset=utf-8",
7811
8262
  "Content-Length": String(buffer.byteLength)
@@ -7868,9 +8319,9 @@ app7.get("/", async (c) => {
7868
8319
  if (hit) {
7869
8320
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
7870
8321
  try {
7871
- const filename = basename2(hit.path);
7872
- const buffer = readFileSync11(hit.path);
7873
- const onDiskBytes = statSync5(hit.path).size;
8322
+ const filename = basename3(hit.path);
8323
+ const buffer = readFileSync13(hit.path);
8324
+ const onDiskBytes = statSync7(hit.path).size;
7874
8325
  const headers = {
7875
8326
  "Content-Type": "text/plain; charset=utf-8",
7876
8327
  "Content-Length": String(buffer.byteLength)
@@ -7907,16 +8358,16 @@ app7.get("/", async (c) => {
7907
8358
  if (!existsSync11(dir)) continue;
7908
8359
  let files;
7909
8360
  try {
7910
- files = readdirSync6(dir).filter((f) => f.endsWith(".log"));
8361
+ files = readdirSync7(dir).filter((f) => f.endsWith(".log"));
7911
8362
  } catch (err) {
7912
8363
  const reason = err instanceof Error ? err.message : String(err);
7913
8364
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
7914
8365
  continue;
7915
8366
  }
7916
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync5(resolve8(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
8367
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve10(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
7917
8368
  seen.add(name);
7918
8369
  try {
7919
- const content = readFileSync11(resolve8(dir, name));
8370
+ const content = readFileSync13(resolve10(dir, name));
7920
8371
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
7921
8372
  logs[name] = tail.trim() || "(empty)";
7922
8373
  } catch (err) {
@@ -7928,12 +8379,12 @@ app7.get("/", async (c) => {
7928
8379
  }
7929
8380
  return c.json({ logs });
7930
8381
  });
7931
- var logs_default = app7;
8382
+ var logs_default = app9;
7932
8383
 
7933
8384
  // server/routes/admin/claude-info.ts
7934
8385
  import { execFileSync as execFileSync3 } from "child_process";
7935
- var app8 = new Hono();
7936
- app8.get("/", (c) => {
8386
+ var app10 = new Hono();
8387
+ app10.get("/", (c) => {
7937
8388
  let version = "unknown";
7938
8389
  try {
7939
8390
  const raw = execFileSync3("claude", ["--version"], { encoding: "utf-8", timeout: 5e3 });
@@ -7951,14 +8402,14 @@ app8.get("/", (c) => {
7951
8402
  const thinkingView = resolvedAccount?.config.thinkingView ?? "default";
7952
8403
  return c.json({ version, account, model, thinkingView });
7953
8404
  });
7954
- var claude_info_default = app8;
8405
+ var claude_info_default = app10;
7955
8406
 
7956
8407
  // server/routes/admin/attachment.ts
7957
8408
  import { readFile as readFile2, readdir } from "fs/promises";
7958
8409
  import { existsSync as existsSync12 } from "fs";
7959
- import { resolve as resolve9 } from "path";
7960
- var app9 = new Hono();
7961
- app9.get("/:attachmentId", requireAdminSession, async (c) => {
8410
+ import { resolve as resolve11 } from "path";
8411
+ var app11 = new Hono();
8412
+ app11.get("/:attachmentId", requireAdminSession, async (c) => {
7962
8413
  const attachmentId = c.req.param("attachmentId");
7963
8414
  const cacheKey = c.var.cacheKey;
7964
8415
  const accountId = getAccountIdForSession(cacheKey);
@@ -7968,11 +8419,11 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
7968
8419
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
7969
8420
  return new Response("Not found", { status: 404 });
7970
8421
  }
7971
- const dir = resolve9(ATTACHMENTS_ROOT, accountId, attachmentId);
8422
+ const dir = resolve11(ATTACHMENTS_ROOT, accountId, attachmentId);
7972
8423
  if (!existsSync12(dir)) {
7973
8424
  return new Response("Not found", { status: 404 });
7974
8425
  }
7975
- const metaPath = resolve9(dir, `${attachmentId}.meta.json`);
8426
+ const metaPath = resolve11(dir, `${attachmentId}.meta.json`);
7976
8427
  if (!existsSync12(metaPath)) {
7977
8428
  return new Response("Not found", { status: 404 });
7978
8429
  }
@@ -7987,7 +8438,7 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
7987
8438
  if (!dataFile) {
7988
8439
  return new Response("Not found", { status: 404 });
7989
8440
  }
7990
- const filePath = resolve9(dir, dataFile);
8441
+ const filePath = resolve11(dir, dataFile);
7991
8442
  const buffer = await readFile2(filePath);
7992
8443
  return new Response(new Uint8Array(buffer), {
7993
8444
  headers: {
@@ -7997,27 +8448,27 @@ app9.get("/:attachmentId", requireAdminSession, async (c) => {
7997
8448
  }
7998
8449
  });
7999
8450
  });
8000
- var attachment_default = app9;
8451
+ var attachment_default = app11;
8001
8452
 
8002
8453
  // server/routes/admin/agents.ts
8003
- import { resolve as resolve10 } from "path";
8004
- import { readdirSync as readdirSync7, readFileSync as readFileSync12, existsSync as existsSync13, rmSync } from "fs";
8005
- var app10 = new Hono();
8006
- app10.get("/", (c) => {
8454
+ import { resolve as resolve12 } from "path";
8455
+ import { readdirSync as readdirSync8, readFileSync as readFileSync14, existsSync as existsSync13, rmSync } from "fs";
8456
+ var app12 = new Hono();
8457
+ app12.get("/", (c) => {
8007
8458
  const account = resolveAccount();
8008
8459
  if (!account) return c.json({ agents: [] });
8009
- const agentsDir = resolve10(account.accountDir, "agents");
8460
+ const agentsDir = resolve12(account.accountDir, "agents");
8010
8461
  if (!existsSync13(agentsDir)) return c.json({ agents: [] });
8011
8462
  const agents = [];
8012
8463
  try {
8013
- const entries = readdirSync7(agentsDir, { withFileTypes: true });
8464
+ const entries = readdirSync8(agentsDir, { withFileTypes: true });
8014
8465
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
8015
8466
  if (!entry.isDirectory()) continue;
8016
8467
  if (entry.name === "admin") continue;
8017
- const configPath2 = resolve10(agentsDir, entry.name, "config.json");
8468
+ const configPath2 = resolve12(agentsDir, entry.name, "config.json");
8018
8469
  if (!existsSync13(configPath2)) continue;
8019
8470
  try {
8020
- const config = JSON.parse(readFileSync12(configPath2, "utf-8"));
8471
+ const config = JSON.parse(readFileSync14(configPath2, "utf-8"));
8021
8472
  agents.push({
8022
8473
  slug: entry.name,
8023
8474
  displayName: config.displayName ?? entry.name,
@@ -8033,7 +8484,7 @@ app10.get("/", (c) => {
8033
8484
  }
8034
8485
  return c.json({ agents });
8035
8486
  });
8036
- app10.delete("/:slug", async (c) => {
8487
+ app12.delete("/:slug", async (c) => {
8037
8488
  const slug = c.req.param("slug");
8038
8489
  const account = resolveAccount();
8039
8490
  if (!account) return c.json({ error: "No account resolved" }, 400);
@@ -8043,7 +8494,7 @@ app10.delete("/:slug", async (c) => {
8043
8494
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
8044
8495
  return c.json({ error: "Invalid agent slug" }, 400);
8045
8496
  }
8046
- const agentDir = resolve10(account.accountDir, "agents", slug);
8497
+ const agentDir = resolve12(account.accountDir, "agents", slug);
8047
8498
  if (!existsSync13(agentDir)) {
8048
8499
  return c.json({ error: "Agent not found" }, 404);
8049
8500
  }
@@ -8063,7 +8514,7 @@ app10.delete("/:slug", async (c) => {
8063
8514
  return c.json({ error: "Failed to delete agent" }, 500);
8064
8515
  }
8065
8516
  });
8066
- app10.post("/:slug/project", async (c) => {
8517
+ app12.post("/:slug/project", async (c) => {
8067
8518
  const slug = c.req.param("slug");
8068
8519
  const account = resolveAccount();
8069
8520
  if (!account) return c.json({ error: "No account resolved" }, 400);
@@ -8073,7 +8524,7 @@ app10.post("/:slug/project", async (c) => {
8073
8524
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
8074
8525
  return c.json({ error: "Invalid agent slug" }, 400);
8075
8526
  }
8076
- const agentDir = resolve10(account.accountDir, "agents", slug);
8527
+ const agentDir = resolve12(account.accountDir, "agents", slug);
8077
8528
  if (!existsSync13(agentDir)) {
8078
8529
  return c.json({ error: "Agent not found on disk" }, 404);
8079
8530
  }
@@ -8085,7 +8536,7 @@ app10.post("/:slug/project", async (c) => {
8085
8536
  return c.json({ error: `Projection failed: ${msg}` }, 500);
8086
8537
  }
8087
8538
  });
8088
- var agents_default = app10;
8539
+ var agents_default = app12;
8089
8540
 
8090
8541
  // server/routes/admin/sessions.ts
8091
8542
  import crypto2 from "crypto";
@@ -8357,8 +8808,8 @@ function formatAge(updatedAtStr) {
8357
8808
  return "unknown";
8358
8809
  }
8359
8810
  }
8360
- var app11 = new Hono();
8361
- app11.get("/", requireAdminSession, async (c) => {
8811
+ var app13 = new Hono();
8812
+ app13.get("/", requireAdminSession, async (c) => {
8362
8813
  const cacheKey = c.var.cacheKey;
8363
8814
  const accountId = getAccountIdForSession(cacheKey);
8364
8815
  if (!accountId) return c.json({ error: "Account not found for session" }, 401);
@@ -8388,7 +8839,7 @@ app11.get("/", requireAdminSession, async (c) => {
8388
8839
  return c.json({ error: "Failed to fetch sessions" }, 500);
8389
8840
  }
8390
8841
  });
8391
- app11.post("/new", requireAdminSession, async (c) => {
8842
+ app13.post("/new", requireAdminSession, async (c) => {
8392
8843
  const oldCacheKey = c.var.cacheKey;
8393
8844
  console.log(`[admin-chat] new-conversation outcome=ingress cacheKey=${oldCacheKey.slice(0, 8)}`);
8394
8845
  const accountId = getAccountIdForSession(oldCacheKey);
@@ -8405,7 +8856,7 @@ app11.post("/new", requireAdminSession, async (c) => {
8405
8856
  console.log(`[admin-chat] new-conversation outcome=ok oldKey=${oldCacheKey.slice(0, 8)} newKey=${newCacheKey.slice(0, 8)}`);
8406
8857
  return c.json({ session_key: newSignedSessionToken, sessionId: null });
8407
8858
  });
8408
- app11.post("/switch", requireAdminSession, async (c) => {
8859
+ app13.post("/switch", requireAdminSession, async (c) => {
8409
8860
  const cacheKey = c.var.cacheKey;
8410
8861
  const accountId = getAccountIdForSession(cacheKey);
8411
8862
  const userId = getUserIdForSession(cacheKey);
@@ -8433,7 +8884,7 @@ app11.post("/switch", requireAdminSession, async (c) => {
8433
8884
  console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetSessionId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
8434
8885
  return c.json({ session_key: targetSignedSessionToken, sessionId: targetSessionId });
8435
8886
  });
8436
- app11.delete("/:id", requireAdminSession, async (c) => {
8887
+ app13.delete("/:id", requireAdminSession, async (c) => {
8437
8888
  const sessionId = c.req.param("id");
8438
8889
  const cacheKey = c.var.cacheKey;
8439
8890
  const accountId = getAccountIdForSession(cacheKey);
@@ -8479,7 +8930,7 @@ app11.delete("/:id", requireAdminSession, async (c) => {
8479
8930
  500
8480
8931
  );
8481
8932
  });
8482
- app11.post("/:id/resume", async (c) => {
8933
+ app13.post("/:id/resume", async (c) => {
8483
8934
  const sessionId = c.req.param("id");
8484
8935
  const t0 = Date.now();
8485
8936
  const signedSessionToken = c.req.query("session_key") ?? "";
@@ -8748,7 +9199,7 @@ app11.post("/:id/resume", async (c) => {
8748
9199
  }
8749
9200
  });
8750
9201
  });
8751
- app11.put("/:id/label", requireAdminSession, async (c) => {
9202
+ app13.put("/:id/label", requireAdminSession, async (c) => {
8752
9203
  const sessionId = c.req.param("id");
8753
9204
  const cacheKey = c.var.cacheKey;
8754
9205
  let body;
@@ -8774,11 +9225,11 @@ app11.put("/:id/label", requireAdminSession, async (c) => {
8774
9225
  return c.json({ error: "Failed to rename session" }, 500);
8775
9226
  }
8776
9227
  });
8777
- var sessions_default = app11;
9228
+ var sessions_default = app13;
8778
9229
 
8779
9230
  // app/lib/claude-agent/spawn-context.ts
8780
- import { existsSync as existsSync15, readFileSync as readFileSync13, readdirSync as readdirSync8, statSync as statSync6 } from "fs";
8781
- import { dirname as dirname2, resolve as resolve11, join as join11 } from "path";
9231
+ import { existsSync as existsSync15, readFileSync as readFileSync15, readdirSync as readdirSync9, statSync as statSync8 } from "fs";
9232
+ import { dirname as dirname3, resolve as resolve13, join as join13 } from "path";
8782
9233
  async function resolveOwnerProfileBlock(accountId, userId) {
8783
9234
  if (!userId) return { ok: false, reason: "missing-user-id" };
8784
9235
  try {
@@ -8807,14 +9258,14 @@ function frontmatterField(manifest, field) {
8807
9258
  function extractPluginToolDescriptions(pluginDir) {
8808
9259
  const out = /* @__PURE__ */ new Map();
8809
9260
  const candidates = [
8810
- join11(pluginDir, "mcp/dist/index.js"),
8811
- join11(pluginDir, "mcp/src/index.ts")
9261
+ join13(pluginDir, "mcp/dist/index.js"),
9262
+ join13(pluginDir, "mcp/src/index.ts")
8812
9263
  ];
8813
9264
  let raw = null;
8814
9265
  for (const path2 of candidates) {
8815
9266
  if (!existsSync15(path2)) continue;
8816
9267
  try {
8817
- raw = readFileSync13(path2, "utf-8");
9268
+ raw = readFileSync15(path2, "utf-8");
8818
9269
  break;
8819
9270
  } catch {
8820
9271
  }
@@ -8863,26 +9314,26 @@ function parseSkillPathsFromFrontmatter(fm) {
8863
9314
  }
8864
9315
  function listPluginDirs() {
8865
9316
  const out = /* @__PURE__ */ new Map();
8866
- const platformPlugins = resolve11(PLATFORM_ROOT, "plugins");
9317
+ const platformPlugins = resolve13(PLATFORM_ROOT, "plugins");
8867
9318
  if (existsSync15(platformPlugins)) {
8868
- for (const name of readdirSync8(platformPlugins)) {
8869
- const dir = join11(platformPlugins, name);
9319
+ for (const name of readdirSync9(platformPlugins)) {
9320
+ const dir = join13(platformPlugins, name);
8870
9321
  try {
8871
- if (statSync6(dir).isDirectory()) out.set(name, dir);
9322
+ if (statSync8(dir).isDirectory()) out.set(name, dir);
8872
9323
  } catch {
8873
9324
  }
8874
9325
  }
8875
9326
  }
8876
- const premiumRoot = resolve11(dirname2(PLATFORM_ROOT), "premium-plugins");
9327
+ const premiumRoot = resolve13(dirname3(PLATFORM_ROOT), "premium-plugins");
8877
9328
  if (existsSync15(premiumRoot)) {
8878
- for (const bundle of readdirSync8(premiumRoot)) {
8879
- const bundlePlugins = join11(premiumRoot, bundle, "plugins");
9329
+ for (const bundle of readdirSync9(premiumRoot)) {
9330
+ const bundlePlugins = join13(premiumRoot, bundle, "plugins");
8880
9331
  if (!existsSync15(bundlePlugins)) continue;
8881
9332
  try {
8882
- for (const name of readdirSync8(bundlePlugins)) {
8883
- const dir = join11(bundlePlugins, name);
9333
+ for (const name of readdirSync9(bundlePlugins)) {
9334
+ const dir = join13(bundlePlugins, name);
8884
9335
  try {
8885
- if (statSync6(dir).isDirectory()) out.set(name, dir);
9336
+ if (statSync8(dir).isDirectory()) out.set(name, dir);
8886
9337
  } catch {
8887
9338
  }
8888
9339
  }
@@ -8893,10 +9344,10 @@ function listPluginDirs() {
8893
9344
  return out;
8894
9345
  }
8895
9346
  function readEnabledPlugins(accountId) {
8896
- const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9347
+ const accountFile = resolve13(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
8897
9348
  if (!existsSync15(accountFile)) return /* @__PURE__ */ new Set();
8898
9349
  try {
8899
- const parsed = JSON.parse(readFileSync13(accountFile, "utf-8"));
9350
+ const parsed = JSON.parse(readFileSync15(accountFile, "utf-8"));
8900
9351
  return new Set(
8901
9352
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
8902
9353
  );
@@ -8908,7 +9359,7 @@ function readFrontmatter(path2) {
8908
9359
  if (!existsSync15(path2)) return null;
8909
9360
  let raw;
8910
9361
  try {
8911
- raw = readFileSync13(path2, "utf-8");
9362
+ raw = readFileSync15(path2, "utf-8");
8912
9363
  } catch {
8913
9364
  return null;
8914
9365
  }
@@ -8923,7 +9374,7 @@ function computeActivePlugins(accountId) {
8923
9374
  for (const name of Array.from(enabled).sort()) {
8924
9375
  const dir = pluginDirs.get(name);
8925
9376
  if (!dir) continue;
8926
- const fm = readFrontmatter(join11(dir, "PLUGIN.md"));
9377
+ const fm = readFrontmatter(join13(dir, "PLUGIN.md"));
8927
9378
  if (!fm) continue;
8928
9379
  const description = frontmatterField(`---
8929
9380
  ${fm}
@@ -8940,7 +9391,7 @@ ${fm}
8940
9391
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
8941
9392
  );
8942
9393
  if (toolNames.length > 0 && descMap.size === 0) {
8943
- const hasSource = existsSync15(join11(dir, "mcp/dist/index.js")) || existsSync15(join11(dir, "mcp/src/index.ts"));
9394
+ const hasSource = existsSync15(join13(dir, "mcp/dist/index.js")) || existsSync15(join13(dir, "mcp/src/index.ts"));
8944
9395
  if (hasSource) {
8945
9396
  console.warn(
8946
9397
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -8950,7 +9401,7 @@ ${fm}
8950
9401
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
8951
9402
  const skills = [];
8952
9403
  for (const relPath of skillPaths) {
8953
- const skillPath = join11(dir, relPath);
9404
+ const skillPath = join13(dir, relPath);
8954
9405
  const skillFm = readFrontmatter(skillPath);
8955
9406
  if (!skillFm) continue;
8956
9407
  const skillName = frontmatterField(`---
@@ -8966,11 +9417,11 @@ ${skillFm}
8966
9417
  return out;
8967
9418
  }
8968
9419
  function computeSpecialistDomains(accountId) {
8969
- const specialistsDir = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
9420
+ const specialistsDir = resolve13(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
8970
9421
  if (!existsSync15(specialistsDir)) return [];
8971
9422
  let entries;
8972
9423
  try {
8973
- entries = readdirSync8(specialistsDir);
9424
+ entries = readdirSync9(specialistsDir);
8974
9425
  } catch {
8975
9426
  return [];
8976
9427
  }
@@ -8979,10 +9430,10 @@ function computeSpecialistDomains(accountId) {
8979
9430
  const resolveDesc = (qualified) => {
8980
9431
  if (!qualified.startsWith("mcp__")) return void 0;
8981
9432
  const rest = qualified.slice(5);
8982
- const sep7 = rest.indexOf("__");
8983
- if (sep7 < 0) return void 0;
8984
- const plugin = rest.slice(0, sep7);
8985
- const tool = rest.slice(sep7 + 2);
9433
+ const sep8 = rest.indexOf("__");
9434
+ if (sep8 < 0) return void 0;
9435
+ const plugin = rest.slice(0, sep8);
9436
+ const tool = rest.slice(sep8 + 2);
8986
9437
  let map = descByPlugin.get(plugin);
8987
9438
  if (!map) {
8988
9439
  const dir = pluginDirs.get(plugin);
@@ -8994,7 +9445,7 @@ function computeSpecialistDomains(accountId) {
8994
9445
  const out = [];
8995
9446
  for (const file of entries.sort()) {
8996
9447
  if (!file.endsWith(".md")) continue;
8997
- const fm = readFrontmatter(join11(specialistsDir, file));
9448
+ const fm = readFrontmatter(join13(specialistsDir, file));
8998
9449
  if (!fm) continue;
8999
9450
  const wrapped = `---
9000
9451
  ${fm}
@@ -9012,11 +9463,11 @@ ${fm}
9012
9463
  return out;
9013
9464
  }
9014
9465
  function computeDormantPlugins(accountId) {
9015
- const accountFile = resolve11(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9466
+ const accountFile = resolve13(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9016
9467
  if (!existsSync15(accountFile)) return [];
9017
9468
  let enabled;
9018
9469
  try {
9019
- const raw = readFileSync13(accountFile, "utf-8");
9470
+ const raw = readFileSync15(accountFile, "utf-8");
9020
9471
  const parsed = JSON.parse(raw);
9021
9472
  enabled = new Set(
9022
9473
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
@@ -9027,22 +9478,22 @@ function computeDormantPlugins(accountId) {
9027
9478
  );
9028
9479
  return [];
9029
9480
  }
9030
- const pluginsDir = resolve11(PLATFORM_ROOT, "plugins");
9481
+ const pluginsDir = resolve13(PLATFORM_ROOT, "plugins");
9031
9482
  if (!existsSync15(pluginsDir)) return [];
9032
9483
  let entries;
9033
9484
  try {
9034
- entries = readdirSync8(pluginsDir);
9485
+ entries = readdirSync9(pluginsDir);
9035
9486
  } catch {
9036
9487
  return [];
9037
9488
  }
9038
9489
  const out = [];
9039
9490
  for (const name of entries) {
9040
9491
  if (enabled.has(name)) continue;
9041
- const manifestPath = resolve11(pluginsDir, name, "PLUGIN.md");
9492
+ const manifestPath = resolve13(pluginsDir, name, "PLUGIN.md");
9042
9493
  if (!existsSync15(manifestPath)) continue;
9043
9494
  let manifest;
9044
9495
  try {
9045
- manifest = readFileSync13(manifestPath, "utf-8");
9496
+ manifest = readFileSync15(manifestPath, "utf-8");
9046
9497
  } catch {
9047
9498
  continue;
9048
9499
  }
@@ -9056,13 +9507,13 @@ function computeDormantPlugins(accountId) {
9056
9507
  }
9057
9508
 
9058
9509
  // server/routes/admin/claude-sessions.ts
9059
- import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
9060
- import { resolve as resolve12 } from "path";
9510
+ import { existsSync as existsSync16, readFileSync as readFileSync16 } from "fs";
9511
+ import { resolve as resolve14 } from "path";
9061
9512
  function readTunnelState(brandConfigDir) {
9062
9513
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
9063
9514
  if (!existsSync16(statePath)) return null;
9064
9515
  try {
9065
- const parsed = JSON.parse(readFileSync14(statePath, "utf-8"));
9516
+ const parsed = JSON.parse(readFileSync16(statePath, "utf-8"));
9066
9517
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
9067
9518
  const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
9068
9519
  const domain = typeof parsed.domain === "string" ? parsed.domain : null;
@@ -9073,10 +9524,10 @@ function readTunnelState(brandConfigDir) {
9073
9524
  }
9074
9525
  }
9075
9526
  function resolveTunnelUrl() {
9076
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
9527
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
9077
9528
  let brand;
9078
9529
  try {
9079
- brand = JSON.parse(readFileSync14(resolve12(platformRoot2, "config", "brand.json"), "utf-8"));
9530
+ brand = JSON.parse(readFileSync16(resolve14(platformRoot2, "config", "brand.json"), "utf-8"));
9080
9531
  } catch {
9081
9532
  return null;
9082
9533
  }
@@ -9103,7 +9554,7 @@ function managerBase3() {
9103
9554
  const port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "claude-session-manager:wrapper" });
9104
9555
  return `http://127.0.0.1:${port2}`;
9105
9556
  }
9106
- var app12 = new Hono();
9557
+ var app14 = new Hono();
9107
9558
  async function performSpawnWithInitialMessage(args) {
9108
9559
  const ownerStart = Date.now();
9109
9560
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
@@ -9180,8 +9631,8 @@ function mintTranscriptEdge(sessionId, claudeSessionId, accountId) {
9180
9631
  if (!sessionId || !claudeSessionId) return;
9181
9632
  void linkConversationTranscript(sessionId, claudeSessionId, accountId);
9182
9633
  }
9183
- app12.use("*", requireAdminSession);
9184
- app12.post("/", async (c) => {
9634
+ app14.use("*", requireAdminSession);
9635
+ app14.post("/", async (c) => {
9185
9636
  const routeStart = Date.now();
9186
9637
  const cacheKey = c.get("cacheKey") ?? "";
9187
9638
  let body = {};
@@ -9224,18 +9675,18 @@ app12.post("/", async (c) => {
9224
9675
  console.log(`${TAG21} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
9225
9676
  return response;
9226
9677
  });
9227
- var claude_sessions_default = app12;
9678
+ var claude_sessions_default = app14;
9228
9679
 
9229
9680
  // server/routes/admin/log-ingest.ts
9230
9681
  var TAG22 = "[log-ingest]";
9231
9682
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
9232
9683
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
9233
9684
  var MAX_LINE_BYTES = 4096;
9234
- var app13 = new Hono();
9685
+ var app15 = new Hono();
9235
9686
  function isLoopbackAddr(addr) {
9236
9687
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
9237
9688
  }
9238
- app13.post("/", async (c) => {
9689
+ app15.post("/", async (c) => {
9239
9690
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
9240
9691
  if (!isLoopbackAddr(remoteAddr)) {
9241
9692
  console.error(`${TAG22} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -9278,7 +9729,7 @@ app13.post("/", async (c) => {
9278
9729
  else console.log(formatted);
9279
9730
  return c.json({ ok: true }, 200);
9280
9731
  });
9281
- var log_ingest_default = app13;
9732
+ var log_ingest_default = app15;
9282
9733
 
9283
9734
  // server/routes/admin/events.ts
9284
9735
  var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
@@ -9287,8 +9738,8 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
9287
9738
  "device-url:vnc-surface-shown",
9288
9739
  "device-url:malformed"
9289
9740
  ]);
9290
- var app14 = new Hono();
9291
- app14.post("/", async (c) => {
9741
+ var app16 = new Hono();
9742
+ app16.post("/", async (c) => {
9292
9743
  const TAG30 = "[admin:events]";
9293
9744
  let body;
9294
9745
  try {
@@ -9319,21 +9770,21 @@ app14.post("/", async (c) => {
9319
9770
  console.error(`[${event}] ${formatted}`);
9320
9771
  return c.json({ ok: true });
9321
9772
  });
9322
- var events_default = app14;
9773
+ var events_default = app16;
9323
9774
 
9324
9775
  // server/routes/admin/files.ts
9325
9776
  import { createReadStream as createReadStream2 } from "fs";
9326
9777
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
9327
9778
  import { realpathSync as realpathSync4 } from "fs";
9328
- import { basename as basename4, dirname as dirname3, join as join13, resolve as resolve15, sep as sep4 } from "path";
9779
+ import { basename as basename5, dirname as dirname4, join as join15, resolve as resolve17, sep as sep5 } from "path";
9329
9780
  import { Readable as Readable2 } from "stream";
9330
9781
 
9331
9782
  // app/lib/data-path.ts
9332
9783
  import { realpathSync as realpathSync3 } from "fs";
9333
- import { resolve as resolve13, normalize, sep as sep2, relative } from "path";
9334
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve13(process.cwd(), "../platform");
9335
- var DATA_ROOT = resolve13(PLATFORM_ROOT5, "..", "data");
9336
- var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve13(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
9784
+ import { resolve as resolve15, normalize, sep as sep3, relative } from "path";
9785
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve15(process.cwd(), "../platform");
9786
+ var DATA_ROOT = resolve15(PLATFORM_ROOT5, "..", "data");
9787
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve15(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
9337
9788
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
9338
9789
  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;
9339
9790
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -9346,7 +9797,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
9346
9797
  }
9347
9798
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
9348
9799
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
9349
- const absolute = resolve13(rootAbs, cleaned);
9800
+ const absolute = resolve15(rootAbs, cleaned);
9350
9801
  let rootReal;
9351
9802
  try {
9352
9803
  rootReal = realpathSync3(rootAbs);
@@ -9363,7 +9814,7 @@ function resolveUnderRoot(raw, rootAbs, rootLabel) {
9363
9814
  } catch (err) {
9364
9815
  const code = err.code;
9365
9816
  if (code === "ENOENT") {
9366
- if (absolute !== rootReal && !absolute.startsWith(rootReal + sep2)) {
9817
+ if (absolute !== rootReal && !absolute.startsWith(rootReal + sep3)) {
9367
9818
  return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: absolute };
9368
9819
  }
9369
9820
  return { ok: false, status: 404, error: "Not found" };
@@ -9374,7 +9825,7 @@ function resolveUnderRoot(raw, rootAbs, rootLabel) {
9374
9825
  error: err instanceof Error ? err.message : String(err)
9375
9826
  };
9376
9827
  }
9377
- if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep2)) {
9828
+ if (resolvedReal !== rootReal && !resolvedReal.startsWith(rootReal + sep3)) {
9378
9829
  return { ok: false, status: 403, error: `Path escapes ${rootLabel}`, resolved: resolvedReal };
9379
9830
  }
9380
9831
  const relPath = relative(rootReal, resolvedReal) || ".";
@@ -9705,7 +10156,7 @@ async function cascadeDeleteDocument(params) {
9705
10156
 
9706
10157
  // app/lib/file-index.ts
9707
10158
  import * as fsp from "fs/promises";
9708
- import { resolve as resolve14, relative as relative2, join as join12, basename as basename3, extname as extname2, sep as sep3 } from "path";
10159
+ import { resolve as resolve16, relative as relative2, join as join14, basename as basename4, extname as extname2, sep as sep4 } from "path";
9709
10160
  import { tmpdir as tmpdir2 } from "os";
9710
10161
  import { execFile as execFile2 } from "child_process";
9711
10162
  import { promisify as promisify2 } from "util";
@@ -9776,7 +10227,7 @@ async function extractPdf(absolute) {
9776
10227
  return stdout.trim();
9777
10228
  }
9778
10229
  async function ocrPdf(absolute) {
9779
- const outPdf = join12(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
10230
+ const outPdf = join14(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
9780
10231
  try {
9781
10232
  await execFileAsync2(
9782
10233
  "ocrmypdf",
@@ -9832,13 +10283,13 @@ async function extractFileContent(absolute) {
9832
10283
  }
9833
10284
  }
9834
10285
  async function readDisplayName(absolute) {
9835
- const dir = absolute.slice(0, absolute.length - basename3(absolute).length);
9836
- const base = basename3(absolute);
10286
+ const dir = absolute.slice(0, absolute.length - basename4(absolute).length);
10287
+ const base = basename4(absolute);
9837
10288
  const dot = base.lastIndexOf(".");
9838
10289
  const stem = dot === -1 ? base : base.slice(0, dot);
9839
10290
  if (base === `${stem}.meta.json`) return null;
9840
10291
  try {
9841
- const raw = await fsp.readFile(join12(dir, `${stem}.meta.json`), "utf-8");
10292
+ const raw = await fsp.readFile(join14(dir, `${stem}.meta.json`), "utf-8");
9842
10293
  const meta = JSON.parse(raw);
9843
10294
  const dn = meta.displayName ?? meta.filename;
9844
10295
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -9858,7 +10309,7 @@ async function walkSubtree(root, dataRoot, out) {
9858
10309
  let clean = true;
9859
10310
  for (const entry of entries) {
9860
10311
  if (entry.isSymbolicLink()) continue;
9861
- const abs = join12(root, entry.name);
10312
+ const abs = join14(root, entry.name);
9862
10313
  if (entry.isDirectory()) {
9863
10314
  const sub = await walkSubtree(abs, dataRoot, out);
9864
10315
  if (!sub.clean) clean = false;
@@ -9867,7 +10318,7 @@ async function walkSubtree(root, dataRoot, out) {
9867
10318
  const st = await fsp.stat(abs);
9868
10319
  out.push({
9869
10320
  absolute: abs,
9870
- relativePath: relative2(dataRoot, abs).split(sep3).join("/"),
10321
+ relativePath: relative2(dataRoot, abs).split(sep4).join("/"),
9871
10322
  sizeBytes: st.size,
9872
10323
  modifiedAt: st.mtime.toISOString()
9873
10324
  });
@@ -9970,7 +10421,7 @@ async function cascadeTrashLinkedKnowledgeDocs(session, accountId, relativePaths
9970
10421
  return { kds, sections, chunks };
9971
10422
  }
9972
10423
  async function buildArtifact(accountId, wf, embed2) {
9973
- const name = basename3(wf.absolute);
10424
+ const name = basename4(wf.absolute);
9974
10425
  const { content, route } = await extractFileContent(wf.absolute);
9975
10426
  const displayName = await readDisplayName(wf.absolute);
9976
10427
  const embedInput = `${name}
@@ -10013,8 +10464,8 @@ async function reconcileFileIndex(accountId, opts) {
10013
10464
  return withSession(opts, async (session) => {
10014
10465
  const walked = [];
10015
10466
  const subtreeRoots = [
10016
- resolve14(dataRoot, "uploads", accountId),
10017
- resolve14(dataRoot, "accounts", accountId)
10467
+ resolve16(dataRoot, "uploads", accountId),
10468
+ resolve16(dataRoot, "accounts", accountId)
10018
10469
  ];
10019
10470
  let clean = true;
10020
10471
  for (const root of subtreeRoots) {
@@ -10095,7 +10546,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
10095
10546
  async function indexFile(accountId, relativePath, opts) {
10096
10547
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
10097
10548
  const embed2 = opts?.embed ?? embed;
10098
- const absolute = resolve14(dataRoot, relativePath);
10549
+ const absolute = resolve16(dataRoot, relativePath);
10099
10550
  await withSession(opts, async (session) => {
10100
10551
  const st = await fsp.stat(absolute);
10101
10552
  const wf = {
@@ -10129,7 +10580,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
10129
10580
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10130
10581
  async function readMeta(absDir, baseName) {
10131
10582
  try {
10132
- const raw = await readFile4(join13(absDir, `${baseName}.meta.json`), "utf8");
10583
+ const raw = await readFile4(join15(absDir, `${baseName}.meta.json`), "utf8");
10133
10584
  const parsed = JSON.parse(raw);
10134
10585
  if (typeof parsed?.filename === "string") {
10135
10586
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -10140,7 +10591,7 @@ async function readMeta(absDir, baseName) {
10140
10591
  }
10141
10592
  async function readAccountNames() {
10142
10593
  const map = /* @__PURE__ */ new Map();
10143
- const accountsDir = resolve15(DATA_ROOT, "accounts");
10594
+ const accountsDir = resolve17(DATA_ROOT, "accounts");
10144
10595
  let names;
10145
10596
  try {
10146
10597
  names = await readdir3(accountsDir);
@@ -10149,7 +10600,7 @@ async function readAccountNames() {
10149
10600
  }
10150
10601
  for (const name of names) {
10151
10602
  if (!UUID_RE3.test(name)) continue;
10152
- const configPath2 = resolve15(accountsDir, name, "account.json");
10603
+ const configPath2 = resolve17(accountsDir, name, "account.json");
10153
10604
  try {
10154
10605
  const raw = await readFile4(configPath2, "utf8");
10155
10606
  const parsed = JSON.parse(raw);
@@ -10167,7 +10618,7 @@ async function readAccountNames() {
10167
10618
  }
10168
10619
  async function enrich(absolute, entry, accountNames) {
10169
10620
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
10170
- const meta = await readMeta(join13(absolute, entry.name), entry.name);
10621
+ const meta = await readMeta(join15(absolute, entry.name), entry.name);
10171
10622
  if (meta?.filename) {
10172
10623
  entry.displayName = meta.filename;
10173
10624
  entry.mimeType = meta.mimeType;
@@ -10227,8 +10678,8 @@ async function knowledgeDocOwnedByAccount(accountId, attachmentId) {
10227
10678
  await session.close();
10228
10679
  }
10229
10680
  }
10230
- var app15 = new Hono();
10231
- app15.get("/", requireAdminSession, async (c) => {
10681
+ var app17 = new Hono();
10682
+ app17.get("/", requireAdminSession, async (c) => {
10232
10683
  const cacheKey = c.var.cacheKey;
10233
10684
  const accountId = getAccountIdForSession(cacheKey);
10234
10685
  if (!accountId) {
@@ -10265,7 +10716,7 @@ app15.get("/", requireAdminSession, async (c) => {
10265
10716
  continue;
10266
10717
  }
10267
10718
  try {
10268
- const entryPath = join13(absolute, name);
10719
+ const entryPath = join15(absolute, name);
10269
10720
  const s = await stat4(entryPath);
10270
10721
  entries.push({
10271
10722
  name,
@@ -10294,7 +10745,7 @@ app15.get("/", requireAdminSession, async (c) => {
10294
10745
  return c.json({ error: message }, 500);
10295
10746
  }
10296
10747
  });
10297
- app15.get("/download", requireAdminSession, async (c) => {
10748
+ app17.get("/download", requireAdminSession, async (c) => {
10298
10749
  const cacheKey = c.var.cacheKey;
10299
10750
  const accountId = getAccountIdForSession(cacheKey);
10300
10751
  if (!accountId) {
@@ -10331,7 +10782,7 @@ app15.get("/download", requireAdminSession, async (c) => {
10331
10782
  if (!info.isFile()) {
10332
10783
  return c.json({ error: "Path is not a file" }, 400);
10333
10784
  }
10334
- const filename = basename4(absolute);
10785
+ const filename = basename5(absolute);
10335
10786
  const mimeType = detectMimeType(absolute);
10336
10787
  const nodeStream = createReadStream2(absolute);
10337
10788
  const webStream = Readable2.toWeb(nodeStream);
@@ -10358,7 +10809,7 @@ app15.get("/download", requireAdminSession, async (c) => {
10358
10809
  return c.json({ error: message }, 500);
10359
10810
  }
10360
10811
  });
10361
- app15.post("/upload", requireAdminSession, async (c) => {
10812
+ app17.post("/upload", requireAdminSession, async (c) => {
10362
10813
  const cacheKey = c.var.cacheKey;
10363
10814
  const accountId = getAccountIdForSession(cacheKey);
10364
10815
  if (!accountId) {
@@ -10388,15 +10839,15 @@ app15.post("/upload", requireAdminSession, async (c) => {
10388
10839
  error: `Unsupported file type: "${file.type}". Supported: ${[...SUPPORTED_MIME_TYPES].join(", ")}.`
10389
10840
  }, 422);
10390
10841
  }
10391
- const safeName = basename4(file.name).replace(/[\0/\\]/g, "_");
10842
+ const safeName = basename5(file.name).replace(/[\0/\\]/g, "_");
10392
10843
  const finalName = `${Date.now()}-${safeName}`;
10393
- const destDir = resolve15(DATA_ROOT, "uploads", accountId);
10394
- const destPath = resolve15(destDir, finalName);
10844
+ const destDir = resolve17(DATA_ROOT, "uploads", accountId);
10845
+ const destPath = resolve17(destDir, finalName);
10395
10846
  try {
10396
10847
  await mkdir3(destDir, { recursive: true });
10397
10848
  const dataRootReal = realpathSync4(DATA_ROOT);
10398
10849
  const destDirReal = realpathSync4(destDir);
10399
- if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep4)) {
10850
+ if (destDirReal !== dataRootReal && !destDirReal.startsWith(dataRootReal + sep5)) {
10400
10851
  console.error(`[data] path-traversal-blocked requested="uploads/${accountId}" resolved="${destDirReal}"`);
10401
10852
  return c.json({ error: "Upload destination escapes DATA_ROOT" }, 403);
10402
10853
  }
@@ -10419,7 +10870,7 @@ app15.post("/upload", requireAdminSession, async (c) => {
10419
10870
  mimeType: file.type
10420
10871
  });
10421
10872
  });
10422
- app15.delete("/", requireAdminSession, async (c) => {
10873
+ app17.delete("/", requireAdminSession, async (c) => {
10423
10874
  const cacheKey = c.var.cacheKey;
10424
10875
  const accountId = getAccountIdForSession(cacheKey);
10425
10876
  if (!accountId) {
@@ -10440,7 +10891,7 @@ app15.delete("/", requireAdminSession, async (c) => {
10440
10891
  console.error(`[data] account-scope-blocked endpoint="DELETE /api/admin/files" path="${relPath}" account=${accountId.slice(0, 8)}\u2026`);
10441
10892
  return c.json({ error: "Not found" }, 404);
10442
10893
  }
10443
- const base = basename4(absolute);
10894
+ const base = basename5(absolute);
10444
10895
  const segments = relPath.split("/").filter(Boolean);
10445
10896
  if (base === "account.json" || segments.includes(".git")) {
10446
10897
  console.error(`[data] file-delete blocked path="${relPath}" reason="protected"`);
@@ -10456,7 +10907,7 @@ app15.delete("/", requireAdminSession, async (c) => {
10456
10907
  }
10457
10908
  const dot = base.lastIndexOf(".");
10458
10909
  const stem = dot === -1 ? base : base.slice(0, dot);
10459
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join13(dirname3(absolute), `${stem}.meta.json`) : null;
10910
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join15(dirname4(absolute), `${stem}.meta.json`) : null;
10460
10911
  await unlink2(absolute);
10461
10912
  if (sidecarPath) {
10462
10913
  try {
@@ -10495,7 +10946,7 @@ app15.delete("/", requireAdminSession, async (c) => {
10495
10946
  return c.json({ error: message }, 500);
10496
10947
  }
10497
10948
  });
10498
- var files_default = app15;
10949
+ var files_default = app17;
10499
10950
 
10500
10951
  // ../lib/graph-search/src/index.ts
10501
10952
  var import_dist = __toESM(require_dist());
@@ -11260,8 +11711,8 @@ var DEFAULT_LIMIT = 20;
11260
11711
  var MAX_LIMIT = 2e3;
11261
11712
  var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage", "WhatsAppMessage"];
11262
11713
  var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
11263
- var app16 = new Hono();
11264
- app16.get("/", requireAdminSession, async (c) => {
11714
+ var app18 = new Hono();
11715
+ app18.get("/", requireAdminSession, async (c) => {
11265
11716
  const cacheKey = c.var.cacheKey;
11266
11717
  const q = (c.req.query("q") ?? "").trim();
11267
11718
  const rawLimit = c.req.query("limit");
@@ -11397,7 +11848,7 @@ app16.get("/", requireAdminSession, async (c) => {
11397
11848
  await session.close();
11398
11849
  }
11399
11850
  });
11400
- var graph_search_default = app16;
11851
+ var graph_search_default = app18;
11401
11852
 
11402
11853
  // server/routes/admin/graph-subgraph.ts
11403
11854
  import neo4j from "neo4j-driver";
@@ -11475,8 +11926,8 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
11475
11926
  "otpCode",
11476
11927
  "cacheKey"
11477
11928
  ]);
11478
- var app17 = new Hono();
11479
- app17.get("/", requireAdminSession, async (c) => {
11929
+ var app19 = new Hono();
11930
+ app19.get("/", requireAdminSession, async (c) => {
11480
11931
  const cacheKey = c.var.cacheKey;
11481
11932
  const accountId = getAccountIdForSession(cacheKey);
11482
11933
  if (!accountId) {
@@ -12059,12 +12510,12 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
12059
12510
  }
12060
12511
  return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
12061
12512
  }
12062
- var graph_subgraph_default = app17;
12513
+ var graph_subgraph_default = app19;
12063
12514
 
12064
12515
  // server/routes/admin/graph-delete.ts
12065
12516
  var ALLOWED_BY = ["graph-page", "graph-drag-trash", "graph-side-panel-trash"];
12066
- var app18 = new Hono();
12067
- app18.post("/", requireAdminSession, async (c) => {
12517
+ var app20 = new Hono();
12518
+ app20.post("/", requireAdminSession, async (c) => {
12068
12519
  const cacheKey = c.var.cacheKey;
12069
12520
  const accountId = getAccountIdForSession(cacheKey);
12070
12521
  if (!accountId) {
@@ -12227,11 +12678,11 @@ app18.post("/", requireAdminSession, async (c) => {
12227
12678
  }
12228
12679
  }
12229
12680
  });
12230
- var graph_delete_default = app18;
12681
+ var graph_delete_default = app20;
12231
12682
 
12232
12683
  // server/routes/admin/graph-restore.ts
12233
- var app19 = new Hono();
12234
- app19.post("/", requireAdminSession, async (c) => {
12684
+ var app21 = new Hono();
12685
+ app21.post("/", requireAdminSession, async (c) => {
12235
12686
  const cacheKey = c.var.cacheKey;
12236
12687
  const accountId = getAccountIdForSession(cacheKey);
12237
12688
  if (!accountId) {
@@ -12295,11 +12746,11 @@ app19.post("/", requireAdminSession, async (c) => {
12295
12746
  }
12296
12747
  }
12297
12748
  });
12298
- var graph_restore_default = app19;
12749
+ var graph_restore_default = app21;
12299
12750
 
12300
12751
  // server/routes/admin/graph-labels-in-graph.ts
12301
- var app20 = new Hono();
12302
- app20.get("/", requireAdminSession, async (c) => {
12752
+ var app22 = new Hono();
12753
+ app22.get("/", requireAdminSession, async (c) => {
12303
12754
  const cacheKey = c.var.cacheKey;
12304
12755
  const accountId = getAccountIdForSession(cacheKey);
12305
12756
  if (!accountId) {
@@ -12365,11 +12816,11 @@ var LABELS_IN_GRAPH_CYPHER = `
12365
12816
  sum(halfEdges) AS relDegree
12366
12817
  RETURN label, nodeCount, relDegree
12367
12818
  `;
12368
- var graph_labels_in_graph_default = app20;
12819
+ var graph_labels_in_graph_default = app22;
12369
12820
 
12370
12821
  // server/routes/admin/graph-default-view.ts
12371
- var app21 = new Hono();
12372
- app21.get("/", requireAdminSession, async (c) => {
12822
+ var app23 = new Hono();
12823
+ app23.get("/", requireAdminSession, async (c) => {
12373
12824
  const cacheKey = c.var.cacheKey;
12374
12825
  const accountId = getAccountIdForSession(cacheKey);
12375
12826
  const userId = getUserIdForSession(cacheKey);
@@ -12407,7 +12858,7 @@ app21.get("/", requireAdminSession, async (c) => {
12407
12858
  }
12408
12859
  }
12409
12860
  });
12410
- app21.put("/", requireAdminSession, async (c) => {
12861
+ app23.put("/", requireAdminSession, async (c) => {
12411
12862
  const cacheKey = c.var.cacheKey;
12412
12863
  const accountId = getAccountIdForSession(cacheKey);
12413
12864
  const userId = getUserIdForSession(cacheKey);
@@ -12496,20 +12947,20 @@ var WRITE_CYPHER = `
12496
12947
  p.updatedAt = $updatedAt
12497
12948
  RETURN p.labels AS labels
12498
12949
  `;
12499
- var graph_default_view_default = app21;
12950
+ var graph_default_view_default = app23;
12500
12951
 
12501
12952
  // server/routes/admin/sidebar-artefacts.ts
12502
12953
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
12503
- import { resolve as resolve16, relative as relative3, isAbsolute, sep as sep5, basename as basename5 } from "path";
12954
+ import { resolve as resolve18, relative as relative3, isAbsolute, sep as sep6, basename as basename6 } from "path";
12504
12955
  import { existsSync as existsSync17 } from "fs";
12505
12956
  var LIMIT = 50;
12506
12957
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
12507
12958
  function toDataRootRelPath(absPath) {
12508
- if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep5)) return null;
12959
+ if (absPath !== DATA_ROOT && !absPath.startsWith(DATA_ROOT + sep6)) return null;
12509
12960
  return relative3(DATA_ROOT, absPath);
12510
12961
  }
12511
- var app22 = new Hono();
12512
- app22.get("/", requireAdminSession, async (c) => {
12962
+ var app24 = new Hono();
12963
+ app24.get("/", requireAdminSession, async (c) => {
12513
12964
  const cacheKey = c.var.cacheKey;
12514
12965
  const accountId = getAccountIdForSession(cacheKey);
12515
12966
  if (!accountId) {
@@ -12520,7 +12971,7 @@ app22.get("/", requireAdminSession, async (c) => {
12520
12971
  if (accountFiles === null) {
12521
12972
  return c.json({ error: "Failed to load artefacts" }, 500);
12522
12973
  }
12523
- const accountDir = resolve16(ACCOUNTS_DIR, accountId);
12974
+ const accountDir = resolve18(ACCOUNTS_DIR, accountId);
12524
12975
  const agents = await fetchAgentTemplateRows(accountDir);
12525
12976
  const artefacts = [...accountFiles, ...agents].sort(
12526
12977
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -12552,7 +13003,7 @@ async function fetchAccountFileArtefacts(accountId) {
12552
13003
  const modifiedAt = r.get("modifiedAt") ?? "";
12553
13004
  return {
12554
13005
  id: `account-file:${relativePath}`,
12555
- name: displayName ?? basename5(relativePath),
13006
+ name: displayName ?? basename6(relativePath),
12556
13007
  kind: "account-file",
12557
13008
  updatedAt: modifiedAt,
12558
13009
  mimeType,
@@ -12564,371 +13015,127 @@ async function fetchAccountFileArtefacts(accountId) {
12564
13015
  const message = err instanceof Error ? err.message : String(err);
12565
13016
  console.error(`[admin/sidebar-artefacts] account=${accountId} error="${message}"`);
12566
13017
  return null;
12567
- } finally {
12568
- await session.close();
12569
- }
12570
- }
12571
- async function fetchAgentTemplateRows(accountDir) {
12572
- const rows = [];
12573
- for (const filename of ADMIN_AGENT_FILES) {
12574
- const overridePath = resolve16(accountDir, "agents", "admin", filename);
12575
- const bundledPath = resolve16(PLATFORM_ROOT, "templates", "agents", "admin", filename);
12576
- const labelStem = filename.replace(/\.md$/, "");
12577
- const row = await readAgentTemplateRow({
12578
- id: `agent-template:admin:${filename}`,
12579
- displayName: `Admin \xB7 ${labelStem}`,
12580
- logName: `admin/${filename}`,
12581
- overridePath,
12582
- overrideRoot: accountDir,
12583
- bundledPath,
12584
- bundledRoot: PLATFORM_ROOT
12585
- });
12586
- if (row) rows.push(row);
12587
- }
12588
- const overrideDir = resolve16(accountDir, "specialists", "agents");
12589
- const bundledDir = resolve16(PLATFORM_ROOT, "templates", "specialists", "agents");
12590
- const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
12591
- for (const filename of specialistNames) {
12592
- const overridePath = resolve16(overrideDir, filename);
12593
- const bundledPath = resolve16(bundledDir, filename);
12594
- const row = await readAgentTemplateRow({
12595
- id: `agent-template:specialist:${filename}`,
12596
- displayName: filename.replace(/\.md$/, ""),
12597
- logName: `specialist/${filename}`,
12598
- overridePath,
12599
- overrideRoot: accountDir,
12600
- bundledPath,
12601
- bundledRoot: PLATFORM_ROOT
12602
- });
12603
- if (row) rows.push(row);
12604
- }
12605
- return rows;
12606
- }
12607
- async function unionSpecialistFilenames(overrideDir, bundledDir) {
12608
- const names = /* @__PURE__ */ new Set();
12609
- for (const dir of [overrideDir, bundledDir]) {
12610
- if (!existsSync17(dir)) continue;
12611
- try {
12612
- const entries = await readdir4(dir);
12613
- for (const entry of entries) {
12614
- if (entry.endsWith(".md")) names.add(entry);
12615
- }
12616
- } catch (err) {
12617
- const message = err instanceof Error ? err.message : String(err);
12618
- console.error(`[admin/sidebar-artefacts] specialists-read-failed dir=${dir} error="${message}"`);
12619
- }
12620
- }
12621
- return [...names].sort();
12622
- }
12623
- async function readAgentTemplateRow(inp) {
12624
- let chosenPath = null;
12625
- if (existsSync17(inp.overridePath)) {
12626
- try {
12627
- validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
12628
- chosenPath = inp.overridePath;
12629
- } catch (err) {
12630
- const message = err instanceof Error ? err.message : String(err);
12631
- console.error(
12632
- `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="${message}"`
12633
- );
12634
- return null;
12635
- }
12636
- } else if (existsSync17(inp.bundledPath)) {
12637
- if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
12638
- console.error(
12639
- `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
12640
- );
12641
- return null;
12642
- }
12643
- chosenPath = inp.bundledPath;
12644
- }
12645
- if (!chosenPath) return null;
12646
- try {
12647
- const st = await stat5(chosenPath);
12648
- const dlPath = toDataRootRelPath(chosenPath);
12649
- return {
12650
- id: inp.id,
12651
- name: inp.displayName,
12652
- kind: "agent-template",
12653
- updatedAt: st.mtime.toISOString(),
12654
- mimeType: "text/markdown",
12655
- // Override paths live under <accountDir> (inside DATA_ROOT) and are
12656
- // downloadable; bundled-fallback templates live under PLATFORM_ROOT
12657
- // (outside DATA_ROOT) → null, so the client shows "not downloadable".
12658
- // Agent templates only ever resolve under DATA_ROOT, so the download
12659
- // root is `data` whenever the path is non-null.
12660
- downloadPath: dlPath,
12661
- downloadRoot: dlPath ? "data" : null
12662
- };
12663
- } catch (err) {
12664
- const message = err instanceof Error ? err.message : String(err);
12665
- console.error(
12666
- `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="${message}"`
12667
- );
12668
- return null;
12669
- }
12670
- }
12671
- function isWithin(target, root) {
12672
- const rel = relative3(root, target);
12673
- return !rel.startsWith("..") && !isAbsolute(rel);
12674
- }
12675
- var sidebar_artefacts_default = app22;
12676
-
12677
- // server/routes/admin/sidebar-sessions.ts
12678
- import { readdirSync as readdirSync9, readFileSync as readFileSync15, statSync as statSync7 } from "fs";
12679
- import { join as join14, resolve as resolve17 } from "path";
12680
- var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
12681
- var PID_FILE_RE = /^([0-9]+)\.json$/;
12682
- var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
12683
- var PUBLIC_ROLE = "public";
12684
- var WEBCHAT_CHANNEL = "webchat";
12685
- var app23 = new Hono();
12686
- function claudeConfigDir() {
12687
- return process.env.CLAUDE_CONFIG_DIR ?? null;
12688
- }
12689
- function enumerateJsonls(projectsRoot) {
12690
- const out = [];
12691
- let slugs;
12692
- try {
12693
- slugs = readdirSync9(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
12694
- } catch (err) {
12695
- if (err.code === "ENOENT") return out;
12696
- throw err;
12697
- }
12698
- for (const slug of slugs) {
12699
- const slugDir = join14(projectsRoot, slug);
12700
- let entries;
12701
- try {
12702
- entries = readdirSync9(slugDir, { withFileTypes: true });
12703
- } catch (err) {
12704
- const code = err.code ?? "unknown";
12705
- console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
12706
- continue;
12707
- }
12708
- for (const entry of entries) {
12709
- if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
12710
- out.push({ path: join14(slugDir, entry.name), isSubagent: false });
12711
- } else if (entry.isDirectory() && entry.name === "subagents") {
12712
- const subDir = join14(slugDir, entry.name);
12713
- let subEntries;
12714
- try {
12715
- subEntries = readdirSync9(subDir, { withFileTypes: true });
12716
- } catch (err) {
12717
- const code = err.code ?? "unknown";
12718
- console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
12719
- continue;
12720
- }
12721
- for (const sub of subEntries) {
12722
- if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
12723
- out.push({ path: join14(subDir, sub.name), isSubagent: true });
12724
- }
12725
- }
12726
- }
12727
- }
12728
- }
12729
- return out;
12730
- }
12731
- function sessionIdToPidMap(configDir2) {
12732
- const out = /* @__PURE__ */ new Map();
12733
- const sessionsDir = join14(configDir2, "sessions");
12734
- let entries;
12735
- try {
12736
- entries = readdirSync9(sessionsDir, { withFileTypes: true });
12737
- } catch {
12738
- return out;
12739
- }
12740
- for (const entry of entries) {
12741
- if (!entry.isFile()) continue;
12742
- const m = entry.name.match(PID_FILE_RE);
12743
- if (!m) continue;
12744
- const pid = Number(m[1]);
12745
- if (!Number.isFinite(pid) || pid <= 0) continue;
12746
- let body;
12747
- try {
12748
- body = readFileSync15(join14(sessionsDir, entry.name), "utf8");
12749
- } catch {
12750
- continue;
12751
- }
12752
- let parsed;
12753
- try {
12754
- parsed = JSON.parse(body);
12755
- } catch {
12756
- continue;
12757
- }
12758
- if (!parsed || typeof parsed !== "object") continue;
12759
- const sid = parsed.sessionId;
12760
- if (typeof sid === "string" && sid.length > 0) out.set(sid, pid);
12761
- }
12762
- return out;
12763
- }
12764
- function loadUserTitles(accountDir) {
12765
- const out = /* @__PURE__ */ new Map();
12766
- if (!accountDir) return out;
12767
- const path2 = join14(accountDir, "session-titles.json");
12768
- let raw;
12769
- try {
12770
- raw = readFileSync15(path2, "utf8");
12771
- } catch {
12772
- return out;
12773
- }
12774
- let parsed;
12775
- try {
12776
- parsed = JSON.parse(raw);
12777
- } catch {
12778
- return out;
12779
- }
12780
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return out;
12781
- for (const [sessionId, value] of Object.entries(parsed)) {
12782
- if (!sessionId) continue;
12783
- if (!value || typeof value !== "object") continue;
12784
- const v = value;
12785
- if (typeof v.title !== "string") continue;
12786
- const trimmed = v.title.trim();
12787
- if (!trimmed) continue;
12788
- out.set(sessionId, trimmed);
13018
+ } finally {
13019
+ await session.close();
12789
13020
  }
12790
- return out;
12791
13021
  }
12792
- function readSidecarMeta(metaPath) {
12793
- let raw;
12794
- try {
12795
- raw = readFileSync15(metaPath, "utf8");
12796
- } catch {
12797
- return { bridgeIds: [], role: null, channel: null };
13022
+ async function fetchAgentTemplateRows(accountDir) {
13023
+ const rows = [];
13024
+ for (const filename of ADMIN_AGENT_FILES) {
13025
+ const overridePath = resolve18(accountDir, "agents", "admin", filename);
13026
+ const bundledPath = resolve18(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13027
+ const labelStem = filename.replace(/\.md$/, "");
13028
+ const row = await readAgentTemplateRow({
13029
+ id: `agent-template:admin:${filename}`,
13030
+ displayName: `Admin \xB7 ${labelStem}`,
13031
+ logName: `admin/${filename}`,
13032
+ overridePath,
13033
+ overrideRoot: accountDir,
13034
+ bundledPath,
13035
+ bundledRoot: PLATFORM_ROOT
13036
+ });
13037
+ if (row) rows.push(row);
12798
13038
  }
12799
- let parsed;
12800
- try {
12801
- parsed = JSON.parse(raw);
12802
- } catch {
12803
- return { bridgeIds: [], role: null, channel: null };
13039
+ const overrideDir = resolve18(accountDir, "specialists", "agents");
13040
+ const bundledDir = resolve18(PLATFORM_ROOT, "templates", "specialists", "agents");
13041
+ const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
13042
+ for (const filename of specialistNames) {
13043
+ const overridePath = resolve18(overrideDir, filename);
13044
+ const bundledPath = resolve18(bundledDir, filename);
13045
+ const row = await readAgentTemplateRow({
13046
+ id: `agent-template:specialist:${filename}`,
13047
+ displayName: filename.replace(/\.md$/, ""),
13048
+ logName: `specialist/${filename}`,
13049
+ overridePath,
13050
+ overrideRoot: accountDir,
13051
+ bundledPath,
13052
+ bundledRoot: PLATFORM_ROOT
13053
+ });
13054
+ if (row) rows.push(row);
12804
13055
  }
12805
- if (!parsed || typeof parsed !== "object") return { bridgeIds: [], role: null, channel: null };
12806
- const r = parsed;
12807
- const bridgeIds = Array.isArray(r.bridgeIds) ? r.bridgeIds.filter((b) => typeof b === "string" && b.length > 0) : [];
12808
- return {
12809
- bridgeIds,
12810
- role: typeof r.role === "string" ? r.role : null,
12811
- channel: typeof r.channel === "string" ? r.channel : null
12812
- };
12813
- }
12814
- function startsWithCliMarker(s) {
12815
- for (const p of CLI_MARKER_PREFIXES) if (s.startsWith(p)) return true;
12816
- return false;
12817
- }
12818
- function trimToTitle(raw) {
12819
- return raw.trim().replace(/\s+/g, " ");
13056
+ return rows;
12820
13057
  }
12821
- function resolveTitle(body, sessionId, userTitles) {
12822
- const userTitle = userTitles.get(sessionId);
12823
- if (userTitle) return { title: trimToTitle(userTitle), source: "user" };
12824
- let aiTitle = null;
12825
- let firstUserMessage = null;
12826
- for (const line of body.split("\n")) {
12827
- if (!line || line[0] !== "{") continue;
12828
- let parsed;
13058
+ async function unionSpecialistFilenames(overrideDir, bundledDir) {
13059
+ const names = /* @__PURE__ */ new Set();
13060
+ for (const dir of [overrideDir, bundledDir]) {
13061
+ if (!existsSync17(dir)) continue;
12829
13062
  try {
12830
- parsed = JSON.parse(line);
12831
- } catch {
12832
- continue;
12833
- }
12834
- if (!parsed || typeof parsed !== "object") continue;
12835
- const row = parsed;
12836
- if (row.type === "ai-title" && typeof row.aiTitle === "string") {
12837
- const t = row.aiTitle.trim();
12838
- if (t) aiTitle = t;
12839
- continue;
12840
- }
12841
- if (firstUserMessage === null && row.type === "user" && row.message && row.message.role === "user") {
12842
- const content = row.message.content;
12843
- if (typeof content !== "string") continue;
12844
- const trimmed = content.trim();
12845
- if (!trimmed) continue;
12846
- if (startsWithCliMarker(trimmed)) continue;
12847
- firstUserMessage = trimmed;
13063
+ const entries = await readdir4(dir);
13064
+ for (const entry of entries) {
13065
+ if (entry.endsWith(".md")) names.add(entry);
13066
+ }
13067
+ } catch (err) {
13068
+ const message = err instanceof Error ? err.message : String(err);
13069
+ console.error(`[admin/sidebar-artefacts] specialists-read-failed dir=${dir} error="${message}"`);
12848
13070
  }
12849
13071
  }
12850
- if (aiTitle) return { title: trimToTitle(aiTitle), source: "ai" };
12851
- if (firstUserMessage) return { title: trimToTitle(firstUserMessage), source: "first-message" };
12852
- return { title: sessionId.slice(0, 8), source: "prefix" };
13072
+ return [...names].sort();
12853
13073
  }
12854
- app23.get("/", requireAdminSession, async (c) => {
12855
- const accountId = process.env.ACCOUNT_ID ?? null;
12856
- const configDir2 = claudeConfigDir();
12857
- if (!configDir2) {
12858
- console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
12859
- return c.json({ sessions: [], accountId });
12860
- }
12861
- const projectsRoot = join14(configDir2, "projects");
12862
- const jsonls = enumerateJsonls(projectsRoot);
12863
- const pidsBySession = sessionIdToPidMap(configDir2);
12864
- const accountDir = accountId ? resolve17(ACCOUNTS_DIR, accountId) : null;
12865
- const userTitles = loadUserTitles(accountDir);
12866
- const rows = [];
12867
- const seenIds = /* @__PURE__ */ new Set();
12868
- let liveCount = 0;
12869
- let subagentCount = 0;
12870
- let nonResumableCount = 0;
12871
- const titleSourceCounts = { user: 0, ai: 0, "first-message": 0, prefix: 0 };
12872
- for (const { path: path2, isSubagent } of jsonls) {
12873
- const lastSlash = path2.lastIndexOf("/");
12874
- const base = path2.slice(lastSlash + 1);
12875
- const projectDir = path2.slice(0, lastSlash);
12876
- const sessionId = base.slice(0, -".jsonl".length);
12877
- if (seenIds.has(sessionId)) {
12878
- console.error(`[admin-sessions-list] duplicate-sessionId sessionId=${sessionId} path=${path2}`);
12879
- continue;
12880
- }
12881
- seenIds.add(sessionId);
12882
- let body;
12883
- let mtimeMs;
13074
+ async function readAgentTemplateRow(inp) {
13075
+ let chosenPath = null;
13076
+ if (existsSync17(inp.overridePath)) {
12884
13077
  try {
12885
- body = readFileSync15(path2, "utf8");
12886
- mtimeMs = statSync7(path2).mtimeMs;
12887
- } catch {
12888
- continue;
13078
+ validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
13079
+ chosenPath = inp.overridePath;
13080
+ } catch (err) {
13081
+ const message = err instanceof Error ? err.message : String(err);
13082
+ console.error(
13083
+ `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="${message}"`
13084
+ );
13085
+ return null;
12889
13086
  }
12890
- const pid = pidsBySession.get(sessionId) ?? null;
12891
- const live = pid !== null;
12892
- const resolved = resolveTitle(body, sessionId, userTitles);
12893
- titleSourceCounts[resolved.source] += 1;
12894
- const metaPath = join14(projectDir, `${sessionId}.meta.json`);
12895
- const { bridgeIds, role, channel } = readSidecarMeta(metaPath);
12896
- const resumable = !(role === PUBLIC_ROLE && channel === WEBCHAT_CHANNEL);
12897
- rows.push({
12898
- sessionId,
12899
- title: resolved.title,
12900
- titleSource: resolved.source,
12901
- startedAt: new Date(mtimeMs).toISOString(),
12902
- live,
12903
- isSubagent,
12904
- pid,
12905
- projectDir,
12906
- bridgeIds,
12907
- resumable
12908
- });
12909
- if (live) liveCount += 1;
12910
- if (isSubagent) subagentCount += 1;
12911
- if (!resumable) nonResumableCount += 1;
13087
+ } else if (existsSync17(inp.bundledPath)) {
13088
+ if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
13089
+ console.error(
13090
+ `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
13091
+ );
13092
+ return null;
13093
+ }
13094
+ chosenPath = inp.bundledPath;
12912
13095
  }
12913
- rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
12914
- console.log(
12915
- `[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} nonResumable=${nonResumableCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} accountId=${accountId ? accountId.slice(0, 8) : "unset"}`
12916
- );
12917
- return c.json({ sessions: rows, accountId });
12918
- });
12919
- var sidebar_sessions_default = app23;
13096
+ if (!chosenPath) return null;
13097
+ try {
13098
+ const st = await stat5(chosenPath);
13099
+ const dlPath = toDataRootRelPath(chosenPath);
13100
+ return {
13101
+ id: inp.id,
13102
+ name: inp.displayName,
13103
+ kind: "agent-template",
13104
+ updatedAt: st.mtime.toISOString(),
13105
+ mimeType: "text/markdown",
13106
+ // Override paths live under <accountDir> (inside DATA_ROOT) and are
13107
+ // downloadable; bundled-fallback templates live under PLATFORM_ROOT
13108
+ // (outside DATA_ROOT) → null, so the client shows "not downloadable".
13109
+ // Agent templates only ever resolve under DATA_ROOT, so the download
13110
+ // root is `data` whenever the path is non-null.
13111
+ downloadPath: dlPath,
13112
+ downloadRoot: dlPath ? "data" : null
13113
+ };
13114
+ } catch (err) {
13115
+ const message = err instanceof Error ? err.message : String(err);
13116
+ console.error(
13117
+ `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="${message}"`
13118
+ );
13119
+ return null;
13120
+ }
13121
+ }
13122
+ function isWithin(target, root) {
13123
+ const rel = relative3(root, target);
13124
+ return !rel.startsWith("..") && !isAbsolute(rel);
13125
+ }
13126
+ var sidebar_artefacts_default = app24;
12920
13127
 
12921
13128
  // server/routes/admin/session-delete.ts
12922
- import { existsSync as existsSync18, readdirSync as readdirSync10, readFileSync as readFileSync16, unlinkSync as unlinkSync2 } from "fs";
12923
- import { join as join15, resolve as resolve18 } from "path";
12924
- var app24 = new Hono();
12925
- var SESSION_ID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13129
+ import { existsSync as existsSync18, readdirSync as readdirSync10, readFileSync as readFileSync17, unlinkSync as unlinkSync2 } from "fs";
13130
+ import { join as join16, resolve as resolve19 } from "path";
13131
+ var app25 = new Hono();
13132
+ var SESSION_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
12926
13133
  var PID_FILE_RE2 = /^([0-9]+)\.json$/;
12927
13134
  var SIGTERM_WAIT_MS = 2e3;
12928
13135
  var SIGKILL_WAIT_MS = 1e3;
12929
13136
  var POLL_INTERVAL_MS = 50;
12930
13137
  function findPidForSession(configDir2, sessionId) {
12931
- const sessionsDir = join15(configDir2, "sessions");
13138
+ const sessionsDir = join16(configDir2, "sessions");
12932
13139
  let entries;
12933
13140
  try {
12934
13141
  entries = readdirSync10(sessionsDir, { withFileTypes: true });
@@ -12943,7 +13150,7 @@ function findPidForSession(configDir2, sessionId) {
12943
13150
  if (!Number.isFinite(pid) || pid <= 0) continue;
12944
13151
  let body;
12945
13152
  try {
12946
- body = readFileSync16(join15(sessionsDir, entry.name), "utf8");
13153
+ body = readFileSync17(join16(sessionsDir, entry.name), "utf8");
12947
13154
  } catch {
12948
13155
  continue;
12949
13156
  }
@@ -12969,7 +13176,7 @@ function isPidAlive(pid) {
12969
13176
  }
12970
13177
  }
12971
13178
  function sleep2(ms) {
12972
- return new Promise((resolve27) => setTimeout(resolve27, ms));
13179
+ return new Promise((resolve28) => setTimeout(resolve28, ms));
12973
13180
  }
12974
13181
  function sendSignal(pid, signal) {
12975
13182
  try {
@@ -13018,7 +13225,7 @@ async function killAndWait(pid) {
13018
13225
  exited: false
13019
13226
  };
13020
13227
  }
13021
- app24.post("/", requireAdminSession, async (c) => {
13228
+ app25.post("/", requireAdminSession, async (c) => {
13022
13229
  let body;
13023
13230
  try {
13024
13231
  body = await c.req.json();
@@ -13027,7 +13234,7 @@ app24.post("/", requireAdminSession, async (c) => {
13027
13234
  }
13028
13235
  const sessionId = typeof body.sessionId === "string" ? body.sessionId : "";
13029
13236
  const projectDir = typeof body.projectDir === "string" ? body.projectDir : "";
13030
- if (!SESSION_ID_RE2.test(sessionId)) {
13237
+ if (!SESSION_ID_RE3.test(sessionId)) {
13031
13238
  return c.json({ error: "sessionId must be a v4 UUID" }, 400);
13032
13239
  }
13033
13240
  if (!projectDir) {
@@ -13037,14 +13244,14 @@ app24.post("/", requireAdminSession, async (c) => {
13037
13244
  if (!configDir2) {
13038
13245
  return c.json({ error: "CLAUDE_CONFIG_DIR not set" }, 500);
13039
13246
  }
13040
- const projectsRoot = resolve18(join15(configDir2, "projects")) + "/";
13041
- const resolvedProject = resolve18(projectDir) + "/";
13247
+ const projectsRoot = resolve19(join16(configDir2, "projects")) + "/";
13248
+ const resolvedProject = resolve19(projectDir) + "/";
13042
13249
  if (!resolvedProject.startsWith(projectsRoot)) {
13043
13250
  console.error(`[sessions-delete] reject reason=projectDir-outside-tree projectDir=${projectDir}`);
13044
13251
  return c.json({ error: "projectDir is not under CLAUDE_CONFIG_DIR/projects/" }, 400);
13045
13252
  }
13046
- const jsonlPath = join15(projectDir, `${sessionId}.jsonl`);
13047
- const sidecarPath = join15(projectDir, `${sessionId}.meta.json`);
13253
+ const jsonlPath = join16(projectDir, `${sessionId}.jsonl`);
13254
+ const sidecarPath = join16(projectDir, `${sessionId}.meta.json`);
13048
13255
  const pid = findPidForSession(configDir2, sessionId);
13049
13256
  let pidKilled = "absent";
13050
13257
  let waitForExitMs = 0;
@@ -13084,7 +13291,7 @@ app24.post("/", requireAdminSession, async (c) => {
13084
13291
  }
13085
13292
  if (pid !== null) {
13086
13293
  try {
13087
- const pidFile = join15(configDir2, "sessions", `${pid}.json`);
13294
+ const pidFile = join16(configDir2, "sessions", `${pid}.json`);
13088
13295
  if (existsSync18(pidFile)) unlinkSync2(pidFile);
13089
13296
  } catch {
13090
13297
  }
@@ -13101,16 +13308,16 @@ app24.post("/", requireAdminSession, async (c) => {
13101
13308
  );
13102
13309
  return c.json({ deleted, pidKilled, jsonlPath, waitForExitMs, escalatedToSIGKILL });
13103
13310
  });
13104
- var session_delete_default = app24;
13311
+ var session_delete_default = app25;
13105
13312
 
13106
13313
  // server/routes/admin/session-rc-spawn.ts
13107
- var app25 = new Hono();
13314
+ var app26 = new Hono();
13108
13315
  function managerBase4() {
13109
13316
  const port2 = process.env.CLAUDE_SESSION_MANAGER_PORT;
13110
13317
  if (!port2) throw new Error("CLAUDE_SESSION_MANAGER_PORT is not set");
13111
13318
  return `http://127.0.0.1:${port2}`;
13112
13319
  }
13113
- app25.post("/", requireAdminSession, async (c) => {
13320
+ app26.post("/", requireAdminSession, async (c) => {
13114
13321
  let body;
13115
13322
  try {
13116
13323
  body = await c.req.json();
@@ -13144,7 +13351,7 @@ app25.post("/", requireAdminSession, async (c) => {
13144
13351
  }
13145
13352
  return c.json(parsed ?? {});
13146
13353
  });
13147
- var session_rc_spawn_default = app25;
13354
+ var session_rc_spawn_default = app26;
13148
13355
 
13149
13356
  // server/routes/admin/system-stats.ts
13150
13357
  import { readFile as readFile5 } from "fs/promises";
@@ -13241,8 +13448,8 @@ async function sample() {
13241
13448
  if (process.platform === "linux") return sampleLinux();
13242
13449
  return sampleOsFallback();
13243
13450
  }
13244
- var app26 = new Hono();
13245
- app26.get("/", async (c) => {
13451
+ var app27 = new Hono();
13452
+ app27.get("/", async (c) => {
13246
13453
  const started = Date.now();
13247
13454
  if (!inflight) {
13248
13455
  inflight = sample().finally(() => {
@@ -13265,27 +13472,27 @@ app26.get("/", async (c) => {
13265
13472
  return c.json({ degraded: true, reason, sampledAtMs: Date.now() });
13266
13473
  }
13267
13474
  });
13268
- var system_stats_default = app26;
13475
+ var system_stats_default = app27;
13269
13476
 
13270
13477
  // server/routes/admin/health.ts
13271
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
13272
- import { resolve as resolve19, join as join16 } from "path";
13273
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve19(process.cwd(), "..");
13478
+ import { existsSync as existsSync19, readFileSync as readFileSync18 } from "fs";
13479
+ import { resolve as resolve20, join as join17 } from "path";
13480
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
13274
13481
  var brandHostname = "maxy";
13275
- var brandJsonPath = join16(PLATFORM_ROOT6, "config", "brand.json");
13482
+ var brandJsonPath = join17(PLATFORM_ROOT6, "config", "brand.json");
13276
13483
  if (existsSync19(brandJsonPath)) {
13277
13484
  try {
13278
- const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
13485
+ const brand = JSON.parse(readFileSync18(brandJsonPath, "utf-8"));
13279
13486
  if (brand.hostname) brandHostname = brand.hostname;
13280
13487
  } catch {
13281
13488
  }
13282
13489
  }
13283
- var VERSION_FILE = resolve19(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
13490
+ var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
13284
13491
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
13285
13492
  var PROBE_TIMEOUT_MS = 1e3;
13286
13493
  function readVersion() {
13287
13494
  if (!existsSync19(VERSION_FILE)) return "unknown";
13288
- return readFileSync17(VERSION_FILE, "utf-8").trim() || "unknown";
13495
+ return readFileSync18(VERSION_FILE, "utf-8").trim() || "unknown";
13289
13496
  }
13290
13497
  async function probeConversationDb() {
13291
13498
  let session;
@@ -13310,8 +13517,8 @@ async function probeConversationDb() {
13310
13517
  });
13311
13518
  }
13312
13519
  }
13313
- var app27 = new Hono();
13314
- app27.get("/", async (c) => {
13520
+ var app28 = new Hono();
13521
+ app28.get("/", async (c) => {
13315
13522
  const version = readVersion();
13316
13523
  const probe = await probeConversationDb();
13317
13524
  const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
@@ -13333,7 +13540,7 @@ app27.get("/", async (c) => {
13333
13540
  uptimeMs
13334
13541
  });
13335
13542
  });
13336
- var health_default2 = app27;
13543
+ var health_default2 = app28;
13337
13544
 
13338
13545
  // server/routes/admin/linkedin-ingest.ts
13339
13546
  import { randomUUID as randomUUID9 } from "crypto";
@@ -13435,8 +13642,8 @@ function buildInitialMessage(env) {
13435
13642
  }
13436
13643
  return header;
13437
13644
  }
13438
- var app28 = new Hono();
13439
- app28.post("/", requireAdminSession, async (c) => {
13645
+ var app29 = new Hono();
13646
+ app29.post("/", requireAdminSession, async (c) => {
13440
13647
  let body;
13441
13648
  try {
13442
13649
  body = await c.req.json();
@@ -13481,7 +13688,7 @@ app28.post("/", requireAdminSession, async (c) => {
13481
13688
  );
13482
13689
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
13483
13690
  });
13484
- var linkedin_ingest_default = app28;
13691
+ var linkedin_ingest_default = app29;
13485
13692
 
13486
13693
  // server/routes/admin/post-turn-context.ts
13487
13694
  import neo4j2 from "neo4j-driver";
@@ -13523,8 +13730,8 @@ function pruneProperties(raw) {
13523
13730
  }
13524
13731
  return out;
13525
13732
  }
13526
- var app29 = new Hono();
13527
- app29.get("/", async (c) => {
13733
+ var app30 = new Hono();
13734
+ app30.get("/", async (c) => {
13528
13735
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13529
13736
  if (!isLoopbackAddr2(remoteAddr)) {
13530
13737
  console.error(`${TAG24} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -13584,7 +13791,7 @@ app29.get("/", async (c) => {
13584
13791
  await session.close();
13585
13792
  }
13586
13793
  });
13587
- var post_turn_context_default = app29;
13794
+ var post_turn_context_default = app30;
13588
13795
 
13589
13796
  // server/routes/admin/public-session-context.ts
13590
13797
  import neo4j3 from "neo4j-driver";
@@ -13626,8 +13833,8 @@ function pruneProperties2(raw) {
13626
13833
  }
13627
13834
  return out;
13628
13835
  }
13629
- var app30 = new Hono();
13630
- app30.get("/", async (c) => {
13836
+ var app31 = new Hono();
13837
+ app31.get("/", async (c) => {
13631
13838
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13632
13839
  if (!isLoopbackAddr3(remoteAddr)) {
13633
13840
  console.error(`${TAG25} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -13686,15 +13893,15 @@ app30.get("/", async (c) => {
13686
13893
  await session.close();
13687
13894
  }
13688
13895
  });
13689
- var public_session_context_default = app30;
13896
+ var public_session_context_default = app31;
13690
13897
 
13691
13898
  // server/routes/admin/public-session-exit.ts
13692
13899
  var TAG26 = "[public-session-exit-route]";
13693
13900
  function isLoopbackAddr4(addr) {
13694
13901
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
13695
13902
  }
13696
- var app31 = new Hono();
13697
- app31.post("/", async (c) => {
13903
+ var app32 = new Hono();
13904
+ app32.post("/", async (c) => {
13698
13905
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13699
13906
  if (!isLoopbackAddr4(remoteAddr)) {
13700
13907
  console.error(`${TAG26} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -13721,15 +13928,15 @@ app31.post("/", async (c) => {
13721
13928
  handlePublicSessionExit(sessionId);
13722
13929
  return c.json({ ok: true });
13723
13930
  });
13724
- var public_session_exit_default = app31;
13931
+ var public_session_exit_default = app32;
13725
13932
 
13726
13933
  // server/routes/admin/access-session-evict.ts
13727
13934
  var TAG27 = "[access-session-evict]";
13728
13935
  function isLoopbackAddr5(addr) {
13729
13936
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
13730
13937
  }
13731
- var app32 = new Hono();
13732
- app32.post("/", async (c) => {
13938
+ var app33 = new Hono();
13939
+ app33.post("/", async (c) => {
13733
13940
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
13734
13941
  if (!isLoopbackAddr5(remoteAddr)) {
13735
13942
  console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
@@ -13757,11 +13964,11 @@ app32.post("/", async (c) => {
13757
13964
  console.log(`${TAG27} grantId=${grantId} dropped=${dropped}`);
13758
13965
  return c.json({ ok: true, dropped });
13759
13966
  });
13760
- var access_session_evict_default = app32;
13967
+ var access_session_evict_default = app33;
13761
13968
 
13762
13969
  // server/routes/admin/browser.ts
13763
- var app33 = new Hono();
13764
- app33.post("/launch", requireAdminSession, async (c) => {
13970
+ var app34 = new Hono();
13971
+ app34.post("/launch", requireAdminSession, async (c) => {
13765
13972
  try {
13766
13973
  const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
13767
13974
  console.error(`[admin/browser/launch] op=request transport=${transport}`);
@@ -13789,52 +13996,52 @@ app33.post("/launch", requireAdminSession, async (c) => {
13789
13996
  );
13790
13997
  }
13791
13998
  });
13792
- var browser_default = app33;
13999
+ var browser_default = app34;
13793
14000
 
13794
14001
  // server/routes/admin/index.ts
13795
- var app34 = new Hono();
13796
- app34.route("/session", session_default);
13797
- app34.route("/logs", logs_default);
13798
- app34.route("/claude-info", claude_info_default);
13799
- app34.route("/attachment", attachment_default);
13800
- app34.route("/agents", agents_default);
13801
- app34.route("/sessions", sessions_default);
13802
- app34.route("/claude-sessions", claude_sessions_default);
13803
- app34.route("/log-ingest", log_ingest_default);
13804
- app34.route("/events", events_default);
13805
- app34.route("/files", files_default);
13806
- app34.route("/graph-search", graph_search_default);
13807
- app34.route("/graph-subgraph", graph_subgraph_default);
13808
- app34.route("/graph-delete", graph_delete_default);
13809
- app34.route("/graph-restore", graph_restore_default);
13810
- app34.route("/graph-labels-in-graph", graph_labels_in_graph_default);
13811
- app34.route("/graph-default-view", graph_default_view_default);
13812
- app34.route("/sidebar-artefacts", sidebar_artefacts_default);
13813
- app34.route("/sidebar-sessions", sidebar_sessions_default);
13814
- app34.route("/session-delete", session_delete_default);
13815
- app34.route("/browser", browser_default);
13816
- app34.route("/session-rc-spawn", session_rc_spawn_default);
13817
- app34.route("/system-stats", system_stats_default);
13818
- app34.route("/health-brand", health_default2);
13819
- app34.route("/linkedin-ingest", linkedin_ingest_default);
13820
- app34.route("/post-turn-context", post_turn_context_default);
13821
- app34.route("/public-session-context", public_session_context_default);
13822
- app34.route("/public-session-exit", public_session_exit_default);
13823
- app34.route("/access-session-evict", access_session_evict_default);
13824
- var admin_default = app34;
14002
+ var app35 = new Hono();
14003
+ app35.route("/session", session_default);
14004
+ app35.route("/logs", logs_default);
14005
+ app35.route("/claude-info", claude_info_default);
14006
+ app35.route("/attachment", attachment_default);
14007
+ app35.route("/agents", agents_default);
14008
+ app35.route("/sessions", sessions_default);
14009
+ app35.route("/claude-sessions", claude_sessions_default);
14010
+ app35.route("/log-ingest", log_ingest_default);
14011
+ app35.route("/events", events_default);
14012
+ app35.route("/files", files_default);
14013
+ app35.route("/graph-search", graph_search_default);
14014
+ app35.route("/graph-subgraph", graph_subgraph_default);
14015
+ app35.route("/graph-delete", graph_delete_default);
14016
+ app35.route("/graph-restore", graph_restore_default);
14017
+ app35.route("/graph-labels-in-graph", graph_labels_in_graph_default);
14018
+ app35.route("/graph-default-view", graph_default_view_default);
14019
+ app35.route("/sidebar-artefacts", sidebar_artefacts_default);
14020
+ app35.route("/sidebar-sessions", sidebar_sessions_default);
14021
+ app35.route("/session-delete", session_delete_default);
14022
+ app35.route("/browser", browser_default);
14023
+ app35.route("/session-rc-spawn", session_rc_spawn_default);
14024
+ app35.route("/system-stats", system_stats_default);
14025
+ app35.route("/health-brand", health_default2);
14026
+ app35.route("/linkedin-ingest", linkedin_ingest_default);
14027
+ app35.route("/post-turn-context", post_turn_context_default);
14028
+ app35.route("/public-session-context", public_session_context_default);
14029
+ app35.route("/public-session-exit", public_session_exit_default);
14030
+ app35.route("/access-session-evict", access_session_evict_default);
14031
+ var admin_default = app35;
13825
14032
 
13826
14033
  // app/lib/access-gate.ts
13827
14034
  import neo4j4 from "neo4j-driver";
13828
- import { readFileSync as readFileSync18 } from "fs";
13829
- import { resolve as resolve20 } from "path";
14035
+ import { readFileSync as readFileSync19 } from "fs";
14036
+ import { resolve as resolve21 } from "path";
13830
14037
  import { randomUUID as randomUUID10 } from "crypto";
13831
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
14038
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
13832
14039
  var driver = null;
13833
14040
  function readPassword() {
13834
14041
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
13835
- const passwordFile = resolve20(PLATFORM_ROOT7, "config/.neo4j-password");
14042
+ const passwordFile = resolve21(PLATFORM_ROOT7, "config/.neo4j-password");
13836
14043
  try {
13837
- return readFileSync18(passwordFile, "utf-8").trim();
14044
+ return readFileSync19(passwordFile, "utf-8").trim();
13838
14045
  } catch {
13839
14046
  throw new Error(
13840
14047
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -14035,8 +14242,8 @@ async function generateNewMagicToken(grantId) {
14035
14242
  var TAG28 = "[access-verify]";
14036
14243
  var MINT_TAG = "[access-session-mint]";
14037
14244
  var COOKIE_NAME = "__access_session";
14038
- var app35 = new Hono();
14039
- app35.post("/", async (c) => {
14245
+ var app36 = new Hono();
14246
+ app36.post("/", async (c) => {
14040
14247
  const ip = c.var.clientIp || "unknown";
14041
14248
  let body;
14042
14249
  try {
@@ -14118,13 +14325,13 @@ app35.post("/", async (c) => {
14118
14325
  displayName: grant.displayName
14119
14326
  });
14120
14327
  });
14121
- var verify_token_default = app35;
14328
+ var verify_token_default = app36;
14122
14329
 
14123
14330
  // app/lib/access-email.ts
14124
14331
  import { spawn as spawn2 } from "child_process";
14125
- import { resolve as resolve21 } from "path";
14126
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
14127
- var SEND_SCRIPT = resolve21(
14332
+ import { resolve as resolve22 } from "path";
14333
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14334
+ var SEND_SCRIPT = resolve22(
14128
14335
  PLATFORM_ROOT8,
14129
14336
  "plugins",
14130
14337
  "email",
@@ -14181,9 +14388,9 @@ async function sendMagicLinkEmail(payload) {
14181
14388
 
14182
14389
  // server/routes/access/request-magic-link.ts
14183
14390
  var TAG29 = "[access-request-link]";
14184
- var app36 = new Hono();
14391
+ var app37 = new Hono();
14185
14392
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
14186
- app36.post("/", async (c) => {
14393
+ app37.post("/", async (c) => {
14187
14394
  let body;
14188
14395
  try {
14189
14396
  body = await c.req.json();
@@ -14257,17 +14464,17 @@ app36.post("/", async (c) => {
14257
14464
  );
14258
14465
  return c.json({ message: VISITOR_MESSAGE }, 200);
14259
14466
  });
14260
- var request_magic_link_default = app36;
14467
+ var request_magic_link_default = app37;
14261
14468
 
14262
14469
  // server/routes/access/index.ts
14263
- var app37 = new Hono();
14264
- app37.route("/verify-token", verify_token_default);
14265
- app37.route("/request-magic-link", request_magic_link_default);
14266
- var access_default = app37;
14470
+ var app38 = new Hono();
14471
+ app38.route("/verify-token", verify_token_default);
14472
+ app38.route("/request-magic-link", request_magic_link_default);
14473
+ var access_default = app38;
14267
14474
 
14268
14475
  // server/routes/sites.ts
14269
- import { existsSync as existsSync20, readFileSync as readFileSync19, realpathSync as realpathSync5, statSync as statSync8 } from "fs";
14270
- import { resolve as resolve22 } from "path";
14476
+ import { existsSync as existsSync20, readFileSync as readFileSync20, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
14477
+ import { resolve as resolve23 } from "path";
14271
14478
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
14272
14479
  var MIME = {
14273
14480
  ".html": "text/html; charset=utf-8",
@@ -14298,8 +14505,8 @@ function getExt(p) {
14298
14505
  if (idx < p.lastIndexOf("/")) return "";
14299
14506
  return p.slice(idx).toLowerCase();
14300
14507
  }
14301
- var app38 = new Hono();
14302
- app38.get("/:rel{.*}", (c) => {
14508
+ var app39 = new Hono();
14509
+ app39.get("/:rel{.*}", (c) => {
14303
14510
  const reqPath = c.req.path;
14304
14511
  const rawRel = c.req.param("rel") ?? "";
14305
14512
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -14324,15 +14531,15 @@ app38.get("/:rel{.*}", (c) => {
14324
14531
  }
14325
14532
  segments.push(seg);
14326
14533
  }
14327
- const rootDir = resolve22(account.accountDir, "sites");
14328
- let filePath = segments.length === 0 ? rootDir : resolve22(rootDir, ...segments);
14534
+ const rootDir = resolve23(account.accountDir, "sites");
14535
+ let filePath = segments.length === 0 ? rootDir : resolve23(rootDir, ...segments);
14329
14536
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
14330
14537
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
14331
14538
  return c.text("Forbidden", 403);
14332
14539
  }
14333
14540
  let stat7;
14334
14541
  try {
14335
- stat7 = existsSync20(filePath) ? statSync8(filePath) : null;
14542
+ stat7 = existsSync20(filePath) ? statSync9(filePath) : null;
14336
14543
  } catch {
14337
14544
  stat7 = null;
14338
14545
  }
@@ -14345,7 +14552,7 @@ app38.get("/:rel{.*}", (c) => {
14345
14552
  return c.redirect(target, 301);
14346
14553
  }
14347
14554
  if (stat7?.isDirectory()) {
14348
- filePath = resolve22(filePath, "index.html");
14555
+ filePath = resolve23(filePath, "index.html");
14349
14556
  }
14350
14557
  if (!filePath.startsWith(rootDir + "/")) {
14351
14558
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
@@ -14370,7 +14577,7 @@ app38.get("/:rel{.*}", (c) => {
14370
14577
  }
14371
14578
  let body;
14372
14579
  try {
14373
- body = readFileSync19(realPath);
14580
+ body = readFileSync20(realPath);
14374
14581
  } catch (err) {
14375
14582
  const code = err?.code;
14376
14583
  if (code === "EISDIR") {
@@ -14402,12 +14609,12 @@ app38.get("/:rel{.*}", (c) => {
14402
14609
  "X-Content-Type-Options": "nosniff"
14403
14610
  });
14404
14611
  });
14405
- var sites_default = app38;
14612
+ var sites_default = app39;
14406
14613
 
14407
14614
  // app/lib/visitor-token.ts
14408
14615
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
14409
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync20, writeFileSync as writeFileSync7 } from "fs";
14410
- import { dirname as dirname4 } from "path";
14616
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync21, writeFileSync as writeFileSync7 } from "fs";
14617
+ import { dirname as dirname5 } from "path";
14411
14618
  var TOKEN_PREFIX = "v1.";
14412
14619
  var SECRET_BYTES = 32;
14413
14620
  var DEFAULT_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -14415,7 +14622,7 @@ var cachedSecret = null;
14415
14622
  function getSecret() {
14416
14623
  if (cachedSecret) return cachedSecret;
14417
14624
  try {
14418
- const hex2 = readFileSync20(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
14625
+ const hex2 = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
14419
14626
  if (hex2.length === SECRET_BYTES * 2) {
14420
14627
  cachedSecret = Buffer.from(hex2, "hex");
14421
14628
  return cachedSecret;
@@ -14424,12 +14631,12 @@ function getSecret() {
14424
14631
  }
14425
14632
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
14426
14633
  try {
14427
- mkdirSync4(dirname4(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
14634
+ mkdirSync4(dirname5(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
14428
14635
  writeFileSync7(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
14429
14636
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
14430
14637
  } catch {
14431
14638
  }
14432
- const hex = readFileSync20(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
14639
+ const hex = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
14433
14640
  cachedSecret = Buffer.from(hex, "hex");
14434
14641
  return cachedSecret;
14435
14642
  }
@@ -14482,8 +14689,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
14482
14689
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
14483
14690
 
14484
14691
  // app/lib/brand-config.ts
14485
- import { existsSync as existsSync21, readFileSync as readFileSync21 } from "fs";
14486
- import { join as join17 } from "path";
14692
+ import { existsSync as existsSync21, readFileSync as readFileSync22 } from "fs";
14693
+ import { join as join18 } from "path";
14487
14694
  var cached2 = null;
14488
14695
  var cachedAttempted = false;
14489
14696
  function readBrandConfig() {
@@ -14491,10 +14698,10 @@ function readBrandConfig() {
14491
14698
  cachedAttempted = true;
14492
14699
  const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
14493
14700
  if (!platformRoot2) return null;
14494
- const brandPath = join17(platformRoot2, "config", "brand.json");
14701
+ const brandPath = join18(platformRoot2, "config", "brand.json");
14495
14702
  if (!existsSync21(brandPath)) return null;
14496
14703
  try {
14497
- cached2 = JSON.parse(readFileSync21(brandPath, "utf-8"));
14704
+ cached2 = JSON.parse(readFileSync22(brandPath, "utf-8"));
14498
14705
  return cached2;
14499
14706
  } catch {
14500
14707
  return null;
@@ -14502,7 +14709,7 @@ function readBrandConfig() {
14502
14709
  }
14503
14710
 
14504
14711
  // server/routes/visitor-consent.ts
14505
- var app39 = new Hono();
14712
+ var app40 = new Hono();
14506
14713
  var CONSENT_COOKIE_NAME = "mxy_consent";
14507
14714
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
14508
14715
  var DEFAULT_CONSENT_COPY = {
@@ -14547,17 +14754,17 @@ function siteSlugFromReferer(referer) {
14547
14754
  return "";
14548
14755
  }
14549
14756
  }
14550
- app39.options("/consent", (c) => {
14757
+ app40.options("/consent", (c) => {
14551
14758
  const origin = getOrigin(c);
14552
14759
  setCorsHeaders(c, origin);
14553
14760
  return c.body(null, 204);
14554
14761
  });
14555
- app39.options("/brand-config", (c) => {
14762
+ app40.options("/brand-config", (c) => {
14556
14763
  const origin = getOrigin(c);
14557
14764
  setCorsHeaders(c, origin);
14558
14765
  return c.body(null, 204);
14559
14766
  });
14560
- app39.post("/consent", async (c) => {
14767
+ app40.post("/consent", async (c) => {
14561
14768
  const origin = getOrigin(c);
14562
14769
  setCorsHeaders(c, origin);
14563
14770
  let raw;
@@ -14597,7 +14804,7 @@ app39.post("/consent", async (c) => {
14597
14804
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
14598
14805
  return c.body(null, 204);
14599
14806
  });
14600
- app39.get("/brand-config", (c) => {
14807
+ app40.get("/brand-config", (c) => {
14601
14808
  const origin = getOrigin(c);
14602
14809
  setCorsHeaders(c, origin);
14603
14810
  const brand = readBrandConfig();
@@ -14607,7 +14814,7 @@ app39.get("/brand-config", (c) => {
14607
14814
  c.header("Cache-Control", "public, max-age=300");
14608
14815
  return c.json({ consent: { copy, palette } });
14609
14816
  });
14610
- var visitor_consent_default = app39;
14817
+ var visitor_consent_default = app40;
14611
14818
 
14612
14819
  // server/routes/listings.ts
14613
14820
  function getCookie(headerValue, name) {
@@ -14628,14 +14835,14 @@ function appendConsentParams(pageUrl, token) {
14628
14835
  const hashIdx = pageUrl.indexOf("#");
14629
14836
  const hash = hashIdx >= 0 ? pageUrl.slice(hashIdx) : "";
14630
14837
  const base = hashIdx >= 0 ? pageUrl.slice(0, hashIdx) : pageUrl;
14631
- const sep7 = base.indexOf("?") >= 0 ? "&" : "?";
14632
- return base + sep7 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
14838
+ const sep8 = base.indexOf("?") >= 0 ? "&" : "?";
14839
+ return base + sep8 + `consent=needed&v=${encodeURIComponent(token)}` + hash;
14633
14840
  }
14634
14841
  }
14635
14842
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
14636
14843
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
14637
- var app40 = new Hono();
14638
- app40.get("/:slug/click", async (c) => {
14844
+ var app41 = new Hono();
14845
+ app41.get("/:slug/click", async (c) => {
14639
14846
  const slug = c.req.param("slug") ?? "";
14640
14847
  const rawSession = c.req.query("session") ?? "";
14641
14848
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -14699,10 +14906,10 @@ app40.get("/:slug/click", async (c) => {
14699
14906
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
14700
14907
  return c.redirect(redirectUrl, 302);
14701
14908
  });
14702
- var listings_default = app40;
14909
+ var listings_default = app41;
14703
14910
 
14704
14911
  // server/routes/visitor-event.ts
14705
- var app41 = new Hono();
14912
+ var app42 = new Hono();
14706
14913
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
14707
14914
  var buckets = /* @__PURE__ */ new Map();
14708
14915
  var RATE_LIMIT = 60;
@@ -14769,12 +14976,12 @@ function originAllowed(origin, allowlist) {
14769
14976
  return false;
14770
14977
  }
14771
14978
  }
14772
- app41.options("/event", (c) => {
14979
+ app42.options("/event", (c) => {
14773
14980
  const origin = getOrigin2(c);
14774
14981
  setCorsHeaders2(c, origin);
14775
14982
  return c.body(null, 204);
14776
14983
  });
14777
- app41.post("/event", async (c) => {
14984
+ app42.post("/event", async (c) => {
14778
14985
  const origin = getOrigin2(c);
14779
14986
  setCorsHeaders2(c, origin);
14780
14987
  const ua = c.req.header("user-agent") ?? "";
@@ -14979,17 +15186,17 @@ async function writeEvent(opts) {
14979
15186
  );
14980
15187
  }
14981
15188
  }
14982
- var visitor_event_default = app41;
15189
+ var visitor_event_default = app42;
14983
15190
 
14984
15191
  // server/routes/session.ts
14985
- import { resolve as resolve23 } from "path";
15192
+ import { resolve as resolve24 } from "path";
14986
15193
  import { existsSync as existsSync22, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
14987
15194
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
14988
15195
  function writeBrandingCache(accountId, agentSlug, branding) {
14989
15196
  try {
14990
- const cacheDir = resolve23(MAXY_DIR, "branding-cache", accountId);
15197
+ const cacheDir = resolve24(MAXY_DIR, "branding-cache", accountId);
14991
15198
  mkdirSync5(cacheDir, { recursive: true });
14992
- writeFileSync8(resolve23(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15199
+ writeFileSync8(resolve24(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
14993
15200
  } catch (err) {
14994
15201
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
14995
15202
  }
@@ -15025,8 +15232,8 @@ function withVisitorCookie(response, visitorId) {
15025
15232
  headers
15026
15233
  });
15027
15234
  }
15028
- var app42 = new Hono();
15029
- app42.post("/", async (c) => {
15235
+ var app43 = new Hono();
15236
+ app43.post("/", async (c) => {
15030
15237
  let body;
15031
15238
  try {
15032
15239
  body = await c.req.json();
@@ -15077,8 +15284,8 @@ app42.post("/", async (c) => {
15077
15284
  }
15078
15285
  let agentConfig = null;
15079
15286
  if (account) {
15080
- const agentDir = resolve23(account.accountDir, "agents", agentSlug);
15081
- if (!existsSync22(agentDir) || !existsSync22(resolve23(agentDir, "config.json"))) {
15287
+ const agentDir = resolve24(account.accountDir, "agents", agentSlug);
15288
+ if (!existsSync22(agentDir) || !existsSync22(resolve24(agentDir, "config.json"))) {
15082
15289
  return c.json({ error: "Agent not found" }, 404);
15083
15290
  }
15084
15291
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -15237,7 +15444,7 @@ app42.post("/", async (c) => {
15237
15444
  newVisitorId
15238
15445
  );
15239
15446
  });
15240
- var session_default2 = app42;
15447
+ var session_default2 = app43;
15241
15448
 
15242
15449
  // app/lib/graph-health.ts
15243
15450
  var import_dist4 = __toESM(require_dist3(), 1);
@@ -15358,13 +15565,13 @@ function startGraphHealthTimer() {
15358
15565
 
15359
15566
  // app/lib/file-watcher.ts
15360
15567
  import * as fsp2 from "fs/promises";
15361
- import { resolve as resolve24, sep as sep6 } from "path";
15568
+ import { resolve as resolve25, sep as sep7 } from "path";
15362
15569
  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;
15363
15570
  var DEFAULT_COALESCE_MS = 500;
15364
15571
  var ROOTS = ["uploads", "accounts"];
15365
15572
  function _routeEvent(rootName, filename) {
15366
15573
  if (!filename) return null;
15367
- const segs = filename.split(sep6).filter(Boolean);
15574
+ const segs = filename.split(sep7).filter(Boolean);
15368
15575
  if (segs.length < 2) return null;
15369
15576
  const accountId = segs[0];
15370
15577
  if (!ACCOUNT_UUID_RE2.test(accountId)) return null;
@@ -15377,7 +15584,7 @@ async function startFileWatcher(opts = {}) {
15377
15584
  const dropFn = opts.drop ?? dropFileIndex;
15378
15585
  for (const r of ROOTS) {
15379
15586
  try {
15380
- await fsp2.mkdir(resolve24(dataRoot, r), { recursive: true });
15587
+ await fsp2.mkdir(resolve25(dataRoot, r), { recursive: true });
15381
15588
  } catch (err) {
15382
15589
  console.error(
15383
15590
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -15398,7 +15605,7 @@ async function startFileWatcher(opts = {}) {
15398
15605
  timers.set(relativePath, t);
15399
15606
  }
15400
15607
  async function runHook(relativePath, accountId) {
15401
- const absolute = resolve24(dataRoot, relativePath);
15608
+ const absolute = resolve25(dataRoot, relativePath);
15402
15609
  let exists = false;
15403
15610
  try {
15404
15611
  const st = await fsp2.stat(absolute);
@@ -15422,7 +15629,7 @@ async function startFileWatcher(opts = {}) {
15422
15629
  }
15423
15630
  }
15424
15631
  async function watchRoot(rootName) {
15425
- const absRoot = resolve24(dataRoot, rootName);
15632
+ const absRoot = resolve25(dataRoot, rootName);
15426
15633
  try {
15427
15634
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
15428
15635
  for await (const event of iter) {
@@ -15732,8 +15939,8 @@ var streamSSE = (c, cb, onError) => {
15732
15939
 
15733
15940
  // app/lib/whatsapp/gateway/routes.ts
15734
15941
  function createWaChannelRoutes(deps) {
15735
- const app44 = new Hono();
15736
- app44.get("/wa-channel/inbound", (c) => {
15942
+ const app45 = new Hono();
15943
+ app45.get("/wa-channel/inbound", (c) => {
15737
15944
  const senderId = c.req.query("senderId");
15738
15945
  if (!senderId) return c.json({ error: "senderId required" }, 400);
15739
15946
  return streamSSE(c, async (stream2) => {
@@ -15751,7 +15958,7 @@ function createWaChannelRoutes(deps) {
15751
15958
  }
15752
15959
  });
15753
15960
  });
15754
- app44.post("/wa-channel/reply", async (c) => {
15961
+ app45.post("/wa-channel/reply", async (c) => {
15755
15962
  const body = await c.req.json().catch(() => null);
15756
15963
  const senderId = body?.senderId;
15757
15964
  const text = body?.text;
@@ -15770,7 +15977,7 @@ function createWaChannelRoutes(deps) {
15770
15977
  console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
15771
15978
  return c.json({ ok: true });
15772
15979
  });
15773
- app44.post("/wa-channel/ready", async (c) => {
15980
+ app45.post("/wa-channel/ready", async (c) => {
15774
15981
  const body = await c.req.json().catch(() => null);
15775
15982
  const senderId = body?.senderId;
15776
15983
  if (typeof senderId !== "string") {
@@ -15779,7 +15986,7 @@ function createWaChannelRoutes(deps) {
15779
15986
  deps.onReady?.(senderId);
15780
15987
  return c.json({ ok: true });
15781
15988
  });
15782
- app44.post("/wa-channel/received", async (c) => {
15989
+ app45.post("/wa-channel/received", async (c) => {
15783
15990
  const body = await c.req.json().catch(() => null);
15784
15991
  const senderId = body?.senderId;
15785
15992
  const waMessageId = body?.waMessageId;
@@ -15789,7 +15996,7 @@ function createWaChannelRoutes(deps) {
15789
15996
  deps.onReceived?.(senderId, waMessageId);
15790
15997
  return c.json({ ok: true });
15791
15998
  });
15792
- return app44;
15999
+ return app45;
15793
16000
  }
15794
16001
 
15795
16002
  // app/lib/whatsapp/gateway/wa-gateway.ts
@@ -15850,13 +16057,22 @@ var WaGateway = class {
15850
16057
  const bytes = Buffer.byteLength(input.text, "utf8");
15851
16058
  const hadSubscriber = this.hub.hasSubscriber(input.senderId);
15852
16059
  const willDeliverNow = this.hub.isReady(input.senderId);
16060
+ const hasFileMedia = !!input.mediaPath && input.mediaType !== "audio";
16061
+ const mediaField = hasFileMedia ? `media=${input.mediaType} mediaPath=${input.mediaPath}` : input.mediaType === "audio" ? "media=audio mediaPath=transcribed" : "media=none";
15853
16062
  this.replies.set(input.senderId, input.reply);
15854
16063
  this.hub.deliver(
15855
- { senderId: input.senderId, text: input.text, waMessageId: `wa-${++this.seq}` },
16064
+ {
16065
+ senderId: input.senderId,
16066
+ text: input.text,
16067
+ waMessageId: `wa-${++this.seq}`,
16068
+ mediaPath: input.mediaPath,
16069
+ mediaType: input.mediaType,
16070
+ mediaMimetype: input.mediaMimetype
16071
+ },
15856
16072
  Date.now()
15857
16073
  );
15858
16074
  console.error(
15859
- `[whatsapp-native] op=inbound senderId=${input.senderId} accountId=${input.accountId} bytes=${bytes} delivery=${willDeliverNow ? "immediate" : "queued"}`
16075
+ `[whatsapp-native] op=inbound senderId=${input.senderId} accountId=${input.accountId} bytes=${bytes} ${mediaField} delivery=${willDeliverNow ? "immediate" : "queued"}`
15860
16076
  );
15861
16077
  if (!hadSubscriber && !this.spawning.has(input.senderId)) {
15862
16078
  this.spawning.add(input.senderId);
@@ -15975,8 +16191,8 @@ function broadcastAdminShutdown(reason) {
15975
16191
 
15976
16192
  // ../lib/entitlement/src/index.ts
15977
16193
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
15978
- import { existsSync as existsSync23, readFileSync as readFileSync22, statSync as statSync9 } from "fs";
15979
- import { resolve as resolve25 } from "path";
16194
+ import { existsSync as existsSync23, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
16195
+ import { resolve as resolve26 } from "path";
15980
16196
 
15981
16197
  // ../lib/entitlement/src/canonicalize.ts
15982
16198
  function canonicalize(value) {
@@ -16011,7 +16227,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
16011
16227
  var GRACE_DAYS = 7;
16012
16228
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
16013
16229
  function pubkeyPath(brand) {
16014
- return resolve25(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
16230
+ return resolve26(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
16015
16231
  }
16016
16232
  var memo = null;
16017
16233
  function memoKey(mtimeMs, account) {
@@ -16023,11 +16239,11 @@ function resolveEntitlement(brand, account) {
16023
16239
  if (brand.commercialMode !== true) {
16024
16240
  return logResolved(implicitTrust(account), null);
16025
16241
  }
16026
- const entitlementPath = resolve25(brand.configDir, "entitlement.json");
16242
+ const entitlementPath = resolve26(brand.configDir, "entitlement.json");
16027
16243
  if (!existsSync23(entitlementPath)) {
16028
16244
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
16029
16245
  }
16030
- const stat7 = statSync9(entitlementPath);
16246
+ const stat7 = statSync10(entitlementPath);
16031
16247
  const key = memoKey(stat7.mtimeMs, account);
16032
16248
  if (memo && memo.key === key) {
16033
16249
  return memo.result;
@@ -16039,7 +16255,7 @@ function resolveEntitlement(brand, account) {
16039
16255
  function verifyAndResolve(brand, entitlementPath, account) {
16040
16256
  let pubkeyPem;
16041
16257
  try {
16042
- pubkeyPem = readFileSync22(pubkeyPath(brand), "utf-8");
16258
+ pubkeyPem = readFileSync23(pubkeyPath(brand), "utf-8");
16043
16259
  } catch (err) {
16044
16260
  return logResolved(anonymousFallback("pubkey-missing"), {
16045
16261
  reason: "pubkey-missing"
@@ -16053,7 +16269,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
16053
16269
  }
16054
16270
  let envelope;
16055
16271
  try {
16056
- envelope = JSON.parse(readFileSync22(entitlementPath, "utf-8"));
16272
+ envelope = JSON.parse(readFileSync23(entitlementPath, "utf-8"));
16057
16273
  } catch {
16058
16274
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
16059
16275
  }
@@ -16214,14 +16430,14 @@ function clientFrom(c) {
16214
16430
  );
16215
16431
  }
16216
16432
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
16217
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join18(PLATFORM_ROOT9, "config", "brand.json") : "";
16433
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join19(PLATFORM_ROOT9, "config", "brand.json") : "";
16218
16434
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
16219
16435
  if (BRAND_JSON_PATH && !existsSync24(BRAND_JSON_PATH)) {
16220
16436
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
16221
16437
  }
16222
16438
  if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
16223
16439
  try {
16224
- const parsed = JSON.parse(readFileSync23(BRAND_JSON_PATH, "utf-8"));
16440
+ const parsed = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
16225
16441
  BRAND = { ...BRAND, ...parsed };
16226
16442
  } catch (err) {
16227
16443
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -16240,11 +16456,11 @@ var brandLoginOpts = {
16240
16456
  bodyFont: BRAND.defaultFonts?.body,
16241
16457
  logoContainsName: !!BRAND.logoContainsName
16242
16458
  };
16243
- var ALIAS_DOMAINS_PATH = join18(homedir2(), BRAND.configDir, "alias-domains.json");
16459
+ var ALIAS_DOMAINS_PATH = join19(homedir2(), BRAND.configDir, "alias-domains.json");
16244
16460
  function loadAliasDomains() {
16245
16461
  try {
16246
16462
  if (!existsSync24(ALIAS_DOMAINS_PATH)) return null;
16247
- const parsed = JSON.parse(readFileSync23(ALIAS_DOMAINS_PATH, "utf-8"));
16463
+ const parsed = JSON.parse(readFileSync24(ALIAS_DOMAINS_PATH, "utf-8"));
16248
16464
  if (!Array.isArray(parsed)) {
16249
16465
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
16250
16466
  return null;
@@ -16268,10 +16484,10 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
16268
16484
  function isPublicHost(host) {
16269
16485
  return host.startsWith("public.") || aliasDomains.has(host);
16270
16486
  }
16271
- var app43 = new Hono();
16487
+ var app44 = new Hono();
16272
16488
  var waGateway = new WaGateway({
16273
16489
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
16274
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
16490
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
16275
16491
  ensureChannelSession: async ({ accountId, senderId, gatewayUrl, serverPath }) => {
16276
16492
  const userId = resolveAdminUserId({ accountId, senderPhone: senderId }) ?? void 0;
16277
16493
  console.error(`[whatsapp-native] op=admin-identity senderId=${senderId} userId=${userId ?? "owner-fallback"}`);
@@ -16286,10 +16502,10 @@ var waGateway = new WaGateway({
16286
16502
  }
16287
16503
  }
16288
16504
  });
16289
- app43.route("/", waGateway.routes());
16505
+ app44.route("/", waGateway.routes());
16290
16506
  waGateway.startSweeper();
16291
- app43.use("*", clientIpMiddleware);
16292
- app43.use("*", async (c, next) => {
16507
+ app44.use("*", clientIpMiddleware);
16508
+ app44.use("*", async (c, next) => {
16293
16509
  await next();
16294
16510
  c.header("X-Content-Type-Options", "nosniff");
16295
16511
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
@@ -16299,7 +16515,7 @@ app43.use("*", async (c, next) => {
16299
16515
  );
16300
16516
  });
16301
16517
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
16302
- app43.use("*", async (c, next) => {
16518
+ app44.use("*", async (c, next) => {
16303
16519
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
16304
16520
  await next();
16305
16521
  return;
@@ -16317,7 +16533,7 @@ app43.use("*", async (c, next) => {
16317
16533
  });
16318
16534
  }
16319
16535
  });
16320
- app43.use("*", async (c, next) => {
16536
+ app44.use("*", async (c, next) => {
16321
16537
  const host = (c.req.header("host") ?? "").split(":")[0];
16322
16538
  if (!isPublicHost(host)) {
16323
16539
  await next();
@@ -16348,7 +16564,7 @@ function resolveRemoteAuthOpts() {
16348
16564
  return brandLoginOpts;
16349
16565
  }
16350
16566
  var MAX_LOGIN_BODY = 8 * 1024;
16351
- app43.post("/__remote-auth/login", async (c) => {
16567
+ app44.post("/__remote-auth/login", async (c) => {
16352
16568
  const client = clientFrom(c);
16353
16569
  const clientIp = client.ip || "unknown";
16354
16570
  if (!requestIsTlsTerminated(c)) {
@@ -16393,7 +16609,7 @@ app43.post("/__remote-auth/login", async (c) => {
16393
16609
  }
16394
16610
  });
16395
16611
  });
16396
- app43.get("/__remote-auth/logout", (c) => {
16612
+ app44.get("/__remote-auth/logout", (c) => {
16397
16613
  const client = clientFrom(c);
16398
16614
  const clientIp = client.ip || "unknown";
16399
16615
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -16406,7 +16622,7 @@ app43.get("/__remote-auth/logout", (c) => {
16406
16622
  }
16407
16623
  });
16408
16624
  });
16409
- app43.post("/__remote-auth/change-password", async (c) => {
16625
+ app44.post("/__remote-auth/change-password", async (c) => {
16410
16626
  const client = clientFrom(c);
16411
16627
  const clientIp = client.ip || "unknown";
16412
16628
  const rateLimited = checkRateLimit(client);
@@ -16457,13 +16673,13 @@ app43.post("/__remote-auth/change-password", async (c) => {
16457
16673
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
16458
16674
  }
16459
16675
  });
16460
- app43.get("/__remote-auth/setup", (c) => {
16676
+ app44.get("/__remote-auth/setup", (c) => {
16461
16677
  if (isRemoteAuthConfigured()) {
16462
16678
  return c.redirect("/");
16463
16679
  }
16464
16680
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
16465
16681
  });
16466
- app43.post("/__remote-auth/set-initial-password", async (c) => {
16682
+ app44.post("/__remote-auth/set-initial-password", async (c) => {
16467
16683
  if (isRemoteAuthConfigured()) {
16468
16684
  return c.redirect("/");
16469
16685
  }
@@ -16501,10 +16717,10 @@ app43.post("/__remote-auth/set-initial-password", async (c) => {
16501
16717
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
16502
16718
  }
16503
16719
  });
16504
- app43.get("/api/remote-auth/status", (c) => {
16720
+ app44.get("/api/remote-auth/status", (c) => {
16505
16721
  return c.json({ configured: isRemoteAuthConfigured() });
16506
16722
  });
16507
- app43.post("/api/remote-auth/set-password", async (c) => {
16723
+ app44.post("/api/remote-auth/set-password", async (c) => {
16508
16724
  let body;
16509
16725
  try {
16510
16726
  body = await c.req.json();
@@ -16535,9 +16751,9 @@ app43.post("/api/remote-auth/set-password", async (c) => {
16535
16751
  return c.json({ error: "Failed to save password" }, 500);
16536
16752
  }
16537
16753
  });
16538
- app43.route("/api/_client-error", client_error_default);
16754
+ app44.route("/api/_client-error", client_error_default);
16539
16755
  console.log("[client-error-route] mounted");
16540
- app43.use("*", async (c, next) => {
16756
+ app44.use("*", async (c, next) => {
16541
16757
  const host = (c.req.header("host") ?? "").split(":")[0];
16542
16758
  const path2 = c.req.path;
16543
16759
  if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
@@ -16570,13 +16786,14 @@ app43.use("*", async (c, next) => {
16570
16786
  console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
16571
16787
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
16572
16788
  });
16573
- app43.route("/api/health", health_default);
16574
- app43.route("/api/chat", chat_default);
16575
- app43.route("/api/whatsapp", whatsapp_default);
16576
- app43.route("/api/onboarding", onboarding_default);
16577
- app43.route("/api/admin", admin_default);
16578
- app43.route("/api/access", access_default);
16579
- app43.route("/api/session", session_default2);
16789
+ app44.route("/api/health", health_default);
16790
+ app44.route("/api/chat", chat_default);
16791
+ app44.route("/api/whatsapp", whatsapp_default);
16792
+ app44.route("/api/whatsapp-reader", whatsapp_reader_default);
16793
+ app44.route("/api/onboarding", onboarding_default);
16794
+ app44.route("/api/admin", admin_default);
16795
+ app44.route("/api/access", access_default);
16796
+ app44.route("/api/session", session_default2);
16580
16797
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
16581
16798
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
16582
16799
  var IMAGE_MIME = {
@@ -16588,7 +16805,7 @@ var IMAGE_MIME = {
16588
16805
  ".svg": "image/svg+xml",
16589
16806
  ".ico": "image/x-icon"
16590
16807
  };
16591
- app43.get("/agent-assets/:slug/:filename", (c) => {
16808
+ app44.get("/agent-assets/:slug/:filename", (c) => {
16592
16809
  const slug = c.req.param("slug");
16593
16810
  const filename = c.req.param("filename");
16594
16811
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -16604,8 +16821,8 @@ app43.get("/agent-assets/:slug/:filename", (c) => {
16604
16821
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
16605
16822
  return c.text("Not found", 404);
16606
16823
  }
16607
- const filePath = resolve26(account.accountDir, "agents", slug, "assets", filename);
16608
- const expectedDir = resolve26(account.accountDir, "agents", slug, "assets");
16824
+ const filePath = resolve27(account.accountDir, "agents", slug, "assets", filename);
16825
+ const expectedDir = resolve27(account.accountDir, "agents", slug, "assets");
16609
16826
  if (!filePath.startsWith(expectedDir + "/")) {
16610
16827
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
16611
16828
  return c.text("Forbidden", 403);
@@ -16617,13 +16834,13 @@ app43.get("/agent-assets/:slug/:filename", (c) => {
16617
16834
  const ext = "." + filename.split(".").pop()?.toLowerCase();
16618
16835
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
16619
16836
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
16620
- const body = readFileSync23(filePath);
16837
+ const body = readFileSync24(filePath);
16621
16838
  return c.body(body, 200, {
16622
16839
  "Content-Type": contentType,
16623
16840
  "Cache-Control": "public, max-age=3600"
16624
16841
  });
16625
16842
  });
16626
- app43.get("/generated/:filename", (c) => {
16843
+ app44.get("/generated/:filename", (c) => {
16627
16844
  const filename = c.req.param("filename");
16628
16845
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
16629
16846
  console.error(`[generated] serve file=${filename} status=403`);
@@ -16634,8 +16851,8 @@ app43.get("/generated/:filename", (c) => {
16634
16851
  console.error(`[generated] serve file=${filename} status=404`);
16635
16852
  return c.text("Not found", 404);
16636
16853
  }
16637
- const filePath = resolve26(account.accountDir, "generated", filename);
16638
- const expectedDir = resolve26(account.accountDir, "generated");
16854
+ const filePath = resolve27(account.accountDir, "generated", filename);
16855
+ const expectedDir = resolve27(account.accountDir, "generated");
16639
16856
  if (!filePath.startsWith(expectedDir + "/")) {
16640
16857
  console.error(`[generated] serve file=${filename} status=403`);
16641
16858
  return c.text("Forbidden", 403);
@@ -16647,22 +16864,22 @@ app43.get("/generated/:filename", (c) => {
16647
16864
  const ext = "." + filename.split(".").pop()?.toLowerCase();
16648
16865
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
16649
16866
  console.log(`[generated] serve file=${filename} status=200`);
16650
- const body = readFileSync23(filePath);
16867
+ const body = readFileSync24(filePath);
16651
16868
  return c.body(body, 200, {
16652
16869
  "Content-Type": contentType,
16653
16870
  "Cache-Control": "public, max-age=86400"
16654
16871
  });
16655
16872
  });
16656
- app43.route("/sites", sites_default);
16657
- app43.route("/listings", listings_default);
16658
- app43.route("/v", visitor_event_default);
16659
- app43.route("/v", visitor_consent_default);
16873
+ app44.route("/sites", sites_default);
16874
+ app44.route("/listings", listings_default);
16875
+ app44.route("/v", visitor_event_default);
16876
+ app44.route("/v", visitor_consent_default);
16660
16877
  var htmlCache = /* @__PURE__ */ new Map();
16661
16878
  var brandLogoPath = "/brand/maxy-monochrome.png";
16662
16879
  var brandIconPath = "/brand/maxy-monochrome.png";
16663
16880
  if (BRAND_JSON_PATH && existsSync24(BRAND_JSON_PATH)) {
16664
16881
  try {
16665
- const fullBrand = JSON.parse(readFileSync23(BRAND_JSON_PATH, "utf-8"));
16882
+ const fullBrand = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
16666
16883
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
16667
16884
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
16668
16885
  } catch {
@@ -16679,9 +16896,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
16679
16896
  function readInstalledVersion() {
16680
16897
  try {
16681
16898
  if (!PLATFORM_ROOT9) return "unknown";
16682
- const versionFile = join18(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
16899
+ const versionFile = join19(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
16683
16900
  if (!existsSync24(versionFile)) return "unknown";
16684
- const content = readFileSync23(versionFile, "utf-8").trim();
16901
+ const content = readFileSync24(versionFile, "utf-8").trim();
16685
16902
  return content || "unknown";
16686
16903
  } catch {
16687
16904
  return "unknown";
@@ -16722,7 +16939,7 @@ var clientErrorReporterScript = `<script>
16722
16939
  function cachedHtml(file) {
16723
16940
  let html = htmlCache.get(file);
16724
16941
  if (!html) {
16725
- html = readFileSync23(resolve26(process.cwd(), "public", file), "utf-8");
16942
+ html = readFileSync24(resolve27(process.cwd(), "public", file), "utf-8");
16726
16943
  const productNameEsc = escapeHtml(BRAND.productName);
16727
16944
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
16728
16945
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -16738,13 +16955,13 @@ ${clientErrorReporterScript}
16738
16955
  }
16739
16956
  var brandedHtmlCache = /* @__PURE__ */ new Map();
16740
16957
  function loadBrandingCache(agentSlug) {
16741
- const configDir2 = join18(homedir2(), BRAND.configDir);
16958
+ const configDir2 = join19(homedir2(), BRAND.configDir);
16742
16959
  try {
16743
16960
  const accountId = getDefaultAccountId();
16744
16961
  if (!accountId) return null;
16745
- const cachePath = join18(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
16962
+ const cachePath = join19(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
16746
16963
  if (!existsSync24(cachePath)) return null;
16747
- return JSON.parse(readFileSync23(cachePath, "utf-8"));
16964
+ return JSON.parse(readFileSync24(cachePath, "utf-8"));
16748
16965
  } catch {
16749
16966
  return null;
16750
16967
  }
@@ -16787,7 +17004,7 @@ function escapeHtml(s) {
16787
17004
  function agentUnavailableHtml() {
16788
17005
  return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
16789
17006
  }
16790
- app43.get("/", (c) => {
17007
+ app44.get("/", (c) => {
16791
17008
  const host = (c.req.header("host") ?? "").split(":")[0];
16792
17009
  if (isPublicHost(host)) {
16793
17010
  const defaultSlug = resolveDefaultSlug();
@@ -16803,12 +17020,12 @@ app43.get("/", (c) => {
16803
17020
  }
16804
17021
  return c.html(cachedHtml("index.html"));
16805
17022
  });
16806
- app43.get("/public", (c) => {
17023
+ app44.get("/public", (c) => {
16807
17024
  const host = (c.req.header("host") ?? "").split(":")[0];
16808
17025
  if (isPublicHost(host)) return c.text("Not found", 404);
16809
17026
  return c.html(cachedHtml("public.html"));
16810
17027
  });
16811
- app43.get("/chat", (c) => {
17028
+ app44.get("/chat", (c) => {
16812
17029
  const host = (c.req.header("host") ?? "").split(":")[0];
16813
17030
  if (isPublicHost(host)) return c.text("Not found", 404);
16814
17031
  return c.html(cachedHtml("public.html"));
@@ -16827,12 +17044,12 @@ async function logViewerFetch(c, next) {
16827
17044
  duration_ms: Date.now() - start
16828
17045
  });
16829
17046
  }
16830
- app43.use("/vnc-viewer.html", logViewerFetch);
16831
- app43.use("/vnc-popout.html", logViewerFetch);
16832
- app43.get("/vnc-popout.html", (c) => {
17047
+ app44.use("/vnc-viewer.html", logViewerFetch);
17048
+ app44.use("/vnc-popout.html", logViewerFetch);
17049
+ app44.get("/vnc-popout.html", (c) => {
16833
17050
  let html = htmlCache.get("vnc-popout.html");
16834
17051
  if (!html) {
16835
- html = readFileSync23(resolve26(process.cwd(), "public", "vnc-popout.html"), "utf-8");
17052
+ html = readFileSync24(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
16836
17053
  const name = escapeHtml(BRAND.productName);
16837
17054
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
16838
17055
  html = html.replace("</head>", ` ${brandScript}
@@ -16842,7 +17059,7 @@ app43.get("/vnc-popout.html", (c) => {
16842
17059
  }
16843
17060
  return c.html(html);
16844
17061
  });
16845
- app43.post("/api/vnc/client-event", async (c) => {
17062
+ app44.post("/api/vnc/client-event", async (c) => {
16846
17063
  let body;
16847
17064
  try {
16848
17065
  body = await c.req.json();
@@ -16863,30 +17080,30 @@ app43.post("/api/vnc/client-event", async (c) => {
16863
17080
  });
16864
17081
  return c.json({ ok: true });
16865
17082
  });
16866
- app43.get("/g/:slug", (c) => {
17083
+ app44.get("/g/:slug", (c) => {
16867
17084
  return c.html(brandedPublicHtml());
16868
17085
  });
16869
- app43.get("/graph", (c) => {
17086
+ app44.get("/graph", (c) => {
16870
17087
  const host = (c.req.header("host") ?? "").split(":")[0];
16871
17088
  if (isPublicHost(host)) return c.text("Not found", 404);
16872
17089
  return c.html(cachedHtml("graph.html"));
16873
17090
  });
16874
- app43.get("/sessions", (c) => {
17091
+ app44.get("/sessions", (c) => {
16875
17092
  const host = (c.req.header("host") ?? "").split(":")[0];
16876
17093
  if (isPublicHost(host)) return c.text("Not found", 404);
16877
17094
  return c.html(cachedHtml("sessions.html"));
16878
17095
  });
16879
- app43.get("/data", (c) => {
17096
+ app44.get("/data", (c) => {
16880
17097
  const host = (c.req.header("host") ?? "").split(":")[0];
16881
17098
  if (isPublicHost(host)) return c.text("Not found", 404);
16882
17099
  return c.html(cachedHtml("data.html"));
16883
17100
  });
16884
- app43.get("/browser", (c) => {
17101
+ app44.get("/browser", (c) => {
16885
17102
  const host = (c.req.header("host") ?? "").split(":")[0];
16886
17103
  if (isPublicHost(host)) return c.text("Not found", 404);
16887
17104
  return c.html(cachedHtml("browser.html"));
16888
17105
  });
16889
- app43.get("/:slug", async (c, next) => {
17106
+ app44.get("/:slug", async (c, next) => {
16890
17107
  const slug = c.req.param("slug");
16891
17108
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
16892
17109
  const account = resolveAccount();
@@ -16901,13 +17118,13 @@ app43.get("/:slug", async (c, next) => {
16901
17118
  await next();
16902
17119
  });
16903
17120
  if (brandFaviconPath !== "/favicon.ico") {
16904
- app43.get("/favicon.ico", (c) => {
17121
+ app44.get("/favicon.ico", (c) => {
16905
17122
  c.header("Cache-Control", "public, max-age=300");
16906
17123
  return c.redirect(brandFaviconPath, 302);
16907
17124
  });
16908
17125
  }
16909
- app43.use("/*", serveStatic({ root: "./public" }));
16910
- app43.all("*", (c) => {
17126
+ app44.use("/*", serveStatic({ root: "./public" }));
17127
+ app44.all("*", (c) => {
16911
17128
  const host = (c.req.header("host") ?? "").split(":")[0];
16912
17129
  const path2 = c.req.path;
16913
17130
  if (isPublicHost(host)) {
@@ -16921,7 +17138,7 @@ app43.all("*", (c) => {
16921
17138
  });
16922
17139
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
16923
17140
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
16924
- var httpServer = serve({ fetch: app43.fetch, port, hostname });
17141
+ var httpServer = serve({ fetch: app44.fetch, port, hostname });
16925
17142
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
16926
17143
  startAuthHealthHeartbeat();
16927
17144
  {
@@ -16943,6 +17160,7 @@ var SUBAPP_MANIFEST = [
16943
17160
  { prefix: "/api/health", file: "server/routes/health.ts", subapp: health_default },
16944
17161
  { prefix: "/api/chat", file: "server/routes/chat.ts", subapp: chat_default },
16945
17162
  { prefix: "/api/whatsapp", file: "server/routes/whatsapp.ts", subapp: whatsapp_default },
17163
+ { prefix: "/api/whatsapp-reader", file: "server/routes/whatsapp-reader.ts", subapp: whatsapp_reader_default },
16946
17164
  { prefix: "/api/onboarding", file: "server/routes/onboarding.ts", subapp: onboarding_default },
16947
17165
  { prefix: "/api/admin", file: "server/routes/admin/index.ts", subapp: admin_default },
16948
17166
  { prefix: "/api/access", file: "server/routes/access/index.ts", subapp: access_default },
@@ -16958,7 +17176,7 @@ for (const m of SUBAPP_MANIFEST) {
16958
17176
  }
16959
17177
  try {
16960
17178
  const registered = [];
16961
- for (const r of app43.routes ?? []) {
17179
+ for (const r of app44.routes ?? []) {
16962
17180
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
16963
17181
  if (AGENT_SLUG_PATTERN.test(r.path)) {
16964
17182
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -16990,7 +17208,7 @@ async function runAdminUserReconcileTick() {
16990
17208
  console.error("[adminuser-self-heal] skip reason=no-users-file");
16991
17209
  return;
16992
17210
  }
16993
- const usersRaw = readFileSync23(USERS_FILE, "utf-8").trim();
17211
+ const usersRaw = readFileSync24(USERS_FILE, "utf-8").trim();
16994
17212
  if (!usersRaw) {
16995
17213
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
16996
17214
  return;
@@ -17038,7 +17256,7 @@ try {
17038
17256
  } catch (err) {
17039
17257
  console.error(`[graph-health] account-enumeration unavailable reason=${err instanceof Error ? err.message : String(err)}`);
17040
17258
  }
17041
- var configDirForWhatsApp = basename6(MAXY_DIR) || ".maxy";
17259
+ var configDirForWhatsApp = basename7(MAXY_DIR) || ".maxy";
17042
17260
  var bootAccount = resolveAccount();
17043
17261
  var bootAccountConfig = bootAccount?.config;
17044
17262
  var bootPublicAgent = bootAccount ? resolvePublicAgent(bootAccount.accountDir, { accountId: bootAccount.accountId })?.slug ?? null : null;
@@ -17097,7 +17315,7 @@ if (bootAccountConfig?.whatsapp) {
17097
17315
  }
17098
17316
  init({
17099
17317
  configDir: configDirForWhatsApp,
17100
- platformRoot: resolve26(process.env.MAXY_PLATFORM_ROOT ?? join18(__dirname, "..")),
17318
+ platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join19(__dirname, "..")),
17101
17319
  accountConfig: bootAccountConfig,
17102
17320
  onMessage: async (msg) => {
17103
17321
  if (msg.isOwnerMirror) {
@@ -17108,8 +17326,9 @@ init({
17108
17326
  console.error(`[whatsapp:route] dropped reason=non-admin-sender senderId=${msg.senderPhone} agentType=${msg.agentType}`);
17109
17327
  return;
17110
17328
  }
17111
- if (!msg.text) {
17112
- console.error(`[whatsapp:route] dropped reason=no-text-on-native-channel senderId=${msg.senderPhone} media=${msg.mediaType ?? "none"}`);
17329
+ const hasFileMedia = !!msg.mediaPath && msg.mediaType !== "audio";
17330
+ if (!msg.text && !hasFileMedia) {
17331
+ console.error(`[whatsapp:route] dropped reason=no-text-no-media senderId=${msg.senderPhone} media=${msg.mediaType ?? "none"}`);
17113
17332
  return;
17114
17333
  }
17115
17334
  try {
@@ -17119,7 +17338,10 @@ init({
17119
17338
  accountId: msg.accountId,
17120
17339
  senderId: msg.senderPhone,
17121
17340
  text: msg.text,
17122
- reply: msg.reply
17341
+ reply: msg.reply,
17342
+ mediaPath: msg.mediaPath,
17343
+ mediaType: msg.mediaType,
17344
+ mediaMimetype: msg.mediaMimetype
17123
17345
  });
17124
17346
  } catch (err) {
17125
17347
  console.error(