@rubytech/create-maxy-code 0.1.315 → 0.1.317

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 (278) hide show
  1. package/package.json +2 -2
  2. package/payload/platform/lib/mcp-eager/dist/index.d.ts +0 -20
  3. package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/mcp-eager/dist/index.js +2 -1
  5. package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -1
  6. package/payload/platform/lib/mcp-eager/src/index.ts +3 -1
  7. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts +8 -0
  8. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  9. package/payload/platform/lib/mcp-lifeline/dist/index.js +71 -0
  10. package/payload/platform/lib/mcp-lifeline/dist/index.js.map +1 -0
  11. package/payload/platform/lib/mcp-lifeline/package.json +7 -0
  12. package/payload/platform/lib/mcp-lifeline/src/__tests__/lifeline.test.ts +146 -0
  13. package/payload/platform/lib/mcp-lifeline/src/index.ts +78 -0
  14. package/payload/platform/lib/mcp-lifeline/tsconfig.json +9 -0
  15. package/payload/platform/lib/mcp-lifeline/vitest.config.ts +9 -0
  16. package/payload/platform/lib/models/dist/index.d.ts +8 -0
  17. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  18. package/payload/platform/lib/models/dist/index.js +20 -1
  19. package/payload/platform/lib/models/dist/index.js.map +1 -1
  20. package/payload/platform/lib/models/src/index.ts +22 -0
  21. package/payload/platform/package.json +5 -2
  22. package/payload/platform/plugins/admin/mcp/dist/index.js +11 -10
  23. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  24. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +20 -11
  25. package/payload/platform/plugins/docs/references/admin-session.md +1 -1
  26. package/payload/platform/plugins/docs/references/admin-ui.md +5 -3
  27. package/payload/platform/plugins/docs/references/internals.md +14 -7
  28. package/payload/platform/plugins/memory/mcp/dist/index.js +32 -31
  29. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  30. package/payload/platform/plugins/memory/references/schema-estate-agent.md +32 -0
  31. package/payload/platform/plugins/outlook/mcp/dist/index.js +8 -7
  32. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  33. package/payload/platform/plugins/quickbooks/mcp/dist/index.js +12 -11
  34. package/payload/platform/plugins/quickbooks/mcp/dist/index.js.map +1 -1
  35. package/payload/platform/plugins/replicate/mcp/dist/index.js +4 -3
  36. package/payload/platform/plugins/replicate/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +11 -10
  38. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  39. package/payload/platform/scripts/__tests__/check-no-raw-mcp-registrations.test.sh +57 -0
  40. package/payload/platform/scripts/check-no-raw-mcp-registrations.mjs +70 -0
  41. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  42. package/payload/platform/services/claude-session-manager/dist/http-server.js +71 -14
  43. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  44. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +5 -0
  45. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  46. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +7 -0
  47. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  49. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +3 -12
  50. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  51. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +8 -0
  52. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  53. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +9 -0
  54. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  55. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +5 -0
  56. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  57. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +15 -0
  58. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  59. package/payload/platform/services/webchat-channel/dist/permission.d.ts +46 -0
  60. package/payload/platform/services/webchat-channel/dist/permission.d.ts.map +1 -0
  61. package/payload/platform/services/webchat-channel/dist/permission.js +56 -0
  62. package/payload/platform/services/webchat-channel/dist/permission.js.map +1 -0
  63. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  64. package/payload/platform/services/webchat-channel/dist/server.js +47 -1
  65. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  66. package/payload/platform/templates/specialists/agents/data-manager.md +3 -1
  67. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts +8 -0
  68. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  69. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js +71 -0
  70. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/dist/index.js.map +1 -0
  71. package/payload/premium-plugins/writer-craft/lib/mcp-lifeline/package.json +7 -0
  72. package/payload/premium-plugins/writer-craft/mcp/dist/index.d.ts.map +1 -1
  73. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +6 -5
  74. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  75. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +6 -5
  76. package/payload/server/{chunk-Q7EWROVN.js → chunk-NCRJQEZ3.js} +0 -101
  77. package/payload/server/maxy-edge.js +1 -1
  78. package/payload/server/public/assets/AdminLoginScreens-CrdmA3KA.js +1 -0
  79. package/payload/server/public/assets/AdminShell-0meAFBva.js +1 -0
  80. package/payload/server/public/assets/Checkbox-DXisJRUK.js +1 -0
  81. package/payload/server/public/assets/OperatorConversations-DBy2G8q3.js +9 -0
  82. package/payload/server/public/assets/OperatorConversations-DvRXfq3q.css +1 -0
  83. package/payload/server/public/assets/admin-DX5lZxWt.js +1 -0
  84. package/payload/server/public/assets/{arc-J2g2u5Xv.js → arc-CxLB9WCE.js} +1 -1
  85. package/payload/server/public/assets/architecture-YZFGNWBL-DN-MYxff.js +1 -0
  86. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CN0BXxpE.js → architectureDiagram-Q4EWVU46-D-EdJPSY.js} +1 -1
  87. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-HX-8wF2p.js → blockDiagram-DXYQGD6D-CXx9RgCm.js} +1 -1
  88. package/payload/server/public/assets/browser-Bxx8w8BA.js +1 -0
  89. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-wIuarKF5.js → c4Diagram-AHTNJAMY-RFBXEe0B.js} +1 -1
  90. package/payload/server/public/assets/channel-y27xl53N.js +1 -0
  91. package/payload/server/public/assets/chat-CT9YrNtI.js +1 -0
  92. package/payload/server/public/assets/{chunk-2KRD3SAO-Buz7egJZ.js → chunk-2KRD3SAO-DBqAFwK9.js} +1 -1
  93. package/payload/server/public/assets/{chunk-336JU56O-_JcFXJqc.js → chunk-336JU56O-DdnFEz6R.js} +2 -2
  94. package/payload/server/public/assets/chunk-426QAEUC-D8Iwaegm.js +1 -0
  95. package/payload/server/public/assets/{chunk-4BX2VUAB-DUR5Dg3M.js → chunk-4BX2VUAB-cnw-3Gbs.js} +1 -1
  96. package/payload/server/public/assets/{chunk-4TB4RGXK-BRIqQ9st.js → chunk-4TB4RGXK-BnqJ0bDc.js} +1 -1
  97. package/payload/server/public/assets/{chunk-55IACEB6-CezTHWXL.js → chunk-55IACEB6-BwyHvvzo.js} +1 -1
  98. package/payload/server/public/assets/{chunk-5FUZZQ4R-DHYUPzF1.js → chunk-5FUZZQ4R-DXA9U02I.js} +1 -1
  99. package/payload/server/public/assets/{chunk-5PVQY5BW-BVn4_fI5.js → chunk-5PVQY5BW-D78bZ_8D.js} +1 -1
  100. package/payload/server/public/assets/{chunk-67CJDMHE-BBLA8Mbi.js → chunk-67CJDMHE-CtE_Mgv7.js} +1 -1
  101. package/payload/server/public/assets/{chunk-7N4EOEYR-CdWfEI5c.js → chunk-7N4EOEYR-CUZDaySl.js} +1 -1
  102. package/payload/server/public/assets/{chunk-AA7GKIK3-tS11knCR.js → chunk-AA7GKIK3-CYQ3jO4X.js} +1 -1
  103. package/payload/server/public/assets/{chunk-BSJP7CBP-GEu1OOZ6.js → chunk-BSJP7CBP-BbA_HyTR.js} +1 -1
  104. package/payload/server/public/assets/{chunk-CIAEETIT-DKrNbbp_.js → chunk-CIAEETIT-D7_YqRhG.js} +1 -1
  105. package/payload/server/public/assets/{chunk-EDXVE4YY-B0InXNyr.js → chunk-EDXVE4YY-B23LrtSw.js} +1 -1
  106. package/payload/server/public/assets/{chunk-ENJZ2VHE-CO7lkHdm.js → chunk-ENJZ2VHE-D3fTHYKN.js} +1 -1
  107. package/payload/server/public/assets/{chunk-FMBD7UC4-CMj74lWo.js → chunk-FMBD7UC4-DFAA2tyh.js} +1 -1
  108. package/payload/server/public/assets/{chunk-FOC6F5B3-CLnKQoXw.js → chunk-FOC6F5B3-BF4IHvlI.js} +1 -1
  109. package/payload/server/public/assets/{chunk-ICPOFSXX-CdiEKIaz.js → chunk-ICPOFSXX-DBUGemHy.js} +2 -2
  110. package/payload/server/public/assets/{chunk-K5T4RW27-B6LA3fiv.js → chunk-K5T4RW27-rMMs08Eh.js} +1 -1
  111. package/payload/server/public/assets/{chunk-KGLVRYIC-DrhRrb8Q.js → chunk-KGLVRYIC-BD2r8R2G.js} +1 -1
  112. package/payload/server/public/assets/{chunk-LIHQZDEY-DVQukevB.js → chunk-LIHQZDEY-D4sYTTwM.js} +1 -1
  113. package/payload/server/public/assets/{chunk-ORNJ4GCN-ZMLkoDhP.js → chunk-ORNJ4GCN-CAs_uFzb.js} +1 -1
  114. package/payload/server/public/assets/{chunk-OYMX7WX6-C0dJkynG.js → chunk-OYMX7WX6-Fkp-2ORc.js} +1 -1
  115. package/payload/server/public/assets/chunk-QZHKN3VN-qHqDpwz3.js +1 -0
  116. package/payload/server/public/assets/{chunk-U2HBQHQK-BQ9BPIFZ.js → chunk-U2HBQHQK-D_pxZh25.js} +1 -1
  117. package/payload/server/public/assets/{chunk-X2U36JSP-CAonGMOd.js → chunk-X2U36JSP-CeVmvvRf.js} +1 -1
  118. package/payload/server/public/assets/{chunk-XPW4576I-D5C_WNlk.js → chunk-XPW4576I-iWP54fKp.js} +1 -1
  119. package/payload/server/public/assets/{chunk-YZCP3GAM-Ecdvzekb.js → chunk-YZCP3GAM-CNtbWJNN.js} +1 -1
  120. package/payload/server/public/assets/{chunk-ZZ45TVLE-BsFZd1cN.js → chunk-ZZ45TVLE-BmlFjU_9.js} +1 -1
  121. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DgVoYWhO.js +1 -0
  122. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C0WNP3uN.js +1 -0
  123. package/payload/server/public/assets/clone-D50F_pvg.js +1 -0
  124. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-DBWHaIwm.js → cose-bilkent-S5V4N54A-C7YmF1Pg.js} +1 -1
  125. package/payload/server/public/assets/{dagre-Dr7ZJYeS.js → dagre-BAmiDDtR.js} +1 -1
  126. package/payload/server/public/assets/{dagre-KV5264BT-oIJddk7m.js → dagre-KV5264BT-Ca3ESJhc.js} +1 -1
  127. package/payload/server/public/assets/data-B9NtsXgF.js +1 -0
  128. package/payload/server/public/assets/{diagram-5BDNPKRD-CEVxqOZ4.js → diagram-5BDNPKRD-BgT1ORf2.js} +1 -1
  129. package/payload/server/public/assets/{diagram-G4DWMVQ6-BovF7Rjx.js → diagram-G4DWMVQ6-BTaUIiem.js} +1 -1
  130. package/payload/server/public/assets/{diagram-MMDJMWI5-BhrF8zoF.js → diagram-MMDJMWI5-Bdb2g6Uo.js} +1 -1
  131. package/payload/server/public/assets/{diagram-TYMM5635-DCUYwxtR.js → diagram-TYMM5635-CkLGC0zZ.js} +1 -1
  132. package/payload/server/public/assets/{dist-DSsFp0Qd.js → dist-Bkbhs3jw.js} +1 -1
  133. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BS2-HdCg.js → erDiagram-SMLLAGMA-D_sj4DMg.js} +1 -1
  134. package/payload/server/public/assets/{flatten-BZMXCpLh.js → flatten-E2Sr0FeD.js} +1 -1
  135. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BzSFLoea.js → flowDiagram-DWJPFMVM-iLERoZTe.js} +1 -1
  136. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-1-3QU7mT.js → ganttDiagram-T4ZO3ILL-D60hjMBy.js} +1 -1
  137. package/payload/server/public/assets/gitGraph-7Q5UKJZL-D-L2yzYf.js +1 -0
  138. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-fTrJ35Wk.js → gitGraphDiagram-UUTBAWPF-Di0XM6fi.js} +1 -1
  139. package/payload/server/public/assets/{graph-Dx2a6vGB.js → graph-B59N222f.js} +3 -3
  140. package/payload/server/public/assets/graph-labels-70w-1ov0.js +1 -0
  141. package/payload/server/public/assets/{graphlib-rlEzI2qD.js → graphlib-C8fUP7uV.js} +1 -1
  142. package/payload/server/public/assets/info-OMHHGYJF-BQn6jndO.js +1 -0
  143. package/payload/server/public/assets/infoDiagram-42DDH7IO-BwMdbiXg.js +2 -0
  144. package/payload/server/public/assets/{isEmpty-DaYIrHay.js → isEmpty-CLz-UprQ.js} +1 -1
  145. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-0eU_UtlT.js → ishikawaDiagram-UXIWVN3A-CwgI4B5Z.js} +1 -1
  146. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-BKLeZohp.js → journeyDiagram-VCZTEJTY-CxBu-tze.js} +1 -1
  147. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-Dq72xyaN.js → kanban-definition-6JOO6SKY-D2qlheA5.js} +1 -1
  148. package/payload/server/public/assets/{line-LQhmDT8k.js → line-Bdod7uzQ.js} +1 -1
  149. package/payload/server/public/assets/{linear-BGotDbGs.js → linear-BiVe6QzC.js} +1 -1
  150. package/payload/server/public/assets/{mermaid-parser.core-DoLdho1V.js → mermaid-parser.core-xZN7hC6M.js} +2 -2
  151. package/payload/server/public/assets/{mermaid.core-C1RRyHGm.js → mermaid.core-D0IylAac.js} +3 -3
  152. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-vUVVVyV1.js → mindmap-definition-QFDTVHPH-J_Szhwf1.js} +1 -1
  153. package/payload/server/public/assets/operator-DpRAhwQN.js +1 -0
  154. package/payload/server/public/assets/{ordinal-BqEhkPyh.js → ordinal-5RtyPJVt.js} +1 -1
  155. package/payload/server/public/assets/packet-4T2RLAQJ-DmkQBx4h.js +1 -0
  156. package/payload/server/public/assets/page-Ehjc9b9V.js +30 -0
  157. package/payload/server/public/assets/pie-ZZUOXDRM-DDnxYUBm.js +1 -0
  158. package/payload/server/public/assets/{pieDiagram-DEJITSTG-B9Pl6Qhc.js → pieDiagram-DEJITSTG-CV5DxUVx.js} +1 -1
  159. package/payload/server/public/assets/public-BcqXGSaE.js +1 -0
  160. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Drn9T81A.js → quadrantDiagram-34T5L4WZ-BsFMVizF.js} +1 -1
  161. package/payload/server/public/assets/radar-PYXPWWZC-7H4k0ChM.js +1 -0
  162. package/payload/server/public/assets/{reduce-T2IuntYP.js → reduce-B3Mw_0s1.js} +1 -1
  163. package/payload/server/public/assets/{requirementDiagram-MS252O5E-C0PAItJm.js → requirementDiagram-MS252O5E-C5eRRvGc.js} +1 -1
  164. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BR42Mtwd.js → sankeyDiagram-XADWPNL6-CJYv5gpw.js} +1 -1
  165. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-c2lR9UOS.js → sequenceDiagram-FGHM5R23-B25563_2.js} +1 -1
  166. package/payload/server/public/assets/{src-DXUM2BJo.js → src-BKOAoFQc.js} +1 -1
  167. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BcHhtqsZ.js → stateDiagram-FHFEXIEX-BLyNJYOA.js} +1 -1
  168. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BSVuxZxz.js +1 -0
  169. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Ax32c10H.js → timeline-definition-GMOUNBTQ-D-HgOM6Q.js} +1 -1
  170. package/payload/server/public/assets/treeView-SZITEDCU-BLXWTQtW.js +1 -0
  171. package/payload/server/public/assets/treemap-W4RFUUIX-DiePDF5d.js +1 -0
  172. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BxePewPq.js → vennDiagram-DHZGUBPP-Cw1JElYp.js} +1 -1
  173. package/payload/server/public/assets/wardley-RL74JXVD-OSUWK5LN.js +1 -0
  174. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DmJwZ2f5.js → wardleyDiagram-NUSXRM2D-BqMWzEko.js} +1 -1
  175. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-YjHomudv.js → xychartDiagram-5P7HB3ND-DBp71TLT.js} +1 -1
  176. package/payload/server/public/browser.html +5 -8
  177. package/payload/server/public/chat.html +8 -12
  178. package/payload/server/public/data.html +5 -7
  179. package/payload/server/public/graph.html +7 -10
  180. package/payload/server/public/index.html +8 -11
  181. package/payload/server/public/operator.html +10 -14
  182. package/payload/server/public/public.html +8 -10
  183. package/payload/server/server.js +376 -226
  184. package/payload/server/public/assets/AccessGate-B0sCa0QJ.js +0 -1
  185. package/payload/server/public/assets/AdminLoginScreens-C7Oaqpr6.js +0 -1
  186. package/payload/server/public/assets/AdminShell-DgK7TWCI.js +0 -1
  187. package/payload/server/public/assets/Checkbox-C4m1jfdP.js +0 -1
  188. package/payload/server/public/assets/OperatorConversations-qc_xy7Az.css +0 -1
  189. package/payload/server/public/assets/OperatorConversations-z2mSY_eQ.js +0 -1
  190. package/payload/server/public/assets/admin-DxYk1Ghu.js +0 -1
  191. package/payload/server/public/assets/architecture-YZFGNWBL-C6nkAxzW.js +0 -1
  192. package/payload/server/public/assets/audio-attachment-mime-BXj3DB3Y.js +0 -30
  193. package/payload/server/public/assets/brand-BwWvCHLs.css +0 -1
  194. package/payload/server/public/assets/brand-DOgCGEoD.js +0 -9
  195. package/payload/server/public/assets/browser-NzxOujfD.js +0 -1
  196. package/payload/server/public/assets/channel-Q39xIXyT.js +0 -1
  197. package/payload/server/public/assets/chat-CEQTEN5z.js +0 -1
  198. package/payload/server/public/assets/chunk-426QAEUC-CCYjp9C2.js +0 -1
  199. package/payload/server/public/assets/chunk-QZHKN3VN-BNBxnHZh.js +0 -1
  200. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BShusfby.js +0 -1
  201. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D4ivPLFF.js +0 -1
  202. package/payload/server/public/assets/clone-CjEM8LwB.js +0 -1
  203. package/payload/server/public/assets/data-CTROHvif.js +0 -1
  204. package/payload/server/public/assets/gitGraph-7Q5UKJZL-Btp3PwZh.js +0 -1
  205. package/payload/server/public/assets/graph-labels-Dxqq08v6.js +0 -1
  206. package/payload/server/public/assets/info-OMHHGYJF-CPt2y6_L.js +0 -1
  207. package/payload/server/public/assets/infoDiagram-42DDH7IO-CpXNTMgd.js +0 -2
  208. package/payload/server/public/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  209. package/payload/server/public/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  210. package/payload/server/public/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  211. package/payload/server/public/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  212. package/payload/server/public/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  213. package/payload/server/public/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  214. package/payload/server/public/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  215. package/payload/server/public/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  216. package/payload/server/public/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  217. package/payload/server/public/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  218. package/payload/server/public/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  219. package/payload/server/public/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  220. package/payload/server/public/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  221. package/payload/server/public/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  222. package/payload/server/public/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  223. package/payload/server/public/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  224. package/payload/server/public/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  225. package/payload/server/public/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  226. package/payload/server/public/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  227. package/payload/server/public/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  228. package/payload/server/public/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  229. package/payload/server/public/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  230. package/payload/server/public/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  231. package/payload/server/public/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  232. package/payload/server/public/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  233. package/payload/server/public/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  234. package/payload/server/public/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  235. package/payload/server/public/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  236. package/payload/server/public/assets/newsreader-latin-300-normal-AOSWdb_s.woff +0 -0
  237. package/payload/server/public/assets/newsreader-latin-300-normal-FGBQ0wlI.woff2 +0 -0
  238. package/payload/server/public/assets/newsreader-latin-400-normal-BFBkh4jY.woff2 +0 -0
  239. package/payload/server/public/assets/newsreader-latin-400-normal-gRTjlS2D.woff +0 -0
  240. package/payload/server/public/assets/newsreader-latin-500-normal-B66TYsaK.woff2 +0 -0
  241. package/payload/server/public/assets/newsreader-latin-500-normal-DFwuUcdu.woff +0 -0
  242. package/payload/server/public/assets/newsreader-latin-ext-300-normal-CFtw49Zd.woff +0 -0
  243. package/payload/server/public/assets/newsreader-latin-ext-300-normal-DRMzurxT.woff2 +0 -0
  244. package/payload/server/public/assets/newsreader-latin-ext-400-normal-DYA1XoQK.woff +0 -0
  245. package/payload/server/public/assets/newsreader-latin-ext-400-normal-svq1FPys.woff2 +0 -0
  246. package/payload/server/public/assets/newsreader-latin-ext-500-normal-BNHmvKvI.woff2 +0 -0
  247. package/payload/server/public/assets/newsreader-latin-ext-500-normal-CZruMFou.woff +0 -0
  248. package/payload/server/public/assets/newsreader-vietnamese-300-normal-CsrIkm-V.woff +0 -0
  249. package/payload/server/public/assets/newsreader-vietnamese-300-normal-D3VHEe81.woff2 +0 -0
  250. package/payload/server/public/assets/newsreader-vietnamese-400-normal-BekUZro8.woff +0 -0
  251. package/payload/server/public/assets/newsreader-vietnamese-400-normal-DdKr49mV.woff2 +0 -0
  252. package/payload/server/public/assets/newsreader-vietnamese-500-normal-BEAbKU8A.woff +0 -0
  253. package/payload/server/public/assets/newsreader-vietnamese-500-normal-CL6a8tp2.woff2 +0 -0
  254. package/payload/server/public/assets/operator-BTHMTwNI.js +0 -1
  255. package/payload/server/public/assets/packet-4T2RLAQJ-Cwc-j_AI.js +0 -1
  256. package/payload/server/public/assets/page-B9fQp1g9.js +0 -1
  257. package/payload/server/public/assets/pie-ZZUOXDRM-BZ9fjD1_.js +0 -1
  258. package/payload/server/public/assets/public-cuggl7du.js +0 -6
  259. package/payload/server/public/assets/public-next-apqAebbA.js +0 -1
  260. package/payload/server/public/assets/public-vnj7OhQj.css +0 -1
  261. package/payload/server/public/assets/radar-PYXPWWZC-BNz5Rt9V.js +0 -1
  262. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BUQ_F4eP.js +0 -1
  263. package/payload/server/public/assets/treeView-SZITEDCU-DcVCQgp1.js +0 -1
  264. package/payload/server/public/assets/treemap-W4RFUUIX-Bm12mwGd.js +0 -1
  265. package/payload/server/public/assets/useSelectionMode-DlgEcMtA.js +0 -5
  266. package/payload/server/public/assets/wardley-RL74JXVD-47Z3ymtK.js +0 -1
  267. package/payload/server/public/public-next.html +0 -25
  268. /package/payload/server/public/assets/{_baseFor-Y5mTRiRv.js → _baseFor-DVaNaTfF.js} +0 -0
  269. /package/payload/server/public/assets/{admin-types-D2qTXuCg.js → admin-types-CJrGd46U.js} +0 -0
  270. /package/payload/server/public/assets/{array-BwJyW1Dp.js → array-8_H1156C.js} +0 -0
  271. /package/payload/server/public/assets/{chunk-CAM3fms7.js → chunk-Pqm5yXtL.js} +0 -0
  272. /package/payload/server/public/assets/{cytoscape.esm-D95TtHqz.js → cytoscape.esm-h10p_6j-.js} +0 -0
  273. /package/payload/server/public/assets/{defaultLocale-kiwRz9Au.js → defaultLocale-pD7tFa1r.js} +0 -0
  274. /package/payload/server/public/assets/{init-CKZirZ49.js → init-CwJ4b81e.js} +0 -0
  275. /package/payload/server/public/assets/{katex-8mXVa4k3.js → katex-DJPjIBAI.js} +0 -0
  276. /package/payload/server/public/assets/{path-B0d9ncVi.js → path-CK8wrAxY.js} +0 -0
  277. /package/payload/server/public/assets/{preload-helper-C5gCWwwF.js → preload-helper-Bf_JiD2A.js} +0 -0
  278. /package/payload/server/public/assets/{rough.esm-BWqoIFNR.js → rough.esm-Dwml_la6.js} +0 -0
