@rubytech/create-maxy-code 0.1.293 → 0.1.295

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 (164) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +22 -4
  3. package/payload/platform/plugins/docs/references/admin-ui.md +19 -2
  4. package/payload/platform/plugins/docs/references/platform.md +2 -1
  5. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  6. package/payload/platform/services/claude-session-manager/dist/http-server.js +28 -3
  7. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  8. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +9 -0
  9. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  10. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +14 -0
  11. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  12. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -4
  13. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  14. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +7 -4
  15. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  16. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts +3 -0
  17. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.d.ts.map +1 -0
  18. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js +28 -0
  19. package/payload/platform/services/claude-session-manager/dist/settings-permission-mode.js.map +1 -0
  20. package/payload/platform/templates/specialists/agents/data-manager.md +27 -0
  21. package/payload/server/public/assets/AdminShell-DDieHnzi.js +1 -0
  22. package/payload/server/public/assets/Checkbox-DTrIyIFP.js +1 -0
  23. package/payload/server/public/assets/Transcript-C3aDVJ-n.js +1 -0
  24. package/payload/server/public/assets/admin-DVdyV-Q6.js +1 -0
  25. package/payload/server/public/assets/{arc-iu3VNUKX.js → arc-DmR-LPIx.js} +1 -1
  26. package/payload/server/public/assets/architecture-YZFGNWBL-CjF2k79a.js +1 -0
  27. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-un5y1Pav.js → architectureDiagram-Q4EWVU46-DR9W0q1P.js} +1 -1
  28. package/payload/server/public/assets/audio-attachment-mime-DGEfApkA.js +1 -0
  29. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CrT4y-Ve.js → blockDiagram-DXYQGD6D-C3uwaI7p.js} +1 -1
  30. package/payload/server/public/assets/browser-DrJReVEG.js +1 -0
  31. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BTNlRxRe.js → c4Diagram-AHTNJAMY-C8hmUDdd.js} +1 -1
  32. package/payload/server/public/assets/channel-drVqp11B.js +1 -0
  33. package/payload/server/public/assets/chat-DeEYwIKE.js +1 -0
  34. package/payload/server/public/assets/{chunk-2KRD3SAO-DjQJDvnb.js → chunk-2KRD3SAO-BYqpHDvA.js} +1 -1
  35. package/payload/server/public/assets/chunk-336JU56O-BRCubMCb.js +2 -0
  36. package/payload/server/public/assets/chunk-426QAEUC-BNINkVsL.js +1 -0
  37. package/payload/server/public/assets/{chunk-4BX2VUAB-B2BREWGj.js → chunk-4BX2VUAB-BeDVr5Tb.js} +1 -1
  38. package/payload/server/public/assets/{chunk-4TB4RGXK-CWOel6yZ.js → chunk-4TB4RGXK-DSMj_AZh.js} +1 -1
  39. package/payload/server/public/assets/{chunk-55IACEB6-8_6mlBoL.js → chunk-55IACEB6-DB18cH4S.js} +1 -1
  40. package/payload/server/public/assets/{chunk-5FUZZQ4R-CcBL3hEb.js → chunk-5FUZZQ4R-6DNGaUkf.js} +1 -1
  41. package/payload/server/public/assets/{chunk-5PVQY5BW-DpqQNCTE.js → chunk-5PVQY5BW-DPhkkS4p.js} +1 -1
  42. package/payload/server/public/assets/{chunk-67CJDMHE-D-EZpLie.js → chunk-67CJDMHE-Ca9KwdQm.js} +1 -1
  43. package/payload/server/public/assets/{chunk-7N4EOEYR-C9Ely26O.js → chunk-7N4EOEYR-BDpzHOmv.js} +1 -1
  44. package/payload/server/public/assets/{chunk-AA7GKIK3-DZZsYrza.js → chunk-AA7GKIK3-DXo9fZho.js} +1 -1
  45. package/payload/server/public/assets/{chunk-BSJP7CBP-B_1DfG3d.js → chunk-BSJP7CBP-CTqmM6qI.js} +1 -1
  46. package/payload/server/public/assets/{chunk-CIAEETIT-Osq5Xgsl.js → chunk-CIAEETIT-NufEId2j.js} +1 -1
  47. package/payload/server/public/assets/{chunk-EDXVE4YY-ecraT_D1.js → chunk-EDXVE4YY-BjWSqn7_.js} +1 -1
  48. package/payload/server/public/assets/{chunk-ENJZ2VHE-D2_uycym.js → chunk-ENJZ2VHE-BX1ZnU4A.js} +1 -1
  49. package/payload/server/public/assets/{chunk-FMBD7UC4-CpPyTbk9.js → chunk-FMBD7UC4-_4wtKsfc.js} +1 -1
  50. package/payload/server/public/assets/{chunk-FOC6F5B3-BBUjlBL-.js → chunk-FOC6F5B3-565zaYb3.js} +1 -1
  51. package/payload/server/public/assets/{chunk-ICPOFSXX-BG-5Z4Qz.js → chunk-ICPOFSXX-DvYSWH7x.js} +2 -2
  52. package/payload/server/public/assets/{chunk-K5T4RW27-BQfKdYtk.js → chunk-K5T4RW27-CTZnA5fq.js} +1 -1
  53. package/payload/server/public/assets/{chunk-KGLVRYIC-D1pxYesN.js → chunk-KGLVRYIC-CeuKp7uR.js} +1 -1
  54. package/payload/server/public/assets/{chunk-LIHQZDEY-CwDi08BU.js → chunk-LIHQZDEY-DXkzlh3_.js} +1 -1
  55. package/payload/server/public/assets/{chunk-ORNJ4GCN-Dy-V9ZFU.js → chunk-ORNJ4GCN-DcZUCmgM.js} +1 -1
  56. package/payload/server/public/assets/{chunk-OYMX7WX6-Be3df9Kc.js → chunk-OYMX7WX6-7_m3mEOK.js} +1 -1
  57. package/payload/server/public/assets/chunk-QZHKN3VN-CBWmDBHe.js +1 -0
  58. package/payload/server/public/assets/{chunk-U2HBQHQK-B1lsc9BA.js → chunk-U2HBQHQK-Bl1a895I.js} +1 -1
  59. package/payload/server/public/assets/{chunk-X2U36JSP-lSzO6qYV.js → chunk-X2U36JSP-WkSpBPYx.js} +1 -1
  60. package/payload/server/public/assets/{chunk-XPW4576I-BvIgWKZQ.js → chunk-XPW4576I-CnU6DVpC.js} +1 -1
  61. package/payload/server/public/assets/{chunk-YZCP3GAM-Bb60_vDO.js → chunk-YZCP3GAM-DpWRmPUo.js} +1 -1
  62. package/payload/server/public/assets/{chunk-ZZ45TVLE-Bny6wiCL.js → chunk-ZZ45TVLE-D9Dgmeso.js} +1 -1
  63. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Dplkw_pj.js +1 -0
  64. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sJXv1Ihp.js +1 -0
  65. package/payload/server/public/assets/clone-Q_B6oO0c.js +1 -0
  66. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-DsO6VRrT.js → cose-bilkent-S5V4N54A-C04wkJr7.js} +1 -1
  67. package/payload/server/public/assets/{dagre-KV5264BT-Bd45zu30.js → dagre-KV5264BT-DPq3dcLH.js} +1 -1
  68. package/payload/server/public/assets/{dagre-DTQyvF-b.js → dagre-PrVfCcSt.js} +1 -1
  69. package/payload/server/public/assets/data-CYyR2m_B.js +1 -0
  70. package/payload/server/public/assets/{diagram-5BDNPKRD-B3GfgObm.js → diagram-5BDNPKRD-DoszElKb.js} +1 -1
  71. package/payload/server/public/assets/{diagram-G4DWMVQ6-Ccy_YcB0.js → diagram-G4DWMVQ6-BRuqosix.js} +1 -1
  72. package/payload/server/public/assets/{diagram-MMDJMWI5-uOEKrHYy.js → diagram-MMDJMWI5-CpigG1d_.js} +1 -1
  73. package/payload/server/public/assets/{diagram-TYMM5635-BAWSU1wH.js → diagram-TYMM5635-BS0eYiq9.js} +1 -1
  74. package/payload/server/public/assets/{erDiagram-SMLLAGMA-C5SNsoHU.js → erDiagram-SMLLAGMA-VEQyXCFl.js} +1 -1
  75. package/payload/server/public/assets/file-download-C3pBZjt9.js +1 -0
  76. package/payload/server/public/assets/{flatten-ya0TqRLc.js → flatten-DeFkSYLU.js} +1 -1
  77. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-eGUNT0jC.js → flowDiagram-DWJPFMVM-2NYMfqHX.js} +1 -1
  78. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-ChQD_MQS.js → ganttDiagram-T4ZO3ILL-AAAa2sqE.js} +1 -1
  79. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DsUTwRUb.js +1 -0
  80. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CK5hWyS_.js → gitGraphDiagram-UUTBAWPF-d8NUAIz5.js} +1 -1
  81. package/payload/server/public/assets/{graph-nPeTW1V_.js → graph-Bx9_2qbJ.js} +3 -3
  82. package/payload/server/public/assets/graph-labels-Cc1nU1_f.js +1 -0
  83. package/payload/server/public/assets/{graphlib-DbSkkysa.js → graphlib-DUlqr2mr.js} +1 -1
  84. package/payload/server/public/assets/info-OMHHGYJF-BV9FyUXQ.js +1 -0
  85. package/payload/server/public/assets/infoDiagram-42DDH7IO-D4dh4-0g.js +2 -0
  86. package/payload/server/public/assets/{isEmpty-h-wRi_o9.js → isEmpty-Bn-Se8yT.js} +1 -1
  87. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DR685OiM.js → ishikawaDiagram-UXIWVN3A-DPTmm2IE.js} +1 -1
  88. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-DYgyVIQE.js → journeyDiagram-VCZTEJTY-B85vjqkE.js} +1 -1
  89. package/payload/server/public/assets/jsx-runtime-5auA0FEj.js +9 -0
  90. package/payload/server/public/assets/jsx-runtime-D3PZpOAF.css +1 -0
  91. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BbOYz3ft.js → kanban-definition-6JOO6SKY-C2Lfb5Xh.js} +1 -1
  92. package/payload/server/public/assets/{line-BmJuH1ci.js → line-CODKFpwO.js} +1 -1
  93. package/payload/server/public/assets/{linear-HbmXARXu.js → linear-CgbkJiu6.js} +1 -1
  94. package/payload/server/public/assets/{mermaid-parser.core-B9dlRmr6.js → mermaid-parser.core-DYdFZnXH.js} +2 -2
  95. package/payload/server/public/assets/{mermaid.core-CA_tMkuh.js → mermaid.core-Bamjzahu.js} +3 -3
  96. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DNfGKB3j.js → mindmap-definition-QFDTVHPH-CLK90bKJ.js} +1 -1
  97. package/payload/server/public/assets/{ordinal-Dwxksj1B.js → ordinal-C-EimP2j.js} +1 -1
  98. package/payload/server/public/assets/packet-4T2RLAQJ-SXjQ83Vr.js +1 -0
  99. package/payload/server/public/assets/pie-ZZUOXDRM-q7TXebDD.js +1 -0
  100. package/payload/server/public/assets/{pieDiagram-DEJITSTG-4nplxyR3.js → pieDiagram-DEJITSTG-DEsnxhqP.js} +1 -1
  101. package/payload/server/public/assets/public-BFMu-jux.js +35 -0
  102. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-BuRxivWl.js → quadrantDiagram-34T5L4WZ-uIP9V2jZ.js} +1 -1
  103. package/payload/server/public/assets/radar-PYXPWWZC-CXKUHVMS.js +1 -0
  104. package/payload/server/public/assets/{reduce-BUuWaDl2.js → reduce-B0wq8DtH.js} +1 -1
  105. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CX0JWzZW.js → requirementDiagram-MS252O5E-CVS6t5tv.js} +1 -1
  106. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BPbfY-tX.js → sankeyDiagram-XADWPNL6-BIsmtyZA.js} +1 -1
  107. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BgDVnY5n.js → sequenceDiagram-FGHM5R23-Cu8TfQiW.js} +1 -1
  108. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DZzcTY8N.js → stateDiagram-FHFEXIEX-ax4vYGft.js} +1 -1
  109. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BRv1By5g.js +1 -0
  110. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-LRc4oAIn.js → timeline-definition-GMOUNBTQ-3l7ojkMA.js} +1 -1
  111. package/payload/server/public/assets/treeView-SZITEDCU-CWuFgUeJ.js +1 -0
  112. package/payload/server/public/assets/treemap-W4RFUUIX-gKO4rbgo.js +1 -0
  113. package/payload/server/public/assets/useSelectionMode-C_EBRd2k.js +5 -0
  114. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-D285XuiE.js → vennDiagram-DHZGUBPP-C_sv0qMD.js} +1 -1
  115. package/payload/server/public/assets/wardley-RL74JXVD-hDEw8pJN.js +1 -0
  116. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-55WTCJwx.js → wardleyDiagram-NUSXRM2D-C7u4IHMB.js} +1 -1
  117. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-mBKutlt4.js → xychartDiagram-5P7HB3ND-A-uLXr1a.js} +1 -1
  118. package/payload/server/public/browser.html +7 -5
  119. package/payload/server/public/chat.html +9 -6
  120. package/payload/server/public/data.html +6 -6
  121. package/payload/server/public/graph.html +9 -7
  122. package/payload/server/public/index.html +9 -7
  123. package/payload/server/public/public.html +6 -4
  124. package/payload/server/server.js +595 -276
  125. package/payload/server/public/assets/AdminShell-7xqVmEF0.js +0 -1
  126. package/payload/server/public/assets/Checkbox-xIFPRr-Y.js +0 -1
  127. package/payload/server/public/assets/Transcript-siyY9S7_.js +0 -1
  128. package/payload/server/public/assets/admin-DVyRE7og.js +0 -1
  129. package/payload/server/public/assets/architecture-YZFGNWBL-HsK_v-AH.js +0 -1
  130. package/payload/server/public/assets/browser-CWFHESdi.js +0 -1
  131. package/payload/server/public/assets/channel-B3X2ELTx.js +0 -1
  132. package/payload/server/public/assets/chat-CoZ5hSiK.js +0 -1
  133. package/payload/server/public/assets/chunk-336JU56O-CWAQPaQW.js +0 -2
  134. package/payload/server/public/assets/chunk-426QAEUC-CYsbwfwG.js +0 -1
  135. package/payload/server/public/assets/chunk-QZHKN3VN-CitInsDb.js +0 -1
  136. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B8ZHYEIL.js +0 -1
  137. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D7TgEwXH.js +0 -1
  138. package/payload/server/public/assets/clone-C-K4Yq8V.js +0 -1
  139. package/payload/server/public/assets/data-Dex0L_hs.js +0 -1
  140. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CP3pxYZ8.js +0 -1
  141. package/payload/server/public/assets/graph-labels-J48HJ3as.js +0 -1
  142. package/payload/server/public/assets/info-OMHHGYJF-DUz8FRjp.js +0 -1
  143. package/payload/server/public/assets/infoDiagram-42DDH7IO-CoLeR6OP.js +0 -2
  144. package/payload/server/public/assets/packet-4T2RLAQJ-C-0PIYwM.js +0 -1
  145. package/payload/server/public/assets/pie-ZZUOXDRM-DUWx5LLr.js +0 -1
  146. package/payload/server/public/assets/public-C7o23SFC.js +0 -35
  147. package/payload/server/public/assets/radar-PYXPWWZC-BPW6Hewb.js +0 -1
  148. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-Bk-yVe98.js +0 -1
  149. package/payload/server/public/assets/treeView-SZITEDCU-CfxoEICI.js +0 -1
  150. package/payload/server/public/assets/treemap-W4RFUUIX-BFC84eoy.js +0 -1
  151. package/payload/server/public/assets/useSelectionMode-CFisDuuw.js +0 -13
  152. package/payload/server/public/assets/useSelectionMode-s7AH5v9J.css +0 -1
  153. package/payload/server/public/assets/wardley-RL74JXVD-C-mQV2If.js +0 -1
  154. /package/payload/server/public/assets/{_baseFor-Dn4GSmI6.js → _baseFor-BV-TyLWt.js} +0 -0
  155. /package/payload/server/public/assets/{array-DJN9YAVf.js → array-lqrvkwy7.js} +0 -0
  156. /package/payload/server/public/assets/{cytoscape.esm-BcJTl1re.js → cytoscape.esm-SmEOayFS.js} +0 -0
  157. /package/payload/server/public/assets/{defaultLocale-B4F_XsBB.js → defaultLocale-Dl3Sud5K.js} +0 -0
  158. /package/payload/server/public/assets/{dist-B7zzC2xF.js → dist-Pgmncqde.js} +0 -0
  159. /package/payload/server/public/assets/{AdminShell-qc_xy7Az.css → file-download-qc_xy7Az.css} +0 -0
  160. /package/payload/server/public/assets/{init-DX0Y1qU4.js → init-BukMwkmL.js} +0 -0
  161. /package/payload/server/public/assets/{katex-CjHJ1D7d.js → katex-jl-BtNZi.js} +0 -0
  162. /package/payload/server/public/assets/{path-7vUsG-o2.js → path-DPTRcLku.js} +0 -0
  163. /package/payload/server/public/assets/{rough.esm-NLRoWnq-.js → rough.esm-VLpapkIG.js} +0 -0
  164. /package/payload/server/public/assets/{src-CpjuOYjb.js → src-CozP7LCe.js} +0 -0
