@rubytech/create-realagent-code 0.1.316 → 0.1.320

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 (304) hide show
  1. package/dist/__tests__/base-toolchain-deps.test.js +67 -0
  2. package/dist/index.js +7 -1
  3. package/package.json +2 -2
  4. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/graph-style/dist/index.js +15 -0
  6. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  7. package/payload/platform/lib/graph-style/src/index.ts +16 -0
  8. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  9. package/payload/platform/lib/graph-write/dist/index.js +3 -0
  10. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  11. package/payload/platform/lib/graph-write/src/index.ts +3 -0
  12. package/payload/platform/lib/mcp-eager/dist/index.d.ts +0 -20
  13. package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -1
  14. package/payload/platform/lib/mcp-eager/dist/index.js +2 -1
  15. package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -1
  16. package/payload/platform/lib/mcp-eager/src/index.ts +3 -1
  17. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts +8 -0
  18. package/payload/platform/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  19. package/payload/platform/lib/mcp-lifeline/dist/index.js +71 -0
  20. package/payload/platform/lib/mcp-lifeline/dist/index.js.map +1 -0
  21. package/payload/platform/lib/mcp-lifeline/package.json +7 -0
  22. package/payload/platform/lib/mcp-lifeline/src/__tests__/lifeline.test.ts +146 -0
  23. package/payload/platform/lib/mcp-lifeline/src/index.ts +78 -0
  24. package/payload/platform/lib/mcp-lifeline/tsconfig.json +9 -0
  25. package/payload/platform/lib/mcp-lifeline/vitest.config.ts +9 -0
  26. package/payload/platform/lib/models/dist/index.d.ts +16 -0
  27. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  28. package/payload/platform/lib/models/dist/index.js +32 -1
  29. package/payload/platform/lib/models/dist/index.js.map +1 -1
  30. package/payload/platform/lib/models/src/index.ts +39 -0
  31. package/payload/platform/neo4j/schema.cypher +103 -0
  32. package/payload/platform/package.json +5 -2
  33. package/payload/platform/plugins/admin/mcp/dist/index.js +11 -10
  34. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  35. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +50 -12
  36. package/payload/platform/plugins/docs/references/admin-ui.md +24 -2
  37. package/payload/platform/plugins/docs/references/internals.md +14 -7
  38. package/payload/platform/plugins/docs/references/neo4j.md +9 -0
  39. package/payload/platform/plugins/docs/references/plugins-guide.md +2 -2
  40. package/payload/platform/plugins/memory/mcp/dist/index.js +32 -31
  41. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +28 -0
  43. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
  44. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +7 -1
  45. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
  46. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
  47. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +19 -1
  48. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
  49. package/payload/platform/plugins/memory/references/schema-knowledge-work.md +80 -0
  50. package/payload/platform/plugins/outlook/mcp/dist/index.js +8 -7
  51. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  52. package/payload/platform/plugins/projects/PLUGIN.md +11 -0
  53. package/payload/platform/plugins/projects/references/meeting-to-tasks.md +34 -0
  54. package/payload/platform/plugins/projects/references/prioritization.md +43 -0
  55. package/payload/platform/plugins/projects/references/risk-premortem.md +34 -0
  56. package/payload/platform/plugins/projects/references/sprint.md +5 -1
  57. package/payload/platform/plugins/projects/references/stakeholder-map.md +43 -0
  58. package/payload/platform/plugins/quickbooks/mcp/dist/index.js +12 -11
  59. package/payload/platform/plugins/quickbooks/mcp/dist/index.js.map +1 -1
  60. package/payload/platform/plugins/replicate/mcp/dist/index.js +4 -3
  61. package/payload/platform/plugins/replicate/mcp/dist/index.js.map +1 -1
  62. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +11 -10
  63. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  64. package/payload/platform/scripts/__tests__/check-no-raw-mcp-registrations.test.sh +57 -0
  65. package/payload/platform/scripts/check-no-raw-mcp-registrations.mjs +70 -0
  66. package/payload/platform/scripts/installer-device-verify.sh +38 -0
  67. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  68. package/payload/platform/services/claude-session-manager/dist/http-server.js +57 -9
  69. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  70. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts +3 -1
  71. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts.map +1 -1
  72. package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.js.map +1 -1
  73. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +7 -1
  74. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +9 -1
  76. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  78. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +3 -12
  79. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  80. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +8 -0
  81. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  82. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +9 -0
  83. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  84. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +5 -0
  85. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  86. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +15 -0
  87. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  88. package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.d.ts +8 -0
  89. package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
  90. package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.js +71 -0
  91. package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.js.map +1 -0
  92. package/payload/premium-plugins/real-agent/lib/mcp-lifeline/package.json +7 -0
  93. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js +9 -8
  94. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js.map +1 -1
  95. package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/index.ts +9 -8
  96. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js +28 -27
  97. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js.map +1 -1
  98. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/index.ts +28 -27
  99. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js +23 -22
  100. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js.map +1 -1
  101. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/index.ts +23 -22
  102. package/payload/server/{chunk-Q7EWROVN.js → chunk-GRKG3KNN.js} +0 -101
  103. package/payload/server/maxy-edge.js +1 -1
  104. package/payload/server/public/assets/AdminLoginScreens-D_e5PYXv.js +1 -0
  105. package/payload/server/public/assets/AdminShell-Dc23yALw.js +1 -0
  106. package/payload/server/public/assets/Checkbox-BHxSr_cA.js +1 -0
  107. package/payload/server/public/assets/OperatorConversations-BqNOXEu8.js +9 -0
  108. package/payload/server/public/assets/OperatorConversations-pu50BU11.css +1 -0
  109. package/payload/server/public/assets/admin-DE55chV9.js +1 -0
  110. package/payload/server/public/assets/{arc-J2g2u5Xv.js → arc-CxLB9WCE.js} +1 -1
  111. package/payload/server/public/assets/architecture-YZFGNWBL-DN-MYxff.js +1 -0
  112. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CN0BXxpE.js → architectureDiagram-Q4EWVU46-D-EdJPSY.js} +1 -1
  113. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-HX-8wF2p.js → blockDiagram-DXYQGD6D-CXx9RgCm.js} +1 -1
  114. package/payload/server/public/assets/browser-C1Dp1UxB.js +1 -0
  115. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-wIuarKF5.js → c4Diagram-AHTNJAMY-RFBXEe0B.js} +1 -1
  116. package/payload/server/public/assets/channel-y27xl53N.js +1 -0
  117. package/payload/server/public/assets/chat-BLQDFyDL.js +1 -0
  118. package/payload/server/public/assets/{chunk-2KRD3SAO-Buz7egJZ.js → chunk-2KRD3SAO-DBqAFwK9.js} +1 -1
  119. package/payload/server/public/assets/{chunk-336JU56O-_JcFXJqc.js → chunk-336JU56O-DdnFEz6R.js} +2 -2
  120. package/payload/server/public/assets/chunk-426QAEUC-D8Iwaegm.js +1 -0
  121. package/payload/server/public/assets/{chunk-4BX2VUAB-DUR5Dg3M.js → chunk-4BX2VUAB-cnw-3Gbs.js} +1 -1
  122. package/payload/server/public/assets/{chunk-4TB4RGXK-BRIqQ9st.js → chunk-4TB4RGXK-BnqJ0bDc.js} +1 -1
  123. package/payload/server/public/assets/{chunk-55IACEB6-CezTHWXL.js → chunk-55IACEB6-BwyHvvzo.js} +1 -1
  124. package/payload/server/public/assets/{chunk-5FUZZQ4R-DHYUPzF1.js → chunk-5FUZZQ4R-DXA9U02I.js} +1 -1
  125. package/payload/server/public/assets/{chunk-5PVQY5BW-BVn4_fI5.js → chunk-5PVQY5BW-D78bZ_8D.js} +1 -1
  126. package/payload/server/public/assets/{chunk-67CJDMHE-BBLA8Mbi.js → chunk-67CJDMHE-CtE_Mgv7.js} +1 -1
  127. package/payload/server/public/assets/{chunk-7N4EOEYR-CdWfEI5c.js → chunk-7N4EOEYR-CUZDaySl.js} +1 -1
  128. package/payload/server/public/assets/{chunk-AA7GKIK3-tS11knCR.js → chunk-AA7GKIK3-CYQ3jO4X.js} +1 -1
  129. package/payload/server/public/assets/{chunk-BSJP7CBP-GEu1OOZ6.js → chunk-BSJP7CBP-BbA_HyTR.js} +1 -1
  130. package/payload/server/public/assets/{chunk-CIAEETIT-DKrNbbp_.js → chunk-CIAEETIT-D7_YqRhG.js} +1 -1
  131. package/payload/server/public/assets/{chunk-EDXVE4YY-B0InXNyr.js → chunk-EDXVE4YY-B23LrtSw.js} +1 -1
  132. package/payload/server/public/assets/{chunk-ENJZ2VHE-CO7lkHdm.js → chunk-ENJZ2VHE-D3fTHYKN.js} +1 -1
  133. package/payload/server/public/assets/{chunk-FMBD7UC4-CMj74lWo.js → chunk-FMBD7UC4-DFAA2tyh.js} +1 -1
  134. package/payload/server/public/assets/{chunk-FOC6F5B3-CLnKQoXw.js → chunk-FOC6F5B3-BF4IHvlI.js} +1 -1
  135. package/payload/server/public/assets/{chunk-ICPOFSXX-CdiEKIaz.js → chunk-ICPOFSXX-DBUGemHy.js} +2 -2
  136. package/payload/server/public/assets/{chunk-K5T4RW27-B6LA3fiv.js → chunk-K5T4RW27-rMMs08Eh.js} +1 -1
  137. package/payload/server/public/assets/{chunk-KGLVRYIC-DrhRrb8Q.js → chunk-KGLVRYIC-BD2r8R2G.js} +1 -1
  138. package/payload/server/public/assets/{chunk-LIHQZDEY-DVQukevB.js → chunk-LIHQZDEY-D4sYTTwM.js} +1 -1
  139. package/payload/server/public/assets/{chunk-ORNJ4GCN-ZMLkoDhP.js → chunk-ORNJ4GCN-CAs_uFzb.js} +1 -1
  140. package/payload/server/public/assets/{chunk-OYMX7WX6-C0dJkynG.js → chunk-OYMX7WX6-Fkp-2ORc.js} +1 -1
  141. package/payload/server/public/assets/chunk-QZHKN3VN-qHqDpwz3.js +1 -0
  142. package/payload/server/public/assets/{chunk-U2HBQHQK-BQ9BPIFZ.js → chunk-U2HBQHQK-D_pxZh25.js} +1 -1
  143. package/payload/server/public/assets/{chunk-X2U36JSP-CAonGMOd.js → chunk-X2U36JSP-CeVmvvRf.js} +1 -1
  144. package/payload/server/public/assets/{chunk-XPW4576I-D5C_WNlk.js → chunk-XPW4576I-iWP54fKp.js} +1 -1
  145. package/payload/server/public/assets/{chunk-YZCP3GAM-Ecdvzekb.js → chunk-YZCP3GAM-CNtbWJNN.js} +1 -1
  146. package/payload/server/public/assets/{chunk-ZZ45TVLE-BsFZd1cN.js → chunk-ZZ45TVLE-BmlFjU_9.js} +1 -1
  147. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DgVoYWhO.js +1 -0
  148. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C0WNP3uN.js +1 -0
  149. package/payload/server/public/assets/clone-D50F_pvg.js +1 -0
  150. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-DBWHaIwm.js → cose-bilkent-S5V4N54A-C7YmF1Pg.js} +1 -1
  151. package/payload/server/public/assets/{dagre-Dr7ZJYeS.js → dagre-BAmiDDtR.js} +1 -1
  152. package/payload/server/public/assets/{dagre-KV5264BT-oIJddk7m.js → dagre-KV5264BT-Ca3ESJhc.js} +1 -1
  153. package/payload/server/public/assets/data-D_L6g-L_.js +1 -0
  154. package/payload/server/public/assets/{diagram-5BDNPKRD-CEVxqOZ4.js → diagram-5BDNPKRD-BgT1ORf2.js} +1 -1
  155. package/payload/server/public/assets/{diagram-G4DWMVQ6-BovF7Rjx.js → diagram-G4DWMVQ6-BTaUIiem.js} +1 -1
  156. package/payload/server/public/assets/{diagram-MMDJMWI5-BhrF8zoF.js → diagram-MMDJMWI5-Bdb2g6Uo.js} +1 -1
  157. package/payload/server/public/assets/{diagram-TYMM5635-DCUYwxtR.js → diagram-TYMM5635-CkLGC0zZ.js} +1 -1
  158. package/payload/server/public/assets/{dist-DSsFp0Qd.js → dist-Bkbhs3jw.js} +1 -1
  159. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BS2-HdCg.js → erDiagram-SMLLAGMA-D_sj4DMg.js} +1 -1
  160. package/payload/server/public/assets/{flatten-BZMXCpLh.js → flatten-E2Sr0FeD.js} +1 -1
  161. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BzSFLoea.js → flowDiagram-DWJPFMVM-iLERoZTe.js} +1 -1
  162. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-1-3QU7mT.js → ganttDiagram-T4ZO3ILL-D60hjMBy.js} +1 -1
  163. package/payload/server/public/assets/gitGraph-7Q5UKJZL-D-L2yzYf.js +1 -0
  164. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-fTrJ35Wk.js → gitGraphDiagram-UUTBAWPF-Di0XM6fi.js} +1 -1
  165. package/payload/server/public/assets/graph-labels-C2r7zl8O.js +1 -0
  166. package/payload/server/public/assets/{graph-BZNc3EXa.js → graph-ticN9QbK.js} +3 -3
  167. package/payload/server/public/assets/{graphlib-rlEzI2qD.js → graphlib-C8fUP7uV.js} +1 -1
  168. package/payload/server/public/assets/info-OMHHGYJF-BQn6jndO.js +1 -0
  169. package/payload/server/public/assets/infoDiagram-42DDH7IO-BwMdbiXg.js +2 -0
  170. package/payload/server/public/assets/{isEmpty-DaYIrHay.js → isEmpty-CLz-UprQ.js} +1 -1
  171. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-0eU_UtlT.js → ishikawaDiagram-UXIWVN3A-CwgI4B5Z.js} +1 -1
  172. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-BKLeZohp.js → journeyDiagram-VCZTEJTY-CxBu-tze.js} +1 -1
  173. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-Dq72xyaN.js → kanban-definition-6JOO6SKY-D2qlheA5.js} +1 -1
  174. package/payload/server/public/assets/{line-LQhmDT8k.js → line-Bdod7uzQ.js} +1 -1
  175. package/payload/server/public/assets/{linear-BGotDbGs.js → linear-BiVe6QzC.js} +1 -1
  176. package/payload/server/public/assets/{mermaid-parser.core-DoLdho1V.js → mermaid-parser.core-xZN7hC6M.js} +2 -2
  177. package/payload/server/public/assets/{mermaid.core-C1RRyHGm.js → mermaid.core-D0IylAac.js} +3 -3
  178. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-vUVVVyV1.js → mindmap-definition-QFDTVHPH-J_Szhwf1.js} +1 -1
  179. package/payload/server/public/assets/operator-COIYJFG7.js +1 -0
  180. package/payload/server/public/assets/{ordinal-BqEhkPyh.js → ordinal-5RtyPJVt.js} +1 -1
  181. package/payload/server/public/assets/packet-4T2RLAQJ-DmkQBx4h.js +1 -0
  182. package/payload/server/public/assets/page-CsOGSSSb.js +30 -0
  183. package/payload/server/public/assets/pie-ZZUOXDRM-DDnxYUBm.js +1 -0
  184. package/payload/server/public/assets/{pieDiagram-DEJITSTG-B9Pl6Qhc.js → pieDiagram-DEJITSTG-CV5DxUVx.js} +1 -1
  185. package/payload/server/public/assets/public-CjT_WNkz.js +1 -0
  186. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Drn9T81A.js → quadrantDiagram-34T5L4WZ-BsFMVizF.js} +1 -1
  187. package/payload/server/public/assets/radar-PYXPWWZC-7H4k0ChM.js +1 -0
  188. package/payload/server/public/assets/{reduce-T2IuntYP.js → reduce-B3Mw_0s1.js} +1 -1
  189. package/payload/server/public/assets/{requirementDiagram-MS252O5E-C0PAItJm.js → requirementDiagram-MS252O5E-C5eRRvGc.js} +1 -1
  190. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BR42Mtwd.js → sankeyDiagram-XADWPNL6-CJYv5gpw.js} +1 -1
  191. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-c2lR9UOS.js → sequenceDiagram-FGHM5R23-B25563_2.js} +1 -1
  192. package/payload/server/public/assets/{src-DXUM2BJo.js → src-BKOAoFQc.js} +1 -1
  193. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BcHhtqsZ.js → stateDiagram-FHFEXIEX-BLyNJYOA.js} +1 -1
  194. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BSVuxZxz.js +1 -0
  195. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Ax32c10H.js → timeline-definition-GMOUNBTQ-D-HgOM6Q.js} +1 -1
  196. package/payload/server/public/assets/treeView-SZITEDCU-BLXWTQtW.js +1 -0
  197. package/payload/server/public/assets/treemap-W4RFUUIX-DiePDF5d.js +1 -0
  198. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BxePewPq.js → vennDiagram-DHZGUBPP-Cw1JElYp.js} +1 -1
  199. package/payload/server/public/assets/wardley-RL74JXVD-OSUWK5LN.js +1 -0
  200. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DmJwZ2f5.js → wardleyDiagram-NUSXRM2D-BqMWzEko.js} +1 -1
  201. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-YjHomudv.js → xychartDiagram-5P7HB3ND-DBp71TLT.js} +1 -1
  202. package/payload/server/public/browser.html +5 -8
  203. package/payload/server/public/chat.html +8 -12
  204. package/payload/server/public/data.html +5 -7
  205. package/payload/server/public/graph.html +7 -10
  206. package/payload/server/public/index.html +8 -11
  207. package/payload/server/public/operator.html +10 -14
  208. package/payload/server/public/public.html +8 -10
  209. package/payload/server/server.js +330 -195
  210. package/payload/server/public/assets/AccessGate-bu988Xo-.js +0 -1
  211. package/payload/server/public/assets/AdminLoginScreens-BCYaOOuk.js +0 -1
  212. package/payload/server/public/assets/AdminShell-DSjJ4Biu.js +0 -1
  213. package/payload/server/public/assets/Checkbox-B4Dbvjls.js +0 -1
  214. package/payload/server/public/assets/OperatorConversations-XsXP7-P-.js +0 -1
  215. package/payload/server/public/assets/OperatorConversations-qc_xy7Az.css +0 -1
  216. package/payload/server/public/assets/admin-m0797WGA.js +0 -1
  217. package/payload/server/public/assets/architecture-YZFGNWBL-C6nkAxzW.js +0 -1
  218. package/payload/server/public/assets/audio-attachment-mime-Jm4KJ4YC.js +0 -30
  219. package/payload/server/public/assets/brand-D8LClgr_.js +0 -9
  220. package/payload/server/public/assets/brand-DvttVeGB.css +0 -1
  221. package/payload/server/public/assets/browser-CBjNMPsz.js +0 -1
  222. package/payload/server/public/assets/channel-Q39xIXyT.js +0 -1
  223. package/payload/server/public/assets/chat-Sg-RGuV6.js +0 -1
  224. package/payload/server/public/assets/chunk-426QAEUC-CCYjp9C2.js +0 -1
  225. package/payload/server/public/assets/chunk-QZHKN3VN-BNBxnHZh.js +0 -1
  226. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BShusfby.js +0 -1
  227. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D4ivPLFF.js +0 -1
  228. package/payload/server/public/assets/clone-CjEM8LwB.js +0 -1
  229. package/payload/server/public/assets/data-CEqE4BDw.js +0 -1
  230. package/payload/server/public/assets/gitGraph-7Q5UKJZL-Btp3PwZh.js +0 -1
  231. package/payload/server/public/assets/graph-labels-Bj5yM9bI.js +0 -1
  232. package/payload/server/public/assets/info-OMHHGYJF-CPt2y6_L.js +0 -1
  233. package/payload/server/public/assets/infoDiagram-42DDH7IO-CpXNTMgd.js +0 -2
  234. package/payload/server/public/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
  235. package/payload/server/public/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  236. package/payload/server/public/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  237. package/payload/server/public/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
  238. package/payload/server/public/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  239. package/payload/server/public/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
  240. package/payload/server/public/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  241. package/payload/server/public/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
  242. package/payload/server/public/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  243. package/payload/server/public/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
  244. package/payload/server/public/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  245. package/payload/server/public/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
  246. package/payload/server/public/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  247. package/payload/server/public/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
  248. package/payload/server/public/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
  249. package/payload/server/public/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  250. package/payload/server/public/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  251. package/payload/server/public/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  252. package/payload/server/public/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  253. package/payload/server/public/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  254. package/payload/server/public/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
  255. package/payload/server/public/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  256. package/payload/server/public/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
  257. package/payload/server/public/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  258. package/payload/server/public/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
  259. package/payload/server/public/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  260. package/payload/server/public/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  261. package/payload/server/public/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
  262. package/payload/server/public/assets/newsreader-latin-300-normal-AOSWdb_s.woff +0 -0
  263. package/payload/server/public/assets/newsreader-latin-300-normal-FGBQ0wlI.woff2 +0 -0
  264. package/payload/server/public/assets/newsreader-latin-400-normal-BFBkh4jY.woff2 +0 -0
  265. package/payload/server/public/assets/newsreader-latin-400-normal-gRTjlS2D.woff +0 -0
  266. package/payload/server/public/assets/newsreader-latin-500-normal-B66TYsaK.woff2 +0 -0
  267. package/payload/server/public/assets/newsreader-latin-500-normal-DFwuUcdu.woff +0 -0
  268. package/payload/server/public/assets/newsreader-latin-ext-300-normal-CFtw49Zd.woff +0 -0
  269. package/payload/server/public/assets/newsreader-latin-ext-300-normal-DRMzurxT.woff2 +0 -0
  270. package/payload/server/public/assets/newsreader-latin-ext-400-normal-DYA1XoQK.woff +0 -0
  271. package/payload/server/public/assets/newsreader-latin-ext-400-normal-svq1FPys.woff2 +0 -0
  272. package/payload/server/public/assets/newsreader-latin-ext-500-normal-BNHmvKvI.woff2 +0 -0
  273. package/payload/server/public/assets/newsreader-latin-ext-500-normal-CZruMFou.woff +0 -0
  274. package/payload/server/public/assets/newsreader-vietnamese-300-normal-CsrIkm-V.woff +0 -0
  275. package/payload/server/public/assets/newsreader-vietnamese-300-normal-D3VHEe81.woff2 +0 -0
  276. package/payload/server/public/assets/newsreader-vietnamese-400-normal-BekUZro8.woff +0 -0
  277. package/payload/server/public/assets/newsreader-vietnamese-400-normal-DdKr49mV.woff2 +0 -0
  278. package/payload/server/public/assets/newsreader-vietnamese-500-normal-BEAbKU8A.woff +0 -0
  279. package/payload/server/public/assets/newsreader-vietnamese-500-normal-CL6a8tp2.woff2 +0 -0
  280. package/payload/server/public/assets/operator-Bph7mx87.js +0 -1
  281. package/payload/server/public/assets/packet-4T2RLAQJ-Cwc-j_AI.js +0 -1
  282. package/payload/server/public/assets/page-CtWCeXdg.js +0 -1
  283. package/payload/server/public/assets/pie-ZZUOXDRM-BZ9fjD1_.js +0 -1
  284. package/payload/server/public/assets/public-gxHCJCs3.js +0 -6
  285. package/payload/server/public/assets/public-next-C3clISGQ.js +0 -1
  286. package/payload/server/public/assets/public-vnj7OhQj.css +0 -1
  287. package/payload/server/public/assets/radar-PYXPWWZC-BNz5Rt9V.js +0 -1
  288. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BUQ_F4eP.js +0 -1
  289. package/payload/server/public/assets/treeView-SZITEDCU-DcVCQgp1.js +0 -1
  290. package/payload/server/public/assets/treemap-W4RFUUIX-Bm12mwGd.js +0 -1
  291. package/payload/server/public/assets/useSelectionMode-BMn70cch.js +0 -5
  292. package/payload/server/public/assets/wardley-RL74JXVD-47Z3ymtK.js +0 -1
  293. package/payload/server/public/public-next.html +0 -25
  294. /package/payload/server/public/assets/{_baseFor-Y5mTRiRv.js → _baseFor-DVaNaTfF.js} +0 -0
  295. /package/payload/server/public/assets/{admin-types-D2qTXuCg.js → admin-types-CJrGd46U.js} +0 -0
  296. /package/payload/server/public/assets/{array-BwJyW1Dp.js → array-8_H1156C.js} +0 -0
  297. /package/payload/server/public/assets/{chunk-CAM3fms7.js → chunk-Pqm5yXtL.js} +0 -0
  298. /package/payload/server/public/assets/{cytoscape.esm-D95TtHqz.js → cytoscape.esm-h10p_6j-.js} +0 -0
  299. /package/payload/server/public/assets/{defaultLocale-kiwRz9Au.js → defaultLocale-pD7tFa1r.js} +0 -0
  300. /package/payload/server/public/assets/{init-CKZirZ49.js → init-CwJ4b81e.js} +0 -0
  301. /package/payload/server/public/assets/{katex-8mXVa4k3.js → katex-DJPjIBAI.js} +0 -0
  302. /package/payload/server/public/assets/{path-B0d9ncVi.js → path-CK8wrAxY.js} +0 -0
  303. /package/payload/server/public/assets/{preload-helper-C5gCWwwF.js → preload-helper-Bf_JiD2A.js} +0 -0
  304. /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-GRKG3KNN.js";