@@ -27,9 +27,7 @@ import {
27
27
  WEBSOCKIFY_PORT,
28
28
  accessPasswordCollides,
29
29
  autoDeliverPremiumPlugins,
30
- bindVisitorToGroup,
31
30
  canAccessAdmin,
32
- checkGroupMembership,
33
31
  checkRateLimit,
34
32
  classifyHost,
35
33
  cleanupLeakedPremiumSubs,
@@ -42,7 +40,6 @@ import {
42
40
  emitMissingOnResolve,
43
41
  ensureConversation,
44
42
  fetchBranding,
45
- findGroupBySlug,
46
43
  findMissingPlugins,
47
44
  findRecentConversation,
48
45
  fingerprintSessionKey,
@@ -50,7 +47,6 @@ import {
50
47
  getAgentSessionIdForConversation,
51
48
  getConversationClaudeSessionIds,
52
49
  getDefaultAccountId,
53
- getGroupParticipants,
54
50
  getOperatorDomains,
55
51
  getRecentMessages,
56
52
  getRoleForSession,
@@ -110,7 +106,7 @@ import {
110
106
  vncLog,
111
107
  walkPremiumBundles,
112
108
  writeAdminUserAndPerson
113
- } from "./chunk-Q7EWROVN.js";
109
+ } from "./chunk-NCRJQEZ3.js";
114
110
  import {
115
111
  __commonJS,
116
112
  __toESM
@@ -532,63 +528,63 @@ var require_dist2 = __commonJS({
532
528
  }
533
529
  function pickShortLabel(node) {
534
530
  const props = node.properties;
535
- const primaryLabel = node.labels[0];
536
- if (primaryLabel === "ToolCall") {
531
+ const primaryLabel2 = node.labels[0];
532
+ if (primaryLabel2 === "ToolCall") {
537
533
  const v = props.toolName;
538
534
  if (typeof v === "string" && v.length > 0) {
539
535
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
540
536
  }
541
- } else if (primaryLabel === "WorkflowRun") {
537
+ } else if (primaryLabel2 === "WorkflowRun") {
542
538
  const v = props.startedAt;
543
539
  if (typeof v === "string" && v.length > 0) {
544
540
  const ts = formatRunTimestamp(v);
545
541
  if (ts)
546
542
  return ts;
547
543
  }
548
- } else if (primaryLabel === "WorkflowStep") {
544
+ } else if (primaryLabel2 === "WorkflowStep") {
549
545
  const v = props.label;
550
546
  if (typeof v === "string" && v.length > 0) {
551
547
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
552
548
  }
553
- } else if (primaryLabel === "Person") {
549
+ } else if (primaryLabel2 === "Person") {
554
550
  const given = typeof props.givenName === "string" ? props.givenName : "";
555
551
  const family = typeof props.familyName === "string" ? props.familyName : "";
556
552
  const full = [given, family].filter((s) => s.length > 0).join(" ");
557
553
  if (full.length > 0) {
558
554
  return full.length > 24 ? full.slice(0, 24) + "\u2026" : full;
559
555
  }
560
- } else if (primaryLabel === "Agent") {
556
+ } else if (primaryLabel2 === "Agent") {
561
557
  const dn = typeof props.displayName === "string" ? props.displayName : "";
562
558
  const slug = typeof props.slug === "string" ? props.slug : "";
563
559
  const v = dn.length > 0 ? dn : slug;
564
560
  if (v.length > 0) {
565
561
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
566
562
  }
567
- } else if (primaryLabel === "Job") {
563
+ } else if (primaryLabel2 === "Job") {
568
564
  const client = typeof props.client === "string" ? props.client : "";
569
565
  const jobId = typeof props.jobId === "string" ? props.jobId : "";
570
566
  const composed = [client, jobId.length > 0 ? `#${jobId}` : ""].filter((s) => s.length > 0).join(" ");
571
567
  if (composed.length > 0) {
572
568
  return composed.length > 24 ? composed.slice(0, 24) + "\u2026" : composed;
573
569
  }
574
- } else if (primaryLabel === "QuoteDocument") {
570
+ } else if (primaryLabel2 === "QuoteDocument") {
575
571
  const ref = typeof props.ref === "string" ? props.ref : "";
576
572
  if (ref.length > 0) {
577
573
  return ref.length > 24 ? ref.slice(0, 24) + "\u2026" : ref;
578
574
  }
579
- } else if (primaryLabel === "InboundInvoice") {
575
+ } else if (primaryLabel2 === "InboundInvoice") {
580
576
  const supplier = typeof props.supplier === "string" ? props.supplier : "";
581
577
  const conf = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
582
578
  const composed = [supplier, conf.length > 0 ? `#${conf}` : ""].filter((s) => s.length > 0).join(" ");
583
579
  if (composed.length > 0) {
584
580
  return composed.length > 24 ? composed.slice(0, 24) + "\u2026" : composed;
585
581
  }
586
- } else if (primaryLabel === "WhatsAppGroup") {
582
+ } else if (primaryLabel2 === "WhatsAppGroup") {
587
583
  const clientName = typeof props.clientName === "string" ? props.clientName : "";
588
584
  if (clientName.length > 0) {
589
585
  return clientName.length > 24 ? clientName.slice(0, 24) + "\u2026" : clientName;
590
586
  }
591
- } else if (primaryLabel === "Message") {
587
+ } else if (primaryLabel2 === "Message") {
592
588
  const role = typeof props.role === "string" ? props.role : "";
593
589
  const roleShort = role === "user" ? "user" : role === "assistant" ? "asst" : role === "system" ? "sys" : role === "tool" ? "tool" : null;
594
590
  const createdAt = typeof props.createdAt === "string" ? props.createdAt : "";
@@ -604,60 +600,60 @@ var require_dist2 = __commonJS({
604
600
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
605
601
  }
606
602
  }
607
- if (primaryLabel === "Conversation") {
603
+ if (primaryLabel2 === "Conversation") {
608
604
  const id = typeof props.sessionId === "string" ? props.sessionId : null;
609
605
  if (id)
610
606
  return `Conv ${id.slice(0, 8)}`;
611
607
  }
612
- return primaryLabel ?? "\u2026";
608
+ return primaryLabel2 ?? "\u2026";
613
609
  }
614
610
  function pickDisplayName(node) {
615
611
  const props = node.properties;
616
- const primaryLabel = node.labels[0];
617
- if (primaryLabel === "ToolCall") {
612
+ const primaryLabel2 = node.labels[0];
613
+ if (primaryLabel2 === "ToolCall") {
618
614
  const v = props.toolName;
619
615
  if (typeof v === "string" && v.length > 0)
620
616
  return v;
621
- } else if (primaryLabel === "WorkflowRun") {
617
+ } else if (primaryLabel2 === "WorkflowRun") {
622
618
  const v = props.startedAt;
623
619
  if (typeof v === "string" && v.length > 0) {
624
620
  const ts = formatRunTimestamp(v);
625
621
  if (ts)
626
622
  return ts;
627
623
  }
628
- } else if (primaryLabel === "WorkflowStep") {
624
+ } else if (primaryLabel2 === "WorkflowStep") {
629
625
  const v = props.label;
630
626
  if (typeof v === "string" && v.length > 0)
631
627
  return v;
632
- } else if (primaryLabel === "Person") {
628
+ } else if (primaryLabel2 === "Person") {
633
629
  const given = typeof props.givenName === "string" ? props.givenName : "";
634
630
  const family = typeof props.familyName === "string" ? props.familyName : "";
635
631
  const full = [given, family].filter((s) => s.length > 0).join(" ");
636
632
  if (full.length > 0)
637
633
  return full;
638
- } else if (primaryLabel === "Agent") {
634
+ } else if (primaryLabel2 === "Agent") {
639
635
  const dn = typeof props.displayName === "string" ? props.displayName : "";
640
636
  const slug = typeof props.slug === "string" ? props.slug : "";
641
637
  const v = dn.length > 0 ? dn : slug;
642
638
  if (v.length > 0)
643
639
  return v;
644
- } else if (primaryLabel === "Job") {
640
+ } else if (primaryLabel2 === "Job") {
645
641
  const client = typeof props.client === "string" ? props.client : "";
646
642
  const jobId = typeof props.jobId === "string" ? props.jobId : "";
647
643
  const composed = [client, jobId.length > 0 ? `#${jobId}` : ""].filter((s) => s.length > 0).join(" ");
648
644
  if (composed.length > 0)
649
645
  return composed;
650
- } else if (primaryLabel === "QuoteDocument") {
646
+ } else if (primaryLabel2 === "QuoteDocument") {
651
647
  const ref = typeof props.ref === "string" ? props.ref : "";
652
648
  if (ref.length > 0)
653
649
  return ref;
654
- } else if (primaryLabel === "InboundInvoice") {
650
+ } else if (primaryLabel2 === "InboundInvoice") {
655
651
  const supplier = typeof props.supplier === "string" ? props.supplier : "";
656
652
  const conf = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
657
653
  const composed = [supplier, conf.length > 0 ? `#${conf}` : ""].filter((s) => s.length > 0).join(" ");
658
654
  if (composed.length > 0)
659
655
  return composed;
660
- } else if (primaryLabel === "WhatsAppGroup") {
656
+ } else if (primaryLabel2 === "WhatsAppGroup") {
661
657
  const clientName = typeof props.clientName === "string" ? props.clientName : "";
662
658
  if (clientName.length > 0)
663
659
  return clientName;
@@ -667,12 +663,12 @@ var require_dist2 = __commonJS({
667
663
  if (typeof v === "string" && v.length > 0)
668
664
  return v;
669
665
  }
670
- if (primaryLabel === "Conversation") {
666
+ if (primaryLabel2 === "Conversation") {
671
667
  const id = typeof props.sessionId === "string" ? props.sessionId : null;
672
668
  if (id)
673
669
  return `Conv ${id.slice(0, 8)}`;
674
670
  }
675
- return primaryLabel ?? "\u2026";
671
+ return primaryLabel2 ?? "\u2026";
676
672
  }
677
673
  }
678
674
  });
@@ -6891,7 +6887,6 @@ function resolveTitle(body, sessionId, userTitles) {
6891
6887
  const channel = stripped.channel;
6892
6888
  if (userTitle) return { title: trimToTitle(userTitle), source: "user", channel };
6893
6889
  if (aiTitle) return { title: trimToTitle(aiTitle), source: "ai", channel };
6894
- if (stripped.inner) return { title: trimToTitle(stripped.inner), source: "first-message", channel };
6895
6890
  return { title: sessionId.slice(0, 8), source: "prefix", channel };
6896
6891
  }
6897
6892
  app3.get("/", requireAdminSession, async (c) => {
@@ -6971,7 +6966,7 @@ app3.get("/", requireAdminSession, async (c) => {
6971
6966
  if (accountId) {
6972
6967
  await Promise.all(
6973
6968
  rows.map(async (row) => {
6974
- if (row.titleSource !== "first-message" && row.titleSource !== "prefix") return;
6969
+ if (row.titleSource !== "prefix") return;
6975
6970
  const pid = personIdBySession.get(row.sessionId);
6976
6971
  if (pid) {
6977
6972
  const name = await loadPersonNameByElementId(accountId, pid);
@@ -7954,18 +7949,37 @@ var UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-f
7954
7949
  function canonicalOverridePath(accountDir) {
7955
7950
  return join13(accountDir, FILE);
7956
7951
  }
7957
- function readCanonicalOverrideId(accountDir) {
7952
+ function readRaw(accountDir) {
7958
7953
  try {
7959
- const raw = JSON.parse(readFileSync14(canonicalOverridePath(accountDir), "utf8"));
7960
- return typeof raw.sessionId === "string" && UUID.test(raw.sessionId) ? raw.sessionId : null;
7954
+ return JSON.parse(readFileSync14(canonicalOverridePath(accountDir), "utf8"));
7961
7955
  } catch {
7962
7956
  return null;
7963
7957
  }
7964
7958
  }
7965
- function writeCanonicalOverrideId(accountDir, sessionId) {
7959
+ function readCanonicalOverrideId(accountDir, userId, primaryUserId) {
7960
+ const raw = readRaw(accountDir);
7961
+ if (!raw) return null;
7962
+ if (raw.byAdmin && typeof raw.byAdmin === "object") {
7963
+ const v = raw.byAdmin[userId];
7964
+ return typeof v === "string" && UUID.test(v) ? v : null;
7965
+ }
7966
+ if (typeof raw.sessionId === "string" && UUID.test(raw.sessionId) && primaryUserId !== null && userId === primaryUserId) {
7967
+ return raw.sessionId;
7968
+ }
7969
+ return null;
7970
+ }
7971
+ function writeCanonicalOverrideId(accountDir, userId, sessionId) {
7972
+ const raw = readRaw(accountDir);
7973
+ const byAdmin = {};
7974
+ if (raw?.byAdmin && typeof raw.byAdmin === "object") {
7975
+ for (const [k, v] of Object.entries(raw.byAdmin)) {
7976
+ if (typeof v === "string") byAdmin[k] = v;
7977
+ }
7978
+ }
7979
+ byAdmin[userId] = sessionId;
7966
7980
  const path2 = canonicalOverridePath(accountDir);
7967
7981
  const tmp = `${path2}.${process.pid}.tmp`;
7968
- writeFileSync5(tmp, JSON.stringify({ sessionId }, null, 2), "utf8");
7982
+ writeFileSync5(tmp, JSON.stringify({ byAdmin }, null, 2), "utf8");
7969
7983
  renameSync(tmp, path2);
7970
7984
  }
7971
7985
 
@@ -7981,6 +7995,33 @@ function adminSessionIdFor(accountId, senderId, personId) {
7981
7995
  return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
7982
7996
  }
7983
7997
 
7998
+ // ../lib/models/src/index.ts
7999
+ var OPUS_MODEL = "claude-opus-4-8[1m]";
8000
+ var SONNET_MODEL = "claude-sonnet-4-6";
8001
+ var HAIKU_MODEL = "claude-haiku-4-5";
8002
+ var MODEL_CONTEXT_WINDOW = {
8003
+ [OPUS_MODEL]: 1e6,
8004
+ [SONNET_MODEL]: 2e5,
8005
+ [HAIKU_MODEL]: 2e5
8006
+ };
8007
+ var MODEL_DISPLAY_NAMES = {
8008
+ [OPUS_MODEL]: "Opus 4.8 (1M context)",
8009
+ [SONNET_MODEL]: "Sonnet 4.6",
8010
+ [HAIKU_MODEL]: "Haiku 4.5"
8011
+ };
8012
+ var SELECTABLE_MODELS = [OPUS_MODEL, SONNET_MODEL, HAIKU_MODEL];
8013
+ function isSelectableModel(id) {
8014
+ return SELECTABLE_MODELS.includes(id);
8015
+ }
8016
+ var PERMISSION_MODES = ["default", "acceptEdits", "plan", "auto", "bypassPermissions"];
8017
+ function isPermissionMode(value) {
8018
+ return PERMISSION_MODES.includes(value);
8019
+ }
8020
+ var EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
8021
+ function isEffortLevel(value) {
8022
+ return EFFORT_LEVELS.includes(value);
8023
+ }
8024
+
7984
8025
  // ../services/claude-session-manager/src/sidecar-store.ts
7985
8026
  import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync as readdirSync9, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
7986
8027
  import { join as join14 } from "path";
@@ -8134,11 +8175,25 @@ function locateSidecar(sessionId) {
8134
8175
  for (const slug of slugs) {
8135
8176
  const metaPath = join15(projectsRoot, slug, `${sessionId}.meta.json`);
8136
8177
  if (existsSync9(metaPath)) {
8137
- return { channel: readSidecarMeta(metaPath).channel };
8178
+ const meta = readSidecarMeta(metaPath);
8179
+ return { channel: meta.channel, adminUserId: meta.adminUserId };
8138
8180
  }
8139
8181
  }
8140
8182
  return null;
8141
8183
  }
8184
+ function readTargetOwner(sessionId) {
8185
+ const sidecar = locateSidecar(sessionId);
8186
+ if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
8187
+ const { projectDir } = locateSession(sessionId);
8188
+ if (projectDir !== null) {
8189
+ return { found: true, owner: readSidecarMeta(join15(projectDir, `${sessionId}.meta.json`)).adminUserId };
8190
+ }
8191
+ return { found: false, owner: null };
8192
+ }
8193
+ function ownedByRequester(owner, requesterUserId, primaryUserId) {
8194
+ if (requesterUserId === null) return false;
8195
+ return owner === requesterUserId || owner === null && requesterUserId === primaryUserId;
8196
+ }
8142
8197
  function sessionSidecarExists(sessionId) {
8143
8198
  return locateSidecar(sessionId) !== null;
8144
8199
  }
@@ -8189,8 +8244,6 @@ async function fetchComposerIndicators(sessionId) {
8189
8244
  }
8190
8245
  }
8191
8246
  var MODEL_ID_PATTERN = /^claude-[a-z0-9][a-z0-9.-]*(\[1m\])?$/;
8192
- var EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
8193
- var PERMISSION_MODE_VALUES = /* @__PURE__ */ new Set(["default", "acceptEdits", "plan", "auto", "bypassPermissions"]);
8194
8247
  function readLevers(preResolved) {
8195
8248
  let account = preResolved;
8196
8249
  if (account === void 0) {
@@ -8206,11 +8259,20 @@ function readLevers(preResolved) {
8206
8259
  const mode = account.config.adminPermissionMode;
8207
8260
  return {
8208
8261
  leverModel: typeof model === "string" && MODEL_ID_PATTERN.test(model) ? model : null,
8209
- leverEffort: typeof effort === "string" && EFFORT_LEVELS.has(effort) ? effort : null,
8210
- leverMode: typeof mode === "string" && PERMISSION_MODE_VALUES.has(mode) ? mode : null
8262
+ leverEffort: typeof effort === "string" && isEffortLevel(effort) ? effort : null,
8263
+ leverMode: typeof mode === "string" && isPermissionMode(mode) ? mode : null
8211
8264
  };
8212
8265
  }
8213
- function latestAdminWebchatSessionId() {
8266
+ function resolvePrimaryAdminUserId() {
8267
+ try {
8268
+ const users = readUsersFile(USERS_FILE);
8269
+ return users && users.length > 0 ? users[0].userId : null;
8270
+ } catch {
8271
+ return null;
8272
+ }
8273
+ }
8274
+ function latestAdminWebchatSessionId(requesterUserId, primaryUserId) {
8275
+ if (requesterUserId === null) return null;
8214
8276
  const cfg = claudeConfigDir();
8215
8277
  if (!cfg) return null;
8216
8278
  let best = null;
@@ -8225,6 +8287,13 @@ function latestAdminWebchatSessionId() {
8225
8287
  } catch {
8226
8288
  continue;
8227
8289
  }
8290
+ const owned = meta.adminUserId === requesterUserId || meta.adminUserId === null && requesterUserId === primaryUserId;
8291
+ if (!owned) {
8292
+ if (best === null || mtimeMs > best.mtimeMs) {
8293
+ console.error(`[webchat:inbound] op=owner-skip candidate=${id.slice(0, 8)} owner=${meta.adminUserId ? meta.adminUserId.slice(0, 8) : "none"} requester=${requesterUserId.slice(0, 8)}`);
8294
+ }
8295
+ continue;
8296
+ }
8228
8297
  if (best === null || mtimeMs > best.mtimeMs) best = { id, mtimeMs };
8229
8298
  }
8230
8299
  return best === null ? null : best.id;
@@ -8234,14 +8303,17 @@ function overrideKnownNonArchived(id) {
8234
8303
  if (projectDir === null) return sessionSidecarExists(id);
8235
8304
  return basename4(projectDir) !== "archive";
8236
8305
  }
8237
- function resolveCanonical(accountId, accountDir) {
8238
- const latest = latestAdminWebchatSessionId();
8306
+ function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId) {
8307
+ if (requesterUserId === null) {
8308
+ return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY), source: "canonical-empty" };
8309
+ }
8310
+ const latest = latestAdminWebchatSessionId(requesterUserId, primaryUserId);
8239
8311
  if (latest !== null) return { sessionId: latest, source: "latest" };
8240
8312
  if (accountDir) {
8241
- const override = readCanonicalOverrideId(accountDir);
8313
+ const override = readCanonicalOverrideId(accountDir, requesterUserId, primaryUserId);
8242
8314
  if (override && overrideKnownNonArchived(override)) return { sessionId: override, source: "override" };
8243
8315
  }
8244
- return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY), source: "canonical-empty" };
8316
+ return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY, requesterUserId), source: "canonical-empty" };
8245
8317
  }
8246
8318
  var REAPPLY_TIMEOUT_MS = 1500;
8247
8319
  async function reapplyLeversViaManager() {
@@ -8274,6 +8346,9 @@ function createWebchatRoutes(deps) {
8274
8346
  console.error(`[webchat:inbound] op=send-refused reason=account-unresolved detail=${detail}`);
8275
8347
  return c.json({ error: "account unresolved" }, 503);
8276
8348
  }
8349
+ const cacheKey = c.get("cacheKey");
8350
+ const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
8351
+ const primaryUserId = resolvePrimaryAdminUserId();
8277
8352
  let text;
8278
8353
  let target;
8279
8354
  let files = [];
@@ -8314,10 +8389,18 @@ function createWebchatRoutes(deps) {
8314
8389
  }
8315
8390
  let deliveryKey = WEBCHAT_ADMIN_KEY;
8316
8391
  let deliverySessionId;
8392
+ const explicitTarget = target !== void 0;
8317
8393
  if (target === void 0) {
8318
- const latest = latestAdminWebchatSessionId();
8394
+ const latest = latestAdminWebchatSessionId(requesterUserId, primaryUserId);
8319
8395
  if (latest !== null) target = latest;
8320
8396
  }
8397
+ if (explicitTarget && target !== void 0) {
8398
+ const t = readTargetOwner(target);
8399
+ if (t.found && !ownedByRequester(t.owner, requesterUserId, primaryUserId)) {
8400
+ console.error(`[webchat:inbound] op=send-refused key=session:${target.slice(0, 8)} reason=foreign-target requester=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8401
+ return c.json({ error: "session not found" }, 404);
8402
+ }
8403
+ }
8321
8404
  if (target !== void 0) {
8322
8405
  let { projectDir, channel } = locateSession(target);
8323
8406
  if (projectDir === null) {
@@ -8393,10 +8476,11 @@ ${note}` : note;
8393
8476
  }
8394
8477
  console.log(`[webchat:inbound] op=send-accepted kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
8395
8478
  }
8479
+ const adminUserId = requesterUserId ?? void 0;
8396
8480
  if (deliverySessionId !== void 0) {
8397
- await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId });
8481
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId, adminUserId });
8398
8482
  } else {
8399
- await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text });
8483
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, adminUserId });
8400
8484
  }
8401
8485
  const sendId = ++sendSeq;
8402
8486
  let turnSessionId = deliverySessionId;
@@ -8407,7 +8491,7 @@ ${note}` : note;
8407
8491
  } catch {
8408
8492
  canonAccount = null;
8409
8493
  }
8410
- turnSessionId = resolveCanonical(accountId, canonAccount?.accountDir ?? null).sessionId;
8494
+ turnSessionId = resolveCanonical(accountId, canonAccount?.accountDir ?? null, requesterUserId, primaryUserId).sessionId;
8411
8495
  }
8412
8496
  const keyDisplay2 = deliveryKey.startsWith("session:") ? deliveryKey.slice(0, "session:".length + 8) : WEBCHAT_ADMIN_KEY;
8413
8497
  const baseline = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
@@ -8432,7 +8516,7 @@ ${note}` : note;
8432
8516
  console.error(`[webchat:settings] op=${String(op)} outcome=refused reason=unknown-op`);
8433
8517
  return c.json({ error: "op must be model, effort, or mode" }, 400);
8434
8518
  }
8435
- if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !EFFORT_LEVELS.has(value) || op === "mode" && !PERMISSION_MODE_VALUES.has(value)) {
8519
+ if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !isEffortLevel(value) || op === "mode" && !isPermissionMode(value)) {
8436
8520
  console.error(`[webchat:settings] op=${op} outcome=refused value=${JSON.stringify(value)} reason=invalid-value`);
8437
8521
  return c.json({ error: `invalid ${op} value` }, 400);
8438
8522
  }
@@ -8473,11 +8557,19 @@ ${note}` : note;
8473
8557
  console.error(`[webchat:inbound] op=session-refused reason=account-unresolved detail=${detail}`);
8474
8558
  return c.json({ error: "account unresolved" }, 503);
8475
8559
  }
8560
+ const cacheKey = c.get("cacheKey");
8561
+ const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
8562
+ const primaryUserId = resolvePrimaryAdminUserId();
8476
8563
  const target = c.req.query("session");
8477
8564
  if (target !== void 0) {
8478
8565
  if (!UUID_PATTERN.test(target)) {
8479
8566
  return c.json({ error: "invalid session id" }, 400);
8480
8567
  }
8568
+ const owned = readTargetOwner(target);
8569
+ if (owned.found && !ownedByRequester(owned.owner, requesterUserId, primaryUserId)) {
8570
+ console.error(`[webchat:inbound] op=session-target-foreign key=session:${target.slice(0, 8)} requester=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8571
+ return c.json({ error: "session not found" }, 404);
8572
+ }
8481
8573
  const { projectDir: projectDir2, channel } = locateSession(target);
8482
8574
  let resolvedProjectDir = projectDir2;
8483
8575
  let transcriptSessionId = target;
@@ -8498,7 +8590,7 @@ ${note}` : note;
8498
8590
  }
8499
8591
  const known = resolvedProjectDir !== null || sessionSidecarExists(target);
8500
8592
  const indicators2 = await fetchComposerIndicators(target);
8501
- return c.json({ sessionId: target, projectDir: resolvedProjectDir, transcriptSessionId, channelBinding: conflictingBinding(channel), known, sizeBytes: jsonlSizeBytes(projectDir2, target), ...indicators2, ...readLevers() });
8593
+ return c.json({ sessionId: target, projectDir: resolvedProjectDir, transcriptSessionId, channelBinding: conflictingBinding(channel), known, sizeBytes: jsonlSizeBytes(projectDir2, target), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${target}`) ?? null, ...indicators2, ...readLevers() });
8502
8594
  }
8503
8595
  let account;
8504
8596
  try {
@@ -8506,11 +8598,14 @@ ${note}` : note;
8506
8598
  } catch {
8507
8599
  account = null;
8508
8600
  }
8509
- const { sessionId, source } = resolveCanonical(accountId, account?.accountDir ?? null);
8510
- if (source === "latest" && account?.accountDir) {
8511
- writeCanonicalOverrideId(account.accountDir, sessionId);
8601
+ const { sessionId, source } = resolveCanonical(accountId, account?.accountDir ?? null, requesterUserId, primaryUserId);
8602
+ if (requesterUserId === null) {
8603
+ console.error(`[webchat:inbound] op=session-resolve-no-identity key=${sessionId.slice(0, 8)}`);
8604
+ }
8605
+ if (source === "latest" && account?.accountDir && requesterUserId !== null) {
8606
+ writeCanonicalOverrideId(account.accountDir, requesterUserId, sessionId);
8512
8607
  }
8513
- console.log(`[webchat:inbound] op=session-resolve key=${sessionId.slice(0, 8)} source=${source}`);
8608
+ console.log(`[webchat:inbound] op=session-resolve key=${sessionId.slice(0, 8)} source=${source} admin=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8514
8609
  const cfg = claudeConfigDir();
8515
8610
  let projectDir = null;
8516
8611
  if (cfg) {
@@ -8521,8 +8616,31 @@ ${note}` : note;
8521
8616
  }
8522
8617
  }
8523
8618
  }
8619
+ if (source === "latest" && requesterUserId !== null) {
8620
+ const owner = readSidecarMeta(join15(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
8621
+ if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
8622
+ console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
8623
+ }
8624
+ }
8524
8625
  const indicators = await fetchComposerIndicators(sessionId);
8525
- return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), ...indicators, ...readLevers(account) });
8626
+ return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
8627
+ });
8628
+ app53.post("/permission-verdict", requireAdminSession, async (c) => {
8629
+ const body = await c.req.json().catch(() => null);
8630
+ const sessionId = body?.sessionId;
8631
+ const requestId = body?.request_id;
8632
+ const behavior = body?.behavior;
8633
+ if (typeof sessionId !== "string" || !UUID_PATTERN.test(sessionId)) {
8634
+ return c.json({ error: "invalid session id" }, 400);
8635
+ }
8636
+ if (typeof requestId !== "string" || requestId.length === 0) {
8637
+ return c.json({ error: "request_id required" }, 400);
8638
+ }
8639
+ if (behavior !== "allow" && behavior !== "deny") {
8640
+ return c.json({ error: "behavior must be allow or deny" }, 400);
8641
+ }
8642
+ const ok = deps.resolvePermissionVerdict?.(`session:${sessionId}`, requestId, behavior) ?? false;
8643
+ return c.json({ ok });
8526
8644
  });
8527
8645
  return app53;
8528
8646
  }
@@ -8705,7 +8823,8 @@ async function managerSpawn(opts) {
8705
8823
  personId: opts.personId,
8706
8824
  visitorId: opts.visitorId,
8707
8825
  name: opts.name,
8708
- webchatChannel: opts.webchatChannel
8826
+ webchatChannel: opts.webchatChannel,
8827
+ previousContext: opts.previousContext
8709
8828
  })
8710
8829
  }).catch((err) => ({ __throw: err instanceof Error ? err.message : String(err) }));
8711
8830
  if ("__throw" in res) {
@@ -8732,6 +8851,7 @@ async function managerRcSpawn(opts) {
8732
8851
  sliceToken: opts.sliceToken,
8733
8852
  personId: opts.personId,
8734
8853
  userId: opts.userId,
8854
+ adminUserId: opts.adminUserId,
8735
8855
  waChannel: opts.waChannel,
8736
8856
  webchatChannel: opts.webchatChannel,
8737
8857
  role: opts.role,
@@ -16086,29 +16206,6 @@ var session_rc_spawn_default = app32;
16086
16206
 
16087
16207
  // server/routes/admin/session-reseat.ts
16088
16208
  import { randomUUID as randomUUID12 } from "crypto";
16089
-
16090
- // ../lib/models/src/index.ts
16091
- var OPUS_MODEL = "claude-opus-4-8[1m]";
16092
- var SONNET_MODEL = "claude-sonnet-4-6";
16093
- var HAIKU_MODEL = "claude-haiku-4-5";
16094
- var MODEL_CONTEXT_WINDOW = {
16095
- [OPUS_MODEL]: 1e6,
16096
- [SONNET_MODEL]: 2e5,
16097
- [HAIKU_MODEL]: 2e5
16098
- };
16099
- var MODEL_DISPLAY_NAMES = {
16100
- [OPUS_MODEL]: "Opus 4.8 (1M context)",
16101
- [SONNET_MODEL]: "Sonnet 4.6",
16102
- [HAIKU_MODEL]: "Haiku 4.5"
16103
- };
16104
- var SELECTABLE_MODELS = [OPUS_MODEL, SONNET_MODEL, HAIKU_MODEL];
16105
- function isSelectableModel(id) {
16106
- return SELECTABLE_MODELS.includes(id);
16107
- }
16108
-
16109
- // server/routes/admin/session-reseat.ts
16110
- var RESEAT_PERMISSION_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits", "plan", "auto", "bypassPermissions"]);
16111
- var RESEAT_EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
16112
16209
  function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticatedName) {
16113
16210
  const sessionId = mintId();
16114
16211
  const key = `session:${sessionId}`;
@@ -16141,8 +16238,8 @@ app33.post("/", requireAdminSession, async (c) => {
16141
16238
  const model = typeof body.model === "string" && isSelectableModel(body.model) ? body.model : null;
16142
16239
  if (fromSessionId === null) return c.json({ error: "fromSessionId must be a valid session id" }, 400);
16143
16240
  if (model === null) return c.json({ error: "model must be a selectable model" }, 400);
16144
- const permissionMode = typeof body.permissionMode === "string" ? RESEAT_PERMISSION_MODES.has(body.permissionMode) ? body.permissionMode : null : void 0;
16145
- const effort = typeof body.effort === "string" ? RESEAT_EFFORT_LEVELS.has(body.effort) ? body.effort : null : void 0;
16241
+ const permissionMode = typeof body.permissionMode === "string" ? isPermissionMode(body.permissionMode) ? body.permissionMode : null : void 0;
16242
+ const effort = typeof body.effort === "string" ? isEffortLevel(body.effort) ? body.effort : null : void 0;
16146
16243
  if (permissionMode === null) return c.json({ error: "permissionMode must be a composer-writable mode" }, 400);
16147
16244
  if (effort === null) return c.json({ error: "effort must be an accepted level" }, 400);
16148
16245
  if (reseatsInFlight.has(fromSessionId)) {
@@ -16152,6 +16249,13 @@ app33.post("/", requireAdminSession, async (c) => {
16152
16249
  try {
16153
16250
  const cacheKey = c.get("cacheKey");
16154
16251
  const adminUserId = cacheKey ? getUserIdForSession(cacheKey) : void 0;
16252
+ {
16253
+ const ownerInfo = readTargetOwner(fromSessionId);
16254
+ if (!(ownerInfo.found && ownedByRequester(ownerInfo.owner, adminUserId ?? null, resolvePrimaryAdminUserId()))) {
16255
+ console.error(`[chat-reseat] op=reseat-refused from=${fromSessionId.slice(0, 8)} reason=foreign-source requester=${adminUserId ? adminUserId.slice(0, 8) : "none"}`);
16256
+ return c.json({ error: "session not found" }, 404);
16257
+ }
16258
+ }
16155
16259
  const accountId = cacheKey ? getAccountIdForSession(cacheKey) : void 0;
16156
16260
  const authenticatedName = accountId ? await resolveAuthenticatedName(accountId, adminUserId) : void 0;
16157
16261
  const plan = resolveReseatPlan(
@@ -16188,12 +16292,13 @@ app33.post("/", requireAdminSession, async (c) => {
16188
16292
  }
16189
16293
  try {
16190
16294
  const account = resolveAccount();
16191
- if (account) {
16295
+ if (account && adminUserId) {
16192
16296
  const accountId2 = resolvePlatformAccountId();
16193
- const canonicalId = adminSessionIdFor(accountId2, WEBCHAT_ADMIN_KEY);
16194
- const currentOverride = readCanonicalOverrideId(account.accountDir);
16297
+ const primaryUserId = resolvePrimaryAdminUserId();
16298
+ const canonicalId = adminSessionIdFor(accountId2, WEBCHAT_ADMIN_KEY, adminUserId);
16299
+ const currentOverride = readCanonicalOverrideId(account.accountDir, adminUserId, primaryUserId);
16195
16300
  if (fromSessionId === canonicalId || fromSessionId === currentOverride) {
16196
- writeCanonicalOverrideId(account.accountDir, plan.sessionId);
16301
+ writeCanonicalOverrideId(account.accountDir, adminUserId, plan.sessionId);
16197
16302
  console.log(`[chat-reseat] op=canonical-forward reseatReqId=${reseatReqId} from=${fromSessionId} to=${plan.sessionId}`);
16198
16303
  }
16199
16304
  }
@@ -16652,9 +16757,8 @@ app37.get("/", async (c) => {
16652
16757
  });
16653
16758
  var post_turn_context_default = app37;
16654
16759
 
16655
- // server/routes/admin/public-session-context.ts
16760
+ // app/lib/slice-writes.ts
16656
16761
  import neo4j4 from "neo4j-driver";
16657
- var TAG32 = "[public-session-context]";
16658
16762
  var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
16659
16763
  "embedding",
16660
16764
  "passwordHash",
@@ -16662,9 +16766,6 @@ var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
16662
16766
  "otpCode",
16663
16767
  "cacheKey"
16664
16768
  ]);
16665
- function isLoopbackAddr3(addr) {
16666
- return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
16667
- }
16668
16769
  function convertValue2(value) {
16669
16770
  if (neo4j4.isDateTime(value) || neo4j4.isDate(value) || neo4j4.isLocalDateTime(value) || neo4j4.isLocalTime(value) || neo4j4.isTime(value) || neo4j4.isDuration(value)) {
16670
16771
  return value.toString();
@@ -16692,6 +16793,78 @@ function pruneProperties2(raw) {
16692
16793
  }
16693
16794
  return out;
16694
16795
  }
16796
+ async function fetchSliceWrites(session, sliceToken, accountId) {
16797
+ const cypher = `
16798
+ MATCH (n)
16799
+ WHERE n.sliceToken = $sliceToken AND n.accountId = $accountId
16800
+ RETURN elementId(n) AS elementId,
16801
+ labels(n) AS labels,
16802
+ properties(n) AS properties,
16803
+ coalesce(n.createdAt, n.observedAt, '') AS sortKey
16804
+ `;
16805
+ const res = await session.executeRead((tx) => tx.run(cypher, { sliceToken, accountId }));
16806
+ const writes = res.records.map((r) => ({
16807
+ elementId: r.get("elementId"),
16808
+ labels: r.get("labels"),
16809
+ properties: pruneProperties2(r.get("properties")),
16810
+ sortKey: String(r.get("sortKey") ?? "")
16811
+ }));
16812
+ writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
16813
+ return writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }));
16814
+ }
16815
+ var STRUCTURAL_KEYS = /* @__PURE__ */ new Set([
16816
+ "accountId",
16817
+ "scope",
16818
+ "sliceToken",
16819
+ "preferenceId",
16820
+ "ideaId",
16821
+ "createdAt",
16822
+ "updatedAt",
16823
+ "observedAt",
16824
+ "sessionId",
16825
+ "createdByAgent",
16826
+ "createdBySession",
16827
+ "confidence",
16828
+ "notApplicable"
16829
+ ]);
16830
+ function primaryLabel(labels) {
16831
+ return labels.find((l) => l.length > 0) ?? "Node";
16832
+ }
16833
+ function renderWrite(write) {
16834
+ const label = primaryLabel(write.labels);
16835
+ const props = write.properties;
16836
+ const parts = [];
16837
+ if (label === "Person") {
16838
+ const name = [props.givenName, props.familyName].filter((v) => typeof v === "string" && v.length > 0).join(" ");
16839
+ if (name) parts.push(name);
16840
+ }
16841
+ const kv = [];
16842
+ for (const [k, v] of Object.entries(props)) {
16843
+ if (STRUCTURAL_KEYS.has(k)) continue;
16844
+ if (label === "Person" && (k === "givenName" || k === "familyName")) continue;
16845
+ if (v === null || v === void 0 || v === "") continue;
16846
+ const val = String(v).slice(0, 200);
16847
+ kv.push(`${k}=${val}`);
16848
+ }
16849
+ const tail = [parts.join(" "), kv.join("; ")].filter((s) => s.length > 0).join(" \u2014 ");
16850
+ if (tail.length === 0) return null;
16851
+ return `- ${label}: ${tail}`;
16852
+ }
16853
+ function formatPreviousContext(writes) {
16854
+ if (writes.length === 0) return null;
16855
+ const lines = writes.filter((w) => w.properties.scope === "user").map(renderWrite).filter((l) => l !== null);
16856
+ if (lines.length === 0) return null;
16857
+ return [
16858
+ "What you already know about this visitor from earlier conversations:",
16859
+ ...lines
16860
+ ].join("\n");
16861
+ }
16862
+
16863
+ // server/routes/admin/public-session-context.ts
16864
+ var TAG32 = "[public-session-context]";
16865
+ function isLoopbackAddr3(addr) {
16866
+ return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
16867
+ }
16695
16868
  var app38 = new Hono();
16696
16869
  app38.get("/", async (c) => {
16697
16870
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
@@ -16716,31 +16889,12 @@ app38.get("/", async (c) => {
16716
16889
  const session = getSession();
16717
16890
  const started = Date.now();
16718
16891
  try {
16719
- const cypher = `
16720
- MATCH (n)
16721
- WHERE n.sliceToken = $sliceToken AND n.accountId = $accountId
16722
- RETURN elementId(n) AS elementId,
16723
- labels(n) AS labels,
16724
- properties(n) AS properties,
16725
- coalesce(n.createdAt, n.observedAt, '') AS sortKey
16726
- `;
16727
- const res = await session.executeRead(
16728
- (tx) => tx.run(cypher, { sliceToken, accountId })
16729
- );
16730
- const writes = res.records.map((r) => ({
16731
- elementId: r.get("elementId"),
16732
- labels: r.get("labels"),
16733
- properties: pruneProperties2(r.get("properties")),
16734
- sortKey: String(r.get("sortKey") ?? "")
16735
- }));
16736
- writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
16892
+ const writes = await fetchSliceWrites(session, sliceToken, accountId);
16737
16893
  const total = Date.now() - started;
16738
16894
  console.log(
16739
16895
  `${TAG32} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
16740
16896
  );
16741
- return c.json({
16742
- writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
16743
- });
16897
+ return c.json({ writes });
16744
16898
  } catch (err) {
16745
16899
  const elapsed = Date.now() - started;
16746
16900
  const message = err instanceof Error ? err.message : String(err);
@@ -17979,19 +18133,8 @@ app51.post("/", async (c) => {
17979
18133
  const account = resolveAccount();
17980
18134
  const cookieHeader = c.req.header("cookie");
17981
18135
  const visitorId = parseVisitorCookie2(cookieHeader);
17982
- const groupSlug = body.group_slug && typeof body.group_slug === "string" ? body.group_slug : null;
17983
- let groupInfo = null;
17984
- if (groupSlug) {
17985
- groupInfo = await findGroupBySlug(groupSlug, accountId).catch(() => null);
17986
- if (!groupInfo) {
17987
- console.error(`[session] group not found: slug=${groupSlug} account=${accountId.slice(0, 8)}\u2026`);
17988
- return c.json({ error: "Group not found" }, 404);
17989
- }
17990
- }
17991
18136
  let agentSlug = null;
17992
- if (groupInfo) {
17993
- agentSlug = groupInfo.agentSlug;
17994
- } else if (body.agent) {
18137
+ if (body.agent) {
17995
18138
  if (!validateAgentSlug(body.agent)) {
17996
18139
  return c.json({ error: "Invalid agent name" }, 400);
17997
18140
  }
@@ -18024,11 +18167,6 @@ app51.post("/", async (c) => {
18024
18167
  ...agentConfig.imageShape ? { agentImageShape: agentConfig.imageShape } : {},
18025
18168
  ...agentConfig.showAgentName ? { showAgentName: agentConfig.showAgentName } : {}
18026
18169
  } : {};
18027
- const groupFields = groupInfo ? {
18028
- group: true,
18029
- groupName: groupInfo.groupName,
18030
- groupSlug
18031
- } : {};
18032
18170
  const branding = await fetchBranding(accountId).catch(() => null);
18033
18171
  if (branding) writeBrandingCache(accountId, agentSlug, branding);
18034
18172
  let accessSession = null;
@@ -18041,7 +18179,6 @@ app51.post("/", async (c) => {
18041
18179
  Response.json({
18042
18180
  auth_required: true,
18043
18181
  agent_id: agentSlug,
18044
- ...groupFields,
18045
18182
  ...branding ? { branding } : {},
18046
18183
  ...agentIdentity
18047
18184
  }),
@@ -18066,7 +18203,6 @@ app51.post("/", async (c) => {
18066
18203
  agent_id: agentSlug,
18067
18204
  resumed,
18068
18205
  ...resumed ? { messages: uiMessages } : {},
18069
- ...groupFields,
18070
18206
  ...branding ? { branding } : {},
18071
18207
  ...agentIdentity
18072
18208
  });
@@ -18077,56 +18213,10 @@ app51.post("/", async (c) => {
18077
18213
  session_key: body.session_key,
18078
18214
  agent_id: agentSlug,
18079
18215
  resumed: false,
18080
- ...groupFields,
18081
18216
  ...branding ? { branding } : {},
18082
18217
  ...agentIdentity
18083
18218
  });
18084
18219
  }
18085
- if (groupInfo && visitorId) {
18086
- let memberName = await checkGroupMembership(groupInfo.sessionId, visitorId).catch(() => null);
18087
- if (!memberName && accessSession) {
18088
- const contactValue = accessSession.contactValue;
18089
- const isEmail = contactValue?.includes("@");
18090
- const bindResult = await bindVisitorToGroup(
18091
- groupInfo.sessionId,
18092
- visitorId,
18093
- isEmail ? contactValue : void 0,
18094
- !isEmail ? contactValue : void 0
18095
- ).catch(() => null);
18096
- memberName = bindResult?.displayName ?? null;
18097
- }
18098
- if (memberName) {
18099
- const neo4jMessages = await getRecentMessages(groupInfo.sessionId).catch(() => []);
18100
- const uiMessages = neo4jMessages.filter((m) => m.content !== GREETING_DIRECTIVE).map((m) => ({
18101
- role: m.role === "user" ? "visitor" : "maxy",
18102
- content: m.content,
18103
- timestamp: new Date(m.createdAt).getTime() || Date.now()
18104
- }));
18105
- const participants = await getGroupParticipants(groupInfo.sessionId).catch(() => []);
18106
- const cacheKey2 = crypto.randomUUID();
18107
- const resumed = uiMessages.length > 0;
18108
- console.log(`[session] cold-resume group=${groupSlug} visitor=${visitorId.slice(0, 8)}\u2026 messages=${uiMessages.length}`);
18109
- return withVisitorCookie(
18110
- Response.json({
18111
- session_key: cacheKey2,
18112
- agent_id: agentSlug,
18113
- resumed,
18114
- ...resumed ? { messages: uiMessages } : {},
18115
- ...groupFields,
18116
- participants: participants.map((p) => ({ displayName: p.displayName, joinedAt: p.joinedAt })),
18117
- ...branding ? { branding } : {},
18118
- ...agentIdentity
18119
- }),
18120
- visitorId
18121
- );
18122
- }
18123
- console.log(`[session] group cold-resume denied: visitor=${visitorId.slice(0, 8)}\u2026 not a member of group=${groupSlug}`);
18124
- return c.json({ error: "Not a member of this group" }, 403);
18125
- }
18126
- if (groupInfo) {
18127
- console.error(`[session] group=${groupSlug} requires visitor cookie`);
18128
- return c.json({ error: "Groups require member authentication" }, 400);
18129
- }
18130
18220
  if (visitorId) {
18131
18221
  const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
18132
18222
  if (recent) {
@@ -18528,7 +18618,7 @@ var defaultResolveName = async (accountId, userId) => {
18528
18618
  const res = await loadAdminUserName(accountId, userId);
18529
18619
  return res.source === "neo4j" && res.joined.length > 0 ? res.joined : null;
18530
18620
  };
18531
- async function readRaw(path2) {
18621
+ async function readRaw2(path2) {
18532
18622
  let raw;
18533
18623
  try {
18534
18624
  raw = await readFile7(path2, "utf8");
@@ -18636,7 +18726,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
18636
18726
  };
18637
18727
  const sidecars = await collectLiveSidecars(projectsRoot);
18638
18728
  for (const path2 of sidecars) {
18639
- const raw = await readRaw(path2);
18729
+ const raw = await readRaw2(path2);
18640
18730
  if (!raw) continue;
18641
18731
  if (raw.role !== ADMIN_ROLE2 || raw.channel !== WEBCHAT_CHANNEL2) continue;
18642
18732
  result.scanned++;
@@ -18654,7 +18744,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
18654
18744
  await writeRaw(path2, raw);
18655
18745
  result.backfilled++;
18656
18746
  await resolveAdminName();
18657
- const back = await readRaw(path2);
18747
+ const back = await readRaw2(path2);
18658
18748
  const wrote = back && back.adminUserId === soleAdminUserId;
18659
18749
  if (wrote && resolvedNameForAdmin) {
18660
18750
  result.resolvedName++;
@@ -19358,6 +19448,20 @@ function createWebchatChannelRoutes(deps) {
19358
19448
  deps.onReady?.(key);
19359
19449
  return c.json({ ok: true });
19360
19450
  });
19451
+ app53.post("/webchat-channel/permission-request", async (c) => {
19452
+ const body = await c.req.json().catch(() => null);
19453
+ const key = body?.key;
19454
+ const requestId = body?.request_id;
19455
+ const toolName = body?.tool_name;
19456
+ const description = body?.description;
19457
+ const inputPreview = body?.input_preview;
19458
+ if (typeof key !== "string" || typeof requestId !== "string" || typeof toolName !== "string" || typeof description !== "string" || typeof inputPreview !== "string") {
19459
+ return c.json({ error: "key, request_id, tool_name, description, input_preview required" }, 400);
19460
+ }
19461
+ if (!deps.awaitPermissionVerdict) return c.json({ timeout: true });
19462
+ const verdict = await deps.awaitPermissionVerdict({ key, requestId, toolName, description, inputPreview });
19463
+ return c.json(verdict);
19464
+ });
19361
19465
  app53.post("/webchat-channel/received", async (c) => {
19362
19466
  const body = await c.req.json().catch(() => null);
19363
19467
  const key = body?.key;
@@ -19378,10 +19482,13 @@ var SWEEP_INTERVAL_MS2 = 15e3;
19378
19482
  function channelIdleMs() {
19379
19483
  return Number(process.env.CHANNEL_PTY_IDLE_MS ?? String(5 * 6e4));
19380
19484
  }
19485
+ function permissionVerdictTtlMs() {
19486
+ return Number(process.env.WEBCHAT_PERMISSION_TTL_MS ?? String(5 * 6e4));
19487
+ }
19381
19488
  function keyDisplay(key) {
19382
19489
  return key.startsWith("session:") ? key.slice(0, "session:".length + 8) : key.slice(0, 8);
19383
19490
  }
19384
- var WebchatGateway = class {
19491
+ var WebchatGateway = class _WebchatGateway {
19385
19492
  constructor(deps) {
19386
19493
  this.deps = deps;
19387
19494
  }
@@ -19394,6 +19501,12 @@ var WebchatGateway = class {
19394
19501
  * /webchat-channel/reply resolves it. Admin webchat registers none (its
19395
19502
  * browser reader tails the JSONL), so handleReply is a no-op there. */
19396
19503
  replyAwaiters = /* @__PURE__ */ new Map();
19504
+ /** Task 940 — open permission prompts awaiting an operator verdict, keyed
19505
+ * `${key}::${requestId}`. The channel server registers one via a held-open
19506
+ * POST (awaitPermissionVerdict); the /chat Allow/Deny button resolves it
19507
+ * (resolvePermissionVerdict); the session pointer surfaces the oldest open
19508
+ * one for that key (pendingPromptFor). */
19509
+ pendingPrompts = /* @__PURE__ */ new Map();
19397
19510
  /** Task 756 — live public sessions, for the idle reaper + session-end review.
19398
19511
  * Admin sessions are never recorded here (they never reap). */
19399
19512
  publicSessions = /* @__PURE__ */ new Map();
@@ -19416,6 +19529,54 @@ var WebchatGateway = class {
19416
19529
  });
19417
19530
  });
19418
19531
  }
19532
+ /** Task 940 — register an open permission prompt and hold for the operator's
19533
+ * verdict. Resolves with `{behavior}` when resolvePermissionVerdict fires for
19534
+ * this key+id, or `{timeout:true}` after `timeoutMs` (the channel server's
19535
+ * held-open POST returns either; on timeout it emits no verdict and the local
19536
+ * terminal dialog stays answerable). */
19537
+ awaitPermissionVerdict(p, timeoutMs) {
19538
+ const k = _WebchatGateway.promptKey(p.key, p.requestId);
19539
+ return new Promise((resolve34) => {
19540
+ this.pendingPrompts.get(k)?.resolve({ timeout: true });
19541
+ const timer2 = setTimeout(() => {
19542
+ this.pendingPrompts.delete(k);
19543
+ resolve34({ timeout: true });
19544
+ }, timeoutMs);
19545
+ if (timer2.unref) timer2.unref();
19546
+ this.pendingPrompts.set(k, {
19547
+ ...p,
19548
+ at: Date.now(),
19549
+ resolve: (r) => {
19550
+ clearTimeout(timer2);
19551
+ this.pendingPrompts.delete(k);
19552
+ resolve34(r);
19553
+ }
19554
+ });
19555
+ console.error(`[webchat:perm] op=open key=${keyDisplay(p.key)} id=${p.requestId} tool=${p.toolName}`);
19556
+ });
19557
+ }
19558
+ /** Task 940 — the operator's Allow/Deny answer for an open prompt. Returns
19559
+ * false (and is a no-op) when no prompt with this key+id is open — a late or
19560
+ * duplicate click. */
19561
+ resolvePermissionVerdict(key, requestId, behavior) {
19562
+ const entry = this.pendingPrompts.get(_WebchatGateway.promptKey(key, requestId));
19563
+ if (!entry) return false;
19564
+ entry.resolve({ behavior });
19565
+ console.error(`[webchat:perm] op=verdict key=${keyDisplay(key)} id=${requestId} behavior=${behavior}`);
19566
+ return true;
19567
+ }
19568
+ /** Task 940 — the oldest open prompt for `key`, for the session pointer's
19569
+ * Allow/Deny card. null when none is open. */
19570
+ pendingPromptFor(key) {
19571
+ let oldest = null;
19572
+ for (const p of this.pendingPrompts.values()) {
19573
+ if (p.key === key && (!oldest || p.at < oldest.at)) oldest = p;
19574
+ }
19575
+ return oldest ? { requestId: oldest.requestId, toolName: oldest.toolName, description: oldest.description, inputPreview: oldest.inputPreview } : null;
19576
+ }
19577
+ static promptKey(key, requestId) {
19578
+ return `${key}::${requestId}`;
19579
+ }
19419
19580
  /** Stamp the op=reply lifeline and resolve any held-open awaiter for `key`.
19420
19581
  * Called by the /reply route's onReply. The first reply after registration
19421
19582
  * wins; a later reply for the same key finds no awaiter and only logs. */
@@ -19478,7 +19639,8 @@ var WebchatGateway = class {
19478
19639
  `[webchat:inbound] op=channel-received key=${key} messageId=${messageId}${found ? "" : " note=unknown"}`
19479
19640
  );
19480
19641
  },
19481
- onReply: (key, text) => this.handleReply(key, text)
19642
+ onReply: (key, text) => this.handleReply(key, text),
19643
+ awaitPermissionVerdict: (p) => this.awaitPermissionVerdict(p, permissionVerdictTtlMs())
19482
19644
  });
19483
19645
  }
19484
19646
  /** Run one reconciliation pass: log every terminal delivery event the sweep
@@ -19526,6 +19688,9 @@ var WebchatGateway = class {
19526
19688
  // Task 800 — only present on a session-targeted launch, so the
19527
19689
  // default-path call shape stays byte-identical.
19528
19690
  ...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
19691
+ // The authenticated admin's userId on an admin bootstrap inbound; the
19692
+ // default-path call shape stays byte-identical when absent.
19693
+ ...input.adminUserId !== void 0 ? { adminUserId: input.adminUserId } : {},
19529
19694
  // Task 756 — public spawn params on a role:'public' inbound.
19530
19695
  ...input.public !== void 0 ? { public: input.public } : {}
19531
19696
  });
@@ -19560,6 +19725,7 @@ function buildPublicWebchatSpawnRequest(input) {
19560
19725
  ...sliceToken ? { sliceToken } : {},
19561
19726
  ...personId ? { personId } : {},
19562
19727
  ...visitorId ? { visitorId } : {},
19728
+ ...input.previousContext ? { previousContext: input.previousContext } : {},
19563
19729
  name,
19564
19730
  webchatChannel: { key: input.key, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath }
19565
19731
  };
@@ -20032,14 +20198,27 @@ waGateway.startSweeper();
20032
20198
  var webchatGateway = new WebchatGateway({
20033
20199
  gatewayUrl: webchatGatewayUrl(),
20034
20200
  serverPath: webchatServerPath(),
20035
- ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId, public: pub }) => {
20201
+ ensureChannelSession: async ({ accountId, key, role, adminUserId, gatewayUrl, serverPath, sessionId, public: pub }) => {
20036
20202
  if (role === "public") {
20037
20203
  if (!pub) {
20038
20204
  console.error(`[webchat:inbound] op=spawn-refused key=${key} role=public reason=missing-public-params`);
20039
20205
  return;
20040
20206
  }
20207
+ let previousContext;
20208
+ if (pub.sliceToken) {
20209
+ const session = getSession();
20210
+ try {
20211
+ const writes = await fetchSliceWrites(session, pub.sliceToken, accountId);
20212
+ previousContext = formatPreviousContext(writes) ?? void 0;
20213
+ console.log(`[webchat:inbound] op=slice-readback key=${key} writes=${writes.length} injected=${previousContext ? "yes" : "no"}`);
20214
+ } catch (err) {
20215
+ console.error(`[webchat:inbound] op=slice-readback-failed key=${key} err=${err instanceof Error ? err.message : String(err)}`);
20216
+ } finally {
20217
+ await session.close();
20218
+ }
20219
+ }
20041
20220
  const result2 = await managerSpawn(
20042
- buildPublicWebchatSpawnRequest({ accountId, key, gatewayUrl, serverPath, public: pub })
20221
+ buildPublicWebchatSpawnRequest({ accountId, key, gatewayUrl, serverPath, previousContext, public: pub })
20043
20222
  );
20044
20223
  if ("error" in result2) {
20045
20224
  console.error(`[webchat:inbound] op=spawn-failed key=${key} role=public error=${result2.error} status=${result2.status}`);
@@ -20048,10 +20227,11 @@ var webchatGateway = new WebchatGateway({
20048
20227
  return { sessionId: result2.sessionId };
20049
20228
  }
20050
20229
  const result = await managerRcSpawn({
20051
- sessionId: sessionId ?? adminSessionIdFor(accountId, key),
20230
+ sessionId: sessionId ?? adminSessionIdFor(accountId, key, adminUserId),
20052
20231
  role: "admin",
20053
20232
  channel: "webchat",
20054
20233
  senderId: key,
20234
+ adminUserId,
20055
20235
  webchatChannel: { key, gatewayUrl, serverPath },
20056
20236
  logContext: `channel=webchat key=${key} role=${role}`
20057
20237
  });
@@ -20385,7 +20565,12 @@ app52.route("/api/chat", chatRoutes);
20385
20565
  app52.route("/api/whatsapp", whatsapp_default);
20386
20566
  app52.route("/api/whatsapp-reader", whatsapp_reader_default);
20387
20567
  app52.route("/api/public-reader", public_reader_default);
20388
- app52.route("/api/webchat", createWebchatRoutes({ handleInbound: (input) => webchatGateway.handleInbound(input) }));
20568
+ app52.route("/api/webchat", createWebchatRoutes({
20569
+ handleInbound: (input) => webchatGateway.handleInbound(input),
20570
+ // Task 940 — the permission relay's pointer read + verdict write.
20571
+ pendingPromptFor: (key) => webchatGateway.pendingPromptFor(key),
20572
+ resolvePermissionVerdict: (key, requestId, behavior) => webchatGateway.resolvePermissionVerdict(key, requestId, behavior)
20573
+ }));
20389
20574
  app52.route("/api/webchat/greeting", webchat_greeting_default);
20390
20575
  app52.route("/api/telegram", telegram_default);
20391
20576
  app52.route("/api/quickbooks", quickbooks_default);
@@ -20565,7 +20750,6 @@ ${clientErrorReporterScript}
20565
20750
  }
20566
20751
  return html;
20567
20752
  }
20568
- var brandedHtmlCache = /* @__PURE__ */ new Map();
20569
20753
  function loadBrandingCache(agentSlug) {
20570
20754
  const configDir2 = join28(homedir3(), BRAND.configDir);
20571
20755
  try {
@@ -20583,36 +20767,6 @@ function resolveDefaultSlug() {
20583
20767
  if (!account) return null;
20584
20768
  return resolveDefaultAgentSlug(account.accountDir);
20585
20769
  }
20586
- function wantsNextSurface(c) {
20587
- return c.req.query("surface") === "next";
20588
- }
20589
- function brandedPublicHtml(agentSlug) {
20590
- const baseHtml = cachedHtml("public.html");
20591
- if (!agentSlug) return baseHtml;
20592
- const cached3 = brandedHtmlCache.get(agentSlug);
20593
- const branding = loadBrandingCache(agentSlug);
20594
- if (!branding) return baseHtml;
20595
- const brandHash = JSON.stringify(branding).length;
20596
- if (cached3 && cached3.mtime === brandHash) return cached3.html;
20597
- const title = escapeHtml(branding.name);
20598
- const description = branding.tagline ? escapeHtml(branding.tagline) : "";
20599
- const themeColor = branding.primaryColor || "";
20600
- const ogImage = branding.logoUrl || "";
20601
- const favicon = branding.faviconUrl || "";
20602
- const metaTags = [
20603
- ` <title>${title}</title>`,
20604
- favicon ? ` <link rel="icon" href="${escapeHtml(favicon)}">` : ` <link rel="icon" href="${escapeHtml(brandFaviconPath)}">`,
20605
- themeColor ? ` <meta name="theme-color" content="${escapeHtml(themeColor)}">` : "",
20606
- ` <meta property="og:title" content="${title}">`,
20607
- description ? ` <meta property="og:description" content="${description}">` : "",
20608
- ogImage ? ` <meta property="og:image" content="${escapeHtml(ogImage)}">` : "",
20609
- ' <meta property="og:type" content="website">'
20610
- ].filter(Boolean).join("\n");
20611
- const html = baseHtml.replace(` <title>${escapeHtml(BRAND.productName)}</title>
20612
- <link rel="icon" href="${escapeHtml(brandFaviconPath)}">`, metaTags);
20613
- brandedHtmlCache.set(agentSlug, { html, mtime: brandHash });
20614
- return html;
20615
- }
20616
20770
  function escapeHtml(s) {
20617
20771
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
20618
20772
  }
@@ -20636,8 +20790,7 @@ app52.get("/", (c) => {
20636
20790
  );
20637
20791
  }
20638
20792
  console.error(`[public-root] op=serve-default slug=${defaultSlug}`);
20639
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20640
- return c.html(brandedPublicHtml(defaultSlug));
20793
+ return c.html(cachedHtml("public.html"));
20641
20794
  }
20642
20795
  console.log(`[host-class] host=${host} class=admin served=index.html`);
20643
20796
  return c.html(cachedHtml("index.html"));
@@ -20645,13 +20798,11 @@ app52.get("/", (c) => {
20645
20798
  app52.get("/public", (c) => {
20646
20799
  const host = (c.req.header("host") ?? "").split(":")[0];
20647
20800
  if (isPublicHost(host)) return c.text("Not found", 404);
20648
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20649
20801
  return c.html(cachedHtml("public.html"));
20650
20802
  });
20651
20803
  app52.get("/public-chat", (c) => {
20652
20804
  const host = (c.req.header("host") ?? "").split(":")[0];
20653
20805
  if (isPublicHost(host)) return c.text("Not found", 404);
20654
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20655
20806
  return c.html(cachedHtml("public.html"));
20656
20807
  });
20657
20808
  async function logViewerFetch(c, next) {
@@ -20705,7 +20856,7 @@ app52.post("/api/vnc/client-event", async (c) => {
20705
20856
  return c.json({ ok: true });
20706
20857
  });
20707
20858
  app52.get("/g/:slug", (c) => {
20708
- return c.html(brandedPublicHtml());
20859
+ return c.html(cachedHtml("public.html"));
20709
20860
  });
20710
20861
  for (const pwa of PWA_SURFACES) {
20711
20862
  app52.get(pwa.manifestPath, (c) => {
@@ -20761,8 +20912,7 @@ app52.get("/:slug", async (c, next) => {
20761
20912
  }
20762
20913
  const branding = loadBrandingCache(slug);
20763
20914
  console.error(`[public-catchall] served path=/${slug} slug=${slug} branding=${branding ? "hit" : "miss"}`);
20764
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20765
- return c.html(brandedPublicHtml(slug));
20915
+ return c.html(cachedHtml("public.html"));
20766
20916
  }
20767
20917
  await next();
20768
20918
  });