@rubytech/create-maxy-code 0.1.298 → 0.1.300

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 (152) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/cloudflare/references/manual-setup.md +51 -3
  3. package/payload/platform/plugins/cloudflare/references/reset-guide.md +19 -1
  4. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +16 -3
  5. package/payload/platform/scripts/check-no-esm-require.mjs +4 -0
  6. package/payload/server/{chunk-7H4KMTMC.js → chunk-JHSF5VPE.js} +171 -95
  7. package/payload/server/maxy-edge.js +19 -1
  8. package/payload/server/public/assets/AdminShell-BFdBxg4P.js +1 -0
  9. package/payload/server/public/assets/{Checkbox-CVPUf_7I.js → Checkbox-BZ1XbA1t.js} +1 -1
  10. package/payload/server/public/assets/{Transcript-FYmq-mL1.js → Transcript-CaVix6W0.js} +1 -1
  11. package/payload/server/public/assets/admin-BK7xIr3o.js +1 -0
  12. package/payload/server/public/assets/{arc-DmR-LPIx.js → arc-DxSm8tli.js} +1 -1
  13. package/payload/server/public/assets/architecture-YZFGNWBL-6g9jRVgc.js +1 -0
  14. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-IVt2X8Dk.js → architectureDiagram-Q4EWVU46-7JSAh0vL.js} +1 -1
  15. package/payload/server/public/assets/audio-attachment-mime-CFyc3gpD.js +30 -0
  16. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-CQDngnsc.js → blockDiagram-DXYQGD6D-DLoVmHKD.js} +1 -1
  17. package/payload/server/public/assets/{browser-D_hZgtfv.js → browser-ClnGUKp-.js} +1 -1
  18. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-BjV_YA-L.js → c4Diagram-AHTNJAMY-Nv1G0o9P.js} +1 -1
  19. package/payload/server/public/assets/channel-BgQLJanG.js +1 -0
  20. package/payload/server/public/assets/chat-ZTAhSoJV.js +1 -0
  21. package/payload/server/public/assets/{chunk-2KRD3SAO-BYqpHDvA.js → chunk-2KRD3SAO-BpqPMhoA.js} +1 -1
  22. package/payload/server/public/assets/chunk-336JU56O-DgXHlVU_.js +2 -0
  23. package/payload/server/public/assets/chunk-426QAEUC-Dr_XVuUq.js +1 -0
  24. package/payload/server/public/assets/{chunk-4BX2VUAB-BeDVr5Tb.js → chunk-4BX2VUAB-nwyZSZH8.js} +1 -1
  25. package/payload/server/public/assets/{chunk-4TB4RGXK-BImQYhPF.js → chunk-4TB4RGXK-Tfxz9LHX.js} +1 -1
  26. package/payload/server/public/assets/{chunk-55IACEB6-DB18cH4S.js → chunk-55IACEB6-6FMJQGXG.js} +1 -1
  27. package/payload/server/public/assets/{chunk-5FUZZQ4R-DrDSHQZv.js → chunk-5FUZZQ4R-g2FgZF3D.js} +1 -1
  28. package/payload/server/public/assets/{chunk-5PVQY5BW-CKX_LIok.js → chunk-5PVQY5BW-DtLwXsPH.js} +1 -1
  29. package/payload/server/public/assets/{chunk-67CJDMHE-Ca9KwdQm.js → chunk-67CJDMHE-K91CP5ZU.js} +1 -1
  30. package/payload/server/public/assets/{chunk-7N4EOEYR-BDpzHOmv.js → chunk-7N4EOEYR-BGpCQhqK.js} +1 -1
  31. package/payload/server/public/assets/{chunk-AA7GKIK3-DXo9fZho.js → chunk-AA7GKIK3-jkDbInck.js} +1 -1
  32. package/payload/server/public/assets/{chunk-BSJP7CBP-CTqmM6qI.js → chunk-BSJP7CBP-mDosdzGs.js} +1 -1
  33. package/payload/server/public/assets/{chunk-CIAEETIT-NufEId2j.js → chunk-CIAEETIT-DhBxewpQ.js} +1 -1
  34. package/payload/server/public/assets/{chunk-EDXVE4YY-D1zHB217.js → chunk-EDXVE4YY-B7c-9Emg.js} +1 -1
  35. package/payload/server/public/assets/{chunk-ENJZ2VHE-SFpdtszU.js → chunk-ENJZ2VHE-Cqhhncox.js} +1 -1
  36. package/payload/server/public/assets/{chunk-FMBD7UC4-_4wtKsfc.js → chunk-FMBD7UC4-BpDq6wj1.js} +1 -1
  37. package/payload/server/public/assets/{chunk-FOC6F5B3-565zaYb3.js → chunk-FOC6F5B3-Ds02-ktu.js} +1 -1
  38. package/payload/server/public/assets/{chunk-ICPOFSXX-cYdq7RKF.js → chunk-ICPOFSXX-BTX5POFr.js} +2 -2
  39. package/payload/server/public/assets/{chunk-K5T4RW27-CTZnA5fq.js → chunk-K5T4RW27-Du1PXXBU.js} +1 -1
  40. package/payload/server/public/assets/{chunk-KGLVRYIC-CeuKp7uR.js → chunk-KGLVRYIC-siasOAf8.js} +1 -1
  41. package/payload/server/public/assets/{chunk-LIHQZDEY-DXkzlh3_.js → chunk-LIHQZDEY-xf1rbZtf.js} +1 -1
  42. package/payload/server/public/assets/{chunk-ORNJ4GCN-DcZUCmgM.js → chunk-ORNJ4GCN-DeTLQ_LD.js} +1 -1
  43. package/payload/server/public/assets/{chunk-OYMX7WX6-B7JLCext.js → chunk-OYMX7WX6-DQ7_oVJn.js} +1 -1
  44. package/payload/server/public/assets/chunk-QZHKN3VN-DF4o9HRJ.js +1 -0
  45. package/payload/server/public/assets/{chunk-U2HBQHQK-DWCeFwem.js → chunk-U2HBQHQK-CXmFUKgn.js} +1 -1
  46. package/payload/server/public/assets/{chunk-X2U36JSP-DGnHsoJ3.js → chunk-X2U36JSP-Bj8-8Wkz.js} +1 -1
  47. package/payload/server/public/assets/{chunk-XPW4576I-CnU6DVpC.js → chunk-XPW4576I-Con3TXqt.js} +1 -1
  48. package/payload/server/public/assets/{chunk-YZCP3GAM-sg4lGGJV.js → chunk-YZCP3GAM-Dx8BHGWf.js} +1 -1
  49. package/payload/server/public/assets/{chunk-ZZ45TVLE-DtUoGmKE.js → chunk-ZZ45TVLE-Dp4Q5Y-f.js} +1 -1
  50. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DAbPKU6u.js +1 -0
  51. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BKuFQLcv.js +1 -0
  52. package/payload/server/public/assets/clone-DnNHGhNe.js +1 -0
  53. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-C04wkJr7.js → cose-bilkent-S5V4N54A-pZiCv69E.js} +1 -1
  54. package/payload/server/public/assets/{dagre-Dfj_jbTe.js → dagre-CLqhEgbL.js} +1 -1
  55. package/payload/server/public/assets/{dagre-KV5264BT-Bd1VlhUJ.js → dagre-KV5264BT-BCxE8iyk.js} +1 -1
  56. package/payload/server/public/assets/{data-DkbQI40a.js → data-DDjeQQ7e.js} +1 -1
  57. package/payload/server/public/assets/{diagram-5BDNPKRD-Dqqyk8GE.js → diagram-5BDNPKRD-slUEdZzz.js} +1 -1
  58. package/payload/server/public/assets/{diagram-G4DWMVQ6-Xk3WKR_U.js → diagram-G4DWMVQ6-DPcraMfu.js} +1 -1
  59. package/payload/server/public/assets/{diagram-MMDJMWI5-CAdGL9U7.js → diagram-MMDJMWI5-DR6luhGK.js} +1 -1
  60. package/payload/server/public/assets/{diagram-TYMM5635-DY1iYQVY.js → diagram-TYMM5635-Jap1B4wA.js} +1 -1
  61. package/payload/server/public/assets/{dist-Pgmncqde.js → dist-Dbh7HrZX.js} +1 -1
  62. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BJ5HYKeb.js → erDiagram-SMLLAGMA-DJKUs2hO.js} +1 -1
  63. package/payload/server/public/assets/{file-download-BYJN3Kgm.js → file-download-DBMW0BNz.js} +1 -1
  64. package/payload/server/public/assets/{flatten-DeFkSYLU.js → flatten-Cl1Bc3dR.js} +1 -1
  65. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-B-q6x5Q_.js → flowDiagram-DWJPFMVM-C8W-ZZ9W.js} +1 -1
  66. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DbjwY_bG.js → ganttDiagram-T4ZO3ILL-DYCX4Xu2.js} +1 -1
  67. package/payload/server/public/assets/gitGraph-7Q5UKJZL-g7mvu6IY.js +1 -0
  68. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-C3bLrOmb.js → gitGraphDiagram-UUTBAWPF-CZu_fpgS.js} +1 -1
  69. package/payload/server/public/assets/{graph-DmikPM4A.js → graph-CR74qec3.js} +1 -1
  70. package/payload/server/public/assets/{graph-labels-CtG6ckdG.js → graph-labels-1Uz0ZBRd.js} +1 -1
  71. package/payload/server/public/assets/{graphlib-BlOjhixq.js → graphlib-Bdp7TA4y.js} +1 -1
  72. package/payload/server/public/assets/info-OMHHGYJF-DZqJuIkB.js +1 -0
  73. package/payload/server/public/assets/infoDiagram-42DDH7IO-cGfGccHz.js +2 -0
  74. package/payload/server/public/assets/{isEmpty-Bn-Se8yT.js → isEmpty-D1pGOD1J.js} +1 -1
  75. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-B_DzwK8l.js → ishikawaDiagram-UXIWVN3A-B7KfIX6z.js} +1 -1
  76. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-COzTF-qc.js → journeyDiagram-VCZTEJTY-CSDwBfhF.js} +1 -1
  77. package/payload/server/public/assets/{jsx-runtime-BjFkEGXb.css → jsx-runtime-BqGVUT1h.css} +1 -1
  78. package/payload/server/public/assets/{jsx-runtime-UQ0Z6nwN.js → jsx-runtime-D3JkFIbi.js} +1 -1
  79. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-C2cOIZU6.js → kanban-definition-6JOO6SKY-CWzcEKTr.js} +1 -1
  80. package/payload/server/public/assets/{line-Bwa6aUYZ.js → line-BNQSlbYn.js} +1 -1
  81. package/payload/server/public/assets/{linear-CgbkJiu6.js → linear-BN6kGN93.js} +1 -1
  82. package/payload/server/public/assets/mermaid-parser.core-CcFhkElq.js +4 -0
  83. package/payload/server/public/assets/mermaid.core-BsIeJ7Cc.js +11 -0
  84. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-bu0QLO17.js → mindmap-definition-QFDTVHPH-CQVzj6D_.js} +1 -1
  85. package/payload/server/public/assets/operator-QP_z97s8.js +1 -0
  86. package/payload/server/public/assets/{ordinal-C-EimP2j.js → ordinal-CBZeH4Yp.js} +1 -1
  87. package/payload/server/public/assets/packet-4T2RLAQJ-Hn8rlHpy.js +1 -0
  88. package/payload/server/public/assets/page-CLijftr1.js +1 -0
  89. package/payload/server/public/assets/pie-ZZUOXDRM-BPGWVqBm.js +1 -0
  90. package/payload/server/public/assets/{pieDiagram-DEJITSTG-DQUe6W2Z.js → pieDiagram-DEJITSTG-DnrQ9fyn.js} +1 -1
  91. package/payload/server/public/assets/preload-helper-CQ36nxok.js +1 -0
  92. package/payload/server/public/assets/public-W-HholkU.js +6 -0
  93. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-ChhcwVRA.js → quadrantDiagram-34T5L4WZ-BQWlCyWi.js} +1 -1
  94. package/payload/server/public/assets/radar-PYXPWWZC-DMdLrj3E.js +1 -0
  95. package/payload/server/public/assets/{reduce-B0wq8DtH.js → reduce-PuPlFPRX.js} +1 -1
  96. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DwQXqTA9.js → requirementDiagram-MS252O5E-Du_vZhU1.js} +1 -1
  97. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-zYqdptBM.js → sankeyDiagram-XADWPNL6-Cf6Z8GPQ.js} +1 -1
  98. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-x2g84gb4.js → sequenceDiagram-FGHM5R23-CS8GVol8.js} +1 -1
  99. package/payload/server/public/assets/{src-CozP7LCe.js → src-BoaldmnP.js} +1 -1
  100. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-CeUrqs2P.js → stateDiagram-FHFEXIEX-Bv1NW2F1.js} +1 -1
  101. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BGUCxPmp.js +1 -0
  102. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CL-c9XN5.js → timeline-definition-GMOUNBTQ-ClGYAsr0.js} +1 -1
  103. package/payload/server/public/assets/treeView-SZITEDCU-CWxofUbI.js +1 -0
  104. package/payload/server/public/assets/treemap-W4RFUUIX-Cfgb_ZG0.js +1 -0
  105. package/payload/server/public/assets/{useSelectionMode-C1_ky4B6.js → useSelectionMode-geYq13zs.js} +1 -1
  106. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-By2HBDYr.js → vennDiagram-DHZGUBPP-C2wTcxQT.js} +1 -1
  107. package/payload/server/public/assets/wardley-RL74JXVD-B45olYjj.js +1 -0
  108. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-iahvFvIS.js → wardleyDiagram-NUSXRM2D-D86-ivEx.js} +1 -1
  109. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-33qqdRhI.js → xychartDiagram-5P7HB3ND-Ba5WAN8P.js} +1 -1
  110. package/payload/server/public/browser.html +7 -7
  111. package/payload/server/public/chat.html +10 -9
  112. package/payload/server/public/data.html +6 -6
  113. package/payload/server/public/graph.html +9 -9
  114. package/payload/server/public/index.html +11 -10
  115. package/payload/server/public/operator.html +24 -0
  116. package/payload/server/public/public.html +8 -7
  117. package/payload/server/server.js +392 -330
  118. package/payload/server/public/assets/AdminShell-BnhxfX97.js +0 -1
  119. package/payload/server/public/assets/admin-CF8K3hqE.js +0 -1
  120. package/payload/server/public/assets/architecture-YZFGNWBL-CjF2k79a.js +0 -1
  121. package/payload/server/public/assets/audio-attachment-mime-DaInZ9sa.js +0 -1
  122. package/payload/server/public/assets/channel-gFnUr8f4.js +0 -1
  123. package/payload/server/public/assets/chat-COcrNTJi.js +0 -1
  124. package/payload/server/public/assets/chunk-336JU56O-B0yBhSVq.js +0 -2
  125. package/payload/server/public/assets/chunk-426QAEUC-BCmWl6vi.js +0 -1
  126. package/payload/server/public/assets/chunk-QZHKN3VN-CBWmDBHe.js +0 -1
  127. package/payload/server/public/assets/classDiagram-6PBFFD2Q-C_wlfUTz.js +0 -1
  128. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Ltv5s3OY.js +0 -1
  129. package/payload/server/public/assets/clone-D0XoXc_v.js +0 -1
  130. package/payload/server/public/assets/gitGraph-7Q5UKJZL-DsUTwRUb.js +0 -1
  131. package/payload/server/public/assets/info-OMHHGYJF-BV9FyUXQ.js +0 -1
  132. package/payload/server/public/assets/infoDiagram-42DDH7IO-BpaHbiXO.js +0 -2
  133. package/payload/server/public/assets/mermaid-parser.core-BFAF0BAk.js +0 -4
  134. package/payload/server/public/assets/mermaid.core-CMOXmawT.js +0 -11
  135. package/payload/server/public/assets/packet-4T2RLAQJ-SXjQ83Vr.js +0 -1
  136. package/payload/server/public/assets/pie-ZZUOXDRM-q7TXebDD.js +0 -1
  137. package/payload/server/public/assets/public-CSEIGhb4.js +0 -35
  138. package/payload/server/public/assets/radar-PYXPWWZC-CXKUHVMS.js +0 -1
  139. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B27DBP9X.js +0 -1
  140. package/payload/server/public/assets/treeView-SZITEDCU-CWuFgUeJ.js +0 -1
  141. package/payload/server/public/assets/treemap-W4RFUUIX-gKO4rbgo.js +0 -1
  142. package/payload/server/public/assets/wardley-RL74JXVD-hDEw8pJN.js +0 -1
  143. /package/payload/server/public/assets/{_baseFor-BV-TyLWt.js → _baseFor-brRjpUOX.js} +0 -0
  144. /package/payload/server/public/assets/{array-lqrvkwy7.js → array-BGFCBI0e.js} +0 -0
  145. /package/payload/server/public/assets/{chunk-CWOGyPgy.js → chunk-Pqm5yXtL.js} +0 -0
  146. /package/payload/server/public/assets/{cytoscape.esm-SmEOayFS.js → cytoscape.esm-TvRJ2tGX.js} +0 -0
  147. /package/payload/server/public/assets/{defaultLocale-Dl3Sud5K.js → defaultLocale-CRZydyG6.js} +0 -0
  148. /package/payload/server/public/assets/{init-BukMwkmL.js → init-B8gtcn7T.js} +0 -0
  149. /package/payload/server/public/assets/{katex-jl-BtNZi.js → katex-RxgSu_dy.js} +0 -0
  150. /package/payload/server/public/assets/{admin-CWMpccrR.css → page-CWMpccrR.css} +0 -0
  151. /package/payload/server/public/assets/{path-DPTRcLku.js → path-DZF-JdEe.js} +0 -0
  152. /package/payload/server/public/assets/{rough.esm-VLpapkIG.js → rough.esm-6CnTHTkH.js} +0 -0