@@ -1214,8 +1214,8 @@ var serveStatic = (options = { root: "" }) => {
1214
1214
  };
1215
1215
 
1216
1216
  // server/index.ts
1217
- import { readFileSync as readFileSync24, existsSync as existsSync25, watchFile } from "fs";
1218
- import { resolve as resolve27, join as join20, basename as basename8 } from "path";
1217
+ import { readFileSync as readFileSync26, existsSync as existsSync26, watchFile } from "fs";
1218
+ import { resolve as resolve28, join as join21, basename as basename8 } from "path";
1219
1219
  import { homedir as homedir3 } from "os";
1220
1220
  import { monitorEventLoopDelay } from "perf_hooks";
1221
1221
 
@@ -1794,7 +1794,7 @@ var credsSaveQueue = Promise.resolve();
1794
1794
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1795
1795
  console.error(`${TAG2} draining credential save queue\u2026`);
1796
1796
  const timer2 = new Promise(
1797
- (resolve28) => setTimeout(() => resolve28("timeout"), timeoutMs)
1797
+ (resolve29) => setTimeout(() => resolve29("timeout"), timeoutMs)
1798
1798
  );
1799
1799
  const result = await Promise.race([
1800
1800
  credsSaveQueue.then(() => "drained"),
@@ -1922,11 +1922,11 @@ async function createWaSocket(opts) {
1922
1922
  return sock;
1923
1923
  }
1924
1924
  async function waitForConnection(sock) {
1925
- return new Promise((resolve28, reject) => {
1925
+ return new Promise((resolve29, reject) => {
1926
1926
  const handler = (update) => {
1927
1927
  if (update.connection === "open") {
1928
1928
  sock.ev.off("connection.update", handler);
1929
- resolve28();
1929
+ resolve29();
1930
1930
  }
1931
1931
  if (update.connection === "close") {
1932
1932
  sock.ev.off("connection.update", handler);
@@ -2040,14 +2040,14 @@ ${inspected}`;
2040
2040
  return inspect2(err, INSPECT_OPTS2);
2041
2041
  }
2042
2042
  function withTimeout(label, promise, timeoutMs) {
2043
- return new Promise((resolve28, reject) => {
2043
+ return new Promise((resolve29, reject) => {
2044
2044
  const timer2 = setTimeout(() => {
2045
2045
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2046
2046
  }, timeoutMs);
2047
2047
  promise.then(
2048
2048
  (value) => {
2049
2049
  clearTimeout(timer2);
2050
- resolve28(value);
2050
+ resolve29(value);
2051
2051
  },
2052
2052
  (err) => {
2053
2053
  clearTimeout(timer2);
@@ -2646,8 +2646,8 @@ async function persistWhatsAppMessage(input) {
2646
2646
  const { givenName, familyName } = splitName(input.pushName);
2647
2647
  const prev = sessionWriteLocks.get(input.cacheKey);
2648
2648
  let release;
2649
- const mine = new Promise((resolve28) => {
2650
- release = resolve28;
2649
+ const mine = new Promise((resolve29) => {
2650
+ release = resolve29;
2651
2651
  });
2652
2652
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2653
2653
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -3727,11 +3727,11 @@ async function connectWithReconnect(conn) {
3727
3727
  console.error(
3728
3728
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3729
3729
  );
3730
- await new Promise((resolve28) => {
3731
- const timer2 = setTimeout(resolve28, delay);
3730
+ await new Promise((resolve29) => {
3731
+ const timer2 = setTimeout(resolve29, delay);
3732
3732
  conn.abortController.signal.addEventListener("abort", () => {
3733
3733
  clearTimeout(timer2);
3734
- resolve28();
3734
+ resolve29();
3735
3735
  }, { once: true });
3736
3736
  });
3737
3737
  }
@@ -3739,16 +3739,16 @@ async function connectWithReconnect(conn) {
3739
3739
  }
3740
3740
  }
3741
3741
  function waitForDisconnectEvent(conn) {
3742
- return new Promise((resolve28) => {
3742
+ return new Promise((resolve29) => {
3743
3743
  if (!conn.sock) {
3744
- resolve28();
3744
+ resolve29();
3745
3745
  return;
3746
3746
  }
3747
3747
  const sock = conn.sock;
3748
3748
  const handler = (update) => {
3749
3749
  if (update.connection === "close") {
3750
3750
  sock.ev.off("connection.update", handler);
3751
- resolve28();
3751
+ resolve29();
3752
3752
  }
3753
3753
  };
3754
3754
  sock.ev.on("connection.update", handler);
@@ -4008,8 +4008,8 @@ async function handleInboundMessage(conn, msg) {
4008
4008
  const conversationKey = isGroup ? remoteJid : senderPhone;
4009
4009
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
4010
4010
  let resolvePending;
4011
- const sttPending = new Promise((resolve28) => {
4012
- resolvePending = resolve28;
4011
+ const sttPending = new Promise((resolve29) => {
4012
+ resolvePending = resolve29;
4013
4013
  });
4014
4014
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
4015
4015
  try {
@@ -4400,20 +4400,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
4400
4400
 
4401
4401
  // server/routes/health.ts
4402
4402
  function checkPort(port2, timeoutMs = 500) {
4403
- return new Promise((resolve28) => {
4403
+ return new Promise((resolve29) => {
4404
4404
  const socket = createConnection2(port2, "127.0.0.1");
4405
4405
  socket.setTimeout(timeoutMs);
4406
4406
  socket.once("connect", () => {
4407
4407
  socket.destroy();
4408
- resolve28(true);
4408
+ resolve29(true);
4409
4409
  });
4410
4410
  socket.once("error", () => {
4411
4411
  socket.destroy();
4412
- resolve28(false);
4412
+ resolve29(false);
4413
4413
  });
4414
4414
  socket.once("timeout", () => {
4415
4415
  socket.destroy();
4416
- resolve28(false);
4416
+ resolve29(false);
4417
4417
  });
4418
4418
  });
4419
4419
  }
@@ -4529,6 +4529,16 @@ async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
4529
4529
  await writeFile2(metaPath, JSON.stringify(meta, null, 2));
4530
4530
  return { attachmentId, filename, storagePath, metaPath, mimeType, sizeBytes };
4531
4531
  }
4532
+ async function storeAttachment(accountId, file) {
4533
+ assertSupportedMime(file.type);
4534
+ if (file.size > MAX_FILE_SIZE_BYTES) {
4535
+ throw new Error(
4536
+ `File "${file.name}" exceeds the 50 MB limit (${(file.size / 1024 / 1024).toFixed(1)} MB).`
4537
+ );
4538
+ }
4539
+ const buffer = Buffer.from(await file.arrayBuffer());
4540
+ return writeAttachment(accountId, file.name, file.type, file.size, buffer);
4541
+ }
4532
4542
  async function storePublicAttachment(sessionId, file, buffer) {
4533
4543
  assertSupportedMime(file.type);
4534
4544
  if (file.size > MAX_FILE_SIZE_BYTES) {
@@ -5510,12 +5520,12 @@ async function dispatchOnce(input) {
5510
5520
  });
5511
5521
  if (!entry) return { error: "spawn-failed" };
5512
5522
  entry.lastInboundAt = Date.now();
5513
- let resolve28;
5523
+ let resolve29;
5514
5524
  const turnPromise = new Promise((r) => {
5515
- resolve28 = r;
5525
+ resolve29 = r;
5516
5526
  });
5517
5527
  const listener = (text) => {
5518
- resolve28(text);
5528
+ resolve29(text);
5519
5529
  };
5520
5530
  entry.subscribers.add(listener);
5521
5531
  const writeAtMs = Date.now();
@@ -6301,8 +6311,8 @@ async function startLogin(opts) {
6301
6311
  await clearAuth(authDir);
6302
6312
  let resolveCode = null;
6303
6313
  let rejectCode = null;
6304
- const codePromise = new Promise((resolve28, reject) => {
6305
- resolveCode = resolve28;
6314
+ const codePromise = new Promise((resolve29, reject) => {
6315
+ resolveCode = resolve29;
6306
6316
  rejectCode = reject;
6307
6317
  });
6308
6318
  const codeTimer = setTimeout(
@@ -7705,15 +7715,97 @@ var whatsapp_reader_default = app5;
7705
7715
  // server/routes/webchat.ts
7706
7716
  import { basename as basename3, dirname as dirname2 } from "path";
7707
7717
  import { join as join10 } from "path";
7718
+ import { readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync5 } from "fs";
7708
7719
  var WEBCHAT_ADMIN_KEY = "webchat-admin";
7720
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
7721
+ function locateSession(sessionId) {
7722
+ const cfg = claudeConfigDir();
7723
+ if (!cfg) return { projectDir: null, channel: null };
7724
+ for (const { path: path2 } of enumerateJsonls(join10(cfg, "projects"))) {
7725
+ if (basename3(path2) === `${sessionId}.jsonl`) {
7726
+ const dir = dirname2(path2);
7727
+ const meta = readSidecarMeta(join10(dir, `${sessionId}.meta.json`));
7728
+ return { projectDir: dir, channel: meta.channel };
7729
+ }
7730
+ }
7731
+ return { projectDir: null, channel: null };
7732
+ }
7733
+ function conflictingBinding(channel) {
7734
+ return channel !== null && channel !== "webchat" ? channel : null;
7735
+ }
7736
+ var NO_INDICATORS = {
7737
+ activity: null,
7738
+ permissionMode: null,
7739
+ effectivePermissionMode: null,
7740
+ model: null
7741
+ };
7742
+ var indicatorsErrorLogged = false;
7743
+ var INDICATORS_TIMEOUT_MS = 1500;
7744
+ async function fetchComposerIndicators(sessionId) {
7745
+ let port2;
7746
+ try {
7747
+ port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "webchat:session" });
7748
+ } catch {
7749
+ return NO_INDICATORS;
7750
+ }
7751
+ try {
7752
+ const res = await fetch(`http://127.0.0.1:${port2}/${sessionId}/meta`, {
7753
+ signal: AbortSignal.timeout(INDICATORS_TIMEOUT_MS)
7754
+ });
7755
+ if (!res.ok) return NO_INDICATORS;
7756
+ const body = await res.json();
7757
+ return {
7758
+ activity: typeof body.activity === "string" ? body.activity : null,
7759
+ permissionMode: typeof body.permissionMode === "string" ? body.permissionMode : null,
7760
+ effectivePermissionMode: typeof body.effectivePermissionMode === "string" ? body.effectivePermissionMode : null,
7761
+ model: typeof body.model === "string" ? body.model : null
7762
+ };
7763
+ } catch (err) {
7764
+ if (!indicatorsErrorLogged) {
7765
+ indicatorsErrorLogged = true;
7766
+ console.error(`[webchat:session] indicators-unavailable detail=${err instanceof Error ? err.message : String(err)} (logged once per process)`);
7767
+ }
7768
+ return NO_INDICATORS;
7769
+ }
7770
+ }
7771
+ var MODEL_ID_PATTERN = /^claude-[a-z0-9][a-z0-9.-]*(\[1m\])?$/;
7772
+ var EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
7773
+ function readLevers() {
7774
+ let account;
7775
+ try {
7776
+ account = resolveAccount();
7777
+ } catch {
7778
+ return { leverModel: null, leverEffort: null };
7779
+ }
7780
+ if (!account) return { leverModel: null, leverEffort: null };
7781
+ const model = account.config.adminModel;
7782
+ const effort = account.config.effort;
7783
+ return {
7784
+ leverModel: typeof model === "string" && MODEL_ID_PATTERN.test(model) ? model : null,
7785
+ leverEffort: typeof effort === "string" && EFFORT_LEVELS.has(effort) ? effort : null
7786
+ };
7787
+ }
7788
+ var REAPPLY_TIMEOUT_MS = 1500;
7789
+ async function reapplyLeversViaManager() {
7790
+ let port2;
7791
+ try {
7792
+ port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "webchat:settings" });
7793
+ } catch {
7794
+ return false;
7795
+ }
7796
+ try {
7797
+ const res = await fetch(`http://127.0.0.1:${port2}/reapply-levers`, {
7798
+ method: "POST",
7799
+ signal: AbortSignal.timeout(REAPPLY_TIMEOUT_MS)
7800
+ });
7801
+ return res.ok;
7802
+ } catch {
7803
+ return false;
7804
+ }
7805
+ }
7709
7806
  function createWebchatRoutes(deps) {
7710
7807
  const app49 = new Hono();
7711
7808
  app49.post("/send", requireAdminSession, async (c) => {
7712
- const body = await c.req.json().catch(() => null);
7713
- const text = body?.text;
7714
- if (typeof text !== "string" || text.length === 0) {
7715
- return c.json({ error: "text required" }, 400);
7716
- }
7717
7809
  let accountId;
7718
7810
  try {
7719
7811
  accountId = resolvePlatformAccountId();
@@ -7722,10 +7814,161 @@ function createWebchatRoutes(deps) {
7722
7814
  console.error(`[webchat:inbound] op=send-refused reason=account-unresolved detail=${detail}`);
7723
7815
  return c.json({ error: "account unresolved" }, 503);
7724
7816
  }
7725
- await deps.handleInbound({ role: "admin", accountId, key: WEBCHAT_ADMIN_KEY, text });
7817
+ let text;
7818
+ let target;
7819
+ let files = [];
7820
+ const contentType = c.req.header("content-type") ?? "";
7821
+ const isMultipart = contentType.startsWith("multipart/form-data");
7822
+ if (isMultipart) {
7823
+ let formData;
7824
+ try {
7825
+ formData = await c.req.formData();
7826
+ } catch {
7827
+ console.error("[webchat:inbound] op=send-refused kind=multipart reason=invalid-body");
7828
+ return c.json({ error: "invalid multipart body" }, 400);
7829
+ }
7830
+ const typed = formData.get("text");
7831
+ text = typeof typed === "string" ? typed : "";
7832
+ files = formData.getAll("attachments").filter((f) => f instanceof File);
7833
+ const rawTarget = formData.get("session");
7834
+ if (rawTarget !== null) {
7835
+ if (typeof rawTarget !== "string" || !UUID_PATTERN.test(rawTarget)) {
7836
+ return c.json({ error: "invalid session id" }, 400);
7837
+ }
7838
+ target = rawTarget;
7839
+ }
7840
+ } else {
7841
+ const body = await c.req.json().catch(() => null);
7842
+ const typed = body?.text;
7843
+ if (typeof typed !== "string" || typed.length === 0) {
7844
+ return c.json({ error: "text required" }, 400);
7845
+ }
7846
+ text = typed;
7847
+ const rawTarget = body?.session;
7848
+ if (rawTarget !== void 0) {
7849
+ if (typeof rawTarget !== "string" || !UUID_PATTERN.test(rawTarget)) {
7850
+ return c.json({ error: "invalid session id" }, 400);
7851
+ }
7852
+ target = rawTarget;
7853
+ }
7854
+ }
7855
+ let deliveryKey = WEBCHAT_ADMIN_KEY;
7856
+ let deliverySessionId;
7857
+ if (target !== void 0) {
7858
+ const { projectDir, channel } = locateSession(target);
7859
+ if (projectDir === null) {
7860
+ return c.json({ error: "session not found" }, 404);
7861
+ }
7862
+ const binding = conflictingBinding(channel);
7863
+ if (binding !== null) {
7864
+ console.error(`[webchat:inbound] op=send-refused key=session:${target.slice(0, 8)} reason=channel-conflict binding=${binding}`);
7865
+ return c.json({ error: "channel-conflict", binding }, 409);
7866
+ }
7867
+ deliveryKey = `session:${target}`;
7868
+ deliverySessionId = target;
7869
+ }
7870
+ if (isMultipart) {
7871
+ const kind = files.some((f) => isAudioMime(f.type)) ? "voice" : "files";
7872
+ if (files.length > MAX_FILES_PER_MESSAGE) {
7873
+ console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=too-many-files count=${files.length}`);
7874
+ return c.json({ error: `Maximum ${MAX_FILES_PER_MESSAGE} files per message.` }, 422);
7875
+ }
7876
+ const audioFile = files.find((f) => isAudioMime(f.type));
7877
+ const regularFiles = files.filter((f) => !isAudioMime(f.type));
7878
+ if (audioFile) {
7879
+ if (audioFile.size > MAX_FILE_SIZE_BYTES) {
7880
+ console.error(`[webchat:inbound] op=send-refused kind=voice reason=oversize bytes=${audioFile.size}`);
7881
+ return c.json({ error: "Recording too long. Try a shorter voice note." }, 422);
7882
+ }
7883
+ const result = await transcribeVoiceNote(audioFile, "admin");
7884
+ if (!result.ok) {
7885
+ console.error(`[webchat:inbound] op=send-refused kind=voice reason=stt-failed detail=${result.error}`);
7886
+ return c.json({ error: result.error }, 422);
7887
+ }
7888
+ text = result.result.text;
7889
+ }
7890
+ for (const file of regularFiles) {
7891
+ try {
7892
+ assertSupportedMime(file.type);
7893
+ if (file.size > MAX_FILE_SIZE_BYTES) {
7894
+ throw new Error(`File "${file.name}" exceeds the 50 MB limit (${(file.size / 1024 / 1024).toFixed(1)} MB).`);
7895
+ }
7896
+ } catch (err) {
7897
+ const detail = err instanceof Error ? err.message : "invalid file";
7898
+ console.error(`[webchat:inbound] op=send-refused kind=files reason=file-rejected detail=${detail}`);
7899
+ return c.json({ error: detail }, 422);
7900
+ }
7901
+ }
7902
+ const stored = [];
7903
+ try {
7904
+ for (const file of regularFiles) {
7905
+ stored.push(await storeAttachment(accountId, file));
7906
+ }
7907
+ } catch (err) {
7908
+ const detail = err instanceof Error ? err.message : String(err);
7909
+ console.error(`[webchat:inbound] op=send-refused kind=files reason=store-failed detail=${detail}`);
7910
+ return c.json({ error: "failed to store attachment" }, 500);
7911
+ }
7912
+ if (stored.length > 0) {
7913
+ const listing = stored.map((s) => `${s.filename} (${s.storagePath})`).join(", ");
7914
+ const note = `[The operator uploaded ${stored.length} file(s): ${listing}]`;
7915
+ text = text.length > 0 ? `${text}
7916
+
7917
+ ${note}` : note;
7918
+ }
7919
+ if (text.length === 0) {
7920
+ console.error(`[webchat:inbound] op=send-refused kind=${kind} reason=empty-text`);
7921
+ return c.json({ error: "text required" }, 400);
7922
+ }
7923
+ console.log(`[webchat:inbound] op=send-accepted kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
7924
+ }
7925
+ if (deliverySessionId !== void 0) {
7926
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId });
7927
+ } else {
7928
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text });
7929
+ }
7726
7930
  return c.json({ ok: true });
7727
7931
  });
7728
- app49.get("/session", requireAdminSession, (c) => {
7932
+ app49.post("/settings", requireAdminSession, async (c) => {
7933
+ const body = await c.req.json().catch(() => null);
7934
+ const op = body?.op;
7935
+ const value = body?.value;
7936
+ if (op !== "model" && op !== "effort") {
7937
+ console.error(`[webchat:settings] op=${String(op)} outcome=refused reason=unknown-op`);
7938
+ return c.json({ error: "op must be model or effort" }, 400);
7939
+ }
7940
+ if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !EFFORT_LEVELS.has(value)) {
7941
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${JSON.stringify(value)} reason=invalid-value`);
7942
+ return c.json({ error: `invalid ${op} value` }, 400);
7943
+ }
7944
+ let account;
7945
+ try {
7946
+ account = resolveAccount();
7947
+ } catch {
7948
+ account = null;
7949
+ }
7950
+ if (!account) {
7951
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
7952
+ return c.json({ error: "account unresolved" }, 503);
7953
+ }
7954
+ const accountJsonPath = join10(account.accountDir, "account.json");
7955
+ try {
7956
+ const parsed = JSON.parse(readFileSync11(accountJsonPath, "utf8"));
7957
+ if (op === "model") parsed.adminModel = value;
7958
+ else parsed.effort = value;
7959
+ const tmp = `${accountJsonPath}.${process.pid}.tmp`;
7960
+ writeFileSync5(tmp, JSON.stringify(parsed, null, 2), "utf8");
7961
+ renameSync(tmp, accountJsonPath);
7962
+ } catch (err) {
7963
+ const detail = err instanceof Error ? err.message : String(err);
7964
+ console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=write-failed detail=${detail}`);
7965
+ return c.json({ error: "persist failed" }, 500);
7966
+ }
7967
+ const settingsApplied = await reapplyLeversViaManager();
7968
+ console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
7969
+ return c.json({ ok: true, settingsApplied });
7970
+ });
7971
+ app49.get("/session", requireAdminSession, async (c) => {
7729
7972
  let accountId;
7730
7973
  try {
7731
7974
  accountId = resolvePlatformAccountId();
@@ -7734,6 +7977,15 @@ function createWebchatRoutes(deps) {
7734
7977
  console.error(`[webchat:inbound] op=session-refused reason=account-unresolved detail=${detail}`);
7735
7978
  return c.json({ error: "account unresolved" }, 503);
7736
7979
  }
7980
+ const target = c.req.query("session");
7981
+ if (target !== void 0) {
7982
+ if (!UUID_PATTERN.test(target)) {
7983
+ return c.json({ error: "invalid session id" }, 400);
7984
+ }
7985
+ const { projectDir: projectDir2, channel } = locateSession(target);
7986
+ const indicators2 = await fetchComposerIndicators(target);
7987
+ return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), ...indicators2 });
7988
+ }
7737
7989
  const sessionId = adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY);
7738
7990
  const cfg = claudeConfigDir();
7739
7991
  let projectDir = null;
@@ -7745,11 +7997,57 @@ function createWebchatRoutes(deps) {
7745
7997
  }
7746
7998
  }