114
110
  import {
115
111
  __commonJS,
116
112
  __toESM
@@ -490,7 +486,22 @@ var require_dist2 = __commonJS({
490
486
  EmailAccount: "#91A063",
491
487
  // Public-agent projection — burnished bronze sits between
492
488
  // people-terracotta and email-moss but shares neither hue.
493
- Agent: "#B8893D"
489
+ Agent: "#B8893D",
490
+ // Knowledge-work ontology (the Maxy brand; schema-knowledge-work.md).
491
+ // Two bands, kept apart from every other family so a knowledge-worker
492
+ // legend reads them as their own groups. Strategy/decision sits in an
493
+ // indigo→violet band (distinct from the business slates and the plum
494
+ // conversational family); Risk is a lone desaturated signal-red placed
495
+ // away from both bands so it reads as a warning; research/evidence sits
496
+ // in a teal→green→gold band (distinct from workflow teal and knowledge
497
+ // moss). All seven hexes are pairwise-unique across the registry.
498
+ Objective: "#3D5A98",
499
+ KeyResult: "#5E7BC4",
500
+ Decision: "#7E60B0",
501
+ Risk: "#C15B57",
502
+ Source: "#2F8FA6",
503
+ Finding: "#4FA389",
504
+ Hypothesis: "#9A8C3E"
494
505
  };
495
506
  exports.FALLBACK_LABEL_COLOUR = "#94A3B8";
496
507
  exports.ALL_GRAPH_LABELS = Object.freeze(Object.keys(exports.GRAPH_LABEL_COLOURS));
@@ -532,63 +543,63 @@ var require_dist2 = __commonJS({
532
543
  }
533
544
  function pickShortLabel(node) {
534
545
  const props = node.properties;
535
- const primaryLabel = node.labels[0];
536
- if (primaryLabel === "ToolCall") {
546
+ const primaryLabel2 = node.labels[0];
547
+ if (primaryLabel2 === "ToolCall") {
537
548
  const v = props.toolName;
538
549
  if (typeof v === "string" && v.length > 0) {
539
550
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
540
551
  }
541
- } else if (primaryLabel === "WorkflowRun") {
552
+ } else if (primaryLabel2 === "WorkflowRun") {
542
553
  const v = props.startedAt;
543
554
  if (typeof v === "string" && v.length > 0) {
544
555
  const ts = formatRunTimestamp(v);
545
556
  if (ts)
546
557
  return ts;
547
558
  }
548
- } else if (primaryLabel === "WorkflowStep") {
559
+ } else if (primaryLabel2 === "WorkflowStep") {
549
560
  const v = props.label;
550
561
  if (typeof v === "string" && v.length > 0) {
551
562
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
552
563
  }
553
- } else if (primaryLabel === "Person") {
564
+ } else if (primaryLabel2 === "Person") {
554
565
  const given = typeof props.givenName === "string" ? props.givenName : "";
555
566
  const family = typeof props.familyName === "string" ? props.familyName : "";
556
567
  const full = [given, family].filter((s) => s.length > 0).join(" ");
557
568
  if (full.length > 0) {
558
569
  return full.length > 24 ? full.slice(0, 24) + "\u2026" : full;
559
570
  }
560
- } else if (primaryLabel === "Agent") {
571
+ } else if (primaryLabel2 === "Agent") {
561
572
  const dn = typeof props.displayName === "string" ? props.displayName : "";
562
573
  const slug = typeof props.slug === "string" ? props.slug : "";
563
574
  const v = dn.length > 0 ? dn : slug;
564
575
  if (v.length > 0) {
565
576
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
566
577
  }
567
- } else if (primaryLabel === "Job") {
578
+ } else if (primaryLabel2 === "Job") {
568
579
  const client = typeof props.client === "string" ? props.client : "";
569
580
  const jobId = typeof props.jobId === "string" ? props.jobId : "";
570
581
  const composed = [client, jobId.length > 0 ? `#${jobId}` : ""].filter((s) => s.length > 0).join(" ");
571
582
  if (composed.length > 0) {
572
583
  return composed.length > 24 ? composed.slice(0, 24) + "\u2026" : composed;
573
584
  }
574
- } else if (primaryLabel === "QuoteDocument") {
585
+ } else if (primaryLabel2 === "QuoteDocument") {
575
586
  const ref = typeof props.ref === "string" ? props.ref : "";
576
587
  if (ref.length > 0) {
577
588
  return ref.length > 24 ? ref.slice(0, 24) + "\u2026" : ref;
578
589
  }
579
- } else if (primaryLabel === "InboundInvoice") {
590
+ } else if (primaryLabel2 === "InboundInvoice") {
580
591
  const supplier = typeof props.supplier === "string" ? props.supplier : "";
581
592
  const conf = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
582
593
  const composed = [supplier, conf.length > 0 ? `#${conf}` : ""].filter((s) => s.length > 0).join(" ");
583
594
  if (composed.length > 0) {
584
595
  return composed.length > 24 ? composed.slice(0, 24) + "\u2026" : composed;
585
596
  }
586
- } else if (primaryLabel === "WhatsAppGroup") {
597
+ } else if (primaryLabel2 === "WhatsAppGroup") {
587
598
  const clientName = typeof props.clientName === "string" ? props.clientName : "";
588
599
  if (clientName.length > 0) {
589
600
  return clientName.length > 24 ? clientName.slice(0, 24) + "\u2026" : clientName;
590
601
  }
591
- } else if (primaryLabel === "Message") {
602
+ } else if (primaryLabel2 === "Message") {
592
603
  const role = typeof props.role === "string" ? props.role : "";
593
604
  const roleShort = role === "user" ? "user" : role === "assistant" ? "asst" : role === "system" ? "sys" : role === "tool" ? "tool" : null;
594
605
  const createdAt = typeof props.createdAt === "string" ? props.createdAt : "";
@@ -604,60 +615,60 @@ var require_dist2 = __commonJS({
604
615
  return v.length > 24 ? v.slice(0, 24) + "\u2026" : v;
605
616
  }
606
617
  }
607
- if (primaryLabel === "Conversation") {
618
+ if (primaryLabel2 === "Conversation") {
608
619
  const id = typeof props.sessionId === "string" ? props.sessionId : null;
609
620
  if (id)
610
621
  return `Conv ${id.slice(0, 8)}`;
611
622
  }
612
- return primaryLabel ?? "\u2026";
623
+ return primaryLabel2 ?? "\u2026";
613
624
  }
614
625
  function pickDisplayName(node) {
615
626
  const props = node.properties;
616
- const primaryLabel = node.labels[0];
617
- if (primaryLabel === "ToolCall") {
627
+ const primaryLabel2 = node.labels[0];
628
+ if (primaryLabel2 === "ToolCall") {
618
629
  const v = props.toolName;
619
630
  if (typeof v === "string" && v.length > 0)
620
631
  return v;
621
- } else if (primaryLabel === "WorkflowRun") {
632
+ } else if (primaryLabel2 === "WorkflowRun") {
622
633
  const v = props.startedAt;
623
634
  if (typeof v === "string" && v.length > 0) {
624
635
  const ts = formatRunTimestamp(v);
625
636
  if (ts)
626
637
  return ts;
627
638
  }
628
- } else if (primaryLabel === "WorkflowStep") {
639
+ } else if (primaryLabel2 === "WorkflowStep") {
629
640
  const v = props.label;
630
641
  if (typeof v === "string" && v.length > 0)
631
642
  return v;
632
- } else if (primaryLabel === "Person") {
643
+ } else if (primaryLabel2 === "Person") {
633
644
  const given = typeof props.givenName === "string" ? props.givenName : "";
634
645
  const family = typeof props.familyName === "string" ? props.familyName : "";
635
646
  const full = [given, family].filter((s) => s.length > 0).join(" ");
636
647
  if (full.length > 0)
637
648
  return full;
638
- } else if (primaryLabel === "Agent") {
649
+ } else if (primaryLabel2 === "Agent") {
639
650
  const dn = typeof props.displayName === "string" ? props.displayName : "";
640
651
  const slug = typeof props.slug === "string" ? props.slug : "";
641
652
  const v = dn.length > 0 ? dn : slug;
642
653
  if (v.length > 0)
643
654
  return v;
644
- } else if (primaryLabel === "Job") {
655
+ } else if (primaryLabel2 === "Job") {
645
656
  const client = typeof props.client === "string" ? props.client : "";
646
657
  const jobId = typeof props.jobId === "string" ? props.jobId : "";
647
658
  const composed = [client, jobId.length > 0 ? `#${jobId}` : ""].filter((s) => s.length > 0).join(" ");
648
659
  if (composed.length > 0)
649
660
  return composed;
650
- } else if (primaryLabel === "QuoteDocument") {
661
+ } else if (primaryLabel2 === "QuoteDocument") {
651
662
  const ref = typeof props.ref === "string" ? props.ref : "";
652
663
  if (ref.length > 0)
653
664
  return ref;
654
- } else if (primaryLabel === "InboundInvoice") {
665
+ } else if (primaryLabel2 === "InboundInvoice") {
655
666
  const supplier = typeof props.supplier === "string" ? props.supplier : "";
656
667
  const conf = typeof props.confirmationNumber === "string" ? props.confirmationNumber : "";
657
668
  const composed = [supplier, conf.length > 0 ? `#${conf}` : ""].filter((s) => s.length > 0).join(" ");
658
669
  if (composed.length > 0)
659
670
  return composed;
660
- } else if (primaryLabel === "WhatsAppGroup") {
671
+ } else if (primaryLabel2 === "WhatsAppGroup") {
661
672
  const clientName = typeof props.clientName === "string" ? props.clientName : "";
662
673
  if (clientName.length > 0)
663
674
  return clientName;
@@ -667,12 +678,12 @@ var require_dist2 = __commonJS({
667
678
  if (typeof v === "string" && v.length > 0)
668
679
  return v;
669
680
  }
670
- if (primaryLabel === "Conversation") {
681
+ if (primaryLabel2 === "Conversation") {
671
682
  const id = typeof props.sessionId === "string" ? props.sessionId : null;
672
683
  if (id)
673
684
  return `Conv ${id.slice(0, 8)}`;
674
685
  }
675
- return primaryLabel ?? "\u2026";
686
+ return primaryLabel2 ?? "\u2026";
676
687
  }
677
688
  }
678
689
  });
@@ -886,7 +897,16 @@ var require_dist3 = __commonJS({
886
897
  "Job",
887
898
  "LineItem",
888
899
  "QuoteDocument",
889
- "VariationNote"
900
+ "VariationNote",
901
+ // Knowledge-work vertical — the seven gap labels, each carrying a
902
+ // CREATE VECTOR INDEX in schema.cypher so the chokepoint auto-embeds them.
903
+ "Objective",
904
+ "KeyResult",
905
+ "Decision",
906
+ "Risk",
907
+ "Source",
908
+ "Finding",
909
+ "Hypothesis"
890
910
  ]);
891
911
  exports.DOCUMENT_ARCHIVE_LABELS = /* @__PURE__ */ new Set([
892
912
  "KnowledgeDocument",
@@ -7953,18 +7973,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
7953
7973
  function canonicalOverridePath(accountDir) {
7954
7974
  return join13(accountDir, FILE);
7955
7975
  }
7956
- function readCanonicalOverrideId(accountDir) {
7976
+ function readRaw(accountDir) {
7957
7977
  try {
7958
- const raw = JSON.parse(readFileSync14(canonicalOverridePath(accountDir), "utf8"));
7959
- return typeof raw.sessionId === "string" && UUID.test(raw.sessionId) ? raw.sessionId : null;
7978
+ return JSON.parse(readFileSync14(canonicalOverridePath(accountDir), "utf8"));
7960
7979
  } catch {
7961
7980
  return null;
7962
7981
  }
7963
7982
  }
7964
- function writeCanonicalOverrideId(accountDir, sessionId) {
7983
+ function readCanonicalOverrideId(accountDir, userId, primaryUserId) {
7984
+ const raw = readRaw(accountDir);
7985
+ if (!raw) return null;
7986
+ if (raw.byAdmin && typeof raw.byAdmin === "object") {
7987
+ const v = raw.byAdmin[userId];
7988
+ return typeof v === "string" && UUID.test(v) ? v : null;
7989
+ }
7990
+ if (typeof raw.sessionId === "string" && UUID.test(raw.sessionId) && primaryUserId !== null && userId === primaryUserId) {
7991
+ return raw.sessionId;
7992
+ }
7993
+ return null;
7994
+ }
7995
+ function writeCanonicalOverrideId(accountDir, userId, sessionId) {
7996
+ const raw = readRaw(accountDir);
7997
+ const byAdmin = {};
7998
+ if (raw?.byAdmin && typeof raw.byAdmin === "object") {
7999
+ for (const [k, v] of Object.entries(raw.byAdmin)) {
8000
+ if (typeof v === "string") byAdmin[k] = v;
8001
+ }
8002
+ }
8003
+ byAdmin[userId] = sessionId;
7965
8004
  const path2 = canonicalOverridePath(accountDir);
7966
8005
  const tmp = `${path2}.${process.pid}.tmp`;
7967
- writeFileSync5(tmp, JSON.stringify({ sessionId }, null, 2), "utf8");
8006
+ writeFileSync5(tmp, JSON.stringify({ byAdmin }, null, 2), "utf8");
7968
8007
  renameSync(tmp, path2);
7969
8008
  }
7970
8009
 
@@ -7980,6 +8019,35 @@ function adminSessionIdFor(accountId, senderId, personId) {
7980
8019
  return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20, 32)}`;
7981
8020
  }
7982
8021
 
8022
+ // ../lib/models/src/index.ts
8023
+ var OPUS_MODEL = "claude-opus-4-8[1m]";
8024
+ var SONNET_MODEL = "claude-sonnet-4-6";
8025
+ var HAIKU_MODEL = "claude-haiku-4-5";
8026
+ var MODEL_CONTEXT_WINDOW = {
8027
+ [OPUS_MODEL]: 1e6,
8028
+ [SONNET_MODEL]: 2e5,
8029
+ [HAIKU_MODEL]: 2e5
8030
+ };
8031
+ var MODEL_DISPLAY_NAMES = {
8032
+ [OPUS_MODEL]: "Opus 4.8 (1M context)",
8033
+ [SONNET_MODEL]: "Sonnet 4.6",
8034
+ [HAIKU_MODEL]: "Haiku 4.5"
8035
+ };
8036
+ var SELECTABLE_MODELS = [OPUS_MODEL, SONNET_MODEL, HAIKU_MODEL];
8037
+ function isSelectableModel(id) {
8038
+ return SELECTABLE_MODELS.includes(id);
8039
+ }
8040
+ var PERMISSION_MODES = ["default", "acceptEdits", "plan", "auto", "bypassPermissions"];
8041
+ function isPermissionMode(value) {
8042
+ return PERMISSION_MODES.includes(value);
8043
+ }
8044
+ var EFFORT_LEVELS = ["low", "medium", "high", "xhigh"];
8045
+ function isEffortLevel(value) {
8046
+ return EFFORT_LEVELS.includes(value);
8047
+ }
8048
+ var SPAWN_PERMISSION_MODES = [...PERMISSION_MODES, "dontAsk"];
8049
+ var SESSION_EFFORT_LEVELS = ["auto", ...EFFORT_LEVELS, "max"];
8050
+
7983
8051
  // ../services/claude-session-manager/src/sidecar-store.ts
7984
8052
  import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync as readdirSync9, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
7985
8053
  import { join as join14 } from "path";
@@ -8133,11 +8201,25 @@ function locateSidecar(sessionId) {
8133
8201
  for (const slug of slugs) {
8134
8202
  const metaPath = join15(projectsRoot, slug, `${sessionId}.meta.json`);
8135
8203
  if (existsSync9(metaPath)) {
8136
- return { channel: readSidecarMeta(metaPath).channel };
8204
+ const meta = readSidecarMeta(metaPath);
8205
+ return { channel: meta.channel, adminUserId: meta.adminUserId };
8137
8206
  }
8138
8207
  }
8139
8208
  return null;
8140
8209
  }
8210
+ function readTargetOwner(sessionId) {
8211
+ const sidecar = locateSidecar(sessionId);
8212
+ if (sidecar !== null) return { found: true, owner: sidecar.adminUserId };
8213
+ const { projectDir } = locateSession(sessionId);
8214
+ if (projectDir !== null) {
8215
+ return { found: true, owner: readSidecarMeta(join15(projectDir, `${sessionId}.meta.json`)).adminUserId };
8216
+ }
8217
+ return { found: false, owner: null };
8218
+ }
8219
+ function ownedByRequester(owner, requesterUserId, primaryUserId) {
8220
+ if (requesterUserId === null) return false;
8221
+ return owner === requesterUserId || owner === null && requesterUserId === primaryUserId;
8222
+ }
8141
8223
  function sessionSidecarExists(sessionId) {
8142
8224
  return locateSidecar(sessionId) !== null;
8143
8225
  }
@@ -8188,8 +8270,6 @@ async function fetchComposerIndicators(sessionId) {
8188
8270
  }
8189
8271
  }
8190
8272
  var MODEL_ID_PATTERN = /^claude-[a-z0-9][a-z0-9.-]*(\[1m\])?$/;
8191
- var EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
8192
- var PERMISSION_MODE_VALUES = /* @__PURE__ */ new Set(["default", "acceptEdits", "plan", "auto", "bypassPermissions"]);
8193
8273
  function readLevers(preResolved) {
8194
8274
  let account = preResolved;
8195
8275
  if (account === void 0) {
@@ -8205,11 +8285,20 @@ function readLevers(preResolved) {
8205
8285
  const mode = account.config.adminPermissionMode;
8206
8286
  return {
8207
8287
  leverModel: typeof model === "string" && MODEL_ID_PATTERN.test(model) ? model : null,
8208
- leverEffort: typeof effort === "string" && EFFORT_LEVELS.has(effort) ? effort : null,
8209
- leverMode: typeof mode === "string" && PERMISSION_MODE_VALUES.has(mode) ? mode : null
8288
+ leverEffort: typeof effort === "string" && isEffortLevel(effort) ? effort : null,
8289
+ leverMode: typeof mode === "string" && isPermissionMode(mode) ? mode : null
8210
8290
  };
8211
8291
  }
8212
- function latestAdminWebchatSessionId() {
8292
+ function resolvePrimaryAdminUserId() {
8293
+ try {
8294
+ const users = readUsersFile(USERS_FILE);
8295
+ return users && users.length > 0 ? users[0].userId : null;
8296
+ } catch {
8297
+ return null;
8298
+ }
8299
+ }
8300
+ function latestAdminWebchatSessionId(requesterUserId, primaryUserId) {
8301
+ if (requesterUserId === null) return null;
8213
8302
  const cfg = claudeConfigDir();
8214
8303
  if (!cfg) return null;
8215
8304
  let best = null;
@@ -8224,6 +8313,13 @@ function latestAdminWebchatSessionId() {
8224
8313
  } catch {
8225
8314
  continue;
8226
8315
  }
8316
+ const owned = meta.adminUserId === requesterUserId || meta.adminUserId === null && requesterUserId === primaryUserId;
8317
+ if (!owned) {
8318
+ if (best === null || mtimeMs > best.mtimeMs) {
8319
+ 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)}`);
8320
+ }
8321
+ continue;
8322
+ }
8227
8323
  if (best === null || mtimeMs > best.mtimeMs) best = { id, mtimeMs };
8228
8324
  }
8229
8325
  return best === null ? null : best.id;
@@ -8233,14 +8329,17 @@ function overrideKnownNonArchived(id) {
8233
8329
  if (projectDir === null) return sessionSidecarExists(id);
8234
8330
  return basename4(projectDir) !== "archive";
8235
8331
  }
8236
- function resolveCanonical(accountId, accountDir) {
8237
- const latest = latestAdminWebchatSessionId();
8332
+ function resolveCanonical(accountId, accountDir, requesterUserId, primaryUserId) {
8333
+ if (requesterUserId === null) {
8334
+ return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY), source: "canonical-empty" };
8335
+ }
8336
+ const latest = latestAdminWebchatSessionId(requesterUserId, primaryUserId);
8238
8337
  if (latest !== null) return { sessionId: latest, source: "latest" };
8239
8338
  if (accountDir) {
8240
- const override = readCanonicalOverrideId(accountDir);
8339
+ const override = readCanonicalOverrideId(accountDir, requesterUserId, primaryUserId);
8241
8340
  if (override && overrideKnownNonArchived(override)) return { sessionId: override, source: "override" };
8242
8341
  }
8243
- return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY), source: "canonical-empty" };
8342
+ return { sessionId: adminSessionIdFor(accountId, WEBCHAT_ADMIN_KEY, requesterUserId), source: "canonical-empty" };
8244
8343
  }
8245
8344
  var REAPPLY_TIMEOUT_MS = 1500;
8246
8345
  async function reapplyLeversViaManager() {
@@ -8273,6 +8372,9 @@ function createWebchatRoutes(deps) {
8273
8372
  console.error(`[webchat:inbound] op=send-refused reason=account-unresolved detail=${detail}`);
8274
8373
  return c.json({ error: "account unresolved" }, 503);
8275
8374
  }
8375
+ const cacheKey = c.get("cacheKey");
8376
+ const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
8377
+ const primaryUserId = resolvePrimaryAdminUserId();
8276
8378
  let text;
8277
8379
  let target;
8278
8380
  let files = [];
@@ -8313,10 +8415,18 @@ function createWebchatRoutes(deps) {
8313
8415
  }
8314
8416
  let deliveryKey = WEBCHAT_ADMIN_KEY;
8315
8417
  let deliverySessionId;
8418
+ const explicitTarget = target !== void 0;
8316
8419
  if (target === void 0) {
8317
- const latest = latestAdminWebchatSessionId();
8420
+ const latest = latestAdminWebchatSessionId(requesterUserId, primaryUserId);
8318
8421
  if (latest !== null) target = latest;
8319
8422
  }
8423
+ if (explicitTarget && target !== void 0) {
8424
+ const t = readTargetOwner(target);
8425
+ if (t.found && !ownedByRequester(t.owner, requesterUserId, primaryUserId)) {
8426
+ console.error(`[webchat:inbound] op=send-refused key=session:${target.slice(0, 8)} reason=foreign-target requester=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8427
+ return c.json({ error: "session not found" }, 404);
8428
+ }
8429
+ }
8320
8430
  if (target !== void 0) {
8321
8431
  let { projectDir, channel } = locateSession(target);
8322
8432
  if (projectDir === null) {
@@ -8392,10 +8502,11 @@ ${note}` : note;
8392
8502
  }
8393
8503
  console.log(`[webchat:inbound] op=send-accepted kind=${kind} files=${stored.length} bytes=${Buffer.byteLength(text, "utf8")}`);
8394
8504
  }
8505
+ const adminUserId = requesterUserId ?? void 0;
8395
8506
  if (deliverySessionId !== void 0) {
8396
- await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId });
8507
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, sessionId: deliverySessionId, adminUserId });
8397
8508
  } else {
8398
- await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text });
8509
+ await deps.handleInbound({ role: "admin", accountId, key: deliveryKey, text, adminUserId });
8399
8510
  }
