@rubytech/create-sitedesk-code 0.1.528 → 0.1.529

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 (214) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/account-ingest-token/dist/index.d.ts +21 -0
  3. package/payload/platform/lib/account-ingest-token/dist/index.d.ts.map +1 -0
  4. package/payload/platform/lib/account-ingest-token/dist/index.js +128 -0
  5. package/payload/platform/lib/account-ingest-token/dist/index.js.map +1 -0
  6. package/payload/platform/lib/account-ingest-token/src/index.ts +137 -0
  7. package/payload/platform/lib/account-ingest-token/tsconfig.json +8 -0
  8. package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts +5 -0
  9. package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
  10. package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
  11. package/payload/platform/lib/agent-dispatch-rule/src/index.ts +5 -0
  12. package/payload/platform/package.json +2 -2
  13. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  14. package/payload/platform/plugins/admin/PLUGIN.md +5 -1
  15. package/payload/platform/plugins/admin/mcp/dist/index.js +37 -0
  16. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  17. package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts +10 -0
  18. package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts.map +1 -0
  19. package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js +22 -0
  20. package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js.map +1 -0
  21. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +25 -4
  22. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
  23. package/payload/platform/plugins/docs/references/admin-ui.md +22 -1
  24. package/payload/platform/plugins/docs/references/linkedin-extension.md +2 -2
  25. package/payload/platform/plugins/linkedin-extension/extension/README.md +3 -3
  26. package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +12 -7
  27. package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +4 -1
  28. package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +4 -1
  29. package/payload/platform/plugins/linkedin-extension/extension/options/options.html +3 -3
  30. package/payload/platform/plugins/linkedin-extension/extension/options/options.js +24 -16
  31. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +45 -2
  32. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -1
  33. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  34. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +15 -2
  35. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  37. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  38. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  39. package/payload/server/public/activity.html +5 -5
  40. package/payload/server/public/agents.html +4 -4
  41. package/payload/server/public/assets/{AdminLoginScreens-Bx9vPuUg.js → AdminLoginScreens-zfexKfbT.js} +1 -1
  42. package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.br +0 -0
  43. package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.gz +0 -0
  44. package/payload/server/public/assets/{AdminShell-BxJPbC3p.js → AdminShell-Cbk0TL1B.js} +1 -1
  45. package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.br +0 -0
  46. package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.gz +0 -0
  47. package/payload/server/public/assets/{CdpScreencastSurface-5HLhTQTV.js → CdpScreencastSurface-CLSQHh4e.js} +1 -1
  48. package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.br +0 -0
  49. package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.gz +0 -0
  50. package/payload/server/public/assets/{activity-BaSYn62l.js → activity-u275Oc-u.js} +1 -1
  51. package/payload/server/public/assets/activity-u275Oc-u.js.br +0 -0
  52. package/payload/server/public/assets/activity-u275Oc-u.js.gz +0 -0
  53. package/payload/server/public/assets/{admin-CYCKrV_x.js → admin-Du1nR_hP.js} +1 -1
  54. package/payload/server/public/assets/admin-Du1nR_hP.js.br +0 -0
  55. package/payload/server/public/assets/admin-Du1nR_hP.js.gz +0 -0
  56. package/payload/server/public/assets/{agents-D8EJG-ta.js → agents-DJTxRLLU.js} +1 -1
  57. package/payload/server/public/assets/agents-DJTxRLLU.js.br +0 -0
  58. package/payload/server/public/assets/agents-DJTxRLLU.js.gz +0 -0
  59. package/payload/server/public/assets/{browser-D6Y_Zu8C.js → browser-Bft6zVkX.js} +1 -1
  60. package/payload/server/public/assets/browser-Bft6zVkX.js.br +0 -0
  61. package/payload/server/public/assets/browser-Bft6zVkX.js.gz +0 -0
  62. package/payload/server/public/assets/{calendar-DD4oVa-r.js → calendar-Ct-DCCqY.js} +1 -1
  63. package/payload/server/public/assets/calendar-Ct-DCCqY.js.br +0 -0
  64. package/payload/server/public/assets/calendar-Ct-DCCqY.js.gz +0 -0
  65. package/payload/server/public/assets/chat-pqasbAg8.js +1 -0
  66. package/payload/server/public/assets/chat-pqasbAg8.js.br +0 -0
  67. package/payload/server/public/assets/chat-pqasbAg8.js.gz +0 -0
  68. package/payload/server/public/assets/chevron-left-C8LTc7lb.js +1 -0
  69. package/payload/server/public/assets/chevron-right-Lz9t7Hed.js +1 -0
  70. package/payload/server/public/assets/chevron-right-Lz9t7Hed.js.br +0 -0
  71. package/payload/server/public/assets/clock-D6QQFHwJ.js +1 -0
  72. package/payload/server/public/assets/clock-D6QQFHwJ.js.br +0 -0
  73. package/payload/server/public/assets/clock-D6QQFHwJ.js.gz +0 -0
  74. package/payload/server/public/assets/data-B1JJ3Y1T.js +1 -0
  75. package/payload/server/public/assets/data-B1JJ3Y1T.js.br +0 -0
  76. package/payload/server/public/assets/data-B1JJ3Y1T.js.gz +0 -0
  77. package/payload/server/public/assets/{file-download-sXU3_umF.js → file-download-C_fSe4dm.js} +1 -1
  78. package/payload/server/public/assets/file-download-C_fSe4dm.js.br +0 -0
  79. package/payload/server/public/assets/file-download-C_fSe4dm.js.gz +0 -0
  80. package/payload/server/public/assets/{file-text-CeXBviDH.js → file-text-D7GbEcqj.js} +1 -1
  81. package/payload/server/public/assets/file-text-D7GbEcqj.js.br +0 -0
  82. package/payload/server/public/assets/file-text-D7GbEcqj.js.gz +0 -0
  83. package/payload/server/public/assets/{graph-labels-D2pQkgYW.js → graph-labels-Dlcb6cW7.js} +1 -1
  84. package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.br +0 -0
  85. package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.gz +0 -0
  86. package/payload/server/public/assets/{graph-BSuDP6k7.js → graph-yl5qU1kO.js} +1 -1
  87. package/payload/server/public/assets/graph-yl5qU1kO.js.br +0 -0
  88. package/payload/server/public/assets/graph-yl5qU1kO.js.gz +0 -0
  89. package/payload/server/public/assets/{maximize-2-DlzSNygU.js → maximize-2-BS689r4W.js} +1 -1
  90. package/payload/server/public/assets/maximize-2-BS689r4W.js.br +0 -0
  91. package/payload/server/public/assets/maximize-2-BS689r4W.js.gz +0 -0
  92. package/payload/server/public/assets/{operator-BP61-xjz.js → operator-CvapnpIW.js} +1 -1
  93. package/payload/server/public/assets/operator-CvapnpIW.js.br +0 -0
  94. package/payload/server/public/assets/operator-CvapnpIW.js.gz +0 -0
  95. package/payload/server/public/assets/{page-eQ4OVros.js → page-987y4JbQ.js} +1 -1
  96. package/payload/server/public/assets/page-987y4JbQ.js.br +0 -0
  97. package/payload/server/public/assets/page-987y4JbQ.js.gz +0 -0
  98. package/payload/server/public/assets/{page-DX7ArY_s.js → page-DWkUH4Z_.js} +1 -1
  99. package/payload/server/public/assets/page-DWkUH4Z_.js.br +0 -0
  100. package/payload/server/public/assets/page-DWkUH4Z_.js.gz +0 -0
  101. package/payload/server/public/assets/{public-DPDKFKM2.js → public-D5pi-VFn.js} +1 -1
  102. package/payload/server/public/assets/public-D5pi-VFn.js.br +0 -0
  103. package/payload/server/public/assets/public-D5pi-VFn.js.gz +0 -0
  104. package/payload/server/public/assets/{rotate-ccw-BR0JbPFV.js → rotate-ccw-zNxnK36R.js} +1 -1
  105. package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.br +0 -0
  106. package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.gz +0 -0
  107. package/payload/server/public/assets/routines-mZzrGA5y.js +2 -0
  108. package/payload/server/public/assets/routines-mZzrGA5y.js.br +0 -0
  109. package/payload/server/public/assets/routines-mZzrGA5y.js.gz +0 -0
  110. package/payload/server/public/assets/{skills-fH0uA7cj.js → skills-5A8PockT.js} +1 -1
  111. package/payload/server/public/assets/skills-5A8PockT.js.br +0 -0
  112. package/payload/server/public/assets/skills-5A8PockT.js.gz +0 -0
  113. package/payload/server/public/assets/{tasks-CrVzFrTR.js → tasks-B1_2wc6L.js} +1 -1
  114. package/payload/server/public/assets/tasks-B1_2wc6L.js.br +0 -0
  115. package/payload/server/public/assets/tasks-B1_2wc6L.js.gz +0 -0
  116. package/payload/server/public/assets/{time-entry-format-C_0jiMpQ.js → time-entry-format-CJ2FSSQt.js} +1 -1
  117. package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.br +0 -0
  118. package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.gz +0 -0
  119. package/payload/server/public/assets/{triangle-alert-eLJHC_QJ.js → triangle-alert-CedsrgME.js} +1 -1
  120. package/payload/server/public/assets/triangle-alert-CedsrgME.js.br +0 -0
  121. package/payload/server/public/assets/triangle-alert-CedsrgME.js.gz +0 -0
  122. package/payload/server/public/assets/{useCopyFeedback-vPCmdOmY.js → useCopyFeedback-zjZZUC2-.js} +1 -1
  123. package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.br +0 -0
  124. package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.gz +0 -0
  125. package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css → useSubAccountSwitcher-72THldvm.css} +1 -1
  126. package/payload/server/public/assets/useSubAccountSwitcher-72THldvm.css.br +0 -0
  127. package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css.gz → useSubAccountSwitcher-72THldvm.css.gz} +0 -0
  128. package/payload/server/public/assets/{useVoiceRecorder-D5bFDRqL.js → useVoiceRecorder-CJecnefX.js} +1 -1
  129. package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.br +0 -0
  130. package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.gz +0 -0
  131. package/payload/server/public/assets/{wrench-sXisQXkf.js → wrench-D8BH20W8.js} +1 -1
  132. package/payload/server/public/assets/wrench-D8BH20W8.js.br +0 -0
  133. package/payload/server/public/assets/wrench-D8BH20W8.js.gz +0 -0
  134. package/payload/server/public/browser.html +5 -5
  135. package/payload/server/public/calendar.html +7 -7
  136. package/payload/server/public/chat.html +13 -13
  137. package/payload/server/public/data.html +12 -12
  138. package/payload/server/public/graph.html +9 -9
  139. package/payload/server/public/index.html +16 -16
  140. package/payload/server/public/operator.html +15 -15
  141. package/payload/server/public/public.html +13 -13
  142. package/payload/server/public/routines.html +7 -7
  143. package/payload/server/public/skills.html +5 -5
  144. package/payload/server/public/tasks.html +6 -6
  145. package/payload/server/server.js +343 -205
  146. package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.br +0 -0
  147. package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.gz +0 -0
  148. package/payload/server/public/assets/AdminShell-BxJPbC3p.js.br +0 -0
  149. package/payload/server/public/assets/AdminShell-BxJPbC3p.js.gz +0 -0
  150. package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.br +0 -0
  151. package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.gz +0 -0
  152. package/payload/server/public/assets/activity-BaSYn62l.js.br +0 -0
  153. package/payload/server/public/assets/activity-BaSYn62l.js.gz +0 -0
  154. package/payload/server/public/assets/admin-CYCKrV_x.js.br +0 -0
  155. package/payload/server/public/assets/admin-CYCKrV_x.js.gz +0 -0
  156. package/payload/server/public/assets/agents-D8EJG-ta.js.br +0 -0
  157. package/payload/server/public/assets/agents-D8EJG-ta.js.gz +0 -0
  158. package/payload/server/public/assets/browser-D6Y_Zu8C.js.br +0 -0
  159. package/payload/server/public/assets/browser-D6Y_Zu8C.js.gz +0 -0
  160. package/payload/server/public/assets/calendar-DD4oVa-r.js.br +0 -0
  161. package/payload/server/public/assets/calendar-DD4oVa-r.js.gz +0 -0
  162. package/payload/server/public/assets/chat-CwWs69PO.js +0 -1
  163. package/payload/server/public/assets/chat-CwWs69PO.js.br +0 -0
  164. package/payload/server/public/assets/chat-CwWs69PO.js.gz +0 -0
  165. package/payload/server/public/assets/chevron-left-ClfIy5Fx.js +0 -1
  166. package/payload/server/public/assets/chevron-right-B0QvXpxl.js +0 -1
  167. package/payload/server/public/assets/chevron-right-B0QvXpxl.js.br +0 -0
  168. package/payload/server/public/assets/clock-BIaRnIP_.js +0 -1
  169. package/payload/server/public/assets/clock-BIaRnIP_.js.br +0 -0
  170. package/payload/server/public/assets/clock-BIaRnIP_.js.gz +0 -0
  171. package/payload/server/public/assets/data-O_9Kiicl.js +0 -1
  172. package/payload/server/public/assets/data-O_9Kiicl.js.br +0 -2
  173. package/payload/server/public/assets/data-O_9Kiicl.js.gz +0 -0
  174. package/payload/server/public/assets/file-download-sXU3_umF.js.br +0 -0
  175. package/payload/server/public/assets/file-download-sXU3_umF.js.gz +0 -0
  176. package/payload/server/public/assets/file-text-CeXBviDH.js.br +0 -0
  177. package/payload/server/public/assets/file-text-CeXBviDH.js.gz +0 -0
  178. package/payload/server/public/assets/graph-BSuDP6k7.js.br +0 -0
  179. package/payload/server/public/assets/graph-BSuDP6k7.js.gz +0 -0
  180. package/payload/server/public/assets/graph-labels-D2pQkgYW.js.br +0 -0
  181. package/payload/server/public/assets/graph-labels-D2pQkgYW.js.gz +0 -0
  182. package/payload/server/public/assets/maximize-2-DlzSNygU.js.br +0 -0
  183. package/payload/server/public/assets/maximize-2-DlzSNygU.js.gz +0 -0
  184. package/payload/server/public/assets/operator-BP61-xjz.js.br +0 -0
  185. package/payload/server/public/assets/operator-BP61-xjz.js.gz +0 -0
  186. package/payload/server/public/assets/page-DX7ArY_s.js.br +0 -0
  187. package/payload/server/public/assets/page-DX7ArY_s.js.gz +0 -0
  188. package/payload/server/public/assets/page-eQ4OVros.js.br +0 -0
  189. package/payload/server/public/assets/page-eQ4OVros.js.gz +0 -0
  190. package/payload/server/public/assets/public-DPDKFKM2.js.br +0 -0
  191. package/payload/server/public/assets/public-DPDKFKM2.js.gz +0 -0
  192. package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.br +0 -0
  193. package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.gz +0 -0
  194. package/payload/server/public/assets/routines-y413YZa-.js +0 -1
  195. package/payload/server/public/assets/routines-y413YZa-.js.br +0 -0
  196. package/payload/server/public/assets/routines-y413YZa-.js.gz +0 -0
  197. package/payload/server/public/assets/skills-fH0uA7cj.js.br +0 -0
  198. package/payload/server/public/assets/skills-fH0uA7cj.js.gz +0 -0
  199. package/payload/server/public/assets/tasks-CrVzFrTR.js.br +0 -0
  200. package/payload/server/public/assets/tasks-CrVzFrTR.js.gz +0 -0
  201. package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.br +0 -1
  202. package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.gz +0 -0
  203. package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.br +0 -1
  204. package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.gz +0 -0
  205. package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.br +0 -0
  206. package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.gz +0 -0
  207. package/payload/server/public/assets/useSubAccountSwitcher-DxuUS_C7.css.br +0 -0
  208. package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.br +0 -0
  209. package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.gz +0 -0
  210. package/payload/server/public/assets/wrench-sXisQXkf.js.br +0 -0
  211. package/payload/server/public/assets/wrench-sXisQXkf.js.gz +0 -0
  212. /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js → useSubAccountSwitcher-HjQZjJBr.js} +0 -0
  213. /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.br → useSubAccountSwitcher-HjQZjJBr.js.br} +0 -0
  214. /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.gz → useSubAccountSwitcher-HjQZjJBr.js.gz} +0 -0