7747
7999
  }
7748
- return c.json({ sessionId, projectDir });
8000
+ const indicators = await fetchComposerIndicators(sessionId);
8001
+ return c.json({ sessionId, projectDir, ...indicators, ...readLevers() });
7749
8002
  });
7750
8003
  return app49;
7751
8004
  }
7752
8005
 
8006
+ // server/routes/webchat-greeting.ts
8007
+ import { resolve as resolve10 } from "path";
8008
+
8009
+ // app/lib/claude-agent/specialist-roster.ts
8010
+ import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
8011
+ import { join as join11 } from "path";
8012
+ function field(fm, name) {
8013
+ const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
8014
+ if (!m) return null;
8015
+ let value = m[1].trim();
8016
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
8017
+ value = value.slice(1, -1);
8018
+ }
8019
+ return value || null;
8020
+ }
8021
+ function readSpecialistRoster(specialistsDir) {
8022
+ if (!existsSync8(specialistsDir)) return { specialists: [], skipped: [] };
8023
+ const entries = readdirSync7(specialistsDir);
8024
+ const specialists = [];
8025
+ const skipped = [];
8026
+ for (const file of entries.sort()) {
8027
+ if (!file.endsWith(".md")) continue;
8028
+ let raw;
8029
+ try {
8030
+ raw = readFileSync12(join11(specialistsDir, file), "utf-8");
8031
+ } catch (err) {
8032
+ skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
8033
+ continue;
8034
+ }
8035
+ const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
8036
+ if (!fm) {
8037
+ skipped.push({ file, reason: "no-frontmatter" });
8038
+ continue;
8039
+ }
8040
+ const name = field(fm[1], "name");
8041
+ if (!name) {
8042
+ skipped.push({ file, reason: "missing-name" });
8043
+ continue;
8044
+ }
8045
+ const summary = field(fm[1], "summary") ?? field(fm[1], "description") ?? "";
8046
+ specialists.push({ name, summary });
8047
+ }
8048
+ return { specialists, skipped };
8049
+ }
8050
+
7753
8051
  // server/routes/webchat-greeting.ts
7754
8052
  var OUTSTANDING_TASK_STATUSES = ["pending", "active", "running"];
7755
8053
  var UPCOMING_EVENT_STATUSES = ["scheduled", "due"];
@@ -7808,10 +8106,25 @@ app6.get("/", requireAdminSession, async (c) => {
7808
8106
  return { events: events2, tasks: tasks2 };
7809
8107
  }
7810
8108
  );
8109
+ let specialists = [];
8110
+ try {
8111
+ const roster = readSpecialistRoster(
8112
+ resolve10(ACCOUNTS_DIR, accountId, "specialists", "agents")
8113
+ );
8114
+ specialists = roster.specialists;
8115
+ for (const s of roster.skipped) {
8116
+ console.warn(
8117
+ `[webchat:greeting] op=specialist-skipped file=${s.file} reason=${s.reason}`
8118
+ );
8119
+ }
8120
+ } catch (err) {
8121
+ const detail = err instanceof Error ? err.message : String(err);
8122
+ console.error(`[webchat:greeting] op=specialists-read-failed reason=${detail}`);
8123
+ }
7811
8124
  console.log(
7812
- `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} ms=${Date.now() - started}`
8125
+ `[webchat:greeting] op=read account=${accountId.slice(0, 8)} events=${events.length} tasks=${tasks.total} specialists=${specialists.length} ms=${Date.now() - started}`
7813
8126
  );