8400
8511
  const sendId = ++sendSeq;
8401
8512
  let turnSessionId = deliverySessionId;
@@ -8406,7 +8517,7 @@ ${note}` : note;
8406
8517
  } catch {
8407
8518
  canonAccount = null;
8408
8519
  }
8409
- turnSessionId = resolveCanonical(accountId, canonAccount?.accountDir ?? null).sessionId;
8520
+ turnSessionId = resolveCanonical(accountId, canonAccount?.accountDir ?? null, requesterUserId, primaryUserId).sessionId;
8410
8521
  }
8411
8522
  const keyDisplay2 = deliveryKey.startsWith("session:") ? deliveryKey.slice(0, "session:".length + 8) : WEBCHAT_ADMIN_KEY;
8412
8523
  const baseline = jsonlSizeBytes(locateSession(turnSessionId).projectDir, turnSessionId);
@@ -8431,7 +8542,7 @@ ${note}` : note;
8431
8542
  console.error(`[webchat:settings] op=${String(op)} outcome=refused reason=unknown-op`);
8432
8543
  return c.json({ error: "op must be model, effort, or mode" }, 400);
8433
8544
  }
8434
- if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !EFFORT_LEVELS.has(value) || op === "mode" && !PERMISSION_MODE_VALUES.has(value)) {
8545
+ if (typeof value !== "string" || op === "model" && !MODEL_ID_PATTERN.test(value) || op === "effort" && !isEffortLevel(value) || op === "mode" && !isPermissionMode(value)) {
8435
8546
  console.error(`[webchat:settings] op=${op} outcome=refused value=${JSON.stringify(value)} reason=invalid-value`);
8436
8547
  return c.json({ error: `invalid ${op} value` }, 400);
8437
8548
  }
@@ -8472,11 +8583,19 @@ ${note}` : note;
8472
8583
  console.error(`[webchat:inbound] op=session-refused reason=account-unresolved detail=${detail}`);
8473
8584
  return c.json({ error: "account unresolved" }, 503);
8474
8585
  }
8586
+ const cacheKey = c.get("cacheKey");
8587
+ const requesterUserId = (cacheKey ? getUserIdForSession(cacheKey) : void 0) ?? null;
8588
+ const primaryUserId = resolvePrimaryAdminUserId();
8475
8589
  const target = c.req.query("session");
8476
8590
  if (target !== void 0) {
8477
8591
  if (!UUID_PATTERN.test(target)) {
8478
8592
  return c.json({ error: "invalid session id" }, 400);
8479
8593
  }
8594
+ const owned = readTargetOwner(target);
8595
+ if (owned.found && !ownedByRequester(owned.owner, requesterUserId, primaryUserId)) {
8596
+ console.error(`[webchat:inbound] op=session-target-foreign key=session:${target.slice(0, 8)} requester=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8597
+ return c.json({ error: "session not found" }, 404);
8598
+ }
8480
8599
  const { projectDir: projectDir2, channel } = locateSession(target);
