@rubytech/create-maxy-code 0.1.469 → 0.1.471

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 (431) hide show
  1. package/dist/index.js +40 -0
  2. package/package.json +1 -1
  3. package/payload/platform/config/brand.json +2 -1
  4. package/payload/platform/docs/superpowers/plans/2026-07-18-graph-native-ledger.md +807 -0
  5. package/payload/platform/docs/superpowers/specs/2026-07-18-graph-native-ledger-design.md +241 -0
  6. package/payload/platform/lib/ledger-core/dist/ageing.d.ts +14 -0
  7. package/payload/platform/lib/ledger-core/dist/ageing.d.ts.map +1 -0
  8. package/payload/platform/lib/ledger-core/dist/ageing.js +38 -0
  9. package/payload/platform/lib/ledger-core/dist/ageing.js.map +1 -0
  10. package/payload/platform/lib/ledger-core/dist/balance.d.ts +25 -0
  11. package/payload/platform/lib/ledger-core/dist/balance.d.ts.map +1 -0
  12. package/payload/platform/lib/ledger-core/dist/balance.js +38 -0
  13. package/payload/platform/lib/ledger-core/dist/balance.js.map +1 -0
  14. package/payload/platform/lib/ledger-core/dist/index.d.ts +5 -0
  15. package/payload/platform/lib/ledger-core/dist/index.d.ts.map +1 -0
  16. package/payload/platform/lib/ledger-core/dist/index.js +5 -0
  17. package/payload/platform/lib/ledger-core/dist/index.js.map +1 -0
  18. package/payload/platform/lib/ledger-core/dist/money.d.ts +12 -0
  19. package/payload/platform/lib/ledger-core/dist/money.d.ts.map +1 -0
  20. package/payload/platform/lib/ledger-core/dist/money.js +16 -0
  21. package/payload/platform/lib/ledger-core/dist/money.js.map +1 -0
  22. package/payload/platform/lib/ledger-core/dist/reconcile.d.ts +51 -0
  23. package/payload/platform/lib/ledger-core/dist/reconcile.d.ts.map +1 -0
  24. package/payload/platform/lib/ledger-core/dist/reconcile.js +77 -0
  25. package/payload/platform/lib/ledger-core/dist/reconcile.js.map +1 -0
  26. package/payload/platform/lib/ledger-core/package.json +16 -0
  27. package/payload/platform/lib/ledger-core/src/__tests__/ageing.test.ts +42 -0
  28. package/payload/platform/lib/ledger-core/src/__tests__/balance.test.ts +48 -0
  29. package/payload/platform/lib/ledger-core/src/__tests__/reconcile.test.ts +87 -0
  30. package/payload/platform/lib/ledger-core/src/ageing.ts +51 -0
  31. package/payload/platform/lib/ledger-core/src/balance.ts +52 -0
  32. package/payload/platform/lib/ledger-core/src/index.ts +4 -0
  33. package/payload/platform/lib/ledger-core/src/money.ts +17 -0
  34. package/payload/platform/lib/ledger-core/src/reconcile.ts +109 -0
  35. package/payload/platform/lib/ledger-core/tsconfig.json +6 -0
  36. package/payload/platform/neo4j/schema.cypher +16 -0
  37. package/payload/platform/package.json +2 -2
  38. package/payload/platform/plugins/.claude-plugin/marketplace.json +10 -0
  39. package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +2 -0
  40. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +171 -2
  41. package/payload/platform/plugins/cloudflare/bin/__tests__/portal-brand-css.test.sh +139 -0
  42. package/payload/platform/plugins/cloudflare/bin/portal-brand-css.mjs +128 -0
  43. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +1 -1
  44. package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +25 -0
  45. package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -3
  46. package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +38 -3
  47. package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.css → portal.css} +13 -2
  48. package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +1 -1
  49. package/payload/platform/plugins/docs/references/admin-ui.md +48 -0
  50. package/payload/platform/plugins/docs/references/google-guide.md +68 -0
  51. package/payload/platform/plugins/docs/references/internals.md +1 -1
  52. package/payload/platform/plugins/docs/references/ledger.md +43 -0
  53. package/payload/platform/plugins/email/PLUGIN.md +4 -0
  54. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts +2 -0
  55. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts.map +1 -0
  56. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js +196 -0
  57. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js.map +1 -0
  58. package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js +10 -8
  59. package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js.map +1 -1
  60. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts +2 -0
  61. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts.map +1 -0
  62. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js +110 -0
  63. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js.map +1 -0
  64. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +22 -0
  65. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  66. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +90 -36
  67. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  68. package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
  69. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +6 -2
  70. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
  71. package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
  72. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +6 -2
  73. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
  74. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +4 -0
  75. package/payload/platform/plugins/google/.claude-plugin/plugin.json +21 -0
  76. package/payload/platform/plugins/google/PLUGIN.md +104 -0
  77. package/payload/platform/plugins/google/lib/mcp-spawn-tee/index.js +193 -0
  78. package/payload/platform/plugins/google/lib/mcp-spawn-tee/package.json +3 -0
  79. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts +2 -0
  80. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts.map +1 -0
  81. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +60 -0
  82. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -0
  83. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts +2 -0
  84. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts.map +1 -0
  85. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js +48 -0
  86. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js.map +1 -0
  87. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts +2 -0
  88. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts.map +1 -0
  89. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js +25 -0
  90. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js.map +1 -0
  91. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts +2 -0
  92. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts.map +1 -0
  93. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js +40 -0
  94. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js.map +1 -0
  95. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts +2 -0
  96. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts.map +1 -0
  97. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js +35 -0
  98. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js.map +1 -0
  99. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts +2 -0
  100. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
  101. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js +85 -0
  102. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js.map +1 -0
  103. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +25 -0
  104. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -0
  105. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js +87 -0
  106. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -0
  107. package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts +46 -0
  108. package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts.map +1 -0
  109. package/payload/platform/plugins/google/mcp/dist/auth/token-store.js +138 -0
  110. package/payload/platform/plugins/google/mcp/dist/auth/token-store.js.map +1 -0
  111. package/payload/platform/plugins/google/mcp/dist/index.d.ts +25 -0
  112. package/payload/platform/plugins/google/mcp/dist/index.d.ts.map +1 -0
  113. package/payload/platform/plugins/google/mcp/dist/index.js +300 -0
  114. package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -0
  115. package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts +28 -0
  116. package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts.map +1 -0
  117. package/payload/platform/plugins/google/mcp/dist/lib/google-client.js +102 -0
  118. package/payload/platform/plugins/google/mcp/dist/lib/google-client.js.map +1 -0
  119. package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts +3 -0
  120. package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts.map +1 -0
  121. package/payload/platform/plugins/google/mcp/dist/lib/log.js +16 -0
  122. package/payload/platform/plugins/google/mcp/dist/lib/log.js.map +1 -0
  123. package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts +12 -0
  124. package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts.map +1 -0
  125. package/payload/platform/plugins/google/mcp/dist/tools/account-info.js +23 -0
  126. package/payload/platform/plugins/google/mcp/dist/tools/account-info.js.map +1 -0
  127. package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts +12 -0
  128. package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts.map +1 -0
  129. package/payload/platform/plugins/google/mcp/dist/tools/account-list.js +9 -0
  130. package/payload/platform/plugins/google/mcp/dist/tools/account-list.js.map +1 -0
  131. package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +42 -0
  132. package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -0
  133. package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +102 -0
  134. package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -0
  135. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts +10 -0
  136. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts.map +1 -0
  137. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js +9 -0
  138. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js.map +1 -0
  139. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts +20 -0
  140. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts.map +1 -0
  141. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js +25 -0
  142. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js.map +1 -0
  143. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts +6 -0
  144. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts.map +1 -0
  145. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js +7 -0
  146. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js.map +1 -0
  147. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts +14 -0
  148. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts.map +1 -0
  149. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js +16 -0
  150. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js.map +1 -0
  151. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts +44 -0
  152. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts.map +1 -0
  153. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js +36 -0
  154. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js.map +1 -0
  155. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts +16 -0
  156. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts.map +1 -0
  157. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js +29 -0
  158. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js.map +1 -0
  159. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts +16 -0
  160. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts.map +1 -0
  161. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js +32 -0
  162. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js.map +1 -0
  163. package/payload/platform/plugins/google/mcp/package.json +20 -0
  164. package/payload/platform/plugins/google/references/auth.md +35 -0
  165. package/payload/platform/plugins/ledger/.claude-plugin/plugin.json +21 -0
  166. package/payload/platform/plugins/ledger/PLUGIN.md +82 -0
  167. package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/index.js +193 -0
  168. package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/package.json +3 -0
  169. package/payload/platform/plugins/ledger/mcp/dist/index.d.ts +2 -0
  170. package/payload/platform/plugins/ledger/mcp/dist/index.d.ts.map +1 -0
  171. package/payload/platform/plugins/ledger/mcp/dist/index.js +168 -0
  172. package/payload/platform/plugins/ledger/mcp/dist/index.js.map +1 -0
  173. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts +4 -0
  174. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts.map +1 -0
  175. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js +0 -0
  176. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js.map +1 -0
  177. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts +5 -0
  178. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts.map +1 -0
  179. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js +40 -0
  180. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js.map +1 -0
  181. package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts +29 -0
  182. package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts.map +1 -0
  183. package/payload/platform/plugins/ledger/mcp/dist/lib/read.js +138 -0
  184. package/payload/platform/plugins/ledger/mcp/dist/lib/read.js.map +1 -0
  185. package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts +47 -0
  186. package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts.map +1 -0
  187. package/payload/platform/plugins/ledger/mcp/dist/lib/types.js +14 -0
  188. package/payload/platform/plugins/ledger/mcp/dist/lib/types.js.map +1 -0
  189. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts +18 -0
  190. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts.map +1 -0
  191. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js +23 -0
  192. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js.map +1 -0
  193. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts +26 -0
  194. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts.map +1 -0
  195. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js +33 -0
  196. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js.map +1 -0
  197. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts +27 -0
  198. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts.map +1 -0
  199. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js +40 -0
  200. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js.map +1 -0
  201. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts +46 -0
  202. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts.map +1 -0
  203. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js +68 -0
  204. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js.map +1 -0
  205. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts +20 -0
  206. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts.map +1 -0
  207. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js +30 -0
  208. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js.map +1 -0
  209. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts +26 -0
  210. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts.map +1 -0
  211. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js +35 -0
  212. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js.map +1 -0
  213. package/payload/platform/plugins/ledger/mcp/package.json +21 -0
  214. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts +2 -0
  215. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts.map +1 -0
  216. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js +81 -0
  217. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js.map +1 -0
  218. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +9 -7
  219. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
  220. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +10 -8
  221. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
  222. package/payload/platform/plugins/memory/references/schema-base.md +22 -0
  223. package/payload/platform/plugins/memory/references/schema-construction.md +0 -18
  224. package/payload/platform/plugins/scheduling/PLUGIN.md +20 -0
  225. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts.map +1 -1
  226. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js +11 -2
  227. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js.map +1 -1
  228. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +1 -1
  229. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  230. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +3 -3
  231. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
  232. package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +138 -0
  233. package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -0
  234. package/payload/platform/services/claude-session-manager/dist/activity-rows.js +268 -0
  235. package/payload/platform/services/claude-session-manager/dist/activity-rows.js.map +1 -0
  236. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  237. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +20 -0
  238. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  239. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +6 -0
  240. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  241. package/payload/platform/services/claude-session-manager/dist/http-server.js +42 -0
  242. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  243. package/payload/platform/services/claude-session-manager/dist/index.js +10 -1
  244. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  245. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +80 -6
  246. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
  247. package/payload/platform/services/claude-session-manager/dist/pty-census.js +96 -20
  248. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
  249. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
  250. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +5 -1
  251. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
  252. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  253. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  254. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  255. package/payload/server/{chunk-POBXIHOF.js → chunk-BSTIQX52.js} +59 -1
  256. package/payload/server/maxy-edge.js +1 -1
  257. package/payload/server/public/activity.html +17 -0
  258. package/payload/server/public/assets/AdminLoginScreens-Rf94VD9w.js +1 -0
  259. package/payload/server/public/assets/AdminShell-CyGKg7MG.js +2 -0
  260. package/payload/server/public/assets/Checkbox-B0jmI2y2.js +1 -0
  261. package/payload/server/public/assets/HeaderMenu-BnTYGNaB.js +9 -0
  262. package/payload/server/public/assets/{useSubAccountSwitcher-pu0jjLCz.css → HeaderMenu-DtIEBHOU.css} +1 -1
  263. package/payload/server/public/assets/activity-BOBTWFr-.js +1 -0
  264. package/payload/server/public/assets/admin-HDLzwbLl.js +1 -0
  265. package/payload/server/public/assets/{arc-qKfXIt8v.js → arc-CFMJyMm-.js} +1 -1
  266. package/payload/server/public/assets/architecture-YZFGNWBL-Cypt5qHL.js +1 -0
  267. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DkVrGn7G.js → architectureDiagram-Q4EWVU46-CmOpXLsH.js} +1 -1
  268. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DqavswGH.js → blockDiagram-DXYQGD6D-CmS8f9YF.js} +1 -1
  269. package/payload/server/public/assets/browser-D4_XLSSm.js +1 -0
  270. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B7fyKiXe.js → c4Diagram-AHTNJAMY-BXIjMl6A.js} +1 -1
  271. package/payload/server/public/assets/calendar-s5V_gbI7.js +1 -0
  272. package/payload/server/public/assets/channel-DhrFAm7m.js +1 -0
  273. package/payload/server/public/assets/chat-40WyKzGb.js +1 -0
  274. package/payload/server/public/assets/chevron-left-C35qGP5f.js +1 -0
  275. package/payload/server/public/assets/{chunk-2KRD3SAO-DsgMtGkv.js → chunk-2KRD3SAO-D4fktAwW.js} +1 -1
  276. package/payload/server/public/assets/{chunk-336JU56O-CkdISfNt.js → chunk-336JU56O-C2MKnRTj.js} +2 -2
  277. package/payload/server/public/assets/chunk-426QAEUC-BhU7-TyS.js +1 -0
  278. package/payload/server/public/assets/{chunk-4BX2VUAB-CYpiF2bl.js → chunk-4BX2VUAB-C13Wz3zS.js} +1 -1
  279. package/payload/server/public/assets/{chunk-4TB4RGXK-CWyc_F7v.js → chunk-4TB4RGXK-CalYahTR.js} +1 -1
  280. package/payload/server/public/assets/{chunk-55IACEB6-BbzKMw2Z.js → chunk-55IACEB6-TmOKdy8a.js} +1 -1
  281. package/payload/server/public/assets/{chunk-5FUZZQ4R-u19Nai9e.js → chunk-5FUZZQ4R-C-i0BVag.js} +1 -1
  282. package/payload/server/public/assets/{chunk-5PVQY5BW-Ba8by6Uy.js → chunk-5PVQY5BW-D6bJMLnf.js} +1 -1
  283. package/payload/server/public/assets/{chunk-67CJDMHE-BwUuxtyb.js → chunk-67CJDMHE-Cif9Uu5C.js} +1 -1
  284. package/payload/server/public/assets/{chunk-7N4EOEYR-BRH9iM9L.js → chunk-7N4EOEYR-WjTHCXnd.js} +1 -1
  285. package/payload/server/public/assets/{chunk-AA7GKIK3-BGoztgLL.js → chunk-AA7GKIK3-CwCfdQmb.js} +1 -1
  286. package/payload/server/public/assets/{chunk-BSJP7CBP-C5GDAZTl.js → chunk-BSJP7CBP-9A67yXwT.js} +1 -1
  287. package/payload/server/public/assets/{chunk-CIAEETIT-ChY32VPS.js → chunk-CIAEETIT-DPMiWSBi.js} +1 -1
  288. package/payload/server/public/assets/{chunk-EDXVE4YY-CPSD3p6p.js → chunk-EDXVE4YY-B9PBdwiT.js} +1 -1
  289. package/payload/server/public/assets/{chunk-ENJZ2VHE-D1oL-iUr.js → chunk-ENJZ2VHE-CM5OqcQ5.js} +1 -1
  290. package/payload/server/public/assets/{chunk-FMBD7UC4-CPvYEr54.js → chunk-FMBD7UC4-Bmt_ZRlV.js} +1 -1
  291. package/payload/server/public/assets/{chunk-FOC6F5B3-9Yyj7Vbz.js → chunk-FOC6F5B3-DfGJGxpX.js} +1 -1
  292. package/payload/server/public/assets/{chunk-ICPOFSXX-BaYgh8FR.js → chunk-ICPOFSXX-D6M89DA0.js} +2 -2
  293. package/payload/server/public/assets/{chunk-K5T4RW27-5ucpeRvm.js → chunk-K5T4RW27-DMpoaqw2.js} +1 -1
  294. package/payload/server/public/assets/{chunk-KGLVRYIC-DW-FHk7T.js → chunk-KGLVRYIC-DYUFgri2.js} +1 -1
  295. package/payload/server/public/assets/{chunk-LIHQZDEY-CGGVfAyG.js → chunk-LIHQZDEY-x3LmeKmx.js} +1 -1
  296. package/payload/server/public/assets/{chunk-ORNJ4GCN-Bv8EUa5d.js → chunk-ORNJ4GCN-BeuNAWkW.js} +1 -1
  297. package/payload/server/public/assets/{chunk-OYMX7WX6-C1mXJnyw.js → chunk-OYMX7WX6-Bv6gisQ6.js} +1 -1
  298. package/payload/server/public/assets/chunk-QZHKN3VN-7_kS3RBy.js +1 -0
  299. package/payload/server/public/assets/{chunk-U2HBQHQK-PwSQz6EP.js → chunk-U2HBQHQK-C2iT9Av2.js} +1 -1
  300. package/payload/server/public/assets/{chunk-X2U36JSP--NPHTBlU.js → chunk-X2U36JSP-Bd6bv87A.js} +1 -1
  301. package/payload/server/public/assets/{chunk-XPW4576I-Bbc7Da32.js → chunk-XPW4576I-ByFnN4JO.js} +1 -1
  302. package/payload/server/public/assets/{chunk-YZCP3GAM-D-9v8e--.js → chunk-YZCP3GAM-Bt8I6ZDb.js} +1 -1
  303. package/payload/server/public/assets/{chunk-ZZ45TVLE-CMPg670Q.js → chunk-ZZ45TVLE-DBMPgZ_A.js} +1 -1
  304. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BrWqm88p.js +1 -0
  305. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D0wzG5Fd.js +1 -0
  306. package/payload/server/public/assets/clone-DQA-nNrl.js +1 -0
  307. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-NVSb1Bhy.js → cose-bilkent-S5V4N54A-DgLEaApT.js} +1 -1
  308. package/payload/server/public/assets/{dagre-KV5264BT-V2Ai1DFl.js → dagre-KV5264BT-kWVPgmmL.js} +1 -1
  309. package/payload/server/public/assets/{dagre-QfLcO-1j.js → dagre-mSazqXgG.js} +1 -1
  310. package/payload/server/public/assets/data-Bq0vU3qJ.js +1 -0
  311. package/payload/server/public/assets/{diagram-5BDNPKRD-Caw21693.js → diagram-5BDNPKRD-BHe_omJD.js} +1 -1
  312. package/payload/server/public/assets/{diagram-G4DWMVQ6-CgwVkT2q.js → diagram-G4DWMVQ6-fUFsmM3x.js} +1 -1
  313. package/payload/server/public/assets/{diagram-MMDJMWI5-DFUrLZhs.js → diagram-MMDJMWI5-DmujPLlM.js} +1 -1
  314. package/payload/server/public/assets/{diagram-TYMM5635-CEEiEuZJ.js → diagram-TYMM5635-B7Aoas89.js} +1 -1
  315. package/payload/server/public/assets/{dist-Cvgxm7qv.js → dist-C9D_xz81.js} +1 -1
  316. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CG10NrT3.js → erDiagram-SMLLAGMA-6hS1rGiO.js} +1 -1
  317. package/payload/server/public/assets/{flatten-DAO0sfCM.js → flatten-BXzaHgtL.js} +1 -1
  318. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BqkV9Okv.js → flowDiagram-DWJPFMVM-Bqhr_r5b.js} +1 -1
  319. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRiCDQF6.js → ganttDiagram-T4ZO3ILL-B8kjyN4o.js} +1 -1
  320. package/payload/server/public/assets/gitGraph-7Q5UKJZL-C_-XjxLd.js +1 -0
  321. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZV2voyy.js → gitGraphDiagram-UUTBAWPF--TTRq4ir.js} +1 -1
  322. package/payload/server/public/assets/{graph-BZiudUGr.js → graph-C252ZHjp.js} +3 -3
  323. package/payload/server/public/assets/graph-labels-DzPbbhLc.js +1 -0
  324. package/payload/server/public/assets/{graphlib-DGPThX8M.js → graphlib-CWkjawc5.js} +1 -1
  325. package/payload/server/public/assets/info-OMHHGYJF-BH8yDCfL.js +1 -0
  326. package/payload/server/public/assets/infoDiagram-42DDH7IO-D8U4M0pK.js +2 -0
  327. package/payload/server/public/assets/{isEmpty-Cb_U81C6.js → isEmpty-uB1dEu_Z.js} +1 -1
  328. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BKsAxSvp.js → ishikawaDiagram-UXIWVN3A-CR8B7VzM.js} +1 -1
  329. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CmliuOd-.js → journeyDiagram-VCZTEJTY-45lWAvtq.js} +1 -1
  330. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DAlElMb-.js → kanban-definition-6JOO6SKY-DkrPXLVb.js} +1 -1
  331. package/payload/server/public/assets/{line-DKZqLKAC.js → line-Db0H446a.js} +1 -1
  332. package/payload/server/public/assets/{linear-CbSGdh1x.js → linear-X3O7lwK3.js} +1 -1
  333. package/payload/server/public/assets/maximize-2-CEbXFpQT.js +1 -0
  334. package/payload/server/public/assets/{mermaid-parser.core-DFvbao9C.js → mermaid-parser.core-CixBHOya.js} +2 -2
  335. package/payload/server/public/assets/{mermaid.core-C0vEBxDm.js → mermaid.core-BGQq98L7.js} +3 -3
  336. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CShASUKd.js → mindmap-definition-QFDTVHPH-v9cJl1mj.js} +1 -1
  337. package/payload/server/public/assets/operator-zKk4HMdX.js +1 -0
  338. package/payload/server/public/assets/{ordinal-H0tVmBDP.js → ordinal-CZY9laxg.js} +1 -1
  339. package/payload/server/public/assets/packet-4T2RLAQJ-Bajcns4r.js +1 -0
  340. package/payload/server/public/assets/page-BrmN_vzV.js +1 -0
  341. package/payload/server/public/assets/page-Cts-ESBe.js +32 -0
  342. package/payload/server/public/assets/{pdf-render-jAQU0nXt.js → pdf-render-7HZBTZ0_.js} +1 -1
  343. package/payload/server/public/assets/pie-ZZUOXDRM-D7hjM5w1.js +1 -0
  344. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CBZHpDAJ.js → pieDiagram-DEJITSTG-DQ0b6edX.js} +1 -1
  345. package/payload/server/public/assets/public-BItzHBc0.js +1 -0
  346. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-n3bB3K91.js → quadrantDiagram-34T5L4WZ-B64mj7Ei.js} +1 -1
  347. package/payload/server/public/assets/radar-PYXPWWZC-B46d5x7a.js +1 -0
  348. package/payload/server/public/assets/{reduce-DAvwat-a.js → reduce-BGQzAenn.js} +1 -1
  349. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DiDvQK3c.js → requirementDiagram-MS252O5E-CE2JIEWo.js} +1 -1
  350. package/payload/server/public/assets/rotate-ccw-B0EYGhGx.js +1 -0
  351. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DWDQQZmd.js → sankeyDiagram-XADWPNL6-Cmt5cfCz.js} +1 -1
  352. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmAqRlBT.js → sequenceDiagram-FGHM5R23-B5vVn_sw.js} +1 -1
  353. package/payload/server/public/assets/{src-DV4LKv2E.js → src-BTKk8KAG.js} +1 -1
  354. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D4R-n6bZ.js → stateDiagram-FHFEXIEX-DiUEJ-RZ.js} +1 -1
  355. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DIm3XuAD.js +1 -0
  356. package/payload/server/public/assets/tasks-ClE8-be8.js +1 -0
  357. package/payload/server/public/assets/time-entry-format-BwjGLnXu.js +1 -0
  358. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CjiHGP4l.js → timeline-definition-GMOUNBTQ-C9jprDVw.js} +1 -1
  359. package/payload/server/public/assets/treeView-SZITEDCU-3XQh5xQ1.js +1 -0
  360. package/payload/server/public/assets/treemap-W4RFUUIX-DwR-_l5z.js +1 -0
  361. package/payload/server/public/assets/triangle-alert-DejWYn1x.js +1 -0
  362. package/payload/server/public/assets/useCopyFeedback-CpSgOavK.js +1 -0
  363. package/payload/server/public/assets/useSelectionMode-ZQZQUgze.js +1 -0
  364. package/payload/server/public/assets/useSubAccountSwitcher-DuRLvCfO.js +1 -0
  365. package/payload/server/public/assets/useVoiceRecorder-BTYYeUJW.js +2 -0
  366. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CBdDQ7c-.js → vennDiagram-DHZGUBPP-DWqQJ9X0.js} +1 -1
  367. package/payload/server/public/assets/wardley-RL74JXVD-DZp9oCGv.js +1 -0
  368. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BlIQPKLb.js → wardleyDiagram-NUSXRM2D-Dg6c2Voh.js} +1 -1
  369. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CslKgh9B.js → xychartDiagram-5P7HB3ND-EhN-zeDj.js} +1 -1
  370. package/payload/server/public/browser.html +7 -6
  371. package/payload/server/public/calendar.html +8 -7
  372. package/payload/server/public/chat.html +15 -14
  373. package/payload/server/public/data.html +14 -12
  374. package/payload/server/public/graph.html +13 -12
  375. package/payload/server/public/index.html +17 -15
  376. package/payload/server/public/operator.html +17 -16
  377. package/payload/server/public/public.html +15 -14
  378. package/payload/server/public/tasks.html +7 -6
  379. package/payload/server/server.js +1064 -536
  380. package/payload/server/public/assets/AdminLoginScreens-Bed8SDxY.js +0 -1
  381. package/payload/server/public/assets/AdminShell-BLh9O6dn.js +0 -2
  382. package/payload/server/public/assets/Checkbox-BC_KSbpS.js +0 -1
  383. package/payload/server/public/assets/admin-DfWgJVI3.js +0 -1
  384. package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +0 -1
  385. package/payload/server/public/assets/browser-C0vkv-hH.js +0 -1
  386. package/payload/server/public/assets/calendar-_pfHw0Hp.js +0 -1
  387. package/payload/server/public/assets/channel-j70eMvcL.js +0 -1
  388. package/payload/server/public/assets/chat-DYT5H81o.js +0 -1
  389. package/payload/server/public/assets/chevron-left-BnpVBu51.js +0 -1
  390. package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +0 -1
  391. package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +0 -1
  392. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +0 -1
  393. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +0 -1
  394. package/payload/server/public/assets/clone-DjPWA_NH.js +0 -1
  395. package/payload/server/public/assets/data-CR-fbPWr.js +0 -1
  396. package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +0 -1
  397. package/payload/server/public/assets/graph-labels-BzmmJwCR.js +0 -1
  398. package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +0 -1
  399. package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +0 -2
  400. package/payload/server/public/assets/maximize-2-Bhdsv0U-.js +0 -1
  401. package/payload/server/public/assets/operator-gm2eP4r6.js +0 -1
  402. package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +0 -1
  403. package/payload/server/public/assets/page-8AB3jUa_.js +0 -1
  404. package/payload/server/public/assets/page-BoPorLg-.js +0 -32
  405. package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +0 -1
  406. package/payload/server/public/assets/public-DqJk6qgW.js +0 -1
  407. package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +0 -1
  408. package/payload/server/public/assets/rotate-ccw-D_5cETGt.js +0 -1
  409. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +0 -1
  410. package/payload/server/public/assets/tasks-EyKLXINi.js +0 -1
  411. package/payload/server/public/assets/time-entry-format-DAwmmR3i.js +0 -1
  412. package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +0 -1
  413. package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +0 -1
  414. package/payload/server/public/assets/useCopyFeedback-rOWd_lzl.js +0 -1
  415. package/payload/server/public/assets/useSelectionMode-DDmLmPph.js +0 -1
  416. package/payload/server/public/assets/useSubAccountSwitcher-CU-lOxTd.js +0 -9
  417. package/payload/server/public/assets/useVoiceRecorder-azG8zSUI.js +0 -2
  418. package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +0 -1
  419. /package/payload/platform/plugins/cloudflare/skills/data-portal/{template/schema.sql → schema.sql} +0 -0
  420. /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/index.html → index.html} +0 -0
  421. /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.js → portal.js} +0 -0
  422. /package/payload/server/public/assets/{_baseFor-D3BqAOBr.js → _baseFor-CMWvz0uA.js} +0 -0
  423. /package/payload/server/public/assets/{array-iYP9fzJp.js → array-Cny_NT6T.js} +0 -0
  424. /package/payload/server/public/assets/{chunk-Ck5AOu5v.js → chunk-TPjIAO9U.js} +0 -0
  425. /package/payload/server/public/assets/{cytoscape.esm-BQSBzPsB.js → cytoscape.esm-De0CCmB2.js} +0 -0
  426. /package/payload/server/public/assets/{defaultLocale-BrdA1gDi.js → defaultLocale-BahRht8U.js} +0 -0
  427. /package/payload/server/public/assets/{init-Bx0S6pkp.js → init-DoIvjoJ_.js} +0 -0
  428. /package/payload/server/public/assets/{katex-BsiH_a6d.js → katex-Bfn1OZEl.js} +0 -0
  429. /package/payload/server/public/assets/{path-BLSgTy3w.js → path-CTezU8L5.js} +0 -0
  430. /package/payload/server/public/assets/{preload-helper-ClBMtM1g.js → preload-helper-CT1Z6Pdu.js} +0 -0
  431. /package/payload/server/public/assets/{rough.esm-BMOtDaaS.js → rough.esm-BJo4pvXu.js} +0 -0