7814
- return c.json({ ok: true, events, tasks });
8127
+ return c.json({ ok: true, events, tasks, specialists });
7815
8128
  } catch (err) {
7816
8129
  const detail = err instanceof Error ? err.message : String(err);
7817
8130
  console.error(`[webchat:greeting] op=read-failed reason=${detail}`);
@@ -7831,8 +8144,8 @@ var webchat_greeting_default = app6;
7831
8144
 
7832
8145
  // server/routes/telegram.ts
7833
8146
  import { homedir } from "os";
7834
- import { resolve as resolve10, join as join11 } from "path";
7835
- import { existsSync as existsSync8, readFileSync as readFileSync11 } from "fs";
8147
+ import { resolve as resolve11, join as join12 } from "path";
8148
+ import { existsSync as existsSync9, readFileSync as readFileSync13 } from "fs";
7836
8149
 
7837
8150
  // app/lib/telegram/access-control.ts
7838
8151
  function checkTelegramAccess(params) {
@@ -7882,11 +8195,11 @@ function routeTelegramUpdate(input) {
7882
8195
  var TAG22 = "[telegram-inbound]";
7883
8196
  var DISPATCH_TIMEOUT_MS = 12e4;
7884
8197
  function configDirName() {
7885
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve10(process.cwd(), "..");
7886
- const brandPath = join11(platformRoot2, "config", "brand.json");
7887
- if (existsSync8(brandPath)) {
8198
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve11(process.cwd(), "..");
8199
+ const brandPath = join12(platformRoot2, "config", "brand.json");
8200
+ if (existsSync9(brandPath)) {
7888
8201
  try {
7889
- return JSON.parse(readFileSync11(brandPath, "utf-8")).configDir ?? ".maxy";
8202
+ return JSON.parse(readFileSync13(brandPath, "utf-8")).configDir ?? ".maxy";
7890
8203
  } catch {
7891
8204
  }
7892
8205
  }
@@ -7894,7 +8207,7 @@ function configDirName() {
7894
8207
  }
7895
8208
  function secretPath(botType) {
7896
8209
  const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
7897
- return resolve10(homedir(), configDirName(), filename);
8210
+ return resolve11(homedir(), configDirName(), filename);
7898
8211
  }
7899
8212
  async function sendTelegram(botToken, chatId, text) {
7900
8213
  try {
@@ -7918,11 +8231,11 @@ app7.post("/", async (c) => {
7918
8231
  return c.json({ ok: false }, 400);
7919
8232
  }
7920
8233
  const sp = secretPath(botType);
7921
- if (!existsSync8(sp)) {
8234
+ if (!existsSync9(sp)) {
7922
8235
  console.error(`${TAG22} op=reject reason=no-secret-file botType=${botType}`);
7923
8236
  return c.json({ ok: false }, 401);
7924
8237
  }
7925
- const expected = readFileSync11(sp, "utf-8").trim();
8238
+ const expected = readFileSync13(sp, "utf-8").trim();
7926
8239
  const got = c.req.header("x-telegram-bot-api-secret-token") ?? "";
7927
8240
  if (got !== expected) {
7928
8241
  console.error(`${TAG22} op=reject reason=bad-secret botType=${botType}`);
@@ -7985,12 +8298,12 @@ var telegram_default = app7;
7985
8298
 
7986
8299
  // server/routes/onboarding.ts
7987
8300
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
7988
- import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync6, writeSync, existsSync as existsSync10, readFileSync as readFileSync13, unlinkSync } from "fs";
8301
+ import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, readFileSync as readFileSync15, unlinkSync } from "fs";
7989
8302
  import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
7990
8303
 
7991
8304
  // ../lib/admins-write/src/index.ts
7992
- import { existsSync as existsSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync5, renameSync, mkdirSync as mkdirSync2, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
7993
- import { dirname as dirname3, join as join12 } from "path";
8305
+ import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync6, renameSync as renameSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
8306
+ import { dirname as dirname3, join as join13 } from "path";
7994
8307
  function logLine(input, result) {
7995
8308
  const userIdShort = input.userId.slice(0, 8);
7996
8309
  console.error(
@@ -8000,15 +8313,15 @@ function logLine(input, result) {
8000
8313
  function writeFileAtomic(filePath, contents, mode) {
8001
8314
  mkdirSync2(dirname3(filePath), { recursive: true });
8002
8315
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
8003
- writeFileSync5(tempPath, contents, mode !== void 0 ? { mode } : void 0);
8004
- renameSync(tempPath, filePath);
8316
+ writeFileSync6(tempPath, contents, mode !== void 0 ? { mode } : void 0);
8317
+ renameSync2(tempPath, filePath);
8005
8318
  }
8006
8319
  function writeAdminEntry(input) {
8007
8320
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
8008
8321
  try {
8009
8322
  let users = [];
8010
- if (existsSync9(input.usersFile)) {
8011
- const raw = readFileSync12(input.usersFile, "utf-8").trim();
8323
+ if (existsSync10(input.usersFile)) {
8324
+ const raw = readFileSync14(input.usersFile, "utf-8").trim();
8012
8325
  if (raw) {
8013
8326
  const parsed = JSON.parse(raw);
8014
8327
  if (!Array.isArray(parsed)) {
@@ -8032,11 +8345,11 @@ function writeAdminEntry(input) {
8032
8345
  return result;
8033
8346
  }
8034
8347
  try {
8035
- const accountJsonPath = join12(input.accountDir, "account.json");
8036
- if (!existsSync9(accountJsonPath)) {
8348
+ const accountJsonPath = join13(input.accountDir, "account.json");
8349
+ if (!existsSync10(accountJsonPath)) {
8037
8350
  throw new Error(`account.json not found at ${accountJsonPath}`);
8038
8351
  }
8039
- const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
8352
+ const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
8040
8353
  const admins = config.admins ?? [];
8041
8354
  if (admins.some((a) => a.userId === input.userId)) {
8042
8355
  result.accountJsonResult = "noop";
@@ -8060,9 +8373,9 @@ function checkAdminAuthInvariant(input) {
8060
8373
  usersWithoutAccount: []
8061
8374
  };
8062
8375
  const usersUserIds = /* @__PURE__ */ new Set();
8063
- if (existsSync9(input.usersFile)) {
8376
+ if (existsSync10(input.usersFile)) {
8064
8377
  try {
8065
- const raw = readFileSync12(input.usersFile, "utf-8").trim();
8378
+ const raw = readFileSync14(input.usersFile, "utf-8").trim();
8066
8379
  if (raw) {
8067
8380
  const users = JSON.parse(raw);
8068
8381
  for (const u of users) {
@@ -8075,10 +8388,10 @@ function checkAdminAuthInvariant(input) {
8075
8388
  }
8076
8389
  }
8077
8390
  const accountUserIds = /* @__PURE__ */ new Set();
8078
- if (existsSync9(input.accountsDir)) {
8391
+ if (existsSync10(input.accountsDir)) {
8079
8392
  let entries;
8080
8393
  try {
8081
- entries = readdirSync7(input.accountsDir);
8394
+ entries = readdirSync8(input.accountsDir);
8082
8395
  } catch (err) {
8083
8396
  const msg = err instanceof Error ? err.message : String(err);
8084
8397
  console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
@@ -8087,17 +8400,17 @@ function checkAdminAuthInvariant(input) {
8087
8400
  }
8088
8401
  for (const entry of entries) {
8089
8402
  if (entry.startsWith(".")) continue;
8090
- const accountDir = join12(input.accountsDir, entry);
8403
+ const accountDir = join13(input.accountsDir, entry);
8091
8404
  try {
8092
8405
  if (!statSync5(accountDir).isDirectory()) continue;
8093
8406
  } catch {
8094
8407
  continue;
8095
8408
  }
8096
- const accountJsonPath = join12(accountDir, "account.json");
8097
- if (!existsSync9(accountJsonPath)) continue;
8409
+ const accountJsonPath = join13(accountDir, "account.json");
8410
+ if (!existsSync10(accountJsonPath)) continue;
8098
8411
  let admins = [];
8099
8412
  try {
8100
- const config = JSON.parse(readFileSync12(accountJsonPath, "utf-8"));
8413
+ const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
8101
8414
  admins = config.admins ?? [];
8102
8415
  } catch (err) {
8103
8416
  const msg = err instanceof Error ? err.message : String(err);
@@ -8137,8 +8450,8 @@ function hashPin2(pin) {
8137
8450
  return createHash3("sha256").update(pin).digest("hex");
8138
8451
  }
8139
8452
  function readUsersFile2() {
8140
- if (!existsSync10(USERS_FILE)) return null;
8141
- const raw = readFileSync13(USERS_FILE, "utf-8").trim();
8453
+ if (!existsSync11(USERS_FILE)) return null;
8454
+ const raw = readFileSync15(USERS_FILE, "utf-8").trim();
8142
8455
  if (!raw) return [];
8143
8456
  return JSON.parse(raw);
8144
8457
  }
@@ -8191,7 +8504,7 @@ app8.post("/claude-auth", async (c) => {
8191
8504
  } catch (err) {
8192
8505
  logoutError = err instanceof Error ? err.message : String(err);
8193
8506
  }
8194
- const credentialsPresent = existsSync10(CLAUDE_CREDENTIALS_FILE);
8507
+ const credentialsPresent = existsSync11(CLAUDE_CREDENTIALS_FILE);
8195
8508
  const ranMs = Date.now() - start;
8196
8509
  console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
8197
8510
  return c.json({ logged_out: !credentialsPresent });
@@ -8209,7 +8522,7 @@ app8.post("/claude-auth", async (c) => {
8209
8522
  return c.json({ launched: cdpReady });
8210
8523
  }
8211
8524
  ensureLogDir();
8212
- writeFileSync6(logPath("claude-auth"), "");
8525
+ writeFileSync7(logPath("claude-auth"), "");
8213
8526
  const claudeAuthLogFd = openSync2(logPath("claude-auth"), "a");
8214
8527
  const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
8215
8528
  if (process.platform === "darwin") {
@@ -8298,9 +8611,9 @@ app8.post("/set-pin", async (c) => {
8298
8611
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
8299
8612
  if (process.platform === "linux") {
8300
8613
  let installOwner = null;
8301
- if (existsSync10(INSTALL_OWNER_FILE)) {
8614
+ if (existsSync11(INSTALL_OWNER_FILE)) {
8302
8615
  try {
8303
- const raw = readFileSync13(INSTALL_OWNER_FILE, "utf-8").trim();
8616
+ const raw = readFileSync15(INSTALL_OWNER_FILE, "utf-8").trim();
8304
8617
  if (raw.length > 0) installOwner = raw;
8305
8618
  } catch (err) {
8306
8619
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -8373,7 +8686,7 @@ app8.delete("/set-pin", async (c) => {
8373
8686
  unlinkSync(USERS_FILE);
8374
8687
  console.log(`[set-pin] cleared users.json (last entry removed): userId=${matchedUser.userId.slice(0, 8)}\u2026`);
8375
8688
  } else {
8376
- writeFileSync6(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
8689
+ writeFileSync7(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
8377
8690
  console.log(`[set-pin] removed entry from users.json: userId=${matchedUser.userId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
8378
8691
  }
8379
8692
  return c.json({ ok: true });
@@ -8381,9 +8694,9 @@ app8.delete("/set-pin", async (c) => {
8381
8694
  var onboarding_default = app8;
8382
8695
 
8383
8696
  // server/routes/client-error.ts
8384
- import { appendFileSync, existsSync as existsSync11, renameSync as renameSync2, statSync as statSync6 } from "fs";
8385
- import { join as join13 } from "path";
8386
- var CLIENT_ERRORS_LOG = join13(LOG_DIR, "client-errors.log");
8697
+ import { appendFileSync, existsSync as existsSync12, renameSync as renameSync3, statSync as statSync6 } from "fs";
8698
+ import { join as join14 } from "path";
8699
+ var CLIENT_ERRORS_LOG = join14(LOG_DIR, "client-errors.log");
8387
8700
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
8388
8701
  var MAX_BODY_SIZE = 8 * 1024;
8389
8702
  var MAX_STACK_LEN = 2e3;
@@ -8426,10 +8739,10 @@ function stackHead(stack) {
8426
8739
  }
8427
8740
  function rotateIfNeeded() {
8428
8741
  try {
8429
- if (!existsSync11(CLIENT_ERRORS_LOG)) return;
8742
+ if (!existsSync12(CLIENT_ERRORS_LOG)) return;
8430
8743
  const stats = statSync6(CLIENT_ERRORS_LOG);
8431
8744
  if (stats.size < MAX_LOG_SIZE) return;
8432
- renameSync2(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
8745
+ renameSync3(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
8433
8746
  } catch (err) {
8434
8747
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
8435
8748
  }
@@ -8708,18 +9021,18 @@ app10.post("/", async (c) => {
8708
9021
  var session_default = app10;
8709
9022
 
8710
9023
  // server/routes/admin/logs.ts
8711
- import { existsSync as existsSync13, readdirSync as readdirSync8, readFileSync as readFileSync14, statSync as statSync7 } from "fs";
8712
- import { resolve as resolve11, basename as basename4 } from "path";
9024
+ import { existsSync as existsSync14, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
9025
+ import { resolve as resolve12, basename as basename4 } from "path";
8713
9026
 
8714
9027
  // app/lib/logs-read-resolve.ts
8715
- import { existsSync as existsSync12 } from "fs";
8716
- import { join as join14 } from "path";
9028
+ import { existsSync as existsSync13 } from "fs";
9029
+ import { join as join15 } from "path";
8717
9030
  function resolveSessionLogPaths(filename, logDirs) {
8718
9031
  const tried = [filename];
8719
9032
  const hits = [];
8720
9033
  for (const dir of logDirs) {
8721
- const fullPath = join14(dir, filename);
8722
- if (existsSync12(fullPath)) {
9034
+ const fullPath = join15(dir, filename);
9035
+ if (existsSync13(fullPath)) {
8723
9036
  hits.push({ path: fullPath, dir });
8724
9037
  }
8725
9038
  }
@@ -8736,7 +9049,7 @@ app11.get("/", async (c) => {
8736
9049
  const cacheKeyParam = c.req.query("cacheKey");
8737
9050
  const download = c.req.query("download") === "1";
8738
9051
  const account = resolveAccount();
8739
- const accountLogDir = account ? resolve11(account.accountDir, "logs") : null;
9052
+ const accountLogDir = account ? resolve12(account.accountDir, "logs") : null;
8740
9053
  const logDirs = [];
8741
9054
  if (accountLogDir) logDirs.push(accountLogDir);
8742
9055
  logDirs.push(LOG_DIR);
@@ -8744,10 +9057,10 @@ app11.get("/", async (c) => {
8744
9057
  const safe = basename4(fileParam);
8745
9058
  const searched = [];
8746
9059
  for (const dir of logDirs) {
8747
- const filePath = resolve11(dir, safe);
9060
+ const filePath = resolve12(dir, safe);
8748
9061
  searched.push(filePath);
8749
9062
  try {
8750
- const buffer = readFileSync14(filePath);
9063
+ const buffer = readFileSync16(filePath);
8751
9064
  const onDiskBytes = statSync7(filePath).size;
8752
9065
  const headers = {
8753
9066
  "Content-Type": "text/plain; charset=utf-8",
@@ -8812,7 +9125,7 @@ app11.get("/", async (c) => {
8812
9125
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
8813
9126
  try {
8814
9127
  const filename = basename4(hit.path);
8815
- const buffer = readFileSync14(hit.path);
9128
+ const buffer = readFileSync16(hit.path);
8816
9129
  const onDiskBytes = statSync7(hit.path).size;
8817
9130
  const headers = {
8818
9131
  "Content-Type": "text/plain; charset=utf-8",
@@ -8847,19 +9160,19 @@ app11.get("/", async (c) => {
8847
9160
  const seen = /* @__PURE__ */ new Set();
8848
9161
  const logs = {};
8849
9162
  for (const dir of logDirs) {
8850
- if (!existsSync13(dir)) continue;
9163
+ if (!existsSync14(dir)) continue;
8851
9164
  let files;
8852
9165
  try {
8853
- files = readdirSync8(dir).filter((f) => f.endsWith(".log"));
9166
+ files = readdirSync9(dir).filter((f) => f.endsWith(".log"));
8854
9167
  } catch (err) {
8855
9168
  const reason = err instanceof Error ? err.message : String(err);
8856
9169
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
8857
9170
  continue;
8858
9171
  }
8859
- files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve11(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9172
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve12(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
8860
9173
  seen.add(name);
8861
9174
  try {
8862
- const content = readFileSync14(resolve11(dir, name));
9175
+ const content = readFileSync16(resolve12(dir, name));
8863
9176
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
8864
9177
  logs[name] = tail.trim() || "(empty)";
8865
9178
  } catch (err) {
@@ -8898,8 +9211,8 @@ var claude_info_default = app12;
8898
9211
 
8899
9212
  // server/routes/admin/attachment.ts
8900
9213
  import { readFile as readFile2, readdir } from "fs/promises";
8901
- import { existsSync as existsSync14 } from "fs";
8902
- import { resolve as resolve12 } from "path";
9214
+ import { existsSync as existsSync15 } from "fs";
9215
+ import { resolve as resolve13 } from "path";
8903
9216
  var app13 = new Hono();
8904
9217
  app13.get("/:attachmentId", requireAdminSession, async (c) => {
8905
9218
  const attachmentId = c.req.param("attachmentId");
@@ -8911,12 +9224,12 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8911
9224
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
8912
9225
  return new Response("Not found", { status: 404 });
8913
9226
  }
8914
- const dir = resolve12(ATTACHMENTS_ROOT, accountId, attachmentId);
8915
- if (!existsSync14(dir)) {
9227
+ const dir = resolve13(ATTACHMENTS_ROOT, accountId, attachmentId);
9228
+ if (!existsSync15(dir)) {
8916
9229
  return new Response("Not found", { status: 404 });
8917
9230
  }
8918
- const metaPath = resolve12(dir, `${attachmentId}.meta.json`);
8919
- if (!existsSync14(metaPath)) {
9231
+ const metaPath = resolve13(dir, `${attachmentId}.meta.json`);
9232
+ if (!existsSync15(metaPath)) {
8920
9233
  return new Response("Not found", { status: 404 });
8921
9234
  }
8922
9235
  let meta;
@@ -8930,7 +9243,7 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8930
9243
  if (!dataFile) {
8931
9244
  return new Response("Not found", { status: 404 });
8932
9245
  }
8933
- const filePath = resolve12(dir, dataFile);
9246
+ const filePath = resolve13(dir, dataFile);
8934
9247
  const buffer = await readFile2(filePath);
8935
9248
  return new Response(new Uint8Array(buffer), {
8936
9249
  headers: {
@@ -8943,24 +9256,24 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
8943
9256
  var attachment_default = app13;
8944
9257
 
8945
9258
  // server/routes/admin/agents.ts
8946
- import { resolve as resolve13 } from "path";
8947
- import { readdirSync as readdirSync9, readFileSync as readFileSync15, existsSync as existsSync15, rmSync } from "fs";
9259
+ import { resolve as resolve14 } from "path";
9260
+ import { readdirSync as readdirSync10, readFileSync as readFileSync17, existsSync as existsSync16, rmSync } from "fs";
8948
9261
  var app14 = new Hono();
8949
9262
  app14.get("/", (c) => {
8950
9263
  const account = resolveAccount();
8951
9264
  if (!account) return c.json({ agents: [] });
8952
- const agentsDir = resolve13(account.accountDir, "agents");
8953
- if (!existsSync15(agentsDir)) return c.json({ agents: [] });
9265
+ const agentsDir = resolve14(account.accountDir, "agents");
9266
+ if (!existsSync16(agentsDir)) return c.json({ agents: [] });
8954
9267
  const agents = [];
8955
9268
  try {
8956
- const entries = readdirSync9(agentsDir, { withFileTypes: true });
9269
+ const entries = readdirSync10(agentsDir, { withFileTypes: true });
8957
9270
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
8958
9271
  if (!entry.isDirectory()) continue;
8959
9272
  if (entry.name === "admin") continue;
8960
- const configPath2 = resolve13(agentsDir, entry.name, "config.json");
8961
- if (!existsSync15(configPath2)) continue;
9273
+ const configPath2 = resolve14(agentsDir, entry.name, "config.json");
9274
+ if (!existsSync16(configPath2)) continue;
8962
9275
  try {
8963
- const config = JSON.parse(readFileSync15(configPath2, "utf-8"));
9276
+ const config = JSON.parse(readFileSync17(configPath2, "utf-8"));
8964
9277
  agents.push({
8965
9278
  slug: entry.name,
8966
9279
  displayName: config.displayName ?? entry.name,
@@ -8986,8 +9299,8 @@ app14.delete("/:slug", async (c) => {
8986
9299
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
8987
9300
  return c.json({ error: "Invalid agent slug" }, 400);
8988
9301
  }
8989
- const agentDir = resolve13(account.accountDir, "agents", slug);
8990
- if (!existsSync15(agentDir)) {
9302
+ const agentDir = resolve14(account.accountDir, "agents", slug);
9303
+ if (!existsSync16(agentDir)) {
8991
9304
  return c.json({ error: "Agent not found" }, 404);
8992
9305
  }
8993
9306
  try {
@@ -9016,8 +9329,8 @@ app14.post("/:slug/project", async (c) => {
9016
9329
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9017
9330
  return c.json({ error: "Invalid agent slug" }, 400);
9018
9331
  }
9019
- const agentDir = resolve13(account.accountDir, "agents", slug);
9020
- if (!existsSync15(agentDir)) {
9332
+ const agentDir = resolve14(account.accountDir, "agents", slug);
9333
+ if (!existsSync16(agentDir)) {
9021
9334
  return c.json({ error: "Agent not found on disk" }, 404);
9022
9335
  }
9023
9336
  try {
@@ -9033,7 +9346,7 @@ var agents_default = app14;
9033
9346
  // server/routes/admin/sessions.ts
9034
9347
  import crypto2 from "crypto";
9035
9348
  import { resolve as resolvePath } from "path";
9036
- import { existsSync as existsSync16, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9349
+ import { existsSync as existsSync17, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9037
9350
 
9038
9351
  // ../lib/admin-conversation-purge/src/index.ts
9039
9352
  async function purgeAdminConversationJsonls(args) {
@@ -9193,7 +9506,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
9193
9506
  let reason = null;
9194
9507
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
9195
9508
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
9196
- else if (!existsSync16(a.storagePath)) reason = "missing-file";
9509
+ else if (!existsSync17(a.storagePath)) reason = "missing-file";
9197
9510
  if (reason) {
9198
9511
  invalid++;
9199
9512
  try {
@@ -9719,8 +10032,8 @@ app15.put("/:id/label", requireAdminSession, async (c) => {
9719
10032
  var sessions_default = app15;
9720
10033
 
9721
10034
  // app/lib/claude-agent/spawn-context.ts
9722
- import { existsSync as existsSync17, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
9723
- import { dirname as dirname4, resolve as resolve14, join as join15 } from "path";
10035
+ import { existsSync as existsSync18, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync8 } from "fs";
10036
+ import { dirname as dirname4, resolve as resolve15, join as join16 } from "path";
9724
10037
  async function resolveOwnerProfileBlock(accountId, userId) {
9725
10038
  if (!userId) return { ok: false, reason: "missing-user-id" };
9726
10039
  try {
@@ -9734,10 +10047,10 @@ async function resolveOwnerProfileBlock(accountId, userId) {
9734
10047
  return { ok: false, reason: "neo4j-unreachable" };
9735
10048
  }
9736
10049
  }
9737
- function frontmatterField(manifest, field) {
10050
+ function frontmatterField(manifest, field2) {
9738
10051
  const fm = manifest.match(/^---\r?\n([\s\S]*?)\r?\n---/);
9739
10052
  if (!fm) return null;
9740
- const re = new RegExp(`^${field}:\\s*(.*?)\\r?$`, "m");
10053
+ const re = new RegExp(`^${field2}:\\s*(.*?)\\r?$`, "m");
9741
10054
  const m = fm[1].match(re);
9742
10055
  if (!m) return null;
9743
10056
  let value = m[1].trim();
@@ -9749,14 +10062,14 @@ function frontmatterField(manifest, field) {
9749
10062
  function extractPluginToolDescriptions(pluginDir) {
9750
10063
  const out = /* @__PURE__ */ new Map();
9751
10064
  const candidates = [
9752
- join15(pluginDir, "mcp/dist/index.js"),
9753
- join15(pluginDir, "mcp/src/index.ts")
10065
+ join16(pluginDir, "mcp/dist/index.js"),
10066
+ join16(pluginDir, "mcp/src/index.ts")
9754
10067
  ];
9755
10068
  let raw = null;
9756
10069
  for (const path2 of candidates) {
9757
- if (!existsSync17(path2)) continue;
10070
+ if (!existsSync18(path2)) continue;
9758
10071
  try {
9759
- raw = readFileSync16(path2, "utf-8");
10072
+ raw = readFileSync18(path2, "utf-8");
9760
10073
  break;
9761
10074
  } catch {
9762
10075
  }
@@ -9805,24 +10118,24 @@ function parseSkillPathsFromFrontmatter(fm) {
9805
10118
  }
9806
10119
  function listPluginDirs() {
9807
10120
  const out = /* @__PURE__ */ new Map();
9808
- const platformPlugins = resolve14(PLATFORM_ROOT, "plugins");
9809
- if (existsSync17(platformPlugins)) {
9810
- for (const name of readdirSync10(platformPlugins)) {
9811
- const dir = join15(platformPlugins, name);
10121
+ const platformPlugins = resolve15(PLATFORM_ROOT, "plugins");
10122
+ if (existsSync18(platformPlugins)) {
10123
+ for (const name of readdirSync11(platformPlugins)) {
10124
+ const dir = join16(platformPlugins, name);
9812
10125
  try {
9813
10126
  if (statSync8(dir).isDirectory()) out.set(name, dir);
9814
10127
  } catch {
9815
10128
  }
9816
10129
  }
9817
10130
  }
9818
- const premiumRoot = resolve14(dirname4(PLATFORM_ROOT), "premium-plugins");
9819
- if (existsSync17(premiumRoot)) {
9820
- for (const bundle of readdirSync10(premiumRoot)) {
9821
- const bundlePlugins = join15(premiumRoot, bundle, "plugins");
9822
- if (!existsSync17(bundlePlugins)) continue;
10131
+ const premiumRoot = resolve15(dirname4(PLATFORM_ROOT), "premium-plugins");
10132
+ if (existsSync18(premiumRoot)) {
10133
+ for (const bundle of readdirSync11(premiumRoot)) {
10134
+ const bundlePlugins = join16(premiumRoot, bundle, "plugins");
10135
+ if (!existsSync18(bundlePlugins)) continue;
9823
10136
  try {
9824
- for (const name of readdirSync10(bundlePlugins)) {
9825
- const dir = join15(bundlePlugins, name);
10137
+ for (const name of readdirSync11(bundlePlugins)) {
10138
+ const dir = join16(bundlePlugins, name);
9826
10139
  try {
9827
10140
  if (statSync8(dir).isDirectory()) out.set(name, dir);
9828
10141
  } catch {
@@ -9835,10 +10148,10 @@ function listPluginDirs() {
9835
10148
  return out;
9836
10149
  }
9837
10150
  function readEnabledPlugins(accountId) {
9838
- const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9839
- if (!existsSync17(accountFile)) return /* @__PURE__ */ new Set();
10151
+ const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10152
+ if (!existsSync18(accountFile)) return /* @__PURE__ */ new Set();
9840
10153
  try {
9841
- const parsed = JSON.parse(readFileSync16(accountFile, "utf-8"));
10154
+ const parsed = JSON.parse(readFileSync18(accountFile, "utf-8"));
9842
10155
  return new Set(
9843
10156
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
9844
10157
  );
@@ -9847,10 +10160,10 @@ function readEnabledPlugins(accountId) {
9847
10160
  }
9848
10161
  }
9849
10162
  function readFrontmatter(path2) {
9850
- if (!existsSync17(path2)) return null;
10163
+ if (!existsSync18(path2)) return null;
9851
10164
  let raw;
9852
10165
  try {
9853
- raw = readFileSync16(path2, "utf-8");
10166
+ raw = readFileSync18(path2, "utf-8");
9854
10167
  } catch {
9855
10168
  return null;
9856
10169
  }
@@ -9865,7 +10178,7 @@ function computeActivePlugins(accountId) {
9865
10178
  for (const name of Array.from(enabled).sort()) {
9866
10179
  const dir = pluginDirs.get(name);
9867
10180
  if (!dir) continue;
9868
- const fm = readFrontmatter(join15(dir, "PLUGIN.md"));
10181
+ const fm = readFrontmatter(join16(dir, "PLUGIN.md"));
9869
10182
  if (!fm) continue;
9870
10183
  const description = frontmatterField(`---
9871
10184
  ${fm}
@@ -9882,7 +10195,7 @@ ${fm}
9882
10195
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
9883
10196
  );
9884
10197
  if (toolNames.length > 0 && descMap.size === 0) {
9885
- const hasSource = existsSync17(join15(dir, "mcp/dist/index.js")) || existsSync17(join15(dir, "mcp/src/index.ts"));
10198
+ const hasSource = existsSync18(join16(dir, "mcp/dist/index.js")) || existsSync18(join16(dir, "mcp/src/index.ts"));
9886
10199
  if (hasSource) {
9887
10200
  console.warn(
9888
10201
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -9892,7 +10205,7 @@ ${fm}
9892
10205
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
9893
10206
  const skills = [];
9894
10207
  for (const relPath of skillPaths) {
9895
- const skillPath = join15(dir, relPath);
10208
+ const skillPath = join16(dir, relPath);
9896
10209
  const skillFm = readFrontmatter(skillPath);
9897
10210
  if (!skillFm) continue;
9898
10211
  const skillName = frontmatterField(`---
@@ -9908,11 +10221,11 @@ ${skillFm}
9908
10221
  return out;
9909
10222
  }
9910
10223
  function computeSpecialistDomains(accountId) {
9911
- const specialistsDir = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
9912
- if (!existsSync17(specialistsDir)) return [];
10224
+ const specialistsDir = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
10225
+ if (!existsSync18(specialistsDir)) return [];
9913
10226
  let entries;
9914
10227
  try {
9915
- entries = readdirSync10(specialistsDir);
10228
+ entries = readdirSync11(specialistsDir);
9916
10229
  } catch {
9917
10230
  return [];
9918
10231
  }
@@ -9936,7 +10249,7 @@ function computeSpecialistDomains(accountId) {
9936
10249
  const out = [];
9937
10250
  for (const file of entries.sort()) {
9938
10251
  if (!file.endsWith(".md")) continue;
9939
- const fm = readFrontmatter(join15(specialistsDir, file));
10252
+ const fm = readFrontmatter(join16(specialistsDir, file));
9940
10253
  if (!fm) continue;
9941
10254
  const wrapped = `---
9942
10255
  ${fm}
@@ -9954,11 +10267,11 @@ ${fm}
9954
10267
  return out;
9955
10268
  }
9956
10269
  function computeDormantPlugins(accountId) {
9957
- const accountFile = resolve14(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
9958
- if (!existsSync17(accountFile)) return [];
10270
+ const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10271
+ if (!existsSync18(accountFile)) return [];
9959
10272
  let enabled;
9960
10273
  try {
9961
- const raw = readFileSync16(accountFile, "utf-8");
10274
+ const raw = readFileSync18(accountFile, "utf-8");
9962
10275
  const parsed = JSON.parse(raw);
9963
10276
  enabled = new Set(
9964
10277
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
@@ -9969,22 +10282,22 @@ function computeDormantPlugins(accountId) {
9969
10282
  );
9970
10283
  return [];
9971
10284
  }
9972
- const pluginsDir = resolve14(PLATFORM_ROOT, "plugins");
9973
- if (!existsSync17(pluginsDir)) return [];
10285
+ const pluginsDir = resolve15(PLATFORM_ROOT, "plugins");
10286
+ if (!existsSync18(pluginsDir)) return [];
9974
10287
  let entries;
9975
10288
  try {
9976
- entries = readdirSync10(pluginsDir);
10289
+ entries = readdirSync11(pluginsDir);
9977
10290
  } catch {
9978
10291
  return [];
9979
10292
  }
9980
10293
  const out = [];
9981
10294
  for (const name of entries) {
9982
10295
  if (enabled.has(name)) continue;
9983
- const manifestPath = resolve14(pluginsDir, name, "PLUGIN.md");
9984
- if (!existsSync17(manifestPath)) continue;
10296
+ const manifestPath = resolve15(pluginsDir, name, "PLUGIN.md");
10297
+ if (!existsSync18(manifestPath)) continue;
9985
10298
  let manifest;
9986
10299
  try {
9987
- manifest = readFileSync16(manifestPath, "utf-8");
10300
+ manifest = readFileSync18(manifestPath, "utf-8");
9988
10301
  } catch {
9989
10302
  continue;
9990
10303
  }
@@ -9998,13 +10311,13 @@ function computeDormantPlugins(accountId) {
9998
10311
  }
9999
10312
 
10000
10313
  // server/routes/admin/claude-sessions.ts
10001
- import { existsSync as existsSync18, readFileSync as readFileSync17 } from "fs";
10002
- import { resolve as resolve15 } from "path";
10314
+ import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
10315
+ import { resolve as resolve16 } from "path";
10003
10316
  function readTunnelState(brandConfigDir) {
10004
10317
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
10005
- if (!existsSync18(statePath)) return null;
10318
+ if (!existsSync19(statePath)) return null;
10006
10319
  try {
10007
- const parsed = JSON.parse(readFileSync17(statePath, "utf-8"));
10320
+ const parsed = JSON.parse(readFileSync19(statePath, "utf-8"));
10008
10321
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
10009
10322
  const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
10010
10323
  const domain = typeof parsed.domain === "string" ? parsed.domain : null;
@@ -10015,10 +10328,10 @@ function readTunnelState(brandConfigDir) {
10015
10328
  }
10016
10329
  }
10017
10330
  function resolveTunnelUrl() {
10018
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve15(process.cwd(), "..");
10331
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
10019
10332
  let brand;
10020
10333
  try {
10021
- brand = JSON.parse(readFileSync17(resolve15(platformRoot2, "config", "brand.json"), "utf-8"));
10334
+ brand = JSON.parse(readFileSync19(resolve16(platformRoot2, "config", "brand.json"), "utf-8"));
10022
10335
  } catch {
10023
10336
  return null;
10024
10337
  }
@@ -10263,15 +10576,15 @@ var events_default = app18;
10263
10576
  import { createReadStream as createReadStream2 } from "fs";
10264
10577
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
10265
10578
  import { realpathSync as realpathSync4 } from "fs";
10266
- import { basename as basename6, dirname as dirname5, join as join17, resolve as resolve18, sep as sep5 } from "path";
10579
+ import { basename as basename6, dirname as dirname5, join as join18, resolve as resolve19, sep as sep5 } from "path";
10267
10580
  import { Readable as Readable2 } from "stream";
10268
10581
 
10269
10582
  // app/lib/data-path.ts
10270
10583
  import { realpathSync as realpathSync3 } from "fs";
10271
- import { resolve as resolve16, normalize, sep as sep3, relative } from "path";
10272
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "../platform");
10273
- var DATA_ROOT = resolve16(PLATFORM_ROOT5, "..", "data");
10274
- var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve16(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10584
+ import { resolve as resolve17, normalize, sep as sep3, relative } from "path";
10585
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "../platform");
10586
+ var DATA_ROOT = resolve17(PLATFORM_ROOT5, "..", "data");
10587
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve17(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10275
10588
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
10276
10589
  var ACCOUNT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
10277
10590
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -10284,7 +10597,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
10284
10597
  }
10285
10598
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
10286
10599
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
10287
- const absolute = resolve16(rootAbs, cleaned);
10600
+ const absolute = resolve17(rootAbs, cleaned);
10288
10601
  let rootReal;
10289
10602
  try {
10290
10603
  rootReal = realpathSync3(rootAbs);
@@ -10643,7 +10956,7 @@ async function cascadeDeleteDocument(params) {
10643
10956
 
10644
10957
  // app/lib/file-index.ts
10645
10958
  import * as fsp from "fs/promises";
10646
- import { resolve as resolve17, relative as relative2, join as join16, basename as basename5, extname as extname2, sep as sep4 } from "path";
10959
+ import { resolve as resolve18, relative as relative2, join as join17, basename as basename5, extname as extname2, sep as sep4 } from "path";
10647
10960
  import { tmpdir as tmpdir2 } from "os";
10648
10961
  import { execFile as execFile2 } from "child_process";
10649
10962
  import { promisify as promisify2 } from "util";
@@ -10714,7 +11027,7 @@ async function extractPdf(absolute) {
10714
11027
  return stdout.trim();
10715
11028
  }
10716
11029
  async function ocrPdf(absolute) {
10717
- const outPdf = join16(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
11030
+ const outPdf = join17(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
10718
11031
  try {
10719
11032
  await execFileAsync2(
10720
11033
  "ocrmypdf",
@@ -10776,7 +11089,7 @@ async function readDisplayName(absolute) {
10776
11089
  const stem = dot === -1 ? base : base.slice(0, dot);
10777
11090
  if (base === `${stem}.meta.json`) return null;
10778
11091
  try {
10779
- const raw = await fsp.readFile(join16(dir, `${stem}.meta.json`), "utf-8");
11092
+ const raw = await fsp.readFile(join17(dir, `${stem}.meta.json`), "utf-8");
10780
11093
  const meta = JSON.parse(raw);
10781
11094
  const dn = meta.displayName ?? meta.filename;
10782
11095
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -10796,7 +11109,7 @@ async function walkSubtree(root, dataRoot, out) {
10796
11109
  let clean = true;
10797
11110
  for (const entry of entries) {
10798
11111
  if (entry.isSymbolicLink()) continue;
10799
- const abs = join16(root, entry.name);
11112
+ const abs = join17(root, entry.name);
10800
11113
  if (entry.isDirectory()) {
10801
11114
  const sub = await walkSubtree(abs, dataRoot, out);
10802
11115
  if (!sub.clean) clean = false;
@@ -10951,8 +11264,8 @@ async function reconcileFileIndex(accountId, opts) {
10951
11264
  return withSession(opts, async (session) => {
10952
11265
  const walked = [];
10953
11266
  const subtreeRoots = [
10954
- resolve17(dataRoot, "uploads", accountId),
10955
- resolve17(dataRoot, "accounts", accountId)
11267
+ resolve18(dataRoot, "uploads", accountId),
11268
+ resolve18(dataRoot, "accounts", accountId)
10956
11269
  ];
10957
11270
  let clean = true;
10958
11271
  for (const root of subtreeRoots) {
@@ -11033,7 +11346,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
11033
11346
  async function indexFile(accountId, relativePath, opts) {
11034
11347
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
11035
11348
  const embed2 = opts?.embed ?? embed;
11036
- const absolute = resolve17(dataRoot, relativePath);
11349
+ const absolute = resolve18(dataRoot, relativePath);
11037
11350
  await withSession(opts, async (session) => {
11038
11351
  const st = await fsp.stat(absolute);
11039
11352
  const wf = {
@@ -11067,7 +11380,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
11067
11380
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11068
11381
  async function readMeta(absDir, baseName) {
11069
11382
  try {
11070
- const raw = await readFile4(join17(absDir, `${baseName}.meta.json`), "utf8");
11383
+ const raw = await readFile4(join18(absDir, `${baseName}.meta.json`), "utf8");
11071
11384
  const parsed = JSON.parse(raw);
11072
11385
  if (typeof parsed?.filename === "string") {
11073
11386
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -11078,7 +11391,7 @@ async function readMeta(absDir, baseName) {
11078
11391
  }
11079
11392
  async function readAccountNames() {
11080
11393
  const map = /* @__PURE__ */ new Map();
11081
- const accountsDir = resolve18(DATA_ROOT, "accounts");
11394
+ const accountsDir = resolve19(DATA_ROOT, "accounts");
11082
11395
  let names;
11083
11396
  try {
11084
11397
  names = await readdir3(accountsDir);
@@ -11087,7 +11400,7 @@ async function readAccountNames() {
11087
11400
  }
11088
11401
  for (const name of names) {
11089
11402
  if (!UUID_RE3.test(name)) continue;
11090
- const configPath2 = resolve18(accountsDir, name, "account.json");
11403
+ const configPath2 = resolve19(accountsDir, name, "account.json");
11091
11404
  try {
11092
11405
  const raw = await readFile4(configPath2, "utf8");
11093
11406
  const parsed = JSON.parse(raw);
@@ -11105,7 +11418,7 @@ async function readAccountNames() {
11105
11418
  }
11106
11419
  async function enrich(absolute, entry, accountNames) {
11107
11420
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
11108
- const meta = await readMeta(join17(absolute, entry.name), entry.name);
11421
+ const meta = await readMeta(join18(absolute, entry.name), entry.name);
11109
11422
  if (meta?.filename) {
11110
11423
  entry.displayName = meta.filename;
11111
11424
  entry.mimeType = meta.mimeType;
@@ -11203,7 +11516,7 @@ app19.get("/", requireAdminSession, async (c) => {
11203
11516
  continue;
11204
11517
  }
11205
11518
  try {
11206
- const entryPath = join17(absolute, name);
11519
+ const entryPath = join18(absolute, name);
11207
11520
  const s = await stat4(entryPath);
11208
11521
  entries.push({
11209
11522
  name,
@@ -11328,8 +11641,8 @@ app19.post("/upload", requireAdminSession, async (c) => {
11328
11641
  }
11329
11642
  const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
11330
11643
  const finalName = `${Date.now()}-${safeName}`;
11331
- const destDir = resolve18(DATA_ROOT, "uploads", accountId);
11332
- const destPath = resolve18(destDir, finalName);
11644
+ const destDir = resolve19(DATA_ROOT, "uploads", accountId);
11645
+ const destPath = resolve19(destDir, finalName);
11333
11646
  try {
11334
11647
  await mkdir3(destDir, { recursive: true });
11335
11648
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11394,7 +11707,7 @@ app19.delete("/", requireAdminSession, async (c) => {
11394
11707
  }
11395
11708
  const dot = base.lastIndexOf(".");
11396
11709
  const stem = dot === -1 ? base : base.slice(0, dot);
11397
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join17(dirname5(absolute), `${stem}.meta.json`) : null;
11710
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join18(dirname5(absolute), `${stem}.meta.json`) : null;
11398
11711
  await unlink2(absolute);
11399
11712
  if (sidecarPath) {
11400
11713
  try {
@@ -13443,8 +13756,8 @@ var graph_default_view_default = app25;
13443
13756
 
13444
13757
  // server/routes/admin/sidebar-artefacts.ts
13445
13758
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
13446
- import { resolve as resolve19, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13447
- import { existsSync as existsSync19 } from "fs";
13759
+ import { resolve as resolve20, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13760
+ import { existsSync as existsSync20 } from "fs";
13448
13761
  var LIMIT = 50;
13449
13762
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
13450
13763
  function toDataRootRelPath(absPath) {
@@ -13463,7 +13776,7 @@ app26.get("/", requireAdminSession, async (c) => {
13463
13776
  if (accountFiles === null) {
13464
13777
  return c.json({ error: "Failed to load artefacts" }, 500);
13465
13778
  }
13466
- const accountDir = resolve19(ACCOUNTS_DIR, accountId);
13779
+ const accountDir = resolve20(ACCOUNTS_DIR, accountId);
13467
13780
  const agents = await fetchAgentTemplateRows(accountDir);
13468
13781
  const artefacts = [...accountFiles, ...agents].sort(
13469
13782
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -13514,8 +13827,8 @@ async function fetchAccountFileArtefacts(accountId) {
13514
13827
  async function fetchAgentTemplateRows(accountDir) {
13515
13828
  const rows = [];
13516
13829
  for (const filename of ADMIN_AGENT_FILES) {
13517
- const overridePath = resolve19(accountDir, "agents", "admin", filename);
13518
- const bundledPath = resolve19(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13830
+ const overridePath = resolve20(accountDir, "agents", "admin", filename);
13831
+ const bundledPath = resolve20(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13519
13832
  const labelStem = filename.replace(/\.md$/, "");
13520
13833
  const row = await readAgentTemplateRow({
13521
13834
  id: `agent-template:admin:${filename}`,
@@ -13528,12 +13841,12 @@ async function fetchAgentTemplateRows(accountDir) {
13528
13841
  });
13529
13842
  if (row) rows.push(row);
13530
13843
  }
13531
- const overrideDir = resolve19(accountDir, "specialists", "agents");
13532
- const bundledDir = resolve19(PLATFORM_ROOT, "templates", "specialists", "agents");
13844
+ const overrideDir = resolve20(accountDir, "specialists", "agents");
13845
+ const bundledDir = resolve20(PLATFORM_ROOT, "templates", "specialists", "agents");
13533
13846
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
13534
13847
  for (const filename of specialistNames) {
13535
- const overridePath = resolve19(overrideDir, filename);
13536
- const bundledPath = resolve19(bundledDir, filename);
13848
+ const overridePath = resolve20(overrideDir, filename);
13849
+ const bundledPath = resolve20(bundledDir, filename);
13537
13850
  const row = await readAgentTemplateRow({
13538
13851
  id: `agent-template:specialist:${filename}`,
13539
13852
  displayName: filename.replace(/\.md$/, ""),
@@ -13550,7 +13863,7 @@ async function fetchAgentTemplateRows(accountDir) {
13550
13863
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
13551
13864
  const names = /* @__PURE__ */ new Set();
13552
13865
  for (const dir of [overrideDir, bundledDir]) {
13553
- if (!existsSync19(dir)) continue;
13866
+ if (!existsSync20(dir)) continue;
13554
13867
  try {
13555
13868
  const entries = await readdir4(dir);
13556
13869
  for (const entry of entries) {
@@ -13565,7 +13878,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
13565
13878
  }
13566
13879
  async function readAgentTemplateRow(inp) {
13567
13880
  let chosenPath = null;
13568
- if (existsSync19(inp.overridePath)) {
13881
+ if (existsSync20(inp.overridePath)) {
13569
13882
  try {
13570
13883
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
13571
13884
  chosenPath = inp.overridePath;
@@ -13576,7 +13889,7 @@ async function readAgentTemplateRow(inp) {
13576
13889
  );
13577
13890
  return null;
13578
13891
  }
13579
- } else if (existsSync19(inp.bundledPath)) {
13892
+ } else if (existsSync20(inp.bundledPath)) {
13580
13893
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
13581
13894
  console.error(
13582
13895
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -13900,24 +14213,24 @@ app31.get("/", async (c) => {
13900
14213
  var system_stats_default = app31;
13901
14214
 
13902
14215
  // server/routes/admin/health.ts
13903
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
13904
- import { resolve as resolve20, join as join18 } from "path";
13905
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve20(process.cwd(), "..");
14216
+ import { existsSync as existsSync21, readFileSync as readFileSync20 } from "fs";
14217
+ import { resolve as resolve21, join as join19 } from "path";
14218
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
13906
14219
  var brandHostname = "maxy";
13907
- var brandJsonPath = join18(PLATFORM_ROOT6, "config", "brand.json");
13908
- if (existsSync20(brandJsonPath)) {
14220
+ var brandJsonPath = join19(PLATFORM_ROOT6, "config", "brand.json");
14221
+ if (existsSync21(brandJsonPath)) {
13909
14222
  try {
13910
- const brand = JSON.parse(readFileSync18(brandJsonPath, "utf-8"));
14223
+ const brand = JSON.parse(readFileSync20(brandJsonPath, "utf-8"));
13911
14224
  if (brand.hostname) brandHostname = brand.hostname;
13912
14225
  } catch {
13913
14226
  }
13914
14227
  }
13915
- var VERSION_FILE = resolve20(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
14228
+ var VERSION_FILE = resolve21(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
13916
14229
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
13917
14230
  var PROBE_TIMEOUT_MS = 1e3;
13918
14231
  function readVersion() {
13919
- if (!existsSync20(VERSION_FILE)) return "unknown";
13920
- return readFileSync18(VERSION_FILE, "utf-8").trim() || "unknown";
14232
+ if (!existsSync21(VERSION_FILE)) return "unknown";
14233
+ return readFileSync20(VERSION_FILE, "utf-8").trim() || "unknown";
13921
14234
  }
13922
14235
  async function probeConversationDb() {
13923
14236
  let session;
@@ -14459,16 +14772,16 @@ var admin_default = app39;
14459
14772
 
14460
14773
  // app/lib/access-gate.ts
14461
14774
  import neo4j4 from "neo4j-driver";
14462
- import { readFileSync as readFileSync19 } from "fs";
14463
- import { resolve as resolve21 } from "path";
14775
+ import { readFileSync as readFileSync21 } from "fs";
14776
+ import { resolve as resolve22 } from "path";
14464
14777
  import { randomUUID as randomUUID10 } from "crypto";
14465
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
14778
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14466
14779
  var driver = null;
14467
14780
  function readPassword() {
14468
14781
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
14469
- const passwordFile = resolve21(PLATFORM_ROOT7, "config/.neo4j-password");
14782
+ const passwordFile = resolve22(PLATFORM_ROOT7, "config/.neo4j-password");
14470
14783
  try {
14471
- return readFileSync19(passwordFile, "utf-8").trim();
14784
+ return readFileSync21(passwordFile, "utf-8").trim();
14472
14785
  } catch {
14473
14786
  throw new Error(
14474
14787
  `Neo4j password not found. Expected at ${passwordFile} or in NEO4J_PASSWORD env var.`
@@ -14756,9 +15069,9 @@ var verify_token_default = app40;
14756
15069
 
14757
15070
  // app/lib/access-email.ts
14758
15071
  import { spawn as spawn2 } from "child_process";
14759
- import { resolve as resolve22 } from "path";
14760
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14761
- var SEND_SCRIPT = resolve22(
15072
+ import { resolve as resolve23 } from "path";
15073
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
15074
+ var SEND_SCRIPT = resolve23(
14762
15075
  PLATFORM_ROOT8,
14763
15076
  "plugins",
14764
15077
  "email",
@@ -14900,8 +15213,8 @@ app42.route("/request-magic-link", request_magic_link_default);
14900
15213
  var access_default = app42;
14901
15214
 
14902
15215
  // server/routes/sites.ts
14903
- import { existsSync as existsSync21, readFileSync as readFileSync20, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
14904
- import { resolve as resolve23 } from "path";
15216
+ import { existsSync as existsSync22, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
15217
+ import { resolve as resolve24 } from "path";
14905
15218
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
14906
15219
  var MIME = {
14907
15220
  ".html": "text/html; charset=utf-8",
@@ -14958,15 +15271,15 @@ app43.get("/:rel{.*}", (c) => {
14958
15271
  }
14959
15272
  segments.push(seg);
14960
15273
  }
14961
- const rootDir = resolve23(account.accountDir, "sites");
14962
- let filePath = segments.length === 0 ? rootDir : resolve23(rootDir, ...segments);
15274
+ const rootDir = resolve24(account.accountDir, "sites");
15275
+ let filePath = segments.length === 0 ? rootDir : resolve24(rootDir, ...segments);
14963
15276
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
14964
15277
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
14965
15278
  return c.text("Forbidden", 403);
14966
15279
  }
14967
15280
  let stat7;
14968
15281
  try {
14969
- stat7 = existsSync21(filePath) ? statSync9(filePath) : null;
15282
+ stat7 = existsSync22(filePath) ? statSync9(filePath) : null;
14970
15283
  } catch {
14971
15284
  stat7 = null;
14972
15285
  }
@@ -14979,13 +15292,13 @@ app43.get("/:rel{.*}", (c) => {
14979
15292
  return c.redirect(target, 301);
14980
15293
  }
14981
15294
  if (stat7?.isDirectory()) {
14982
- filePath = resolve23(filePath, "index.html");
15295
+ filePath = resolve24(filePath, "index.html");
14983
15296
  }
14984
15297
  if (!filePath.startsWith(rootDir + "/")) {
14985
15298
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
14986
15299
  return c.text("Forbidden", 403);
14987
15300
  }
14988
- if (!existsSync21(filePath)) {
15301
+ if (!existsSync22(filePath)) {
14989
15302
  console.error(`[sites] not-found path=${reqPath} status=404`);
14990
15303
  return c.text("Not found", 404);
14991
15304
  }
@@ -15004,7 +15317,7 @@ app43.get("/:rel{.*}", (c) => {
15004
15317
  }
15005
15318
  let body;
15006
15319
  try {
15007
- body = readFileSync20(realPath);
15320
+ body = readFileSync22(realPath);
15008
15321
  } catch (err) {
15009
15322
  const code = err?.code;
15010
15323
  if (code === "EISDIR") {
@@ -15040,7 +15353,7 @@ var sites_default = app43;
15040
15353
 
15041
15354
  // app/lib/visitor-token.ts
15042
15355
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
15043
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync21, writeFileSync as writeFileSync7 } from "fs";
15356
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync23, writeFileSync as writeFileSync8 } from "fs";
15044
15357
  import { dirname as dirname6 } from "path";
15045
15358
  var TOKEN_PREFIX = "v1.";
15046
15359
  var SECRET_BYTES = 32;
@@ -15049,7 +15362,7 @@ var cachedSecret = null;
15049
15362
  function getSecret() {
15050
15363
  if (cachedSecret) return cachedSecret;
15051
15364
  try {
15052
- const hex2 = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15365
+ const hex2 = readFileSync23(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15053
15366
  if (hex2.length === SECRET_BYTES * 2) {
15054
15367
  cachedSecret = Buffer.from(hex2, "hex");
15055
15368
  return cachedSecret;
@@ -15059,11 +15372,11 @@ function getSecret() {
15059
15372
  const fresh = randomBytes(SECRET_BYTES).toString("hex");
15060
15373
  try {
15061
15374
  mkdirSync4(dirname6(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
15062
- writeFileSync7(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
15375
+ writeFileSync8(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
15063
15376
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
15064
15377
  } catch {
15065
15378
  }
15066
- const hex = readFileSync21(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15379
+ const hex = readFileSync23(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
15067
15380
  cachedSecret = Buffer.from(hex, "hex");
15068
15381
  return cachedSecret;
15069
15382
  }
@@ -15116,8 +15429,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
15116
15429
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
15117
15430
 
15118
15431
  // app/lib/brand-config.ts
15119
- import { existsSync as existsSync22, readFileSync as readFileSync22 } from "fs";
15120
- import { join as join19 } from "path";
15432
+ import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
15433
+ import { join as join20 } from "path";
15121
15434
  var cached2 = null;
15122
15435
  var cachedAttempted = false;
15123
15436
  function readBrandConfig() {
@@ -15125,10 +15438,10 @@ function readBrandConfig() {
15125
15438
  cachedAttempted = true;
15126
15439
  const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
15127
15440
  if (!platformRoot2) return null;
15128
- const brandPath = join19(platformRoot2, "config", "brand.json");
15129
- if (!existsSync22(brandPath)) return null;
15441
+ const brandPath = join20(platformRoot2, "config", "brand.json");
15442
+ if (!existsSync23(brandPath)) return null;
15130
15443
  try {
15131
- cached2 = JSON.parse(readFileSync22(brandPath, "utf-8"));
15444
+ cached2 = JSON.parse(readFileSync24(brandPath, "utf-8"));
15132
15445
  return cached2;
15133
15446
  } catch {
15134
15447
  return null;
@@ -15616,14 +15929,14 @@ async function writeEvent(opts) {
15616
15929
  var visitor_event_default = app46;
15617
15930
 
15618
15931
  // server/routes/session.ts
15619
- import { resolve as resolve24 } from "path";
15620
- import { existsSync as existsSync23, writeFileSync as writeFileSync8, mkdirSync as mkdirSync5 } from "fs";
15932
+ import { resolve as resolve25 } from "path";
15933
+ import { existsSync as existsSync24, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
15621
15934
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
15622
15935
  function writeBrandingCache(accountId, agentSlug, branding) {
15623
15936
  try {
15624
- const cacheDir = resolve24(MAXY_DIR, "branding-cache", accountId);
15937
+ const cacheDir = resolve25(MAXY_DIR, "branding-cache", accountId);
15625
15938
  mkdirSync5(cacheDir, { recursive: true });
15626
- writeFileSync8(resolve24(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15939
+ writeFileSync9(resolve25(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15627
15940
  } catch (err) {
15628
15941
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
15629
15942
  }
@@ -15711,8 +16024,8 @@ app47.post("/", async (c) => {
15711
16024
  }
15712
16025
  let agentConfig = null;
15713
16026
  if (account) {
15714
- const agentDir = resolve24(account.accountDir, "agents", agentSlug);
15715
- if (!existsSync23(agentDir) || !existsSync23(resolve24(agentDir, "config.json"))) {
16027
+ const agentDir = resolve25(account.accountDir, "agents", agentSlug);
16028
+ if (!existsSync24(agentDir) || !existsSync24(resolve25(agentDir, "config.json"))) {
15716
16029
  return c.json({ error: "Agent not found" }, 404);
15717
16030
  }
15718
16031
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -15992,7 +16305,7 @@ function startGraphHealthTimer() {
15992
16305
 
15993
16306
  // app/lib/file-watcher.ts
15994
16307
  import * as fsp2 from "fs/promises";
15995
- import { resolve as resolve25, sep as sep7 } from "path";
16308
+ import { resolve as resolve26, sep as sep7 } from "path";
15996
16309
  var ACCOUNT_UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
15997
16310
  var DEFAULT_COALESCE_MS = 500;
15998
16311
  var ROOTS = ["uploads", "accounts"];
@@ -16011,7 +16324,7 @@ async function startFileWatcher(opts = {}) {
16011
16324
  const dropFn = opts.drop ?? dropFileIndex;
16012
16325
  for (const r of ROOTS) {
16013
16326
  try {
16014
- await fsp2.mkdir(resolve25(dataRoot, r), { recursive: true });
16327
+ await fsp2.mkdir(resolve26(dataRoot, r), { recursive: true });
16015
16328
  } catch (err) {
16016
16329
  console.error(
16017
16330
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -16032,7 +16345,7 @@ async function startFileWatcher(opts = {}) {
16032
16345
  timers.set(relativePath, t);
16033
16346
  }
16034
16347
  async function runHook(relativePath, accountId) {
16035
- const absolute = resolve25(dataRoot, relativePath);
16348
+ const absolute = resolve26(dataRoot, relativePath);
16036
16349
  let exists = false;
16037
16350
  try {
16038
16351
  const st = await fsp2.stat(absolute);
@@ -16056,7 +16369,7 @@ async function startFileWatcher(opts = {}) {
16056
16369
  }
16057
16370
  }
16058
16371
  async function watchRoot(rootName) {
16059
- const absRoot = resolve25(dataRoot, rootName);
16372
+ const absRoot = resolve26(dataRoot, rootName);
16060
16373
  try {
16061
16374
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
16062
16375
  for await (const event of iter) {
@@ -16745,6 +17058,9 @@ function createWebchatChannelRoutes(deps) {
16745
17058
  var QUEUED_THRESHOLD_MS2 = 3e4;
16746
17059
  var ACK_THRESHOLD_MS2 = 3e4;
16747
17060
  var SWEEP_INTERVAL_MS2 = 15e3;
17061
+ function keyDisplay(key) {
17062
+ return key.startsWith("session:") ? key.slice(0, "session:".length + 8) : key.slice(0, 8);
17063
+ }
16748
17064
  var WebchatGateway = class {
16749
17065
  constructor(deps) {
16750
17066
  this.deps = deps;
@@ -16807,7 +17123,7 @@ var WebchatGateway = class {
16807
17123
  );
16808
17124
  if (willDeliverNow) this.lastDeliveredAt.set(input.key, Date.now());
16809
17125
  console.error(
16810
- `[webchat:inbound] op=received key=${input.key.slice(0, 8)} role=${input.role} bytes=${bytes} delivery=${willDeliverNow ? "immediate" : "queued"}`
17126
+ `[webchat:inbound] op=received key=${keyDisplay(input.key)} role=${input.role} bytes=${bytes} delivery=${willDeliverNow ? "immediate" : "queued"}`
16811
17127
  );
16812
17128
  if (!hadSubscriber && !this.spawning.has(input.key)) {
16813
17129
  this.spawning.add(input.key);
@@ -16818,7 +17134,10 @@ var WebchatGateway = class {
16818
17134
  key: input.key,
16819
17135
  role: input.role,
16820
17136
  gatewayUrl: this.deps.gatewayUrl,
16821
- serverPath: this.deps.serverPath
17137
+ serverPath: this.deps.serverPath,
17138
+ // Task 800 — only present on a session-targeted launch, so the
17139
+ // default-path call shape stays byte-identical.
17140
+ ...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {}
16822
17141
  });
16823
17142
  } finally {
16824
17143
  this.spawning.delete(input.key);
@@ -16944,8 +17263,8 @@ function broadcastAdminShutdown(reason) {
16944
17263
 
16945
17264
  // ../lib/entitlement/src/index.ts
16946
17265
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
16947
- import { existsSync as existsSync24, readFileSync as readFileSync23, statSync as statSync10 } from "fs";
16948
- import { resolve as resolve26 } from "path";
17266
+ import { existsSync as existsSync25, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
17267
+ import { resolve as resolve27 } from "path";
16949
17268
 
16950
17269
  // ../lib/entitlement/src/canonicalize.ts
16951
17270
  function canonicalize(value) {
@@ -16980,7 +17299,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
16980
17299
  var GRACE_DAYS = 7;
16981
17300
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
16982
17301
  function pubkeyPath(brand) {
16983
- return resolve26(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
17302
+ return resolve27(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
16984
17303
  }
16985
17304
  var memo = null;
16986
17305
  function memoKey(mtimeMs, account) {
@@ -16992,8 +17311,8 @@ function resolveEntitlement(brand, account) {
16992
17311
  if (brand.commercialMode !== true) {
16993
17312
  return logResolved(implicitTrust(account), null);
16994
17313
  }
16995
- const entitlementPath = resolve26(brand.configDir, "entitlement.json");
16996
- if (!existsSync24(entitlementPath)) {
17314
+ const entitlementPath = resolve27(brand.configDir, "entitlement.json");
17315
+ if (!existsSync25(entitlementPath)) {
16997
17316
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
16998
17317
  }
16999
17318
  const stat7 = statSync10(entitlementPath);
@@ -17008,7 +17327,7 @@ function resolveEntitlement(brand, account) {
17008
17327
  function verifyAndResolve(brand, entitlementPath, account) {
17009
17328
  let pubkeyPem;
17010
17329
  try {
17011
- pubkeyPem = readFileSync23(pubkeyPath(brand), "utf-8");
17330
+ pubkeyPem = readFileSync25(pubkeyPath(brand), "utf-8");
17012
17331
  } catch (err) {
17013
17332
  return logResolved(anonymousFallback("pubkey-missing"), {
17014
17333
  reason: "pubkey-missing"
@@ -17022,7 +17341,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
17022
17341
  }
17023
17342
  let envelope;
17024
17343
  try {
17025
- envelope = JSON.parse(readFileSync23(entitlementPath, "utf-8"));
17344
+ envelope = JSON.parse(readFileSync25(entitlementPath, "utf-8"));
17026
17345
  } catch {
17027
17346
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
17028
17347
  }
@@ -17183,14 +17502,14 @@ function clientFrom(c) {
17183
17502
  );
17184
17503
  }
17185
17504
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
17186
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join20(PLATFORM_ROOT9, "config", "brand.json") : "";
17505
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join21(PLATFORM_ROOT9, "config", "brand.json") : "";
17187
17506
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
17188
- if (BRAND_JSON_PATH && !existsSync25(BRAND_JSON_PATH)) {
17507
+ if (BRAND_JSON_PATH && !existsSync26(BRAND_JSON_PATH)) {
17189
17508
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
17190
17509
  }
17191
- if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
17510
+ if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
17192
17511
  try {
17193
- const parsed = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
17512
+ const parsed = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
17194
17513
  BRAND = { ...BRAND, ...parsed };
17195
17514
  } catch (err) {
17196
17515
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -17209,11 +17528,11 @@ var brandLoginOpts = {
17209
17528
  bodyFont: BRAND.defaultFonts?.body,
17210
17529
  logoContainsName: !!BRAND.logoContainsName
17211
17530
  };
17212
- var ALIAS_DOMAINS_PATH = join20(homedir3(), BRAND.configDir, "alias-domains.json");
17531
+ var ALIAS_DOMAINS_PATH = join21(homedir3(), BRAND.configDir, "alias-domains.json");
17213
17532
  function loadAliasDomains() {
17214
17533
  try {
17215
- if (!existsSync25(ALIAS_DOMAINS_PATH)) return null;
17216
- const parsed = JSON.parse(readFileSync24(ALIAS_DOMAINS_PATH, "utf-8"));
17534
+ if (!existsSync26(ALIAS_DOMAINS_PATH)) return null;
17535
+ const parsed = JSON.parse(readFileSync26(ALIAS_DOMAINS_PATH, "utf-8"));
17217
17536
  if (!Array.isArray(parsed)) {
17218
17537
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
17219
17538
  return null;
@@ -17241,7 +17560,7 @@ var app48 = new Hono();
17241
17560
  var nativeFileFollowers = /* @__PURE__ */ new Map();
17242
17561
  var waGateway = new WaGateway({
17243
17562
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17244
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17563
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17245
17564
  // Task 751 — file delivery on the native channel: resolve the platform
17246
17565
  // account + path validation here and funnel through the shared send core.
17247
17566
  sendDocument: async ({ senderId, accountId, filePath, caption }) => {
@@ -17257,7 +17576,7 @@ var waGateway = new WaGateway({
17257
17576
  caption,
17258
17577
  accountId,
17259
17578
  maxyAccountId,
17260
- platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."))
17579
+ platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."))
17261
17580
  });
17262
17581
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
17263
17582
  },
@@ -17297,14 +17616,14 @@ app48.route("/", waGateway.routes());
17297
17616
  waGateway.startSweeper();
17298
17617
  var webchatGateway = new WebchatGateway({
17299
17618
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17300
- serverPath: process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, ".."), "services/webchat-channel/dist/server.js"),
17301
- ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath }) => {
17619
+ serverPath: process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/webchat-channel/dist/server.js"),
17620
+ ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId }) => {
17302
17621
  if (role !== "admin") {
17303
17622
  console.error(`[webchat:inbound] op=spawn-refused key=${key} role=${role} reason=public-path-not-wired`);
17304
17623
  return;
17305
17624
  }
17306
17625
  const result = await managerRcSpawn({
17307
- sessionId: adminSessionIdFor(accountId, key),
17626
+ sessionId: sessionId ?? adminSessionIdFor(accountId, key),
17308
17627
  role: "admin",
17309
17628
  channel: "webchat",
17310
17629
  senderId: key,
@@ -17638,20 +17957,20 @@ app48.get("/agent-assets/:slug/:filename", (c) => {
17638
17957
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
17639
17958
  return c.text("Not found", 404);
17640
17959
  }
17641
- const filePath = resolve27(account.accountDir, "agents", slug, "assets", filename);
17642
- const expectedDir = resolve27(account.accountDir, "agents", slug, "assets");
17960
+ const filePath = resolve28(account.accountDir, "agents", slug, "assets", filename);
17961
+ const expectedDir = resolve28(account.accountDir, "agents", slug, "assets");
17643
17962
  if (!filePath.startsWith(expectedDir + "/")) {
17644
17963
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
17645
17964
  return c.text("Forbidden", 403);
17646
17965
  }
17647
- if (!existsSync25(filePath)) {
17966
+ if (!existsSync26(filePath)) {
17648
17967
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
17649
17968
  return c.text("Not found", 404);
17650
17969
  }
17651
17970
  const ext = "." + filename.split(".").pop()?.toLowerCase();
17652
17971
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
17653
17972
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
17654
- const body = readFileSync24(filePath);
17973
+ const body = readFileSync26(filePath);
17655
17974
  return c.body(body, 200, {
17656
17975
  "Content-Type": contentType,
17657
17976
  "Cache-Control": "public, max-age=3600"
@@ -17668,20 +17987,20 @@ app48.get("/generated/:filename", (c) => {
17668
17987
  console.error(`[generated] serve file=${filename} status=404`);
17669
17988
  return c.text("Not found", 404);
17670
17989
  }
17671
- const filePath = resolve27(account.accountDir, "generated", filename);
17672
- const expectedDir = resolve27(account.accountDir, "generated");
17990
+ const filePath = resolve28(account.accountDir, "generated", filename);
17991
+ const expectedDir = resolve28(account.accountDir, "generated");
17673
17992
  if (!filePath.startsWith(expectedDir + "/")) {
17674
17993
  console.error(`[generated] serve file=${filename} status=403`);
17675
17994
  return c.text("Forbidden", 403);
17676
17995
  }
17677
- if (!existsSync25(filePath)) {
17996
+ if (!existsSync26(filePath)) {
17678
17997
  console.error(`[generated] serve file=${filename} status=404`);
17679
17998
  return c.text("Not found", 404);
17680
17999
  }
17681
18000
  const ext = "." + filename.split(".").pop()?.toLowerCase();
17682
18001
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
17683
18002
  console.log(`[generated] serve file=${filename} status=200`);
17684
- const body = readFileSync24(filePath);
18003
+ const body = readFileSync26(filePath);
17685
18004
  return c.body(body, 200, {
17686
18005
  "Content-Type": contentType,
17687
18006
  "Cache-Control": "public, max-age=86400"
@@ -17694,9 +18013,9 @@ app48.route("/v", visitor_consent_default);
17694
18013
  var htmlCache = /* @__PURE__ */ new Map();
17695
18014
  var brandLogoPath = "/brand/maxy-monochrome.png";
17696
18015
  var brandIconPath = "/brand/maxy-monochrome.png";
17697
- if (BRAND_JSON_PATH && existsSync25(BRAND_JSON_PATH)) {
18016
+ if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
17698
18017
  try {
17699
- const fullBrand = JSON.parse(readFileSync24(BRAND_JSON_PATH, "utf-8"));
18018
+ const fullBrand = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
17700
18019
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
17701
18020
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
17702
18021
  } catch {
@@ -17713,9 +18032,9 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
17713
18032
  function readInstalledVersion() {
17714
18033
  try {
17715
18034
  if (!PLATFORM_ROOT9) return "unknown";
17716
- const versionFile = join20(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
17717
- if (!existsSync25(versionFile)) return "unknown";
17718
- const content = readFileSync24(versionFile, "utf-8").trim();
18035
+ const versionFile = join21(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
18036
+ if (!existsSync26(versionFile)) return "unknown";
18037
+ const content = readFileSync26(versionFile, "utf-8").trim();
17719
18038
  return content || "unknown";
17720
18039
  } catch {
17721
18040
  return "unknown";
@@ -17756,7 +18075,7 @@ var clientErrorReporterScript = `<script>
17756
18075
  function cachedHtml(file) {
17757
18076
  let html = htmlCache.get(file);
17758
18077
  if (!html) {
17759
- html = readFileSync24(resolve27(process.cwd(), "public", file), "utf-8");
18078
+ html = readFileSync26(resolve28(process.cwd(), "public", file), "utf-8");
17760
18079
  const productNameEsc = escapeHtml(BRAND.productName);
17761
18080
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
17762
18081
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -17772,13 +18091,13 @@ ${clientErrorReporterScript}
17772
18091
  }
17773
18092
  var brandedHtmlCache = /* @__PURE__ */ new Map();
17774
18093
  function loadBrandingCache(agentSlug) {
17775
- const configDir2 = join20(homedir3(), BRAND.configDir);
18094
+ const configDir2 = join21(homedir3(), BRAND.configDir);
17776
18095
  try {
17777
18096
  const accountId = getDefaultAccountId();
17778
18097
  if (!accountId) return null;
17779
- const cachePath = join20(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
17780
- if (!existsSync25(cachePath)) return null;
17781
- return JSON.parse(readFileSync24(cachePath, "utf-8"));
18098
+ const cachePath = join21(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
18099
+ if (!existsSync26(cachePath)) return null;
18100
+ return JSON.parse(readFileSync26(cachePath, "utf-8"));
17782
18101
  } catch {
17783
18102
  return null;
17784
18103
  }
@@ -17866,7 +18185,7 @@ app48.use("/vnc-popout.html", logViewerFetch);
17866
18185
  app48.get("/vnc-popout.html", (c) => {
17867
18186
  let html = htmlCache.get("vnc-popout.html");
17868
18187
  if (!html) {
17869
- html = readFileSync24(resolve27(process.cwd(), "public", "vnc-popout.html"), "utf-8");
18188
+ html = readFileSync26(resolve28(process.cwd(), "public", "vnc-popout.html"), "utf-8");
17870
18189
  const name = escapeHtml(BRAND.productName);
17871
18190
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
17872
18191
  html = html.replace("</head>", ` ${brandScript}
@@ -18022,11 +18341,11 @@ try {
18022
18341
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
18023
18342
  async function runAdminUserReconcileTick() {
18024
18343
  try {
18025
- if (!existsSync25(USERS_FILE)) {
18344
+ if (!existsSync26(USERS_FILE)) {
18026
18345
  console.error("[adminuser-self-heal] skip reason=no-users-file");
18027
18346
  return;
18028
18347
  }
18029
- const usersRaw = readFileSync24(USERS_FILE, "utf-8").trim();
18348
+ const usersRaw = readFileSync26(USERS_FILE, "utf-8").trim();
18030
18349
  if (!usersRaw) {
18031
18350
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
18032
18351
  return;
@@ -18136,7 +18455,7 @@ if (bootAccountConfig?.whatsapp) {
18136
18455
  }
18137
18456
  init({
18138
18457
  configDir: configDirForWhatsApp,
18139
- platformRoot: resolve27(process.env.MAXY_PLATFORM_ROOT ?? join20(__dirname, "..")),
18458
+ platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, "..")),
18140
18459
  accountConfig: bootAccountConfig,
18141
18460
  onMessage: async (msg) => {
18142
18461
  if (msg.isOwnerMirror) {