@@ -1800,10 +1800,10 @@ var require_dist5 = __commonJS({
1800
1800
  });
1801
1801
 
1802
1802
  // server/index.ts
1803
- import { readFileSync as readFileSync45, existsSync as existsSync48, watchFile, readdirSync as readdirSync28, statSync as statSync25 } from "fs";
1803
+ import { readFileSync as readFileSync46, existsSync as existsSync49, watchFile, readdirSync as readdirSync29, statSync as statSync25 } from "fs";
1804
1804
  import { spawn as spawn3 } from "child_process";
1805
1805
  import { createHash as createHash7 } from "crypto";
1806
- import { resolve as resolve43, join as join52, basename as basename16 } from "path";
1806
+ import { resolve as resolve45, join as join52, basename as basename16 } from "path";
1807
1807
  import { homedir as homedir4 } from "os";
1808
1808
 
1809
1809
  // server/lib/route-cache-watchers.ts
@@ -3299,20 +3299,20 @@ function buildX11Env(chromiumWrapperPath, transport = "vnc") {
3299
3299
 
3300
3300
  // server/routes/health.ts
3301
3301
  function checkPort(port2, timeoutMs = 500) {
3302
- return new Promise((resolve44) => {
3302
+ return new Promise((resolve46) => {
3303
3303
  const socket = createConnection2(port2, "127.0.0.1");
3304
3304
  socket.setTimeout(timeoutMs);
3305
3305
  socket.once("connect", () => {
3306
3306
  socket.destroy();
3307
- resolve44(true);
3307
+ resolve46(true);
3308
3308
  });
3309
3309
  socket.once("error", () => {
3310
3310
  socket.destroy();
3311
- resolve44(false);
3311
+ resolve46(false);
3312
3312
  });
3313
3313
  socket.once("timeout", () => {
3314
3314
  socket.destroy();
3315
- resolve44(false);
3315
+ resolve46(false);
3316
3316
  });
3317
3317
  });
3318
3318
  }
@@ -5003,7 +5003,7 @@ async function defaultResolve(accountId) {
5003
5003
  return resolveSocket2(accountId);
5004
5004
  }
5005
5005
  async function fetchAvatar(accountId, jid, deps = {}) {
5006
- const resolve44 = deps.resolve;
5006
+ const resolve46 = deps.resolve;
5007
5007
  const httpGet = deps.httpGet ?? defaultHttpGet;
5008
5008
  const maxAgeMs = deps.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
5009
5009
  const cached3 = readAvatar(accountId, jid);
@@ -5013,7 +5013,7 @@ async function fetchAvatar(accountId, jid, deps = {}) {
5013
5013
  return "fresh";
5014
5014
  }
5015
5015
  console.log(`${TAG6} op=cache jid=${jid} hit=false ageMs=${ageMs2}`);
5016
- const res = resolve44 ? resolve44(accountId) : await defaultResolve(accountId);
5016
+ const res = resolve46 ? resolve46(accountId) : await defaultResolve(accountId);
5017
5017
  if (!res.ok) {
5018
5018
  console.log(`${TAG6} op=no-socket jid=${jid} account=${accountId.slice(0, 8)} reason=${res.reason}`);
5019
5019
  return "no-socket";
@@ -5982,8 +5982,8 @@ async function startLogin(opts) {
5982
5982
  await clearAuth(authDir);
5983
5983
  let resolveCode = null;
5984
5984
  let rejectCode = null;
5985
- const codePromise = new Promise((resolve44, reject) => {
5986
- resolveCode = resolve44;
5985
+ const codePromise = new Promise((resolve46, reject) => {
5986
+ resolveCode = resolve46;
5987
5987
  rejectCode = reject;
5988
5988
  });
5989
5989
  const codeTimer = setTimeout(
@@ -6729,10 +6729,10 @@ app3.post("/config", async (c) => {
6729
6729
  const entries2 = readdirSync7(agentsDir, { withFileTypes: true });
6730
6730
  for (const entry of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
6731
6731
  if (!entry.isDirectory() || entry.name === "admin") continue;
6732
- const configPath2 = resolve7(agentsDir, entry.name, "config.json");
6733
- if (!existsSync7(configPath2)) continue;
6732
+ const configPath3 = resolve7(agentsDir, entry.name, "config.json");
6733
+ if (!existsSync7(configPath3)) continue;
6734
6734
  try {
6735
- const config = JSON.parse(readFileSync9(configPath2, "utf-8"));
6735
+ const config = JSON.parse(readFileSync9(configPath3, "utf-8"));
6736
6736
  agents.push({ slug: entry.name, displayName: config.displayName ?? entry.name });
6737
6737
  } catch {
6738
6738
  console.error(`${TAG14} config action=list-public-agents error="failed to parse config.json for agent ${entry.name}" \u2014 skipping`);
@@ -7905,10 +7905,10 @@ function discoverPortalAccounts(accountsDir, shared = null) {
7905
7905
  if (!existsSync8(accountsDir)) return [];
7906
7906
  const found = [];
7907
7907
  for (const accountId of readdirSync8(accountsDir)) {
7908
- const configPath2 = join15(accountsDir, accountId, "data-portal.json");
7909
- if (!existsSync8(configPath2)) continue;
7908
+ const configPath3 = join15(accountsDir, accountId, "data-portal.json");
7909
+ if (!existsSync8(configPath3)) continue;
7910
7910
  try {
7911
- const cfg = JSON.parse(readFileSync10(configPath2, "utf-8"));
7911
+ const cfg = JSON.parse(readFileSync10(configPath3, "utf-8"));
7912
7912
  if (typeof cfg.portalDbName === "string" && cfg.portalDbName.length > 0 && typeof cfg.bucketName === "string" && cfg.bucketName.length > 0) {
7913
7913
  found.push({
7914
7914
  accountId,
@@ -13037,7 +13037,7 @@ app13.post("/", async (c) => {
13037
13037
  const safe = typeof v === "string" ? truncate(v, 200) : typeof v === "number" || typeof v === "boolean" ? String(v) : JSON.stringify(v).slice(0, 200);
13038
13038
  return `${k}=${safe}`;
13039
13039
  }).join(" ");
13040
- const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle", "dashboard-load"]);
13040
+ const TAGGED_PREFIX_SOURCES = /* @__PURE__ */ new Set(["stream-log-click", "pwa", "graph-settle", "dashboard-load", "routines"]);
13041
13041
  if (TAGGED_PREFIX_SOURCES.has(source)) {
13042
13042
  console.log(
13043
13043
  `[${source}] ts=${ts} ip=${ip} version=${version || "unknown"}${extra ? " " + extra : ""}`
@@ -13136,15 +13136,15 @@ function operatorRoleFor(config, userId) {
13136
13136
  async function buildAccountOptionList(accounts, userId) {
13137
13137
  const houseAccount = accounts.find((a) => a.config.role === "house");
13138
13138
  console.log(`[admin-accounts] op=list count=${accounts.length} house=${houseAccount?.accountId ?? "none"}`);
13139
- const resolve44 = async (a) => {
13139
+ const resolve46 = async (a) => {
13140
13140
  const businessName = await fetchAccountName(a.accountId) || void 0;
13141
13141
  return { accountId: a.accountId, businessName, role: operatorRoleFor(a.config, userId), isHouse: a.config.role === "house" };
13142
13142
  };
13143
13143
  const houseOptions = await Promise.all(
13144
- accounts.filter((a) => a.config.role === "house").map(resolve44)
13144
+ accounts.filter((a) => a.config.role === "house").map(resolve46)
13145
13145
  );
13146
13146
  const nonHouseOptions = await Promise.all(
13147
- accounts.filter((a) => a.config.role !== "house").map(resolve44)
13147
+ accounts.filter((a) => a.config.role !== "house").map(resolve46)
13148
13148
  );
13149
13149
  const sortKey = (o) => (o.businessName || o.accountId).toLowerCase();
13150
13150
  nonHouseOptions.sort((x, y) => {
@@ -14269,10 +14269,10 @@ app20.get("/", requireAdminSession, (c) => {
14269
14269
  for (const entry of entries2.sort((a, b) => a.name.localeCompare(b.name))) {
14270
14270
  if (!entry.isDirectory()) continue;
14271
14271
  if (entry.name === "admin") continue;
14272
- const configPath2 = resolve20(agentsDir, entry.name, "config.json");
14273
- if (!existsSync30(configPath2)) continue;
14272
+ const configPath3 = resolve20(agentsDir, entry.name, "config.json");
14273
+ if (!existsSync30(configPath3)) continue;
14274
14274
  try {
14275
- const config = JSON.parse(readFileSync28(configPath2, "utf-8"));
14275
+ const config = JSON.parse(readFileSync28(configPath3, "utf-8"));
14276
14276
  agents.push({
14277
14277
  slug: entry.name,
14278
14278
  displayName: config.displayName ?? entry.name,
@@ -14406,11 +14406,11 @@ app20.get("/:slug", requireAdminSession, (c) => {
14406
14406
  });
14407
14407
  }
14408
14408
  const agentDir = resolve20(account.accountDir, "agents", slug);
14409
- const configPath2 = resolve20(agentDir, "config.json");
14410
- if (!existsSync30(configPath2)) return c.json({ error: "Agent not found" }, 404);
14409
+ const configPath3 = resolve20(agentDir, "config.json");
14410
+ if (!existsSync30(configPath3)) return c.json({ error: "Agent not found" }, 404);
14411
14411
  let config;
14412
14412
  try {
14413
- config = JSON.parse(readFileSync28(configPath2, "utf-8"));
14413
+ config = JSON.parse(readFileSync28(configPath3, "utf-8"));
14414
14414
  } catch {
14415
14415
  console.error(`[admin/agents] op=detail slug=${slug} error="config.json parse failed"`);
14416
14416
  return c.json({ error: "Agent config unreadable" }, 500);
@@ -16907,9 +16907,9 @@ async function readAccountNames() {
16907
16907
  }
16908
16908
  for (const name of names) {
16909
16909
  if (!UUID_RE3.test(name)) continue;
16910
- const configPath2 = resolve24(accountsDir, name, "account.json");
16910
+ const configPath3 = resolve24(accountsDir, name, "account.json");
16911
16911
  try {
16912
- const raw = await readFile9(configPath2, "utf8");
16912
+ const raw = await readFile9(configPath3, "utf8");
16913
16913
  const parsed = JSON.parse(raw);
16914
16914
  if (typeof parsed?.name === "string" && parsed.name.length > 0) {
16915
16915
  map.set(name, parsed.name);
@@ -21259,6 +21259,56 @@ var health_default2 = app41;
21259
21259
  // server/routes/admin/linkedin-ingest.ts
21260
21260
  import { randomUUID as randomUUID9 } from "crypto";
21261
21261
 
21262
+ // ../lib/account-ingest-token/src/index.ts
21263
+ import { randomBytes, timingSafeEqual } from "crypto";
21264
+ import { existsSync as existsSync37, readdirSync as readdirSync24, readFileSync as readFileSync34, writeFileSync as writeFileSync14 } from "fs";
21265
+ import { resolve as resolve30 } from "path";
21266
+ var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
21267
+ var INGEST_TOKEN_FIELD = "ingestToken";
21268
+ var TOKEN_RE = /^[0-9a-f]{64}$/;
21269
+ function configPath2(accountsDir, accountId) {
21270
+ return resolve30(accountsDir, accountId, "account.json");
21271
+ }
21272
+ function readConfig2(accountsDir, accountId) {
21273
+ const path = configPath2(accountsDir, accountId);
21274
+ if (!existsSync37(path)) return null;
21275
+ try {
21276
+ const parsed = JSON.parse(readFileSync34(path, "utf-8"));
21277
+ return parsed !== null && typeof parsed === "object" ? parsed : null;
21278
+ } catch {
21279
+ return null;
21280
+ }
21281
+ }
21282
+ function readIngestToken(accountsDir, accountId) {
21283
+ const value = readConfig2(accountsDir, accountId)?.[INGEST_TOKEN_FIELD];
21284
+ return typeof value === "string" && TOKEN_RE.test(value) ? value : null;
21285
+ }
21286
+ function listAccountIdsOnDisk(accountsDir) {
21287
+ if (!existsSync37(accountsDir)) return [];
21288
+ let entries2;
21289
+ try {
21290
+ entries2 = readdirSync24(accountsDir);
21291
+ } catch {
21292
+ return [];
21293
+ }
21294
+ return entries2.filter(
21295
+ (name) => UUID_RE4.test(name) && existsSync37(resolve30(accountsDir, name, "account.json"))
21296
+ );
21297
+ }
21298
+ function resolveAccountIdByIngestToken(accountsDir, token) {
21299
+ if (typeof token !== "string" || !TOKEN_RE.test(token)) return null;
21300
+ const probe = Buffer.from(token, "utf-8");
21301
+ for (const accountId of listAccountIdsOnDisk(accountsDir)) {
21302
+ const stored = readIngestToken(accountsDir, accountId);
21303
+ if (!stored) continue;
21304
+ const candidate = Buffer.from(stored, "utf-8");
21305
+ if (candidate.length === probe.length && timingSafeEqual(candidate, probe)) {
21306
+ return accountId;
21307
+ }
21308
+ }
21309
+ return null;
21310
+ }
21311
+
21262
21312
  // app/lib/channel-pty-bridge/manager-client.ts
21263
21313
  function managerBase2() {
21264
21314
  const port2 = requirePortEnv("CLAUDE_SESSION_MANAGER_PORT", { tag: "channel-pty-bridge:manager-client" });
@@ -21483,8 +21533,29 @@ function buildInitialMessage(env) {
21483
21533
  }
21484
21534
  return header;
21485
21535
  }
21536
+ var AUTH_TAG = "[linkedin-ingest-auth]";
21537
+ var requireIngestToken = async (c, next) => {
21538
+ let token = "";
21539
+ try {
21540
+ const body = await c.req.json();
21541
+ if (body && typeof body.ingest_token === "string") token = body.ingest_token;
21542
+ } catch {
21543
+ }
21544
+ if (!token) {
21545
+ console.error(`${AUTH_TAG} outcome=reject status=400 code=token-missing path=${c.req.path}`);
21546
+ return c.json({ ok: false, error: "auth", code: "token-missing" }, 400);
21547
+ }
21548
+ const accountId = resolveAccountIdByIngestToken(ACCOUNTS_DIR, token);
21549
+ if (!accountId) {
21550
+ console.error(`${AUTH_TAG} outcome=reject status=401 code=token-unknown path=${c.req.path}`);
21551
+ return c.json({ ok: false, error: "auth", code: "token-unknown" }, 401);
21552
+ }
21553
+ c.set("ingestAccountId", accountId);
21554
+ console.log(`${AUTH_TAG} outcome=accept accountId=${accountId.slice(0, 8)} path=${c.req.path}`);
21555
+ await next();
21556
+ };
21486
21557
  var app42 = new Hono();
21487
- app42.post("/", requireAdminSession, async (c) => {
21558
+ app42.post("/", requireIngestToken, async (c) => {
21488
21559
  let body;
21489
21560
  try {
21490
21561
  body = await c.req.json();
@@ -21498,8 +21569,7 @@ app42.post("/", requireAdminSession, async (c) => {
21498
21569
  return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
21499
21570
  }
21500
21571
  const envelope = v.envelope;
21501
- const cacheKey = c.var.cacheKey ?? "";
21502
- const senderId = getAccountIdForSession(cacheKey) ?? "";
21572
+ const senderId = c.var.ingestAccountId ?? "";
21503
21573
  if (!senderId) {
21504
21574
  console.error(TAG22 + " rejected status=500 reason=admin-account-not-resolved");
21505
21575
  return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
@@ -22009,7 +22079,7 @@ app48.post("/screencast-event", requireAdminSession, async (c) => {
22009
22079
  var browser_default = app48;
22010
22080
 
22011
22081
  // server/routes/admin/calendar.ts
22012
- import { existsSync as existsSync37 } from "fs";
22082
+ import { existsSync as existsSync38 } from "fs";
22013
22083
  import { join as join44 } from "path";
22014
22084
 
22015
22085
  // server/lib/calendar-ics.ts
@@ -22109,7 +22179,7 @@ function countVEvents(ics) {
22109
22179
  }
22110
22180
 
22111
22181
  // server/lib/calendar-availability.ts
22112
- import { readFileSync as readFileSync34 } from "fs";
22182
+ import { readFileSync as readFileSync35 } from "fs";
22113
22183
  import { join as join43 } from "path";
22114
22184
  var AVAILABILITY_FILENAME = "calendar-availability.json";
22115
22185
  var REQUIRED_KEYS = [
@@ -22122,7 +22192,7 @@ function readAvailabilityConfig(accountDir) {
22122
22192
  const path = join43(accountDir, AVAILABILITY_FILENAME);
22123
22193
  let raw;
22124
22194
  try {
22125
- raw = readFileSync34(path, "utf-8");
22195
+ raw = readFileSync35(path, "utf-8");
22126
22196
  } catch {
22127
22197
  throw new Error(`availability not configured: ${path} not found`);
22128
22198
  }
@@ -22482,7 +22552,7 @@ app49.get("/booking-link", requireAdminSession, (c) => {
22482
22552
  }
22483
22553
  const id82 = account.accountId.slice(0, 8);
22484
22554
  try {
22485
- if (!existsSync37(join44(account.accountDir, AVAILABILITY_FILENAME))) {
22555
+ if (!existsSync38(join44(account.accountDir, AVAILABILITY_FILENAME))) {
22486
22556
  console.log(`[calendar] op=booking-link accountId=${id82} bookingDomain=none source=availability-config`);
22487
22557
  return c.json({ bookingDomain: null });
22488
22558
  }
@@ -22501,7 +22571,7 @@ app49.get("/booking-link", requireAdminSession, (c) => {
22501
22571
  var calendar_default = app49;
22502
22572
 
22503
22573
  // server/routes/admin/data-portal.ts
22504
- import { existsSync as existsSync38, readFileSync as readFileSync35 } from "fs";
22574
+ import { existsSync as existsSync39, readFileSync as readFileSync36 } from "fs";
22505
22575
  import { join as join45 } from "path";
22506
22576
  var app50 = new Hono();
22507
22577
  var PORTAL_FILENAME = "data-portal.json";
@@ -22514,11 +22584,11 @@ app50.get("/portal-link", requireAdminSession, (c) => {
22514
22584
  const id82 = account.accountId.slice(0, 8);
22515
22585
  try {
22516
22586
  const path = join45(account.accountDir, PORTAL_FILENAME);
22517
- if (!existsSync38(path)) {
22587
+ if (!existsSync39(path)) {
22518
22588
  console.log(`[data-portal] op=portal-link accountId=${id82} portalDomain=none source=data-portal-config`);
22519
22589
  return c.json({ portalDomain: null });
22520
22590
  }
22521
- const cfg = JSON.parse(readFileSync35(path, "utf-8"));
22591
+ const cfg = JSON.parse(readFileSync36(path, "utf-8"));
22522
22592
  const portalDomain = typeof cfg.portalDomain === "string" && cfg.portalDomain.trim() ? cfg.portalDomain.trim() : null;
22523
22593
  console.log(`[data-portal] op=portal-link accountId=${id82} portalDomain=${portalDomain ?? "none"} source=data-portal-config`);
22524
22594
  return c.json({ portalDomain });
@@ -22535,8 +22605,8 @@ import cronParser from "cron-parser";
22535
22605
  import { int as int2 } from "neo4j-driver";
22536
22606
 
22537
22607
  // ../lib/agent-dispatch-rule/src/index.ts
22538
- import { readFileSync as readFileSync36 } from "fs";
22539
- import { resolve as resolve30 } from "path";
22608
+ import { readFileSync as readFileSync37 } from "fs";
22609
+ import { resolve as resolve31 } from "path";
22540
22610
  function normalizeE1642(value) {
22541
22611
  let candidate = value.trim().replace(/[\s\-().]/g, "");
22542
22612
  candidate = candidate.replace(/^whatsapp:/i, "");
@@ -22553,7 +22623,7 @@ function phonesMatch2(a, b) {
22553
22623
  function readChannelAdmins(accountDir, channel) {
22554
22624
  let config = {};
22555
22625
  try {
22556
- config = JSON.parse(readFileSync36(resolve30(accountDir, "account.json"), "utf-8"));
22626
+ config = JSON.parse(readFileSync37(resolve31(accountDir, "account.json"), "utf-8"));
22557
22627
  } catch {
22558
22628
  config = {};
22559
22629
  }
@@ -22585,9 +22655,16 @@ function registeredAccountForDestination(houseDir, houseAccountId, destination)
22585
22655
  if (adminPhones.some((p) => phonesMatch2(p, destination))) return houseAccountId;
22586
22656
  return null;
22587
22657
  }
22658
+ function boundSubAccountFor(accountDir, destination) {
22659
+ const { accountManagers } = readChannelAdmins(accountDir, "whatsapp");
22660
+ for (const [managerPhone, subAccountId] of Object.entries(accountManagers)) {
22661
+ if (subAccountId && phonesMatch2(managerPhone, destination)) return subAccountId;
22662
+ }
22663
+ return null;
22664
+ }
22588
22665
  function validateAgentDestination(accountsDir, houseAccountId, creatingAccountId, channel, destination) {
22589
22666
  if (channel === "whatsapp") {
22590
- const houseDir = resolve30(accountsDir, houseAccountId);
22667
+ const houseDir = resolve31(accountsDir, houseAccountId);
22591
22668
  const registered = registeredAccountForDestination(houseDir, houseAccountId, destination);
22592
22669
  if (registered === null) return { valid: false, reason: "not-registered" };
22593
22670
  if (creatingAccountId === houseAccountId) return { valid: true };
@@ -22599,7 +22676,7 @@ function validateAgentDestination(accountsDir, houseAccountId, creatingAccountId
22599
22676
  scheduleAccount: creatingAccountId
22600
22677
  };
22601
22678
  }
22602
- const { adminUsers } = readChannelAdmins(resolve30(accountsDir, creatingAccountId), "telegram");
22679
+ const { adminUsers } = readChannelAdmins(resolve31(accountsDir, creatingAccountId), "telegram");
22603
22680
  const asNumber = Number(destination);
22604
22681
  const ok = Number.isInteger(asNumber) && adminUsers.includes(asNumber);
22605
22682
  return ok ? { valid: true } : { valid: false, reason: "not-registered" };
@@ -22609,7 +22686,7 @@ function listDispatchDestinations(input) {
22609
22686
  const managers = [];
22610
22687
  const admins = [];
22611
22688
  if (houseAccountId !== null) {
22612
- const houseDir = resolve30(accountsDir, houseAccountId);
22689
+ const houseDir = resolve31(accountsDir, houseAccountId);
22613
22690
  const { adminPhones, accountManagers } = readChannelAdmins(houseDir, "whatsapp");
22614
22691
  const seen = /* @__PURE__ */ new Set();
22615
22692
  for (const [phone, subAccountId] of Object.entries(accountManagers)) {
@@ -22627,7 +22704,7 @@ function listDispatchDestinations(input) {
22627
22704
  admins.push({ channel: "whatsapp", destination: phone, label: "House admin" });
22628
22705
  }
22629
22706
  }
22630
- const { adminUsers } = readChannelAdmins(resolve30(accountsDir, accountId), "telegram");
22707
+ const { adminUsers } = readChannelAdmins(resolve31(accountsDir, accountId), "telegram");
22631
22708
  const telegram = [...adminUsers].sort((a, b) => a - b).map((id) => ({ channel: "telegram", destination: String(id), label: "Telegram admin" }));
22632
22709
  const byDestination = (a, b) => a.destination.localeCompare(b.destination);
22633
22710
  return [...managers.sort(byDestination), ...admins.sort(byDestination), ...telegram];
@@ -23294,8 +23371,8 @@ app51.delete("/:eventId", requireAdminSession, async (c) => {
23294
23371
  var routines_default = app51;
23295
23372
 
23296
23373
  // server/routes/admin/skills.ts
23297
- import { existsSync as existsSync39, readdirSync as readdirSync24, readFileSync as readFileSync37, rmSync as rmSync5 } from "fs";
23298
- import { resolve as resolve31 } from "path";
23374
+ import { existsSync as existsSync40, readdirSync as readdirSync25, readFileSync as readFileSync38, rmSync as rmSync5 } from "fs";
23375
+ import { resolve as resolve32 } from "path";
23299
23376
  var app52 = new Hono();
23300
23377
  var NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
23301
23378
  function splitSkillMd(text) {
@@ -23318,9 +23395,9 @@ function stripQuotes(s) {
23318
23395
  return s;
23319
23396
  }
23320
23397
  function subdirs2(dir) {
23321
- if (!existsSync39(dir)) return [];
23398
+ if (!existsSync40(dir)) return [];
23322
23399
  try {
23323
- return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
23400
+ return readdirSync25(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
23324
23401
  } catch {
23325
23402
  return [];
23326
23403
  }
@@ -23333,19 +23410,19 @@ app52.get("/", requireAdminSession, async (c) => {
23333
23410
  }
23334
23411
  ensureAccountWatchers(acct.accountId, acct.accountDir);
23335
23412
  const { value, state } = await getOrCompute("skills", acct.accountId, async () => {
23336
- const pluginsDir = resolve31(acct.accountDir, "plugins");
23413
+ const pluginsDir = resolve32(acct.accountDir, "plugins");
23337
23414
  const skills = [];
23338
23415
  let pluginCount = 0;
23339
23416
  for (const plugin of subdirs2(pluginsDir)) {
23340
23417
  pluginCount++;
23341
- const skillsDir = resolve31(pluginsDir, plugin, "skills");
23418
+ const skillsDir = resolve32(pluginsDir, plugin, "skills");
23342
23419
  for (const skill of subdirs2(skillsDir)) {
23343
- const skillMd = resolve31(skillsDir, skill, "SKILL.md");
23344
- if (!existsSync39(skillMd)) continue;
23420
+ const skillMd = resolve32(skillsDir, skill, "SKILL.md");
23421
+ if (!existsSync40(skillMd)) continue;
23345
23422
  try {
23346
- const { frontmatter } = splitSkillMd(readFileSync37(skillMd, "utf-8"));
23347
- const refsDir = resolve31(skillsDir, skill, "references");
23348
- const refCount = existsSync39(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
23423
+ const { frontmatter } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
23424
+ const refsDir = resolve32(skillsDir, skill, "references");
23425
+ const refCount = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).length : 0;
23349
23426
  skills.push({ plugin, skill, description: frontmatter.description, refCount });
23350
23427
  } catch (err) {
23351
23428
  console.error(`[admin:skills] op=list-skip plugin=${plugin} skill=${skill} reason="${err instanceof Error ? err.message : String(err)}"`);
@@ -23367,15 +23444,15 @@ app52.get("/:plugin/:skill", requireAdminSession, async (c) => {
23367
23444
  console.error(`[admin:skills] op=get outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
23368
23445
  return c.json({ error: "Invalid plugin or skill name" }, 400);
23369
23446
  }
23370
- const skillDir = resolve31(acct.accountDir, "plugins", plugin, "skills", skill);
23371
- const skillMd = resolve31(skillDir, "SKILL.md");
23372
- const found = existsSync39(skillMd);
23447
+ const skillDir = resolve32(acct.accountDir, "plugins", plugin, "skills", skill);
23448
+ const skillMd = resolve32(skillDir, "SKILL.md");
23449
+ const found = existsSync40(skillMd);
23373
23450
  console.log(`[admin:skills] op=get plugin=${plugin} skill=${skill} found=${found}`);
23374
23451
  if (!found) return c.json({ error: "Skill not found" }, 404);
23375
23452
  try {
23376
- const { frontmatter, body } = splitSkillMd(readFileSync37(skillMd, "utf-8"));
23377
- const refsDir = resolve31(skillDir, "references");
23378
- const references = existsSync39(refsDir) ? readdirSync24(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
23453
+ const { frontmatter, body } = splitSkillMd(readFileSync38(skillMd, "utf-8"));
23454
+ const refsDir = resolve32(skillDir, "references");
23455
+ const references = existsSync40(refsDir) ? readdirSync25(refsDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name).sort() : [];
23379
23456
  return c.json({ skill: { plugin, skill, frontmatter, body, references } });
23380
23457
  } catch (err) {
23381
23458
  const message = err instanceof Error ? err.message : String(err);
@@ -23392,10 +23469,10 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
23392
23469
  console.error(`[admin:skills] op=delete outcome=rejected reason=invalid-name plugin="${plugin}" skill="${skill}"`);
23393
23470
  return c.json({ error: "Invalid plugin or skill name" }, 400);
23394
23471
  }
23395
- const pluginDir = resolve31(acct.accountDir, "plugins", plugin);
23396
- const skillsDir = resolve31(pluginDir, "skills");
23397
- const skillDir = resolve31(skillsDir, skill);
23398
- if (!existsSync39(resolve31(skillDir, "SKILL.md"))) {
23472
+ const pluginDir = resolve32(acct.accountDir, "plugins", plugin);
23473
+ const skillsDir = resolve32(pluginDir, "skills");
23474
+ const skillDir = resolve32(skillsDir, skill);
23475
+ if (!existsSync40(resolve32(skillDir, "SKILL.md"))) {
23399
23476
  console.error(`[admin:skills] op=delete outcome=rejected reason=not-found plugin=${plugin} skill=${skill}`);
23400
23477
  return c.json({ error: "Skill not found" }, 404);
23401
23478
  }
@@ -23403,7 +23480,7 @@ app52.delete("/:plugin/:skill", requireAdminSession, async (c) => {
23403
23480
  rmSync5(skillDir, { recursive: true, force: true });
23404
23481
  const pluginDirRemoved = subdirs2(skillsDir).length === 0;
23405
23482
  if (pluginDirRemoved) rmSync5(pluginDir, { recursive: true, force: true });
23406
- const skillDirGone = !existsSync39(skillDir);
23483
+ const skillDirGone = !existsSync40(skillDir);
23407
23484
  if (!skillDirGone) {
23408
23485
  console.error(`[admin:skills] op=delete plugin=${plugin} skill=${skill} outcome=rejected reason=rm-incomplete skillDirGone=false`);
23409
23486
  return c.json({ error: "Delete did not remove the skill directory" }, 503);
@@ -23875,20 +23952,20 @@ app57.post("/", requireAdminSession, async (c) => {
23875
23952
  var task_time_adjust_default = app57;
23876
23953
 
23877
23954
  // app/lib/admin-roster.ts
23878
- import { existsSync as existsSync40, readdirSync as readdirSync25, readFileSync as readFileSync38 } from "fs";
23879
- import { resolve as resolve32 } from "path";
23955
+ import { existsSync as existsSync41, readdirSync as readdirSync26, readFileSync as readFileSync39 } from "fs";
23956
+ import { resolve as resolve33 } from "path";
23880
23957
  function readHouseAdminUserIds(accountsDir = ACCOUNTS_DIR) {
23881
23958
  let entries2;
23882
23959
  try {
23883
- entries2 = readdirSync25(accountsDir);
23960
+ entries2 = readdirSync26(accountsDir);
23884
23961
  } catch {
23885
23962
  return [];
23886
23963
  }
23887
23964
  for (const entry of entries2) {
23888
- const cfgPath = resolve32(accountsDir, entry, "account.json");
23889
- if (!existsSync40(cfgPath)) continue;
23965
+ const cfgPath = resolve33(accountsDir, entry, "account.json");
23966
+ if (!existsSync41(cfgPath)) continue;
23890
23967
  try {
23891
- const cfg = JSON.parse(readFileSync38(cfgPath, "utf-8"));
23968
+ const cfg = JSON.parse(readFileSync39(cfgPath, "utf-8"));
23892
23969
  if (cfg.role !== "house") continue;
23893
23970
  if (!Array.isArray(cfg.admins)) return [];
23894
23971
  return cfg.admins.map(
@@ -24218,7 +24295,21 @@ app61.get("/", requireAdminSession, async (c) => {
24218
24295
  var admin_users_list_default = app61;
24219
24296
 
24220
24297
  // server/routes/admin/dispatch-destinations.ts
24298
+ import { resolve as resolve34 } from "path";
24221
24299
  var TAG37 = "[admin:routines]";
24300
+ function scopeFor(d, houseDir, houseAccountId) {
24301
+ if (d.channel !== "whatsapp") return null;
24302
+ if (d.label === "Account manager") return boundSubAccountFor(houseDir, d.destination);
24303
+ return houseAccountId;
24304
+ }
24305
+ function telephoneVariants(destination) {
24306
+ const digits = normalizeE1642(destination);
24307
+ if (digits.length === 0) return [destination];
24308
+ return [.../* @__PURE__ */ new Set([destination, digits, `+${digits}`])];
24309
+ }
24310
+ function scrubDigitRuns(message) {
24311
+ return message.replace(/\d{7,}/g, "<redacted>");
24312
+ }
24222
24313
  var app62 = new Hono();
24223
24314
  app62.get("/", requireAdminSession, async (c) => {
24224
24315
  const accountId = getAccountIdForSession(c.var.cacheKey);
@@ -24234,15 +24325,62 @@ app62.get("/", requireAdminSession, async (c) => {
24234
24325
  console.error(`${TAG37} op=destinations account=${accountId.slice(0, 8)} outcome=house-unresolved reason="${message}"`);
24235
24326
  }
24236
24327
  const destinations = listDispatchDestinations({ accountsDir: ACCOUNTS_DIR, houseAccountId, accountId });
24328
+ const houseDir = houseAccountId === null ? null : resolve34(ACCOUNTS_DIR, houseAccountId);
24329
+ const byScope = /* @__PURE__ */ new Map();
24330
+ for (const d of destinations) {
24331
+ const scope = houseDir === null || houseAccountId === null ? null : scopeFor(d, houseDir, houseAccountId);
24332
+ if (scope === null) continue;
24333
+ const list = byScope.get(scope);
24334
+ if (list) list.push(d);
24335
+ else byScope.set(scope, [d]);
24336
+ }
24337
+ let namesUnresolved = null;
24338
+ let named = 0;
24339
+ if (byScope.size > 0) {
24340
+ let session = null;
24341
+ try {
24342
+ session = getSession();
24343
+ for (const [scopeAccountId, rows] of byScope) {
24344
+ const telephones = [...new Set(rows.flatMap((d) => telephoneVariants(d.destination)))];
24345
+ const result = await session.run(
24346
+ `MATCH (p:Person {accountId: $accountId}) WHERE p.telephone IN $telephones
24347
+ RETURN p.telephone AS telephone, p.givenName AS givenName, p.familyName AS familyName`,
24348
+ { accountId: scopeAccountId, telephones }
24349
+ );
24350
+ const found = /* @__PURE__ */ new Map();
24351
+ for (const rec of result.records) {
24352
+ const tel = rec.get("telephone");
24353
+ if (!tel) continue;
24354
+ const name = [rec.get("givenName"), rec.get("familyName")].filter(Boolean).join(" ");
24355
+ if (name.length > 0) found.set(normalizeE1642(tel), name);
24356
+ }
24357
+ for (const d of rows) {
24358
+ const hit = found.get(normalizeE1642(d.destination));
24359
+ if (hit) {
24360
+ d.name = hit;
24361
+ named += 1;
24362
+ }
24363
+ }
24364
+ }
24365
+ } catch (err) {
24366
+ namesUnresolved = scrubDigitRuns(err instanceof Error ? err.message : String(err));
24367
+ for (const d of destinations) delete d.name;
24368
+ named = 0;
24369
+ } finally {
24370
+ if (session) await session.close();
24371
+ }
24372
+ }
24373
+ const scopes = [...byScope.keys()];
24374
+ const nameScope = scopes.length === 0 ? "none" : scopes.every((s) => s === houseAccountId) ? "house" : scopes.some((s) => s === houseAccountId) ? "mixed" : "account";
24237
24375
  console.log(
24238
- `${TAG37} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length}` + (houseAccountId === null ? " outcome=house-unresolved" : "")
24376
+ `${TAG37} op=destinations account=${accountId.slice(0, 8)} count=${destinations.length} named=${named} unnamed=${destinations.length - named} nameScope=${nameScope}` + (houseAccountId === null ? " outcome=house-unresolved" : "") + (namesUnresolved === null ? "" : ` outcome=names-unresolved reason="${namesUnresolved}"`)
24239
24377
  );
24240
24378
  return c.json({ destinations });
24241
24379
  });
24242
24380
  var dispatch_destinations_default = app62;
24243
24381
 
24244
24382
  // server/routes/admin/activity.ts
24245
- import { readdirSync as readdirSync26 } from "fs";
24383
+ import { readdirSync as readdirSync27 } from "fs";
24246
24384
  var app63 = new Hono();
24247
24385
  var TAG38 = "[activity]";
24248
24386
  function resolveHouseAccountId(accounts) {
@@ -24258,7 +24396,7 @@ function requestToken() {
24258
24396
  var short = (id) => id ? id.slice(0, 8) : "unset";
24259
24397
  function countAccountDirsOnDisk() {
24260
24398
  try {
24261
- return readdirSync26(ACCOUNTS_DIR, { withFileTypes: true }).filter(
24399
+ return readdirSync27(ACCOUNTS_DIR, { withFileTypes: true }).filter(
24262
24400
  (e) => e.isDirectory() && !e.name.startsWith(".")
24263
24401
  ).length;
24264
24402
  } catch {
@@ -24522,9 +24660,9 @@ var verify_token_default = app65;
24522
24660
 
24523
24661
  // app/lib/access-email.ts
24524
24662
  import { spawn as spawn2 } from "child_process";
24525
- import { resolve as resolve33 } from "path";
24526
- var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve33(process.cwd(), "..");
24527
- var SEND_SCRIPT = resolve33(
24663
+ import { resolve as resolve35 } from "path";
24664
+ var PLATFORM_ROOT5 = process.env.MAXY_PLATFORM_ROOT ?? resolve35(process.cwd(), "..");
24665
+ var SEND_SCRIPT = resolve35(
24528
24666
  PLATFORM_ROOT5,
24529
24667
  "plugins",
24530
24668
  "email",
@@ -24666,8 +24804,8 @@ app67.route("/request-magic-link", request_magic_link_default);
24666
24804
  var access_default = app67;
24667
24805
 
24668
24806
  // server/routes/sites.ts
24669
- import { existsSync as existsSync41, readFileSync as readFileSync39, realpathSync as realpathSync8, statSync as statSync22 } from "fs";
24670
- import { resolve as resolve34 } from "path";
24807
+ import { existsSync as existsSync42, readFileSync as readFileSync40, realpathSync as realpathSync8, statSync as statSync22 } from "fs";
24808
+ import { resolve as resolve36 } from "path";
24671
24809
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
24672
24810
  var MIME = {
24673
24811
  ".html": "text/html; charset=utf-8",
@@ -24724,15 +24862,15 @@ app68.get("/:rel{.*}", (c) => {
24724
24862
  }
24725
24863
  segments.push(seg);
24726
24864
  }
24727
- const rootDir = resolve34(account.accountDir, "sites");
24728
- let filePath = segments.length === 0 ? rootDir : resolve34(rootDir, ...segments);
24865
+ const rootDir = resolve36(account.accountDir, "sites");
24866
+ let filePath = segments.length === 0 ? rootDir : resolve36(rootDir, ...segments);
24729
24867
  if (filePath !== rootDir && !filePath.startsWith(rootDir + "/")) {
24730
24868
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24731
24869
  return c.text("Forbidden", 403);
24732
24870
  }
24733
24871
  let stat11;
24734
24872
  try {
24735
- stat11 = existsSync41(filePath) ? statSync22(filePath) : null;
24873
+ stat11 = existsSync42(filePath) ? statSync22(filePath) : null;
24736
24874
  } catch {
24737
24875
  stat11 = null;
24738
24876
  }
@@ -24745,13 +24883,13 @@ app68.get("/:rel{.*}", (c) => {
24745
24883
  return c.redirect(target, 301);
24746
24884
  }
24747
24885
  if (stat11?.isDirectory()) {
24748
- filePath = resolve34(filePath, "index.html");
24886
+ filePath = resolve36(filePath, "index.html");
24749
24887
  }
24750
24888
  if (!filePath.startsWith(rootDir + "/")) {
24751
24889
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
24752
24890
  return c.text("Forbidden", 403);
24753
24891
  }
24754
- if (!existsSync41(filePath)) {
24892
+ if (!existsSync42(filePath)) {
24755
24893
  console.error(`[sites] not-found path=${reqPath} status=404`);
24756
24894
  return c.text("Not found", 404);
24757
24895
  }
@@ -24770,7 +24908,7 @@ app68.get("/:rel{.*}", (c) => {
24770
24908
  }
24771
24909
  let body;
24772
24910
  try {
24773
- body = readFileSync39(realPath);
24911
+ body = readFileSync40(realPath);
24774
24912
  } catch (err) {
24775
24913
  const code = err?.code;
24776
24914
  if (code === "EISDIR") {
@@ -24805,8 +24943,8 @@ app68.get("/:rel{.*}", (c) => {
24805
24943
  var sites_default = app68;
24806
24944
 
24807
24945
  // app/lib/visitor-token.ts
24808
- import { createHmac, randomBytes, timingSafeEqual } from "crypto";
24809
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync40, writeFileSync as writeFileSync14 } from "fs";
24946
+ import { createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
24947
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync41, writeFileSync as writeFileSync15 } from "fs";
24810
24948
  import { dirname as dirname15 } from "path";
24811
24949
  var TOKEN_PREFIX = "v1.";
24812
24950
  var SECRET_BYTES = 32;
@@ -24815,21 +24953,21 @@ var cachedSecret = null;
24815
24953
  function getSecret() {
24816
24954
  if (cachedSecret) return cachedSecret;
24817
24955
  try {
24818
- const hex2 = readFileSync40(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
24956
+ const hex2 = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
24819
24957
  if (hex2.length === SECRET_BYTES * 2) {
24820
24958
  cachedSecret = Buffer.from(hex2, "hex");
24821
24959
  return cachedSecret;
24822
24960
  }
24823
24961
  } catch {
24824
24962
  }
24825
- const fresh = randomBytes(SECRET_BYTES).toString("hex");
24963
+ const fresh = randomBytes2(SECRET_BYTES).toString("hex");
24826
24964
  try {
24827
24965
  mkdirSync8(dirname15(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
24828
- writeFileSync14(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
24966
+ writeFileSync15(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
24829
24967
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
24830
24968
  } catch {
24831
24969
  }
24832
- const hex = readFileSync40(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
24970
+ const hex = readFileSync41(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
24833
24971
  cachedSecret = Buffer.from(hex, "hex");
24834
24972
  return cachedSecret;
24835
24973
  }
@@ -24862,7 +25000,7 @@ function verifyVisitorToken(token, now = Date.now()) {
24862
25000
  const expected = signPayload(payloadJson, getSecret());
24863
25001
  const expectedBuf = Buffer.from(expected, "utf-8");
24864
25002
  const provBuf = Buffer.from(sigB64, "utf-8");
24865
- if (expectedBuf.length !== provBuf.length || !timingSafeEqual(expectedBuf, provBuf)) {
25003
+ if (expectedBuf.length !== provBuf.length || !timingSafeEqual2(expectedBuf, provBuf)) {
24866
25004
  return { ok: false, reason: "bad-sig" };
24867
25005
  }
24868
25006
  let payload;
@@ -24882,7 +25020,7 @@ var VISITOR_COOKIE_NAME = "mxy_v";
24882
25020
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
24883
25021
 
24884
25022
  // app/lib/brand-config.ts
24885
- import { existsSync as existsSync42, readFileSync as readFileSync41 } from "fs";
25023
+ import { existsSync as existsSync43, readFileSync as readFileSync42 } from "fs";
24886
25024
  import { join as join47 } from "path";
24887
25025
  var cached2 = null;
24888
25026
  var cachedAttempted = false;
@@ -24892,9 +25030,9 @@ function readBrandConfig() {
24892
25030
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
24893
25031
  if (!platformRoot5) return null;
24894
25032
  const brandPath = join47(platformRoot5, "config", "brand.json");
24895
- if (!existsSync42(brandPath)) return null;
25033
+ if (!existsSync43(brandPath)) return null;
24896
25034
  try {
24897
- cached2 = JSON.parse(readFileSync41(brandPath, "utf-8"));
25035
+ cached2 = JSON.parse(readFileSync42(brandPath, "utf-8"));
24898
25036
  return cached2;
24899
25037
  } catch {
24900
25038
  return null;
@@ -25391,14 +25529,14 @@ async function writeEvent(opts) {
25391
25529
  var visitor_event_default = app71;
25392
25530
 
25393
25531
  // server/routes/session.ts
25394
- import { resolve as resolve35 } from "path";
25395
- import { existsSync as existsSync43, writeFileSync as writeFileSync15, mkdirSync as mkdirSync9 } from "fs";
25396
- var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
25532
+ import { resolve as resolve37 } from "path";
25533
+ import { existsSync as existsSync44, writeFileSync as writeFileSync16, mkdirSync as mkdirSync9 } from "fs";
25534
+ var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
25397
25535
  function writeBrandingCache(accountId, agentSlug, branding) {
25398
25536
  try {
25399
- const cacheDir = resolve35(MAXY_DIR, "branding-cache", accountId);
25537
+ const cacheDir = resolve37(MAXY_DIR, "branding-cache", accountId);
25400
25538
  mkdirSync9(cacheDir, { recursive: true });
25401
- writeFileSync15(resolve35(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25539
+ writeFileSync16(resolve37(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
25402
25540
  } catch (err) {
25403
25541
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
25404
25542
  }
@@ -25408,7 +25546,7 @@ function parseVisitorCookie2(cookieHeader) {
25408
25546
  const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
25409
25547
  if (!match) return null;
25410
25548
  const value = decodeURIComponent(match[1]).trim();
25411
- return UUID_RE4.test(value) ? value : null;
25549
+ return UUID_RE5.test(value) ? value : null;
25412
25550
  }
25413
25551
  function parseAccessSessionId2(cookieHeader) {
25414
25552
  if (!cookieHeader) return null;
@@ -25475,8 +25613,8 @@ app72.post("/", async (c) => {
25475
25613
  }
25476
25614
  let agentConfig = null;
25477
25615
  if (account) {
25478
- const agentDir = resolve35(account.accountDir, "agents", agentSlug);
25479
- if (!existsSync43(agentDir) || !existsSync43(resolve35(agentDir, "config.json"))) {
25616
+ const agentDir = resolve37(account.accountDir, "agents", agentSlug);
25617
+ if (!existsSync44(agentDir) || !existsSync44(resolve37(agentDir, "config.json"))) {
25480
25618
  return c.json({ error: "Agent not found" }, 404);
25481
25619
  }
25482
25620
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -25506,7 +25644,7 @@ app72.post("/", async (c) => {
25506
25644
  );
25507
25645
  }
25508
25646
  }
25509
- if (body.session_key && typeof body.session_key === "string" && UUID_RE4.test(body.session_key)) {
25647
+ if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
25510
25648
  if (visitorId) {
25511
25649
  const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
25512
25650
  if (recent) {
@@ -25736,7 +25874,7 @@ var calendar_public_default = app73;
25736
25874
  // server/routes/portal-fetch.ts
25737
25875
  import { createReadStream as createReadStream3 } from "fs";
25738
25876
  import { stat as stat8, readFile as readFile11, realpath } from "fs/promises";
25739
- import { join as join48, resolve as resolve36, sep as sep11 } from "path";
25877
+ import { join as join48, resolve as resolve38, sep as sep11 } from "path";
25740
25878
  import { Readable as Readable3 } from "stream";
25741
25879
  var app74 = new Hono();
25742
25880
  var TAG41 = "[portal-fetch]";
@@ -25789,7 +25927,7 @@ ${expiresAtMs}`)
25789
25927
  return diff === 0;
25790
25928
  }
25791
25929
  async function readAccountSecret(accountId) {
25792
- const path = resolve36(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
25930
+ const path = resolve38(DATA_ROOT, "accounts", accountId, "secrets", "data-portal.env");
25793
25931
  let text;
25794
25932
  try {
25795
25933
  text = await readFile11(path, "utf8");
@@ -25825,7 +25963,7 @@ async function resolveFetchTarget(accountDir, relPath, ownerId) {
25825
25963
  const exposeFolders = await readExposeFolders2(accountDir);
25826
25964
  const { exposed } = resolveExposedDirs(schemaText, exposeFolders);
25827
25965
  if (exposed.length === 0 && !ownerId) return { ok: false, reason: "not-exposed" };
25828
- const lexical = resolve36(accountDir, relPath);
25966
+ const lexical = resolve38(accountDir, relPath);
25829
25967
  let root;
25830
25968
  let absolute;
25831
25969
  try {
@@ -25874,7 +26012,7 @@ async function handle(c, headOnly) {
25874
26012
  return c.json({ ok: false, error: "denied" }, 401);
25875
26013
  }
25876
26014
  const target = await resolveFetchTarget(
25877
- resolve36(DATA_ROOT, "accounts", accountId),
26015
+ resolve38(DATA_ROOT, "accounts", accountId),
25878
26016
  relPath,
25879
26017
  owner || void 0
25880
26018
  );
@@ -25988,7 +26126,7 @@ function startTimeEntryCensus(openSession, opts = {}) {
25988
26126
  }
25989
26127
 
25990
26128
  // app/lib/ledger-census.ts
25991
- import { readdirSync as readdirSync27, readFileSync as readFileSync42, statSync as statSync23 } from "fs";
26129
+ import { readdirSync as readdirSync28, readFileSync as readFileSync43, statSync as statSync23 } from "fs";
25992
26130
  import { join as join49 } from "path";
25993
26131
 
25994
26132
  // ../lib/ledger-core/dist/reconcile.js
@@ -26037,7 +26175,7 @@ var DAY_MS = 864e5;
26037
26175
  function countWriteRejects24h(logDir, now) {
26038
26176
  let entries2;
26039
26177
  try {
26040
- entries2 = readdirSync27(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
26178
+ entries2 = readdirSync28(logDir).filter((f) => f.startsWith("mcp-ledger-") && f.endsWith(".log"));
26041
26179
  } catch {
26042
26180
  return 0;
26043
26181
  }
@@ -26046,7 +26184,7 @@ function countWriteRejects24h(logDir, now) {
26046
26184
  const path = join49(logDir, name);
26047
26185
  try {
26048
26186
  if (now - statSync23(path).mtimeMs > DAY_MS) continue;
26049
- for (const line of readFileSync42(path, "utf8").split("\n")) {
26187
+ for (const line of readFileSync43(path, "utf8").split("\n")) {
26050
26188
  if (line.includes("[graph-write] reject")) total += 1;
26051
26189
  }
26052
26190
  } catch {
@@ -26315,7 +26453,7 @@ function startGraphHealthTimer() {
26315
26453
 
26316
26454
  // app/lib/file-watcher.ts
26317
26455
  import * as fsp2 from "fs/promises";
26318
- import { resolve as resolve37, sep as sep12 } from "path";
26456
+ import { resolve as resolve39, sep as sep12 } from "path";
26319
26457
  var ACCOUNT_UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26320
26458
  var DEFAULT_COALESCE_MS = 500;
26321
26459
  var ROOTS = ["accounts"];
@@ -26334,7 +26472,7 @@ async function startFileWatcher(opts = {}) {
26334
26472
  const dropFn = opts.drop ?? dropFileIndex;
26335
26473
  for (const r of ROOTS) {
26336
26474
  try {
26337
- await fsp2.mkdir(resolve37(dataRoot, r), { recursive: true });
26475
+ await fsp2.mkdir(resolve39(dataRoot, r), { recursive: true });
26338
26476
  } catch (err) {
26339
26477
  console.error(
26340
26478
  `[file-watcher] start-failed root="${r}" err="${err.message}" \u2014 index will be maintained by the 5-min reconcile backstop only`
@@ -26355,7 +26493,7 @@ async function startFileWatcher(opts = {}) {
26355
26493
  timers.set(relativePath, t);
26356
26494
  }
26357
26495
  async function runHook(relativePath, accountId) {
26358
- const absolute = resolve37(dataRoot, relativePath);
26496
+ const absolute = resolve39(dataRoot, relativePath);
26359
26497
  let exists = false;
26360
26498
  try {
26361
26499
  const st = await fsp2.stat(absolute);
@@ -26379,7 +26517,7 @@ async function startFileWatcher(opts = {}) {
26379
26517
  }
26380
26518
  }
26381
26519
  async function watchRoot(rootName) {
26382
- const absRoot = resolve37(dataRoot, rootName);
26520
+ const absRoot = resolve39(dataRoot, rootName);
26383
26521
  try {
26384
26522
  const iter = fsp2.watch(absRoot, { recursive: true, signal: controller.signal });
26385
26523
  for await (const event of iter) {
@@ -26418,7 +26556,7 @@ async function startFileWatcher(opts = {}) {
26418
26556
 
26419
26557
  // app/lib/migrate-uploads.ts
26420
26558
  import { mkdir as mkdir4, readdir as readdir6, rename as rename4, rm as rm3 } from "fs/promises";
26421
- import { dirname as dirname16, relative as relative8, resolve as resolve38 } from "path";
26559
+ import { dirname as dirname16, relative as relative8, resolve as resolve40 } from "path";
26422
26560
  var ACCOUNT_UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
26423
26561
  async function walkFiles(dir) {
26424
26562
  const out = [];
@@ -26429,7 +26567,7 @@ async function walkFiles(dir) {
26429
26567
  return out;
26430
26568
  }
26431
26569
  for (const e of entries2) {
26432
- const abs = resolve38(dir, e.name);
26570
+ const abs = resolve40(dir, e.name);
26433
26571
  if (e.isDirectory()) {
26434
26572
  out.push(...await walkFiles(abs));
26435
26573
  } else if (e.isFile()) {
@@ -26449,7 +26587,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26449
26587
  let moved = 0;
26450
26588
  for (const oldAbs of files) {
26451
26589
  const suffix = relative8(srcDir, oldAbs);
26452
- const newAbs = resolve38(destDir, suffix);
26590
+ const newAbs = resolve40(destDir, suffix);
26453
26591
  await mkdir4(dirname16(newAbs), { recursive: true });
26454
26592
  await rename4(oldAbs, newAbs);
26455
26593
  moved++;
@@ -26476,7 +26614,7 @@ async function relocateTree(srcDir, destDir, dataRoot, accountId, session) {
26476
26614
  }
26477
26615
  async function migrateUploads(opts = {}) {
26478
26616
  const dataRoot = opts.dataRoot ?? DATA_ROOT;
26479
- const oldRoot = resolve38(dataRoot, "uploads");
26617
+ const oldRoot = resolve40(dataRoot, "uploads");
26480
26618
  let topEntries;
26481
26619
  try {
26482
26620
  topEntries = await readdir6(oldRoot, { withFileTypes: true });
@@ -26497,8 +26635,8 @@ async function migrateUploads(opts = {}) {
26497
26635
  const name = entry.name;
26498
26636
  if (ACCOUNT_UUID_RE4.test(name)) {
26499
26637
  moved += await relocateTree(
26500
- resolve38(oldRoot, name),
26501
- resolve38(dataRoot, "accounts", name, "uploads"),
26638
+ resolve40(oldRoot, name),
26639
+ resolve40(dataRoot, "accounts", name, "uploads"),
26502
26640
  dataRoot,
26503
26641
  name,
26504
26642
  session
@@ -26510,8 +26648,8 @@ async function migrateUploads(opts = {}) {
26510
26648
  continue;
26511
26649
  }
26512
26650
  moved += await relocateTree(
26513
- resolve38(oldRoot, "public"),
26514
- resolve38(dataRoot, "accounts", installAccountId, "uploads", "public"),
26651
+ resolve40(oldRoot, "public"),
26652
+ resolve40(dataRoot, "accounts", installAccountId, "uploads", "public"),
26515
26653
  dataRoot,
26516
26654
  null,
26517
26655
  // public uploads carry no graph nodes
@@ -26541,7 +26679,7 @@ async function migrateUploads(opts = {}) {
26541
26679
 
26542
26680
  // app/lib/migrate-admin-webchat-sidecars.ts
26543
26681
  import { readdir as readdir7, readFile as readFile12, rename as rename5, writeFile as writeFile4, unlink as unlink4 } from "fs/promises";
26544
- import { existsSync as existsSync44 } from "fs";
26682
+ import { existsSync as existsSync45 } from "fs";
26545
26683
  import { join as join50 } from "path";
26546
26684
  var ADMIN_ROLE2 = "admin";
26547
26685
  var WEBCHAT_CHANNEL2 = "webchat";
@@ -26571,7 +26709,7 @@ async function writeRaw(path, obj) {
26571
26709
  await rename5(tmp, path);
26572
26710
  } catch (err) {
26573
26711
  try {
26574
- if (existsSync44(tmp)) await unlink4(tmp);
26712
+ if (existsSync45(tmp)) await unlink4(tmp);
26575
26713
  } catch {
26576
26714
  }
26577
26715
  throw err;
@@ -26694,7 +26832,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
26694
26832
 
26695
26833
  // app/lib/migrate-sidecar-account-ids.ts
26696
26834
  import { readdir as readdir8, readFile as readFile13, rename as rename6, writeFile as writeFile5, unlink as unlink5 } from "fs/promises";
26697
- import { existsSync as existsSync45 } from "fs";
26835
+ import { existsSync as existsSync46 } from "fs";
26698
26836
  import { join as join51 } from "path";
26699
26837
  var SESSION_META_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
26700
26838
  function projectSlugForCwd(cwd) {
@@ -26721,7 +26859,7 @@ async function writeRaw2(path, obj) {
26721
26859
  await rename6(tmp, path);
26722
26860
  } catch (err) {
26723
26861
  try {
26724
- if (existsSync45(tmp)) await unlink5(tmp);
26862
+ if (existsSync46(tmp)) await unlink5(tmp);
26725
26863
  } catch {
26726
26864
  }
26727
26865
  throw err;
@@ -27897,16 +28035,16 @@ var WebchatGateway = class _WebchatGateway {
27897
28035
  * The public /api/chat route awaits this to return the reply on the same SSE
27898
28036
  * response, preserving the pre-756 POST→single-blob browser contract. */
27899
28037
  awaitReply(key, timeoutMs) {
27900
- return new Promise((resolve44) => {
28038
+ return new Promise((resolve46) => {
27901
28039
  const timer = setTimeout(() => {
27902
28040
  this.replyAwaiters.delete(key);
27903
- resolve44({ timeout: true });
28041
+ resolve46({ timeout: true });
27904
28042
  }, timeoutMs);
27905
28043
  if (timer.unref) timer.unref();
27906
28044
  this.replyAwaiters.set(key, (r) => {
27907
28045
  clearTimeout(timer);
27908
28046
  this.replyAwaiters.delete(key);
27909
- resolve44(r);
28047
+ resolve46(r);
27910
28048
  });
27911
28049
  });
27912
28050
  }
@@ -27917,11 +28055,11 @@ var WebchatGateway = class _WebchatGateway {
27917
28055
  * terminal dialog stays answerable). */
27918
28056
  awaitPermissionVerdict(p, timeoutMs) {
27919
28057
  const k = _WebchatGateway.promptKey(p.key, p.requestId);
27920
- return new Promise((resolve44) => {
28058
+ return new Promise((resolve46) => {
27921
28059
  this.pendingPrompts.get(k)?.resolve({ timeout: true });
27922
28060
  const timer = setTimeout(() => {
27923
28061
  this.pendingPrompts.delete(k);
27924
- resolve44({ timeout: true });
28062
+ resolve46({ timeout: true });
27925
28063
  }, timeoutMs);
27926
28064
  if (timer.unref) timer.unref();
27927
28065
  this.pendingPrompts.set(k, {
@@ -27931,7 +28069,7 @@ var WebchatGateway = class _WebchatGateway {
27931
28069
  clearTimeout(timer);
27932
28070
  this.pendingPrompts.delete(k);
27933
28071
  this.deps.onPointerChange?.(p.key);
27934
- resolve44(r);
28072
+ resolve46(r);
27935
28073
  }
27936
28074
  });
27937
28075
  console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
@@ -28507,7 +28645,7 @@ async function fanOut(subscribers, text, onError, tag) {
28507
28645
 
28508
28646
  // app/lib/webchat/file-delivery.ts
28509
28647
  import { realpathSync as realpathSync9 } from "fs";
28510
- import { resolve as resolve39 } from "path";
28648
+ import { resolve as resolve41 } from "path";
28511
28649
 
28512
28650
  // app/lib/channel-pty-bridge/file-delivery.ts
28513
28651
  var SEND_USER_FILE = "SendUserFile";
@@ -28608,7 +28746,7 @@ function makeWebchatSendFile(entry) {
28608
28746
  console.error(`${TAG45} file-delivery reject reason=no-account sender=${entry.senderId}`);
28609
28747
  return { ok: false, error: "no-account" };
28610
28748
  }
28611
- const accountDir = resolve39(platformRoot2(), "..", "data/accounts", entry.accountId);
28749
+ const accountDir = resolve41(platformRoot2(), "..", "data/accounts", entry.accountId);
28612
28750
  try {
28613
28751
  const resolved = realpathSync9(filePath);
28614
28752
  const accountResolved = realpathSync9(accountDir);
@@ -29172,7 +29310,7 @@ function buildTelegramSpawnRequest(input) {
29172
29310
  // app/lib/telegram/outbound/send-document.ts
29173
29311
  import { realpathSync as realpathSync10 } from "fs";
29174
29312
  import { readFile as readFile14, stat as stat10 } from "fs/promises";
29175
- import { resolve as resolve40, basename as basename15 } from "path";
29313
+ import { resolve as resolve42, basename as basename15 } from "path";
29176
29314
  var TAG47 = "[telegram:outbound]";
29177
29315
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
29178
29316
  async function sendTelegramDocument(input) {
@@ -29183,7 +29321,7 @@ async function sendTelegramDocument(input) {
29183
29321
  if (!maxyAccountId || !platformRoot5) {
29184
29322
  return { ok: false, status: 400, error: "Cannot validate file path: missing account or platform context" };
29185
29323
  }
29186
- const accountDir = resolve40(platformRoot5, "..", "data/accounts", maxyAccountId);
29324
+ const accountDir = resolve42(platformRoot5, "..", "data/accounts", maxyAccountId);
29187
29325
  let accountResolved;
29188
29326
  try {
29189
29327
  accountResolved = realpathSync10(accountDir);
@@ -29591,14 +29729,14 @@ function resolveScheduledEffectiveAccountForInstall(accountDir, destination) {
29591
29729
  }
29592
29730
 
29593
29731
  // server/lib/booking-site-accounts.ts
29594
- import { existsSync as existsSync46, readFileSync as readFileSync43 } from "fs";
29595
- import { resolve as resolve41 } from "path";
29732
+ import { existsSync as existsSync47, readFileSync as readFileSync44 } from "fs";
29733
+ import { resolve as resolve43 } from "path";
29596
29734
  function listBookingSiteAccounts(accounts) {
29597
29735
  return accounts.filter((a) => {
29598
- const availPath = resolve41(a.accountDir, "calendar-availability.json");
29599
- if (!existsSync46(availPath)) return false;
29736
+ const availPath = resolve43(a.accountDir, "calendar-availability.json");
29737
+ if (!existsSync47(availPath)) return false;
29600
29738
  try {
29601
- const cfg = JSON.parse(readFileSync43(availPath, "utf-8"));
29739
+ const cfg = JSON.parse(readFileSync44(availPath, "utf-8"));
29602
29740
  return typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
29603
29741
  } catch {
29604
29742
  return false;
@@ -29636,8 +29774,8 @@ function broadcastAdminShutdown(reason) {
29636
29774
 
29637
29775
  // ../lib/entitlement/src/index.ts
29638
29776
  import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
29639
- import { existsSync as existsSync47, readFileSync as readFileSync44, statSync as statSync24 } from "fs";
29640
- import { resolve as resolve42 } from "path";
29777
+ import { existsSync as existsSync48, readFileSync as readFileSync45, statSync as statSync24 } from "fs";
29778
+ import { resolve as resolve44 } from "path";
29641
29779
 
29642
29780
  // ../lib/entitlement/src/canonicalize.ts
29643
29781
  function canonicalize(value) {
@@ -29672,7 +29810,7 @@ var PUBKEY_SHA256 = "8eee6bcb33545fd13b16d3199a5735ca5db5062834c7b49dfe4f23801d9
29672
29810
  var GRACE_DAYS = 7;
29673
29811
  var GRACE_MS = GRACE_DAYS * 24 * 60 * 60 * 1e3;
29674
29812
  function pubkeyPath(brand) {
29675
- return resolve42(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29813
+ return resolve44(brand.platformRoot, "lib", "entitlement", "rubytech-pubkey.pem");
29676
29814
  }
29677
29815
  var memo = null;
29678
29816
  function memoKey(mtimeMs, account) {
@@ -29684,8 +29822,8 @@ function resolveEntitlement(brand, account) {
29684
29822
  if (brand.commercialMode !== true) {
29685
29823
  return logResolved(implicitTrust(account), null);
29686
29824
  }
29687
- const entitlementPath = resolve42(brand.configDir, "entitlement.json");
29688
- if (!existsSync47(entitlementPath)) {
29825
+ const entitlementPath = resolve44(brand.configDir, "entitlement.json");
29826
+ if (!existsSync48(entitlementPath)) {
29689
29827
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
29690
29828
  }
29691
29829
  const stat11 = statSync24(entitlementPath);
@@ -29700,7 +29838,7 @@ function resolveEntitlement(brand, account) {
29700
29838
  function verifyAndResolve(brand, entitlementPath, account) {
29701
29839
  let pubkeyPem;
29702
29840
  try {
29703
- pubkeyPem = readFileSync44(pubkeyPath(brand), "utf-8");
29841
+ pubkeyPem = readFileSync45(pubkeyPath(brand), "utf-8");
29704
29842
  } catch (err) {
29705
29843
  return logResolved(anonymousFallback("pubkey-missing"), {
29706
29844
  reason: "pubkey-missing"
@@ -29714,7 +29852,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
29714
29852
  }
29715
29853
  let envelope;
29716
29854
  try {
29717
- envelope = JSON.parse(readFileSync44(entitlementPath, "utf-8"));
29855
+ envelope = JSON.parse(readFileSync45(entitlementPath, "utf-8"));
29718
29856
  } catch {
29719
29857
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
29720
29858
  }
@@ -29878,12 +30016,12 @@ installMediaDownloadGuard();
29878
30016
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT || "";
29879
30017
  var BRAND_JSON_PATH = PLATFORM_ROOT6 ? join52(PLATFORM_ROOT6, "config", "brand.json") : "";
29880
30018
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
29881
- if (BRAND_JSON_PATH && !existsSync48(BRAND_JSON_PATH)) {
30019
+ if (BRAND_JSON_PATH && !existsSync49(BRAND_JSON_PATH)) {
29882
30020
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
29883
30021
  }
29884
- if (BRAND_JSON_PATH && existsSync48(BRAND_JSON_PATH)) {
30022
+ if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
29885
30023
  try {
29886
- const parsed = JSON.parse(readFileSync45(BRAND_JSON_PATH, "utf-8"));
30024
+ const parsed = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
29887
30025
  BRAND = { ...BRAND, ...parsed };
29888
30026
  } catch (err) {
29889
30027
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -29918,8 +30056,8 @@ var brandLoginOpts = {
29918
30056
  var ALIAS_DOMAINS_PATH = join52(homedir4(), BRAND.configDir, "alias-domains.json");
29919
30057
  function loadAliasDomains() {
29920
30058
  try {
29921
- if (!existsSync48(ALIAS_DOMAINS_PATH)) return null;
29922
- const parsed = JSON.parse(readFileSync45(ALIAS_DOMAINS_PATH, "utf-8"));
30059
+ if (!existsSync49(ALIAS_DOMAINS_PATH)) return null;
30060
+ const parsed = JSON.parse(readFileSync46(ALIAS_DOMAINS_PATH, "utf-8"));
29923
30061
  if (!Array.isArray(parsed)) {
29924
30062
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
29925
30063
  return null;
@@ -29994,7 +30132,7 @@ var waGateway = new WaGateway({
29994
30132
  fetchStandingRules: fetchAccountStandingRules,
29995
30133
  resolveSessionOverride: (accountId, senderId) => resolveChannelOverride(accountId, "whatsapp", senderId),
29996
30134
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
29997
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve43(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
30135
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
29998
30136
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
29999
30137
  // path-validation scope) is the sender's effective SESSION account, resolved
30000
30138
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -30009,7 +30147,7 @@ var waGateway = new WaGateway({
30009
30147
  caption,
30010
30148
  accountId,
30011
30149
  maxyAccountId,
30012
- platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."))
30150
+ platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, ".."))
30013
30151
  });
30014
30152
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
30015
30153
  },
@@ -30711,20 +30849,20 @@ app75.get("/agent-assets/:slug/:filename", (c) => {
30711
30849
  console.error(`[agent-assets] no-account slug=${slug} file=${filename}`);
30712
30850
  return c.text("Not found", 404);
30713
30851
  }
30714
- const filePath = resolve43(account.accountDir, "agents", slug, "assets", filename);
30715
- const expectedDir = resolve43(account.accountDir, "agents", slug, "assets");
30852
+ const filePath = resolve45(account.accountDir, "agents", slug, "assets", filename);
30853
+ const expectedDir = resolve45(account.accountDir, "agents", slug, "assets");
30716
30854
  if (!filePath.startsWith(expectedDir + "/")) {
30717
30855
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
30718
30856
  return c.text("Forbidden", 403);
30719
30857
  }
30720
- if (!existsSync48(filePath)) {
30858
+ if (!existsSync49(filePath)) {
30721
30859
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
30722
30860
  return c.text("Not found", 404);
30723
30861
  }
30724
30862
  const ext = "." + filename.split(".").pop()?.toLowerCase();
30725
30863
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
30726
30864
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
30727
- const body = readFileSync45(filePath);
30865
+ const body = readFileSync46(filePath);
30728
30866
  return c.body(body, 200, {
30729
30867
  "Content-Type": contentType,
30730
30868
  "Cache-Control": "public, max-age=3600"
@@ -30741,20 +30879,20 @@ app75.get("/generated/:filename", (c) => {
30741
30879
  console.error(`[generated] serve file=${filename} status=404`);
30742
30880
  return c.text("Not found", 404);
30743
30881
  }
30744
- const filePath = resolve43(account.accountDir, "generated", filename);
30745
- const expectedDir = resolve43(account.accountDir, "generated");
30882
+ const filePath = resolve45(account.accountDir, "generated", filename);
30883
+ const expectedDir = resolve45(account.accountDir, "generated");
30746
30884
  if (!filePath.startsWith(expectedDir + "/")) {
30747
30885
  console.error(`[generated] serve file=${filename} status=403`);
30748
30886
  return c.text("Forbidden", 403);
30749
30887
  }
30750
- if (!existsSync48(filePath)) {
30888
+ if (!existsSync49(filePath)) {
30751
30889
  console.error(`[generated] serve file=${filename} status=404`);
30752
30890
  return c.text("Not found", 404);
30753
30891
  }
30754
30892
  const ext = "." + filename.split(".").pop()?.toLowerCase();
30755
30893
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
30756
30894
  console.log(`[generated] serve file=${filename} status=200`);
30757
- const body = readFileSync45(filePath);
30895
+ const body = readFileSync46(filePath);
30758
30896
  return c.body(body, 200, {
30759
30897
  "Content-Type": contentType,
30760
30898
  "Cache-Control": "public, max-age=86400"
@@ -30767,9 +30905,9 @@ app75.route("/v", visitor_consent_default);
30767
30905
  var htmlCache = /* @__PURE__ */ new Map();
30768
30906
  var brandLogoPath = "/brand/maxy-monochrome.png";
30769
30907
  var brandIconPath = "/brand/maxy-monochrome.png";
30770
- if (BRAND_JSON_PATH && existsSync48(BRAND_JSON_PATH)) {
30908
+ if (BRAND_JSON_PATH && existsSync49(BRAND_JSON_PATH)) {
30771
30909
  try {
30772
- const fullBrand = JSON.parse(readFileSync45(BRAND_JSON_PATH, "utf-8"));
30910
+ const fullBrand = JSON.parse(readFileSync46(BRAND_JSON_PATH, "utf-8"));
30773
30911
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
30774
30912
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
30775
30913
  } catch {
@@ -30796,11 +30934,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
30796
30934
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
30797
30935
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
30798
30936
  var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
30799
- (p) => existsSync48(resolve43(process.cwd(), "public", p.replace(/^\//, "")))
30937
+ (p) => existsSync49(resolve45(process.cwd(), "public", p.replace(/^\//, "")))
30800
30938
  );
30801
30939
  var SW_SOURCE = (() => {
30802
30940
  try {
30803
- return readFileSync45(resolve43(process.cwd(), "public", "sw.js"), "utf-8");
30941
+ return readFileSync46(resolve45(process.cwd(), "public", "sw.js"), "utf-8");
30804
30942
  } catch {
30805
30943
  return null;
30806
30944
  }
@@ -30809,8 +30947,8 @@ function readInstalledVersion() {
30809
30947
  try {
30810
30948
  if (!PLATFORM_ROOT6) return "unknown";
30811
30949
  const versionFile = join52(PLATFORM_ROOT6, "config", `.${BRAND.hostname}-version`);
30812
- if (!existsSync48(versionFile)) return "unknown";
30813
- const content = readFileSync45(versionFile, "utf-8").trim();
30950
+ if (!existsSync49(versionFile)) return "unknown";
30951
+ const content = readFileSync46(versionFile, "utf-8").trim();
30814
30952
  return content || "unknown";
30815
30953
  } catch {
30816
30954
  return "unknown";
@@ -30821,7 +30959,7 @@ var versionScript = `<script>window.__MAXY_VERSION__=${JSON.stringify(INSTALLED_
30821
30959
  function cachedHtml(file) {
30822
30960
  let html = htmlCache.get(file);
30823
30961
  if (!html) {
30824
- html = readFileSync45(resolve43(process.cwd(), "public", file), "utf-8");
30962
+ html = readFileSync46(resolve45(process.cwd(), "public", file), "utf-8");
30825
30963
  const productNameEsc = escapeHtml(BRAND.productName);
30826
30964
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
30827
30965
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -30843,8 +30981,8 @@ function loadBrandingCache(agentSlug) {
30843
30981
  const accountId = getDefaultAccountId();
30844
30982
  if (!accountId) return null;
30845
30983
  const cachePath = join52(configDir, "branding-cache", accountId, `${agentSlug}.json`);
30846
- if (!existsSync48(cachePath)) return null;
30847
- return JSON.parse(readFileSync45(cachePath, "utf-8"));
30984
+ if (!existsSync49(cachePath)) return null;
30985
+ return JSON.parse(readFileSync46(cachePath, "utf-8"));
30848
30986
  } catch {
30849
30987
  return null;
30850
30988
  }
@@ -30939,7 +31077,7 @@ app75.use("/vnc-popout.html", logViewerFetch);
30939
31077
  app75.get("/vnc-popout.html", (c) => {
30940
31078
  let html = htmlCache.get("vnc-popout.html");
30941
31079
  if (!html) {
30942
- html = readFileSync45(resolve43(process.cwd(), "public", "vnc-popout.html"), "utf-8");
31080
+ html = readFileSync46(resolve45(process.cwd(), "public", "vnc-popout.html"), "utf-8");
30943
31081
  const name = escapeHtml(BRAND.productName);
30944
31082
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
30945
31083
  html = html.replace("</head>", ` ${brandScript}
@@ -31092,9 +31230,9 @@ var httpServer = serve({ fetch: app75.fetch, port, hostname });
31092
31230
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31093
31231
  {
31094
31232
  const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31095
- const reconcileScript = resolve43(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
31233
+ const reconcileScript = resolve45(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
31096
31234
  const runReconcile = (ctx) => {
31097
- if (!existsSync48(reconcileScript)) return;
31235
+ if (!existsSync49(reconcileScript)) return;
31098
31236
  try {
31099
31237
  const child = spawn3(process.execPath, [reconcileScript], {
31100
31238
  env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
@@ -31133,14 +31271,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31133
31271
  {
31134
31272
  const DREAM_CYCLE_SWEEP_INTERVAL_MS = 36e5;
31135
31273
  const dreamPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31136
- const dreamSweepScript = resolve43(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31274
+ const dreamSweepScript = resolve45(dreamPlatformRoot, "plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js");
31137
31275
  registerLoop({
31138
31276
  name: "dream-cycle-sweep",
31139
31277
  intervalMs: DREAM_CYCLE_SWEEP_INTERVAL_MS,
31140
31278
  firstRunDelayMs: 3e4,
31141
31279
  detached: true,
31142
31280
  run: (ctx) => {
31143
- if (!existsSync48(dreamSweepScript)) return;
31281
+ if (!existsSync49(dreamSweepScript)) return;
31144
31282
  try {
31145
31283
  const child = spawn3(process.execPath, [dreamSweepScript], {
31146
31284
  env: { ...process.env, PLATFORM_ROOT: dreamPlatformRoot },
@@ -31157,10 +31295,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31157
31295
  }
31158
31296
  {
31159
31297
  const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31160
- const outlookScript = resolve43(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31298
+ const outlookScript = resolve45(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
31161
31299
  const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
31162
31300
  const runOutlookComplete = (ctx) => {
31163
- if (!existsSync48(outlookScript)) return;
31301
+ if (!existsSync49(outlookScript)) return;
31164
31302
  try {
31165
31303
  const child = spawn3(process.execPath, [outlookScript], {
31166
31304
  env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
@@ -31183,18 +31321,18 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31183
31321
  }
31184
31322
  {
31185
31323
  const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31186
- const strandedAccountsDir = resolve43(auditRoot, "..", "data/accounts");
31324
+ const strandedAccountsDir = resolve45(auditRoot, "..", "data/accounts");
31187
31325
  const STRANDED_AUDIT_INTERVAL_MS = 3e5;
31188
31326
  const STRANDED_AGE_MS = 16 * 6e4;
31189
31327
  const STRANDED_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
31190
31328
  const runStrandedAudit = () => {
31191
31329
  try {
31192
- if (!existsSync48(strandedAccountsDir)) return;
31330
+ if (!existsSync49(strandedAccountsDir)) return;
31193
31331
  const now = Date.now();
31194
- for (const name of readdirSync28(strandedAccountsDir)) {
31332
+ for (const name of readdirSync29(strandedAccountsDir)) {
31195
31333
  if (!STRANDED_UUID_RE.test(name)) continue;
31196
- const pendingPath2 = resolve43(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31197
- if (!existsSync48(pendingPath2)) continue;
31334
+ const pendingPath2 = resolve45(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
31335
+ if (!existsSync49(pendingPath2)) continue;
31198
31336
  const ageMs2 = now - statSync25(pendingPath2).mtimeMs;
31199
31337
  if (ageMs2 > STRANDED_AGE_MS) {
31200
31338
  console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs2 / 1e3)}`);
@@ -31213,7 +31351,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31213
31351
  }
31214
31352
  {
31215
31353
  const googleRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31216
- const googleAccountsDir = resolve43(googleRoot, "..", "data/accounts");
31354
+ const googleAccountsDir = resolve45(googleRoot, "..", "data/accounts");
31217
31355
  const GOOGLE_PENDING_AUDIT_INTERVAL_MS = 3e5;
31218
31356
  const runGooglePendingAuditSafe = () => {
31219
31357
  try {
@@ -31228,10 +31366,10 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31228
31366
  firstRunDelayMs: 27e3,
31229
31367
  run: runGooglePendingAuditSafe
31230
31368
  });
31231
- const googleAuditScript = resolve43(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31369
+ const googleAuditScript = resolve45(googleRoot, "plugins/google/mcp/dist/scripts/account-audit.js");
31232
31370
  const GOOGLE_ACCOUNT_AUDIT_INTERVAL_MS = 36e5;
31233
31371
  const runGoogleAccountAudit = (ctx) => {
31234
- if (!existsSync48(googleAuditScript)) return;
31372
+ if (!existsSync49(googleAuditScript)) return;
31235
31373
  try {
31236
31374
  const child = spawn3(process.execPath, [googleAuditScript], {
31237
31375
  env: { ...process.env, PLATFORM_ROOT: googleRoot },
@@ -31324,7 +31462,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31324
31462
  }
31325
31463
  {
31326
31464
  const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31327
- const publishScript = resolve43(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31465
+ const publishScript = resolve45(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
31328
31466
  const PUBLISH_INTERVAL_MS = 3e5;
31329
31467
  const bookingAccounts = () => {
31330
31468
  try {
@@ -31335,7 +31473,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31335
31473
  }
31336
31474
  };
31337
31475
  const spawnPublish = (account, ctx) => {
31338
- if (!existsSync48(publishScript)) return;
31476
+ if (!existsSync49(publishScript)) return;
31339
31477
  try {
31340
31478
  const child = spawn3(process.execPath, [publishScript], {
31341
31479
  env: {
@@ -31354,21 +31492,21 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
31354
31492
  }
31355
31493
  };
31356
31494
  const auditSnapshotAge = (account) => {
31357
- const availPath = resolve43(account.accountDir, "calendar-availability.json");
31495
+ const availPath = resolve45(account.accountDir, "calendar-availability.json");
31358
31496
  let hasBookingSite = false;
31359
31497
  try {
31360
- if (existsSync48(availPath)) {
31361
- const cfg = JSON.parse(readFileSync45(availPath, "utf-8"));
31498
+ if (existsSync49(availPath)) {
31499
+ const cfg = JSON.parse(readFileSync46(availPath, "utf-8"));
31362
31500
  hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
31363
31501
  }
31364
31502
  } catch {
31365
31503
  }
31366
31504
  if (!hasBookingSite) return;
31367
- const statePath = resolve43(account.accountDir, "state", "booking-availability", "last-publish.json");
31505
+ const statePath = resolve45(account.accountDir, "state", "booking-availability", "last-publish.json");
31368
31506
  let lastSuccessAt = null;
31369
- if (existsSync48(statePath)) {
31507
+ if (existsSync49(statePath)) {
31370
31508
  try {
31371
- const rec = JSON.parse(readFileSync45(statePath, "utf-8"));
31509
+ const rec = JSON.parse(readFileSync46(statePath, "utf-8"));
31372
31510
  lastSuccessAt = rec.lastSuccessAt ?? null;
31373
31511
  } catch {
31374
31512
  console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
@@ -31401,11 +31539,11 @@ startTimeEntryCensus(() => getSession());
31401
31539
  startLedgerCensus(() => getSession());
31402
31540
  {
31403
31541
  const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..");
31404
- const auditScript = resolve43(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31542
+ const auditScript = resolve45(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
31405
31543
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
31406
31544
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
31407
31545
  const runConnectorAudit = (ctx) => {
31408
- if (!existsSync48(auditScript)) return;
31546
+ if (!existsSync49(auditScript)) return;
31409
31547
  try {
31410
31548
  const child = spawn3(process.execPath, [auditScript], {
31411
31549
  env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
@@ -31525,11 +31663,11 @@ try {
31525
31663
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31526
31664
  async function runAdminUserReconcileTick() {
31527
31665
  try {
31528
- if (!existsSync48(USERS_FILE)) {
31666
+ if (!existsSync49(USERS_FILE)) {
31529
31667
  console.error("[adminuser-self-heal] skip reason=no-users-file");
31530
31668
  return;
31531
31669
  }
31532
- const usersRaw = readFileSync45(USERS_FILE, "utf-8").trim();
31670
+ const usersRaw = readFileSync46(USERS_FILE, "utf-8").trim();
31533
31671
  if (!usersRaw) {
31534
31672
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
31535
31673
  return;
@@ -31581,8 +31719,8 @@ registerLoop({
31581
31719
  });
31582
31720
  var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
31583
31721
  function countUsersRows() {
31584
- if (!existsSync48(USERS_FILE)) return 0;
31585
- const raw = readFileSync45(USERS_FILE, "utf-8").trim();
31722
+ if (!existsSync49(USERS_FILE)) return 0;
31723
+ const raw = readFileSync46(USERS_FILE, "utf-8").trim();
31586
31724
  if (!raw) return 0;
31587
31725
  const users = JSON.parse(raw);
31588
31726
  return users.filter((u) => typeof u.userId === "string").length;
@@ -31716,7 +31854,7 @@ if (bootAccountConfig?.whatsapp) {
31716
31854
  }
31717
31855
  init({
31718
31856
  configDir: configDirForWhatsApp,
31719
- platformRoot: resolve43(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..")),
31857
+ platformRoot: resolve45(process.env.MAXY_PLATFORM_ROOT ?? join52(__dirname, "..")),
31720
31858
  accountConfig: bootAccountConfig,
31721
31859
  // Task 2074 — enrich with the sub-account name and fan out to every open
31722
31860
  // admin SSE stream. Fire-and-forget: the manager's persist path must not