@@ -1,6 +1,7 @@
1
1
  import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  ACCOUNTS_DIR,
4
+ AGENT_SLUG_PATTERN,
4
5
  BIN_DIR,
5
6
  BRAND_NAME,
6
7
  CDP_PORT,
@@ -15,6 +16,8 @@ import {
15
16
  LOG_DIR,
16
17
  MAXY_DIR,
17
18
  PLATFORM_ROOT,
19
+ PUBLIC_ALLOWED_EXACT,
20
+ PUBLIC_ALLOWED_PREFIXES,
18
21
  RFB_PORT,
19
22
  SYSTEM_PATH_SLUGS,
20
23
  USERS_FILE,
@@ -26,6 +29,7 @@ import {
26
29
  canAccessAdmin,
27
30
  checkGroupMembership,
28
31
  checkRateLimit,
32
+ classifyHost,
29
33
  cleanupLeakedPremiumSubs,
30
34
  clearRateLimit,
31
35
  clientIpMiddleware,
@@ -45,6 +49,7 @@ import {
45
49
  getConversationClaudeSessionIds,
46
50
  getDefaultAccountId,
47
51
  getGroupParticipants,
52
+ getOperatorDomains,
48
53
  getRecentMessages,
49
54
  getRoleForSession,
50
55
  getSession,
@@ -55,7 +60,9 @@ import {
55
60
  getUserTimezone,
56
61
  httpLog,
57
62
  isActiveAgentSlug,
63
+ isOperatorHost,
58
64
  isPasswordValid,
65
+ isPublicPathAllowed,
59
66
  isRemoteAuthConfigured,
60
67
  linkConversationTranscript,
61
68
  listAdminSessions,
@@ -97,7 +104,7 @@ import {
97
104
  vncLog,
98
105
  walkPremiumBundles,
99
106
  writeAdminUserAndPerson
100
- } from "./chunk-7H4KMTMC.js";
107
+ } from "./chunk-JHSF5VPE.js";
101
108
  import {
102
109
  __commonJS,
103
110
  __toESM
@@ -1214,35 +1221,21 @@ var serveStatic = (options = { root: "" }) => {
1214
1221
  };
1215
1222
 
1216
1223
  // server/index.ts
1217
- import { readFileSync as readFileSync26, existsSync as existsSync26, watchFile } from "fs";
1218
- import { resolve as resolve28, join as join21, basename as basename8 } from "path";
1224
+ import { readFileSync as readFileSync26, existsSync as existsSync27, watchFile } from "fs";
1225
+ import { resolve as resolve29, join as join22, basename as basename8 } from "path";
1219
1226
  import { homedir as homedir3 } from "os";
1220
1227
  import { monitorEventLoopDelay } from "perf_hooks";
1221
1228
 
1222
- // app/lib/agent-slug-pattern.ts
1223
- var AGENT_SLUG_PATTERN = /^\/([a-z][a-z0-9-]{2,49})$/;
1224
-
1225
- // server/public-host-gate.ts
1226
- var PUBLIC_ALLOWED_PREFIXES = [
1227
- "/api/session",
1228
- "/api/chat",
1229
- "/api/access/",
1230
- "/api/health",
1231
- "/api/group/",
1232
- "/api/telegram/",
1233
- "/assets/",
1234
- "/brand/",
1235
- "/agent-assets/",
1236
- "/generated/",
1237
- "/g/",
1238
- "/sites/"
1239
- ];
1240
- var PUBLIC_ALLOWED_EXACT = ["/favicon.ico", "/brand-defaults.css"];
1241
- function isPublicPathAllowed(path2) {
1242
- if (path2 === "/") return true;
1243
- if (PUBLIC_ALLOWED_EXACT.includes(path2)) return true;
1244
- if (PUBLIC_ALLOWED_PREFIXES.some((prefix) => path2.startsWith(prefix))) return true;
1245
- return AGENT_SLUG_PATTERN.test(path2);
1229
+ // server/webchat-descriptor.ts
1230
+ import { resolve, join as join2 } from "path";
1231
+ function webchatGatewayUrl() {
1232
+ return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
1233
+ }
1234
+ function webchatServerPath() {
1235
+ return process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve(process.env.MAXY_PLATFORM_ROOT ?? join2(__dirname, ".."), "services/webchat-channel/dist/server.js");
1236
+ }
1237
+ function webchatChannelDescriptor(key) {
1238
+ return { key, gatewayUrl: webchatGatewayUrl(), serverPath: webchatServerPath() };
1246
1239
  }
1247
1240
 
1248
1241
  // app/lib/claude-auth.ts
@@ -1794,7 +1787,7 @@ var credsSaveQueue = Promise.resolve();
1794
1787
  async function drainCredsSaveQueue(timeoutMs = 5e3) {
1795
1788
  console.error(`${TAG2} draining credential save queue\u2026`);
1796
1789
  const timer2 = new Promise(
1797
- (resolve29) => setTimeout(() => resolve29("timeout"), timeoutMs)
1790
+ (resolve30) => setTimeout(() => resolve30("timeout"), timeoutMs)
1798
1791
  );
1799
1792
  const result = await Promise.race([
1800
1793
  credsSaveQueue.then(() => "drained"),
@@ -1922,11 +1915,11 @@ async function createWaSocket(opts) {
1922
1915
  return sock;
1923
1916
  }
1924
1917
  async function waitForConnection(sock) {
1925
- return new Promise((resolve29, reject) => {
1918
+ return new Promise((resolve30, reject) => {
1926
1919
  const handler = (update) => {
1927
1920
  if (update.connection === "open") {
1928
1921
  sock.ev.off("connection.update", handler);
1929
- resolve29();
1922
+ resolve30();
1930
1923
  }
1931
1924
  if (update.connection === "close") {
1932
1925
  sock.ev.off("connection.update", handler);
@@ -2040,14 +2033,14 @@ ${inspected}`;
2040
2033
  return inspect2(err, INSPECT_OPTS2);
2041
2034
  }
2042
2035
  function withTimeout(label, promise, timeoutMs) {
2043
- return new Promise((resolve29, reject) => {
2036
+ return new Promise((resolve30, reject) => {
2044
2037
  const timer2 = setTimeout(() => {
2045
2038
  reject(new Error(`${label} timed out after ${timeoutMs}ms`));
2046
2039
  }, timeoutMs);
2047
2040
  promise.then(
2048
2041
  (value) => {
2049
2042
  clearTimeout(timer2);
2050
- resolve29(value);
2043
+ resolve30(value);
2051
2044
  },
2052
2045
  (err) => {
2053
2046
  clearTimeout(timer2);
@@ -2646,8 +2639,8 @@ async function persistWhatsAppMessage(input) {
2646
2639
  const { givenName, familyName } = splitName(input.pushName);
2647
2640
  const prev = sessionWriteLocks.get(input.cacheKey);
2648
2641
  let release;
2649
- const mine = new Promise((resolve29) => {
2650
- release = resolve29;
2642
+ const mine = new Promise((resolve30) => {
2643
+ release = resolve30;
2651
2644
  });
2652
2645
  const chained = (prev ?? Promise.resolve()).then(() => mine);
2653
2646
  sessionWriteLocks.set(input.cacheKey, chained);
@@ -2833,7 +2826,7 @@ async function ensureWhatsAppConversation(input) {
2833
2826
 
2834
2827
  // ../lib/account-enumeration/src/index.ts
2835
2828
  import { readdirSync, readFileSync as readFileSync3 } from "fs";
2836
- import { resolve } from "path";
2829
+ import { resolve as resolve2 } from "path";
2837
2830
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2838
2831
  var cache = /* @__PURE__ */ new Map();
2839
2832
  function enumerateValidAccountIds(accountsDir) {
@@ -2852,7 +2845,7 @@ function enumerateValidAccountIds(accountsDir) {
2852
2845
  const valid = [];
2853
2846
  for (const name of names) {
2854
2847
  if (!UUID_RE.test(name)) continue;
2855
- const configPath2 = resolve(accountsDir, name, "account.json");
2848
+ const configPath2 = resolve2(accountsDir, name, "account.json");
2856
2849
  try {
2857
2850
  JSON.parse(readFileSync3(configPath2, "utf-8"));
2858
2851
  valid.push(name);
@@ -2871,7 +2864,7 @@ function getAccountsDirFromEnv() {
2871
2864
  "[graph-write] MAXY_PLATFORM_ROOT not set \u2014 cannot enforce accountId gate. Set MAXY_PLATFORM_ROOT in the spawning process or pass `accountsDir` explicitly."
2872
2865
  );
2873
2866
  }
2874
- return resolve(root, "..", "data/accounts");
2867
+ return resolve2(root, "..", "data/accounts");
2875
2868
  }
2876
2869
  function validateAccountIdEnv(envValue, diskIds) {
2877
2870
  if (!envValue) {
@@ -2910,7 +2903,7 @@ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
2910
2903
  // app/lib/whatsapp/inbound/media.ts
2911
2904
  import { randomUUID as randomUUID2 } from "crypto";
2912
2905
  import { writeFile, mkdir } from "fs/promises";
2913
- import { join as join2 } from "path";
2906
+ import { join as join3 } from "path";
2914
2907
  import {
2915
2908
  downloadMediaMessage,
2916
2909
  downloadContentFromMessage,
@@ -2996,7 +2989,7 @@ async function downloadInboundMedia(msg, sock, opts) {
2996
2989
  await mkdir(MEDIA_DIR, { recursive: true });
2997
2990
  const ext = mimeToExt(mimetype ?? "application/octet-stream");
2998
2991
  const filename = `${randomUUID2()}.${ext}`;
2999
- const filePath = join2(MEDIA_DIR, filename);
2992
+ const filePath = join3(MEDIA_DIR, filename);
3000
2993
  await writeFile(filePath, buffer);
3001
2994
  const sizeKB = (buffer.length / 1024).toFixed(0);
3002
2995
  console.error(`${TAG9} media downloaded type=${mimetype ?? "unknown"} size=${sizeKB}KB path=${filePath}`);
@@ -3727,11 +3720,11 @@ async function connectWithReconnect(conn) {
3727
3720
  console.error(
3728
3721
  `${TAG13} reconnecting account=${conn.accountId} in ${delay}ms (attempt ${decision.nextAttempts}/${maxAttempts})`
3729
3722
  );
3730
- await new Promise((resolve29) => {
3731
- const timer2 = setTimeout(resolve29, delay);
3723
+ await new Promise((resolve30) => {
3724
+ const timer2 = setTimeout(resolve30, delay);
3732
3725
  conn.abortController.signal.addEventListener("abort", () => {
3733
3726
  clearTimeout(timer2);
3734
- resolve29();
3727
+ resolve30();
3735
3728
  }, { once: true });
3736
3729
  });
3737
3730
  }
@@ -3739,16 +3732,16 @@ async function connectWithReconnect(conn) {
3739
3732
  }
3740
3733
  }
3741
3734
  function waitForDisconnectEvent(conn) {
3742
- return new Promise((resolve29) => {
3735
+ return new Promise((resolve30) => {
3743
3736
  if (!conn.sock) {
3744
- resolve29();
3737
+ resolve30();
3745
3738
  return;
3746
3739
  }
3747
3740
  const sock = conn.sock;
3748
3741
  const handler = (update) => {
3749
3742
  if (update.connection === "close") {
3750
3743
  sock.ev.off("connection.update", handler);
3751
- resolve29();
3744
+ resolve30();
3752
3745
  }
3753
3746
  };
3754
3747
  sock.ev.on("connection.update", handler);
@@ -4008,8 +4001,8 @@ async function handleInboundMessage(conn, msg) {
4008
4001
  const conversationKey = isGroup ? remoteJid : senderPhone;
4009
4002
  const debounceKey = `${conn.accountId}:${conversationKey}:${senderPhone}`;
4010
4003
  let resolvePending;
4011
- const sttPending = new Promise((resolve29) => {
4012
- resolvePending = resolve29;
4004
+ const sttPending = new Promise((resolve30) => {
4005
+ resolvePending = resolve30;
4013
4006
  });
4014
4007
  if (conn.debouncer) conn.debouncer.registerPending(debounceKey, sttPending);
4015
4008
  try {
@@ -4106,9 +4099,9 @@ async function handleInboundMessage(conn, msg) {
4106
4099
  import { spawnSync, execFileSync } from "child_process";
4107
4100
  import { createConnection } from "net";
4108
4101
  import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
4109
- import { resolve as resolve2 } from "path";
4110
- var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve2(process.cwd(), "..");
4111
- var VNC_SCRIPT = resolve2(PLATFORM_ROOT2, "scripts/vnc.sh");
4102
+ import { resolve as resolve3 } from "path";
4103
+ var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve3(process.cwd(), "..");
4104
+ var VNC_SCRIPT = resolve3(PLATFORM_ROOT2, "scripts/vnc.sh");
4112
4105
  var displayMode = process.env.DISPLAY_MODE ?? "virtual";
4113
4106
  if (displayMode === "native") {
4114
4107
  console.log(`[vnc] DISPLAY_MODE=native \u2014 local requests use desktop display, remote requests use VNC`);
@@ -4221,7 +4214,7 @@ function ensureLogDir() {
4221
4214
  mkdirSync(LOG_DIR, { recursive: true });
4222
4215
  }
4223
4216
  function logPath(name) {
4224
- return resolve2(LOG_DIR, `${name}.log`);
4217
+ return resolve3(LOG_DIR, `${name}.log`);
4225
4218
  }
4226
4219
  async function ensureVnc() {
4227
4220
  const up = await waitForPort(RFB_PORT, 1e3);
@@ -4300,7 +4293,7 @@ function killChromium() {
4300
4293
  }
4301
4294
  function writeChromiumWrapper() {
4302
4295
  mkdirSync(BIN_DIR, { recursive: true });
4303
- const wrapperPath = resolve2(BIN_DIR, "chromium");
4296
+ const wrapperPath = resolve3(BIN_DIR, "chromium");
4304
4297
  writeFileSync3(wrapperPath, `#!/bin/bash
4305
4298
  LOG="${LOG_DIR}/chromium.log"
4306
4299
  echo "==== [$(date)] chromium wrapper ====" >> "$LOG"
@@ -4400,20 +4393,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
4400
4393
 
4401
4394
  // server/routes/health.ts
4402
4395
  function checkPort(port2, timeoutMs = 500) {
4403
- return new Promise((resolve29) => {
4396
+ return new Promise((resolve30) => {
4404
4397
  const socket = createConnection2(port2, "127.0.0.1");
4405
4398
  socket.setTimeout(timeoutMs);
4406
4399
  socket.once("connect", () => {
4407
4400
  socket.destroy();
4408
- resolve29(true);
4401
+ resolve30(true);
4409
4402
  });
4410
4403
  socket.once("error", () => {
4411
4404
  socket.destroy();
4412
- resolve29(false);
4405
+ resolve30(false);
4413
4406
  });
4414
4407
  socket.once("timeout", () => {
4415
4408
  socket.destroy();
4416
- resolve29(false);
4409
+ resolve30(false);
4417
4410
  });
4418
4411
  });
4419
4412
  }
@@ -4483,9 +4476,9 @@ var health_default = app;
4483
4476
  import { randomUUID as randomUUID3 } from "crypto";
4484
4477
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
4485
4478
  import { realpathSync } from "fs";
4486
- import { resolve as resolve3, extname } from "path";
4487
- var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve3(process.cwd(), "../platform");
4488
- var ATTACHMENTS_ROOT = resolve3(PLATFORM_ROOT3, "..", "data/uploads");
4479
+ import { resolve as resolve4, extname } from "path";
4480
+ var PLATFORM_ROOT3 = process.env.MAXY_PLATFORM_ROOT ?? resolve4(process.cwd(), "../platform");
4481
+ var ATTACHMENTS_ROOT = resolve4(PLATFORM_ROOT3, "..", "data/uploads");
4489
4482
  var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
4490
4483
  "image/jpeg",
4491
4484
  "image/png",
@@ -4512,11 +4505,11 @@ function assertSupportedMime(mimeType) {
4512
4505
  }
4513
4506
  async function writeAttachment(scope, filename, mimeType, sizeBytes, buffer) {
4514
4507
  const attachmentId = randomUUID3();
4515
- const dir = resolve3(ATTACHMENTS_ROOT, scope, attachmentId);
4508
+ const dir = resolve4(ATTACHMENTS_ROOT, scope, attachmentId);
4516
4509
  await mkdir2(dir, { recursive: true });
4517
4510
  const ext = extname(filename) || "";
4518
- const storagePath = resolve3(dir, `${attachmentId}${ext}`);
4519
- const metaPath = resolve3(dir, `${attachmentId}.meta.json`);
4511
+ const storagePath = resolve4(dir, `${attachmentId}${ext}`);
4512
+ const metaPath = resolve4(dir, `${attachmentId}.meta.json`);
4520
4513
  const meta = {
4521
4514
  attachmentId,
4522
4515
  scope,
@@ -4590,11 +4583,11 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
4590
4583
  `Component artefact exceeds the 50 MB limit (${(buffer.byteLength / 1024 / 1024).toFixed(1)} MB).`
4591
4584
  );
4592
4585
  }
4593
- const dir = resolve3(ATTACHMENTS_ROOT, accountId, attachmentId);
4586
+ const dir = resolve4(ATTACHMENTS_ROOT, accountId, attachmentId);
4594
4587
  await mkdir2(dir, { recursive: true });
4595
4588
  const ext = extname(filename) || (mimeType === "text/html" ? ".html" : ".md");
4596
- const storagePath = resolve3(dir, `${attachmentId}${ext}`);
4597
- const metaPath = resolve3(dir, `${attachmentId}.meta.json`);
4589
+ const storagePath = resolve4(dir, `${attachmentId}${ext}`);
4590
+ const metaPath = resolve4(dir, `${attachmentId}.meta.json`);
4598
4591
  const meta = {
4599
4592
  attachmentId,
4600
4593
  scope: accountId,
@@ -4611,7 +4604,7 @@ async function storeComponentArtefact(accountId, attachmentId, mimeType, content
4611
4604
  // app/lib/stt/voice-note.ts
4612
4605
  import { writeFile as writeFile3, mkdtemp, rm } from "fs/promises";
4613
4606
  import { tmpdir } from "os";
4614
- import { join as join3 } from "path";
4607
+ import { join as join4 } from "path";
4615
4608
  var TAG14 = "[voice]";
4616
4609
  var AUDIO_MIME_TYPES = /* @__PURE__ */ new Set([
4617
4610
  "audio/ogg",
@@ -4655,9 +4648,9 @@ async function transcribeVoiceNote(file, source) {
4655
4648
  let tempDir;
4656
4649
  let tempPath;
4657
4650
  try {
4658
- tempDir = await mkdtemp(join3(tmpdir(), "voice-"));
4651
+ tempDir = await mkdtemp(join4(tmpdir(), "voice-"));
4659
4652
  const ext = audioExtension(mimeType);
4660
- tempPath = join3(tempDir, `recording${ext}`);
4653
+ tempPath = join4(tempDir, `recording${ext}`);
4661
4654
  const buffer = Buffer.from(await file.arrayBuffer());
4662
4655
  await writeFile3(tempPath, buffer);
4663
4656
  } catch (err) {
@@ -4698,7 +4691,7 @@ async function transcribeVoiceNote(file, source) {
4698
4691
  }
4699
4692
 
4700
4693
  // app/lib/channel-pty-bridge/bridge.ts
4701
- import { resolve as resolve5 } from "path";
4694
+ import { resolve as resolve6 } from "path";
4702
4695
 
4703
4696
  // app/lib/channel-pty-bridge/manager-client.ts
4704
4697
  function managerBase() {
@@ -5150,7 +5143,7 @@ async function fanOut(subscribers, text, onError, tag) {
5150
5143
  // app/lib/whatsapp/outbound/send-document.ts
5151
5144
  import { realpathSync as realpathSync2 } from "fs";
5152
5145
  import { readFile, stat as stat2 } from "fs/promises";
5153
- import { resolve as resolve4, basename } from "path";
5146
+ import { resolve as resolve5, basename } from "path";
5154
5147
  var TAG16 = "[whatsapp:outbound]";
5155
5148
  var WHATSAPP_DOCUMENT_MAX_BYTES = 100 * 1024 * 1024;
5156
5149
  var lastDocumentOutboundAt = /* @__PURE__ */ new Map();
@@ -5181,7 +5174,7 @@ async function sendWhatsAppDocument(input) {
5181
5174
  if (!maxyAccountId || !platformRoot2) {
5182
5175
  return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
5183
5176
  }
5184
- const accountDir = resolve4(platformRoot2, "..", "data/accounts", maxyAccountId);
5177
+ const accountDir = resolve5(platformRoot2, "..", "data/accounts", maxyAccountId);
5185
5178
  let resolvedPath;
5186
5179
  try {
5187
5180
  resolvedPath = realpathSync2(filePath);
@@ -5388,7 +5381,7 @@ async function ensureEntry(input) {
5388
5381
  });
5389
5382
  } else {
5390
5383
  console.error(`${tag} route role=${input.role} target=public-spawn senderId=${input.senderId}`);
5391
- const attachmentDir = resolve5(ATTACHMENTS_ROOT, "public", input.senderId);
5384
+ const attachmentDir = resolve6(ATTACHMENTS_ROOT, "public", input.senderId);
5392
5385
  spawned = await managerSpawn({
5393
5386
  senderId: input.senderId,
5394
5387
  role: input.role,
@@ -5520,12 +5513,12 @@ async function dispatchOnce(input) {
5520
5513
  });
5521
5514
  if (!entry) return { error: "spawn-failed" };
5522
5515
  entry.lastInboundAt = Date.now();
5523
- let resolve29;
5516
+ let resolve30;
5524
5517
  const turnPromise = new Promise((r) => {
5525
- resolve29 = r;
5518
+ resolve30 = r;
5526
5519
  });
5527
5520
  const listener = (text) => {
5528
- resolve29(text);
5521
+ resolve30(text);
5529
5522
  };
5530
5523
  entry.subscribers.add(listener);
5531
5524
  const writeAtMs = Date.now();
@@ -5895,7 +5888,7 @@ ${result.result.text}` : result.result.text;
5895
5888
  var chat_default = app2;
5896
5889
 
5897
5890
  // server/routes/whatsapp.ts
5898
- import { join as join6, resolve as resolve7 } from "path";
5891
+ import { join as join7, resolve as resolve8 } from "path";
5899
5892
  import { readdirSync as readdirSync3, readFileSync as readFileSync7, existsSync as existsSync5 } from "fs";
5900
5893
 
5901
5894
  // app/lib/whatsapp/login.ts
@@ -5903,10 +5896,10 @@ import { randomUUID as randomUUID6 } from "crypto";
5903
5896
 
5904
5897
  // app/lib/whatsapp/config-persist.ts
5905
5898
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
5906
- import { resolve as resolve6, join as join4 } from "path";
5899
+ import { resolve as resolve7, join as join5 } from "path";
5907
5900
  var TAG18 = "[whatsapp:config]";
5908
5901
  function configPath(accountDir) {
5909
- return resolve6(accountDir, "account.json");
5902
+ return resolve7(accountDir, "account.json");
5910
5903
  }
5911
5904
  function readConfig(accountDir) {
5912
5905
  const path2 = configPath(accountDir);
@@ -6055,7 +6048,7 @@ function setPublicAgent(accountDir, slug) {
6055
6048
  if (!trimmed) {
6056
6049
  return { ok: false, error: "Agent slug cannot be empty." };
6057
6050
  }
6058
- const agentConfigPath = join4(accountDir, "agents", trimmed, "config.json");
6051
+ const agentConfigPath = join5(accountDir, "agents", trimmed, "config.json");
6059
6052
  if (!existsSync4(agentConfigPath)) {
6060
6053
  return { ok: false, error: `Agent "${trimmed}" not found \u2014 no config.json at ${agentConfigPath}. Check the agent slug and try again.` };
6061
6054
  }
@@ -6313,8 +6306,8 @@ async function startLogin(opts) {
6313
6306
  await clearAuth(authDir);
6314
6307
  let resolveCode = null;
6315
6308
  let rejectCode = null;
6316
- const codePromise = new Promise((resolve29, reject) => {
6317
- resolveCode = resolve29;
6309
+ const codePromise = new Promise((resolve30, reject) => {
6310
+ resolveCode = resolve30;
6318
6311
  rejectCode = reject;
6319
6312
  });
6320
6313
  const codeTimer = setTimeout(
@@ -6546,11 +6539,11 @@ function serializeWhatsAppSchema() {
6546
6539
 
6547
6540
  // app/lib/whatsapp/status-reconcile.ts
6548
6541
  import { readdirSync as readdirSync2 } from "fs";
6549
- import { join as join5 } from "path";
6542
+ import { join as join6 } from "path";
6550
6543
  var TAG20 = "[whatsapp:reconcile]";
6551
6544
  function listCredsAccountIds(credsRoot) {
6552
6545
  try {
6553
- return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join5(credsRoot, e.name))).map((e) => e.name);
6546
+ return readdirSync2(credsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && hasCredsSync(join6(credsRoot, e.name))).map((e) => e.name);
6554
6547
  } catch {
6555
6548
  return [];
6556
6549
  }
@@ -6565,7 +6558,7 @@ function reconcileCredsOnDisk(opts) {
6565
6558
  const entries = [];
6566
6559
  for (const accountId of listCredsAccountIds(credsRoot)) {
6567
6560
  if (liveAccountIds.has(accountId)) continue;
6568
- const authDir = join5(credsRoot, accountId);
6561
+ const authDir = join6(credsRoot, accountId);
6569
6562
  const selfPhone = readSelfId(authDir).e164 ?? void 0;
6570
6563
  const configured = accountDir ? isAccountConfigured(accountDir, accountId) : false;
6571
6564
  console.error(
@@ -6592,7 +6585,7 @@ app3.get("/status", (c) => {
6592
6585
  try {
6593
6586
  const live = getStatus();
6594
6587
  const liveIds = new Set(live.map((a) => a.accountId));
6595
- const credsRoot = join6(MAXY_DIR, "credentials", "whatsapp");
6588
+ const credsRoot = join7(MAXY_DIR, "credentials", "whatsapp");
6596
6589
  const accountDir = resolveAccount()?.accountDir ?? null;
6597
6590
  const reconciled = reconcileCredsOnDisk({ credsRoot, accountDir, liveAccountIds: liveIds });
6598
6591
  const accounts = [...live, ...reconciled];
@@ -6613,7 +6606,7 @@ app3.post("/login/start", async (c) => {
6613
6606
  if (!phone) {
6614
6607
  return c.json({ error: 'Missing required field "phone" (E.164, e.g. +441234567890).' }, 400);
6615
6608
  }
6616
- const authDir = join6(MAXY_DIR, "credentials", "whatsapp", accountId);
6609
+ const authDir = join7(MAXY_DIR, "credentials", "whatsapp", accountId);
6617
6610
  const accountDir = resolveAccount()?.accountDir ?? null;
6618
6611
  const result = await startLogin({ accountId, authDir, phone, accountDir, force });
6619
6612
  console.error(`${TAG21} login/start result account=${accountId} hasCode=${!!result.pairingCode}${result.selfPhone ? ` phone=${result.selfPhone}` : ""}`);
@@ -6711,14 +6704,14 @@ app3.post("/config", async (c) => {
6711
6704
  return c.json({ ok: true, slug: resolved?.slug ?? null, source: resolved?.source ?? null });
6712
6705
  }
6713
6706
  case "list-public-agents": {
6714
- const agentsDir = resolve7(account.accountDir, "agents");
6707
+ const agentsDir = resolve8(account.accountDir, "agents");
6715
6708
  const agents = [];
6716
6709
  if (existsSync5(agentsDir)) {
6717
6710
  try {
6718
6711
  const entries = readdirSync3(agentsDir, { withFileTypes: true });
6719
6712
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
6720
6713
  if (!entry.isDirectory() || entry.name === "admin") continue;
6721
- const configPath2 = resolve7(agentsDir, entry.name, "config.json");
6714
+ const configPath2 = resolve8(agentsDir, entry.name, "config.json");
6722
6715
  if (!existsSync5(configPath2)) continue;
6723
6716
  try {
6724
6717
  const config = JSON.parse(readFileSync7(configPath2, "utf-8"));
@@ -6991,11 +6984,11 @@ var whatsapp_default = app3;
6991
6984
 
6992
6985
  // server/routes/whatsapp-reader.ts
6993
6986
  import { readFileSync as readFileSync10, watch, statSync as statSync4, openSync, readSync, closeSync, existsSync as existsSync7, readdirSync as readdirSync6 } from "fs";
6994
- import { basename as basename2, dirname, join as join9, resolve as resolve9, sep as sep2 } from "path";
6987
+ import { basename as basename2, dirname, join as join10, resolve as resolve10, sep as sep2 } from "path";
6995
6988
 
6996
6989
  // server/routes/admin/sidebar-sessions.ts
6997
6990
  import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
6998
- import { join as join7, resolve as resolve8 } from "path";
6991
+ import { join as join8, resolve as resolve9 } from "path";
6999
6992
  var SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/i;
7000
6993
  var CLI_MARKER_PREFIXES = ["<local-command-", "<command-name>", "<command-message>"];
7001
6994
  var PUBLIC_ROLE = "public";
@@ -7014,7 +7007,7 @@ function enumerateJsonls(projectsRoot) {
7014
7007
  throw err;
7015
7008
  }
7016
7009
  for (const slug of slugs) {
7017
- const slugDir = join7(projectsRoot, slug);
7010
+ const slugDir = join8(projectsRoot, slug);
7018
7011
  let entries;
7019
7012
  try {
7020
7013
  entries = readdirSync4(slugDir, { withFileTypes: true });
@@ -7025,9 +7018,9 @@ function enumerateJsonls(projectsRoot) {
7025
7018
  }
7026
7019
  for (const entry of entries) {
7027
7020
  if (entry.isFile() && SESSION_ID_RE.test(entry.name)) {
7028
- out.push({ path: join7(slugDir, entry.name), isSubagent: false, archived: false });
7021
+ out.push({ path: join8(slugDir, entry.name), isSubagent: false, archived: false });
7029
7022
  } else if (entry.isDirectory() && entry.name === "subagents") {
7030
- const subDir = join7(slugDir, entry.name);
7023
+ const subDir = join8(slugDir, entry.name);
7031
7024
  let subEntries;
7032
7025
  try {
7033
7026
  subEntries = readdirSync4(subDir, { withFileTypes: true });
@@ -7038,11 +7031,11 @@ function enumerateJsonls(projectsRoot) {
7038
7031
  }
7039
7032
  for (const sub of subEntries) {
7040
7033
  if (sub.isFile() && SESSION_ID_RE.test(sub.name)) {
7041
- out.push({ path: join7(subDir, sub.name), isSubagent: true, archived: false });
7034
+ out.push({ path: join8(subDir, sub.name), isSubagent: true, archived: false });
7042
7035
  }
7043
7036
  }
7044
7037
  } else if (entry.isDirectory() && entry.name === "archive") {
7045
- const archiveDir = join7(slugDir, entry.name);
7038
+ const archiveDir = join8(slugDir, entry.name);
7046
7039
  let archiveEntries;
7047
7040
  try {
7048
7041
  archiveEntries = readdirSync4(archiveDir, { withFileTypes: true });
@@ -7053,7 +7046,7 @@ function enumerateJsonls(projectsRoot) {
7053
7046
  }
7054
7047
  for (const arc of archiveEntries) {
7055
7048
  if (arc.isFile() && SESSION_ID_RE.test(arc.name)) {
7056
- out.push({ path: join7(archiveDir, arc.name), isSubagent: false, archived: true });
7049
+ out.push({ path: join8(archiveDir, arc.name), isSubagent: false, archived: true });
7057
7050
  }
7058
7051
  }
7059
7052
  }
@@ -7086,7 +7079,7 @@ async function fetchLiveSessions() {
7086
7079
  function loadUserTitles(accountDir) {
7087
7080
  const out = /* @__PURE__ */ new Map();
7088
7081
  if (!accountDir) return out;
7089
- const path2 = join7(accountDir, "session-titles.json");
7082
+ const path2 = join8(accountDir, "session-titles.json");
7090
7083
  let raw;
7091
7084
  try {
7092
7085
  raw = readFileSync8(path2, "utf8");
@@ -7183,10 +7176,10 @@ app4.get("/", requireAdminSession, async (c) => {
7183
7176
  console.error("[admin-sessions-list] CLAUDE_CONFIG_DIR not set; returning empty list");
7184
7177
  return c.json({ sessions: [], accountId });
7185
7178
  }
7186
- const projectsRoot = join7(configDir2, "projects");
7179
+ const projectsRoot = join8(configDir2, "projects");
7187
7180
  const jsonls = enumerateJsonls(projectsRoot);
7188
7181
  const liveSessions = await fetchLiveSessions();
7189
- const accountDir = accountId ? resolve8(ACCOUNTS_DIR, accountId) : null;
7182
+ const accountDir = accountId ? resolve9(ACCOUNTS_DIR, accountId) : null;
7190
7183
  const userTitles = loadUserTitles(accountDir);
7191
7184
  const rows = [];
7192
7185
  const seenIds = /* @__PURE__ */ new Set();
@@ -7217,7 +7210,7 @@ app4.get("/", requireAdminSession, async (c) => {
7217
7210
  const pid = live ? liveSessions.get(sessionId) ?? null : null;
7218
7211
  const resolved = resolveTitle(body, sessionId, userTitles);
7219
7212
  titleSourceCounts[resolved.source] += 1;
7220
- const metaPath = join7(projectDir, `${sessionId}.meta.json`);
7213
+ const metaPath = join8(projectDir, `${sessionId}.meta.json`);
7221
7214
  const { bridgeIds, role, channel } = readSidecarMeta(metaPath);
7222
7215
  const resumable = !(role === PUBLIC_ROLE && channel === WEBCHAT_CHANNEL);
7223
7216
  rows.push({
@@ -7264,7 +7257,7 @@ function selectAdminChannelSessions(rows) {
7264
7257
  // app/lib/admin-identity/pin-validator.ts
7265
7258
  import { createHash as createHash2 } from "crypto";
7266
7259
  import { existsSync as existsSync6, readFileSync as readFileSync9, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
7267
- import { join as join8 } from "path";
7260
+ import { join as join9 } from "path";
7268
7261
  function hashPin(pin) {
7269
7262
  return createHash2("sha256").update(pin).digest("hex");
7270
7263
  }
@@ -7298,13 +7291,13 @@ function scanForOrphanedAccountAdmins(users, accountsDir) {
7298
7291
  }
7299
7292
  for (const entry of entries) {
7300
7293
  if (entry.startsWith(".")) continue;
7301
- const accountDir = join8(accountsDir, entry);
7294
+ const accountDir = join9(accountsDir, entry);
7302
7295
  try {
7303
7296
  if (!statSync3(accountDir).isDirectory()) continue;
7304
7297
  } catch {
7305
7298
  continue;
7306
7299
  }
7307
- const accountJsonPath = join8(accountDir, "account.json");
7300
+ const accountJsonPath = join9(accountDir, "account.json");
7308
7301
  if (!existsSync6(accountJsonPath)) continue;
7309
7302
  try {
7310
7303
  const config = JSON.parse(readFileSync9(accountJsonPath, "utf-8"));
@@ -7484,13 +7477,13 @@ var app5 = new Hono();
7484
7477
  app5.get("/conversations", requireAdminSession, async (c) => {
7485
7478
  const cfg = claudeConfigDir();
7486
7479
  if (!cfg) return c.json({ conversations: [] });
7487
- const projectsRoot = join9(cfg, "projects");
7480
+ const projectsRoot = join10(cfg, "projects");
7488
7481
  const userTitles = loadUserTitles(ACCOUNTS_DIR ?? null);
7489
7482
  const rows = [];
7490
7483
  for (const { path: path2 } of enumerateJsonls(projectsRoot)) {
7491
7484
  const sessionId = basename2(path2).replace(/\.jsonl$/, "");
7492
7485
  const projectDir = dirname(path2);
7493
- const meta = readSidecarMeta(join9(projectDir, `${sessionId}.meta.json`));
7486
+ const meta = readSidecarMeta(join10(projectDir, `${sessionId}.meta.json`));
7494
7487
  if (meta.role !== "admin" || meta.channel !== "whatsapp" && meta.channel !== "telegram") continue;
7495
7488
  let body = "";
7496
7489
  try {
@@ -7577,11 +7570,11 @@ app5.get("/stream", requireAdminSession, (c) => {
7577
7570
  const sessionId = c.req.query("sessionId") ?? "";
7578
7571
  const projectDir = c.req.query("projectDir") ?? "";
7579
7572
  const cfg = claudeConfigDir();
7580
- const projectsRoot = cfg ? resolve9(join9(cfg, "projects")) : null;
7573
+ const projectsRoot = cfg ? resolve10(join10(cfg, "projects")) : null;
7581
7574
  if (!cfg || !projectsRoot || !SESSION_ID_RE2.test(sessionId)) {
7582
7575
  return c.json({ error: "bad session reference" }, 400);
7583
7576
  }
7584
- const jsonlPath = resolve9(join9(projectDir, `${sessionId}.jsonl`));
7577
+ const jsonlPath = resolve10(join10(projectDir, `${sessionId}.jsonl`));
7585
7578
  if (!jsonlPath.startsWith(projectsRoot + sep2)) {
7586
7579
  return c.json({ error: "bad session reference" }, 400);
7587
7580
  }
@@ -7668,7 +7661,7 @@ var DIRECTIVE_NAME_RE = /^\d+-\d+\.txt$/;
7668
7661
  function directiveStoreDir(sessionId) {
7669
7662
  const account = resolveAccount();
7670
7663
  if (!account) return null;
7671
- return resolve9(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
7664
+ return resolve10(account.accountDir, "logs", "prompt-optimiser-directives", sessionId);
7672
7665
  }
7673
7666
  app5.get("/directives", requireAdminSession, (c) => {
7674
7667
  const sessionId = c.req.query("sessionId") ?? "";
@@ -7687,7 +7680,7 @@ app5.get("/directives", requireAdminSession, (c) => {
7687
7680
  const pid = Number(pidPart);
7688
7681
  let len = 0;
7689
7682
  try {
7690
- len = statSync4(join9(dir, name)).size;
7683
+ len = statSync4(join10(dir, name)).size;
7691
7684
  } catch {
7692
7685
  }
7693
7686
  return { name, secs, pid, ts: Number.isFinite(secs) ? new Date(secs * 1e3).toISOString() : null, len };
@@ -7702,7 +7695,7 @@ app5.get("/directive", requireAdminSession, (c) => {
7702
7695
  }
7703
7696
  const dir = directiveStoreDir(sessionId);
7704
7697
  if (!dir) return c.json({ error: "no account" }, 404);
7705
- const path2 = resolve9(join9(dir, name));
7698
+ const path2 = resolve10(join10(dir, name));
7706
7699
  if (!path2.startsWith(dir + sep2)) return c.json({ error: "bad reference" }, 400);
7707
7700
  let body;
7708
7701
  try {
@@ -7716,22 +7709,34 @@ var whatsapp_reader_default = app5;
7716
7709
 
7717
7710
  // server/routes/webchat.ts
7718
7711
  import { basename as basename3, dirname as dirname2 } from "path";
7719
- import { join as join10 } from "path";
7720
- import { readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync5 } from "fs";
7712
+ import { join as join11 } from "path";
7713
+ import { existsSync as existsSync8, readdirSync as readdirSync7, readFileSync as readFileSync11, renameSync, writeFileSync as writeFileSync5 } from "fs";
7721
7714
  var WEBCHAT_ADMIN_KEY = "webchat-admin";
7722
7715
  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;
7723
7716
  function locateSession(sessionId) {
7724
7717
  const cfg = claudeConfigDir();
7725
7718
  if (!cfg) return { projectDir: null, channel: null };
7726
- for (const { path: path2 } of enumerateJsonls(join10(cfg, "projects"))) {
7719
+ for (const { path: path2 } of enumerateJsonls(join11(cfg, "projects"))) {
7727
7720
  if (basename3(path2) === `${sessionId}.jsonl`) {
7728
7721
  const dir = dirname2(path2);
7729
- const meta = readSidecarMeta(join10(dir, `${sessionId}.meta.json`));
7722
+ const meta = readSidecarMeta(join11(dir, `${sessionId}.meta.json`));
7730
7723
  return { projectDir: dir, channel: meta.channel };
7731
7724
  }
7732
7725
  }
7733
7726
  return { projectDir: null, channel: null };
7734
7727
  }
7728
+ function sessionSidecarExists(sessionId) {
7729
+ const cfg = claudeConfigDir();
7730
+ if (!cfg) return false;
7731
+ const projectsRoot = join11(cfg, "projects");
7732
+ let slugs;
7733
+ try {
7734
+ slugs = readdirSync7(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
7735
+ } catch {
7736
+ return false;
7737
+ }
7738
+ return slugs.some((slug) => existsSync8(join11(projectsRoot, slug, `${sessionId}.meta.json`)));
7739
+ }
7735
7740
  function conflictingBinding(channel) {
7736
7741
  return channel !== null && channel !== "webchat" ? channel : null;
7737
7742
  }
@@ -7958,7 +7963,7 @@ ${note}` : note;
7958
7963
  console.error(`[webchat:settings] op=${op} outcome=refused value=${value} reason=account-unresolved`);
7959
7964
  return c.json({ error: "account unresolved" }, 503);
7960
7965
  }
7961
- const accountJsonPath = join10(account.accountDir, "account.json");
7966
+ const accountJsonPath = join11(account.accountDir, "account.json");
7962
7967
  try {
7963
7968
  const parsed = JSON.parse(readFileSync11(accountJsonPath, "utf8"));
7964
7969
  if (op === "model") parsed.adminModel = value;
@@ -7991,14 +7996,15 @@ ${note}` : note;
7991
7996
  return c.json({ error: "invalid session id" }, 400);
7992
7997
  }
7993
7998
  const { projectDir: projectDir2, channel } = locateSession(target);
7999
+ const known = projectDir2 !== null || sessionSidecarExists(target);
7994
8000
  const indicators2 = await fetchComposerIndicators(target);
7995
- return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), ...indicators2 });
8001
+ return c.json({ sessionId: target, projectDir: projectDir2, channelBinding: conflictingBinding(channel), known, ...indicators2 });
7996
8002
  }
7997
8003
  const sessionId = adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY);
7998
8004
  const cfg = claudeConfigDir();
7999
8005
  let projectDir = null;
8000
8006
  if (cfg) {
8001
- for (const { path: path2 } of enumerateJsonls(join10(cfg, "projects"))) {
8007
+ for (const { path: path2 } of enumerateJsonls(join11(cfg, "projects"))) {
8002
8008
  if (basename3(path2) === `${sessionId}.jsonl`) {
8003
8009
  projectDir = dirname2(path2);
8004
8010
  break;
@@ -8012,11 +8018,11 @@ ${note}` : note;
8012
8018
  }
8013
8019
 
8014
8020
  // server/routes/webchat-greeting.ts
8015
- import { resolve as resolve10 } from "path";
8021
+ import { resolve as resolve11 } from "path";
8016
8022
 
8017
8023
  // app/lib/claude-agent/specialist-roster.ts
8018
- import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync7 } from "fs";
8019
- import { join as join11 } from "path";
8024
+ import { existsSync as existsSync9, readFileSync as readFileSync12, readdirSync as readdirSync8 } from "fs";
8025
+ import { join as join12 } from "path";
8020
8026
  function field(fm, name) {
8021
8027
  const m = fm.match(new RegExp(`^${name}:\\s*(.*?)\\r?$`, "m"));
8022
8028
  if (!m) return null;
@@ -8027,15 +8033,15 @@ function field(fm, name) {
8027
8033
  return value || null;
8028
8034
  }
8029
8035
  function readSpecialistRoster(specialistsDir) {
8030
- if (!existsSync8(specialistsDir)) return { specialists: [], skipped: [] };
8031
- const entries = readdirSync7(specialistsDir);
8036
+ if (!existsSync9(specialistsDir)) return { specialists: [], skipped: [] };
8037
+ const entries = readdirSync8(specialistsDir);
8032
8038
  const specialists = [];
8033
8039
  const skipped = [];
8034
8040
  for (const file of entries.sort()) {
8035
8041
  if (!file.endsWith(".md")) continue;
8036
8042
  let raw;
8037
8043
  try {
8038
- raw = readFileSync12(join11(specialistsDir, file), "utf-8");
8044
+ raw = readFileSync12(join12(specialistsDir, file), "utf-8");
8039
8045
  } catch (err) {
8040
8046
  skipped.push({ file, reason: err instanceof Error ? err.message : String(err) });
8041
8047
  continue;
@@ -8117,7 +8123,7 @@ app6.get("/", requireAdminSession, async (c) => {
8117
8123
  let specialists = [];
8118
8124
  try {
8119
8125
  const roster = readSpecialistRoster(
8120
- resolve10(ACCOUNTS_DIR, accountId, "specialists", "agents")
8126
+ resolve11(ACCOUNTS_DIR, accountId, "specialists", "agents")
8121
8127
  );
8122
8128
  specialists = roster.specialists;
8123
8129
  for (const s of roster.skipped) {
@@ -8152,8 +8158,8 @@ var webchat_greeting_default = app6;
8152
8158
 
8153
8159
  // server/routes/telegram.ts
8154
8160
  import { homedir } from "os";
8155
- import { resolve as resolve11, join as join12 } from "path";
8156
- import { existsSync as existsSync9, readFileSync as readFileSync13 } from "fs";
8161
+ import { resolve as resolve12, join as join13 } from "path";
8162
+ import { existsSync as existsSync10, readFileSync as readFileSync13 } from "fs";
8157
8163
 
8158
8164
  // app/lib/telegram/access-control.ts
8159
8165
  function checkTelegramAccess(params) {
@@ -8203,9 +8209,9 @@ function routeTelegramUpdate(input) {
8203
8209
  var TAG22 = "[telegram-inbound]";
8204
8210
  var DISPATCH_TIMEOUT_MS = 12e4;
8205
8211
  function configDirName() {
8206
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve11(process.cwd(), "..");
8207
- const brandPath = join12(platformRoot2, "config", "brand.json");
8208
- if (existsSync9(brandPath)) {
8212
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? resolve12(process.cwd(), "..");
8213
+ const brandPath = join13(platformRoot2, "config", "brand.json");
8214
+ if (existsSync10(brandPath)) {
8209
8215
  try {
8210
8216
  return JSON.parse(readFileSync13(brandPath, "utf-8")).configDir ?? ".maxy";
8211
8217
  } catch {
@@ -8215,7 +8221,7 @@ function configDirName() {
8215
8221
  }
8216
8222
  function secretPath(botType) {
8217
8223
  const filename = botType === "admin" ? ".telegram-admin-webhook-secret" : ".telegram-webhook-secret";
8218
- return resolve11(homedir(), configDirName(), filename);
8224
+ return resolve12(homedir(), configDirName(), filename);
8219
8225
  }
8220
8226
  async function sendTelegram(botToken, chatId, text) {
8221
8227
  try {
@@ -8239,7 +8245,7 @@ app7.post("/", async (c) => {
8239
8245
  return c.json({ ok: false }, 400);
8240
8246
  }
8241
8247
  const sp = secretPath(botType);
8242
- if (!existsSync9(sp)) {
8248
+ if (!existsSync10(sp)) {
8243
8249
  console.error(`${TAG22} op=reject reason=no-secret-file botType=${botType}`);
8244
8250
  return c.json({ ok: false }, 401);
8245
8251
  }
@@ -8306,12 +8312,12 @@ var telegram_default = app7;
8306
8312
 
8307
8313
  // server/routes/onboarding.ts
8308
8314
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync2 } from "child_process";
8309
- import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync11, readFileSync as readFileSync15, unlinkSync } from "fs";
8315
+ import { openSync as openSync2, closeSync as closeSync2, writeFileSync as writeFileSync7, writeSync, existsSync as existsSync12, readFileSync as readFileSync15, unlinkSync } from "fs";
8310
8316
  import { createHash as createHash3, randomUUID as randomUUID7 } from "crypto";
8311
8317
 
8312
8318
  // ../lib/admins-write/src/index.ts
8313
- import { existsSync as existsSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync6, renameSync as renameSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
8314
- import { dirname as dirname3, join as join13 } from "path";
8319
+ import { existsSync as existsSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync6, renameSync as renameSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync9, statSync as statSync5 } from "fs";
8320
+ import { dirname as dirname3, join as join14 } from "path";
8315
8321
  function logLine(input, result) {
8316
8322
  const userIdShort = input.userId.slice(0, 8);
8317
8323
  console.error(
@@ -8328,7 +8334,7 @@ function writeAdminEntry(input) {
8328
8334
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
8329
8335
  try {
8330
8336
  let users = [];
8331
- if (existsSync10(input.usersFile)) {
8337
+ if (existsSync11(input.usersFile)) {
8332
8338
  const raw = readFileSync14(input.usersFile, "utf-8").trim();
8333
8339
  if (raw) {
8334
8340
  const parsed = JSON.parse(raw);
@@ -8353,8 +8359,8 @@ function writeAdminEntry(input) {
8353
8359
  return result;
8354
8360
  }
8355
8361
  try {
8356
- const accountJsonPath = join13(input.accountDir, "account.json");
8357
- if (!existsSync10(accountJsonPath)) {
8362
+ const accountJsonPath = join14(input.accountDir, "account.json");
8363
+ if (!existsSync11(accountJsonPath)) {
8358
8364
  throw new Error(`account.json not found at ${accountJsonPath}`);
8359
8365
  }
8360
8366
  const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
@@ -8381,7 +8387,7 @@ function checkAdminAuthInvariant(input) {
8381
8387
  usersWithoutAccount: []
8382
8388
  };
8383
8389
  const usersUserIds = /* @__PURE__ */ new Set();
8384
- if (existsSync10(input.usersFile)) {
8390
+ if (existsSync11(input.usersFile)) {
8385
8391
  try {
8386
8392
  const raw = readFileSync14(input.usersFile, "utf-8").trim();
8387
8393
  if (raw) {
@@ -8396,10 +8402,10 @@ function checkAdminAuthInvariant(input) {
8396
8402
  }
8397
8403
  }
8398
8404
  const accountUserIds = /* @__PURE__ */ new Set();
8399
- if (existsSync10(input.accountsDir)) {
8405
+ if (existsSync11(input.accountsDir)) {
8400
8406
  let entries;
8401
8407
  try {
8402
- entries = readdirSync8(input.accountsDir);
8408
+ entries = readdirSync9(input.accountsDir);
8403
8409
  } catch (err) {
8404
8410
  const msg = err instanceof Error ? err.message : String(err);
8405
8411
  console.error(`[${input.tag}] accounts-dir unreadable accountsDir=${input.accountsDir} error=${msg}`);
@@ -8408,14 +8414,14 @@ function checkAdminAuthInvariant(input) {
8408
8414
  }
8409
8415
  for (const entry of entries) {
8410
8416
  if (entry.startsWith(".")) continue;
8411
- const accountDir = join13(input.accountsDir, entry);
8417
+ const accountDir = join14(input.accountsDir, entry);
8412
8418
  try {
8413
8419
  if (!statSync5(accountDir).isDirectory()) continue;
8414
8420
  } catch {
8415
8421
  continue;
8416
8422
  }
8417
- const accountJsonPath = join13(accountDir, "account.json");
8418
- if (!existsSync10(accountJsonPath)) continue;
8423
+ const accountJsonPath = join14(accountDir, "account.json");
8424
+ if (!existsSync11(accountJsonPath)) continue;
8419
8425
  let admins = [];
8420
8426
  try {
8421
8427
  const config = JSON.parse(readFileSync14(accountJsonPath, "utf-8"));
@@ -8458,7 +8464,7 @@ function hashPin2(pin) {
8458
8464
  return createHash3("sha256").update(pin).digest("hex");
8459
8465
  }
8460
8466
  function readUsersFile2() {
8461
- if (!existsSync11(USERS_FILE)) return null;
8467
+ if (!existsSync12(USERS_FILE)) return null;
8462
8468
  const raw = readFileSync15(USERS_FILE, "utf-8").trim();
8463
8469
  if (!raw) return [];
8464
8470
  return JSON.parse(raw);
@@ -8512,7 +8518,7 @@ app8.post("/claude-auth", async (c) => {
8512
8518
  } catch (err) {
8513
8519
  logoutError = err instanceof Error ? err.message : String(err);
8514
8520
  }
8515
- const credentialsPresent = existsSync11(CLAUDE_CREDENTIALS_FILE);
8521
+ const credentialsPresent = existsSync12(CLAUDE_CREDENTIALS_FILE);
8516
8522
  const ranMs = Date.now() - start;
8517
8523
  console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
8518
8524
  return c.json({ logged_out: !credentialsPresent });
@@ -8619,7 +8625,7 @@ app8.post("/set-pin", async (c) => {
8619
8625
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
8620
8626
  if (process.platform === "linux") {
8621
8627
  let installOwner = null;
8622
- if (existsSync11(INSTALL_OWNER_FILE)) {
8628
+ if (existsSync12(INSTALL_OWNER_FILE)) {
8623
8629
  try {
8624
8630
  const raw = readFileSync15(INSTALL_OWNER_FILE, "utf-8").trim();
8625
8631
  if (raw.length > 0) installOwner = raw;
@@ -8702,9 +8708,9 @@ app8.delete("/set-pin", async (c) => {
8702
8708
  var onboarding_default = app8;
8703
8709
 
8704
8710
  // server/routes/client-error.ts
8705
- import { appendFileSync, existsSync as existsSync12, renameSync as renameSync3, statSync as statSync6 } from "fs";
8706
- import { join as join14 } from "path";
8707
- var CLIENT_ERRORS_LOG = join14(LOG_DIR, "client-errors.log");
8711
+ import { appendFileSync, existsSync as existsSync13, renameSync as renameSync3, statSync as statSync6 } from "fs";
8712
+ import { join as join15 } from "path";
8713
+ var CLIENT_ERRORS_LOG = join15(LOG_DIR, "client-errors.log");
8708
8714
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
8709
8715
  var MAX_BODY_SIZE = 8 * 1024;
8710
8716
  var MAX_STACK_LEN = 2e3;
@@ -8747,7 +8753,7 @@ function stackHead(stack) {
8747
8753
  }
8748
8754
  function rotateIfNeeded() {
8749
8755
  try {
8750
- if (!existsSync12(CLIENT_ERRORS_LOG)) return;
8756
+ if (!existsSync13(CLIENT_ERRORS_LOG)) return;
8751
8757
  const stats = statSync6(CLIENT_ERRORS_LOG);
8752
8758
  if (stats.size < MAX_LOG_SIZE) return;
8753
8759
  renameSync3(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
@@ -9029,18 +9035,18 @@ app10.post("/", async (c) => {
9029
9035
  var session_default = app10;
9030
9036
 
9031
9037
  // server/routes/admin/logs.ts
9032
- import { existsSync as existsSync14, readdirSync as readdirSync9, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
9033
- import { resolve as resolve12, basename as basename4 } from "path";
9038
+ import { existsSync as existsSync15, readdirSync as readdirSync10, readFileSync as readFileSync16, statSync as statSync7 } from "fs";
9039
+ import { resolve as resolve13, basename as basename4 } from "path";
9034
9040
 
9035
9041
  // app/lib/logs-read-resolve.ts
9036
- import { existsSync as existsSync13 } from "fs";
9037
- import { join as join15 } from "path";
9042
+ import { existsSync as existsSync14 } from "fs";
9043
+ import { join as join16 } from "path";
9038
9044
  function resolveSessionLogPaths(filename, logDirs) {
9039
9045
  const tried = [filename];
9040
9046
  const hits = [];
9041
9047
  for (const dir of logDirs) {
9042
- const fullPath = join15(dir, filename);
9043
- if (existsSync13(fullPath)) {
9048
+ const fullPath = join16(dir, filename);
9049
+ if (existsSync14(fullPath)) {
9044
9050
  hits.push({ path: fullPath, dir });
9045
9051
  }
9046
9052
  }
@@ -9057,7 +9063,7 @@ app11.get("/", async (c) => {
9057
9063
  const cacheKeyParam = c.req.query("cacheKey");
9058
9064
  const download = c.req.query("download") === "1";
9059
9065
  const account = resolveAccount();
9060
- const accountLogDir = account ? resolve12(account.accountDir, "logs") : null;
9066
+ const accountLogDir = account ? resolve13(account.accountDir, "logs") : null;
9061
9067
  const logDirs = [];
9062
9068
  if (accountLogDir) logDirs.push(accountLogDir);
9063
9069
  logDirs.push(LOG_DIR);
@@ -9065,7 +9071,7 @@ app11.get("/", async (c) => {
9065
9071
  const safe = basename4(fileParam);
9066
9072
  const searched = [];
9067
9073
  for (const dir of logDirs) {
9068
- const filePath = resolve12(dir, safe);
9074
+ const filePath = resolve13(dir, safe);
9069
9075
  searched.push(filePath);
9070
9076
  try {
9071
9077
  const buffer = readFileSync16(filePath);
@@ -9168,19 +9174,19 @@ app11.get("/", async (c) => {
9168
9174
  const seen = /* @__PURE__ */ new Set();
9169
9175
  const logs = {};
9170
9176
  for (const dir of logDirs) {
9171
- if (!existsSync14(dir)) continue;
9177
+ if (!existsSync15(dir)) continue;
9172
9178
  let files;
9173
9179
  try {
9174
- files = readdirSync9(dir).filter((f) => f.endsWith(".log"));
9180
+ files = readdirSync10(dir).filter((f) => f.endsWith(".log"));
9175
9181
  } catch (err) {
9176
9182
  const reason = err instanceof Error ? err.message : String(err);
9177
9183
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
9178
9184
  continue;
9179
9185
  }
9180
- 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 }) => {
9186
+ files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync7(resolve13(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
9181
9187
  seen.add(name);
9182
9188
  try {
9183
- const content = readFileSync16(resolve12(dir, name));
9189
+ const content = readFileSync16(resolve13(dir, name));
9184
9190
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
9185
9191
  logs[name] = tail.trim() || "(empty)";
9186
9192
  } catch (err) {
@@ -9219,8 +9225,8 @@ var claude_info_default = app12;
9219
9225
 
9220
9226
  // server/routes/admin/attachment.ts
9221
9227
  import { readFile as readFile2, readdir } from "fs/promises";
9222
- import { existsSync as existsSync15 } from "fs";
9223
- import { resolve as resolve13 } from "path";
9228
+ import { existsSync as existsSync16 } from "fs";
9229
+ import { resolve as resolve14 } from "path";
9224
9230
  var app13 = new Hono();
9225
9231
  app13.get("/:attachmentId", requireAdminSession, async (c) => {
9226
9232
  const attachmentId = c.req.param("attachmentId");
@@ -9232,12 +9238,12 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
9232
9238
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(attachmentId)) {
9233
9239
  return new Response("Not found", { status: 404 });
9234
9240
  }
9235
- const dir = resolve13(ATTACHMENTS_ROOT, accountId, attachmentId);
9236
- if (!existsSync15(dir)) {
9241
+ const dir = resolve14(ATTACHMENTS_ROOT, accountId, attachmentId);
9242
+ if (!existsSync16(dir)) {
9237
9243
  return new Response("Not found", { status: 404 });
9238
9244
  }
9239
- const metaPath = resolve13(dir, `${attachmentId}.meta.json`);
9240
- if (!existsSync15(metaPath)) {
9245
+ const metaPath = resolve14(dir, `${attachmentId}.meta.json`);
9246
+ if (!existsSync16(metaPath)) {
9241
9247
  return new Response("Not found", { status: 404 });
9242
9248
  }
9243
9249
  let meta;
@@ -9251,7 +9257,7 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
9251
9257
  if (!dataFile) {
9252
9258
  return new Response("Not found", { status: 404 });
9253
9259
  }
9254
- const filePath = resolve13(dir, dataFile);
9260
+ const filePath = resolve14(dir, dataFile);
9255
9261
  const buffer = await readFile2(filePath);
9256
9262
  return new Response(new Uint8Array(buffer), {
9257
9263
  headers: {
@@ -9264,22 +9270,22 @@ app13.get("/:attachmentId", requireAdminSession, async (c) => {
9264
9270
  var attachment_default = app13;
9265
9271
 
9266
9272
  // server/routes/admin/agents.ts
9267
- import { resolve as resolve14 } from "path";
9268
- import { readdirSync as readdirSync10, readFileSync as readFileSync17, existsSync as existsSync16, rmSync } from "fs";
9273
+ import { resolve as resolve15 } from "path";
9274
+ import { readdirSync as readdirSync11, readFileSync as readFileSync17, existsSync as existsSync17, rmSync } from "fs";
9269
9275
  var app14 = new Hono();
9270
9276
  app14.get("/", (c) => {
9271
9277
  const account = resolveAccount();
9272
9278
  if (!account) return c.json({ agents: [] });
9273
- const agentsDir = resolve14(account.accountDir, "agents");
9274
- if (!existsSync16(agentsDir)) return c.json({ agents: [] });
9279
+ const agentsDir = resolve15(account.accountDir, "agents");
9280
+ if (!existsSync17(agentsDir)) return c.json({ agents: [] });
9275
9281
  const agents = [];
9276
9282
  try {
9277
- const entries = readdirSync10(agentsDir, { withFileTypes: true });
9283
+ const entries = readdirSync11(agentsDir, { withFileTypes: true });
9278
9284
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
9279
9285
  if (!entry.isDirectory()) continue;
9280
9286
  if (entry.name === "admin") continue;
9281
- const configPath2 = resolve14(agentsDir, entry.name, "config.json");
9282
- if (!existsSync16(configPath2)) continue;
9287
+ const configPath2 = resolve15(agentsDir, entry.name, "config.json");
9288
+ if (!existsSync17(configPath2)) continue;
9283
9289
  try {
9284
9290
  const config = JSON.parse(readFileSync17(configPath2, "utf-8"));
9285
9291
  agents.push({
@@ -9307,8 +9313,8 @@ app14.delete("/:slug", async (c) => {
9307
9313
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9308
9314
  return c.json({ error: "Invalid agent slug" }, 400);
9309
9315
  }
9310
- const agentDir = resolve14(account.accountDir, "agents", slug);
9311
- if (!existsSync16(agentDir)) {
9316
+ const agentDir = resolve15(account.accountDir, "agents", slug);
9317
+ if (!existsSync17(agentDir)) {
9312
9318
  return c.json({ error: "Agent not found" }, 404);
9313
9319
  }
9314
9320
  try {
@@ -9337,8 +9343,8 @@ app14.post("/:slug/project", async (c) => {
9337
9343
  if (slug.includes("/") || slug.includes("..") || slug.includes("\\")) {
9338
9344
  return c.json({ error: "Invalid agent slug" }, 400);
9339
9345
  }
9340
- const agentDir = resolve14(account.accountDir, "agents", slug);
9341
- if (!existsSync16(agentDir)) {
9346
+ const agentDir = resolve15(account.accountDir, "agents", slug);
9347
+ if (!existsSync17(agentDir)) {
9342
9348
  return c.json({ error: "Agent not found on disk" }, 404);
9343
9349
  }
9344
9350
  try {
@@ -9354,7 +9360,7 @@ var agents_default = app14;
9354
9360
  // server/routes/admin/sessions.ts
9355
9361
  import crypto2 from "crypto";
9356
9362
  import { resolve as resolvePath } from "path";
9357
- import { existsSync as existsSync17, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9363
+ import { existsSync as existsSync18, mkdirSync as mkdirSync3, createWriteStream } from "fs";
9358
9364
 
9359
9365
  // ../lib/admin-conversation-purge/src/index.ts
9360
9366
  async function purgeAdminConversationJsonls(args) {
@@ -9514,7 +9520,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
9514
9520
  let reason = null;
9515
9521
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
9516
9522
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
9517
- else if (!existsSync17(a.storagePath)) reason = "missing-file";
9523
+ else if (!existsSync18(a.storagePath)) reason = "missing-file";
9518
9524
  if (reason) {
9519
9525
  invalid++;
9520
9526
  try {
@@ -10040,8 +10046,8 @@ app15.put("/:id/label", requireAdminSession, async (c) => {
10040
10046
  var sessions_default = app15;
10041
10047
 
10042
10048
  // app/lib/claude-agent/spawn-context.ts
10043
- import { existsSync as existsSync18, readFileSync as readFileSync18, readdirSync as readdirSync11, statSync as statSync8 } from "fs";
10044
- import { dirname as dirname4, resolve as resolve15, join as join16 } from "path";
10049
+ import { existsSync as existsSync19, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync8 } from "fs";
10050
+ import { dirname as dirname4, resolve as resolve16, join as join17 } from "path";
10045
10051
  async function resolveOwnerProfileBlock(accountId, userId) {
10046
10052
  if (!userId) return { ok: false, reason: "missing-user-id" };
10047
10053
  try {
@@ -10070,12 +10076,12 @@ function frontmatterField(manifest, field2) {
10070
10076
  function extractPluginToolDescriptions(pluginDir) {
10071
10077
  const out = /* @__PURE__ */ new Map();
10072
10078
  const candidates = [
10073
- join16(pluginDir, "mcp/dist/index.js"),
10074
- join16(pluginDir, "mcp/src/index.ts")
10079
+ join17(pluginDir, "mcp/dist/index.js"),
10080
+ join17(pluginDir, "mcp/src/index.ts")
10075
10081
  ];
10076
10082
  let raw = null;
10077
10083
  for (const path2 of candidates) {
10078
- if (!existsSync18(path2)) continue;
10084
+ if (!existsSync19(path2)) continue;
10079
10085
  try {
10080
10086
  raw = readFileSync18(path2, "utf-8");
10081
10087
  break;
@@ -10126,24 +10132,24 @@ function parseSkillPathsFromFrontmatter(fm) {
10126
10132
  }
10127
10133
  function listPluginDirs() {
10128
10134
  const out = /* @__PURE__ */ new Map();
10129
- const platformPlugins = resolve15(PLATFORM_ROOT, "plugins");
10130
- if (existsSync18(platformPlugins)) {
10131
- for (const name of readdirSync11(platformPlugins)) {
10132
- const dir = join16(platformPlugins, name);
10135
+ const platformPlugins = resolve16(PLATFORM_ROOT, "plugins");
10136
+ if (existsSync19(platformPlugins)) {
10137
+ for (const name of readdirSync12(platformPlugins)) {
10138
+ const dir = join17(platformPlugins, name);
10133
10139
  try {
10134
10140
  if (statSync8(dir).isDirectory()) out.set(name, dir);
10135
10141
  } catch {
10136
10142
  }
10137
10143
  }
10138
10144
  }
10139
- const premiumRoot = resolve15(dirname4(PLATFORM_ROOT), "premium-plugins");
10140
- if (existsSync18(premiumRoot)) {
10141
- for (const bundle of readdirSync11(premiumRoot)) {
10142
- const bundlePlugins = join16(premiumRoot, bundle, "plugins");
10143
- if (!existsSync18(bundlePlugins)) continue;
10145
+ const premiumRoot = resolve16(dirname4(PLATFORM_ROOT), "premium-plugins");
10146
+ if (existsSync19(premiumRoot)) {
10147
+ for (const bundle of readdirSync12(premiumRoot)) {
10148
+ const bundlePlugins = join17(premiumRoot, bundle, "plugins");
10149
+ if (!existsSync19(bundlePlugins)) continue;
10144
10150
  try {
10145
- for (const name of readdirSync11(bundlePlugins)) {
10146
- const dir = join16(bundlePlugins, name);
10151
+ for (const name of readdirSync12(bundlePlugins)) {
10152
+ const dir = join17(bundlePlugins, name);
10147
10153
  try {
10148
10154
  if (statSync8(dir).isDirectory()) out.set(name, dir);
10149
10155
  } catch {
@@ -10156,8 +10162,8 @@ function listPluginDirs() {
10156
10162
  return out;
10157
10163
  }
10158
10164
  function readEnabledPlugins(accountId) {
10159
- const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10160
- if (!existsSync18(accountFile)) return /* @__PURE__ */ new Set();
10165
+ const accountFile = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10166
+ if (!existsSync19(accountFile)) return /* @__PURE__ */ new Set();
10161
10167
  try {
10162
10168
  const parsed = JSON.parse(readFileSync18(accountFile, "utf-8"));
10163
10169
  return new Set(
@@ -10168,7 +10174,7 @@ function readEnabledPlugins(accountId) {
10168
10174
  }
10169
10175
  }
10170
10176
  function readFrontmatter(path2) {
10171
- if (!existsSync18(path2)) return null;
10177
+ if (!existsSync19(path2)) return null;
10172
10178
  let raw;
10173
10179
  try {
10174
10180
  raw = readFileSync18(path2, "utf-8");
@@ -10186,7 +10192,7 @@ function computeActivePlugins(accountId) {
10186
10192
  for (const name of Array.from(enabled).sort()) {
10187
10193
  const dir = pluginDirs.get(name);
10188
10194
  if (!dir) continue;
10189
- const fm = readFrontmatter(join16(dir, "PLUGIN.md"));
10195
+ const fm = readFrontmatter(join17(dir, "PLUGIN.md"));
10190
10196
  if (!fm) continue;
10191
10197
  const description = frontmatterField(`---
10192
10198
  ${fm}
@@ -10203,7 +10209,7 @@ ${fm}
10203
10209
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
10204
10210
  );
10205
10211
  if (toolNames.length > 0 && descMap.size === 0) {
10206
- const hasSource = existsSync18(join16(dir, "mcp/dist/index.js")) || existsSync18(join16(dir, "mcp/src/index.ts"));
10212
+ const hasSource = existsSync19(join17(dir, "mcp/dist/index.js")) || existsSync19(join17(dir, "mcp/src/index.ts"));
10207
10213
  if (hasSource) {
10208
10214
  console.warn(
10209
10215
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -10213,7 +10219,7 @@ ${fm}
10213
10219
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
10214
10220
  const skills = [];
10215
10221
  for (const relPath of skillPaths) {
10216
- const skillPath = join16(dir, relPath);
10222
+ const skillPath = join17(dir, relPath);
10217
10223
  const skillFm = readFrontmatter(skillPath);
10218
10224
  if (!skillFm) continue;
10219
10225
  const skillName = frontmatterField(`---
@@ -10229,11 +10235,11 @@ ${skillFm}
10229
10235
  return out;
10230
10236
  }
10231
10237
  function computeSpecialistDomains(accountId) {
10232
- const specialistsDir = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
10233
- if (!existsSync18(specialistsDir)) return [];
10238
+ const specialistsDir = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
10239
+ if (!existsSync19(specialistsDir)) return [];
10234
10240
  let entries;
10235
10241
  try {
10236
- entries = readdirSync11(specialistsDir);
10242
+ entries = readdirSync12(specialistsDir);
10237
10243
  } catch {
10238
10244
  return [];
10239
10245
  }
@@ -10257,7 +10263,7 @@ function computeSpecialistDomains(accountId) {
10257
10263
  const out = [];
10258
10264
  for (const file of entries.sort()) {
10259
10265
  if (!file.endsWith(".md")) continue;
10260
- const fm = readFrontmatter(join16(specialistsDir, file));
10266
+ const fm = readFrontmatter(join17(specialistsDir, file));
10261
10267
  if (!fm) continue;
10262
10268
  const wrapped = `---
10263
10269
  ${fm}
@@ -10275,8 +10281,8 @@ ${fm}
10275
10281
  return out;
10276
10282
  }
10277
10283
  function computeDormantPlugins(accountId) {
10278
- const accountFile = resolve15(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10279
- if (!existsSync18(accountFile)) return [];
10284
+ const accountFile = resolve16(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
10285
+ if (!existsSync19(accountFile)) return [];
10280
10286
  let enabled;
10281
10287
  try {
10282
10288
  const raw = readFileSync18(accountFile, "utf-8");
@@ -10290,19 +10296,19 @@ function computeDormantPlugins(accountId) {
10290
10296
  );
10291
10297
  return [];
10292
10298
  }
10293
- const pluginsDir = resolve15(PLATFORM_ROOT, "plugins");
10294
- if (!existsSync18(pluginsDir)) return [];
10299
+ const pluginsDir = resolve16(PLATFORM_ROOT, "plugins");
10300
+ if (!existsSync19(pluginsDir)) return [];
10295
10301
  let entries;
10296
10302
  try {
10297
- entries = readdirSync11(pluginsDir);
10303
+ entries = readdirSync12(pluginsDir);
10298
10304
  } catch {
10299
10305
  return [];
10300
10306
  }
10301
10307
  const out = [];
10302
10308
  for (const name of entries) {
10303
10309
  if (enabled.has(name)) continue;
10304
- const manifestPath = resolve15(pluginsDir, name, "PLUGIN.md");
10305
- if (!existsSync18(manifestPath)) continue;
10310
+ const manifestPath = resolve16(pluginsDir, name, "PLUGIN.md");
10311
+ if (!existsSync19(manifestPath)) continue;
10306
10312
  let manifest;
10307
10313
  try {
10308
10314
  manifest = readFileSync18(manifestPath, "utf-8");
@@ -10319,11 +10325,11 @@ function computeDormantPlugins(accountId) {
10319
10325
  }
10320
10326
 
10321
10327
  // server/routes/admin/claude-sessions.ts
10322
- import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
10323
- import { resolve as resolve16 } from "path";
10328
+ import { existsSync as existsSync20, readFileSync as readFileSync19 } from "fs";
10329
+ import { resolve as resolve17 } from "path";
10324
10330
  function readTunnelState(brandConfigDir) {
10325
10331
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
10326
- if (!existsSync19(statePath)) return null;
10332
+ if (!existsSync20(statePath)) return null;
10327
10333
  try {
10328
10334
  const parsed = JSON.parse(readFileSync19(statePath, "utf-8"));
10329
10335
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
@@ -10336,10 +10342,10 @@ function readTunnelState(brandConfigDir) {
10336
10342
  }
10337
10343
  }
10338
10344
  function resolveTunnelUrl() {
10339
- const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
10345
+ const platformRoot2 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
10340
10346
  let brand;
10341
10347
  try {
10342
- brand = JSON.parse(readFileSync19(resolve16(platformRoot2, "config", "brand.json"), "utf-8"));
10348
+ brand = JSON.parse(readFileSync19(resolve17(platformRoot2, "config", "brand.json"), "utf-8"));
10343
10349
  } catch {
10344
10350
  return null;
10345
10351
  }
@@ -10584,15 +10590,15 @@ var events_default = app18;
10584
10590
  import { createReadStream as createReadStream2 } from "fs";
10585
10591
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
10586
10592
  import { realpathSync as realpathSync4 } from "fs";
10587
- import { basename as basename6, dirname as dirname5, join as join18, resolve as resolve19, sep as sep5 } from "path";
10593
+ import { basename as basename6, dirname as dirname5, join as join19, resolve as resolve20, sep as sep5 } from "path";
10588
10594
  import { Readable as Readable2 } from "stream";
10589
10595
 
10590
10596
  // app/lib/data-path.ts
10591
10597
  import { realpathSync as realpathSync3 } from "fs";
10592
- import { resolve as resolve17, normalize, sep as sep3, relative } from "path";
10593
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "../platform");
10594
- var DATA_ROOT = resolve17(PLATFORM_ROOT5, "..", "data");
10595
- var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve17(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10598
+ import { resolve as resolve18, normalize, sep as sep3, relative } from "path";
10599
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve18(process.cwd(), "../platform");
10600
+ var DATA_ROOT = resolve18(PLATFORM_ROOT5, "..", "data");
10601
+ var CLAUDE_UPLOADS_ROOT = process.env.CLAUDE_CONFIG_DIR ? resolve18(process.env.CLAUDE_CONFIG_DIR, "uploads") : null;
10596
10602
  var ACCOUNT_PARTITION_DIRS = /* @__PURE__ */ new Set(["uploads", "accounts"]);
10597
10603
  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;
10598
10604
  function crossesForeignAccountPartition(relPath, accountId) {
@@ -10605,7 +10611,7 @@ function crossesForeignAccountPartition(relPath, accountId) {
10605
10611
  }
10606
10612
  function resolveUnderRoot(raw, rootAbs, rootLabel) {
10607
10613
  const cleaned = normalize("/" + (raw ?? "").replace(/\\/g, "/")).replace(/^\/+/, "");
10608
- const absolute = resolve17(rootAbs, cleaned);
10614
+ const absolute = resolve18(rootAbs, cleaned);
10609
10615
  let rootReal;
10610
10616
  try {
10611
10617
  rootReal = realpathSync3(rootAbs);
@@ -10964,7 +10970,7 @@ async function cascadeDeleteDocument(params) {
10964
10970
 
10965
10971
  // app/lib/file-index.ts
10966
10972
  import * as fsp from "fs/promises";
10967
- import { resolve as resolve18, relative as relative2, join as join17, basename as basename5, extname as extname2, sep as sep4 } from "path";
10973
+ import { resolve as resolve19, relative as relative2, join as join18, basename as basename5, extname as extname2, sep as sep4 } from "path";
10968
10974
  import { tmpdir as tmpdir2 } from "os";
10969
10975
  import { execFile as execFile2 } from "child_process";
10970
10976
  import { promisify as promisify2 } from "util";
@@ -11035,7 +11041,7 @@ async function extractPdf(absolute) {
11035
11041
  return stdout.trim();
11036
11042
  }
11037
11043
  async function ocrPdf(absolute) {
11038
- const outPdf = join17(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
11044
+ const outPdf = join18(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
11039
11045
  try {
11040
11046
  await execFileAsync2(
11041
11047
  "ocrmypdf",
@@ -11097,7 +11103,7 @@ async function readDisplayName(absolute) {
11097
11103
  const stem = dot === -1 ? base : base.slice(0, dot);
11098
11104
  if (base === `${stem}.meta.json`) return null;
11099
11105
  try {
11100
- const raw = await fsp.readFile(join17(dir, `${stem}.meta.json`), "utf-8");
11106
+ const raw = await fsp.readFile(join18(dir, `${stem}.meta.json`), "utf-8");
11101
11107
  const meta = JSON.parse(raw);
11102
11108
  const dn = meta.displayName ?? meta.filename;
11103
11109
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -11117,7 +11123,7 @@ async function walkSubtree(root, dataRoot, out) {
11117
11123
  let clean = true;
11118
11124
  for (const entry of entries) {
11119
11125
  if (entry.isSymbolicLink()) continue;
11120
- const abs = join17(root, entry.name);
11126
+ const abs = join18(root, entry.name);
11121
11127
  if (entry.isDirectory()) {
11122
11128
  const sub = await walkSubtree(abs, dataRoot, out);
11123
11129
  if (!sub.clean) clean = false;
@@ -11272,8 +11278,8 @@ async function reconcileFileIndex(accountId, opts) {
11272
11278
  return withSession(opts, async (session) => {
11273
11279
  const walked = [];
11274
11280
  const subtreeRoots = [
11275
- resolve18(dataRoot, "uploads", accountId),
11276
- resolve18(dataRoot, "accounts", accountId)
11281
+ resolve19(dataRoot, "uploads", accountId),
11282
+ resolve19(dataRoot, "accounts", accountId)
11277
11283
  ];
11278
11284
  let clean = true;
11279
11285
  for (const root of subtreeRoots) {
@@ -11354,7 +11360,7 @@ async function reconcileFileIndexDebounced(accountId, opts) {
11354
11360
  async function indexFile(accountId, relativePath, opts) {
11355
11361
  const dataRoot = opts?.dataRoot ?? DATA_ROOT;
11356
11362
  const embed2 = opts?.embed ?? embed;
11357
- const absolute = resolve18(dataRoot, relativePath);
11363
+ const absolute = resolve19(dataRoot, relativePath);
11358
11364
  await withSession(opts, async (session) => {
11359
11365
  const st = await fsp.stat(absolute);
11360
11366
  const wf = {
@@ -11388,7 +11394,7 @@ async function dropFileIndex(accountId, relativePath, opts) {
11388
11394
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11389
11395
  async function readMeta(absDir, baseName) {
11390
11396
  try {
11391
- const raw = await readFile4(join18(absDir, `${baseName}.meta.json`), "utf8");
11397
+ const raw = await readFile4(join19(absDir, `${baseName}.meta.json`), "utf8");
11392
11398
  const parsed = JSON.parse(raw);
11393
11399
  if (typeof parsed?.filename === "string") {
11394
11400
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -11399,7 +11405,7 @@ async function readMeta(absDir, baseName) {
11399
11405
  }
11400
11406
  async function readAccountNames() {
11401
11407
  const map = /* @__PURE__ */ new Map();
11402
- const accountsDir = resolve19(DATA_ROOT, "accounts");
11408
+ const accountsDir = resolve20(DATA_ROOT, "accounts");
11403
11409
  let names;
11404
11410
  try {
11405
11411
  names = await readdir3(accountsDir);
@@ -11408,7 +11414,7 @@ async function readAccountNames() {
11408
11414
  }
11409
11415
  for (const name of names) {
11410
11416
  if (!UUID_RE3.test(name)) continue;
11411
- const configPath2 = resolve19(accountsDir, name, "account.json");
11417
+ const configPath2 = resolve20(accountsDir, name, "account.json");
11412
11418
  try {
11413
11419
  const raw = await readFile4(configPath2, "utf8");
11414
11420
  const parsed = JSON.parse(raw);
@@ -11426,7 +11432,7 @@ async function readAccountNames() {
11426
11432
  }
11427
11433
  async function enrich(absolute, entry, accountNames) {
11428
11434
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
11429
- const meta = await readMeta(join18(absolute, entry.name), entry.name);
11435
+ const meta = await readMeta(join19(absolute, entry.name), entry.name);
11430
11436
  if (meta?.filename) {
11431
11437
  entry.displayName = meta.filename;
11432
11438
  entry.mimeType = meta.mimeType;
@@ -11524,7 +11530,7 @@ app19.get("/", requireAdminSession, async (c) => {
11524
11530
  continue;
11525
11531
  }
11526
11532
  try {
11527
- const entryPath = join18(absolute, name);
11533
+ const entryPath = join19(absolute, name);
11528
11534
  const s = await stat4(entryPath);
11529
11535
  entries.push({
11530
11536
  name,
@@ -11649,8 +11655,8 @@ app19.post("/upload", requireAdminSession, async (c) => {
11649
11655
  }
11650
11656
  const safeName = basename6(file.name).replace(/[\0/\\]/g, "_");
11651
11657
  const finalName = `${Date.now()}-${safeName}`;
11652
- const destDir = resolve19(DATA_ROOT, "uploads", accountId);
11653
- const destPath = resolve19(destDir, finalName);
11658
+ const destDir = resolve20(DATA_ROOT, "uploads", accountId);
11659
+ const destPath = resolve20(destDir, finalName);
11654
11660
  try {
11655
11661
  await mkdir3(destDir, { recursive: true });
11656
11662
  const dataRootReal = realpathSync4(DATA_ROOT);
@@ -11715,7 +11721,7 @@ app19.delete("/", requireAdminSession, async (c) => {
11715
11721
  }
11716
11722
  const dot = base.lastIndexOf(".");
11717
11723
  const stem = dot === -1 ? base : base.slice(0, dot);
11718
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join18(dirname5(absolute), `${stem}.meta.json`) : null;
11724
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join19(dirname5(absolute), `${stem}.meta.json`) : null;
11719
11725
  await unlink2(absolute);
11720
11726
  if (sidecarPath) {
11721
11727
  try {
@@ -13764,8 +13770,8 @@ var graph_default_view_default = app25;
13764
13770
 
13765
13771
  // server/routes/admin/sidebar-artefacts.ts
13766
13772
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
13767
- import { resolve as resolve20, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13768
- import { existsSync as existsSync20 } from "fs";
13773
+ import { resolve as resolve21, relative as relative3, isAbsolute, sep as sep6, basename as basename7 } from "path";
13774
+ import { existsSync as existsSync21 } from "fs";
13769
13775
  var LIMIT = 50;
13770
13776
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
13771
13777
  function toDataRootRelPath(absPath) {
@@ -13784,7 +13790,7 @@ app26.get("/", requireAdminSession, async (c) => {
13784
13790
  if (accountFiles === null) {
13785
13791
  return c.json({ error: "Failed to load artefacts" }, 500);
13786
13792
  }
13787
- const accountDir = resolve20(ACCOUNTS_DIR, accountId);
13793
+ const accountDir = resolve21(ACCOUNTS_DIR, accountId);
13788
13794
  const agents = await fetchAgentTemplateRows(accountDir);
13789
13795
  const artefacts = [...accountFiles, ...agents].sort(
13790
13796
  (a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? "")
@@ -13835,8 +13841,8 @@ async function fetchAccountFileArtefacts(accountId) {
13835
13841
  async function fetchAgentTemplateRows(accountDir) {
13836
13842
  const rows = [];
13837
13843
  for (const filename of ADMIN_AGENT_FILES) {
13838
- const overridePath = resolve20(accountDir, "agents", "admin", filename);
13839
- const bundledPath = resolve20(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13844
+ const overridePath = resolve21(accountDir, "agents", "admin", filename);
13845
+ const bundledPath = resolve21(PLATFORM_ROOT, "templates", "agents", "admin", filename);
13840
13846
  const labelStem = filename.replace(/\.md$/, "");
13841
13847
  const row = await readAgentTemplateRow({
13842
13848
  id: `agent-template:admin:${filename}`,
@@ -13849,12 +13855,12 @@ async function fetchAgentTemplateRows(accountDir) {
13849
13855
  });
13850
13856
  if (row) rows.push(row);
13851
13857
  }
13852
- const overrideDir = resolve20(accountDir, "specialists", "agents");
13853
- const bundledDir = resolve20(PLATFORM_ROOT, "templates", "specialists", "agents");
13858
+ const overrideDir = resolve21(accountDir, "specialists", "agents");
13859
+ const bundledDir = resolve21(PLATFORM_ROOT, "templates", "specialists", "agents");
13854
13860
  const specialistNames = await unionSpecialistFilenames(overrideDir, bundledDir);
13855
13861
  for (const filename of specialistNames) {
13856
- const overridePath = resolve20(overrideDir, filename);
13857
- const bundledPath = resolve20(bundledDir, filename);
13862
+ const overridePath = resolve21(overrideDir, filename);
13863
+ const bundledPath = resolve21(bundledDir, filename);
13858
13864
  const row = await readAgentTemplateRow({
13859
13865
  id: `agent-template:specialist:${filename}`,
13860
13866
  displayName: filename.replace(/\.md$/, ""),
@@ -13871,7 +13877,7 @@ async function fetchAgentTemplateRows(accountDir) {
13871
13877
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
13872
13878
  const names = /* @__PURE__ */ new Set();
13873
13879
  for (const dir of [overrideDir, bundledDir]) {
13874
- if (!existsSync20(dir)) continue;
13880
+ if (!existsSync21(dir)) continue;
13875
13881
  try {
13876
13882
  const entries = await readdir4(dir);
13877
13883
  for (const entry of entries) {
@@ -13886,7 +13892,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
13886
13892
  }
13887
13893
  async function readAgentTemplateRow(inp) {
13888
13894
  let chosenPath = null;
13889
- if (existsSync20(inp.overridePath)) {
13895
+ if (existsSync21(inp.overridePath)) {
13890
13896
  try {
13891
13897
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
13892
13898
  chosenPath = inp.overridePath;
@@ -13897,7 +13903,7 @@ async function readAgentTemplateRow(inp) {
13897
13903
  );
13898
13904
  return null;
13899
13905
  }
13900
- } else if (existsSync20(inp.bundledPath)) {
13906
+ } else if (existsSync21(inp.bundledPath)) {
13901
13907
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
13902
13908
  console.error(
13903
13909
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -14062,6 +14068,36 @@ app29.post("/", requireAdminSession, async (c) => {
14062
14068
  var session_archive_default = app29;
14063
14069
 
14064
14070
  // server/routes/admin/session-rc-spawn.ts
14071
+ import { randomUUID as randomUUID9 } from "crypto";
14072
+ function resolveSpawnPlan(host, operatorDomains, body, mintId = randomUUID9) {
14073
+ const operator = isOperatorHost(host, operatorDomains);
14074
+ const resumeId = typeof body.sessionId === "string" && body.sessionId.length > 0 ? body.sessionId : void 0;
14075
+ const name = typeof body.name === "string" && body.name.length > 0 ? body.name : void 0;
14076
+ const webchatBind = resumeId === void 0 || operator;
14077
+ const kind = resumeId === void 0 ? "new" : "resume";
14078
+ const origin = operator ? "operator" : "admin";
14079
+ const payload = {};
14080
+ let sessionId;
14081
+ if (webchatBind) {
14082
+ sessionId = resumeId ?? mintId();
14083
+ const key = `session:${sessionId}`;
14084
+ payload.sessionId = sessionId;
14085
+ payload.role = "admin";
14086
+ payload.channel = "webchat";
14087
+ payload.senderId = key;
14088
+ payload.webchatChannel = webchatChannelDescriptor(key);
14089
+ if (name) payload.name = name;
14090
+ } else {
14091
+ sessionId = resumeId;
14092
+ payload.sessionId = resumeId;
14093
+ if (name) payload.name = name;
14094
+ }
14095
+ return { webchatBind, origin, kind, sessionId, payload };
14096
+ }
14097
+ function shapeWebchatResponse(sessionId, manager) {
14098
+ const outcome = typeof manager?.outcome === "string" ? manager.outcome : "bound";
14099
+ return { sessionId, outcome, target: `/chat?session=${sessionId}` };
14100
+ }
14065
14101
  var app30 = new Hono();
14066
14102
  app30.post("/", requireAdminSession, async (c) => {
14067
14103
  let body;
@@ -14070,19 +14106,26 @@ app30.post("/", requireAdminSession, async (c) => {
14070
14106
  } catch {
14071
14107
  body = {};
14072
14108
  }
14073
- const payload = {};
14074
- if (typeof body.sessionId === "string" && body.sessionId.length > 0) payload.sessionId = body.sessionId;
14075
- if (typeof body.name === "string" && body.name.length > 0) payload.name = body.name;
14109
+ const host = (c.req.header("host") ?? "").split(":")[0];
14110
+ const plan = resolveSpawnPlan(host, getOperatorDomains(), body);
14111
+ const spawnReqId = randomUUID9();
14112
+ console.log(
14113
+ `[chat-spawn] op=request spawnReqId=${spawnReqId} origin=${plan.origin} kind=${plan.kind} sessionId=${plan.kind === "new" ? "new" : plan.sessionId}`
14114
+ );
14115
+ if (plan.webchatBind) {
14116
+ console.log(`[chat-spawn] op=args spawnReqId=${spawnReqId} webchatChannel=present sessionId=${plan.sessionId}`);
14117
+ }
14076
14118
  let res;
14077
14119
  try {
14078
14120
  res = await fetch(`${managerBase3("session-rc-spawn:wrapper")}/rc-spawn`, {
14079
14121
  method: "POST",
14080
14122
  headers: { "content-type": "application/json" },
14081
- body: JSON.stringify(payload)
14123
+ body: JSON.stringify(plan.payload)
14082
14124
  });
14083
14125
  } catch (err) {
14084
14126
  const msg = err instanceof Error ? err.message : String(err);
14085
14127
  console.error(`[session-rc-spawn] manager-unreachable err=${msg}`);
14128
+ console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=spawn-failed`);
14086
14129
  return c.json({ error: `session manager unreachable: ${msg}` }, 502);
14087
14130
  }
14088
14131
  const text = await res.text();
@@ -14093,8 +14136,18 @@ app30.post("/", requireAdminSession, async (c) => {
14093
14136
  }
14094
14137
  if (!res.ok) {
14095
14138
  console.error(`[session-rc-spawn] manager-error status=${res.status} body=${text.slice(0, 200)}`);
14139
+ console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=spawn-failed`);
14096
14140
  return c.json(parsed ?? { error: text }, res.status);
14097
14141
  }
14142
+ if (plan.webchatBind) {
14143
+ const target = `/chat?session=${plan.sessionId}`;
14144
+ console.log(
14145
+ `[chat-spawn] op=acquired spawnReqId=${spawnReqId} pid=${parsed?.spawnedPid ?? "none"} sessionId=${plan.sessionId}`
14146
+ );
14147
+ console.log(`[chat-spawn] op=navigate spawnReqId=${spawnReqId} target=${target}`);
14148
+ console.log(`[chat-spawn] op=exit spawnReqId=${spawnReqId} outcome=bound`);
14149
+ return c.json(shapeWebchatResponse(plan.sessionId, parsed));
14150
+ }
14098
14151
  return c.json(parsed ?? {});
14099
14152
  });
14100
14153
  var session_rc_spawn_default = app30;
@@ -14221,23 +14274,23 @@ app31.get("/", async (c) => {
14221
14274
  var system_stats_default = app31;
14222
14275
 
14223
14276
  // server/routes/admin/health.ts
14224
- import { existsSync as existsSync21, readFileSync as readFileSync20 } from "fs";
14225
- import { resolve as resolve21, join as join19 } from "path";
14226
- var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
14277
+ import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
14278
+ import { resolve as resolve22, join as join20 } from "path";
14279
+ var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14227
14280
  var brandHostname = "maxy";
14228
- var brandJsonPath = join19(PLATFORM_ROOT6, "config", "brand.json");
14229
- if (existsSync21(brandJsonPath)) {
14281
+ var brandJsonPath = join20(PLATFORM_ROOT6, "config", "brand.json");
14282
+ if (existsSync22(brandJsonPath)) {
14230
14283
  try {
14231
14284
  const brand = JSON.parse(readFileSync20(brandJsonPath, "utf-8"));
14232
14285
  if (brand.hostname) brandHostname = brand.hostname;
14233
14286
  } catch {
14234
14287
  }
14235
14288
  }
14236
- var VERSION_FILE = resolve21(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
14289
+ var VERSION_FILE = resolve22(PLATFORM_ROOT6, `config/.${brandHostname}-version`);
14237
14290
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
14238
14291
  var PROBE_TIMEOUT_MS = 1e3;
14239
14292
  function readVersion() {
14240
- if (!existsSync21(VERSION_FILE)) return "unknown";
14293
+ if (!existsSync22(VERSION_FILE)) return "unknown";
14241
14294
  return readFileSync20(VERSION_FILE, "utf-8").trim() || "unknown";
14242
14295
  }
14243
14296
  async function probeConversationDb() {
@@ -14289,7 +14342,7 @@ app32.get("/", async (c) => {
14289
14342
  var health_default2 = app32;
14290
14343
 
14291
14344
  // server/routes/admin/linkedin-ingest.ts
14292
- import { randomUUID as randomUUID9 } from "crypto";
14345
+ import { randomUUID as randomUUID10 } from "crypto";
14293
14346
  var TAG25 = "[linkedin-ingest-route]";
14294
14347
  var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
14295
14348
  var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
@@ -14415,7 +14468,7 @@ app33.post("/", requireAdminSession, async (c) => {
14415
14468
  );
14416
14469
  const initialMessage = buildInitialMessage(envelope);
14417
14470
  const spawnStart = Date.now();
14418
- const sessionId = randomUUID9();
14471
+ const sessionId = randomUUID10();
14419
14472
  console.log(TAG25 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
14420
14473
  const spawned = await managerRcSpawn({
14421
14474
  sessionId,
@@ -14781,13 +14834,13 @@ var admin_default = app39;
14781
14834
  // app/lib/access-gate.ts
14782
14835
  import neo4j4 from "neo4j-driver";
14783
14836
  import { readFileSync as readFileSync21 } from "fs";
14784
- import { resolve as resolve22 } from "path";
14785
- import { randomUUID as randomUUID10 } from "crypto";
14786
- var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve22(process.cwd(), "..");
14837
+ import { resolve as resolve23 } from "path";
14838
+ import { randomUUID as randomUUID11 } from "crypto";
14839
+ var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
14787
14840
  var driver = null;
14788
14841
  function readPassword() {
14789
14842
  if (process.env.NEO4J_PASSWORD) return process.env.NEO4J_PASSWORD;
14790
- const passwordFile = resolve22(PLATFORM_ROOT7, "config/.neo4j-password");
14843
+ const passwordFile = resolve23(PLATFORM_ROOT7, "config/.neo4j-password");
14791
14844
  try {
14792
14845
  return readFileSync21(passwordFile, "utf-8").trim();
14793
14846
  } catch {
@@ -14965,7 +15018,7 @@ async function consumeMagicTokenAndActivate(grantId) {
14965
15018
  }
14966
15019
  }
14967
15020
  async function generateNewMagicToken(grantId) {
14968
- const token = randomUUID10();
15021
+ const token = randomUUID11();
14969
15022
  const session = getSession3();
14970
15023
  try {
14971
15024
  const result = await session.run(
@@ -15077,9 +15130,9 @@ var verify_token_default = app40;
15077
15130
 
15078
15131
  // app/lib/access-email.ts
15079
15132
  import { spawn as spawn2 } from "child_process";
15080
- import { resolve as resolve23 } from "path";
15081
- var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve23(process.cwd(), "..");
15082
- var SEND_SCRIPT = resolve23(
15133
+ import { resolve as resolve24 } from "path";
15134
+ var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve24(process.cwd(), "..");
15135
+ var SEND_SCRIPT = resolve24(
15083
15136
  PLATFORM_ROOT8,
15084
15137
  "plugins",
15085
15138
  "email",
@@ -15221,8 +15274,8 @@ app42.route("/request-magic-link", request_magic_link_default);
15221
15274
  var access_default = app42;
15222
15275
 
15223
15276
  // server/routes/sites.ts
15224
- import { existsSync as existsSync22, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
15225
- import { resolve as resolve24 } from "path";
15277
+ import { existsSync as existsSync23, readFileSync as readFileSync22, realpathSync as realpathSync5, statSync as statSync9 } from "fs";
15278
+ import { resolve as resolve25 } from "path";
15226
15279
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
15227
15280
  var MIME = {
15228
15281
  ".html": "text/html; charset=utf-8",
@@ -15279,15 +15332,15 @@ app43.get("/:rel{.*}", (c) => {
15279
15332
  }
15280
15333
  segments.push(seg);
15281
15334
  }
15282
- const rootDir = resolve24(account.accountDir, "sites");
15283
- let filePath = segments.length === 0 ? rootDir : resolve24(rootDir, ...segments);
15335
+ const rootDir = resolve25(account.accountDir, "sites");
15336
+ let filePath = segments.length === 0 ? rootDir : resolve25(rootDir, ...segments);
15284
15337
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
15285
15338
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
15286
15339
  return c.text("Forbidden", 403);
15287
15340
  }
15288
15341
  let stat7;
15289
15342
  try {
15290
- stat7 = existsSync22(filePath) ? statSync9(filePath) : null;
15343
+ stat7 = existsSync23(filePath) ? statSync9(filePath) : null;
15291
15344
  } catch {
15292
15345
  stat7 = null;
15293
15346
  }
@@ -15300,13 +15353,13 @@ app43.get("/:rel{.*}", (c) => {
15300
15353
  return c.redirect(target, 301);
15301
15354
  }
15302
15355
  if (stat7?.isDirectory()) {
15303
- filePath = resolve24(filePath, "index.html");
15356
+ filePath = resolve25(filePath, "index.html");
15304
15357
  }
15305
15358
  if (!filePath.startsWith(rootDir + "/")) {
15306
15359
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
15307
15360
  return c.text("Forbidden", 403);
15308
15361
  }
15309
- if (!existsSync22(filePath)) {
15362
+ if (!existsSync23(filePath)) {
15310
15363
  console.error(`[sites] not-found path=${reqPath} status=404`);
15311
15364
  return c.text("Not found", 404);
15312
15365
  }
@@ -15437,8 +15490,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
15437
15490
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
15438
15491
 
15439
15492
  // app/lib/brand-config.ts
15440
- import { existsSync as existsSync23, readFileSync as readFileSync24 } from "fs";
15441
- import { join as join20 } from "path";
15493
+ import { existsSync as existsSync24, readFileSync as readFileSync24 } from "fs";
15494
+ import { join as join21 } from "path";
15442
15495
  var cached2 = null;
15443
15496
  var cachedAttempted = false;
15444
15497
  function readBrandConfig() {
@@ -15446,8 +15499,8 @@ function readBrandConfig() {
15446
15499
  cachedAttempted = true;
15447
15500
  const platformRoot2 = process.env.MAXY_PLATFORM_ROOT;
15448
15501
  if (!platformRoot2) return null;
15449
- const brandPath = join20(platformRoot2, "config", "brand.json");
15450
- if (!existsSync23(brandPath)) return null;
15502
+ const brandPath = join21(platformRoot2, "config", "brand.json");
15503
+ if (!existsSync24(brandPath)) return null;
15451
15504
  try {
15452
15505
  cached2 = JSON.parse(readFileSync24(brandPath, "utf-8"));
15453
15506
  return cached2;
@@ -15937,14 +15990,14 @@ async function writeEvent(opts) {
15937
15990
  var visitor_event_default = app46;
15938
15991
 
15939
15992
  // server/routes/session.ts
15940
- import { resolve as resolve25 } from "path";
15941
- import { existsSync as existsSync24, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
15993
+ import { resolve as resolve26 } from "path";
15994
+ import { existsSync as existsSync25, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
15942
15995
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
15943
15996
  function writeBrandingCache(accountId, agentSlug, branding) {
15944
15997
  try {
15945
- const cacheDir = resolve25(MAXY_DIR, "branding-cache", accountId);
15998
+ const cacheDir = resolve26(MAXY_DIR, "branding-cache", accountId);
15946
15999
  mkdirSync5(cacheDir, { recursive: true });
15947
- writeFileSync9(resolve25(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
16000
+ writeFileSync9(resolve26(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
15948
16001
  } catch (err) {
15949
16002
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
15950
16003
  }
@@ -16032,8 +16085,8 @@ app47.post("/", async (c) => {
16032
16085
  }
16033
16086
  let agentConfig = null;
16034
16087
  if (account) {
16035
- const agentDir = resolve25(account.accountDir, "agents", agentSlug);
16036
- if (!existsSync24(agentDir) || !existsSync24(resolve25(agentDir, "config.json"))) {
16088
+ const agentDir = resolve26(account.accountDir, "agents", agentSlug);
16089
+ if (!existsSync25(agentDir) || !existsSync25(resolve26(agentDir, "config.json"))) {
16037
16090
  return c.json({ error: "Agent not found" }, 404);
16038
16091
  }
16039
16092
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -16313,7 +16366,7 @@ function startGraphHealthTimer() {
16313
16366
 
16314
16367
  // app/lib/file-watcher.ts
16315
16368
  import * as fsp2 from "fs/promises";
16316
- import { resolve as resolve26, sep as sep7 } from "path";
16369
+ import { resolve as resolve27, sep as sep7 } from "path";
16317
16370
  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;
16318
16371
  var DEFAULT_COALESCE_MS = 500;
16319
16372
  var ROOTS = ["uploads", "accounts"];
@@ -16332,7 +16385,7 @@ async function startFileWatcher(opts = {}) {
16332
16385
  const dropFn = opts.drop ?? dropFileIndex;
16333
16386
  for (const r of ROOTS) {
16334
16387
  try {
16335
- await fsp2.mkdir(resolve26(dataRoot, r), { recursive: true });
16388
+ await fsp2.mkdir(resolve27(dataRoot, r), { recursive: true });
16336
16389
  } catch (err) {
16337
16390
  console.error(
16338
16391
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -16353,7 +16406,7 @@ async function startFileWatcher(opts = {}) {
16353
16406
  timers.set(relativePath, t);
16354
16407
  }
16355
16408
  async function runHook(relativePath, accountId) {
16356
- const absolute = resolve26(dataRoot, relativePath);
16409
+ const absolute = resolve27(dataRoot, relativePath);
16357
16410
  let exists = false;
16358
16411
  try {
16359
16412
  const st = await fsp2.stat(absolute);
@@ -16377,7 +16430,7 @@ async function startFileWatcher(opts = {}) {
16377
16430
  }
16378
16431
  }
16379
16432
  async function watchRoot(rootName) {
16380
- const absRoot = resolve26(dataRoot, rootName);
16433
+ const absRoot = resolve27(dataRoot, rootName);
16381
16434
  try {
16382
16435
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
16383
16436
  for await (const event of iter) {
@@ -17271,8 +17324,8 @@ function broadcastAdminShutdown(reason) {
17271
17324
 
17272
17325
  // ../lib/entitlement/src/index.ts
17273
17326
  import { createPublicKey, createHash as createHash5, verify as cryptoVerify } from "crypto";
17274
- import { existsSync as existsSync25, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
17275
- import { resolve as resolve27 } from "path";
17327
+ import { existsSync as existsSync26, readFileSync as readFileSync25, statSync as statSync10 } from "fs";
17328
+ import { resolve as resolve28 } from "path";
17276
17329
 
17277
17330
  // ../lib/entitlement/src/canonicalize.ts
17278
17331
  function canonicalize(value) {
@@ -17307,7 +17360,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
17307
17360
  var GRACE_DAYS = 7;
17308
17361
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
17309
17362
  function pubkeyPath(brand) {
17310
- return resolve27(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
17363
+ return resolve28(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
17311
17364
  }
17312
17365
  var memo = null;
17313
17366
  function memoKey(mtimeMs, account) {
@@ -17319,8 +17372,8 @@ function resolveEntitlement(brand, account) {
17319
17372
  if (brand.commercialMode !== true) {
17320
17373
  return logResolved(implicitTrust(account), null);
17321
17374
  }
17322
- const entitlementPath = resolve27(brand.configDir, "entitlement.json");
17323
- if (!existsSync25(entitlementPath)) {
17375
+ const entitlementPath = resolve28(brand.configDir, "entitlement.json");
17376
+ if (!existsSync26(entitlementPath)) {
17324
17377
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
17325
17378
  }
17326
17379
  const stat7 = statSync10(entitlementPath);
@@ -17510,12 +17563,12 @@ function clientFrom(c) {
17510
17563
  );
17511
17564
  }
17512
17565
  var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
17513
- var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join21(PLATFORM_ROOT9, "config", "brand.json") : "";
17566
+ var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join22(PLATFORM_ROOT9, "config", "brand.json") : "";
17514
17567
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
17515
- if (BRAND_JSON_PATH && !existsSync26(BRAND_JSON_PATH)) {
17568
+ if (BRAND_JSON_PATH && !existsSync27(BRAND_JSON_PATH)) {
17516
17569
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
17517
17570
  }
17518
- if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
17571
+ if (BRAND_JSON_PATH && existsSync27(BRAND_JSON_PATH)) {
17519
17572
  try {
17520
17573
  const parsed = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
17521
17574
  BRAND = { ...BRAND, ...parsed };
@@ -17536,10 +17589,10 @@ var brandLoginOpts = {
17536
17589
  bodyFont: BRAND.defaultFonts?.body,
17537
17590
  logoContainsName: !!BRAND.logoContainsName
17538
17591
  };
17539
- var ALIAS_DOMAINS_PATH = join21(homedir3(), BRAND.configDir, "alias-domains.json");
17592
+ var ALIAS_DOMAINS_PATH = join22(homedir3(), BRAND.configDir, "alias-domains.json");
17540
17593
  function loadAliasDomains() {
17541
17594
  try {
17542
- if (!existsSync26(ALIAS_DOMAINS_PATH)) return null;
17595
+ if (!existsSync27(ALIAS_DOMAINS_PATH)) return null;
17543
17596
  const parsed = JSON.parse(readFileSync26(ALIAS_DOMAINS_PATH, "utf-8"));
17544
17597
  if (!Array.isArray(parsed)) {
17545
17598
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
@@ -17568,7 +17621,7 @@ var app48 = new Hono();
17568
17621
  var nativeFileFollowers = /* @__PURE__ */ new Map();
17569
17622
  var waGateway = new WaGateway({
17570
17623
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17571
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17624
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
17572
17625
  // Task 751 — file delivery on the native channel: resolve the platform
17573
17626
  // account + path validation here and funnel through the shared send core.
17574
17627
  sendDocument: async ({ senderId, accountId, filePath, caption }) => {
@@ -17584,7 +17637,7 @@ var waGateway = new WaGateway({
17584
17637
  caption,
17585
17638
  accountId,
17586
17639
  maxyAccountId,
17587
- platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."))
17640
+ platformRoot: resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, ".."))
17588
17641
  });
17589
17642
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
17590
17643
  },
@@ -17623,8 +17676,8 @@ var waGateway = new WaGateway({
17623
17676
  app48.route("/", waGateway.routes());
17624
17677
  waGateway.startSweeper();
17625
17678
  var webchatGateway = new WebchatGateway({
17626
- gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
17627
- serverPath: process.env.MAXY_WEBCHAT_CHANNEL_SERVER_PATH ?? resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, ".."), "services/webchat-channel/dist/server.js"),
17679
+ gatewayUrl: webchatGatewayUrl(),
17680
+ serverPath: webchatServerPath(),
17628
17681
  ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId }) => {
17629
17682
  if (role !== "admin") {
17630
17683
  console.error(`[webchat:inbound] op=spawn-refused key=${key} role=${role} reason=public-path-not-wired`);
@@ -17676,7 +17729,7 @@ app48.use("*", async (c, next) => {
17676
17729
  });
17677
17730
  app48.use("*", async (c, next) => {
17678
17731
  const host = (c.req.header("host") ?? "").split(":")[0];
17679
- if (!isPublicHost(host)) {
17732
+ if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
17680
17733
  await next();
17681
17734
  return;
17682
17735
  }
@@ -17908,7 +17961,10 @@ app48.use("*", async (c, next) => {
17908
17961
  remoteAddress: rawRemote,
17909
17962
  xForwardedFor: rawXff,
17910
17963
  cookieHeader: c.req.header("cookie"),
17911
- isPublicHost
17964
+ // Task 829 — operator-wins: an operator host is admin-gated, so it must not
17965
+ // be classified public here (which would bypass the admin gate). A host in
17966
+ // both operator-domains.json and alias-domains.json stays admin-gated.
17967
+ isPublicHost: (h) => !isOperatorHost(h, getOperatorDomains()) && isPublicHost(h)
17912
17968
  });
17913
17969
  if (decision.allow) {
17914
17970
  await next();
@@ -17965,13 +18021,13 @@ app48.get("/agent-assets/:slug/:filename", (c) => {
17965
18021
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
17966
18022
  return c.text("Not found", 404);
17967
18023
  }
17968
- const filePath = resolve28(account.accountDir, "agents", slug, "assets", filename);
17969
- const expectedDir = resolve28(account.accountDir, "agents", slug, "assets");
18024
+ const filePath = resolve29(account.accountDir, "agents", slug, "assets", filename);
18025
+ const expectedDir = resolve29(account.accountDir, "agents", slug, "assets");
17970
18026
  if (!filePath.startsWith(expectedDir + "/")) {
17971
18027
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
17972
18028
  return c.text("Forbidden", 403);
17973
18029
  }
17974
- if (!existsSync26(filePath)) {
18030
+ if (!existsSync27(filePath)) {
17975
18031
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
17976
18032
  return c.text("Not found", 404);
17977
18033
  }
@@ -17995,13 +18051,13 @@ app48.get("/generated/:filename", (c) => {
17995
18051
  console.error(`[generated] serve file=${filename} status=404`);
17996
18052
  return c.text("Not found", 404);
17997
18053
  }
17998
- const filePath = resolve28(account.accountDir, "generated", filename);
17999
- const expectedDir = resolve28(account.accountDir, "generated");
18054
+ const filePath = resolve29(account.accountDir, "generated", filename);
18055
+ const expectedDir = resolve29(account.accountDir, "generated");
18000
18056
  if (!filePath.startsWith(expectedDir + "/")) {
18001
18057
  console.error(`[generated] serve file=${filename} status=403`);
18002
18058
  return c.text("Forbidden", 403);
18003
18059
  }
18004
- if (!existsSync26(filePath)) {
18060
+ if (!existsSync27(filePath)) {
18005
18061
  console.error(`[generated] serve file=${filename} status=404`);
18006
18062
  return c.text("Not found", 404);
18007
18063
  }
@@ -18021,7 +18077,7 @@ app48.route("/v", visitor_consent_default);
18021
18077
  var htmlCache = /* @__PURE__ */ new Map();
18022
18078
  var brandLogoPath = "/brand/maxy-monochrome.png";
18023
18079
  var brandIconPath = "/brand/maxy-monochrome.png";
18024
- if (BRAND_JSON_PATH && existsSync26(BRAND_JSON_PATH)) {
18080
+ if (BRAND_JSON_PATH && existsSync27(BRAND_JSON_PATH)) {
18025
18081
  try {
18026
18082
  const fullBrand = JSON.parse(readFileSync26(BRAND_JSON_PATH, "utf-8"));
18027
18083
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
@@ -18040,8 +18096,8 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
18040
18096
  function readInstalledVersion() {
18041
18097
  try {
18042
18098
  if (!PLATFORM_ROOT9) return "unknown";
18043
- const versionFile = join21(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
18044
- if (!existsSync26(versionFile)) return "unknown";
18099
+ const versionFile = join22(PLATFORM_ROOT9, "config", `.${BRAND.hostname}-version`);
18100
+ if (!existsSync27(versionFile)) return "unknown";
18045
18101
  const content = readFileSync26(versionFile, "utf-8").trim();
18046
18102
  return content || "unknown";
18047
18103
  } catch {
@@ -18083,7 +18139,7 @@ var clientErrorReporterScript = `<script>
18083
18139
  function cachedHtml(file) {
18084
18140
  let html = htmlCache.get(file);
18085
18141
  if (!html) {
18086
- html = readFileSync26(resolve28(process.cwd(), "public", file), "utf-8");
18142
+ html = readFileSync26(resolve29(process.cwd(), "public", file), "utf-8");
18087
18143
  const productNameEsc = escapeHtml(BRAND.productName);
18088
18144
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
18089
18145
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -18099,12 +18155,12 @@ ${clientErrorReporterScript}
18099
18155
  }
18100
18156
  var brandedHtmlCache = /* @__PURE__ */ new Map();
18101
18157
  function loadBrandingCache(agentSlug) {
18102
- const configDir2 = join21(homedir3(), BRAND.configDir);
18158
+ const configDir2 = join22(homedir3(), BRAND.configDir);
18103
18159
  try {
18104
18160
  const accountId = getDefaultAccountId();
18105
18161
  if (!accountId) return null;
18106
- const cachePath = join21(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
18107
- if (!existsSync26(cachePath)) return null;
18162
+ const cachePath = join22(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
18163
+ if (!existsSync27(cachePath)) return null;
18108
18164
  return JSON.parse(readFileSync26(cachePath, "utf-8"));
18109
18165
  } catch {
18110
18166
  return null;
@@ -18150,7 +18206,12 @@ function agentUnavailableHtml() {
18150
18206
  }
18151
18207
  app48.get("/", (c) => {
18152
18208
  const host = (c.req.header("host") ?? "").split(":")[0];
18153
- if (isPublicHost(host)) {
18209
+ const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
18210
+ if (klass === "operator") {
18211
+ console.log(`[host-class] host=${host} class=operator served=operator.html`);
18212
+ return c.html(cachedHtml("operator.html"));
18213
+ }
18214
+ if (klass === "public") {
18154
18215
  const defaultSlug = resolveDefaultSlug();
18155
18216
  if (!defaultSlug) {
18156
18217
  console.error("[public-root] op=no-default");
@@ -18162,6 +18223,7 @@ app48.get("/", (c) => {
18162
18223
  console.error(`[public-root] op=serve-default slug=${defaultSlug}`);
18163
18224
  return c.html(brandedPublicHtml(defaultSlug));
18164
18225
  }
18226
+ console.log(`[host-class] host=${host} class=admin served=index.html`);
18165
18227
  return c.html(cachedHtml("index.html"));
18166
18228
  });
18167
18229
  app48.get("/public", (c) => {
@@ -18193,7 +18255,7 @@ app48.use("/vnc-popout.html", logViewerFetch);
18193
18255
  app48.get("/vnc-popout.html", (c) => {
18194
18256
  let html = htmlCache.get("vnc-popout.html");
18195
18257
  if (!html) {
18196
- html = readFileSync26(resolve28(process.cwd(), "public", "vnc-popout.html"), "utf-8");
18258
+ html = readFileSync26(resolve29(process.cwd(), "public", "vnc-popout.html"), "utf-8");
18197
18259
  const name = escapeHtml(BRAND.productName);
18198
18260
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
18199
18261
  html = html.replace("</head>", ` ${brandScript}
@@ -18229,7 +18291,7 @@ app48.get("/g/:slug", (c) => {
18229
18291
  });
18230
18292
  app48.get("/graph", (c) => {
18231
18293
  const host = (c.req.header("host") ?? "").split(":")[0];
18232
- if (isPublicHost(host)) return c.text("Not found", 404);
18294
+ if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
18233
18295
  return c.html(cachedHtml("graph.html"));
18234
18296
  });
18235
18297
  app48.get("/chat", (c) => {
@@ -18244,7 +18306,7 @@ app48.get("/data", (c) => {
18244
18306
  });
18245
18307
  app48.get("/browser", (c) => {
18246
18308
  const host = (c.req.header("host") ?? "").split(":")[0];
18247
- if (isPublicHost(host)) return c.text("Not found", 404);
18309
+ if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
18248
18310
  return c.html(cachedHtml("browser.html"));
18249
18311
  });
18250
18312
  app48.get("/:slug", async (c, next) => {
@@ -18349,7 +18411,7 @@ try {
18349
18411
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
18350
18412
  async function runAdminUserReconcileTick() {
18351
18413
  try {
18352
- if (!existsSync26(USERS_FILE)) {
18414
+ if (!existsSync27(USERS_FILE)) {
18353
18415
  console.error("[adminuser-self-heal] skip reason=no-users-file");
18354
18416
  return;
18355
18417
  }
@@ -18463,7 +18525,7 @@ if (bootAccountConfig?.whatsapp) {
18463
18525
  }
18464
18526
  init({
18465
18527
  configDir: configDirForWhatsApp,
18466
- platformRoot: resolve28(process.env.MAXY_PLATFORM_ROOT ?? join21(__dirname, "..")),
18528
+ platformRoot: resolve29(process.env.MAXY_PLATFORM_ROOT ?? join22(__dirname, "..")),
18467
18529
  accountConfig: bootAccountConfig,
18468
18530
  onMessage: async (msg) => {
18469
18531
  if (msg.isOwnerMirror) {