8481
8600
  let resolvedProjectDir = projectDir2;
8482
8601
  let transcriptSessionId = target;
@@ -8505,11 +8624,14 @@ ${note}` : note;
8505
8624
  } catch {
8506
8625
  account = null;
8507
8626
  }
8508
- const { sessionId, source } = resolveCanonical(accountId, account?.accountDir ?? null);
8509
- if (source === "latest" && account?.accountDir) {
8510
- writeCanonicalOverrideId(account.accountDir, sessionId);
8627
+ const { sessionId, source } = resolveCanonical(accountId, account?.accountDir ?? null, requesterUserId, primaryUserId);
8628
+ if (requesterUserId === null) {
8629
+ console.error(`[webchat:inbound] op=session-resolve-no-identity key=${sessionId.slice(0, 8)}`);
8511
8630
  }
8512
- console.log(`[webchat:inbound] op=session-resolve key=${sessionId.slice(0, 8)} source=${source}`);
8631
+ if (source === "latest" && account?.accountDir && requesterUserId !== null) {
8632
+ writeCanonicalOverrideId(account.accountDir, requesterUserId, sessionId);
8633
+ }
8634
+ console.log(`[webchat:inbound] op=session-resolve key=${sessionId.slice(0, 8)} source=${source} admin=${requesterUserId ? requesterUserId.slice(0, 8) : "none"}`);
8513
8635
  const cfg = claudeConfigDir();
8514
8636
  let projectDir = null;
8515
8637
  if (cfg) {
@@ -8520,6 +8642,12 @@ ${note}` : note;
8520
8642
  }