@@ -42,6 +42,7 @@ import {
42
42
  embed,
43
43
  emitMissingOnResolve,
44
44
  ensureConversation,
45
+ ensureSessionConversation,
45
46
  fetchAccountName,
46
47
  fetchBranding,
47
48
  findMissingPlugins,
@@ -111,7 +112,7 @@ import {
111
112
  vncLog,
112
113
  walkPremiumBundles,
113
114
  writeAdminUserAndPerson
114
- } from "./chunk-POBXIHOF.js";
115
+ } from "./chunk-BSTIQX52.js";
115
116
  import {
116
117
  D1_MAX_SQL_STATEMENT_BYTES,
117
118
  D1_QUERY_MAX_BODY_BYTES,
@@ -1533,10 +1534,10 @@ var serveStatic = (options = { root: "" }) => {
1533
1534
  };
1534
1535
 
1535
1536
  // server/index.ts
1536
- import { readFileSync as readFileSync38, existsSync as existsSync36, watchFile, readdirSync as readdirSync21, statSync as statSync14 } from "fs";
1537
+ import { readFileSync as readFileSync39, existsSync as existsSync37, watchFile, readdirSync as readdirSync23, statSync as statSync14 } from "fs";
1537
1538
  import { spawn as spawn3 } from "child_process";
1538
1539
  import { createHash as createHash7 } from "crypto";
1539
- import { resolve as resolve36, join as join38, basename as basename12 } from "path";
1540
+ import { resolve as resolve36, join as join39, basename as basename12 } from "path";
1540
1541
  import { homedir as homedir4 } from "os";
1541
1542
  import { monitorEventLoopDelay } from "perf_hooks";
1542
1543
 
@@ -6675,8 +6676,8 @@ function webchatTurnTimeoutMs() {
6675
6676
  return Number(process.env.WEBCHAT_TURN_TIMEOUT_MS ?? String(2 * 6e4));
6676
6677
  }
6677
6678
  function createChatRoutes(deps) {
6678
- const app63 = new Hono();
6679
- app63.post("/", async (c) => {
6679
+ const app64 = new Hono();
6680
+ app64.post("/", async (c) => {
6680
6681
  console.log(`[chat-route] entered route=public method=POST`);
6681
6682
  const contentType = c.req.header("content-type") ?? "";
6682
6683
  const account = resolveAccount();
@@ -6940,7 +6941,7 @@ ${result.result.text}` : result.result.text;
6940
6941
  }
6941
6942
  });
6942
6943
  });
6943
- return app63;
6944
+ return app64;
6944
6945
  }
6945
6946
 
6946
6947
  // app/lib/channel-pty-bridge/admin-session-id.ts
@@ -6974,8 +6975,8 @@ function isLoopbackAddr(addr) {
6974
6975
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
6975
6976
  }
6976
6977
  function createScheduleInjectRoutes(deps) {
6977
- const app63 = new Hono();
6978
- app63.post("/", async (c) => {
6978
+ const app64 = new Hono();
6979
+ app64.post("/", async (c) => {
6979
6980
  const env = c.env;
6980
6981
  const remoteAddr = env?.incoming?.socket?.remoteAddress ?? "";
6981
6982
  if (!isLoopbackAddr(remoteAddr)) {
@@ -7076,11 +7077,11 @@ function createScheduleInjectRoutes(deps) {
7076
7077
  console.error(`${TAG17} op=inject-spawn eventId=${eventId} sessionId=${sessionId} result=ok status=-`);
7077
7078
  return c.json({ ok: true }, 200);
7078
7079
  });
7079
- return app63;
7080
+ return app64;
7080
7081
  }
7081
7082
 
7082
7083
  // server/index.ts
7083
- var import_dist9 = __toESM(require_dist(), 1);
7084
+ var import_dist10 = __toESM(require_dist(), 1);
7084
7085
 
7085
7086
  // app/lib/whatsapp/socket-resolution-error.ts
7086
7087
  function formatPresentKeys(presentKeys) {
@@ -12012,8 +12013,8 @@ async function reapplyLeversViaManager() {
12012
12013
  var WEBCHAT_SEND_TURN_WINDOW_MS = Number(process.env.WEBCHAT_SEND_TURN_WINDOW_MS ?? String(15e3));
12013
12014
  var sendSeq = 0;
12014
12015
  function createWebchatRoutes(deps) {
12015
- const app63 = new Hono();
12016
- app63.post("/send", requireAdminSession, async (c) => {
12016
+ const app64 = new Hono();
12017
+ app64.post("/send", requireAdminSession, async (c) => {
12017
12018
  let accountId;
12018
12019
  try {
12019
12020
  accountId = resolvePlatformAccountId();
@@ -12225,7 +12226,7 @@ ${note}` : note;
12225
12226
  if (turnTimer.unref) turnTimer.unref();
12226
12227
  return c.json({ ok: true });
12227
12228
  });
12228
- app63.post("/interrupt", requireAdminSession, async (c) => {
12229
+ app64.post("/interrupt", requireAdminSession, async (c) => {
12229
12230
  const cacheKey = c.get("cacheKey");
12230
12231
  const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
12231
12232
  const primaryUserId = resolvePrimaryAdminUserId();
@@ -12253,7 +12254,7 @@ ${note}` : note;
12253
12254
  }
12254
12255
  return c.json({ ok: true, stopped: outcome.stopped, intId: outcome.intId, deadChild: outcome.deadChild }, 200);
12255
12256
  });
12256
- app63.post("/settings", requireAdminSession, async (c) => {
12257
+ app64.post("/settings", requireAdminSession, async (c) => {
12257
12258
  const body = await c.req.json().catch(() => null);
12258
12259
  const op = body?.op;
12259
12260
  const value = body?.value;
@@ -12293,7 +12294,7 @@ ${note}` : note;
12293
12294
  console.log(`[webchat:settings] op=${op} outcome=accepted value=${value} settingsApplied=${settingsApplied}`);
12294
12295
  return c.json({ ok: true, settingsApplied });
12295
12296
  });
12296
- app63.get("/session", requireAdminSession, async (c) => {
12297
+ app64.get("/session", requireAdminSession, async (c) => {
12297
12298
  let accountId;
12298
12299
  try {
12299
12300
  accountId = resolvePlatformAccountId();
@@ -12371,7 +12372,7 @@ ${note}` : note;
12371
12372
  const indicators = await fetchComposerIndicators(sessionId);
12372
12373
  return c.json({ sessionId, projectDir, source, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, deliveryFailure: deps.deliveryFailureFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
12373
12374
  });
12374
- app63.post("/permission-verdict", requireAdminSession, async (c) => {
12375
+ app64.post("/permission-verdict", requireAdminSession, async (c) => {
12375
12376
  const body = await c.req.json().catch(() => null);
12376
12377
  const sessionId = body?.sessionId;
12377
12378
  const requestId = body?.request_id;
@@ -12388,7 +12389,7 @@ ${note}` : note;
12388
12389
  const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
12389
12390
  return c.json({ ok });
12390
12391
  });
12391
- return app63;
12392
+ return app64;
12392
12393
  }
12393
12394
 
12394
12395
  // server/routes/webchat-greeting.ts
@@ -12788,9 +12789,249 @@ app9.get("/callback", async (c) => {
12788
12789
  });
12789
12790
  var quickbooks_default = app9;
12790
12791
 
12792
+ // server/routes/google-oauth.ts
12793
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
12794
+ import { chmodSync, existsSync as existsSync17, mkdirSync as mkdirSync5, readdirSync as readdirSync16, readFileSync as readFileSync25, renameSync as renameSync6, rmSync as rmSync2, writeFileSync as writeFileSync9 } from "fs";
12795
+ import { join as join24 } from "path";
12796
+ var TAG26 = "[google-oauth]";
12797
+ var TOKEN_URL = "https://oauth2.googleapis.com/token";
12798
+ var PRIMARY_CALENDAR_URL = "https://www.googleapis.com/calendar/v3/calendars/primary";
12799
+ var PENDING_LIFETIME_MS = 6e5;
12800
+ function sanitizeAccountKey(key) {
12801
+ const safe = key.replace(/[^A-Za-z0-9._-]/g, "_");
12802
+ return safe === "." || safe === ".." ? `_${safe}` : safe;
12803
+ }
12804
+ function secretsDir(accountsDir, accountId) {
12805
+ return join24(accountsDir, sanitizeAccountKey(accountId), "secrets", "google");
12806
+ }
12807
+ function esc(s) {
12808
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
12809
+ }
12810
+ function refreshTokenBelongsToAccount(accountsDir, accountId, refreshToken) {
12811
+ const dir = join24(secretsDir(accountsDir, accountId), "accounts");
12812
+ if (!existsSync17(dir)) return false;
12813
+ let key;
12814
+ try {
12815
+ key = loadKey(accountsDir, accountId);
12816
+ } catch {
12817
+ return false;
12818
+ }
12819
+ for (const entry of readdirSync16(dir)) {
12820
+ const path3 = join24(dir, entry, "tokens.enc");
12821
+ if (!existsSync17(path3)) continue;
12822
+ try {
12823
+ const blob = JSON.parse(decrypt(key, readFileSync25(path3, "utf-8").trim()));
12824
+ if (blob.refreshToken && blob.refreshToken === refreshToken) return true;
12825
+ } catch {
12826
+ }
12827
+ }
12828
+ return false;
12829
+ }
12830
+ function loadKey(accountsDir, accountId) {
12831
+ const dir = secretsDir(accountsDir, accountId);
12832
+ const keyPath = join24(dir, ".key");
12833
+ mkdirSync5(dir, { recursive: true, mode: 448 });
12834
+ if (existsSync17(keyPath)) return Buffer.from(readFileSync25(keyPath, "utf-8").trim(), "base64");
12835
+ const k = randomBytes(32);
12836
+ writeFileSync9(keyPath, k.toString("base64"), { mode: 384 });
12837
+ chmodSync(keyPath, 384);
12838
+ return k;
12839
+ }
12840
+ function decrypt(key, raw) {
12841
+ const [ivHex, payload] = raw.split(":");
12842
+ const d = createDecipheriv("aes-256-cbc", key, Buffer.from(ivHex, "hex"));
12843
+ return d.update(payload, "hex", "utf8") + d.final("utf8");
12844
+ }
12845
+ function encrypt(key, plain) {
12846
+ const iv = randomBytes(16);
12847
+ const c = createCipheriv("aes-256-cbc", key, iv);
12848
+ return `${iv.toString("hex")}:${c.update(plain, "utf8", "hex") + c.final("hex")}`;
12849
+ }
12850
+ function atomicWrite(path3, contents) {
12851
+ const temp = `${path3}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
12852
+ try {
12853
+ writeFileSync9(temp, contents, { mode: 384 });
12854
+ chmodSync(temp, 384);
12855
+ renameSync6(temp, path3);
12856
+ } catch (err) {
12857
+ try {
12858
+ rmSync2(temp, { force: true });
12859
+ } catch {
12860
+ }
12861
+ throw err;
12862
+ }
12863
+ }
12864
+ function readPending(accountsDir, accountId) {
12865
+ const path3 = join24(secretsDir(accountsDir, accountId), "pending-oauth.enc");
12866
+ if (!existsSync17(path3)) return null;
12867
+ const raw = readFileSync25(path3, "utf-8").trim();
12868
+ if (!raw) return null;
12869
+ try {
12870
+ return JSON.parse(decrypt(loadKey(accountsDir, accountId), raw));
12871
+ } catch {
12872
+ return null;
12873
+ }
12874
+ }
12875
+ function clearPending(accountsDir, accountId) {
12876
+ const path3 = join24(secretsDir(accountsDir, accountId), "pending-oauth.enc");
12877
+ if (existsSync17(path3)) rmSync2(path3, { force: true });
12878
+ }
12879
+ function writeTokens(accountsDir, accountId, email, tok) {
12880
+ const key = loadKey(accountsDir, accountId);
12881
+ const dir = join24(secretsDir(accountsDir, accountId), "accounts", sanitizeAccountKey(email));
12882
+ mkdirSync5(dir, { recursive: true, mode: 448 });
12883
+ const now = Date.now();
12884
+ const blob = {
12885
+ accessToken: tok.accessToken,
12886
+ refreshToken: tok.refreshToken,
12887
+ accessTokenExpiry: now + tok.expiresInSeconds * 1e3,
12888
+ lastRefresh: now,
12889
+ email,
12890
+ scopes: tok.scopes
12891
+ };
12892
+ atomicWrite(join24(dir, "tokens.enc"), encrypt(key, JSON.stringify(blob)));
12893
+ }
12894
+ function readHouseGoogleCreds(platformRoot5) {
12895
+ const path3 = join24(platformRoot5, "config", "google-house.env");
12896
+ if (!existsSync17(path3)) return null;
12897
+ const env = {};
12898
+ for (const line of readFileSync25(path3, "utf-8").split(/\r?\n/)) {
12899
+ const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
12900
+ if (m) env[m[1]] = m[2].trim();
12901
+ }
12902
+ if (!env.GOOGLE_CLIENT_ID || !env.GOOGLE_CLIENT_SECRET) return null;
12903
+ return { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET };
12904
+ }
12905
+ function page2(title, body) {
12906
+ return `<!doctype html><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title}</title><div style="font:16px/1.5 system-ui;margin:3rem auto;max-width:30rem;padding:0 1rem"><h1 style="font-size:1.3rem">${title}</h1><p>${body}</p></div>`;
12907
+ }
12908
+ function createGoogleOAuthRoutes(platformRoot5, accountsDir) {
12909
+ const routes = new Hono();
12910
+ routes.get("/oauth/callback", async (c) => {
12911
+ const code = c.req.query("code");
12912
+ const state = c.req.query("state");
12913
+ const accountId = c.req.query("account");
12914
+ if (!code || !state || !accountId) {
12915
+ console.error(`${TAG26} op=callback outcome=error error=missing-params`);
12916
+ return c.html(page2("Missing parameters", "Return to your chat and start again."), 400);
12917
+ }
12918
+ const held = readPending(accountsDir, accountId);
12919
+ const stateMatch = held !== null && held.state === state;
12920
+ console.error(`${TAG26} op=callback reg=${state} account=${accountId} state-match=${stateMatch}`);
12921
+ if (!held || !stateMatch) {
12922
+ return c.html(page2("This link has expired", "Return to your chat and start again."), 400);
12923
+ }
12924
+ const ageMs = Date.now() - held.createdAt;
12925
+ if (ageMs > PENDING_LIFETIME_MS) {
12926
+ console.error(`${TAG26} op=callback reg=${state} outcome=error error=pending-expired ageMs=${ageMs}`);
12927
+ clearPending(accountsDir, accountId);
12928
+ return c.html(page2("This link has expired", "Return to your chat and start again."), 400);
12929
+ }
12930
+ const failed = (title, body, status) => {
12931
+ clearPending(accountsDir, accountId);
12932
+ return c.html(page2(title, body), status);
12933
+ };
12934
+ const creds = readHouseGoogleCreds(platformRoot5);
12935
+ if (!creds) {
12936
+ console.error(`${TAG26} op=token-exchange reg=${state} outcome=error error=house-env-missing`);
12937
+ return failed("Not configured", "This install has no Google credentials yet.", 500);
12938
+ }
12939
+ const publicBase = (process.env.GOOGLE_PUBLIC_BASE ?? "").replace(/\/+$/, "");
12940
+ if (!publicBase) {
12941
+ console.error(`${TAG26} op=callback reg=${state} outcome=error error=public-base-unset`);
12942
+ return failed("Not configured", "This install has no public base configured.", 500);
12943
+ }
12944
+ const redirectUri = `${publicBase}/api/google/oauth/callback?account=${encodeURIComponent(accountId)}`;
12945
+ try {
12946
+ const res = await fetch(TOKEN_URL, {
12947
+ method: "POST",
12948
+ headers: { "content-type": "application/x-www-form-urlencoded" },
12949
+ body: new URLSearchParams({
12950
+ code,
12951
+ client_id: creds.clientId,
12952
+ client_secret: creds.clientSecret,
12953
+ redirect_uri: redirectUri,
12954
+ grant_type: "authorization_code",
12955
+ code_verifier: held.verifier
12956
+ })
12957
+ });
12958
+ const text = await res.text();
12959
+ if (!res.ok) {
12960
+ console.error(`${TAG26} op=token-exchange reg=${state} outcome=error status=${res.status} body=${text.slice(0, 300)}`);
12961
+ return failed("Could not connect", `Google refused the exchange (${res.status}).`, 502);
12962
+ }
12963
+ console.error(`${TAG26} op=token-exchange reg=${state} outcome=ok`);
12964
+ const tok = JSON.parse(text);
12965
+ const calRes = await fetch(PRIMARY_CALENDAR_URL, {
12966
+ headers: { authorization: `Bearer ${tok.access_token}` }
12967
+ });
12968
+ const calText = await calRes.text();
12969
+ if (!calRes.ok) {
12970
+ console.error(`${TAG26} op=identity reg=${state} outcome=error status=${calRes.status} body=${calText.slice(0, 300)}`);
12971
+ return failed("Could not connect", "Connected, but the calendar identity could not be read.", 502);
12972
+ }
12973
+ const email = JSON.parse(calText).id;
12974
+ console.error(`${TAG26} op=identity reg=${state} email=${email}`);
12975
+ writeTokens(accountsDir, accountId, email, {
12976
+ accessToken: tok.access_token,
12977
+ refreshToken: tok.refresh_token ?? null,
12978
+ expiresInSeconds: tok.expires_in,
12979
+ scopes: tok.scope ? tok.scope.split(" ") : []
12980
+ });
12981
+ console.error(
12982
+ `${TAG26} op=tokens-write reg=${state} account=${accountId} refreshIssued=${tok.refresh_token ? "true" : "false"}`
12983
+ );
12984
+ clearPending(accountsDir, accountId);
12985
+ console.error(`${TAG26} op=pending-clear reg=${state} verified=${readPending(accountsDir, accountId) === null}`);
12986
+ console.error(`${TAG26} op=registered reg=${state} account=${accountId} email=${email}`);
12987
+ return c.html(
12988
+ page2(
12989
+ "Calendar connected",
12990
+ `${esc(email)} is connected to this account. You can close this page and return to your chat.`
12991
+ )
12992
+ );
12993
+ } catch (err) {
12994
+ const msg = err.message;
12995
+ console.error(`${TAG26} op=token-exchange reg=${state} outcome=error error=${msg}`);
12996
+ return failed("Could not connect", "Something went wrong. Return to your chat and try again.", 502);
12997
+ }
12998
+ });
12999
+ routes.post("/oauth/refresh", async (c) => {
13000
+ const body = await c.req.json().catch(() => ({}));
13001
+ const { accountId, refreshToken } = body;
13002
+ if (!accountId || !refreshToken) {
13003
+ return c.json({ error: "accountId and refreshToken are required" }, 400);
13004
+ }
13005
+ if (!refreshTokenBelongsToAccount(accountsDir, accountId, refreshToken)) {
13006
+ console.error(`${TAG26} op=refresh account=${accountId} outcome=denied reason=token-not-held`);
13007
+ return c.json({ error: "refresh token is not held by this account" }, 403);
13008
+ }
13009
+ const creds = readHouseGoogleCreds(platformRoot5);
13010
+ if (!creds) return c.json({ error: "google-house.env is absent or incomplete" }, 500);
13011
+ const res = await fetch(TOKEN_URL, {
13012
+ method: "POST",
13013
+ headers: { "content-type": "application/x-www-form-urlencoded" },
13014
+ body: new URLSearchParams({
13015
+ client_id: creds.clientId,
13016
+ client_secret: creds.clientSecret,
13017
+ refresh_token: refreshToken,
13018
+ grant_type: "refresh_token"
13019
+ })
13020
+ });
13021
+ const text = await res.text();
13022
+ if (!res.ok) {
13023
+ console.error(`${TAG26} op=refresh account=${accountId} outcome=error status=${res.status} body=${text.slice(0, 300)}`);
13024
+ return c.json({ error: text.slice(0, 300) }, 502);
13025
+ }
13026
+ console.error(`${TAG26} op=refresh account=${accountId} outcome=ok`);
13027
+ return c.json(JSON.parse(text));
13028
+ });
13029
+ return routes;
13030
+ }
13031
+
12791
13032
  // server/routes/onboarding.ts
12792
13033
  import { spawn, spawnSync as spawnSync2, execFileSync as execFileSync3 } from "child_process";
12793
- import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync10, writeSync, existsSync as existsSync18, readFileSync as readFileSync26, unlinkSync as unlinkSync3, renameSync as renameSync7 } from "fs";
13034
+ import { openSync as openSync3, closeSync as closeSync3, writeFileSync as writeFileSync11, writeSync, existsSync as existsSync19, readFileSync as readFileSync27, unlinkSync as unlinkSync3, renameSync as renameSync8 } from "fs";
12794
13035
  import { createHash as createHash4, randomUUID as randomUUID8 } from "crypto";
12795
13036
 
12796
13037
  // app/lib/claude-spawn-env.ts
@@ -12799,7 +13040,7 @@ function claudeBin() {
12799
13040
  }
12800
13041
 
12801
13042
  // server/routes/onboarding.ts
12802
- import { dirname as dirname9, join as join25 } from "path";
13043
+ import { dirname as dirname9, join as join26 } from "path";
12803
13044
 
12804
13045
  // app/lib/claude-keychain.ts
12805
13046
  import { execFileSync as execFileSync2 } from "child_process";
@@ -12928,8 +13169,8 @@ function readHostCredsBlob(service) {
12928
13169
  }
12929
13170
 
12930
13171
  // ../lib/admins-write/src/index.ts
12931
- import { existsSync as existsSync17, readFileSync as readFileSync25, writeFileSync as writeFileSync9, renameSync as renameSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync16, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
12932
- import { dirname as dirname8, join as join24 } from "path";
13172
+ import { existsSync as existsSync18, readFileSync as readFileSync26, writeFileSync as writeFileSync10, renameSync as renameSync7, mkdirSync as mkdirSync6, readdirSync as readdirSync17, statSync as statSync8, appendFileSync as appendFileSync2 } from "fs";
13173
+ import { dirname as dirname8, join as join25 } from "path";
12933
13174
  function id8(value) {
12934
13175
  return value.slice(0, 8);
12935
13176
  }
@@ -12943,7 +13184,7 @@ function appendUsersAuditLine(audit, fields) {
12943
13184
  const line = `[users-audit] action=${fields.action} actor=${actor}${targetFields}${sess} field=${fields.field} rowsBefore=${fields.rowsBefore} rowsAfter=${fields.rowsAfter} ts=${(/* @__PURE__ */ new Date()).toISOString()}
12944
13185
  `;
12945
13186
  try {
12946
- mkdirSync5(dirname8(audit.logFile), { recursive: true, mode: 448 });
13187
+ mkdirSync6(dirname8(audit.logFile), { recursive: true, mode: 448 });
12947
13188
  appendFileSync2(audit.logFile, line, { mode: 384 });
12948
13189
  } catch (err) {
12949
13190
  console.error(
@@ -12961,17 +13202,17 @@ function logLine(input, result) {
12961
13202
  );
12962
13203
  }
12963
13204
  function writeFileAtomic(filePath, contents, mode) {
12964
- mkdirSync5(dirname8(filePath), { recursive: true });
13205
+ mkdirSync6(dirname8(filePath), { recursive: true });
12965
13206
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
12966
- writeFileSync9(tempPath, contents, mode !== void 0 ? { mode } : void 0);
12967
- renameSync6(tempPath, filePath);
13207
+ writeFileSync10(tempPath, contents, mode !== void 0 ? { mode } : void 0);
13208
+ renameSync7(tempPath, filePath);
12968
13209
  }
12969
13210
  function writeAdminEntry(input) {
12970
13211
  const result = { usersJsonResult: "noop", accountJsonResult: "noop" };
12971
13212
  try {
12972
13213
  let users = [];
12973
- if (existsSync17(input.usersFile)) {
12974
- const raw = readFileSync25(input.usersFile, "utf-8").trim();
13214
+ if (existsSync18(input.usersFile)) {
13215
+ const raw = readFileSync26(input.usersFile, "utf-8").trim();
12975
13216
  if (raw) {
12976
13217
  const parsed = JSON.parse(raw);
12977
13218
  if (!Array.isArray(parsed)) {
@@ -13002,11 +13243,11 @@ function writeAdminEntry(input) {
13002
13243
  return result;
13003
13244
  }
13004
13245
  try {
13005
- const accountJsonPath = join24(input.accountDir, "account.json");
13006
- if (!existsSync17(accountJsonPath)) {
13246
+ const accountJsonPath = join25(input.accountDir, "account.json");
13247
+ if (!existsSync18(accountJsonPath)) {
13007
13248
  throw new Error(`account.json not found at ${accountJsonPath}`);
13008
13249
  }
13009
- const config = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
13250
+ const config = JSON.parse(readFileSync26(accountJsonPath, "utf-8"));
13010
13251
  const admins = config.admins ?? [];
13011
13252
  if (admins.some((a) => a.userId === input.userId)) {
13012
13253
  result.accountJsonResult = "noop";
@@ -13026,9 +13267,9 @@ function writeAdminEntry(input) {
13026
13267
  function computeAdminStoreDivergence(input) {
13027
13268
  const result = { divergences: 0, accountWithoutUsers: [], usersWithoutAccount: [], errors: [] };
13028
13269
  const usersUserIds = /* @__PURE__ */ new Set();
13029
- if (existsSync17(input.usersFile)) {
13270
+ if (existsSync18(input.usersFile)) {
13030
13271
  try {
13031
- const raw = readFileSync25(input.usersFile, "utf-8").trim();
13272
+ const raw = readFileSync26(input.usersFile, "utf-8").trim();
13032
13273
  if (raw) {
13033
13274
  const users = JSON.parse(raw);
13034
13275
  for (const u of users) {
@@ -13040,27 +13281,27 @@ function computeAdminStoreDivergence(input) {
13040
13281
  }
13041
13282
  }
13042
13283
  const accountUserIds = /* @__PURE__ */ new Set();
13043
- if (existsSync17(input.accountsDir)) {
13284
+ if (existsSync18(input.accountsDir)) {
13044
13285
  let entries;
13045
13286
  try {
13046
- entries = readdirSync16(input.accountsDir);
13287
+ entries = readdirSync17(input.accountsDir);
13047
13288
  } catch (err) {
13048
13289
  result.errors.push({ source: input.accountsDir, detail: err instanceof Error ? err.message : String(err) });
13049
13290
  return result;
13050
13291
  }
13051
13292
  for (const entry of entries) {
13052
13293
  if (entry.startsWith(".")) continue;
13053
- const accountDir = join24(input.accountsDir, entry);
13294
+ const accountDir = join25(input.accountsDir, entry);
13054
13295
  try {
13055
13296
  if (!statSync8(accountDir).isDirectory()) continue;
13056
13297
  } catch {
13057
13298
  continue;
13058
13299
  }
13059
- const accountJsonPath = join24(accountDir, "account.json");
13060
- if (!existsSync17(accountJsonPath)) continue;
13300
+ const accountJsonPath = join25(accountDir, "account.json");
13301
+ if (!existsSync18(accountJsonPath)) continue;
13061
13302
  let admins = [];
13062
13303
  try {
13063
- const config = JSON.parse(readFileSync25(accountJsonPath, "utf-8"));
13304
+ const config = JSON.parse(readFileSync26(accountJsonPath, "utf-8"));
13064
13305
  admins = config.admins ?? [];
13065
13306
  } catch (err) {
13066
13307
  result.errors.push({ source: accountJsonPath, detail: err instanceof Error ? err.message : String(err) });
@@ -13108,8 +13349,8 @@ function hashPin2(pin) {
13108
13349
  return createHash4("sha256").update(pin).digest("hex");
13109
13350
  }
13110
13351
  function readUsersFile2() {
13111
- if (!existsSync18(USERS_FILE)) return null;
13112
- const raw = readFileSync26(USERS_FILE, "utf-8").trim();
13352
+ if (!existsSync19(USERS_FILE)) return null;
13353
+ const raw = readFileSync27(USERS_FILE, "utf-8").trim();
13113
13354
  if (!raw) return [];
13114
13355
  return JSON.parse(raw);
13115
13356
  }
@@ -13168,7 +13409,7 @@ app10.post("/claude-auth", async (c) => {
13168
13409
  } catch (err) {
13169
13410
  logoutError = err instanceof Error ? err.message : String(err);
13170
13411
  }
13171
- const credentialsPresent = existsSync18(CLAUDE_CREDENTIALS_FILE);
13412
+ const credentialsPresent = existsSync19(CLAUDE_CREDENTIALS_FILE);
13172
13413
  const ranMs = Date.now() - start;
13173
13414
  console.log(`[onboarding] op=claude-logout credentialsPresent=${credentialsPresent} ranMs=${ranMs} logoutError=${logoutError ? JSON.stringify(logoutError.slice(0, 120)) : "none"}`);
13174
13415
  return c.json({ logged_out: !credentialsPresent });
@@ -13202,7 +13443,7 @@ app10.post("/claude-auth", async (c) => {
13202
13443
  return c.json({ launched: cdpReady });
13203
13444
  }
13204
13445
  ensureLogDir();
13205
- writeFileSync10(logPath("claude-auth"), "");
13446
+ writeFileSync11(logPath("claude-auth"), "");
13206
13447
  const claudeAuthLogFd = openSync3(logPath("claude-auth"), "a");
13207
13448
  const onClaudeOutput = (chunk) => writeSync(claudeAuthLogFd, chunk);
13208
13449
  if (process.platform === "darwin") {
@@ -13227,14 +13468,14 @@ app10.post("/claude-auth", async (c) => {
13227
13468
  readBlob: readHostCredsBlob,
13228
13469
  writeFile: (blob) => {
13229
13470
  const tmp = `${CLAUDE_CREDENTIALS_FILE}.${process.pid}.tmp`;
13230
- writeFileSync10(tmp, blob, { mode: 384 });
13231
- renameSync7(tmp, CLAUDE_CREDENTIALS_FILE);
13471
+ writeFileSync11(tmp, blob, { mode: 384 });
13472
+ renameSync8(tmp, CLAUDE_CREDENTIALS_FILE);
13232
13473
  },
13233
13474
  log: (line) => console.log(line)
13234
13475
  });
13235
13476
  persistKeychainService(
13236
13477
  writebackResult,
13237
- (service) => writeFileSync10(join25(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
13478
+ (service) => writeFileSync11(join26(dirname9(CLAUDE_CREDENTIALS_FILE), ".keychain-service"), service, { mode: 384 }),
13238
13479
  (line) => console.log(line)
13239
13480
  );
13240
13481
  if (darwinAuthChild === claudeProc2) darwinAuthChild = null;
@@ -13317,9 +13558,9 @@ app10.post("/set-pin", async (c) => {
13317
13558
  console.log(`[set-pin] wrote users.json + account.json admins: userId=${userId.slice(0, 8)}\u2026 role=owner`);
13318
13559
  if (process.platform === "linux") {
13319
13560
  let installOwner = null;
13320
- if (existsSync18(INSTALL_OWNER_FILE)) {
13561
+ if (existsSync19(INSTALL_OWNER_FILE)) {
13321
13562
  try {
13322
- const raw = readFileSync26(INSTALL_OWNER_FILE, "utf-8").trim();
13563
+ const raw = readFileSync27(INSTALL_OWNER_FILE, "utf-8").trim();
13323
13564
  if (raw.length > 0) installOwner = raw;
13324
13565
  } catch (err) {
13325
13566
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -13400,7 +13641,7 @@ app10.delete("/set-pin", requireAdminSession, async (c) => {
13400
13641
  unlinkSync3(USERS_FILE);
13401
13642
  console.log(`[set-pin] cleared users.json (last entry removed): userId=${sessionUserId.slice(0, 8)}\u2026`);
13402
13643
  } else {
13403
- writeFileSync10(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
13644
+ writeFileSync11(USERS_FILE, JSON.stringify(remaining), { mode: 384 });
13404
13645
  console.log(`[set-pin] removed entry from users.json: userId=${sessionUserId.slice(0, 8)}\u2026 remaining=${remaining.length}`);
13405
13646
  }
13406
13647
  logUsersAudit(
@@ -13465,9 +13706,9 @@ app10.put("/set-pin", requireAdminSession, async (c) => {
13465
13706
  console.log(`[set-pin] changed PIN in place: userId=${sessionUserId.slice(0, 8)}\u2026`);
13466
13707
  if (process.platform === "linux") {
13467
13708
  let installOwner = null;
13468
- if (existsSync18(INSTALL_OWNER_FILE)) {
13709
+ if (existsSync19(INSTALL_OWNER_FILE)) {
13469
13710
  try {
13470
- const raw = readFileSync26(INSTALL_OWNER_FILE, "utf-8").trim();
13711
+ const raw = readFileSync27(INSTALL_OWNER_FILE, "utf-8").trim();
13471
13712
  if (raw.length > 0) installOwner = raw;
13472
13713
  } catch (err) {
13473
13714
  console.error(`[set-pin] install-owner-read-failed path=${INSTALL_OWNER_FILE} error=${err instanceof Error ? err.message : String(err)}`);
@@ -13499,9 +13740,9 @@ ${body.newPin}
13499
13740
  var onboarding_default = app10;
13500
13741
 
13501
13742
  // server/routes/client-error.ts
13502
- import { appendFileSync as appendFileSync3, existsSync as existsSync19, renameSync as renameSync8, statSync as statSync9 } from "fs";
13503
- import { join as join26 } from "path";
13504
- var CLIENT_ERRORS_LOG = join26(LOG_DIR, "client-errors.log");
13743
+ import { appendFileSync as appendFileSync3, existsSync as existsSync20, renameSync as renameSync9, statSync as statSync9 } from "fs";
13744
+ import { join as join27 } from "path";
13745
+ var CLIENT_ERRORS_LOG = join27(LOG_DIR, "client-errors.log");
13505
13746
  var MAX_LOG_SIZE = 10 * 1024 * 1024;
13506
13747
  var MAX_BODY_SIZE = 8 * 1024;
13507
13748
  var MAX_STACK_LEN = 2e3;
@@ -13549,10 +13790,10 @@ function stackHead(stack) {
13549
13790
  }
13550
13791
  function rotateIfNeeded() {
13551
13792
  try {
13552
- if (!existsSync19(CLIENT_ERRORS_LOG)) return;
13793
+ if (!existsSync20(CLIENT_ERRORS_LOG)) return;
13553
13794
  const stats = statSync9(CLIENT_ERRORS_LOG);
13554
13795
  if (stats.size < MAX_LOG_SIZE) return;
13555
- renameSync8(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
13796
+ renameSync9(CLIENT_ERRORS_LOG, CLIENT_ERRORS_LOG + ".1");
13556
13797
  } catch (err) {
13557
13798
  console.error(`[client-error] log rotation failed: ${err instanceof Error ? err.message : String(err)}`);
13558
13799
  }
@@ -13876,18 +14117,18 @@ app13.get("/", requireAdminSession, async (c) => {
13876
14117
  var accounts_default = app13;
13877
14118
 
13878
14119
  // server/routes/admin/logs.ts
13879
- import { existsSync as existsSync21, readdirSync as readdirSync17, readFileSync as readFileSync27, statSync as statSync10 } from "fs";
14120
+ import { existsSync as existsSync22, readdirSync as readdirSync18, readFileSync as readFileSync28, statSync as statSync10 } from "fs";
13880
14121
  import { resolve as resolve17, basename as basename7 } from "path";
13881
14122
 
13882
14123
  // app/lib/logs-read-resolve.ts
13883
- import { existsSync as existsSync20 } from "fs";
13884
- import { join as join27 } from "path";
14124
+ import { existsSync as existsSync21 } from "fs";
14125
+ import { join as join28 } from "path";
13885
14126
  function resolveSessionLogPaths(filename, logDirs) {
13886
14127
  const tried = [filename];
13887
14128
  const hits = [];
13888
14129
  for (const dir of logDirs) {
13889
- const fullPath = join27(dir, filename);
13890
- if (existsSync20(fullPath)) {
14130
+ const fullPath = join28(dir, filename);
14131
+ if (existsSync21(fullPath)) {
13891
14132
  hits.push({ path: fullPath, dir });
13892
14133
  }
13893
14134
  }
@@ -13915,7 +14156,7 @@ app14.get("/", async (c) => {
13915
14156
  const filePath = resolve17(dir, safe);
13916
14157
  searched.push(filePath);
13917
14158
  try {
13918
- const buffer = readFileSync27(filePath);
14159
+ const buffer = readFileSync28(filePath);
13919
14160
  const onDiskBytes = statSync10(filePath).size;
13920
14161
  const headers = {
13921
14162
  "Content-Type": "text/plain; charset=utf-8",
@@ -13980,7 +14221,7 @@ app14.get("/", async (c) => {
13980
14221
  console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} sessionId=${sessionIdSlice} via=${primaryId === cacheKey ? "cacheKey" : primaryId === sessionKeyFromConv ? "reverse-lookup" : "sessionId-fallback"}`);
13981
14222
  try {
13982
14223
  const filename = basename7(hit.path);
13983
- const buffer = readFileSync27(hit.path);
14224
+ const buffer = readFileSync28(hit.path);
13984
14225
  const onDiskBytes = statSync10(hit.path).size;
13985
14226
  const headers = {
13986
14227
  "Content-Type": "text/plain; charset=utf-8",
@@ -14015,10 +14256,10 @@ app14.get("/", async (c) => {
14015
14256
  const seen = /* @__PURE__ */ new Set();
14016
14257
  const logs = {};
14017
14258
  for (const dir of logDirs) {
14018
- if (!existsSync21(dir)) continue;
14259
+ if (!existsSync22(dir)) continue;
14019
14260
  let files;
14020
14261
  try {
14021
- files = readdirSync17(dir).filter((f) => f.endsWith(".log"));
14262
+ files = readdirSync18(dir).filter((f) => f.endsWith(".log"));
14022
14263
  } catch (err) {
14023
14264
  const reason = err instanceof Error ? err.message : String(err);
14024
14265
  console.warn(`[admin/logs] readdir-fail dir=${dir} reason=${reason}`);
@@ -14027,7 +14268,7 @@ app14.get("/", async (c) => {
14027
14268
  files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync10(resolve17(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
14028
14269
  seen.add(name);
14029
14270
  try {
14030
- const content = readFileSync27(resolve17(dir, name));
14271
+ const content = readFileSync28(resolve17(dir, name));
14031
14272
  const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
14032
14273
  logs[name] = tail.trim() || "(empty)";
14033
14274
  } catch (err) {
@@ -14067,7 +14308,7 @@ var claude_info_default = app15;
14067
14308
 
14068
14309
  // server/routes/admin/attachment.ts
14069
14310
  import { readFile as readFile2, readdir } from "fs/promises";
14070
- import { existsSync as existsSync22 } from "fs";
14311
+ import { existsSync as existsSync23 } from "fs";
14071
14312
  import { resolve as resolve18 } from "path";
14072
14313
  var app16 = new Hono();
14073
14314
  var ATTACHMENT_ID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
@@ -14090,12 +14331,12 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
14090
14331
  }
14091
14332
  let accountId = pinnedAccountId;
14092
14333
  let dir = uploadsDirFor2(accountId, attachmentId);
14093
- let found = existsSync22(dir);
14334
+ let found = existsSync23(dir);
14094
14335
  if (!found) {
14095
14336
  for (const candidate of listValidAccounts()) {
14096
14337
  if (candidate.accountId === pinnedAccountId) continue;
14097
14338
  const candidateDir = uploadsDirFor2(candidate.accountId, attachmentId);
14098
- if (existsSync22(candidateDir)) {
14339
+ if (existsSync23(candidateDir)) {
14099
14340
  accountId = candidate.accountId;
14100
14341
  dir = candidateDir;
14101
14342
  found = true;
@@ -14110,7 +14351,7 @@ app16.get("/:attachmentId", requireAdminSession, async (c) => {
14110
14351
  return new Response("Not found", { status: 404 });
14111
14352
  }
14112
14353
  const metaPath = resolve18(dir, `${attachmentId}.meta.json`);
14113
- if (!existsSync22(metaPath)) {
14354
+ if (!existsSync23(metaPath)) {
14114
14355
  return new Response("Not found", { status: 404 });
14115
14356
  }
14116
14357
  let meta;
@@ -14144,23 +14385,23 @@ var attachment_default = app16;
14144
14385
 
14145
14386
  // server/routes/admin/agents.ts
14146
14387
  import { resolve as resolve19 } from "path";
14147
- import { readdirSync as readdirSync18, readFileSync as readFileSync28, existsSync as existsSync23, rmSync as rmSync2 } from "fs";
14388
+ import { readdirSync as readdirSync19, readFileSync as readFileSync29, existsSync as existsSync24, rmSync as rmSync3 } from "fs";
14148
14389
  var app17 = new Hono();
14149
14390
  app17.get("/", (c) => {
14150
14391
  const account = resolveAccount();
14151
14392
  if (!account) return c.json({ agents: [] });
14152
14393
  const agentsDir = resolve19(account.accountDir, "agents");
14153
- if (!existsSync23(agentsDir)) return c.json({ agents: [] });
14394
+ if (!existsSync24(agentsDir)) return c.json({ agents: [] });
14154
14395
  const agents = [];
14155
14396
  try {
14156
- const entries = readdirSync18(agentsDir, { withFileTypes: true });
14397
+ const entries = readdirSync19(agentsDir, { withFileTypes: true });
14157
14398
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
14158
14399
  if (!entry.isDirectory()) continue;
14159
14400
  if (entry.name === "admin") continue;
14160
14401
  const configPath2 = resolve19(agentsDir, entry.name, "config.json");
14161
- if (!existsSync23(configPath2)) continue;
14402
+ if (!existsSync24(configPath2)) continue;
14162
14403
  try {
14163
- const config = JSON.parse(readFileSync28(configPath2, "utf-8"));
14404
+ const config = JSON.parse(readFileSync29(configPath2, "utf-8"));
14164
14405
  agents.push({
14165
14406
  slug: entry.name,
14166
14407
  displayName: config.displayName ?? entry.name,
@@ -14187,7 +14428,7 @@ app17.delete("/:slug", async (c) => {
14187
14428
  return c.json({ error: "Invalid agent slug" }, 400);
14188
14429
  }
14189
14430
  const agentDir = resolve19(account.accountDir, "agents", slug);
14190
- if (!existsSync23(agentDir)) {
14431
+ if (!existsSync24(agentDir)) {
14191
14432
  return c.json({ error: "Agent not found" }, 404);
14192
14433
  }
14193
14434
  try {
@@ -14198,7 +14439,7 @@ app17.delete("/:slug", async (c) => {
14198
14439
  return c.json({ error: `Graph cleanup failed: ${msg}` }, 500);
14199
14440
  }
14200
14441
  try {
14201
- rmSync2(agentDir, { recursive: true, force: true });
14442
+ rmSync3(agentDir, { recursive: true, force: true });
14202
14443
  console.log(`[admin/agents] deleted agent "${slug}"`);
14203
14444
  return c.json({ ok: true });
14204
14445
  } catch (err) {
@@ -14217,7 +14458,7 @@ app17.post("/:slug/project", async (c) => {
14217
14458
  return c.json({ error: "Invalid agent slug" }, 400);
14218
14459
  }
14219
14460
  const agentDir = resolve19(account.accountDir, "agents", slug);
14220
- if (!existsSync23(agentDir)) {
14461
+ if (!existsSync24(agentDir)) {
14221
14462
  return c.json({ error: "Agent not found on disk" }, 404);
14222
14463
  }
14223
14464
  try {
@@ -14233,7 +14474,7 @@ var agents_default = app17;
14233
14474
  // server/routes/admin/sessions.ts
14234
14475
  import crypto2 from "crypto";
14235
14476
  import { resolve as resolvePath } from "path";
14236
- import { existsSync as existsSync24, mkdirSync as mkdirSync6, createWriteStream } from "fs";
14477
+ import { existsSync as existsSync25, mkdirSync as mkdirSync7, createWriteStream } from "fs";
14237
14478
 
14238
14479
  // ../lib/admin-conversation-purge/src/index.ts
14239
14480
  async function purgeAdminConversationJsonls(args) {
@@ -14380,7 +14621,7 @@ var pickComponentBytes = (..._args) => null;
14380
14621
  function openResumeStreamLog(accountId, sessionId) {
14381
14622
  const dir = resolvePath(ACCOUNTS_DIR, accountId, "resume-logs");
14382
14623
  try {
14383
- mkdirSync6(dir, { recursive: true });
14624
+ mkdirSync7(dir, { recursive: true });
14384
14625
  } catch {
14385
14626
  }
14386
14627
  return createWriteStream(resolvePath(dir, `${sessionId}.log`), { flags: "a" });
@@ -14393,7 +14634,7 @@ function validateAndShapeAttachments(raws, conversationAccountId, sessionId, mes
14393
14634
  let reason = null;
14394
14635
  if (!a.attachmentId || !a.filename || !a.mimeType || !a.storagePath) reason = "schema-fail";
14395
14636
  else if (a.accountId !== conversationAccountId) reason = "account-mismatch";
14396
- else if (!existsSync24(a.storagePath)) reason = "missing-file";
14637
+ else if (!existsSync25(a.storagePath)) reason = "missing-file";
14397
14638
  if (reason) {
14398
14639
  invalid++;
14399
14640
  try {
@@ -14919,8 +15160,8 @@ app18.put("/:id/label", requireAdminSession, async (c) => {
14919
15160
  var sessions_default = app18;
14920
15161
 
14921
15162
  // app/lib/claude-agent/spawn-context.ts
14922
- import { existsSync as existsSync25, readFileSync as readFileSync29, readdirSync as readdirSync19, statSync as statSync11 } from "fs";
14923
- import { dirname as dirname10, resolve as resolve20, join as join28 } from "path";
15163
+ import { existsSync as existsSync26, readFileSync as readFileSync30, readdirSync as readdirSync20, statSync as statSync11 } from "fs";
15164
+ import { dirname as dirname10, resolve as resolve20, join as join29 } from "path";
14924
15165
  async function resolveOwnerProfileBlock(accountId, userId) {
14925
15166
  if (!userId) return { ok: false, reason: "missing-user-id" };
14926
15167
  try {
@@ -14961,14 +15202,14 @@ function frontmatterField(manifest, field2) {
14961
15202
  function extractPluginToolDescriptions(pluginDir) {
14962
15203
  const out = /* @__PURE__ */ new Map();
14963
15204
  const candidates = [
14964
- join28(pluginDir, "mcp/dist/index.js"),
14965
- join28(pluginDir, "mcp/src/index.ts")
15205
+ join29(pluginDir, "mcp/dist/index.js"),
15206
+ join29(pluginDir, "mcp/src/index.ts")
14966
15207
  ];
14967
15208
  let raw = null;
14968
15209
  for (const path3 of candidates) {
14969
- if (!existsSync25(path3)) continue;
15210
+ if (!existsSync26(path3)) continue;
14970
15211
  try {
14971
- raw = readFileSync29(path3, "utf-8");
15212
+ raw = readFileSync30(path3, "utf-8");
14972
15213
  break;
14973
15214
  } catch {
14974
15215
  }
@@ -15018,9 +15259,9 @@ function parseSkillPathsFromFrontmatter(fm) {
15018
15259
  function listPluginDirs() {
15019
15260
  const out = /* @__PURE__ */ new Map();
15020
15261
  const platformPlugins = resolve20(PLATFORM_ROOT, "plugins");
15021
- if (existsSync25(platformPlugins)) {
15022
- for (const name of readdirSync19(platformPlugins)) {
15023
- const dir = join28(platformPlugins, name);
15262
+ if (existsSync26(platformPlugins)) {
15263
+ for (const name of readdirSync20(platformPlugins)) {
15264
+ const dir = join29(platformPlugins, name);
15024
15265
  try {
15025
15266
  if (statSync11(dir).isDirectory()) out.set(name, dir);
15026
15267
  } catch {
@@ -15028,13 +15269,13 @@ function listPluginDirs() {
15028
15269
  }
15029
15270
  }
15030
15271
  const premiumRoot = resolve20(dirname10(PLATFORM_ROOT), "premium-plugins");
15031
- if (existsSync25(premiumRoot)) {
15032
- for (const bundle of readdirSync19(premiumRoot)) {
15033
- const bundlePlugins = join28(premiumRoot, bundle, "plugins");
15034
- if (!existsSync25(bundlePlugins)) continue;
15272
+ if (existsSync26(premiumRoot)) {
15273
+ for (const bundle of readdirSync20(premiumRoot)) {
15274
+ const bundlePlugins = join29(premiumRoot, bundle, "plugins");
15275
+ if (!existsSync26(bundlePlugins)) continue;
15035
15276
  try {
15036
- for (const name of readdirSync19(bundlePlugins)) {
15037
- const dir = join28(bundlePlugins, name);
15277
+ for (const name of readdirSync20(bundlePlugins)) {
15278
+ const dir = join29(bundlePlugins, name);
15038
15279
  try {
15039
15280
  if (statSync11(dir).isDirectory()) out.set(name, dir);
15040
15281
  } catch {
@@ -15048,9 +15289,9 @@ function listPluginDirs() {
15048
15289
  }
15049
15290
  function readEnabledPlugins(accountId) {
15050
15291
  const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
15051
- if (!existsSync25(accountFile)) return /* @__PURE__ */ new Set();
15292
+ if (!existsSync26(accountFile)) return /* @__PURE__ */ new Set();
15052
15293
  try {
15053
- const parsed = JSON.parse(readFileSync29(accountFile, "utf-8"));
15294
+ const parsed = JSON.parse(readFileSync30(accountFile, "utf-8"));
15054
15295
  return new Set(
15055
15296
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
15056
15297
  );
@@ -15059,10 +15300,10 @@ function readEnabledPlugins(accountId) {
15059
15300
  }
15060
15301
  }
15061
15302
  function readFrontmatter(path3) {
15062
- if (!existsSync25(path3)) return null;
15303
+ if (!existsSync26(path3)) return null;
15063
15304
  let raw;
15064
15305
  try {
15065
- raw = readFileSync29(path3, "utf-8");
15306
+ raw = readFileSync30(path3, "utf-8");
15066
15307
  } catch {
15067
15308
  return null;
15068
15309
  }
@@ -15077,7 +15318,7 @@ function computeActivePlugins(accountId) {
15077
15318
  for (const name of Array.from(enabled).sort()) {
15078
15319
  const dir = pluginDirs.get(name);
15079
15320
  if (!dir) continue;
15080
- const fm = readFrontmatter(join28(dir, "PLUGIN.md"));
15321
+ const fm = readFrontmatter(join29(dir, "PLUGIN.md"));
15081
15322
  if (!fm) continue;
15082
15323
  const description = frontmatterField(`---
15083
15324
  ${fm}
@@ -15094,7 +15335,7 @@ ${fm}
15094
15335
  `plugin-manifest-tool-coverage plugin=${name} tools=${tools.length} with-desc=${withDesc}`
15095
15336
  );
15096
15337
  if (toolNames.length > 0 && descMap.size === 0) {
15097
- const hasSource = existsSync25(join28(dir, "mcp/dist/index.js")) || existsSync25(join28(dir, "mcp/src/index.ts"));
15338
+ const hasSource = existsSync26(join29(dir, "mcp/dist/index.js")) || existsSync26(join29(dir, "mcp/src/index.ts"));
15098
15339
  if (hasSource) {
15099
15340
  console.warn(
15100
15341
  `[spawn-context] WARN plugin=${name} mcp source present but tool-description regex matched zero entries \u2014 SDK upgrade may have changed the registration shape`
@@ -15104,7 +15345,7 @@ ${fm}
15104
15345
  const skillPaths = parseSkillPathsFromFrontmatter(fm);
15105
15346
  const skills = [];
15106
15347
  for (const relPath of skillPaths) {
15107
- const skillPath = join28(dir, relPath);
15348
+ const skillPath = join29(dir, relPath);
15108
15349
  const skillFm = readFrontmatter(skillPath);
15109
15350
  if (!skillFm) continue;
15110
15351
  const skillName = frontmatterField(`---
@@ -15121,10 +15362,10 @@ ${skillFm}
15121
15362
  }
15122
15363
  function computeSpecialistDomains(accountId) {
15123
15364
  const specialistsDir = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "specialists", "agents");
15124
- if (!existsSync25(specialistsDir)) return [];
15365
+ if (!existsSync26(specialistsDir)) return [];
15125
15366
  let entries;
15126
15367
  try {
15127
- entries = readdirSync19(specialistsDir);
15368
+ entries = readdirSync20(specialistsDir);
15128
15369
  } catch {
15129
15370
  return [];
15130
15371
  }
@@ -15148,7 +15389,7 @@ function computeSpecialistDomains(accountId) {
15148
15389
  const out = [];
15149
15390
  for (const file of entries.sort()) {
15150
15391
  if (!file.endsWith(".md")) continue;
15151
- const fm = readFrontmatter(join28(specialistsDir, file));
15392
+ const fm = readFrontmatter(join29(specialistsDir, file));
15152
15393
  if (!fm) continue;
15153
15394
  const wrapped = `---
15154
15395
  ${fm}
@@ -15167,10 +15408,10 @@ ${fm}
15167
15408
  }
15168
15409
  function computeDormantPlugins(accountId) {
15169
15410
  const accountFile = resolve20(PLATFORM_ROOT, "..", "data/accounts", accountId, "account.json");
15170
- if (!existsSync25(accountFile)) return [];
15411
+ if (!existsSync26(accountFile)) return [];
15171
15412
  let enabled;
15172
15413
  try {
15173
- const raw = readFileSync29(accountFile, "utf-8");
15414
+ const raw = readFileSync30(accountFile, "utf-8");
15174
15415
  const parsed = JSON.parse(raw);
15175
15416
  enabled = new Set(
15176
15417
  Array.isArray(parsed.enabledPlugins) ? parsed.enabledPlugins.filter((p) => typeof p === "string") : []
@@ -15182,10 +15423,10 @@ function computeDormantPlugins(accountId) {
15182
15423
  return [];
15183
15424
  }
15184
15425
  const pluginsDir = resolve20(PLATFORM_ROOT, "plugins");
15185
- if (!existsSync25(pluginsDir)) return [];
15426
+ if (!existsSync26(pluginsDir)) return [];
15186
15427
  let entries;
15187
15428
  try {
15188
- entries = readdirSync19(pluginsDir);
15429
+ entries = readdirSync20(pluginsDir);
15189
15430
  } catch {
15190
15431
  return [];
15191
15432
  }
@@ -15193,10 +15434,10 @@ function computeDormantPlugins(accountId) {
15193
15434
  for (const name of entries) {
15194
15435
  if (enabled.has(name)) continue;
15195
15436
  const manifestPath = resolve20(pluginsDir, name, "PLUGIN.md");
15196
- if (!existsSync25(manifestPath)) continue;
15437
+ if (!existsSync26(manifestPath)) continue;
15197
15438
  let manifest;
15198
15439
  try {
15199
- manifest = readFileSync29(manifestPath, "utf-8");
15440
+ manifest = readFileSync30(manifestPath, "utf-8");
15200
15441
  } catch {
15201
15442
  continue;
15202
15443
  }
@@ -15210,13 +15451,13 @@ function computeDormantPlugins(accountId) {
15210
15451
  }
15211
15452
 
15212
15453
  // server/routes/admin/claude-sessions.ts
15213
- import { existsSync as existsSync26, readFileSync as readFileSync30 } from "fs";
15454
+ import { existsSync as existsSync27, readFileSync as readFileSync31 } from "fs";
15214
15455
  import { resolve as resolve21 } from "path";
15215
15456
  function readTunnelState(brandConfigDir) {
15216
15457
  const statePath = `${process.env.HOME ?? ""}/${brandConfigDir}/cloudflared/tunnel.state`;
15217
- if (!existsSync26(statePath)) return null;
15458
+ if (!existsSync27(statePath)) return null;
15218
15459
  try {
15219
- const parsed = JSON.parse(readFileSync30(statePath, "utf-8"));
15460
+ const parsed = JSON.parse(readFileSync31(statePath, "utf-8"));
15220
15461
  const tunnelId = typeof parsed.tunnelId === "string" ? parsed.tunnelId : null;
15221
15462
  const tunnelName = typeof parsed.tunnelName === "string" ? parsed.tunnelName : null;
15222
15463
  const domain = typeof parsed.domain === "string" ? parsed.domain : null;
@@ -15230,7 +15471,7 @@ function resolveTunnelUrl() {
15230
15471
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT ?? process.env.PLATFORM_ROOT ?? resolve21(process.cwd(), "..");
15231
15472
  let brand;
15232
15473
  try {
15233
- brand = JSON.parse(readFileSync30(resolve21(platformRoot5, "config", "brand.json"), "utf-8"));
15474
+ brand = JSON.parse(readFileSync31(resolve21(platformRoot5, "config", "brand.json"), "utf-8"));
15234
15475
  } catch {
15235
15476
  return null;
15236
15477
  }
@@ -15241,7 +15482,7 @@ function resolveTunnelUrl() {
15241
15482
  if (!state) return null;
15242
15483
  return `https://${hostname2}.${state.domain}`;
15243
15484
  }
15244
- var TAG26 = "[claude-session-manager:wrapper]";
15485
+ var TAG27 = "[claude-session-manager:wrapper]";
15245
15486
  async function refuseIfClaudeAuthDead(c, route, sessionId) {
15246
15487
  const auth = await ensureAuth();
15247
15488
  if (auth.status !== "dead" && auth.status !== "missing") return null;
@@ -15259,12 +15500,12 @@ async function performSpawnWithInitialMessage(args) {
15259
15500
  const aboutOwner = await resolveOwnerProfileBlock(args.senderId, args.userId);
15260
15501
  const ownerMs = Date.now() - ownerStart;
15261
15502
  const aboutOwnerStatus = aboutOwner == null ? "absent" : "ok" in aboutOwner && aboutOwner.ok === false ? `unresolved:${aboutOwner.reason}` : "ok";
15262
- console.log(`${TAG26} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
15503
+ console.log(`${TAG27} about-owner-resolved status=${aboutOwnerStatus} ms=${ownerMs}`);
15263
15504
  const dormantPlugins = computeDormantPlugins(args.senderId);
15264
15505
  const activePlugins = computeActivePlugins(args.senderId);
15265
15506
  const specialistDomains = computeSpecialistDomains(args.senderId);
15266
15507
  const tunnelUrl = resolveTunnelUrl();
15267
- console.log(`${TAG26} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
15508
+ console.log(`${TAG27} tunnel-url-resolved value=${tunnelUrl ?? "null"}`);
15268
15509
  const upstreamPayload = JSON.stringify({
15269
15510
  senderId: args.senderId,
15270
15511
  // Task 205 — pass userId through to the manager so it lands as
@@ -15291,24 +15532,24 @@ async function performSpawnWithInitialMessage(args) {
15291
15532
  // unshapely values.
15292
15533
  conversationNodeId: args.conversationNodeId
15293
15534
  });
15294
- console.log(`${TAG26} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
15535
+ console.log(`${TAG27} forward-spawn-start managerBase=${managerBase("claude-session-manager:wrapper")} bytes=${upstreamPayload.length} hidden=${args.hidden} specialist=${args.specialist ?? "none"}`);
15295
15536
  const forwardStart = Date.now();
15296
15537
  const upstream = await fetch(`${managerBase("claude-session-manager:wrapper")}/public-spawn`, {
15297
15538
  method: "POST",
15298
15539
  headers: { "content-type": "application/json" },
15299
15540
  body: upstreamPayload
15300
15541
  }).catch((err) => {
15301
- console.error(`${TAG26} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
15542
+ console.error(`${TAG27} fetch-failed op=spawn message=${err instanceof Error ? err.message : String(err)} ms=${Date.now() - forwardStart}`);
15302
15543
  return null;
15303
15544
  });
15304
15545
  if (!upstream) return {
15305
15546
  response: new Response(JSON.stringify({ error: "manager-unreachable" }), { status: 503, headers: { "content-type": "application/json" } }),
15306
15547
  claudeSessionId: null
15307
15548
  };
15308
- console.log(`${TAG26} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
15549
+ console.log(`${TAG27} forward-spawn-done status=${upstream.status} ms=${Date.now() - forwardStart}`);
15309
15550
  if (args.initialMessage) {
15310
15551
  const inputBytes = Buffer.byteLength(args.initialMessage, "utf8");
15311
- console.log(`${TAG26} initial-message-inlined bytes=${inputBytes}`);
15552
+ console.log(`${TAG27} initial-message-inlined bytes=${inputBytes}`);
15312
15553
  }
15313
15554
  const bodyText = await upstream.text().catch(() => "");
15314
15555
  let claudeSessionId = null;
@@ -15343,7 +15584,7 @@ app19.post("/", async (c) => {
15343
15584
  if (refusal) return refusal;
15344
15585
  const senderId = getAccountIdForSession(cacheKey) ?? "";
15345
15586
  if (!senderId) {
15346
- console.error(`${TAG26} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
15587
+ console.error(`${TAG27} reject reason=no-account-id cacheKey-prefix=${cacheKey.slice(0, 8)}`);
15347
15588
  return c.json({ error: "admin-account-not-resolved" }, 500);
15348
15589
  }
15349
15590
  const userId = getUserIdForSession(cacheKey) ?? void 0;
@@ -15352,7 +15593,7 @@ app19.post("/", async (c) => {
15352
15593
  const permissionMode = typeof body.permissionMode === "string" ? body.permissionMode : void 0;
15353
15594
  const specialist = typeof body.specialist === "string" && /^[A-Za-z0-9_-]{1,64}$/.test(body.specialist) ? body.specialist : void 0;
15354
15595
  const model = typeof body.model === "string" && /^[A-Za-z0-9._-]{1,64}$/.test(body.model) ? body.model : void 0;
15355
- console.log(`${TAG26} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
15596
+ console.log(`${TAG27} spawn-request-in surface=cookie accountId=${senderId.slice(0, 8)} userId=${userId ? userId.slice(0, 8) : "absent"} channel=${channel} permissionMode=${permissionMode ?? "default"} specialist=${specialist ?? "none"} model=${model ?? "default"} initialMessage=${initialMessage ? "yes" : "no"}`);
15356
15597
  const conversationNodeId = cacheKey ? getSessionIdForSession(cacheKey) : void 0;
15357
15598
  const { response, claudeSessionId } = await performSpawnWithInitialMessage({
15358
15599
  senderId,
@@ -15371,13 +15612,13 @@ app19.post("/", async (c) => {
15371
15612
  claudeSessionId,
15372
15613
  senderId
15373
15614
  );
15374
- console.log(`${TAG26} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
15615
+ console.log(`${TAG27} route-done surface=cookie status=${response.status} route-ms=${Date.now() - routeStart}`);
15375
15616
  return response;
15376
15617
  });
15377
15618
  var claude_sessions_default = app19;
15378
15619
 
15379
15620
  // server/routes/admin/log-ingest.ts
15380
- var TAG27 = "[log-ingest]";
15621
+ var TAG28 = "[log-ingest]";
15381
15622
  var TAG_PATTERN = /^[A-Za-z0-9_:-]{1,32}$/;
15382
15623
  var LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error"]);
15383
15624
  var MAX_LINE_BYTES = 4096;
@@ -15388,7 +15629,7 @@ function isLoopbackAddr2(addr) {
15388
15629
  app20.post("/", async (c) => {
15389
15630
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
15390
15631
  if (!isLoopbackAddr2(remoteAddr)) {
15391
- console.error(`${TAG27} reject reason=non-loopback remoteAddr=${remoteAddr}`);
15632
+ console.error(`${TAG28} reject reason=non-loopback remoteAddr=${remoteAddr}`);
15392
15633
  return c.json({ error: "log-ingest-loopback-only" }, 403);
15393
15634
  }
15394
15635
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -15397,7 +15638,7 @@ app20.post("/", async (c) => {
15397
15638
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
15398
15639
  const offender = tokens.find((t) => !isLoopbackAddr2(t));
15399
15640
  if (offender !== void 0) {
15400
- console.error(`${TAG27} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
15641
+ console.error(`${TAG28} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
15401
15642
  return c.json({ error: "log-ingest-loopback-only" }, 403);
15402
15643
  }
15403
15644
  }
@@ -15439,18 +15680,18 @@ var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
15439
15680
  ]);
15440
15681
  var app21 = new Hono();
15441
15682
  app21.post("/", async (c) => {
15442
- const TAG47 = "[admin:events]";
15683
+ const TAG51 = "[admin:events]";
15443
15684
  let body;
15444
15685
  try {
15445
15686
  body = await c.req.json();
15446
15687
  } catch (err) {
15447
15688
  const detail = err instanceof Error ? err.message : String(err);
15448
- console.error(`${TAG47} reject reason=body-not-json detail=${detail}`);
15689
+ console.error(`${TAG51} reject reason=body-not-json detail=${detail}`);
15449
15690
  return c.json({ ok: false, detail: "Request body was not valid JSON" }, 400);
15450
15691
  }
15451
15692
  const event = typeof body.event === "string" ? body.event : "";
15452
15693
  if (!ALLOWED_EVENTS.has(event)) {
15453
- console.error(`${TAG47} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
15694
+ console.error(`${TAG51} reject reason=event-not-allowed event=${JSON.stringify(event)}`);
15454
15695
  return c.json({ ok: false, detail: `Event "${event}" is not allowed` }, 400);
15455
15696
  }
15456
15697
  const rawFields = body.fields && typeof body.fields === "object" ? body.fields : {};
@@ -15472,11 +15713,11 @@ app21.post("/", async (c) => {
15472
15713
  var events_default = app21;
15473
15714
 
15474
15715
  // server/routes/admin/files.ts
15475
- import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync27 } from "fs";
15716
+ import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync28 } from "fs";
15476
15717
  import { readdir as readdir3, readFile as readFile4, stat as stat4, mkdir as mkdir3, unlink as unlink2, rename, rmdir } from "fs/promises";
15477
15718
  import { realpathSync as realpathSync6 } from "fs";
15478
15719
  import { randomUUID as randomUUID10 } from "crypto";
15479
- import { basename as basename9, dirname as dirname11, join as join30, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
15720
+ import { basename as basename9, dirname as dirname11, join as join31, relative as relative4, resolve as resolve23, sep as sep6 } from "path";
15480
15721
  import { Readable as Readable2 } from "stream";
15481
15722
 
15482
15723
  // ../lib/graph-trash/src/index.ts
@@ -15794,7 +16035,7 @@ async function cascadeDeleteDocument(params) {
15794
16035
 
15795
16036
  // app/lib/file-index.ts
15796
16037
  import * as fsp from "fs/promises";
15797
- import { resolve as resolve22, relative as relative3, join as join29, basename as basename8, extname as extname2, sep as sep5 } from "path";
16038
+ import { resolve as resolve22, relative as relative3, join as join30, basename as basename8, extname as extname2, sep as sep5 } from "path";
15798
16039
  import { tmpdir as tmpdir2 } from "os";
15799
16040
  import { execFile as execFile2 } from "child_process";
15800
16041
  import { promisify as promisify2 } from "util";
@@ -15876,7 +16117,7 @@ async function extractPdf(absolute) {
15876
16117
  return stdout.trim();
15877
16118
  }
15878
16119
  async function ocrPdf(absolute) {
15879
- const outPdf = join29(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
16120
+ const outPdf = join30(tmpdir2(), `file-index-ocr-${process.pid}-${Date.now()}.pdf`);
15880
16121
  try {
15881
16122
  await execFileAsync2(
15882
16123
  "ocrmypdf",
@@ -15938,7 +16179,7 @@ async function readDisplayName(absolute) {
15938
16179
  const stem = dot === -1 ? base : base.slice(0, dot);
15939
16180
  if (base === `${stem}.meta.json`) return null;
15940
16181
  try {
15941
- const raw = await fsp.readFile(join29(dir, `${stem}.meta.json`), "utf-8");
16182
+ const raw = await fsp.readFile(join30(dir, `${stem}.meta.json`), "utf-8");
15942
16183
  const meta = JSON.parse(raw);
15943
16184
  const dn = meta.displayName ?? meta.filename;
15944
16185
  return typeof dn === "string" && dn.length > 0 ? dn : null;
@@ -15959,7 +16200,7 @@ async function walkSubtree(root, dataRoot, out) {
15959
16200
  for (const entry of entries) {
15960
16201
  if (entry.isSymbolicLink()) continue;
15961
16202
  if (entry.isDirectory() && entry.name === ".uploads-tmp") continue;
15962
- const abs = join29(root, entry.name);
16203
+ const abs = join30(root, entry.name);
15963
16204
  if (entry.isDirectory()) {
15964
16205
  const sub = await walkSubtree(abs, dataRoot, out);
15965
16206
  if (!sub.clean) clean = false;
@@ -16315,7 +16556,7 @@ var UPLOAD_TMP_DIR = ".uploads-tmp";
16315
16556
  var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
16316
16557
  async function readMeta(absDir, baseName) {
16317
16558
  try {
16318
- const raw = await readFile4(join30(absDir, `${baseName}.meta.json`), "utf8");
16559
+ const raw = await readFile4(join31(absDir, `${baseName}.meta.json`), "utf8");
16319
16560
  const parsed = JSON.parse(raw);
16320
16561
  if (typeof parsed?.filename === "string") {
16321
16562
  return { filename: parsed.filename, mimeType: typeof parsed.mimeType === "string" ? parsed.mimeType : void 0 };
@@ -16370,7 +16611,7 @@ async function servableFilesIn(dirAbs, uuid) {
16370
16611
  }
16371
16612
  async function enrich(absolute, entry, accountNames) {
16372
16613
  if (entry.kind === "directory" && UUID_RE3.test(entry.name)) {
16373
- const dirAbs = join30(absolute, entry.name);
16614
+ const dirAbs = join31(absolute, entry.name);
16374
16615
  const meta = await readMeta(dirAbs, entry.name);
16375
16616
  if (meta?.filename) {
16376
16617
  const servable = await servableFilesIn(dirAbs, entry.name);
@@ -16379,7 +16620,7 @@ async function enrich(absolute, entry, accountNames) {
16379
16620
  let size = null;
16380
16621
  let modifiedAt = entry.modifiedAt;
16381
16622
  try {
16382
- const st = await stat4(join30(dirAbs, innerName));
16623
+ const st = await stat4(join31(dirAbs, innerName));
16383
16624
  size = st.size;
16384
16625
  modifiedAt = st.mtime.toISOString();
16385
16626
  } catch {
@@ -16554,7 +16795,7 @@ app22.get("/", requireAdminSession, async (c) => {
16554
16795
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
16555
16796
  const protectedEntry = isProtectedFromDeletion(childRel).protected;
16556
16797
  try {
16557
- const entryPath = join30(absolute, name);
16798
+ const entryPath = join31(absolute, name);
16558
16799
  const s = await stat4(entryPath);
16559
16800
  entries.push({
16560
16801
  name,
@@ -16617,7 +16858,7 @@ app22.get("/download", requireAdminSession, async (c) => {
16617
16858
  console.error(`[data] op=scratchpad-no-session sessionId="${sessionId.slice(0, 8)}\u2026"`);
16618
16859
  return c.json({ error: "Not found" }, 404);
16619
16860
  }
16620
- const meta = readSidecarMeta(join30(projectDir, `${sessionId}.meta.json`));
16861
+ const meta = readSidecarMeta(join31(projectDir, `${sessionId}.meta.json`));
16621
16862
  if (!meta.accountId || meta.accountId !== accountId) {
16622
16863
  console.error(`[data] account-scope-blocked root="scratchpad" sessionId="${sessionId.slice(0, 8)}\u2026" account=${accountId.slice(0, 8)}\u2026`);
16623
16864
  return c.json({ error: "Not found" }, 404);
@@ -16712,7 +16953,7 @@ async function* walkRegularFiles(dirAbsolute) {
16712
16953
  const dirents = await readdir3(dirAbsolute, { withFileTypes: true });
16713
16954
  for (const d of dirents) {
16714
16955
  if (d.isSymbolicLink()) continue;
16715
- const child = join30(dirAbsolute, d.name);
16956
+ const child = join31(dirAbsolute, d.name);
16716
16957
  if (d.isDirectory()) {
16717
16958
  yield* walkRegularFiles(child);
16718
16959
  continue;
@@ -16822,7 +17063,7 @@ async function resolveUploadTarget(c, accountId, uid) {
16822
17063
  const base = resolveOwnAccountWrite(rawDir, accountId, "POST /api/admin/files/upload");
16823
17064
  if (!base.ok) return { ok: false, status: base.status, error: base.error };
16824
17065
  const relDir = relpath ? dirname11(relpath) : ".";
16825
- const destRel = relDir === "." ? base.relative : join30(base.relative, relDir);
17066
+ const destRel = relDir === "." ? base.relative : join31(base.relative, relDir);
16826
17067
  if (crossesForeignAccountPartition(destRel, accountId)) {
16827
17068
  console.error(`[data] account-scope-blocked endpoint="POST /api/admin/files/upload" path="${destRel}" account=${accountId.slice(0, 8)}\u2026`);
16828
17069
  return { ok: false, status: 404, error: "Not found" };
@@ -16896,7 +17137,7 @@ app22.post("/upload", requireAdminSession, async (c) => {
16896
17137
  });
16897
17138
  await unlink2(tmpPath).catch(() => {
16898
17139
  });
16899
- const tempRemoved = !existsSync27(tmpPath);
17140
+ const tempRemoved = !existsSync28(tmpPath);
16900
17141
  console.error(`[data-upload] op=cleanup uid=${uid} tempRemoved=${tempRemoved}`);
16901
17142
  };
16902
17143
  const reader = body.getReader();
@@ -16970,7 +17211,7 @@ async function discardChunkUpload(uploadId, state) {
16970
17211
  });
16971
17212
  await unlink2(state.tmpPath).catch(() => {
16972
17213
  });
16973
- const tempRemoved = !existsSync27(state.tmpPath);
17214
+ const tempRemoved = !existsSync28(state.tmpPath);
16974
17215
  console.error(`[data-upload] op=cleanup uid=${uploadId} tempRemoved=${tempRemoved}`);
16975
17216
  }
16976
17217
  async function writeChunkBody(body, out, alreadyReceived, ceiling) {
@@ -17199,7 +17440,7 @@ app22.delete("/", requireAdminSession, async (c) => {
17199
17440
  const dot = base.lastIndexOf(".");
17200
17441
  const stem = dot === -1 ? base : base.slice(0, dot);
17201
17442
  const containerDir = dirname11(absolute);
17202
- const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join30(containerDir, `${stem}.meta.json`) : null;
17443
+ const sidecarPath = UUID_RE3.test(stem) && base !== `${stem}.meta.json` ? join31(containerDir, `${stem}.meta.json`) : null;
17203
17444
  const isAttachmentContainer = UUID_RE3.test(stem) && basename9(containerDir) === stem;
17204
17445
  await unlink2(absolute);
17205
17446
  if (sidecarPath) {
@@ -17209,7 +17450,7 @@ app22.delete("/", requireAdminSession, async (c) => {
17209
17450
  }
17210
17451
  }
17211
17452
  if (isAttachmentContainer) {
17212
- await unlink2(join30(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
17453
+ await unlink2(join31(containerDir, `${stem}${EXTRACTED_TEXT_SUFFIX}`)).catch(() => {
17213
17454
  });
17214
17455
  await rmdir(containerDir).catch(() => {
17215
17456
  });
@@ -18313,8 +18554,8 @@ function isHiddenByDefault(label) {
18313
18554
  }
18314
18555
 
18315
18556
  // server/lib/top-level-labels.ts
18316
- import { readdirSync as readdirSync20, readFileSync as readFileSync31 } from "fs";
18317
- import { join as join31, resolve as resolve24 } from "path";
18557
+ import { readdirSync as readdirSync21, readFileSync as readFileSync32 } from "fs";
18558
+ import { join as join32, resolve as resolve24 } from "path";
18318
18559
  var STATIC_TOP_LEVEL_LABELS = Object.freeze(
18319
18560
  /* @__PURE__ */ new Set([
18320
18561
  // Base-schema infra (schema-base.md has no top-level section).
@@ -18407,7 +18648,7 @@ function parseTopLevelLabels(content) {
18407
18648
  }
18408
18649
  function resolveReferencesDir() {
18409
18650
  if (process.env.MAXY_PLATFORM_ROOT) {
18410
- return join31(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
18651
+ return join32(process.env.MAXY_PLATFORM_ROOT, "plugins", "memory", "references");
18411
18652
  }
18412
18653
  return resolve24(import.meta.dirname, "../../../plugins/memory/references");
18413
18654
  }
@@ -18415,9 +18656,9 @@ function parseTableTopLevelLabels(referencesDir) {
18415
18656
  const labels = /* @__PURE__ */ new Set();
18416
18657
  const contributingFiles = [];
18417
18658
  try {
18418
- const fileNames = readdirSync20(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
18659
+ const fileNames = readdirSync21(referencesDir).filter((f) => f.startsWith("schema-") && f.endsWith(".md")).sort();
18419
18660
  for (const fileName of fileNames) {
18420
- const content = readFileSync31(join31(referencesDir, fileName), "utf-8");
18661
+ const content = readFileSync32(join32(referencesDir, fileName), "utf-8");
18421
18662
  const parsed = parseTopLevelLabels(content);
18422
18663
  if (parsed.length > 0) contributingFiles.push(fileName);
18423
18664
  for (const label of parsed) labels.add(label);
@@ -19571,7 +19812,7 @@ var graph_default_view_default = app28;
19571
19812
  // server/routes/admin/sidebar-artefacts.ts
19572
19813
  import { readdir as readdir4, stat as stat5 } from "fs/promises";
19573
19814
  import { resolve as resolve25, relative as relative5, isAbsolute as isAbsolute2, sep as sep7, basename as basename10 } from "path";
19574
- import { existsSync as existsSync28 } from "fs";
19815
+ import { existsSync as existsSync29 } from "fs";
19575
19816
  var LIMIT = 50;
19576
19817
  var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
19577
19818
  function toDataRootRelPath(absPath) {
@@ -19678,7 +19919,7 @@ async function fetchAgentTemplateRows(accountDir) {
19678
19919
  async function unionSpecialistFilenames(overrideDir, bundledDir) {
19679
19920
  const names = /* @__PURE__ */ new Set();
19680
19921
  for (const dir of [overrideDir, bundledDir]) {
19681
- if (!existsSync28(dir)) continue;
19922
+ if (!existsSync29(dir)) continue;
19682
19923
  try {
19683
19924
  const entries = await readdir4(dir);
19684
19925
  for (const entry of entries) {
@@ -19693,7 +19934,7 @@ async function unionSpecialistFilenames(overrideDir, bundledDir) {
19693
19934
  }
19694
19935
  async function readAgentTemplateRow(inp) {
19695
19936
  let chosenPath = null;
19696
- if (existsSync28(inp.overridePath)) {
19937
+ if (existsSync29(inp.overridePath)) {
19697
19938
  try {
19698
19939
  validateFilePathInAccount(inp.overridePath, inp.overrideRoot);
19699
19940
  chosenPath = inp.overridePath;
@@ -19704,7 +19945,7 @@ async function readAgentTemplateRow(inp) {
19704
19945
  );
19705
19946
  return null;
19706
19947
  }
19707
- } else if (existsSync28(inp.bundledPath)) {
19948
+ } else if (existsSync29(inp.bundledPath)) {
19708
19949
  if (!isWithin(inp.bundledPath, inp.bundledRoot)) {
19709
19950
  console.error(
19710
19951
  `[admin/sidebar-artefacts] agent-template-read-failed agent=${inp.displayName} kind=${inp.logName} error="bundled path outside PLATFORM_ROOT"`
@@ -20306,14 +20547,14 @@ app37.get("/", async (c) => {
20306
20547
  var system_stats_default = app37;
20307
20548
 
20308
20549
  // server/routes/admin/health.ts
20309
- import { existsSync as existsSync29, readFileSync as readFileSync32 } from "fs";
20310
- import { resolve as resolve26, join as join32 } from "path";
20550
+ import { existsSync as existsSync30, readFileSync as readFileSync33 } from "fs";
20551
+ import { resolve as resolve26, join as join33 } from "path";
20311
20552
  var PLATFORM_ROOT6 = process.env.MAXY_PLATFORM_ROOT ?? resolve26(process.cwd(), "..");
20312
20553
  var brandHostname = "maxy";
20313
- var brandJsonPath = join32(PLATFORM_ROOT6, "config", "brand.json");
20314
- if (existsSync29(brandJsonPath)) {
20554
+ var brandJsonPath = join33(PLATFORM_ROOT6, "config", "brand.json");
20555
+ if (existsSync30(brandJsonPath)) {
20315
20556
  try {
20316
- const brand = JSON.parse(readFileSync32(brandJsonPath, "utf-8"));
20557
+ const brand = JSON.parse(readFileSync33(brandJsonPath, "utf-8"));
20317
20558
  if (brand.hostname) brandHostname = brand.hostname;
20318
20559
  } catch {
20319
20560
  }
@@ -20322,8 +20563,8 @@ var VERSION_FILE = resolve26(PLATFORM_ROOT6, `config/.${brandHostname}-version`)
20322
20563
  var PROCESS_STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
20323
20564
  var PROBE_TIMEOUT_MS = 1e3;
20324
20565
  function readVersion() {
20325
- if (!existsSync29(VERSION_FILE)) return "unknown";
20326
- return readFileSync32(VERSION_FILE, "utf-8").trim() || "unknown";
20566
+ if (!existsSync30(VERSION_FILE)) return "unknown";
20567
+ return readFileSync33(VERSION_FILE, "utf-8").trim() || "unknown";
20327
20568
  }
20328
20569
  async function probeConversationDb() {
20329
20570
  let session;
@@ -20502,7 +20743,7 @@ function managerLogFollowUrl(sessionId, opts) {
20502
20743
  }
20503
20744
 
20504
20745
  // server/routes/admin/linkedin-ingest.ts
20505
- var TAG28 = "[linkedin-ingest-route]";
20746
+ var TAG29 = "[linkedin-ingest-route]";
20506
20747
  var UUID2 = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
20507
20748
  var ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
20508
20749
  var LINKEDIN_URL = /^https:\/\/www\.linkedin\.com\//;
@@ -20606,29 +20847,29 @@ app39.post("/", requireAdminSession, async (c) => {
20606
20847
  try {
20607
20848
  body = await c.req.json();
20608
20849
  } catch {
20609
- console.error(TAG28 + " rejected status=400 reason=schema:body-not-json");
20850
+ console.error(TAG29 + " rejected status=400 reason=schema:body-not-json");
20610
20851
  return c.json({ ok: false, error: "schema", reason: "body-not-json" }, 400);
20611
20852
  }
20612
20853
  const v = validate(body);
20613
20854
  if (!v.ok) {
20614
- console.error(TAG28 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
20855
+ console.error(TAG29 + " rejected status=" + v.status + " reason=" + v.reason + " missing=" + v.missing.join(","));
20615
20856
  return c.json({ ok: false, error: v.error, reason: v.reason, missing: v.missing }, v.status);
20616
20857
  }
20617
20858
  const envelope = v.envelope;
20618
20859
  const cacheKey = c.var.cacheKey ?? "";
20619
20860
  const senderId = getAccountIdForSession(cacheKey) ?? "";
20620
20861
  if (!senderId) {
20621
- console.error(TAG28 + " rejected status=500 reason=admin-account-not-resolved");
20862
+ console.error(TAG29 + " rejected status=500 reason=admin-account-not-resolved");
20622
20863
  return c.json({ ok: false, error: "admin-account-not-resolved" }, 500);
20623
20864
  }
20624
20865
  const payloadBytes = JSON.stringify(envelope).length;
20625
20866
  console.log(
20626
- TAG28 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
20867
+ TAG29 + " received kind=" + envelope.kind + " account=" + senderId.slice(0, 8) + " pageUrl=" + envelope.pageUrl + " dispatchId=" + envelope.dispatchId + " payloadBytes=" + payloadBytes
20627
20868
  );
20628
20869
  const initialMessage = buildInitialMessage(envelope);
20629
20870
  const spawnStart = Date.now();
20630
20871
  const sessionId = randomUUID13();
20631
- console.log(TAG28 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
20872
+ console.log(TAG29 + " route target=rc-spawn dispatchId=" + envelope.dispatchId + " sessionId=" + sessionId.slice(0, 8));
20632
20873
  const spawned = await managerRcSpawn({
20633
20874
  sessionId,
20634
20875
  initialMessage,
@@ -20637,12 +20878,12 @@ app39.post("/", requireAdminSession, async (c) => {
20637
20878
  });
20638
20879
  if ("error" in spawned) {
20639
20880
  console.error(
20640
- TAG28 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
20881
+ TAG29 + " dispatch-failed dispatchId=" + envelope.dispatchId + " status=" + spawned.status + " ms=" + (Date.now() - spawnStart) + " message=" + spawned.error
20641
20882
  );
20642
20883
  return c.json({ ok: false, error: "dispatch-failed", upstreamStatus: spawned.status, detail: spawned.error }, 502);
20643
20884
  }
20644
20885
  console.log(
20645
- TAG28 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
20886
+ TAG29 + " dispatched dispatchId=" + envelope.dispatchId + " taskId=" + spawned.sessionId + " ms=" + (Date.now() - spawnStart)
20646
20887
  );
20647
20888
  return c.json({ ok: true, dispatchId: envelope.dispatchId, taskId: spawned.sessionId }, 202);
20648
20889
  });
@@ -20650,7 +20891,7 @@ var linkedin_ingest_default = app39;
20650
20891
 
20651
20892
  // server/routes/admin/post-turn-context.ts
20652
20893
  import neo4j3 from "neo4j-driver";
20653
- var TAG29 = "[post-turn-context]";
20894
+ var TAG30 = "[post-turn-context]";
20654
20895
  var STRIPPED_PROPERTIES2 = /* @__PURE__ */ new Set([
20655
20896
  "embedding",
20656
20897
  "passwordHash",
@@ -20692,7 +20933,7 @@ var app40 = new Hono();
20692
20933
  app40.get("/", async (c) => {
20693
20934
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
20694
20935
  if (!isLoopbackAddr3(remoteAddr)) {
20695
- console.error(`${TAG29} reject reason=non-loopback remoteAddr=${remoteAddr}`);
20936
+ console.error(`${TAG30} reject reason=non-loopback remoteAddr=${remoteAddr}`);
20696
20937
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
20697
20938
  }
20698
20939
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -20701,7 +20942,7 @@ app40.get("/", async (c) => {
20701
20942
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
20702
20943
  const offender = tokens.find((t) => !isLoopbackAddr3(t));
20703
20944
  if (offender !== void 0) {
20704
- console.error(`${TAG29} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
20945
+ console.error(`${TAG30} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
20705
20946
  return c.json({ error: "post-turn-context-loopback-only" }, 403);
20706
20947
  }
20707
20948
  }
@@ -20733,7 +20974,7 @@ app40.get("/", async (c) => {
20733
20974
  writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
20734
20975
  const total = Date.now() - started;
20735
20976
  console.log(
20736
- `${TAG29} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
20977
+ `${TAG30} sessionId=${sessionId} accountId=${accountId} writes=${writes.length} ms=${total}`
20737
20978
  );
20738
20979
  return c.json({
20739
20980
  writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
@@ -20742,7 +20983,7 @@ app40.get("/", async (c) => {
20742
20983
  const elapsed = Date.now() - started;
20743
20984
  const message = err instanceof Error ? err.message : String(err);
20744
20985
  console.error(
20745
- `${TAG29} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
20986
+ `${TAG30} neo4j-unreachable sessionId=${sessionId} ms=${elapsed} err="${message}"`
20746
20987
  );
20747
20988
  return c.json({ error: `post-turn-context unavailable: ${message}` }, 503);
20748
20989
  } finally {
@@ -20855,7 +21096,7 @@ function formatPreviousContext(writes) {
20855
21096
  }
20856
21097
 
20857
21098
  // server/routes/admin/public-session-context.ts
20858
- var TAG30 = "[public-session-context]";
21099
+ var TAG31 = "[public-session-context]";
20859
21100
  function isLoopbackAddr4(addr) {
20860
21101
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
20861
21102
  }
@@ -20863,7 +21104,7 @@ var app41 = new Hono();
20863
21104
  app41.get("/", async (c) => {
20864
21105
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
20865
21106
  if (!isLoopbackAddr4(remoteAddr)) {
20866
- console.error(`${TAG30} reject reason=non-loopback remoteAddr=${remoteAddr}`);
21107
+ console.error(`${TAG31} reject reason=non-loopback remoteAddr=${remoteAddr}`);
20867
21108
  return c.json({ error: "public-session-context-loopback-only" }, 403);
20868
21109
  }
20869
21110
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -20872,7 +21113,7 @@ app41.get("/", async (c) => {
20872
21113
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
20873
21114
  const offender = tokens.find((t) => !isLoopbackAddr4(t));
20874
21115
  if (offender !== void 0) {
20875
- console.error(`${TAG30} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
21116
+ console.error(`${TAG31} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
20876
21117
  return c.json({ error: "public-session-context-loopback-only" }, 403);
20877
21118
  }
20878
21119
  }
@@ -20886,14 +21127,14 @@ app41.get("/", async (c) => {
20886
21127
  const writes = await fetchSliceWrites(session, sliceToken, accountId);
20887
21128
  const total = Date.now() - started;
20888
21129
  console.log(
20889
- `${TAG30} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
21130
+ `${TAG31} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
20890
21131
  );
20891
21132
  return c.json({ writes });
20892
21133
  } catch (err) {
20893
21134
  const elapsed = Date.now() - started;
20894
21135
  const message = err instanceof Error ? err.message : String(err);
20895
21136
  console.error(
20896
- `${TAG30} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
21137
+ `${TAG31} neo4j-unreachable sliceToken=${sliceToken.slice(0, 8)} ms=${elapsed} err="${message}"`
20897
21138
  );
20898
21139
  return c.json({ error: `public-session-context unavailable: ${message}` }, 503);
20899
21140
  } finally {
@@ -20912,7 +21153,7 @@ function getWebchatGateway() {
20912
21153
  }
20913
21154
 
20914
21155
  // server/routes/admin/public-session-exit.ts
20915
- var TAG31 = "[public-session-exit-route]";
21156
+ var TAG32 = "[public-session-exit-route]";
20916
21157
  function isLoopbackAddr5(addr) {
20917
21158
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
20918
21159
  }
@@ -20920,7 +21161,7 @@ var app42 = new Hono();
20920
21161
  app42.post("/", async (c) => {
20921
21162
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
20922
21163
  if (!isLoopbackAddr5(remoteAddr)) {
20923
- console.error(`${TAG31} reject reason=non-loopback remoteAddr=${remoteAddr}`);
21164
+ console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
20924
21165
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
20925
21166
  }
20926
21167
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -20929,7 +21170,7 @@ app42.post("/", async (c) => {
20929
21170
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
20930
21171
  const offender = tokens.find((t) => !isLoopbackAddr5(t));
20931
21172
  if (offender !== void 0) {
20932
- console.error(`${TAG31} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
21173
+ console.error(`${TAG32} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
20933
21174
  return c.json({ error: "public-session-exit-loopback-only" }, 403);
20934
21175
  }
20935
21176
  }
@@ -20943,7 +21184,7 @@ app42.post("/", async (c) => {
20943
21184
  if (!sessionId) return c.json({ error: "sessionId required" }, 400);
20944
21185
  const gateway = getWebchatGateway();
20945
21186
  if (!gateway) {
20946
- console.error(`${TAG31} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
21187
+ console.error(`${TAG32} reject reason=gateway-unset sessionId=${sessionId.slice(0, 8)}`);
20947
21188
  return c.json({ error: "webchat-gateway-unset" }, 503);
20948
21189
  }
20949
21190
  gateway.handlePublicSessionExit(sessionId);
@@ -20952,7 +21193,7 @@ app42.post("/", async (c) => {
20952
21193
  var public_session_exit_default = app42;
20953
21194
 
20954
21195
  // server/routes/admin/access-session-evict.ts
20955
- var TAG32 = "[access-session-evict]";
21196
+ var TAG33 = "[access-session-evict]";
20956
21197
  function isLoopbackAddr6(addr) {
20957
21198
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
20958
21199
  }
@@ -20960,7 +21201,7 @@ var app43 = new Hono();
20960
21201
  app43.post("/", async (c) => {
20961
21202
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
20962
21203
  if (!isLoopbackAddr6(remoteAddr)) {
20963
- console.error(`${TAG32} reject reason=non-loopback remoteAddr=${remoteAddr}`);
21204
+ console.error(`${TAG33} reject reason=non-loopback remoteAddr=${remoteAddr}`);
20964
21205
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
20965
21206
  }
20966
21207
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -20969,7 +21210,7 @@ app43.post("/", async (c) => {
20969
21210
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
20970
21211
  const offender = tokens.find((t) => !isLoopbackAddr6(t));
20971
21212
  if (offender !== void 0) {
20972
- console.error(`${TAG32} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
21213
+ console.error(`${TAG33} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
20973
21214
  return c.json({ error: "access-session-evict-loopback-only" }, 403);
20974
21215
  }
20975
21216
  }
@@ -20982,13 +21223,13 @@ app43.post("/", async (c) => {
20982
21223
  const grantId = typeof body.grantId === "string" ? body.grantId.trim() : "";
20983
21224
  if (!grantId) return c.json({ error: "grantId required" }, 400);
20984
21225
  const dropped = evictAccessSessionsByGrant(grantId);
20985
- console.log(`${TAG32} grantId=${grantId} dropped=${dropped}`);
21226
+ console.log(`${TAG33} grantId=${grantId} dropped=${dropped}`);
20986
21227
  return c.json({ ok: true, dropped });
20987
21228
  });
20988
21229
  var access_session_evict_default = app43;
20989
21230
 
20990
21231
  // server/routes/admin/enrol-person.ts
20991
- var TAG33 = "[enrol]";
21232
+ var TAG34 = "[enrol]";
20992
21233
  function isLoopbackAddr7(addr) {
20993
21234
  return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
20994
21235
  }
@@ -20997,7 +21238,7 @@ var app44 = new Hono();
20997
21238
  app44.post("/", async (c) => {
20998
21239
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
20999
21240
  if (!isLoopbackAddr7(remoteAddr)) {
21000
- console.error(`${TAG33} reject reason=non-loopback remoteAddr=${remoteAddr}`);
21241
+ console.error(`${TAG34} reject reason=non-loopback remoteAddr=${remoteAddr}`);
21001
21242
  return c.json({ error: "enrol-person-loopback-only" }, 403);
21002
21243
  }
21003
21244
  const xffHeader = c.env?.incoming?.headers?.["x-forwarded-for"];
@@ -21006,7 +21247,7 @@ app44.post("/", async (c) => {
21006
21247
  const tokens = xffRaw.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
21007
21248
  const offender = tokens.find((t) => !isLoopbackAddr7(t));
21008
21249
  if (offender !== void 0) {
21009
- console.error(`${TAG33} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
21250
+ console.error(`${TAG34} reject reason=xff-non-loopback xff=${JSON.stringify(xffRaw)}`);
21010
21251
  return c.json({ error: "enrol-person-loopback-only" }, 403);
21011
21252
  }
21012
21253
  }
@@ -21031,7 +21272,7 @@ app44.post("/", async (c) => {
21031
21272
  }
21032
21273
  const accountId = process.env.ACCOUNT_ID ?? "";
21033
21274
  if (!accountId) {
21034
- console.error(`${TAG33} op=person result=no-account-id`);
21275
+ console.error(`${TAG34} op=person result=no-account-id`);
21035
21276
  return c.json({ error: "no-account-id" }, 500);
21036
21277
  }
21037
21278
  let personId;
@@ -21039,7 +21280,7 @@ app44.post("/", async (c) => {
21039
21280
  personId = await enrolPerson({ accountId, phone, email, agentSlug });
21040
21281
  } catch (err) {
21041
21282
  console.error(
21042
- `${TAG33} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
21283
+ `${TAG34} op=person result=write-failed agentSlug=${agentSlug} contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
21043
21284
  );
21044
21285
  return c.json({ error: "enrol-failed" }, 500);
21045
21286
  }
@@ -21049,11 +21290,11 @@ app44.post("/", async (c) => {
21049
21290
  if (g) grant = { grantId: g.grantId, status: g.status, contactValue: g.contactValue };
21050
21291
  } catch (err) {
21051
21292
  console.error(
21052
- `${TAG33} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
21293
+ `${TAG34} op=person result=grant-lookup-failed contact=${maskContact(email)} err="${err instanceof Error ? err.message : String(err)}"`
21053
21294
  );
21054
21295
  }
21055
21296
  console.log(
21056
- `${TAG33} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
21297
+ `${TAG34} op=person personId=${personId} account=${accountId} agentSlug=${agentSlug} contact=${maskContact(email)}`
21057
21298
  );
21058
21299
  return c.json({ personId, grant }, 200);
21059
21300
  });
@@ -21099,8 +21340,8 @@ app45.post("/launch", requireAdminSession, async (c) => {
21099
21340
  var browser_default = app45;
21100
21341
 
21101
21342
  // server/routes/admin/calendar.ts
21102
- import { existsSync as existsSync30 } from "fs";
21103
- import { join as join34 } from "path";
21343
+ import { existsSync as existsSync31 } from "fs";
21344
+ import { join as join35 } from "path";
21104
21345
 
21105
21346
  // server/lib/calendar-ics.ts
21106
21347
  var CRLF = "\r\n";
@@ -21199,8 +21440,8 @@ function countVEvents(ics) {
21199
21440
  }
21200
21441
 
21201
21442
  // server/lib/calendar-availability.ts
21202
- import { readFileSync as readFileSync33 } from "fs";
21203
- import { join as join33 } from "path";
21443
+ import { readFileSync as readFileSync34 } from "fs";
21444
+ import { join as join34 } from "path";
21204
21445
  var AVAILABILITY_FILENAME = "calendar-availability.json";
21205
21446
  var REQUIRED_KEYS = [
21206
21447
  "timezone",
@@ -21209,10 +21450,10 @@ var REQUIRED_KEYS = [
21209
21450
  "weekly"
21210
21451
  ];
21211
21452
  function readAvailabilityConfig(accountDir) {
21212
- const path3 = join33(accountDir, AVAILABILITY_FILENAME);
21453
+ const path3 = join34(accountDir, AVAILABILITY_FILENAME);
21213
21454
  let raw;
21214
21455
  try {
21215
- raw = readFileSync33(path3, "utf-8");
21456
+ raw = readFileSync34(path3, "utf-8");
21216
21457
  } catch {
21217
21458
  throw new Error(`availability not configured: ${path3} not found`);
21218
21459
  }
@@ -21571,7 +21812,7 @@ app46.get("/booking-link", requireAdminSession, (c) => {
21571
21812
  console.error('[calendar] op=booking-link-fail err="no account configured"');
21572
21813
  return c.json({ bookingDomain: null });
21573
21814
  }
21574
- if (!existsSync30(join34(account.accountDir, AVAILABILITY_FILENAME))) {
21815
+ if (!existsSync31(join35(account.accountDir, AVAILABILITY_FILENAME))) {
21575
21816
  console.log("[calendar] op=booking-link bookingDomain=none source=availability-config");
21576
21817
  return c.json({ bookingDomain: null });
21577
21818
  }
@@ -21607,7 +21848,7 @@ function toNum(v) {
21607
21848
  }
21608
21849
 
21609
21850
  // server/routes/admin/tasks-list.ts
21610
- var TAG34 = "[task-timer]";
21851
+ var TAG35 = "[task-timer]";
21611
21852
  var COMPLETED = /* @__PURE__ */ new Set(["completed"]);
21612
21853
  var HIDDEN_FROM_OPEN = /* @__PURE__ */ new Set(["completed", "cancelled"]);
21613
21854
  var app47 = new Hono();
@@ -21615,7 +21856,7 @@ app47.get("/", requireAdminSession, async (c) => {
21615
21856
  const cacheKey = c.var.cacheKey;
21616
21857
  const accountId = getAccountIdForSession(cacheKey);
21617
21858
  if (!accountId) {
21618
- console.error(`${TAG34} op=list auth-rejected reason="no account for session"`);
21859
+ console.error(`${TAG35} op=list auth-rejected reason="no account for session"`);
21619
21860
  return c.json({ error: "Account not found for session" }, 401);
21620
21861
  }
21621
21862
  const session = getSession();
@@ -21653,10 +21894,10 @@ app47.get("/", requireAdminSession, async (c) => {
21653
21894
  if (COMPLETED.has(status)) completed.push(row);
21654
21895
  else if (!HIDDEN_FROM_OPEN.has(status)) open.push(row);
21655
21896
  }
21656
- console.log(`${TAG34} op=list account=${accountId} open=${open.length} completed=${completed.length}`);
21897
+ console.log(`${TAG35} op=list account=${accountId} open=${open.length} completed=${completed.length}`);
21657
21898
  return c.json({ open, completed });
21658
21899
  } catch (err) {
21659
- console.error(`${TAG34} op=list error="${err instanceof Error ? err.message : String(err)}"`);
21900
+ console.error(`${TAG35} op=list error="${err instanceof Error ? err.message : String(err)}"`);
21660
21901
  return c.json({ error: "tasks-list-failed" }, 500);
21661
21902
  } finally {
21662
21903
  await session.close();
@@ -21666,7 +21907,7 @@ var tasks_list_default = app47;
21666
21907
 
21667
21908
  // server/routes/admin/task-timer-start.ts
21668
21909
  import { randomUUID as randomUUID14 } from "crypto";
21669
- var TAG35 = "[task-timer]";
21910
+ var TAG36 = "[task-timer]";
21670
21911
  var app48 = new Hono();
21671
21912
  app48.post("/", requireAdminSession, async (c) => {
21672
21913
  const cacheKey = c.var.cacheKey;
@@ -21688,7 +21929,7 @@ app48.post("/", requireAdminSession, async (c) => {
21688
21929
  { taskId, accountId }
21689
21930
  );
21690
21931
  if (target.records.length === 0) {
21691
- console.error(`${TAG35} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
21932
+ console.error(`${TAG36} op=start taskId=${taskId} accountId=${accountId} result=task-not-found`);
21692
21933
  return c.json({ error: "task-not-found" }, 404);
21693
21934
  }
21694
21935
  const open = await session.run(
@@ -21700,7 +21941,7 @@ app48.post("/", requireAdminSession, async (c) => {
21700
21941
  const priorEntryId = open.records[0]?.get("entryId");
21701
21942
  const priorStartedAt = open.records[0]?.get("startedAt");
21702
21943
  if (priorEntryId) {
21703
- console.log(`${TAG35} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
21944
+ console.log(`${TAG36} op=start taskId=${taskId} accountId=${accountId} result=already-running`);
21704
21945
  return c.json({ ok: true, running: true, entryId: priorEntryId, startedAt: priorStartedAt });
21705
21946
  }
21706
21947
  const entryId = randomUUID14();
@@ -21710,10 +21951,10 @@ app48.post("/", requireAdminSession, async (c) => {
21710
21951
  CREATE (te)-[:LOGGED_AGAINST]->(t)`,
21711
21952
  { taskId, accountId, entryId, now }
21712
21953
  );
21713
- console.log(`${TAG35} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
21954
+ console.log(`${TAG36} op=opened taskId=${taskId} entryId=${entryId} startedAt=${now}`);
21714
21955
  return c.json({ ok: true, running: true, entryId, startedAt: now });
21715
21956
  } catch (err) {
21716
- console.error(`${TAG35} op=start error="${err instanceof Error ? err.message : String(err)}"`);
21957
+ console.error(`${TAG36} op=start error="${err instanceof Error ? err.message : String(err)}"`);
21717
21958
  return c.json({ error: "task-timer-start-failed" }, 500);
21718
21959
  } finally {
21719
21960
  await session.close();
@@ -21723,7 +21964,7 @@ var task_timer_start_default = app48;
21723
21964
 
21724
21965
  // server/routes/admin/task-timer-stop.ts
21725
21966
  import neo4j5 from "neo4j-driver";
21726
- var TAG36 = "[task-timer]";
21967
+ var TAG37 = "[task-timer]";
21727
21968
  var app49 = new Hono();
21728
21969
  app49.post("/", requireAdminSession, async (c) => {
21729
21970
  const cacheKey = c.var.cacheKey;
@@ -21755,7 +21996,7 @@ app49.post("/", requireAdminSession, async (c) => {
21755
21996
  { taskId, accountId }
21756
21997
  );
21757
21998
  const secondsLogged2 = toNum(cur.records[0]?.get("secondsLogged"));
21758
- console.log(`${TAG36} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
21999
+ console.log(`${TAG37} op=stop taskId=${taskId} entryId=none seconds=0 totalAfter=${secondsLogged2}`);
21759
22000
  return c.json({ ok: true, running: false, seconds: 0, secondsLogged: secondsLogged2 });
21760
22001
  }
21761
22002
  const seconds = secondsBetween(startedAt, now);
@@ -21778,11 +22019,11 @@ app49.post("/", requireAdminSession, async (c) => {
21778
22019
  const sumEntries = toNum(verify.records[0]?.get("sumEntries"));
21779
22020
  const sumAdjustments = toNum(verify.records[0]?.get("sumAdjustments"));
21780
22021
  const secondsLogged = toNum(verify.records[0]?.get("secondsLogged"));
21781
- console.log(`${TAG36} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
21782
- console.log(`${TAG36} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
22022
+ console.log(`${TAG37} op=stop taskId=${taskId} entryId=${entryId} seconds=${seconds} totalAfter=${secondsLogged}`);
22023
+ console.log(`${TAG37} op=persisted taskId=${taskId} entryId=${entryId} sumEntries=${sumEntries} sumAdjustments=${sumAdjustments} secondsLogged=${secondsLogged}`);
21783
22024
  return c.json({ ok: true, running: false, seconds, secondsLogged });
21784
22025
  } catch (err) {
21785
- console.error(`${TAG36} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
22026
+ console.error(`${TAG37} op=stop error="${err instanceof Error ? err.message : String(err)}"`);
21786
22027
  return c.json({ error: "task-timer-stop-failed" }, 500);
21787
22028
  } finally {
21788
22029
  await session.close();
@@ -21791,7 +22032,7 @@ app49.post("/", requireAdminSession, async (c) => {
21791
22032
  var task_timer_stop_default = app49;
21792
22033
 
21793
22034
  // server/routes/admin/task-complete.ts
21794
- var TAG37 = "[task-timer]";
22035
+ var TAG38 = "[task-timer]";
21795
22036
  var app50 = new Hono();
21796
22037
  app50.post("/", requireAdminSession, async (c) => {
21797
22038
  const cacheKey = c.var.cacheKey;
@@ -21818,10 +22059,10 @@ app50.post("/", requireAdminSession, async (c) => {
21818
22059
  return c.json({ error: "task-not-found" }, 404);
21819
22060
  }
21820
22061
  const secondsLogged = toNum(result.records[0].get("secondsLogged"));
21821
- console.log(`${TAG37} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
22062
+ console.log(`${TAG38} op=complete taskId=${taskId} status=completed secondsLogged=${secondsLogged}`);
21822
22063
  return c.json({ ok: true, status: "completed", secondsLogged });
21823
22064
  } catch (err) {
21824
- console.error(`${TAG37} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
22065
+ console.error(`${TAG38} op=complete error="${err instanceof Error ? err.message : String(err)}"`);
21825
22066
  return c.json({ error: "task-complete-failed" }, 500);
21826
22067
  } finally {
21827
22068
  await session.close();
@@ -21832,7 +22073,7 @@ var task_complete_default = app50;
21832
22073
  // server/routes/admin/task-time-adjust.ts
21833
22074
  import { randomUUID as randomUUID15 } from "crypto";
21834
22075
  import neo4j6 from "neo4j-driver";
21835
- var TAG38 = "[task-time-adjust]";
22076
+ var TAG39 = "[task-time-adjust]";
21836
22077
  var app51 = new Hono();
21837
22078
  app51.post("/", requireAdminSession, async (c) => {
21838
22079
  const cacheKey = c.var.cacheKey;
@@ -21842,22 +22083,22 @@ app51.post("/", requireAdminSession, async (c) => {
21842
22083
  try {
21843
22084
  body = await c.req.json();
21844
22085
  } catch {
21845
- console.error(`${TAG38} op=reject reason=bad-json`);
22086
+ console.error(`${TAG39} op=reject reason=bad-json`);
21846
22087
  return c.json({ error: "invalid-json" }, 400);
21847
22088
  }
21848
22089
  const taskId = typeof body.taskId === "string" ? body.taskId : "";
21849
22090
  if (!taskId) {
21850
- console.error(`${TAG38} op=reject reason=no-task`);
22091
+ console.error(`${TAG39} op=reject reason=no-task`);
21851
22092
  return c.json({ error: "taskId required" }, 400);
21852
22093
  }
21853
22094
  const newSeconds = body.newSeconds;
21854
22095
  if (typeof newSeconds !== "number" || !Number.isInteger(newSeconds) || newSeconds < 0) {
21855
- console.error(`${TAG38} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
22096
+ console.error(`${TAG39} op=reject reason=invalid-seconds taskId=${taskId} accountId=${accountId}`);
21856
22097
  return c.json({ error: "newSeconds must be a non-negative integer" }, 400);
21857
22098
  }
21858
22099
  const adjustmentId = randomUUID15();
21859
22100
  const now = (/* @__PURE__ */ new Date()).toISOString();
21860
- console.log(`${TAG38} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
22101
+ console.log(`${TAG39} op=request adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId} newSeconds=${newSeconds}`);
21861
22102
  const session = getSession();
21862
22103
  try {
21863
22104
  const guard = await session.run(
@@ -21867,12 +22108,12 @@ app51.post("/", requireAdminSession, async (c) => {
21867
22108
  { taskId, accountId }
21868
22109
  );
21869
22110
  if (guard.records.length === 0) {
21870
- console.error(`${TAG38} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
22111
+ console.error(`${TAG39} op=reject reason=no-task adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
21871
22112
  return c.json({ error: "task-not-found" }, 404);
21872
22113
  }
21873
22114
  const openCount = toNum(guard.records[0].get("openCount"));
21874
22115
  if (openCount > 0) {
21875
- console.error(`${TAG38} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
22116
+ console.error(`${TAG39} op=reject reason=running adjustmentId=${adjustmentId} taskId=${taskId} accountId=${accountId}`);
21876
22117
  return c.json({ error: "task-timer-running" }, 409);
21877
22118
  }
21878
22119
  const previousSeconds = toNum(guard.records[0].get("previousSeconds"));
@@ -21898,10 +22139,10 @@ app51.post("/", requireAdminSession, async (c) => {
21898
22139
  }
21899
22140
  );
21900
22141
  const secondsLoggedAfter = toNum(write.records[0]?.get("secondsLoggedAfter"));
21901
- console.log(`${TAG38} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
22142
+ console.log(`${TAG39} op=persisted adjustmentId=${adjustmentId} previousSeconds=${previousSeconds} newSeconds=${newSeconds} delta=${delta} secondsLoggedAfter=${secondsLoggedAfter}`);
21902
22143
  return c.json({ ok: true, secondsLogged: secondsLoggedAfter });
21903
22144
  } catch (err) {
21904
- console.error(`${TAG38} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
22145
+ console.error(`${TAG39} op=error adjustmentId=${adjustmentId} taskId=${taskId} error="${err instanceof Error ? err.message : String(err)}"`);
21905
22146
  return c.json({ error: "task-time-adjust-failed" }, 500);
21906
22147
  } finally {
21907
22148
  await session.close();
@@ -21909,57 +22150,150 @@ app51.post("/", requireAdminSession, async (c) => {
21909
22150
  });
21910
22151
  var task_time_adjust_default = app51;
21911
22152
 
21912
- // server/routes/admin/index.ts
22153
+ // server/routes/admin/activity.ts
22154
+ import { readdirSync as readdirSync22 } from "fs";
21913
22155
  var app52 = new Hono();
21914
- app52.route("/session", session_default);
21915
- app52.route("/accounts", accounts_default);
21916
- app52.route("/logs", logs_default);
21917
- app52.route("/claude-info", claude_info_default);
21918
- app52.route("/attachment", attachment_default);
21919
- app52.route("/agents", agents_default);
21920
- app52.route("/sessions", sessions_default);
21921
- app52.route("/claude-sessions", claude_sessions_default);
21922
- app52.route("/log-ingest", log_ingest_default);
21923
- app52.route("/events", events_default);
21924
- app52.route("/files", files_default);
21925
- app52.route("/graph-search", graph_search_default);
21926
- app52.route("/graph-subgraph", graph_subgraph_default);
21927
- app52.route("/graph-delete", graph_delete_default);
21928
- app52.route("/graph-restore", graph_restore_default);
21929
- app52.route("/graph-labels-in-graph", graph_labels_in_graph_default);
21930
- app52.route("/graph-default-view", graph_default_view_default);
21931
- app52.route("/sidebar-artefacts", sidebar_artefacts_default);
21932
- app52.route("/sidebar-sessions", sidebar_sessions_default);
21933
- app52.route("/session-delete", session_delete_default);
21934
- app52.route("/session-stop", session_stop_default);
21935
- app52.route("/session-archive", session_archive_default);
21936
- app52.route("/session-rename", session_rename_default);
21937
- app52.route("/session-usage", session_usage_default);
21938
- app52.route("/browser", browser_default);
21939
- app52.route("/session-rc-spawn", session_rc_spawn_default);
21940
- app52.route("/session-reseat", session_reseat_default);
21941
- app52.route("/system-stats", system_stats_default);
21942
- app52.route("/health-brand", health_default2);
21943
- app52.route("/linkedin-ingest", linkedin_ingest_default);
21944
- app52.route("/post-turn-context", post_turn_context_default);
21945
- app52.route("/public-session-context", public_session_context_default);
21946
- app52.route("/public-session-exit", public_session_exit_default);
21947
- app52.route("/access-session-evict", access_session_evict_default);
21948
- app52.route("/enrol-person", enrol_person_default);
21949
- app52.route("/calendar", calendar_default);
21950
- app52.route("/tasks-list", tasks_list_default);
21951
- app52.route("/task-timer-start", task_timer_start_default);
21952
- app52.route("/task-timer-stop", task_timer_stop_default);
21953
- app52.route("/task-complete", task_complete_default);
21954
- app52.route("/task-time-adjust", task_time_adjust_default);
21955
- var admin_default = app52;
22156
+ var TAG40 = "[activity]";
22157
+ function resolveHouseAccountId(accounts) {
22158
+ const houses = accounts.filter((a) => a.config.role === "house");
22159
+ if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
22160
+ if (houses.length > 1) return { accountId: null, reason: "multiple-houses" };
22161
+ if (accounts.length === 1) return { accountId: accounts[0].accountId, reason: "sole-account" };
22162
+ return { accountId: null, reason: "no-house" };
22163
+ }
22164
+ function requestToken() {
22165
+ return Math.random().toString(16).slice(2, 10);
22166
+ }
22167
+ var short = (id) => id ? id.slice(0, 8) : "unset";
22168
+ function countAccountDirsOnDisk() {
22169
+ try {
22170
+ return readdirSync22(ACCOUNTS_DIR, { withFileTypes: true }).filter(
22171
+ (e) => e.isDirectory() && !e.name.startsWith(".")
22172
+ ).length;
22173
+ } catch {
22174
+ return null;
22175
+ }
22176
+ }
22177
+ app52.get("/", requireAdminSession, async (c) => {
22178
+ const req = requestToken();
22179
+ const cacheKey = c.var.cacheKey;
22180
+ const caller2 = getAccountIdForSession(cacheKey) ?? null;
22181
+ const valid = listValidAccounts();
22182
+ const house = resolveHouseAccountId(valid);
22183
+ const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
22184
+ console.log(
22185
+ `${TAG40} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
22186
+ );
22187
+ if (!isHouse) {
22188
+ const reason = house.accountId === null ? house.reason : "not-house";
22189
+ console.error(
22190
+ `${TAG40} op=gate req=${req} decision=deny reason=${reason} caller=${short(caller2)} houseAcct=${short(house.accountId)} accounts=${valid.length}`
22191
+ );
22192
+ return c.json({ error: "house-only" }, 403);
22193
+ }
22194
+ console.log(`${TAG40} op=gate req=${req} decision=allow caller=${short(caller2)} via=${house.reason}`);
22195
+ const onDisk = countAccountDirsOnDisk();
22196
+ console.log(
22197
+ `${TAG40} op=accounts req=${req} onDisk=${onDisk ?? "unknown"} valid=${valid.length} ids=${valid.map((a) => short(a.accountId)).join(",")}`
22198
+ );
22199
+ const start = Date.now();
22200
+ let res;
22201
+ try {
22202
+ res = await fetch(`${managerBase("activity:wrapper")}/activity`, {
22203
+ signal: AbortSignal.timeout(3e4)
22204
+ });
22205
+ } catch (err) {
22206
+ console.error(
22207
+ `${TAG40} op=manager-fail req=${req} reason=unreachable err=${err instanceof Error ? err.message : String(err)}`
22208
+ );
22209
+ return c.json({ error: "manager-unreachable" }, 502);
22210
+ }
22211
+ if (res.status !== 200) {
22212
+ console.error(`${TAG40} op=manager-fail req=${req} reason=status status=${res.status}`);
22213
+ return c.json({ error: `manager-status-${res.status}` }, 502);
22214
+ }
22215
+ const body = await res.json().catch(() => null);
22216
+ if (!body || !Array.isArray(body.rows)) {
22217
+ console.error(`${TAG40} op=manager-fail req=${req} reason=bad-json`);
22218
+ return c.json({ error: "manager-bad-json" }, 502);
22219
+ }
22220
+ const rows = body.rows;
22221
+ const census = body.census ?? null;
22222
+ const untaggedCount = rows.filter((r) => r.accountId === null).length;
22223
+ const meteringFailed = rows.filter((r) => r.meteringError !== null).length;
22224
+ const censusAgeMs = census ? Date.now() - census.sampleAtMs : null;
22225
+ console.log(
22226
+ `${TAG40} op=census req=${req} ageMs=${censusAgeMs ?? "none"} live=${census?.live ?? "none"} cpuNull=${census?.cpuNull ?? "none"}`
22227
+ );
22228
+ console.log(
22229
+ `${TAG40} op=response req=${req} rows=${rows.length} accounts=${valid.length} untagged=${untaggedCount} meteringFailed=${meteringFailed} ms=${Date.now() - start}`
22230
+ );
22231
+ return c.json({
22232
+ rows,
22233
+ census,
22234
+ censusAgeMs,
22235
+ accounts: {
22236
+ onDisk,
22237
+ valid: valid.length,
22238
+ ids: valid.map((a) => a.accountId),
22239
+ untaggedCount
22240
+ }
22241
+ });
22242
+ });
22243
+ var activity_default = app52;
22244
+
22245
+ // server/routes/admin/index.ts
22246
+ var app53 = new Hono();
22247
+ app53.route("/session", session_default);
22248
+ app53.route("/accounts", accounts_default);
22249
+ app53.route("/logs", logs_default);
22250
+ app53.route("/claude-info", claude_info_default);
22251
+ app53.route("/attachment", attachment_default);
22252
+ app53.route("/agents", agents_default);
22253
+ app53.route("/sessions", sessions_default);
22254
+ app53.route("/claude-sessions", claude_sessions_default);
22255
+ app53.route("/log-ingest", log_ingest_default);
22256
+ app53.route("/events", events_default);
22257
+ app53.route("/files", files_default);
22258
+ app53.route("/graph-search", graph_search_default);
22259
+ app53.route("/graph-subgraph", graph_subgraph_default);
22260
+ app53.route("/graph-delete", graph_delete_default);
22261
+ app53.route("/graph-restore", graph_restore_default);
22262
+ app53.route("/graph-labels-in-graph", graph_labels_in_graph_default);
22263
+ app53.route("/graph-default-view", graph_default_view_default);
22264
+ app53.route("/sidebar-artefacts", sidebar_artefacts_default);
22265
+ app53.route("/sidebar-sessions", sidebar_sessions_default);
22266
+ app53.route("/session-delete", session_delete_default);
22267
+ app53.route("/session-stop", session_stop_default);
22268
+ app53.route("/session-archive", session_archive_default);
22269
+ app53.route("/session-rename", session_rename_default);
22270
+ app53.route("/session-usage", session_usage_default);
22271
+ app53.route("/browser", browser_default);
22272
+ app53.route("/session-rc-spawn", session_rc_spawn_default);
22273
+ app53.route("/session-reseat", session_reseat_default);
22274
+ app53.route("/system-stats", system_stats_default);
22275
+ app53.route("/health-brand", health_default2);
22276
+ app53.route("/linkedin-ingest", linkedin_ingest_default);
22277
+ app53.route("/post-turn-context", post_turn_context_default);
22278
+ app53.route("/public-session-context", public_session_context_default);
22279
+ app53.route("/public-session-exit", public_session_exit_default);
22280
+ app53.route("/access-session-evict", access_session_evict_default);
22281
+ app53.route("/enrol-person", enrol_person_default);
22282
+ app53.route("/calendar", calendar_default);
22283
+ app53.route("/tasks-list", tasks_list_default);
22284
+ app53.route("/task-timer-start", task_timer_start_default);
22285
+ app53.route("/task-timer-stop", task_timer_stop_default);
22286
+ app53.route("/task-complete", task_complete_default);
22287
+ app53.route("/task-time-adjust", task_time_adjust_default);
22288
+ app53.route("/activity", activity_default);
22289
+ var admin_default = app53;
21956
22290
 
21957
22291
  // server/routes/access/verify-token.ts
21958
- var TAG39 = "[access-verify]";
22292
+ var TAG41 = "[access-verify]";
21959
22293
  var MINT_TAG = "[access-session-mint]";
21960
22294
  var COOKIE_NAME = "__access_session";
21961
- var app53 = new Hono();
21962
- app53.post("/", async (c) => {
22295
+ var app54 = new Hono();
22296
+ app54.post("/", async (c) => {
21963
22297
  const ip = c.var.clientIp || "unknown";
21964
22298
  let body;
21965
22299
  try {
@@ -21974,39 +22308,39 @@ app53.post("/", async (c) => {
21974
22308
  }
21975
22309
  const rateMsg = checkAccessRateLimit(ip, agentSlug);
21976
22310
  if (rateMsg) {
21977
- console.error(`${TAG39} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
22311
+ console.error(`${TAG41} grantId=- agentSlug=${agentSlug} result=rate-limited ip=${ip}`);
21978
22312
  return c.json({ error: rateMsg }, 429);
21979
22313
  }
21980
22314
  const grant = await findGrantByMagicToken(token);
21981
22315
  if (!grant) {
21982
22316
  recordAccessFailedAttempt(ip, agentSlug);
21983
- console.error(`${TAG39} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
22317
+ console.error(`${TAG41} grantId=- agentSlug=${agentSlug} result=notfound ip=${ip}`);
21984
22318
  return c.json({ error: "invalid-or-expired-link" }, 401);
21985
22319
  }
21986
22320
  if (grant.agentSlug !== agentSlug) {
21987
22321
  recordAccessFailedAttempt(ip, agentSlug);
21988
22322
  console.error(
21989
- `${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
22323
+ `${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=agent-mismatch grantAgent=${grant.agentSlug} ip=${ip}`
21990
22324
  );
21991
22325
  return c.json({ error: "invalid-or-expired-link" }, 401);
21992
22326
  }
21993
22327
  if (grant.status === "expired" || grant.status === "revoked") {
21994
22328
  recordAccessFailedAttempt(ip, agentSlug);
21995
22329
  console.error(
21996
- `${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
22330
+ `${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired status=${grant.status} ip=${ip}`
21997
22331
  );
21998
22332
  return c.json({ error: "access-no-longer-valid" }, 401);
21999
22333
  }
22000
22334
  if (grant.expiresAt !== null && grant.expiresAt < Date.now()) {
22001
22335
  recordAccessFailedAttempt(ip, agentSlug);
22002
22336
  console.error(
22003
- `${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
22337
+ `${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=expired reason=expiresAt-past ip=${ip}`
22004
22338
  );
22005
22339
  return c.json({ error: "access-no-longer-valid" }, 401);
22006
22340
  }
22007
22341
  if (!grant.sliceToken) {
22008
22342
  console.error(
22009
- `${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
22343
+ `${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=no-slice-token reason=schema-violation`
22010
22344
  );
22011
22345
  return c.json({ error: "grant-misconfigured" }, 500);
22012
22346
  }
@@ -22022,12 +22356,12 @@ app53.post("/", async (c) => {
22022
22356
  await consumeMagicTokenAndActivate(grant.grantId);
22023
22357
  } catch (err) {
22024
22358
  console.error(
22025
- `${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
22359
+ `${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=consume-failed err="${err instanceof Error ? err.message : String(err)}"`
22026
22360
  );
22027
22361
  return c.json({ error: "verification-failed" }, 500);
22028
22362
  }
22029
22363
  clearAccessRateLimit(ip, agentSlug);
22030
- console.log(`${TAG39} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
22364
+ console.log(`${TAG41} grantId=${grant.grantId} agentSlug=${agentSlug} result=ok ip=${ip}`);
22031
22365
  console.log(
22032
22366
  `${MINT_TAG} grantId=${grant.grantId} sliceToken=${grant.sliceToken.slice(0, 8)} agentSlug=${agentSlug} personId=${grant.personId ?? "none"}`
22033
22367
  );
@@ -22041,7 +22375,7 @@ app53.post("/", async (c) => {
22041
22375
  displayName: grant.displayName
22042
22376
  });
22043
22377
  });
22044
- var verify_token_default = app53;
22378
+ var verify_token_default = app54;
22045
22379
 
22046
22380
  // app/lib/access-email.ts
22047
22381
  import { spawn as spawn2 } from "child_process";
@@ -22103,10 +22437,10 @@ async function sendMagicLinkEmail(payload) {
22103
22437
  }
22104
22438
 
22105
22439
  // server/routes/access/request-magic-link.ts
22106
- var TAG40 = "[access-request-link]";
22107
- var app54 = new Hono();
22440
+ var TAG42 = "[access-request-link]";
22441
+ var app55 = new Hono();
22108
22442
  var VISITOR_MESSAGE = "If that email is on the invite list, a fresh link is on the way.";
22109
- app54.post("/", async (c) => {
22443
+ app55.post("/", async (c) => {
22110
22444
  let body;
22111
22445
  try {
22112
22446
  body = await c.req.json();
@@ -22120,18 +22454,18 @@ app54.post("/", async (c) => {
22120
22454
  }
22121
22455
  const rateMsg = checkRequestLinkRateLimit(contactValue);
22122
22456
  if (rateMsg) {
22123
- console.error(`${TAG40} contactValue=${maskContact(contactValue)} result=rate-limited`);
22457
+ console.error(`${TAG42} contactValue=${maskContact(contactValue)} result=rate-limited`);
22124
22458
  return c.json({ error: rateMsg }, 429);
22125
22459
  }
22126
22460
  recordRequestLinkAttempt(contactValue);
22127
22461
  const accountId = process.env.ACCOUNT_ID ?? "";
22128
22462
  if (!accountId) {
22129
- console.error(`${TAG40} contactValue=${maskContact(contactValue)} result=no-account-id`);
22463
+ console.error(`${TAG42} contactValue=${maskContact(contactValue)} result=no-account-id`);
22130
22464
  return c.json({ message: VISITOR_MESSAGE }, 200);
22131
22465
  }
22132
22466
  const grant = await findActiveGrantByContact(contactValue, agentSlug, accountId);
22133
22467
  if (!grant) {
22134
- console.log(`${TAG40} contactValue=${maskContact(contactValue)} result=notfound`);
22468
+ console.log(`${TAG42} contactValue=${maskContact(contactValue)} result=notfound`);
22135
22469
  return c.json({ message: VISITOR_MESSAGE }, 200);
22136
22470
  }
22137
22471
  let token;
@@ -22139,7 +22473,7 @@ app54.post("/", async (c) => {
22139
22473
  token = await generateNewMagicToken(grant.grantId);
22140
22474
  } catch (err) {
22141
22475
  console.error(
22142
- `${TAG40} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
22476
+ `${TAG42} contactValue=${maskContact(contactValue)} result=mint-failed err="${err instanceof Error ? err.message : String(err)}"`
22143
22477
  );
22144
22478
  return c.json({ message: VISITOR_MESSAGE }, 200);
22145
22479
  }
@@ -22171,25 +22505,25 @@ app54.post("/", async (c) => {
22171
22505
  });
22172
22506
  if (!sendResult.ok) {
22173
22507
  console.error(
22174
- `${TAG40} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
22508
+ `${TAG42} contactValue=${maskContact(contactValue)} result=send-failed err="${sendResult.error}"`
22175
22509
  );
22176
22510
  return c.json({ message: VISITOR_MESSAGE }, 200);
22177
22511
  }
22178
22512
  console.log(
22179
- `${TAG40} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
22513
+ `${TAG42} contactValue=${maskContact(contactValue)} result=ok messageId=${sendResult.messageId}`
22180
22514
  );
22181
22515
  return c.json({ message: VISITOR_MESSAGE }, 200);
22182
22516
  });
22183
- var request_magic_link_default = app54;
22517
+ var request_magic_link_default = app55;
22184
22518
 
22185
22519
  // server/routes/access/index.ts
22186
- var app55 = new Hono();
22187
- app55.route("/verify-token", verify_token_default);
22188
- app55.route("/request-magic-link", request_magic_link_default);
22189
- var access_default = app55;
22520
+ var app56 = new Hono();
22521
+ app56.route("/verify-token", verify_token_default);
22522
+ app56.route("/request-magic-link", request_magic_link_default);
22523
+ var access_default = app56;
22190
22524
 
22191
22525
  // server/routes/sites.ts
22192
- import { existsSync as existsSync31, readFileSync as readFileSync34, realpathSync as realpathSync7, statSync as statSync12 } from "fs";
22526
+ import { existsSync as existsSync32, readFileSync as readFileSync35, realpathSync as realpathSync7, statSync as statSync12 } from "fs";
22193
22527
  import { resolve as resolve28 } from "path";
22194
22528
  var SAFE_SEG_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
22195
22529
  var MIME = {
@@ -22221,8 +22555,8 @@ function getExt(p) {
22221
22555
  if (idx < p.lastIndexOf("/")) return "";
22222
22556
  return p.slice(idx).toLowerCase();
22223
22557
  }
22224
- var app56 = new Hono();
22225
- app56.get("/:rel{.*}", (c) => {
22558
+ var app57 = new Hono();
22559
+ app57.get("/:rel{.*}", (c) => {
22226
22560
  const reqPath = c.req.path;
22227
22561
  const rawRel = c.req.param("rel") ?? "";
22228
22562
  const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
@@ -22255,7 +22589,7 @@ app56.get("/:rel{.*}", (c) => {
22255
22589
  }
22256
22590
  let stat8;
22257
22591
  try {
22258
- stat8 = existsSync31(filePath) ? statSync12(filePath) : null;
22592
+ stat8 = existsSync32(filePath) ? statSync12(filePath) : null;
22259
22593
  } catch {
22260
22594
  stat8 = null;
22261
22595
  }
@@ -22274,7 +22608,7 @@ app56.get("/:rel{.*}", (c) => {
22274
22608
  console.error(`[sites] path-traversal-rejected path=${reqPath} reason=escape status=403`);
22275
22609
  return c.text("Forbidden", 403);
22276
22610
  }
22277
- if (!existsSync31(filePath)) {
22611
+ if (!existsSync32(filePath)) {
22278
22612
  console.error(`[sites] not-found path=${reqPath} status=404`);
22279
22613
  return c.text("Not found", 404);
22280
22614
  }
@@ -22293,7 +22627,7 @@ app56.get("/:rel{.*}", (c) => {
22293
22627
  }
22294
22628
  let body;
22295
22629
  try {
22296
- body = readFileSync34(realPath);
22630
+ body = readFileSync35(realPath);
22297
22631
  } catch (err) {
22298
22632
  const code = err?.code;
22299
22633
  if (code === "EISDIR") {
@@ -22325,11 +22659,11 @@ app56.get("/:rel{.*}", (c) => {
22325
22659
  "X-Content-Type-Options": "nosniff"
22326
22660
  });
22327
22661
  });
22328
- var sites_default = app56;
22662
+ var sites_default = app57;
22329
22663
 
22330
22664
  // app/lib/visitor-token.ts
22331
- import { createHmac, randomBytes, timingSafeEqual } from "crypto";
22332
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync35, writeFileSync as writeFileSync11 } from "fs";
22665
+ import { createHmac, randomBytes as randomBytes2, timingSafeEqual } from "crypto";
22666
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync36, writeFileSync as writeFileSync12 } from "fs";
22333
22667
  import { dirname as dirname12 } from "path";
22334
22668
  var TOKEN_PREFIX = "v1.";
22335
22669
  var SECRET_BYTES = 32;
@@ -22338,21 +22672,21 @@ var cachedSecret = null;
22338
22672
  function getSecret() {
22339
22673
  if (cachedSecret) return cachedSecret;
22340
22674
  try {
22341
- const hex2 = readFileSync35(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
22675
+ const hex2 = readFileSync36(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
22342
22676
  if (hex2.length === SECRET_BYTES * 2) {
22343
22677
  cachedSecret = Buffer.from(hex2, "hex");
22344
22678
  return cachedSecret;
22345
22679
  }
22346
22680
  } catch {
22347
22681
  }
22348
- const fresh = randomBytes(SECRET_BYTES).toString("hex");
22682
+ const fresh = randomBytes2(SECRET_BYTES).toString("hex");
22349
22683
  try {
22350
- mkdirSync7(dirname12(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
22351
- writeFileSync11(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
22684
+ mkdirSync8(dirname12(VISITOR_TOKEN_SECRET_FILE), { recursive: true, mode: 448 });
22685
+ writeFileSync12(VISITOR_TOKEN_SECRET_FILE, fresh, { mode: 384, flag: "wx" });
22352
22686
  console.log(`[visitor-token] secret minted path=${VISITOR_TOKEN_SECRET_FILE}`);
22353
22687
  } catch {
22354
22688
  }
22355
- const hex = readFileSync35(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
22689
+ const hex = readFileSync36(VISITOR_TOKEN_SECRET_FILE, "utf-8").trim();
22356
22690
  cachedSecret = Buffer.from(hex, "hex");
22357
22691
  return cachedSecret;
22358
22692
  }
@@ -22405,8 +22739,8 @@ var VISITOR_COOKIE_NAME = "mxy_v";
22405
22739
  var VISITOR_COOKIE_MAX_AGE_SECONDS = Math.floor(DEFAULT_TTL_MS / 1e3);
22406
22740
 
22407
22741
  // app/lib/brand-config.ts
22408
- import { existsSync as existsSync32, readFileSync as readFileSync36 } from "fs";
22409
- import { join as join35 } from "path";
22742
+ import { existsSync as existsSync33, readFileSync as readFileSync37 } from "fs";
22743
+ import { join as join36 } from "path";
22410
22744
  var cached2 = null;
22411
22745
  var cachedAttempted = false;
22412
22746
  function readBrandConfig() {
@@ -22414,10 +22748,10 @@ function readBrandConfig() {
22414
22748
  cachedAttempted = true;
22415
22749
  const platformRoot5 = process.env.MAXY_PLATFORM_ROOT;
22416
22750
  if (!platformRoot5) return null;
22417
- const brandPath = join35(platformRoot5, "config", "brand.json");
22418
- if (!existsSync32(brandPath)) return null;
22751
+ const brandPath = join36(platformRoot5, "config", "brand.json");
22752
+ if (!existsSync33(brandPath)) return null;
22419
22753
  try {
22420
- cached2 = JSON.parse(readFileSync36(brandPath, "utf-8"));
22754
+ cached2 = JSON.parse(readFileSync37(brandPath, "utf-8"));
22421
22755
  return cached2;
22422
22756
  } catch {
22423
22757
  return null;
@@ -22425,7 +22759,7 @@ function readBrandConfig() {
22425
22759
  }
22426
22760
 
22427
22761
  // server/routes/visitor-consent.ts
22428
- var app57 = new Hono();
22762
+ var app58 = new Hono();
22429
22763
  var CONSENT_COOKIE_NAME = "mxy_consent";
22430
22764
  var CONSENT_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365;
22431
22765
  var DEFAULT_CONSENT_COPY = {
@@ -22470,17 +22804,17 @@ function siteSlugFromReferer(referer) {
22470
22804
  return "";
22471
22805
  }
22472
22806
  }
22473
- app57.options("/consent", (c) => {
22807
+ app58.options("/consent", (c) => {
22474
22808
  const origin = getOrigin(c);
22475
22809
  setCorsHeaders(c, origin);
22476
22810
  return c.body(null, 204);
22477
22811
  });
22478
- app57.options("/brand-config", (c) => {
22812
+ app58.options("/brand-config", (c) => {
22479
22813
  const origin = getOrigin(c);
22480
22814
  setCorsHeaders(c, origin);
22481
22815
  return c.body(null, 204);
22482
22816
  });
22483
- app57.post("/consent", async (c) => {
22817
+ app58.post("/consent", async (c) => {
22484
22818
  const origin = getOrigin(c);
22485
22819
  setCorsHeaders(c, origin);
22486
22820
  let raw;
@@ -22520,7 +22854,7 @@ app57.post("/consent", async (c) => {
22520
22854
  console.log(`[consent] ${parsed.decision} site=${site} brand=${brandName} tokenBound=${tokenBound}`);
22521
22855
  return c.body(null, 204);
22522
22856
  });
22523
- app57.get("/brand-config", (c) => {
22857
+ app58.get("/brand-config", (c) => {
22524
22858
  const origin = getOrigin(c);
22525
22859
  setCorsHeaders(c, origin);
22526
22860
  const brand = readBrandConfig();
@@ -22530,7 +22864,7 @@ app57.get("/brand-config", (c) => {
22530
22864
  c.header("Cache-Control", "public, max-age=300");
22531
22865
  return c.json({ consent: { copy, palette } });
22532
22866
  });
22533
- var visitor_consent_default = app57;
22867
+ var visitor_consent_default = app58;
22534
22868
 
22535
22869
  // server/routes/listings.ts
22536
22870
  function getCookie(headerValue, name) {
@@ -22557,8 +22891,8 @@ function appendConsentParams(pageUrl, token) {
22557
22891
  }
22558
22892
  var SAFE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,118}[a-z0-9])?$/;
22559
22893
  var CHAT_SESSION_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
22560
- var app58 = new Hono();
22561
- app58.get("/:slug/click", async (c) => {
22894
+ var app59 = new Hono();
22895
+ app59.get("/:slug/click", async (c) => {
22562
22896
  const slug = c.req.param("slug") ?? "";
22563
22897
  const rawSession = c.req.query("session") ?? "";
22564
22898
  const sessionKey = CHAT_SESSION_KEY_RE.test(rawSession) ? rawSession : "invalid";
@@ -22622,10 +22956,10 @@ app58.get("/:slug/click", async (c) => {
22622
22956
  console.log(`[property-card-click] sessionKey=${sessionKey} listingSlug=${slug} consent=${consentCookie ?? "absent"} ts=${(/* @__PURE__ */ new Date()).toISOString()}`);
22623
22957
  return c.redirect(redirectUrl, 302);
22624
22958
  });
22625
- var listings_default = app58;
22959
+ var listings_default = app59;
22626
22960
 
22627
22961
  // server/routes/visitor-event.ts
22628
- var app59 = new Hono();
22962
+ var app60 = new Hono();
22629
22963
  var BOT_UA_RE = /\b(bot|crawl|spider|slurp|headlesschrome|phantomjs|googlebot|bingbot|yandex|baiduspider|ahrefsbot|semrushbot|mj12bot|dotbot|petalbot)\b/i;
22630
22964
  var buckets = /* @__PURE__ */ new Map();
22631
22965
  var RATE_LIMIT = 60;
@@ -22692,12 +23026,12 @@ function originAllowed(origin, allowlist) {
22692
23026
  return false;
22693
23027
  }
22694
23028
  }
22695
- app59.options("/event", (c) => {
23029
+ app60.options("/event", (c) => {
22696
23030
  const origin = getOrigin2(c);
22697
23031
  setCorsHeaders2(c, origin);
22698
23032
  return c.body(null, 204);
22699
23033
  });
22700
- app59.post("/event", async (c) => {
23034
+ app60.post("/event", async (c) => {
22701
23035
  const origin = getOrigin2(c);
22702
23036
  setCorsHeaders2(c, origin);
22703
23037
  const ua = c.req.header("user-agent") ?? "";
@@ -22902,17 +23236,17 @@ async function writeEvent(opts) {
22902
23236
  );
22903
23237
  }
22904
23238
  }
22905
- var visitor_event_default = app59;
23239
+ var visitor_event_default = app60;
22906
23240
 
22907
23241
  // server/routes/session.ts
22908
23242
  import { resolve as resolve29 } from "path";
22909
- import { existsSync as existsSync33, writeFileSync as writeFileSync12, mkdirSync as mkdirSync8 } from "fs";
23243
+ import { existsSync as existsSync34, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9 } from "fs";
22910
23244
  var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
22911
23245
  function writeBrandingCache(accountId, agentSlug, branding) {
22912
23246
  try {
22913
23247
  const cacheDir = resolve29(MAXY_DIR, "branding-cache", accountId);
22914
- mkdirSync8(cacheDir, { recursive: true });
22915
- writeFileSync12(resolve29(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
23248
+ mkdirSync9(cacheDir, { recursive: true });
23249
+ writeFileSync13(resolve29(cacheDir, `${agentSlug}.json`), JSON.stringify(branding), "utf-8");
22916
23250
  } catch (err) {
22917
23251
  console.error(`[branding] cache write failed: ${err instanceof Error ? err.message : String(err)}`);
22918
23252
  }
@@ -22948,8 +23282,8 @@ function withVisitorCookie(response, visitorId) {
22948
23282
  headers
22949
23283
  });
22950
23284
  }
22951
- var app60 = new Hono();
22952
- app60.post("/", async (c) => {
23285
+ var app61 = new Hono();
23286
+ app61.post("/", async (c) => {
22953
23287
  let body;
22954
23288
  try {
22955
23289
  body = await c.req.json();
@@ -22990,7 +23324,7 @@ app60.post("/", async (c) => {
22990
23324
  let agentConfig = null;
22991
23325
  if (account) {
22992
23326
  const agentDir = resolve29(account.accountDir, "agents", agentSlug);
22993
- if (!existsSync33(agentDir) || !existsSync33(resolve29(agentDir, "config.json"))) {
23327
+ if (!existsSync34(agentDir) || !existsSync34(resolve29(agentDir, "config.json"))) {
22994
23328
  return c.json({ error: "Agent not found" }, 404);
22995
23329
  }
22996
23330
  agentConfig = resolveAgentConfig(account.accountDir, agentSlug);
@@ -23096,7 +23430,7 @@ app60.post("/", async (c) => {
23096
23430
  newVisitorId
23097
23431
  );
23098
23432
  });
23099
- var session_default2 = app60;
23433
+ var session_default2 = app61;
23100
23434
 
23101
23435
  // server/lib/calendar-slots.ts
23102
23436
  var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
@@ -23179,17 +23513,17 @@ function computeOpenSlots(config, busy, fromISO, toISO) {
23179
23513
  }
23180
23514
 
23181
23515
  // server/routes/calendar-public.ts
23182
- var app61 = new Hono();
23516
+ var app62 = new Hono();
23183
23517
  function setCors(c) {
23184
23518
  c.header("Access-Control-Allow-Origin", "*");
23185
23519
  c.header("Access-Control-Allow-Methods", "GET, OPTIONS");
23186
23520
  c.header("Access-Control-Allow-Headers", "content-type");
23187
23521
  }
23188
- app61.options("/free-busy", (c) => {
23522
+ app62.options("/free-busy", (c) => {
23189
23523
  setCors(c);
23190
23524
  return c.body(null, 204);
23191
23525
  });
23192
- app61.get("/free-busy", async (c) => {
23526
+ app62.get("/free-busy", async (c) => {
23193
23527
  setCors(c);
23194
23528
  const from = c.req.query("from");
23195
23529
  const to = c.req.query("to");
@@ -23235,10 +23569,10 @@ app61.get("/free-busy", async (c) => {
23235
23569
  await session.close();
23236
23570
  }
23237
23571
  });
23238
- var calendar_public_default = app61;
23572
+ var calendar_public_default = app62;
23239
23573
 
23240
23574
  // app/lib/timeentry-census.ts
23241
- var TAG41 = "[timeentry-census]";
23575
+ var TAG43 = "[timeentry-census]";
23242
23576
  function reconcileTimeEntries(rows, now, horizonMs) {
23243
23577
  const openEntries = rows.openEntries.length;
23244
23578
  let oldestOpenAgeMs = 0;
@@ -23278,12 +23612,12 @@ async function runTimeEntryCensusOnce(session, now, horizonMs) {
23278
23612
  sumAdjustments: toNum(r.get("sumAdjustments"))
23279
23613
  }));
23280
23614
  const finding = reconcileTimeEntries({ openEntries, taskSums }, now, horizonMs);
23281
- const line = `${TAG41} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
23615
+ const line = `${TAG43} openEntries=${finding.openEntries} oldestOpenAgeMin=${finding.oldestOpenAgeMin} maxOpenPerAccount=${finding.maxOpenPerAccount} driftTasks=${finding.driftTasks}`;
23282
23616
  if (finding.alarm) console.error(`${line} alarm=true`);
23283
23617
  else console.log(line);
23284
23618
  return finding;
23285
23619
  } catch (err) {
23286
- console.error(`${TAG41} error="${err instanceof Error ? err.message : String(err)}"`);
23620
+ console.error(`${TAG43} error="${err instanceof Error ? err.message : String(err)}"`);
23287
23621
  return null;
23288
23622
  }
23289
23623
  }
@@ -23297,13 +23631,13 @@ function startTimeEntryCensus(openSession, opts = {}) {
23297
23631
  try {
23298
23632
  session = openSession();
23299
23633
  } catch (err) {
23300
- console.error(`${TAG41} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
23634
+ console.error(`${TAG43} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`);
23301
23635
  return;
23302
23636
  }
23303
23637
  try {
23304
23638
  await runTimeEntryCensusOnce(session, Date.now(), horizonMs);
23305
23639
  } catch (err) {
23306
- console.error(`${TAG41} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
23640
+ console.error(`${TAG43} tick-failed error="${err instanceof Error ? err.message : String(err)}"`);
23307
23641
  } finally {
23308
23642
  try {
23309
23643
  await session.close();
@@ -23321,8 +23655,181 @@ function startTimeEntryCensus(openSession, opts = {}) {
23321
23655
  return () => clearInterval(id);
23322
23656
  }
23323
23657
 
23658
+ // ../lib/ledger-core/dist/reconcile.js
23659
+ var LEDGER_INDEX_NAMES = [
23660
+ "invoice_account_confirmation_unique",
23661
+ "cash_entry_account_entryid_unique",
23662
+ "cash_entry_account",
23663
+ "invoice_line_account",
23664
+ "invoice_payment_account",
23665
+ "credit_account"
23666
+ ];
23667
+ function countSuspectDuplicates(keys) {
23668
+ const groups = /* @__PURE__ */ new Map();
23669
+ for (const k of keys) {
23670
+ const composite = `${k.invoiceId}|${k.amount}|${k.date}`;
23671
+ const ids = groups.get(composite) ?? /* @__PURE__ */ new Set();
23672
+ ids.add(k.paymentId);
23673
+ groups.set(composite, ids);
23674
+ }
23675
+ let total = 0;
23676
+ for (const ids of groups.values())
23677
+ total += Math.max(0, ids.size - 1);
23678
+ return total;
23679
+ }
23680
+ function reconcileLedger(rows, _now) {
23681
+ const suspectDuplicates = countSuspectDuplicates(rows.paymentKeys);
23682
+ const alarm = rows.orphanPayments > 0 || rows.storedBalanceProps > 0 || suspectDuplicates > 0 || rows.declaredNotLive.length > 0;
23683
+ return {
23684
+ invoices: rows.invoices,
23685
+ payments: rows.payments,
23686
+ orphanPayments: rows.orphanPayments,
23687
+ storedBalanceProps: rows.storedBalanceProps,
23688
+ suspectDuplicates,
23689
+ declaredNotLive: rows.declaredNotLive,
23690
+ alarm
23691
+ };
23692
+ }
23693
+ function formatCensusLine(f) {
23694
+ return `[ledger-census] invoices=${f.invoices} payments=${f.payments} orphanPayments=${f.orphanPayments} storedBalanceProps=${f.storedBalanceProps} suspectDuplicates=${f.suspectDuplicates} declaredNotLive=${f.declaredNotLive.length === 0 ? "none" : f.declaredNotLive.join(",")}`;
23695
+ }
23696
+
23697
+ // app/lib/ledger-census.ts
23698
+ var TAG44 = "[ledger-census]";
23699
+ function toNum2(v) {
23700
+ if (typeof v === "number") return v;
23701
+ if (v && typeof v === "object" && "toNumber" in v) {
23702
+ return v.toNumber();
23703
+ }
23704
+ return 0;
23705
+ }
23706
+ async function runLedgerCensusOnce(session, now) {
23707
+ try {
23708
+ const counts = await session.run(
23709
+ `MATCH (i:Invoice|InboundInvoice) WITH count(i) AS invoices
23710
+ OPTIONAL MATCH (p:InvoicePayment)
23711
+ RETURN invoices, count(p) AS payments`
23712
+ );
23713
+ const orphans = await session.run(
23714
+ `MATCH (p:InvoicePayment)
23715
+ WHERE NOT ( (:Invoice|InboundInvoice)-[:HAS_PAYMENT]->(p) )
23716
+ RETURN count(p) AS orphanPayments`
23717
+ );
23718
+ const stored = await session.run(
23719
+ `MATCH (i:Invoice|InboundInvoice)
23720
+ WHERE i.outstanding IS NOT NULL OR i.balance IS NOT NULL OR i.amountPaid IS NOT NULL
23721
+ RETURN count(i) AS storedBalanceProps`
23722
+ );
23723
+ const keys = await session.run(
23724
+ `MATCH (i:Invoice|InboundInvoice)-[:HAS_PAYMENT]->(p:InvoicePayment)
23725
+ RETURN i.confirmationNumber AS invoiceId, p.paymentId AS paymentId,
23726
+ p.amount AS amount, p.date AS date`
23727
+ );
23728
+ const indexes = await session.run(`SHOW INDEXES YIELD name RETURN collect(name) AS names`);
23729
+ const live = new Set(indexes.records[0]?.get("names") ?? []);
23730
+ const finding = reconcileLedger(
23731
+ {
23732
+ invoices: toNum2(counts.records[0]?.get("invoices")),
23733
+ payments: toNum2(counts.records[0]?.get("payments")),
23734
+ orphanPayments: toNum2(orphans.records[0]?.get("orphanPayments")),
23735
+ storedBalanceProps: toNum2(stored.records[0]?.get("storedBalanceProps")),
23736
+ paymentKeys: keys.records.map((r) => ({
23737
+ invoiceId: r.get("invoiceId") ?? "",
23738
+ paymentId: r.get("paymentId") ?? "",
23739
+ amount: toNum2(r.get("amount")),
23740
+ date: r.get("date") ?? ""
23741
+ })),
23742
+ declaredNotLive: LEDGER_INDEX_NAMES.filter((n) => !live.has(n))
23743
+ },
23744
+ now
23745
+ );
23746
+ const line = formatCensusLine(finding);
23747
+ if (finding.alarm) console.error(`${line} alarm=true`);
23748
+ else console.log(line);
23749
+ return finding;
23750
+ } catch (err) {
23751
+ console.error(`${TAG44} error="${err instanceof Error ? err.message : String(err)}"`);
23752
+ return null;
23753
+ }
23754
+ }
23755
+ var DEFAULT_INTERVAL_MS2 = 15 * 60 * 1e3;
23756
+ function startLedgerCensus(openSession, opts = {}) {
23757
+ const intervalMs = opts.intervalMs ?? DEFAULT_INTERVAL_MS2;
23758
+ const tick = async () => {
23759
+ let session;
23760
+ try {
23761
+ session = openSession();
23762
+ } catch (err) {
23763
+ console.error(
23764
+ `${TAG44} open-session-failed error="${err instanceof Error ? err.message : String(err)}"`
23765
+ );
23766
+ return;
23767
+ }
23768
+ try {
23769
+ await runLedgerCensusOnce(session, Date.now());
23770
+ } catch (err) {
23771
+ console.error(
23772
+ `${TAG44} tick-failed error="${err instanceof Error ? err.message : String(err)}"`
23773
+ );
23774
+ } finally {
23775
+ try {
23776
+ await session.close();
23777
+ } catch {
23778
+ }
23779
+ }
23780
+ };
23781
+ void tick();
23782
+ const id = setInterval(() => {
23783
+ void tick();
23784
+ }, intervalMs);
23785
+ if (typeof id.unref === "function") {
23786
+ ;
23787
+ id.unref();
23788
+ }
23789
+ return () => clearInterval(id);
23790
+ }
23791
+
23792
+ // app/lib/conversation-audit.ts
23793
+ var TAG45 = "[conversation-audit]";
23794
+ async function runConversationAudit() {
23795
+ const session = getSession();
23796
+ try {
23797
+ const res = await session.run(
23798
+ `MATCH (a:Conversation {channel: 'whatsapp'})
23799
+ WHERE a.channelAddress =~ '[0-9]+'
23800
+ WITH collect(a.channelAddress) AS anchored
23801
+ MATCH (c:Conversation {channel: 'whatsapp'})
23802
+ WITH anchored,
23803
+ count(*) AS total,
23804
+ sum(CASE WHEN c.channelAddress = 'default' THEN 1 ELSE 0 END) AS unpairable,
23805
+ collect(CASE WHEN c.channelAddress =~ 'default:[0-9]+'
23806
+ THEN substring(c.channelAddress, 8) END) AS forensic
23807
+ RETURN total,
23808
+ unpairable,
23809
+ size([p IN forensic WHERE p IS NOT NULL AND NOT p IN anchored]) AS unreconciled`,
23810
+ {}
23811
+ );
23812
+ const rec = res.records[0];
23813
+ const result = {
23814
+ total: Number(rec?.get("total") ?? 0),
23815
+ unreconciled: Number(rec?.get("unreconciled") ?? 0),
23816
+ unpairable: Number(rec?.get("unpairable") ?? 0)
23817
+ };
23818
+ console.error(
23819
+ `${TAG45} channel=whatsapp total=${result.total} unreconciled=${result.unreconciled} unpairable=${result.unpairable}`
23820
+ );
23821
+ return result;
23822
+ } catch (err) {
23823
+ const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
23824
+ console.error(`${TAG45} op=failed reason=${reason}`);
23825
+ return null;
23826
+ } finally {
23827
+ await session.close();
23828
+ }
23829
+ }
23830
+
23324
23831
  // app/lib/graph-health.ts
23325
- var import_dist4 = __toESM(require_dist4(), 1);
23832
+ var import_dist5 = __toESM(require_dist4(), 1);
23326
23833
  var HOUR_MS = 60 * 60 * 1e3;
23327
23834
  function renderLabelTop(rows) {
23328
23835
  return rows.map((b) => {
@@ -23367,7 +23874,7 @@ async function runGraphHealthTick() {
23367
23874
  console.error(
23368
23875
  `[graph-health] userprofile-multi accounts=${upAccounts} top=${upTop.length > 0 ? upTop.join(",") : "none"}`
23369
23876
  );
23370
- const indexed = [...import_dist4.VECTOR_INDEXED_LABELS];
23877
+ const indexed = [...import_dist5.VECTOR_INDEXED_LABELS];
23371
23878
  const embCount = await session.run(
23372
23879
  `MATCH (n) WHERE n.embedding IS NULL AND any(l IN labels(n) WHERE l IN $indexed)
23373
23880
  RETURN count(n) AS total`,
@@ -23666,8 +24173,8 @@ async function migrateUploads(opts = {}) {
23666
24173
 
23667
24174
  // app/lib/migrate-admin-webchat-sidecars.ts
23668
24175
  import { readdir as readdir6, readFile as readFile6, rename as rename3, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
23669
- import { existsSync as existsSync34 } from "fs";
23670
- import { join as join36 } from "path";
24176
+ import { existsSync as existsSync35 } from "fs";
24177
+ import { join as join37 } from "path";
23671
24178
  var ADMIN_ROLE2 = "admin";
23672
24179
  var WEBCHAT_CHANNEL2 = "webchat";
23673
24180
  var SESSION_META_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.meta\.json$/i;
@@ -23696,7 +24203,7 @@ async function writeRaw(path3, obj) {
23696
24203
  await rename3(tmp, path3);
23697
24204
  } catch (err) {
23698
24205
  try {
23699
- if (existsSync34(tmp)) await unlink3(tmp);
24206
+ if (existsSync35(tmp)) await unlink3(tmp);
23700
24207
  } catch {
23701
24208
  }
23702
24209
  throw err;
@@ -23712,7 +24219,7 @@ async function collectLiveSidecars(projectsRoot) {
23712
24219
  }
23713
24220
  for (const slug of slugs) {
23714
24221
  if (!slug.isDirectory()) continue;
23715
- const slugDir = join36(projectsRoot, slug.name);
24222
+ const slugDir = join37(projectsRoot, slug.name);
23716
24223
  let entries;
23717
24224
  try {
23718
24225
  entries = await readdir6(slugDir, { withFileTypes: true });
@@ -23721,9 +24228,9 @@ async function collectLiveSidecars(projectsRoot) {
23721
24228
  }
23722
24229
  for (const entry of entries) {
23723
24230
  if (entry.isFile() && SESSION_META_RE.test(entry.name)) {
23724
- out.push(join36(slugDir, entry.name));
24231
+ out.push(join37(slugDir, entry.name));
23725
24232
  } else if (entry.isDirectory() && entry.name === "subagents") {
23726
- const subDir = join36(slugDir, entry.name);
24233
+ const subDir = join37(slugDir, entry.name);
23727
24234
  let subs;
23728
24235
  try {
23729
24236
  subs = await readdir6(subDir, { withFileTypes: true });
@@ -23731,7 +24238,7 @@ async function collectLiveSidecars(projectsRoot) {
23731
24238
  continue;
23732
24239
  }
23733
24240
  for (const s of subs) {
23734
- if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join36(subDir, s.name));
24241
+ if (s.isFile() && SESSION_META_RE.test(s.name)) out.push(join37(subDir, s.name));
23735
24242
  }
23736
24243
  }
23737
24244
  }
@@ -23743,7 +24250,7 @@ function shortId(path3) {
23743
24250
  return base.slice(0, 8);
23744
24251
  }
23745
24252
  async function migrateAdminWebchatSidecars(opts = {}) {
23746
- const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join36(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
24253
+ const projectsRoot = opts.projectsRoot ?? (process.env.CLAUDE_CONFIG_DIR ? join37(process.env.CLAUDE_CONFIG_DIR, "projects") : null) ?? "";
23747
24254
  const usersFile = opts.usersFile ?? USERS_FILE;
23748
24255
  const accountId = opts.accountId ?? resolveAccount()?.accountId ?? null;
23749
24256
  const resolveName = opts.resolveName ?? defaultResolveName;
@@ -23935,7 +24442,7 @@ var InboundHub = class {
23935
24442
  };
23936
24443
 
23937
24444
  // app/lib/whatsapp/gateway/wa-gateway.ts
23938
- var import_dist5 = __toESM(require_dist(), 1);
24445
+ var import_dist6 = __toESM(require_dist(), 1);
23939
24446
 
23940
24447
  // node_modules/hono/dist/utils/stream.js
23941
24448
  var StreamingApi = class {
@@ -24088,8 +24595,8 @@ var streamSSE = (c, cb, onError) => {
24088
24595
 
24089
24596
  // app/lib/whatsapp/gateway/routes.ts
24090
24597
  function createWaChannelRoutes(deps) {
24091
- const app63 = new Hono();
24092
- app63.get("/wa-channel/inbound", (c) => {
24598
+ const app64 = new Hono();
24599
+ app64.get("/wa-channel/inbound", (c) => {
24093
24600
  const senderId = c.req.query("senderId");
24094
24601
  if (!senderId) return c.json({ error: "senderId required" }, 400);
24095
24602
  return streamSSE(c, async (stream2) => {
@@ -24107,7 +24614,7 @@ function createWaChannelRoutes(deps) {
24107
24614
  }
24108
24615
  });
24109
24616
  });
24110
- app63.post("/wa-channel/reply", async (c) => {
24617
+ app64.post("/wa-channel/reply", async (c) => {
24111
24618
  const body = await c.req.json().catch(() => null);
24112
24619
  const senderId = body?.senderId;
24113
24620
  const text = body?.text;
@@ -24128,7 +24635,7 @@ function createWaChannelRoutes(deps) {
24128
24635
  console.error(`[whatsapp-native] op=reply-dispatch senderId=${senderId} bytes=${bytes}`);
24129
24636
  return c.json({ ok: true });
24130
24637
  });
24131
- app63.post("/wa-channel/reply-document", async (c) => {
24638
+ app64.post("/wa-channel/reply-document", async (c) => {
24132
24639
  const body = await c.req.json().catch(() => null);
24133
24640
  const senderId = body?.senderId;
24134
24641
  const files = body?.files;
@@ -24167,7 +24674,7 @@ function createWaChannelRoutes(deps) {
24167
24674
  }
24168
24675
  return c.json({ ok: true, results });
24169
24676
  });
24170
- app63.post("/wa-channel/ready", async (c) => {
24677
+ app64.post("/wa-channel/ready", async (c) => {
24171
24678
  const body = await c.req.json().catch(() => null);
24172
24679
  const senderId = body?.senderId;
24173
24680
  if (typeof senderId !== "string") {
@@ -24176,7 +24683,7 @@ function createWaChannelRoutes(deps) {
24176
24683
  deps.onReady?.(senderId);
24177
24684
  return c.json({ ok: true });
24178
24685
  });
24179
- app63.post("/wa-channel/received", async (c) => {
24686
+ app64.post("/wa-channel/received", async (c) => {
24180
24687
  const body = await c.req.json().catch(() => null);
24181
24688
  const senderId = body?.senderId;
24182
24689
  const waMessageId = body?.waMessageId;
@@ -24186,7 +24693,7 @@ function createWaChannelRoutes(deps) {
24186
24693
  deps.onReceived?.(senderId, waMessageId);
24187
24694
  return c.json({ ok: true });
24188
24695
  });
24189
- app63.post("/wa-channel/turn-end", async (c) => {
24696
+ app64.post("/wa-channel/turn-end", async (c) => {
24190
24697
  const body = await c.req.json().catch(() => null);
24191
24698
  const senderId = body?.senderId;
24192
24699
  const sessionId = body?.sessionId;
@@ -24219,7 +24726,7 @@ function createWaChannelRoutes(deps) {
24219
24726
  console.error(`[whatsapp-native] op=turn-end sessionId=${sid} replied=no delivered=none`);
24220
24727
  return c.json({ ok: true, delivered: "none" });
24221
24728
  });
24222
- return app63;
24729
+ return app64;
24223
24730
  }
24224
24731
 
24225
24732
  // app/lib/whatsapp/gateway/wa-gateway.ts
@@ -24321,7 +24828,7 @@ var WaGateway = class {
24321
24828
  const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
24322
24829
  const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
24323
24830
  console.error(
24324
- `[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist5.INJECTION_RULE_CAP}`
24831
+ `[preference-inject] op=inject channel=wa accountId=${input.effectiveAccountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
24325
24832
  );
24326
24833
  }
24327
24834
  this.hub.deliver(
@@ -24594,12 +25101,12 @@ var InboundHub2 = class {
24594
25101
  };
24595
25102
 
24596
25103
  // app/lib/webchat/gateway/webchat-gateway.ts
24597
- var import_dist6 = __toESM(require_dist(), 1);
25104
+ var import_dist7 = __toESM(require_dist(), 1);
24598
25105
 
24599
25106
  // app/lib/webchat/gateway/routes.ts
24600
25107
  function createWebchatChannelRoutes(deps) {
24601
- const app63 = new Hono();
24602
- app63.get("/webchat-channel/inbound", (c) => {
25108
+ const app64 = new Hono();
25109
+ app64.get("/webchat-channel/inbound", (c) => {
24603
25110
  const key = c.req.query("key");
24604
25111
  if (!key) return c.json({ error: "key required" }, 400);
24605
25112
  return streamSSE(c, async (stream2) => {
@@ -24617,7 +25124,7 @@ function createWebchatChannelRoutes(deps) {
24617
25124
  }
24618
25125
  });
24619
25126
  });
24620
- app63.post("/webchat-channel/reply", async (c) => {
25127
+ app64.post("/webchat-channel/reply", async (c) => {
24621
25128
  const body = await c.req.json().catch(() => null);
24622
25129
  const key = body?.key;
24623
25130
  const text = body?.text;
@@ -24627,7 +25134,7 @@ function createWebchatChannelRoutes(deps) {
24627
25134
  deps.onReply?.(key, text);
24628
25135
  return c.json({ ok: true });
24629
25136
  });
24630
- app63.post("/webchat-channel/connector-auth", async (c) => {
25137
+ app64.post("/webchat-channel/connector-auth", async (c) => {
24631
25138
  const body = await c.req.json().catch(() => null);
24632
25139
  const key = body?.key;
24633
25140
  const sessionId = body?.sessionId;
@@ -24640,7 +25147,7 @@ function createWebchatChannelRoutes(deps) {
24640
25147
  const result = await deps.onConnectorAuth({ key, sessionId, name, completed });
24641
25148
  return c.json(result);
24642
25149
  });
24643
- app63.post("/webchat-channel/ready", async (c) => {
25150
+ app64.post("/webchat-channel/ready", async (c) => {
24644
25151
  const body = await c.req.json().catch(() => null);
24645
25152
  const key = body?.key;
24646
25153
  if (typeof key !== "string") {
@@ -24649,7 +25156,7 @@ function createWebchatChannelRoutes(deps) {
24649
25156
  deps.onReady?.(key);
24650
25157
  return c.json({ ok: true });
24651
25158
  });
24652
- app63.post("/webchat-channel/permission-request", async (c) => {
25159
+ app64.post("/webchat-channel/permission-request", async (c) => {
24653
25160
  const body = await c.req.json().catch(() => null);
24654
25161
  const key = body?.key;
24655
25162
  const requestId = body?.request_id;
@@ -24663,7 +25170,7 @@ function createWebchatChannelRoutes(deps) {
24663
25170
  const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
24664
25171
  return c.json(verdict);
24665
25172
  });
24666
- app63.post("/webchat-channel/received", async (c) => {
25173
+ app64.post("/webchat-channel/received", async (c) => {
24667
25174
  const body = await c.req.json().catch(() => null);
24668
25175
  const key = body?.key;
24669
25176
  const messageId = body?.messageId;
@@ -24673,7 +25180,7 @@ function createWebchatChannelRoutes(deps) {
24673
25180
  deps.onReceived?.(key, messageId);
24674
25181
  return c.json({ ok: true });
24675
25182
  });
24676
- app63.post("/webchat-channel/turn-end", async (c) => {
25183
+ app64.post("/webchat-channel/turn-end", async (c) => {
24677
25184
  const body = await c.req.json().catch(() => null);
24678
25185
  const key = body?.key;
24679
25186
  const sessionId = body?.sessionId;
@@ -24696,7 +25203,7 @@ function createWebchatChannelRoutes(deps) {
24696
25203
  console.error(`[webchat-native] op=turn-end channel=webchat key=${k} sessionId=${sid} replied=no delivered=none`);
24697
25204
  return c.json({ ok: true, delivered: "none" });
24698
25205
  });
24699
- return app63;
25206
+ return app64;
24700
25207
  }
24701
25208
 
24702
25209
  // app/lib/webchat/gateway/webchat-gateway.ts
@@ -25042,7 +25549,7 @@ var WebchatGateway = class _WebchatGateway {
25042
25549
  const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
25043
25550
  const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
25044
25551
  console.error(
25045
- `[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist6.INJECTION_RULE_CAP}`
25552
+ `[preference-inject] op=inject channel=web accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
25046
25553
  );
25047
25554
  }
25048
25555
  this.hub.deliver(
@@ -25411,14 +25918,14 @@ function makeFileDelivery(opts) {
25411
25918
  }
25412
25919
 
25413
25920
  // app/lib/webchat/file-delivery.ts
25414
- var TAG42 = "[webchat-adaptor]";
25921
+ var TAG46 = "[webchat-adaptor]";
25415
25922
  function platformRoot2() {
25416
25923
  return process.env.MAXY_PLATFORM_ROOT || "";
25417
25924
  }
25418
25925
  function makeWebchatSendFile(entry) {
25419
25926
  return async (filePath) => {
25420
25927
  if (!entry.accountId) {
25421
- console.error(`${TAG42} file-delivery reject reason=no-account sender=${entry.senderId}`);
25928
+ console.error(`${TAG46} file-delivery reject reason=no-account sender=${entry.senderId}`);
25422
25929
  return { ok: false, error: "no-account" };
25423
25930
  }
25424
25931
  const accountDir = resolve32(platformRoot2(), "..", "data/accounts", entry.accountId);
@@ -25426,14 +25933,14 @@ function makeWebchatSendFile(entry) {
25426
25933
  const resolved = realpathSync8(filePath);
25427
25934
  const accountResolved = realpathSync8(accountDir);
25428
25935
  if (!resolved.startsWith(accountResolved + "/")) {
25429
- console.error(`${TAG42} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
25936
+ console.error(`${TAG46} file-delivery reject reason=outside_account_directory sender=${entry.senderId}`);
25430
25937
  return { ok: false, error: "outside-account" };
25431
25938
  }
25432
25939
  return { ok: true };
25433
25940
  } catch (err) {
25434
25941
  const code = err.code;
25435
25942
  console.error(
25436
- `${TAG42} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
25943
+ `${TAG46} file-delivery reject reason=${code === "ENOENT" ? "not-found" : "path-error"} sender=${entry.senderId}`
25437
25944
  );
25438
25945
  return { ok: false, error: code === "ENOENT" ? "not-found" : "path-error" };
25439
25946
  }
@@ -25442,7 +25949,7 @@ function makeWebchatSendFile(entry) {
25442
25949
  function makeWebchatFileDelivery(entry) {
25443
25950
  return makeFileDelivery({
25444
25951
  entry,
25445
- tag: TAG42,
25952
+ tag: TAG46,
25446
25953
  channel: "webchat",
25447
25954
  sendFile: makeWebchatSendFile(entry),
25448
25955
  deferUntilVerdict: true
@@ -25504,7 +26011,7 @@ function buildPublicWebchatSpawnRequest(input) {
25504
26011
  }
25505
26012
 
25506
26013
  // app/lib/whatsapp/inbound/file-delivery-bridge.ts
25507
- var TAG43 = "[whatsapp-adaptor]";
26014
+ var TAG47 = "[whatsapp-adaptor]";
25508
26015
  var SEND_USER_FILE2 = "SendUserFile";
25509
26016
  var WHATSAPP_SEND_DOCUMENT = "whatsapp-send-document";
25510
26017
  function platformRoot3() {
@@ -25522,7 +26029,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
25522
26029
  });
25523
26030
  if (result.ok) return { ok: true };
25524
26031
  console.error(
25525
- `${TAG43} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
26032
+ `${TAG47} file-delivery reject reason=send-failed sender=${entry.senderId} status=${result.status} message=${result.error}`
25526
26033
  );
25527
26034
  return { ok: false, error: result.error };
25528
26035
  };
@@ -25530,7 +26037,7 @@ function makeWhatsAppSendFile(entry, maxyAccountId) {
25530
26037
  function makeWhatsAppFileDelivery(entry, maxyAccountId) {
25531
26038
  const shared = makeFileDelivery({
25532
26039
  entry,
25533
- tag: TAG43,
26040
+ tag: TAG47,
25534
26041
  channel: "whatsapp",
25535
26042
  sendFile: makeWhatsAppSendFile(entry, maxyAccountId)
25536
26043
  });
@@ -25565,7 +26072,7 @@ function makeWhatsAppFileDelivery(entry, maxyAccountId) {
25565
26072
  if (!delivered) {
25566
26073
  const fileField = call.filePath !== void 0 ? ` file=${call.filePath}` : "";
25567
26074
  console.error(
25568
- `${TAG43} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
26075
+ `${TAG47} file-delivery-unreconciled sender=${entry.senderId} sessionId=${sid} tool=${WHATSAPP_SEND_DOCUMENT}${fileField}`
25569
26076
  );
25570
26077
  }
25571
26078
  }
@@ -25747,12 +26254,12 @@ var InboundHub3 = class {
25747
26254
  };
25748
26255
 
25749
26256
  // app/lib/telegram/gateway/telegram-gateway.ts
25750
- var import_dist7 = __toESM(require_dist(), 1);
26257
+ var import_dist8 = __toESM(require_dist(), 1);
25751
26258
 
25752
26259
  // app/lib/telegram/gateway/routes.ts
25753
26260
  function createTelegramChannelRoutes(deps) {
25754
- const app63 = new Hono();
25755
- app63.get("/tg-channel/inbound", (c) => {
26261
+ const app64 = new Hono();
26262
+ app64.get("/tg-channel/inbound", (c) => {
25756
26263
  const key = c.req.query("key");
25757
26264
  if (!key) return c.json({ error: "key required" }, 400);
25758
26265
  return streamSSE(c, async (stream2) => {
@@ -25770,7 +26277,7 @@ function createTelegramChannelRoutes(deps) {
25770
26277
  }
25771
26278
  });
25772
26279
  });
25773
- app63.post("/tg-channel/reply", async (c) => {
26280
+ app64.post("/tg-channel/reply", async (c) => {
25774
26281
  const body = await c.req.json().catch(() => null);
25775
26282
  const key = body?.key;
25776
26283
  const text = body?.text;
@@ -25786,7 +26293,7 @@ function createTelegramChannelRoutes(deps) {
25786
26293
  console.error(`[telegram-native] op=reply key=${key} bytes=${Buffer.byteLength(text, "utf8")}`);
25787
26294
  return c.json({ ok: true });
25788
26295
  });
25789
- app63.post("/tg-channel/ready", async (c) => {
26296
+ app64.post("/tg-channel/ready", async (c) => {
25790
26297
  const body = await c.req.json().catch(() => null);
25791
26298
  const key = body?.key;
25792
26299
  if (typeof key !== "string") {
@@ -25795,7 +26302,7 @@ function createTelegramChannelRoutes(deps) {
25795
26302
  deps.onReady?.(key);
25796
26303
  return c.json({ ok: true });
25797
26304
  });
25798
- app63.post("/tg-channel/received", async (c) => {
26305
+ app64.post("/tg-channel/received", async (c) => {
25799
26306
  const body = await c.req.json().catch(() => null);
25800
26307
  const key = body?.key;
25801
26308
  const messageId = body?.messageId;
@@ -25805,7 +26312,7 @@ function createTelegramChannelRoutes(deps) {
25805
26312
  deps.onReceived?.(key, messageId);
25806
26313
  return c.json({ ok: true });
25807
26314
  });
25808
- app63.post("/tg-channel/turn-end", async (c) => {
26315
+ app64.post("/tg-channel/turn-end", async (c) => {
25809
26316
  const body = await c.req.json().catch(() => null);
25810
26317
  const key = body?.key;
25811
26318
  const sessionId = body?.sessionId;
@@ -25838,7 +26345,7 @@ function createTelegramChannelRoutes(deps) {
25838
26345
  console.error(`[telegram-native] op=turn-end key=${key} sessionId=${sid} replied=no delivered=none`);
25839
26346
  return c.json({ ok: true, delivered: "none" });
25840
26347
  });
25841
- return app63;
26348
+ return app64;
25842
26349
  }
25843
26350
 
25844
26351
  // app/lib/telegram/gateway/telegram-gateway.ts
@@ -25903,7 +26410,7 @@ var TelegramGateway = class {
25903
26410
  const injected = res.block ? (res.block.match(/^- /gm) ?? []).length : 0;
25904
26411
  const owner8 = res.ownerUserId ? res.ownerUserId.slice(0, 8) : "-";
25905
26412
  console.error(
25906
- `[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist7.INJECTION_RULE_CAP}`
26413
+ `[preference-inject] op=inject channel=tg accountId=${input.accountId} injected=${injected} owner=${owner8} source=${res.source} capped=${injected >= import_dist8.INJECTION_RULE_CAP}`
25907
26414
  );
25908
26415
  }
25909
26416
  this.hub.deliver(
@@ -25969,7 +26476,7 @@ function buildTelegramSpawnRequest(input) {
25969
26476
  import { realpathSync as realpathSync9 } from "fs";
25970
26477
  import { readFile as readFile7, stat as stat7 } from "fs/promises";
25971
26478
  import { resolve as resolve33, basename as basename11 } from "path";
25972
- var TAG44 = "[telegram:outbound]";
26479
+ var TAG48 = "[telegram:outbound]";
25973
26480
  var TELEGRAM_DOCUMENT_MAX_BYTES = 50 * 1024 * 1024;
25974
26481
  async function sendTelegramDocument(input) {
25975
26482
  const { botToken, chatId, filePath, caption, maxyAccountId, platformRoot: platformRoot5 } = input;
@@ -25985,16 +26492,16 @@ async function sendTelegramDocument(input) {
25985
26492
  resolvedPath = realpathSync9(filePath);
25986
26493
  const accountResolved = realpathSync9(accountDir);
25987
26494
  if (!resolvedPath.startsWith(accountResolved + "/")) {
25988
- console.error(`${TAG44} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
26495
+ console.error(`${TAG48} document REJECTED reason=outside_account_directory maxyAccountId=${maxyAccountId}`);
25989
26496
  return { ok: false, status: 403, error: "Access denied: file is outside the account directory" };
25990
26497
  }
25991
26498
  } catch (err) {
25992
26499
  const code = err.code;
25993
26500
  if (code === "ENOENT") {
25994
- console.error(`${TAG44} document ENOENT path=${filePath}`);
26501
+ console.error(`${TAG48} document ENOENT path=${filePath}`);
25995
26502
  return { ok: false, status: 404, error: `File not found: ${filePath}` };
25996
26503
  }
25997
- console.error(`${TAG44} document path error: ${String(err)}`);
26504
+ console.error(`${TAG48} document path error: ${String(err)}`);
25998
26505
  return { ok: false, status: 500, error: String(err) };
25999
26506
  }
26000
26507
  const fileStat = await stat7(resolvedPath);
@@ -26027,13 +26534,13 @@ async function sendTelegramDocument(input) {
26027
26534
  error = e instanceof Error ? e.message : String(e);
26028
26535
  }
26029
26536
  console.error(
26030
- `${TAG44} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
26537
+ `${TAG48} sent document to=${chatId} file=${filename} bytes=${fileStat.size} ok=${ok}` + (messageId !== void 0 ? ` id=${messageId}` : "")
26031
26538
  );
26032
26539
  return ok ? { ok: true, messageId } : { ok: false, status: 500, error };
26033
26540
  }
26034
26541
 
26035
26542
  // app/lib/telegram/outbound/file-delivery.ts
26036
- var TAG45 = "[telegram:outbound]";
26543
+ var TAG49 = "[telegram:outbound]";
26037
26544
  function platformRoot4() {
26038
26545
  return process.env.MAXY_PLATFORM_ROOT || "";
26039
26546
  }
@@ -26045,11 +26552,11 @@ function makeTelegramSendFile(entry) {
26045
26552
  botToken = (entry.role === "admin" ? tg?.adminBotToken : tg?.publicBotToken) ?? null;
26046
26553
  }
26047
26554
  if (!botToken) {
26048
- console.error(`${TAG45} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
26555
+ console.error(`${TAG49} file-delivery reject reason=no-bot-token sender=${entry.senderId} role=${entry.role}`);
26049
26556
  return { ok: false, error: "no-bot-token" };
26050
26557
  }
26051
26558
  if (entry.replyTarget == null) {
26052
- console.error(`${TAG45} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
26559
+ console.error(`${TAG49} file-delivery reject reason=no-reply-target sender=${entry.senderId} role=${entry.role}`);
26053
26560
  return { ok: false, error: "no-reply-target" };
26054
26561
  }
26055
26562
  const result = await sendTelegramDocument({
@@ -26066,7 +26573,7 @@ function makeTelegramSendFile(entry) {
26066
26573
  function makeTelegramFileDelivery(entry) {
26067
26574
  return makeFileDelivery({
26068
26575
  entry,
26069
- tag: TAG45,
26576
+ tag: TAG49,
26070
26577
  channel: "telegram",
26071
26578
  sendFile: makeTelegramSendFile(entry)
26072
26579
  });
@@ -26106,17 +26613,17 @@ function startTelegramNativeFileFollower(input) {
26106
26613
  }
26107
26614
 
26108
26615
  // server/telegram-descriptor.ts
26109
- import { resolve as resolve34, join as join37 } from "path";
26616
+ import { resolve as resolve34, join as join38 } from "path";
26110
26617
  function telegramGatewayUrl() {
26111
26618
  return `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`;
26112
26619
  }
26113
26620
  function telegramServerPath() {
26114
- return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join37(__dirname, ".."), "services/telegram-channel/dist/server.js");
26621
+ return process.env.MAXY_TELEGRAM_CHANNEL_SERVER_PATH ?? resolve34(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/telegram-channel/dist/server.js");
26115
26622
  }
26116
26623
 
26117
26624
  // app/lib/channel-pty-bridge/public-session-end-review.ts
26118
26625
  import { randomUUID as randomUUID16 } from "crypto";
26119
- var TAG46 = "[public-session-review]";
26626
+ var TAG50 = "[public-session-review]";
26120
26627
  var CONSUMED_CAP = 500;
26121
26628
  var consumed = /* @__PURE__ */ new Set();
26122
26629
  function consumeOnce(sessionId) {
@@ -26143,7 +26650,7 @@ async function fetchJsonl(sessionId) {
26143
26650
  return await res.text();
26144
26651
  } catch (err) {
26145
26652
  console.error(
26146
- `${TAG46} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
26653
+ `${TAG50} jsonl-fetch-failed sessionId=${sessionId} err="${err instanceof Error ? err.message : String(err)}"`
26147
26654
  );
26148
26655
  return null;
26149
26656
  }
@@ -26167,7 +26674,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
26167
26674
  const res = await fetch(url);
26168
26675
  if (!res.ok) {
26169
26676
  console.error(
26170
- `${TAG46} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
26677
+ `${TAG50} prior-writes-fetch-failed sliceToken=${sliceToken.slice(0, 8)} status=${res.status}`
26171
26678
  );
26172
26679
  return [];
26173
26680
  }
@@ -26175,7 +26682,7 @@ async function fetchPriorWrites(sliceToken, accountId) {
26175
26682
  return Array.isArray(body.writes) ? body.writes : [];
26176
26683
  } catch (err) {
26177
26684
  console.error(
26178
- `${TAG46} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
26685
+ `${TAG50} prior-writes-fetch-threw sliceToken=${sliceToken.slice(0, 8)} err="${err instanceof Error ? err.message : String(err)}"`
26179
26686
  );
26180
26687
  return [];
26181
26688
  }
@@ -26204,7 +26711,7 @@ function composeInitialMessage(input) {
26204
26711
  }
26205
26712
  async function dispatchReviewer(input, initialMessage) {
26206
26713
  const sessionId = randomUUID16();
26207
- console.log(`${TAG46} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
26714
+ console.log(`${TAG50} route target=rc-spawn sessionId=${sessionId.slice(0, 8)} sourceSession=${input.sessionId.slice(0, 8)}`);
26208
26715
  const spawned = await managerRcSpawn({
26209
26716
  sessionId,
26210
26717
  initialMessage,
@@ -26224,21 +26731,21 @@ async function firePublicSessionEndReview(input) {
26224
26731
  const dispatchedAt = Date.now();
26225
26732
  if (consumed.has(input.sessionId)) {
26226
26733
  console.log(
26227
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
26734
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
26228
26735
  );
26229
26736
  return;
26230
26737
  }
26231
26738
  const jsonl = await fetchJsonl(input.sessionId);
26232
26739
  if (!jsonl) {
26233
26740
  console.log(
26234
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
26741
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-jsonl-missing`
26235
26742
  );
26236
26743
  return;
26237
26744
  }
26238
26745
  const operatorTurns = countOperatorTurns(jsonl);
26239
26746
  if (operatorTurns === 0) {
26240
26747
  console.log(
26241
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
26748
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-no-turns`
26242
26749
  );
26243
26750
  return;
26244
26751
  }
@@ -26252,28 +26759,28 @@ async function firePublicSessionEndReview(input) {
26252
26759
  });
26253
26760
  if (!consumeOnce(input.sessionId)) {
26254
26761
  console.log(
26255
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
26762
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-already-reviewed`
26256
26763
  );
26257
26764
  return;
26258
26765
  }
26259
26766
  const dispatched = await dispatchReviewer(input, initialMessage);
26260
26767
  if (!dispatched.ok) {
26261
26768
  console.error(
26262
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
26769
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=skipped-spawn-failed reason=${dispatched.reason}`
26263
26770
  );
26264
26771
  return;
26265
26772
  }
26266
26773
  console.log(
26267
- `${TAG46} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
26774
+ `${TAG50} dispatchFor=${input.dispatchFor} sessionId=${input.sessionId} sliceToken=${sliceShort} personId=${personField} result=dispatched managerSessionId=${dispatched.managerSessionId} operatorTurns=${operatorTurns} priorWrites=${priorWrites.length} ms=${Date.now() - dispatchedAt}`
26268
26775
  );
26269
26776
  }
26270
26777
 
26271
26778
  // app/lib/whatsapp/inbound/resolve-client-graph-owner.ts
26272
- var import_dist8 = __toESM(require_dist(), 1);
26779
+ var import_dist9 = __toESM(require_dist(), 1);
26273
26780
  async function resolveClientOwnerUserId(accountId, deps = {}) {
26274
26781
  const listAccounts = deps.listAccounts ?? listValidAccounts;
26275
26782
  const getSession4 = deps.getSession ?? getSession;
26276
- const resolveOwner2 = deps.resolveOwner ?? import_dist8.resolveOwnerUserId;
26783
+ const resolveOwner2 = deps.resolveOwner ?? import_dist9.resolveOwnerUserId;
26277
26784
  const role = listAccounts().find((a) => a.accountId === accountId)?.config.role;
26278
26785
  if (role !== "client") return null;
26279
26786
  const session = getSession4();
@@ -26398,7 +26905,7 @@ function broadcastAdminShutdown(reason) {
26398
26905
 
26399
26906
  // ../lib/entitlement/src/index.ts
26400
26907
  import { createPublicKey, createHash as createHash6, verify as cryptoVerify } from "crypto";
26401
- import { existsSync as existsSync35, readFileSync as readFileSync37, statSync as statSync13 } from "fs";
26908
+ import { existsSync as existsSync36, readFileSync as readFileSync38, statSync as statSync13 } from "fs";
26402
26909
  import { resolve as resolve35 } from "path";
26403
26910
 
26404
26911
  // ../lib/entitlement/src/canonicalize.ts
@@ -26447,7 +26954,7 @@ function resolveEntitlement(brand, account) {
26447
26954
  return logResolved(implicitTrust(account), null);
26448
26955
  }
26449
26956
  const entitlementPath = resolve35(brand.configDir, "entitlement.json");
26450
- if (!existsSync35(entitlementPath)) {
26957
+ if (!existsSync36(entitlementPath)) {
26451
26958
  return logResolved(anonymousFallback("missing"), { reason: "missing" });
26452
26959
  }
26453
26960
  const stat8 = statSync13(entitlementPath);
@@ -26462,7 +26969,7 @@ function resolveEntitlement(brand, account) {
26462
26969
  function verifyAndResolve(brand, entitlementPath, account) {
26463
26970
  let pubkeyPem;
26464
26971
  try {
26465
- pubkeyPem = readFileSync37(pubkeyPath(brand), "utf-8");
26972
+ pubkeyPem = readFileSync38(pubkeyPath(brand), "utf-8");
26466
26973
  } catch (err) {
26467
26974
  return logResolved(anonymousFallback("pubkey-missing"), {
26468
26975
  reason: "pubkey-missing"
@@ -26476,7 +26983,7 @@ function verifyAndResolve(brand, entitlementPath, account) {
26476
26983
  }
26477
26984
  let envelope;
26478
26985
  try {
26479
- envelope = JSON.parse(readFileSync37(entitlementPath, "utf-8"));
26986
+ envelope = JSON.parse(readFileSync38(entitlementPath, "utf-8"));
26480
26987
  } catch {
26481
26988
  return logResolved(anonymousFallback("malformed"), { reason: "malformed" });
26482
26989
  }
@@ -26637,14 +27144,14 @@ function clientFrom(c) {
26637
27144
  );
26638
27145
  }
26639
27146
  var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT || "";
26640
- var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join38(PLATFORM_ROOT8, "config", "brand.json") : "";
27147
+ var BRAND_JSON_PATH = PLATFORM_ROOT8 ? join39(PLATFORM_ROOT8, "config", "brand.json") : "";
26641
27148
  var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", marketingUrl: "https://getmaxy.com" };
26642
- if (BRAND_JSON_PATH && !existsSync36(BRAND_JSON_PATH)) {
27149
+ if (BRAND_JSON_PATH && !existsSync37(BRAND_JSON_PATH)) {
26643
27150
  console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
26644
27151
  }
26645
- if (BRAND_JSON_PATH && existsSync36(BRAND_JSON_PATH)) {
27152
+ if (BRAND_JSON_PATH && existsSync37(BRAND_JSON_PATH)) {
26646
27153
  try {
26647
- const parsed = JSON.parse(readFileSync38(BRAND_JSON_PATH, "utf-8"));
27154
+ const parsed = JSON.parse(readFileSync39(BRAND_JSON_PATH, "utf-8"));
26648
27155
  BRAND = { ...BRAND, ...parsed };
26649
27156
  } catch (err) {
26650
27157
  console.error(`[brand] Failed to parse brand.json: ${err.message}`);
@@ -26676,11 +27183,11 @@ var brandLoginOpts = {
26676
27183
  appleTouchIconPath: brandAppIcon512Path,
26677
27184
  themeColor: BRAND.defaultColors?.primary
26678
27185
  };
26679
- var ALIAS_DOMAINS_PATH = join38(homedir4(), BRAND.configDir, "alias-domains.json");
27186
+ var ALIAS_DOMAINS_PATH = join39(homedir4(), BRAND.configDir, "alias-domains.json");
26680
27187
  function loadAliasDomains() {
26681
27188
  try {
26682
- if (!existsSync36(ALIAS_DOMAINS_PATH)) return null;
26683
- const parsed = JSON.parse(readFileSync38(ALIAS_DOMAINS_PATH, "utf-8"));
27189
+ if (!existsSync37(ALIAS_DOMAINS_PATH)) return null;
27190
+ const parsed = JSON.parse(readFileSync39(ALIAS_DOMAINS_PATH, "utf-8"));
26684
27191
  if (!Array.isArray(parsed)) {
26685
27192
  console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
26686
27193
  return null;
@@ -26704,14 +27211,14 @@ watchFile(ALIAS_DOMAINS_PATH, { interval: 2e3 }, () => {
26704
27211
  function isPublicHost(host) {
26705
27212
  return host.startsWith("public.") || aliasDomains.has(host);
26706
27213
  }
26707
- var app62 = new Hono();
27214
+ var app63 = new Hono();
26708
27215
  var nativeFileFollowers = /* @__PURE__ */ new Map();
26709
27216
  var webchatFileFollowers = /* @__PURE__ */ new Map();
26710
27217
  async function fetchAccountStandingRules(accountId) {
26711
27218
  const session = getSession();
26712
27219
  try {
26713
- const res = await (0, import_dist9.resolveActiveRules)(session, accountId);
26714
- return { block: (0, import_dist9.formatStandingRulesBlock)(res.rules), ownerUserId: res.ownerUserId, source: res.source };
27220
+ const res = await (0, import_dist10.resolveActiveRules)(session, accountId);
27221
+ return { block: (0, import_dist10.formatStandingRulesBlock)(res.rules), ownerUserId: res.ownerUserId, source: res.source };
26715
27222
  } catch (err) {
26716
27223
  console.error(
26717
27224
  `[preference-inject] op=fetch-failed accountId=${accountId} error=${err instanceof Error ? err.message : String(err)}`
@@ -26744,7 +27251,7 @@ async function recordPassiveDispatch(input) {
26744
27251
  var waGateway = new WaGateway({
26745
27252
  fetchStandingRules: fetchAccountStandingRules,
26746
27253
  gatewayUrl: `http://127.0.0.1:${process.env.MAXY_UI_INTERNAL_PORT ?? ""}`,
26747
- serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
27254
+ serverPath: process.env.MAXY_WA_CHANNEL_SERVER_PATH ?? resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "services/whatsapp-channel/dist/server.js"),
26748
27255
  // Task 751 / 1390 — file delivery on the native channel. `maxyAccountId` (the
26749
27256
  // path-validation scope) is the sender's effective SESSION account, resolved
26750
27257
  // once at the inbound gate and threaded here via the gateway's per-sender doc
@@ -26759,7 +27266,7 @@ var waGateway = new WaGateway({
26759
27266
  caption,
26760
27267
  accountId,
26761
27268
  maxyAccountId,
26762
- platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, ".."))
27269
+ platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."))
26763
27270
  });
26764
27271
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
26765
27272
  },
@@ -26812,6 +27319,13 @@ var waGateway = new WaGateway({
26812
27319
  console.error(`[whatsapp-native] op=account-manager-route senderId=${senderId} managesAccount=${managesAccount} effectiveAccount=${effectiveAccountId} source=gate`);
26813
27320
  }
26814
27321
  const req = buildWaSpawnRequest({ accountId: effectiveAccountId, senderId, role, personId, gatewayUrl, serverPath });
27322
+ await ensureSessionConversation({
27323
+ accountId: effectiveAccountId,
27324
+ sessionId: req.sessionId,
27325
+ channel: "whatsapp",
27326
+ channelAddress: senderId,
27327
+ agentType: role === "admin" ? "admin" : "public"
27328
+ });
26815
27329
  let userId = role === "admin" ? resolveAdminUserId({ accountId: effectiveAccountId, senderPhone: senderId }) ?? (ownerSelfPhone ? resolveOwnerUserId(effectiveAccountId) ?? void 0 : void 0) : void 0;
26816
27330
  let graphOwnerResolved = false;
26817
27331
  if (role === "admin" && userId === void 0) {
@@ -26850,13 +27364,13 @@ var waGateway = new WaGateway({
26850
27364
  nativeFileFollowers.set(senderId, ac);
26851
27365
  }
26852
27366
  });
26853
- app62.route("/", waGateway.routes());
27367
+ app63.route("/", waGateway.routes());
26854
27368
  waGateway.startSweeper();
26855
27369
  function runDuplicateSenderAudit() {
26856
27370
  try {
26857
27371
  const configDir2 = process.env.CLAUDE_CONFIG_DIR;
26858
27372
  if (!configDir2) return;
26859
- const projectsRoot = join38(configDir2, "projects");
27373
+ const projectsRoot = join39(configDir2, "projects");
26860
27374
  const records = [];
26861
27375
  for (const { path: jsonlPath, isSubagent, archived } of enumerateJsonls(projectsRoot)) {
26862
27376
  if (isSubagent || archived) continue;
@@ -26968,7 +27482,7 @@ var webchatGateway = new WebchatGateway({
26968
27482
  firePublicSessionEndReview: (input) => firePublicSessionEndReview(input)
26969
27483
  });
26970
27484
  setWebchatGateway(webchatGateway);
26971
- app62.route("/", webchatGateway.routes());
27485
+ app63.route("/", webchatGateway.routes());
26972
27486
  webchatGateway.startSweeper();
26973
27487
  webchatGateway.startPublicReaper();
26974
27488
  var telegramFileFollowers = /* @__PURE__ */ new Map();
@@ -27002,7 +27516,7 @@ var telegramGateway = new TelegramGateway({
27002
27516
  }
27003
27517
  });
27004
27518
  setTelegramGateway(telegramGateway);
27005
- app62.route("/", telegramGateway.routes());
27519
+ app63.route("/", telegramGateway.routes());
27006
27520
  telegramGateway.startSweeper();
27007
27521
  var chatRoutes = createChatRoutes({
27008
27522
  handleInbound: (input) => webchatGateway.handleInbound(input),
@@ -27036,19 +27550,19 @@ var scheduleInjectRoutes = createScheduleInjectRoutes({
27036
27550
  return managed.account;
27037
27551
  }
27038
27552
  });
27039
- app62.route("/api/channel/schedule-inject", scheduleInjectRoutes);
27040
- app62.use("*", clientIpMiddleware);
27553
+ app63.route("/api/channel/schedule-inject", scheduleInjectRoutes);
27554
+ app63.use("*", clientIpMiddleware);
27041
27555
  function allowsSameOriginFraming(path3) {
27042
27556
  return path3 === "/vnc-viewer.html" || path3.startsWith("/api/admin/attachment/") || path3.startsWith("/api/public-reader/attachment/") || path3 === "/api/admin/files/download";
27043
27557
  }
27044
- app62.use("*", async (c, next) => {
27558
+ app63.use("*", async (c, next) => {
27045
27559
  await next();
27046
27560
  c.header("X-Content-Type-Options", "nosniff");
27047
27561
  c.header("Referrer-Policy", "strict-origin-when-cross-origin");
27048
27562
  c.header("X-Frame-Options", allowsSameOriginFraming(c.req.path) ? "SAMEORIGIN" : "DENY");
27049
27563
  });
27050
27564
  var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
27051
- app62.use("*", async (c, next) => {
27565
+ app63.use("*", async (c, next) => {
27052
27566
  if (!HTTP_LOG_PATHS.has(c.req.path)) {
27053
27567
  await next();
27054
27568
  return;
@@ -27066,7 +27580,7 @@ app62.use("*", async (c, next) => {
27066
27580
  });
27067
27581
  }
27068
27582
  });
27069
- app62.use("*", async (c, next) => {
27583
+ app63.use("*", async (c, next) => {
27070
27584
  const host = (c.req.header("host") ?? "").split(":")[0];
27071
27585
  if (isOperatorHost(host, getOperatorDomains()) || !isPublicHost(host)) {
27072
27586
  await next();
@@ -27104,7 +27618,7 @@ function resolveRemoteAuthOpts(c) {
27104
27618
  return { ...brandLoginOpts, origin };
27105
27619
  }
27106
27620
  var MAX_LOGIN_BODY = 8 * 1024;
27107
- app62.post("/__remote-auth/login", async (c) => {
27621
+ app63.post("/__remote-auth/login", async (c) => {
27108
27622
  const client = clientFrom(c);
27109
27623
  const clientIp = client.ip || "unknown";
27110
27624
  if (!requestIsTlsTerminated(c)) {
@@ -27149,7 +27663,7 @@ app62.post("/__remote-auth/login", async (c) => {
27149
27663
  }
27150
27664
  });
27151
27665
  });
27152
- app62.get("/__remote-auth/logout", (c) => {
27666
+ app63.get("/__remote-auth/logout", (c) => {
27153
27667
  const client = clientFrom(c);
27154
27668
  const clientIp = client.ip || "unknown";
27155
27669
  console.error(`[remote-auth] logout ip=${clientIp}`);
@@ -27162,7 +27676,7 @@ app62.get("/__remote-auth/logout", (c) => {
27162
27676
  }
27163
27677
  });
27164
27678
  });
27165
- app62.post("/__remote-auth/change-password", async (c) => {
27679
+ app63.post("/__remote-auth/change-password", async (c) => {
27166
27680
  const client = clientFrom(c);
27167
27681
  const clientIp = client.ip || "unknown";
27168
27682
  const rateLimited = checkRateLimit(client);
@@ -27221,13 +27735,13 @@ app62.post("/__remote-auth/change-password", async (c) => {
27221
27735
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "change", changeError: "Failed to save password", redirect }), 200);
27222
27736
  }
27223
27737
  });
27224
- app62.get("/__remote-auth/setup", (c) => {
27738
+ app63.get("/__remote-auth/setup", (c) => {
27225
27739
  if (isRemoteAuthConfigured()) {
27226
27740
  return c.redirect("/");
27227
27741
  }
27228
27742
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup" }), 200);
27229
27743
  });
27230
- app62.post("/__remote-auth/set-initial-password", async (c) => {
27744
+ app63.post("/__remote-auth/set-initial-password", async (c) => {
27231
27745
  if (isRemoteAuthConfigured()) {
27232
27746
  return c.redirect("/");
27233
27747
  }
@@ -27265,10 +27779,10 @@ app62.post("/__remote-auth/set-initial-password", async (c) => {
27265
27779
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
27266
27780
  }
27267
27781
  });
27268
- app62.get("/api/remote-auth/status", (c) => {
27782
+ app63.get("/api/remote-auth/status", (c) => {
27269
27783
  return c.json({ configured: isRemoteAuthConfigured() });
27270
27784
  });
27271
- app62.post("/api/remote-auth/set-password", async (c) => {
27785
+ app63.post("/api/remote-auth/set-password", async (c) => {
27272
27786
  let body;
27273
27787
  try {
27274
27788
  body = await c.req.json();
@@ -27307,10 +27821,10 @@ app62.post("/api/remote-auth/set-password", async (c) => {
27307
27821
  return c.json({ error: "Failed to save password" }, 500);
27308
27822
  }
27309
27823
  });
27310
- app62.route("/api/_client-error", client_error_default);
27824
+ app63.route("/api/_client-error", client_error_default);
27311
27825
  console.log("[client-error-route] mounted");
27312
27826
  var PWA_PUBLIC_PATHS = /* @__PURE__ */ new Set(["/sw.js", ...PWA_SURFACES.map((s) => s.manifestPath)]);
27313
- app62.use("*", async (c, next) => {
27827
+ app63.use("*", async (c, next) => {
27314
27828
  const host = (c.req.header("host") ?? "").split(":")[0];
27315
27829
  const path3 = c.req.path;
27316
27830
  if (path3 === "/favicon.ico" || path3.startsWith("/assets/") || path3.startsWith("/brand/") || // Public free/busy is read by the booking page (a separate Cloudflare Pages
@@ -27354,27 +27868,34 @@ app62.use("*", async (c, next) => {
27354
27868
  }
27355
27869
  return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(c), redirect: path3 }), 200);
27356
27870
  });
27357
- app62.route("/api/health", health_default);
27358
- app62.route("/api/chat", chatRoutes);
27359
- app62.route("/api/whatsapp", whatsapp_default);
27360
- app62.route("/api/storage", storage_broker_default);
27361
- app62.route("/api/whatsapp-reader", whatsapp_reader_default);
27362
- app62.route("/api/public-reader", public_reader_default);
27363
- app62.route("/api/webchat", createWebchatRoutes({
27871
+ app63.route("/api/health", health_default);
27872
+ app63.route("/api/chat", chatRoutes);
27873
+ app63.route("/api/whatsapp", whatsapp_default);
27874
+ app63.route("/api/storage", storage_broker_default);
27875
+ app63.route("/api/whatsapp-reader", whatsapp_reader_default);
27876
+ app63.route("/api/public-reader", public_reader_default);
27877
+ app63.route("/api/webchat", createWebchatRoutes({
27364
27878
  handleInbound: (input) => webchatGateway.handleInbound(input),
27365
27879
  // Task 940 — the permission relay's pointer read + verdict write.
27366
27880
  pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
27367
27881
  deliveryFailureFor: (key) => webchatGateway.deliveryFailureFor(key),
27368
27882
  resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
27369
27883
  }));
27370
- app62.route("/api/webchat/greeting", webchat_greeting_default);
27371
- app62.route("/api/telegram", telegram_default);
27372
- app62.route("/api/quickbooks", quickbooks_default);
27373
- app62.route("/api/onboarding", onboarding_default);
27374
- app62.route("/api/admin", admin_default);
27375
- app62.route("/api/access", access_default);
27376
- app62.route("/api/session", session_default2);
27377
- app62.route("/api/calendar", calendar_public_default);
27884
+ app63.route("/api/webchat/greeting", webchat_greeting_default);
27885
+ app63.route("/api/telegram", telegram_default);
27886
+ app63.route("/api/quickbooks", quickbooks_default);
27887
+ app63.route(
27888
+ "/api/google",
27889
+ createGoogleOAuthRoutes(
27890
+ resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..")),
27891
+ resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, ".."), "..", "data/accounts")
27892
+ )
27893
+ );
27894
+ app63.route("/api/onboarding", onboarding_default);
27895
+ app63.route("/api/admin", admin_default);
27896
+ app63.route("/api/access", access_default);
27897
+ app63.route("/api/session", session_default2);
27898
+ app63.route("/api/calendar", calendar_public_default);
27378
27899
  var SAFE_SLUG_RE2 = /^[a-z][a-z0-9-]{2,49}$/;
27379
27900
  var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
27380
27901
  var IMAGE_MIME = {
@@ -27386,7 +27907,7 @@ var IMAGE_MIME = {
27386
27907
  ".svg": "image/svg+xml",
27387
27908
  ".ico": "image/x-icon"
27388
27909
  };
27389
- app62.get("/agent-assets/:slug/:filename", (c) => {
27910
+ app63.get("/agent-assets/:slug/:filename", (c) => {
27390
27911
  const slug = c.req.param("slug");
27391
27912
  const filename = c.req.param("filename");
27392
27913
  if (!SAFE_SLUG_RE2.test(slug)) {
@@ -27408,20 +27929,20 @@ app62.get("/agent-assets/:slug/:filename", (c) => {
27408
27929
  console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
27409
27930
  return c.text("Forbidden", 403);
27410
27931
  }
27411
- if (!existsSync36(filePath)) {
27932
+ if (!existsSync37(filePath)) {
27412
27933
  console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
27413
27934
  return c.text("Not found", 404);
27414
27935
  }
27415
27936
  const ext = "." + filename.split(".").pop()?.toLowerCase();
27416
27937
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
27417
27938
  console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
27418
- const body = readFileSync38(filePath);
27939
+ const body = readFileSync39(filePath);
27419
27940
  return c.body(body, 200, {
27420
27941
  "Content-Type": contentType,
27421
27942
  "Cache-Control": "public, max-age=3600"
27422
27943
  });
27423
27944
  });
27424
- app62.get("/generated/:filename", (c) => {
27945
+ app63.get("/generated/:filename", (c) => {
27425
27946
  const filename = c.req.param("filename");
27426
27947
  if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
27427
27948
  console.error(`[generated] serve file=${filename} status=403`);
@@ -27438,29 +27959,29 @@ app62.get("/generated/:filename", (c) => {
27438
27959
  console.error(`[generated] serve file=${filename} status=403`);
27439
27960
  return c.text("Forbidden", 403);
27440
27961
  }
27441
- if (!existsSync36(filePath)) {
27962
+ if (!existsSync37(filePath)) {
27442
27963
  console.error(`[generated] serve file=${filename} status=404`);
27443
27964
  return c.text("Not found", 404);
27444
27965
  }
27445
27966
  const ext = "." + filename.split(".").pop()?.toLowerCase();
27446
27967
  const contentType = IMAGE_MIME[ext] || "application/octet-stream";
27447
27968
  console.log(`[generated] serve file=${filename} status=200`);
27448
- const body = readFileSync38(filePath);
27969
+ const body = readFileSync39(filePath);
27449
27970
  return c.body(body, 200, {
27450
27971
  "Content-Type": contentType,
27451
27972
  "Cache-Control": "public, max-age=86400"
27452
27973
  });
27453
27974
  });
27454
- app62.route("/sites", sites_default);
27455
- app62.route("/listings", listings_default);
27456
- app62.route("/v", visitor_event_default);
27457
- app62.route("/v", visitor_consent_default);
27975
+ app63.route("/sites", sites_default);
27976
+ app63.route("/listings", listings_default);
27977
+ app63.route("/v", visitor_event_default);
27978
+ app63.route("/v", visitor_consent_default);
27458
27979
  var htmlCache = /* @__PURE__ */ new Map();
27459
27980
  var brandLogoPath = "/brand/maxy-monochrome.png";
27460
27981
  var brandIconPath = "/brand/maxy-monochrome.png";
27461
- if (BRAND_JSON_PATH && existsSync36(BRAND_JSON_PATH)) {
27982
+ if (BRAND_JSON_PATH && existsSync37(BRAND_JSON_PATH)) {
27462
27983
  try {
27463
- const fullBrand = JSON.parse(readFileSync38(BRAND_JSON_PATH, "utf-8"));
27984
+ const fullBrand = JSON.parse(readFileSync39(BRAND_JSON_PATH, "utf-8"));
27464
27985
  if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
27465
27986
  brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
27466
27987
  } catch {
@@ -27487,11 +28008,11 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
27487
28008
  var brandThemeColor = BRAND.defaultColors?.primary ?? "#000000";
27488
28009
  var brandBackgroundColor = BRAND.defaultColors?.background ?? "#ffffff";
27489
28010
  var brandAppIconsExist = [brandAppIcon192Path, brandAppIcon512Path, brandMaskableIconPath].every(
27490
- (p) => existsSync36(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
28011
+ (p) => existsSync37(resolve36(process.cwd(), "public", p.replace(/^\//, "")))
27491
28012
  );
27492
28013
  var SW_SOURCE = (() => {
27493
28014
  try {
27494
- return readFileSync38(resolve36(process.cwd(), "public", "sw.js"), "utf-8");
28015
+ return readFileSync39(resolve36(process.cwd(), "public", "sw.js"), "utf-8");
27495
28016
  } catch {
27496
28017
  return null;
27497
28018
  }
@@ -27499,9 +28020,9 @@ var SW_SOURCE = (() => {
27499
28020
  function readInstalledVersion() {
27500
28021
  try {
27501
28022
  if (!PLATFORM_ROOT8) return "unknown";
27502
- const versionFile = join38(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
27503
- if (!existsSync36(versionFile)) return "unknown";
27504
- const content = readFileSync38(versionFile, "utf-8").trim();
28023
+ const versionFile = join39(PLATFORM_ROOT8, "config", `.${BRAND.hostname}-version`);
28024
+ if (!existsSync37(versionFile)) return "unknown";
28025
+ const content = readFileSync39(versionFile, "utf-8").trim();
27505
28026
  return content || "unknown";
27506
28027
  } catch {
27507
28028
  return "unknown";
@@ -27542,7 +28063,7 @@ var clientErrorReporterScript = `<script>
27542
28063
  function cachedHtml(file) {
27543
28064
  let html = htmlCache.get(file);
27544
28065
  if (!html) {
27545
- html = readFileSync38(resolve36(process.cwd(), "public", file), "utf-8");
28066
+ html = readFileSync39(resolve36(process.cwd(), "public", file), "utf-8");
27546
28067
  const productNameEsc = escapeHtml(BRAND.productName);
27547
28068
  html = html.replace(/<title>([^<]*)<\/title>/, (_match, inner) => `<title>${escapeHtml(inner).replace(/Maxy/g, productNameEsc)}</title>`);
27548
28069
  html = html.replace('href="/favicon.ico"', `href="${escapeHtml(brandFaviconPath)}"`);
@@ -27559,13 +28080,13 @@ ${clientErrorReporterScript}
27559
28080
  return html;
27560
28081
  }
27561
28082
  function loadBrandingCache(agentSlug) {
27562
- const configDir2 = join38(homedir4(), BRAND.configDir);
28083
+ const configDir2 = join39(homedir4(), BRAND.configDir);
27563
28084
  try {
27564
28085
  const accountId = getDefaultAccountId();
27565
28086
  if (!accountId) return null;
27566
- const cachePath = join38(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
27567
- if (!existsSync36(cachePath)) return null;
27568
- return JSON.parse(readFileSync38(cachePath, "utf-8"));
28087
+ const cachePath = join39(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
28088
+ if (!existsSync37(cachePath)) return null;
28089
+ return JSON.parse(readFileSync39(cachePath, "utf-8"));
27569
28090
  } catch {
27570
28091
  return null;
27571
28092
  }
@@ -27609,7 +28130,7 @@ function brandedPublicHtml(agentSlug) {
27609
28130
  function agentUnavailableHtml() {
27610
28131
  return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${escapeHtml(BRAND.productName)}</title></head><body style="font-family:system-ui,sans-serif;max-width:32rem;margin:4rem auto;padding:0 1.5rem;color:#222"><h1 style="font-size:1.25rem">Agent unavailable</h1><p>This agent isn't available right now. If you reached this page from a saved link, the agent may have been turned off.</p></body></html>`;
27611
28132
  }
27612
- app62.get("/", (c) => {
28133
+ app63.get("/", (c) => {
27613
28134
  const host = (c.req.header("host") ?? "").split(":")[0];
27614
28135
  const klass = classifyHost(host, getOperatorDomains(), isPublicHost);
27615
28136
  if (klass === "operator") {
@@ -27631,12 +28152,12 @@ app62.get("/", (c) => {
27631
28152
  console.log(`[host-class] host=${host} class=admin served=index.html`);
27632
28153
  return c.html(cachedHtml("index.html"));
27633
28154
  });
27634
- app62.get("/public", (c) => {
28155
+ app63.get("/public", (c) => {
27635
28156
  const host = (c.req.header("host") ?? "").split(":")[0];
27636
28157
  if (isPublicHost(host)) return c.text("Not found", 404);
27637
28158
  return c.html(cachedHtml("public.html"));
27638
28159
  });
27639
- app62.get("/public-chat", (c) => {
28160
+ app63.get("/public-chat", (c) => {
27640
28161
  const host = (c.req.header("host") ?? "").split(":")[0];
27641
28162
  if (isPublicHost(host)) return c.text("Not found", 404);
27642
28163
  return c.html(cachedHtml("public.html"));
@@ -27655,12 +28176,12 @@ async function logViewerFetch(c, next) {
27655
28176
  duration_ms: Date.now() - start
27656
28177
  });
27657
28178
  }
27658
- app62.use("/vnc-viewer.html", logViewerFetch);
27659
- app62.use("/vnc-popout.html", logViewerFetch);
27660
- app62.get("/vnc-popout.html", (c) => {
28179
+ app63.use("/vnc-viewer.html", logViewerFetch);
28180
+ app63.use("/vnc-popout.html", logViewerFetch);
28181
+ app63.get("/vnc-popout.html", (c) => {
27661
28182
  let html = htmlCache.get("vnc-popout.html");
27662
28183
  if (!html) {
27663
- html = readFileSync38(resolve36(process.cwd(), "public", "vnc-popout.html"), "utf-8");
28184
+ html = readFileSync39(resolve36(process.cwd(), "public", "vnc-popout.html"), "utf-8");
27664
28185
  const name = escapeHtml(BRAND.productName);
27665
28186
  html = html.replace("<title>Browser \u2014 Maxy</title>", `<title>${name}</title>`);
27666
28187
  html = html.replace("</head>", ` ${brandScript}
@@ -27670,7 +28191,7 @@ app62.get("/vnc-popout.html", (c) => {
27670
28191
  }
27671
28192
  return c.html(html);
27672
28193
  });
27673
- app62.post("/api/vnc/client-event", async (c) => {
28194
+ app63.post("/api/vnc/client-event", async (c) => {
27674
28195
  let body;
27675
28196
  try {
27676
28197
  body = await c.req.json();
@@ -27691,11 +28212,11 @@ app62.post("/api/vnc/client-event", async (c) => {
27691
28212
  });
27692
28213
  return c.json({ ok: true });
27693
28214
  });
27694
- app62.get("/g/:slug", (c) => {
28215
+ app63.get("/g/:slug", (c) => {
27695
28216
  return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
27696
28217
  });
27697
28218
  for (const pwa of PWA_SURFACES) {
27698
- app62.get(pwa.manifestPath, (c) => {
28219
+ app63.get(pwa.manifestPath, (c) => {
27699
28220
  const manifest = buildManifest(pwa, {
27700
28221
  productName: BRAND.productName,
27701
28222
  appIcon192: brandAppIcon192Path,
@@ -27711,7 +28232,7 @@ for (const pwa of PWA_SURFACES) {
27711
28232
  return c.body(JSON.stringify(manifest));
27712
28233
  });
27713
28234
  }
27714
- app62.get("/sw.js", (c) => {
28235
+ app63.get("/sw.js", (c) => {
27715
28236
  if (SW_SOURCE == null) {
27716
28237
  console.error("[pwa] op=sw status=500 reason=sw-source-missing");
27717
28238
  return c.text("Service worker unavailable", 500);
@@ -27720,12 +28241,12 @@ app62.get("/sw.js", (c) => {
27720
28241
  console.log(`[pwa] op=sw status=200 ct=${SW_CONTENT_TYPE}`);
27721
28242
  return c.body(SW_SOURCE);
27722
28243
  });
27723
- app62.get("/graph", (c) => {
28244
+ app63.get("/graph", (c) => {
27724
28245
  const host = (c.req.header("host") ?? "").split(":")[0];
27725
28246
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
27726
28247
  return c.html(cachedHtml("graph.html"));
27727
28248
  });
27728
- app62.get("/chat", (c) => {
28249
+ app63.get("/chat", (c) => {
27729
28250
  const host = (c.req.header("host") ?? "").split(":")[0];
27730
28251
  if (isOperatorHost(host, getOperatorDomains())) {
27731
28252
  console.log(`[host-class] host=${host} class=operator served=operator.html`);
@@ -27734,27 +28255,32 @@ app62.get("/chat", (c) => {
27734
28255
  if (isPublicHost(host)) return c.text("Not found", 404);
27735
28256
  return c.html(cachedHtml("chat.html"));
27736
28257
  });
27737
- app62.get("/data", (c) => {
28258
+ app63.get("/data", (c) => {
27738
28259
  const host = (c.req.header("host") ?? "").split(":")[0];
27739
28260
  if (isPublicHost(host)) return c.text("Not found", 404);
27740
28261
  return c.html(cachedHtml("data.html"));
27741
28262
  });
27742
- app62.get("/tasks", (c) => {
28263
+ app63.get("/tasks", (c) => {
27743
28264
  const host = (c.req.header("host") ?? "").split(":")[0];
27744
28265
  if (isPublicHost(host)) return c.text("Not found", 404);
27745
28266
  return c.html(cachedHtml("tasks.html"));
27746
28267
  });
27747
- app62.get("/calendar", (c) => {
28268
+ app63.get("/activity", (c) => {
28269
+ const host = (c.req.header("host") ?? "").split(":")[0];
28270
+ if (isPublicHost(host)) return c.text("Not found", 404);
28271
+ return c.html(cachedHtml("activity.html"));
28272
+ });
28273
+ app63.get("/calendar", (c) => {
27748
28274
  const host = (c.req.header("host") ?? "").split(":")[0];
27749
28275
  if (isPublicHost(host)) return c.text("Not found", 404);
27750
28276
  return c.html(cachedHtml("calendar.html"));
27751
28277
  });
27752
- app62.get("/browser", (c) => {
28278
+ app63.get("/browser", (c) => {
27753
28279
  const host = (c.req.header("host") ?? "").split(":")[0];
27754
28280
  if (isPublicHost(host) || isOperatorHost(host, getOperatorDomains())) return c.text("Not found", 404);
27755
28281
  return c.html(cachedHtml("browser.html"));
27756
28282
  });
27757
- app62.get("/:slug", async (c, next) => {
28283
+ app63.get("/:slug", async (c, next) => {
27758
28284
  const slug = c.req.param("slug");
27759
28285
  if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
27760
28286
  const account = resolveAccount();
@@ -27769,13 +28295,13 @@ app62.get("/:slug", async (c, next) => {
27769
28295
  await next();
27770
28296
  });
27771
28297
  if (brandFaviconPath !== "/favicon.ico") {
27772
- app62.get("/favicon.ico", (c) => {
28298
+ app63.get("/favicon.ico", (c) => {
27773
28299
  c.header("Cache-Control", "public, max-age=300");
27774
28300
  return c.redirect(brandFaviconPath, 302);
27775
28301
  });
27776
28302
  }
27777
- app62.use("/*", serveStatic({ root: "./public" }));
27778
- app62.all("*", (c) => {
28303
+ app63.use("/*", serveStatic({ root: "./public" }));
28304
+ app63.all("*", (c) => {
27779
28305
  const host = (c.req.header("host") ?? "").split(":")[0];
27780
28306
  const path3 = c.req.path;
27781
28307
  if (isPublicHost(host)) {
@@ -27789,14 +28315,14 @@ app62.all("*", (c) => {
27789
28315
  });
27790
28316
  var port = requirePortEnv("MAXY_UI_INTERNAL_PORT", { tag: "ui-server" });
27791
28317
  var hostname = process.env.HOSTNAME ?? "127.0.0.1";
27792
- var httpServer = serve({ fetch: app62.fetch, port, hostname });
28318
+ var httpServer = serve({ fetch: app63.fetch, port, hostname });
27793
28319
  console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27794
28320
  {
27795
- const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28321
+ const reconcilePlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27796
28322
  const reconcileScript = resolve36(reconcilePlatformRoot, "plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js");
27797
28323
  const RECONCILE_INTERVAL_MS = 12e4;
27798
28324
  const runReconcile = () => {
27799
- if (!existsSync36(reconcileScript)) return;
28325
+ if (!existsSync37(reconcileScript)) return;
27800
28326
  try {
27801
28327
  const child = spawn3(process.execPath, [reconcileScript], {
27802
28328
  env: { ...process.env, PLATFORM_ROOT: reconcilePlatformRoot },
@@ -27814,11 +28340,11 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27814
28340
  loop.unref();
27815
28341
  }
27816
28342
  {
27817
- const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28343
+ const outlookPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27818
28344
  const outlookScript = resolve36(outlookPlatformRoot, "plugins/outlook/mcp/dist/scripts/complete-registration.js");
27819
28345
  const OUTLOOK_COMPLETE_INTERVAL_MS = 3e4;
27820
28346
  const runOutlookComplete = () => {
27821
- if (!existsSync36(outlookScript)) return;
28347
+ if (!existsSync37(outlookScript)) return;
27822
28348
  try {
27823
28349
  const child = spawn3(process.execPath, [outlookScript], {
27824
28350
  env: { ...process.env, PLATFORM_ROOT: outlookPlatformRoot },
@@ -27836,19 +28362,19 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27836
28362
  outlookLoop.unref();
27837
28363
  }
27838
28364
  {
27839
- const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28365
+ const auditRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27840
28366
  const strandedAccountsDir = resolve36(auditRoot, "..", "data/accounts");
27841
28367
  const STRANDED_AUDIT_INTERVAL_MS = 3e5;
27842
28368
  const STRANDED_AGE_MS = 16 * 6e4;
27843
28369
  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;
27844
28370
  const runStrandedAudit = () => {
27845
28371
  try {
27846
- if (!existsSync36(strandedAccountsDir)) return;
28372
+ if (!existsSync37(strandedAccountsDir)) return;
27847
28373
  const now = Date.now();
27848
- for (const name of readdirSync21(strandedAccountsDir)) {
28374
+ for (const name of readdirSync23(strandedAccountsDir)) {
27849
28375
  if (!STRANDED_UUID_RE.test(name)) continue;
27850
28376
  const pendingPath2 = resolve36(strandedAccountsDir, name, "secrets/outlook/pending-devicecode.enc");
27851
- if (!existsSync36(pendingPath2)) continue;
28377
+ if (!existsSync37(pendingPath2)) continue;
27852
28378
  const ageMs = now - statSync14(pendingPath2).mtimeMs;
27853
28379
  if (ageMs > STRANDED_AGE_MS) {
27854
28380
  console.error(`[outlook-mcp] devicecode-stranded account=${name} ageSec=${Math.floor(ageMs / 1e3)}`);
@@ -27864,7 +28390,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27864
28390
  strandedLoop.unref();
27865
28391
  }
27866
28392
  {
27867
- const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28393
+ const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27868
28394
  const STORAGE_AUDIT_INTERVAL_MS = 3e5;
27869
28395
  const runStorageAuditSafe = () => {
27870
28396
  runStorageAudit(auditPlatformRoot).catch(
@@ -27886,7 +28412,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27886
28412
  pagesAuditLoop.unref();
27887
28413
  }
27888
28414
  {
27889
- const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28415
+ const publishPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27890
28416
  const publishScript = resolve36(publishPlatformRoot, "plugins/scheduling/mcp/dist/scripts/publish-availability.js");
27891
28417
  const PUBLISH_INTERVAL_MS = 3e5;
27892
28418
  const currentAccount = () => {
@@ -27898,7 +28424,7 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27898
28424
  }
27899
28425
  };
27900
28426
  const spawnPublish = (account) => {
27901
- if (!existsSync36(publishScript)) return;
28427
+ if (!existsSync37(publishScript)) return;
27902
28428
  try {
27903
28429
  const child = spawn3(process.execPath, [publishScript], {
27904
28430
  env: {
@@ -27919,8 +28445,8 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27919
28445
  const availPath = resolve36(account.accountDir, "calendar-availability.json");
27920
28446
  let hasBookingSite = false;
27921
28447
  try {
27922
- if (existsSync36(availPath)) {
27923
- const cfg = JSON.parse(readFileSync38(availPath, "utf-8"));
28448
+ if (existsSync37(availPath)) {
28449
+ const cfg = JSON.parse(readFileSync39(availPath, "utf-8"));
27924
28450
  hasBookingSite = typeof cfg.bookingDbName === "string" && cfg.bookingDbName.length > 0;
27925
28451
  }
27926
28452
  } catch {
@@ -27928,9 +28454,9 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27928
28454
  if (!hasBookingSite) return;
27929
28455
  const statePath = resolve36(account.accountDir, "state", "booking-availability", "last-publish.json");
27930
28456
  let lastSuccessAt = null;
27931
- if (existsSync36(statePath)) {
28457
+ if (existsSync37(statePath)) {
27932
28458
  try {
27933
- const rec = JSON.parse(readFileSync38(statePath, "utf-8"));
28459
+ const rec = JSON.parse(readFileSync39(statePath, "utf-8"));
27934
28460
  lastSuccessAt = rec.lastSuccessAt ?? null;
27935
28461
  } catch {
27936
28462
  console.error(`[calendar-availability] op=audit accountId=${account.accountId} snapshotAgeMs=na reason=bad-state-file`);
@@ -27953,13 +28479,14 @@ console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
27953
28479
  publishLoop.unref();
27954
28480
  }
27955
28481
  startTimeEntryCensus(() => getSession());
28482
+ startLedgerCensus(() => getSession());
27956
28483
  {
27957
- const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..");
28484
+ const auditPlatformRoot = process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..");
27958
28485
  const auditScript = resolve36(auditPlatformRoot, "plugins/connector/mcp/dist/scripts/audit-connectors.js");
27959
28486
  const auditLogDir = process.env.LOG_DIR ?? LOG_DIR;
27960
28487
  const CONNECTOR_AUDIT_INTERVAL_MS = 3e5;
27961
28488
  const runConnectorAudit = () => {
27962
- if (!existsSync36(auditScript)) return;
28489
+ if (!existsSync37(auditScript)) return;
27963
28490
  try {
27964
28491
  const child = spawn3(process.execPath, [auditScript], {
27965
28492
  env: { ...process.env, PLATFORM_ROOT: auditPlatformRoot, LOG_DIR: auditLogDir },
@@ -28030,7 +28557,7 @@ for (const m of SUBAPP_MANIFEST) {
28030
28557
  }
28031
28558
  try {
28032
28559
  const registered = [];
28033
- for (const r of app62.routes ?? []) {
28560
+ for (const r of app63.routes ?? []) {
28034
28561
  if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
28035
28562
  if (AGENT_SLUG_PATTERN.test(r.path)) {
28036
28563
  registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
@@ -28070,11 +28597,11 @@ try {
28070
28597
  var ADMINUSER_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
28071
28598
  async function runAdminUserReconcileTick() {
28072
28599
  try {
28073
- if (!existsSync36(USERS_FILE)) {
28600
+ if (!existsSync37(USERS_FILE)) {
28074
28601
  console.error("[adminuser-self-heal] skip reason=no-users-file");
28075
28602
  return;
28076
28603
  }
28077
- const usersRaw = readFileSync38(USERS_FILE, "utf-8").trim();
28604
+ const usersRaw = readFileSync39(USERS_FILE, "utf-8").trim();
28078
28605
  if (!usersRaw) {
28079
28606
  console.error("[adminuser-self-heal] skip reason=empty-users-file");
28080
28607
  return;
@@ -28092,6 +28619,7 @@ async function runAdminUserReconcileTick() {
28092
28619
  }
28093
28620
  await runAdminUserSelfHeal({ userId, accountId: account.accountId });
28094
28621
  await runUserProfileReconcile();
28622
+ await runConversationAudit();
28095
28623
  } catch (err) {
28096
28624
  console.error(`[adminuser-self-heal] rejected: ${err instanceof Error ? err.message : String(err)}`);
28097
28625
  }
@@ -28103,8 +28631,8 @@ var adminUserReconcileTimer = setInterval(() => {
28103
28631
  if (typeof adminUserReconcileTimer.unref === "function") adminUserReconcileTimer.unref();
28104
28632
  var USERS_RECONCILE_INTERVAL_MS = 60 * 60 * 1e3;
28105
28633
  function countUsersRows() {
28106
- if (!existsSync36(USERS_FILE)) return 0;
28107
- const raw = readFileSync38(USERS_FILE, "utf-8").trim();
28634
+ if (!existsSync37(USERS_FILE)) return 0;
28635
+ const raw = readFileSync39(USERS_FILE, "utf-8").trim();
28108
28636
  if (!raw) return 0;
28109
28637
  const users = JSON.parse(raw);
28110
28638
  return users.filter((u) => typeof u.userId === "string").length;
@@ -28224,7 +28752,7 @@ if (bootAccountConfig?.whatsapp) {
28224
28752
  }
28225
28753
  init({
28226
28754
  configDir: configDirForWhatsApp,
28227
- platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join38(__dirname, "..")),
28755
+ platformRoot: resolve36(process.env.MAXY_PLATFORM_ROOT ?? join39(__dirname, "..")),
28228
28756
  accountConfig: bootAccountConfig,
28229
28757
  onMessage: async (msg) => {
28230
28758
  if (msg.isOwnerMirror) {