8521
8643
  }
8522
8644
  }
8645
+ if (source === "latest" && requesterUserId !== null) {
8646
+ const owner = readSidecarMeta(join15(projectDir ?? "", `${sessionId}.meta.json`)).adminUserId;
8647
+ if (owner !== null && owner !== requesterUserId && requesterUserId !== primaryUserId) {
8648
+ console.error(`[webchat:inbound] op=session-resolve-foreign key=${sessionId.slice(0, 8)} owner=${owner.slice(0, 8)} requester=${requesterUserId.slice(0, 8)}`);
8649
+ }
8650
+ }
8523
8651
  const indicators = await fetchComposerIndicators(sessionId);
8524
8652
  return c.json({ sessionId, projectDir, sizeBytes: jsonlSizeBytes(projectDir, sessionId), pendingPermissionPrompt: deps.pendingPromptFor?.(`session:${sessionId}`) ?? null, ...indicators, ...readLevers(account) });
8525
8653
  });
@@ -8721,7 +8849,8 @@ async function managerSpawn(opts) {
8721
8849
  personId: opts.personId,
8722
8850
  visitorId: opts.visitorId,
8723
8851
  name: opts.name,
8724
- webchatChannel: opts.webchatChannel
8852
+ webchatChannel: opts.webchatChannel,
8853
+ previousContext: opts.previousContext
8725
8854
  })
8726
8855
  }).catch((err) => ({ __throw: err instanceof Error ? err.message : String(err) }));
8727
8856
  if ("__throw" in res) {
@@ -8748,6 +8877,7 @@ async function managerRcSpawn(opts) {
8748
8877
  sliceToken: opts.sliceToken,
8749
8878
  personId: opts.personId,
8750
8879
  userId: opts.userId,
8880
+ adminUserId: opts.adminUserId,
8751
8881
  waChannel: opts.waChannel,
8752
8882
  webchatChannel: opts.webchatChannel,
8753
8883
  role: opts.role,
@@ -13282,6 +13412,7 @@ app20.get("/download", requireAdminSession, async (c) => {
13282
13412
  if (root !== "data" && root !== "claude-uploads") {
13283
13413
  return c.json({ error: "invalid root" }, 400);
13284
13414
  }
13415
+ const disposition = c.req.query("disposition") ?? "attachment";
13285
13416
  const resolution = root === "claude-uploads" ? resolveClaudeUploadsPath(rawPath) : resolveDataPath(rawPath);
13286
13417
  if (!resolution.ok) {
13287
13418
  if (resolution.status === 403) {
@@ -13310,6 +13441,21 @@ app20.get("/download", requireAdminSession, async (c) => {
13310
13441
  const mimeType = detectMimeType(absolute);
13311
13442
  const nodeStream = createReadStream2(absolute);
13312
13443
  const webStream = Readable2.toWeb(nodeStream);
13444
+ if (disposition === "inline") {
13445
+ if (!mimeType.startsWith("image/")) {
13446
+ console.error(`[data] op=thumb-refused path="${relPath}" mime="${mimeType}" reason=not-image`);
13447
+ return c.json({ error: "Inline serve is image-only" }, 400);
13448
+ }
13449
+ console.error(`[data] op=thumb-serve path="${relPath}" mime="${mimeType}" size=${info.size} status=200`);
13450
+ return new Response(webStream, {
13451
+ status: 200,
13452
+ headers: {
13453
+ "Content-Type": mimeType,
13454
+ "Content-Length": String(info.size),
13455
+ "Cache-Control": "private, max-age=3600"
13456
+ }
13457
+ });
13458
+ }
13313
13459
  console.error(`[data] file-download root="${root}" path="${relPath}" size=${info.size}`);
13314
13460
  const safeQuotedName = filename.replace(/[\r\n"\\]/g, "_");
13315
13461
  const encodedName = encodeURIComponent(filename);
@@ -14607,7 +14753,15 @@ var FILTER_TOP_LEVEL_LABELS = Object.freeze(
14607
14753
  "Workflow",
14608
14754
  "Email",
14609
14755
  "EmailAccount",
14610
- "Agent"
14756
+ "Agent",
14757
+ // Knowledge-work vertical (schema-knowledge-work.md) — operator-entry labels.
14758
+ "Objective",
14759
+ "KeyResult",
14760
+ "Decision",
14761
+ "Risk",
14762
+ "Source",
14763
+ "Finding",
14764
+ "Hypothesis"
14611
14765
  ])
14612
14766
  );
14613
14767
  var AGENT_ACTION_LABELS = Object.freeze(
@@ -16102,29 +16256,6 @@ var session_rc_spawn_default = app32;
16102
16256
 
16103
16257
  // server/routes/admin/session-reseat.ts
16104
16258
  import { randomUUID as randomUUID12 } from "crypto";
16105
-
16106
- // ../lib/models/src/index.ts
16107
- var OPUS_MODEL = "claude-opus-4-8[1m]";
16108
- var SONNET_MODEL = "claude-sonnet-4-6";
16109
- var HAIKU_MODEL = "claude-haiku-4-5";
16110
- var MODEL_CONTEXT_WINDOW = {
16111
- [OPUS_MODEL]: 1e6,
16112
- [SONNET_MODEL]: 2e5,
16113
- [HAIKU_MODEL]: 2e5
16114
- };
16115
- var MODEL_DISPLAY_NAMES = {
16116
- [OPUS_MODEL]: "Opus 4.8 (1M context)",
16117
- [SONNET_MODEL]: "Sonnet 4.6",
16118
- [HAIKU_MODEL]: "Haiku 4.5"
16119
- };
16120
- var SELECTABLE_MODELS = [OPUS_MODEL, SONNET_MODEL, HAIKU_MODEL];
16121
- function isSelectableModel(id) {
16122
- return SELECTABLE_MODELS.includes(id);
16123
- }
16124
-
16125
- // server/routes/admin/session-reseat.ts
16126
- var RESEAT_PERMISSION_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits", "plan", "auto", "bypassPermissions"]);
16127
- var RESEAT_EFFORT_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh"]);
16128
16259
  function resolveReseatPlan(body, mintId = randomUUID12, adminUserId, authenticatedName) {
16129
16260
  const sessionId = mintId();
16130
16261
  const key = `session:${sessionId}`;
@@ -16157,8 +16288,8 @@ app33.post("/", requireAdminSession, async (c) => {
16157
16288
  const model = typeof body.model === "string" && isSelectableModel(body.model) ? body.model : null;
16158
16289
  if (fromSessionId === null) return c.json({ error: "fromSessionId must be a valid session id" }, 400);
16159
16290
  if (model === null) return c.json({ error: "model must be a selectable model" }, 400);
16160
- const permissionMode = typeof body.permissionMode === "string" ? RESEAT_PERMISSION_MODES.has(body.permissionMode) ? body.permissionMode : null : void 0;
16161
- const effort = typeof body.effort === "string" ? RESEAT_EFFORT_LEVELS.has(body.effort) ? body.effort : null : void 0;
16291
+ const permissionMode = typeof body.permissionMode === "string" ? isPermissionMode(body.permissionMode) ? body.permissionMode : null : void 0;
16292
+ const effort = typeof body.effort === "string" ? isEffortLevel(body.effort) ? body.effort : null : void 0;
16162
16293
  if (permissionMode === null) return c.json({ error: "permissionMode must be a composer-writable mode" }, 400);
16163
16294
  if (effort === null) return c.json({ error: "effort must be an accepted level" }, 400);
16164
16295
  if (reseatsInFlight.has(fromSessionId)) {
@@ -16168,6 +16299,13 @@ app33.post("/", requireAdminSession, async (c) => {
16168
16299
  try {
16169
16300
  const cacheKey = c.get("cacheKey");
16170
16301
  const adminUserId = cacheKey ? getUserIdForSession(cacheKey) : void 0;
16302
+ {
16303
+ const ownerInfo = readTargetOwner(fromSessionId);
16304
+ if (!(ownerInfo.found && ownedByRequester(ownerInfo.owner, adminUserId ?? null, resolvePrimaryAdminUserId()))) {
16305
+ console.error(`[chat-reseat] op=reseat-refused from=${fromSessionId.slice(0, 8)} reason=foreign-source requester=${adminUserId ? adminUserId.slice(0, 8) : "none"}`);
16306
+ return c.json({ error: "session not found" }, 404);
16307
+ }
16308
+ }
16171
16309
  const accountId = cacheKey ? getAccountIdForSession(cacheKey) : void 0;
16172
16310
  const authenticatedName = accountId ? await resolveAuthenticatedName(accountId, adminUserId) : void 0;
16173
16311
  const plan = resolveReseatPlan(
@@ -16204,12 +16342,13 @@ app33.post("/", requireAdminSession, async (c) => {
16204
16342
  }
16205
16343
  try {
16206
16344
  const account = resolveAccount();
16207
- if (account) {
16345
+ if (account && adminUserId) {
16208
16346
  const accountId2 = resolvePlatformAccountId();
16209
- const canonicalId = adminSessionIdFor(accountId2, WEBCHAT_ADMIN_KEY);
16210
- const currentOverride = readCanonicalOverrideId(account.accountDir);
16347
+ const primaryUserId = resolvePrimaryAdminUserId();
16348
+ const canonicalId = adminSessionIdFor(accountId2, WEBCHAT_ADMIN_KEY, adminUserId);
16349
+ const currentOverride = readCanonicalOverrideId(account.accountDir, adminUserId, primaryUserId);
16211
16350
  if (fromSessionId === canonicalId || fromSessionId === currentOverride) {
16212
- writeCanonicalOverrideId(account.accountDir, plan.sessionId);
16351
+ writeCanonicalOverrideId(account.accountDir, adminUserId, plan.sessionId);
16213
16352
  console.log(`[chat-reseat] op=canonical-forward reseatReqId=${reseatReqId} from=${fromSessionId} to=${plan.sessionId}`);
16214
16353
  }
16215
16354
  }
@@ -16668,9 +16807,8 @@ app37.get("/", async (c) => {
16668
16807
  });
16669
16808
  var post_turn_context_default = app37;
16670
16809
 
16671
- // server/routes/admin/public-session-context.ts
16810
+ // app/lib/slice-writes.ts
16672
16811
  import neo4j4 from "neo4j-driver";
16673
- var TAG32 = "[public-session-context]";
16674
16812
  var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
16675
16813
  "embedding",
16676
16814
  "passwordHash",
@@ -16678,9 +16816,6 @@ var STRIPPED_PROPERTIES3 = /* @__PURE__ */ new Set([
16678
16816
  "otpCode",
16679
16817
  "cacheKey"
16680
16818
  ]);
16681
- function isLoopbackAddr3(addr) {
16682
- return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
16683
- }
16684
16819
  function convertValue2(value) {
16685
16820
  if (neo4j4.isDateTime(value) || neo4j4.isDate(value) || neo4j4.isLocalDateTime(value) || neo4j4.isLocalTime(value) || neo4j4.isTime(value) || neo4j4.isDuration(value)) {
16686
16821
  return value.toString();
@@ -16708,6 +16843,78 @@ function pruneProperties2(raw) {
16708
16843
  }
16709
16844
  return out;
16710
16845
  }
16846
+ async function fetchSliceWrites(session, sliceToken, accountId) {
16847
+ const cypher = `
16848
+ MATCH (n)
16849
+ WHERE n.sliceToken = $sliceToken AND n.accountId = $accountId
16850
+ RETURN elementId(n) AS elementId,
16851
+ labels(n) AS labels,
16852
+ properties(n) AS properties,
16853
+ coalesce(n.createdAt, n.observedAt, '') AS sortKey
16854
+ `;
16855
+ const res = await session.executeRead((tx) => tx.run(cypher, { sliceToken, accountId }));
16856
+ const writes = res.records.map((r) => ({
16857
+ elementId: r.get("elementId"),
16858
+ labels: r.get("labels"),
16859
+ properties: pruneProperties2(r.get("properties")),
16860
+ sortKey: String(r.get("sortKey") ?? "")
16861
+ }));
16862
+ writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
16863
+ return writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }));
16864
+ }
16865
+ var STRUCTURAL_KEYS = /* @__PURE__ */ new Set([
16866
+ "accountId",
16867
+ "scope",
16868
+ "sliceToken",
16869
+ "preferenceId",
16870
+ "ideaId",
16871
+ "createdAt",
16872
+ "updatedAt",
16873
+ "observedAt",
16874
+ "sessionId",
16875
+ "createdByAgent",
16876
+ "createdBySession",
16877
+ "confidence",
16878
+ "notApplicable"
16879
+ ]);
16880
+ function primaryLabel(labels) {
16881
+ return labels.find((l) => l.length > 0) ?? "Node";
16882
+ }
16883
+ function renderWrite(write) {
16884
+ const label = primaryLabel(write.labels);
16885
+ const props = write.properties;
16886
+ const parts = [];
16887
+ if (label === "Person") {
16888
+ const name = [props.givenName, props.familyName].filter((v) => typeof v === "string" && v.length > 0).join(" ");
16889
+ if (name) parts.push(name);
16890
+ }
16891
+ const kv = [];
16892
+ for (const [k, v] of Object.entries(props)) {
16893
+ if (STRUCTURAL_KEYS.has(k)) continue;
16894
+ if (label === "Person" && (k === "givenName" || k === "familyName")) continue;
16895
+ if (v === null || v === void 0 || v === "") continue;
16896
+ const val = String(v).slice(0, 200);
16897
+ kv.push(`${k}=${val}`);
16898
+ }
16899
+ const tail = [parts.join(" "), kv.join("; ")].filter((s) => s.length > 0).join(" \u2014 ");
16900
+ if (tail.length === 0) return null;
16901
+ return `- ${label}: ${tail}`;
16902
+ }
16903
+ function formatPreviousContext(writes) {
16904
+ if (writes.length === 0) return null;
16905
+ const lines = writes.filter((w) => w.properties.scope === "user").map(renderWrite).filter((l) => l !== null);
16906
+ if (lines.length === 0) return null;
16907
+ return [
16908
+ "What you already know about this visitor from earlier conversations:",
16909
+ ...lines
16910
+ ].join("\n");
16911
+ }
16912
+
16913
+ // server/routes/admin/public-session-context.ts
16914
+ var TAG32 = "[public-session-context]";
16915
+ function isLoopbackAddr3(addr) {
16916
+ return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1";
16917
+ }
16711
16918
  var app38 = new Hono();
16712
16919
  app38.get("/", async (c) => {
16713
16920
  const remoteAddr = c.env?.incoming?.socket?.remoteAddress ?? "";
@@ -16732,31 +16939,12 @@ app38.get("/", async (c) => {
16732
16939
  const session = getSession();
16733
16940
  const started = Date.now();
16734
16941
  try {
16735
- const cypher = `
16736
- MATCH (n)
16737
- WHERE n.sliceToken = $sliceToken AND n.accountId = $accountId
16738
- RETURN elementId(n) AS elementId,
16739
- labels(n) AS labels,
16740
- properties(n) AS properties,
16741
- coalesce(n.createdAt, n.observedAt, '') AS sortKey
16742
- `;
16743
- const res = await session.executeRead(
16744
- (tx) => tx.run(cypher, { sliceToken, accountId })
16745
- );
16746
- const writes = res.records.map((r) => ({
16747
- elementId: r.get("elementId"),
16748
- labels: r.get("labels"),
16749
- properties: pruneProperties2(r.get("properties")),
16750
- sortKey: String(r.get("sortKey") ?? "")
16751
- }));
16752
- writes.sort((a, b) => a.sortKey.localeCompare(b.sortKey));
16942
+ const writes = await fetchSliceWrites(session, sliceToken, accountId);
16753
16943
  const total = Date.now() - started;
16754
16944
  console.log(
16755
16945
  `${TAG32} sliceToken=${sliceToken.slice(0, 8)} writes=${writes.length} ms=${total}`
16756
16946
  );
16757
- return c.json({
16758
- writes: writes.map(({ elementId, labels, properties }) => ({ elementId, labels, properties }))
16759
- });
16947
+ return c.json({ writes });
16760
16948
  } catch (err) {
16761
16949
  const elapsed = Date.now() - started;
16762
16950
  const message = err instanceof Error ? err.message : String(err);
@@ -17995,19 +18183,8 @@ app51.post("/", async (c) => {
17995
18183
  const account = resolveAccount();
17996
18184
  const cookieHeader = c.req.header("cookie");
17997
18185
  const visitorId = parseVisitorCookie2(cookieHeader);
17998
- const groupSlug = body.group_slug && typeof body.group_slug === "string" ? body.group_slug : null;
17999
- let groupInfo = null;
18000
- if (groupSlug) {
18001
- groupInfo = await findGroupBySlug(groupSlug, accountId).catch(() => null);
18002
- if (!groupInfo) {
18003
- console.error(`[session] group not found: slug=${groupSlug} account=${accountId.slice(0, 8)}\u2026`);
18004
- return c.json({ error: "Group not found" }, 404);
18005
- }
18006
- }
18007
18186
  let agentSlug = null;
18008
- if (groupInfo) {
18009
- agentSlug = groupInfo.agentSlug;
18010
- } else if (body.agent) {
18187
+ if (body.agent) {
18011
18188
  if (!validateAgentSlug(body.agent)) {
18012
18189
  return c.json({ error: "Invalid agent name" }, 400);
18013
18190
  }
@@ -18040,11 +18217,6 @@ app51.post("/", async (c) => {
18040
18217
  ...agentConfig.imageShape ? { agentImageShape: agentConfig.imageShape } : {},
18041
18218
  ...agentConfig.showAgentName ? { showAgentName: agentConfig.showAgentName } : {}
18042
18219
  } : {};
18043
- const groupFields = groupInfo ? {
18044
- group: true,
18045
- groupName: groupInfo.groupName,
18046
- groupSlug
18047
- } : {};
18048
18220
  const branding = await fetchBranding(accountId).catch(() => null);
18049
18221
  if (branding) writeBrandingCache(accountId, agentSlug, branding);
18050
18222
  let accessSession = null;
@@ -18057,7 +18229,6 @@ app51.post("/", async (c) => {
18057
18229
  Response.json({
18058
18230
  auth_required: true,
18059
18231
  agent_id: agentSlug,
18060
- ...groupFields,
18061
18232
  ...branding ? { branding } : {},
18062
18233
  ...agentIdentity
18063
18234
  }),
@@ -18082,7 +18253,6 @@ app51.post("/", async (c) => {
18082
18253
  agent_id: agentSlug,
18083
18254
  resumed,
18084
18255
  ...resumed ? { messages: uiMessages } : {},
18085
- ...groupFields,
18086
18256
  ...branding ? { branding } : {},
18087
18257
  ...agentIdentity
18088
18258
  });
@@ -18093,56 +18263,10 @@ app51.post("/", async (c) => {
18093
18263
  session_key: body.session_key,
18094
18264
  agent_id: agentSlug,
18095
18265
  resumed: false,
18096
- ...groupFields,
18097
18266
  ...branding ? { branding } : {},
18098
18267
  ...agentIdentity
18099
18268
  });
18100
18269
  }
18101
- if (groupInfo && visitorId) {
18102
- let memberName = await checkGroupMembership(groupInfo.sessionId, visitorId).catch(() => null);
18103
- if (!memberName && accessSession) {
18104
- const contactValue = accessSession.contactValue;
18105
- const isEmail = contactValue?.includes("@");
18106
- const bindResult = await bindVisitorToGroup(
18107
- groupInfo.sessionId,
18108
- visitorId,
18109
- isEmail ? contactValue : void 0,
18110
- !isEmail ? contactValue : void 0
18111
- ).catch(() => null);
18112
- memberName = bindResult?.displayName ?? null;
18113
- }
18114
- if (memberName) {
18115
- const neo4jMessages = await getRecentMessages(groupInfo.sessionId).catch(() => []);
18116
- const uiMessages = neo4jMessages.filter((m) => m.content !== GREETING_DIRECTIVE).map((m) => ({
18117
- role: m.role === "user" ? "visitor" : "maxy",
18118
- content: m.content,
18119
- timestamp: new Date(m.createdAt).getTime() || Date.now()
18120
- }));
18121
- const participants = await getGroupParticipants(groupInfo.sessionId).catch(() => []);
18122
- const cacheKey2 = crypto.randomUUID();
18123
- const resumed = uiMessages.length > 0;
18124
- console.log(`[session] cold-resume group=${groupSlug} visitor=${visitorId.slice(0, 8)}\u2026 messages=${uiMessages.length}`);
18125
- return withVisitorCookie(
18126
- Response.json({
18127
- session_key: cacheKey2,
18128
- agent_id: agentSlug,
18129
- resumed,
18130
- ...resumed ? { messages: uiMessages } : {},
18131
- ...groupFields,
18132
- participants: participants.map((p) => ({ displayName: p.displayName, joinedAt: p.joinedAt })),
18133
- ...branding ? { branding } : {},
18134
- ...agentIdentity
18135
- }),
18136
- visitorId
18137
- );
18138
- }
18139
- console.log(`[session] group cold-resume denied: visitor=${visitorId.slice(0, 8)}\u2026 not a member of group=${groupSlug}`);
18140
- return c.json({ error: "Not a member of this group" }, 403);
18141
- }
18142
- if (groupInfo) {
18143
- console.error(`[session] group=${groupSlug} requires visitor cookie`);
18144
- return c.json({ error: "Groups require member authentication" }, 400);
18145
- }
18146
18270
  if (visitorId) {
18147
18271
  const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
18148
18272
  if (recent) {
@@ -18544,7 +18668,7 @@ var defaultResolveName = async (accountId, userId) => {
18544
18668
  const res = await loadAdminUserName(accountId, userId);
18545
18669
  return res.source === "neo4j" && res.joined.length > 0 ? res.joined : null;
18546
18670
  };
18547
- async function readRaw(path2) {
18671
+ async function readRaw2(path2) {
18548
18672
  let raw;
18549
18673
  try {
18550
18674
  raw = await readFile7(path2, "utf8");
@@ -18652,7 +18776,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
18652
18776
  };
18653
18777
  const sidecars = await collectLiveSidecars(projectsRoot);
18654
18778
  for (const path2 of sidecars) {
18655
- const raw = await readRaw(path2);
18779
+ const raw = await readRaw2(path2);
18656
18780
  if (!raw) continue;
18657
18781
  if (raw.role !== ADMIN_ROLE2 || raw.channel !== WEBCHAT_CHANNEL2) continue;
18658
18782
  result.scanned++;
@@ -18670,7 +18794,7 @@ async function migrateAdminWebchatSidecars(opts = {}) {
18670
18794
  await writeRaw(path2, raw);
18671
18795
  result.backfilled++;
18672
18796
  await resolveAdminName();
18673
- const back = await readRaw(path2);
18797
+ const back = await readRaw2(path2);
18674
18798
  const wrote = back && back.adminUserId === soleAdminUserId;
18675
18799
  if (wrote && resolvedNameForAdmin) {
18676
18800
  result.resolvedName++;
@@ -19614,6 +19738,9 @@ var WebchatGateway = class _WebchatGateway {
19614
19738
  // Task 800 — only present on a session-targeted launch, so the
19615
19739
  // default-path call shape stays byte-identical.
19616
19740
  ...input.sessionId !== void 0 ? { sessionId: input.sessionId } : {},
19741
+ // The authenticated admin's userId on an admin bootstrap inbound; the
19742
+ // default-path call shape stays byte-identical when absent.
19743
+ ...input.adminUserId !== void 0 ? { adminUserId: input.adminUserId } : {},
19617
19744
  // Task 756 — public spawn params on a role:'public' inbound.
19618
19745
  ...input.public !== void 0 ? { public: input.public } : {}
19619
19746
  });
@@ -19648,6 +19775,7 @@ function buildPublicWebchatSpawnRequest(input) {
19648
19775
  ...sliceToken ? { sliceToken } : {},
19649
19776
  ...personId ? { personId } : {},
19650
19777
  ...visitorId ? { visitorId } : {},
19778
+ ...input.previousContext ? { previousContext: input.previousContext } : {},
19651
19779
  name,
19652
19780
  webchatChannel: { key: input.key, gatewayUrl: input.gatewayUrl, serverPath: input.serverPath }
19653
19781
  };
@@ -20120,14 +20248,27 @@ waGateway.startSweeper();
20120
20248
  var webchatGateway = new WebchatGateway({
20121
20249
  gatewayUrl: webchatGatewayUrl(),
20122
20250
  serverPath: webchatServerPath(),
20123
- ensureChannelSession: async ({ accountId, key, role, gatewayUrl, serverPath, sessionId, public: pub }) => {
20251
+ ensureChannelSession: async ({ accountId, key, role, adminUserId, gatewayUrl, serverPath, sessionId, public: pub }) => {
20124
20252
  if (role === "public") {
20125
20253
  if (!pub) {
20126
20254
  console.error(`[webchat:inbound] op=spawn-refused key=${key} role=public reason=missing-public-params`);
20127
20255
  return;
20128
20256
  }
20257
+ let previousContext;
20258
+ if (pub.sliceToken) {
20259
+ const session = getSession();
20260
+ try {
20261
+ const writes = await fetchSliceWrites(session, pub.sliceToken, accountId);
20262
+ previousContext = formatPreviousContext(writes) ?? void 0;
20263
+ console.log(`[webchat:inbound] op=slice-readback key=${key} writes=${writes.length} injected=${previousContext ? "yes" : "no"}`);
20264
+ } catch (err) {
20265
+ console.error(`[webchat:inbound] op=slice-readback-failed key=${key} err=${err instanceof Error ? err.message : String(err)}`);
20266
+ } finally {
20267
+ await session.close();
20268
+ }
20269
+ }
20129
20270
  const result2 = await managerSpawn(
20130
- buildPublicWebchatSpawnRequest({ accountId, key, gatewayUrl, serverPath, public: pub })
20271
+ buildPublicWebchatSpawnRequest({ accountId, key, gatewayUrl, serverPath, previousContext, public: pub })
20131
20272
  );
20132
20273
  if ("error" in result2) {
20133
20274
  console.error(`[webchat:inbound] op=spawn-failed key=${key} role=public error=${result2.error} status=${result2.status}`);
@@ -20136,10 +20277,11 @@ var webchatGateway = new WebchatGateway({
20136
20277
  return { sessionId: result2.sessionId };
20137
20278
  }
20138
20279
  const result = await managerRcSpawn({
20139
- sessionId: sessionId ?? adminSessionIdFor(accountId, key),
20280
+ sessionId: sessionId ?? adminSessionIdFor(accountId, key, adminUserId),
20140
20281
  role: "admin",
20141
20282
  channel: "webchat",
20142
20283
  senderId: key,
20284
+ adminUserId,
20143
20285
  webchatChannel: { key, gatewayUrl, serverPath },
20144
20286
  logContext: `channel=webchat key=${key} role=${role}`
20145
20287
  });
@@ -20658,7 +20800,6 @@ ${clientErrorReporterScript}
20658
20800
  }
20659
20801
  return html;
20660
20802
  }
20661
- var brandedHtmlCache = /* @__PURE__ */ new Map();
20662
20803
  function loadBrandingCache(agentSlug) {
20663
20804
  const configDir2 = join28(homedir3(), BRAND.configDir);
20664
20805
  try {
@@ -20676,9 +20817,10 @@ function resolveDefaultSlug() {
20676
20817
  if (!account) return null;
20677
20818
  return resolveDefaultAgentSlug(account.accountDir);
20678
20819
  }
20679
- function wantsNextSurface(c) {
20680
- return c.req.query("surface") === "next";
20820
+ function escapeHtml(s) {
20821
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
20681
20822
  }
20823
+ var brandedHtmlCache = /* @__PURE__ */ new Map();
20682
20824
  function brandedPublicHtml(agentSlug) {
20683
20825
  const baseHtml = cachedHtml("public.html");
20684
20826
  if (!agentSlug) return baseHtml;
@@ -20706,9 +20848,6 @@ function brandedPublicHtml(agentSlug) {
20706
20848
  brandedHtmlCache.set(agentSlug, { html, mtime: brandHash });
20707
20849
  return html;
20708
20850
  }
20709
- function escapeHtml(s) {
20710
- return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
20711
- }
20712
20851
  function agentUnavailableHtml() {
20713
20852
  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>`;
20714
20853
  }
@@ -20729,7 +20868,6 @@ app52.get("/", (c) => {
20729
20868
  );
20730
20869
  }
20731
20870
  console.error(`[public-root] op=serve-default slug=${defaultSlug}`);
20732
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20733
20871
  return c.html(brandedPublicHtml(defaultSlug));
20734
20872
  }
20735
20873
  console.log(`[host-class] host=${host} class=admin served=index.html`);
@@ -20738,13 +20876,11 @@ app52.get("/", (c) => {
20738
20876
  app52.get("/public", (c) => {
20739
20877
  const host = (c.req.header("host") ?? "").split(":")[0];
20740
20878
  if (isPublicHost(host)) return c.text("Not found", 404);
20741
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20742
20879
  return c.html(cachedHtml("public.html"));
20743
20880
  });
20744
20881
  app52.get("/public-chat", (c) => {
20745
20882
  const host = (c.req.header("host") ?? "").split(":")[0];
20746
20883
  if (isPublicHost(host)) return c.text("Not found", 404);
20747
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20748
20884
  return c.html(cachedHtml("public.html"));
20749
20885
  });
20750
20886
  async function logViewerFetch(c, next) {
@@ -20798,7 +20934,7 @@ app52.post("/api/vnc/client-event", async (c) => {
20798
20934
  return c.json({ ok: true });
20799
20935
  });
20800
20936
  app52.get("/g/:slug", (c) => {
20801
- return c.html(brandedPublicHtml());
20937
+ return c.html(brandedPublicHtml(resolveDefaultSlug() ?? void 0));
20802
20938
  });
20803
20939
  for (const pwa of PWA_SURFACES) {
20804
20940
  app52.get(pwa.manifestPath, (c) => {
@@ -20854,7 +20990,6 @@ app52.get("/:slug", async (c, next) => {
20854
20990
  }
20855
20991
  const branding = loadBrandingCache(slug);
20856
20992
  console.error(`[public-catchall] served path=/${slug} slug=${slug} branding=${branding ? "hit" : "miss"}`);
20857
- if (wantsNextSurface(c)) return c.html(cachedHtml("public-next.html"));
20858
20993
  return c.html(brandedPublicHtml(slug));
20859
20994
  }
20860
20995
  await next();