@axiom-lattice/gateway 4.1.6 → 4.2.0

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 (1129) hide show
  1. package/dist/{a2a-standard-G3J5ZHQ7.mjs → a2a-standard-WC2BSOFV.mjs} +2 -2
  2. package/dist/a2a-standard-WC2BSOFV.mjs.map +1 -0
  3. package/dist/chunk-K32XEQLH.mjs +28 -0
  4. package/dist/chunk-K32XEQLH.mjs.map +1 -0
  5. package/dist/{chunk-K4XELOSO.mjs → chunk-QKPZWWHH.mjs} +3 -2
  6. package/dist/{chunk-K4XELOSO.mjs.map → chunk-QKPZWWHH.mjs.map} +1 -1
  7. package/dist/embed/agent-chat-loader.js +1 -0
  8. package/dist/embed/embed-page-1c-75E4QIWF.js +1 -0
  9. package/dist/embed/embed-page-AgentDetailSideApp-6CVXM3P3.js +1 -0
  10. package/dist/embed/embed-page-AgentDetailSideApp-DRGKJ6C5.css +1 -0
  11. package/dist/embed/embed-page-AgentGovernanceWorkbench-4B3NJPCY.js +5 -0
  12. package/dist/embed/embed-page-AgentGovernanceWorkbench-SDS3GBCC.css +1 -0
  13. package/dist/embed/embed-page-ReactChart-OG5Z43H7.js +1 -0
  14. package/dist/embed/embed-page-ReactChart-VBM467ER.css +1 -0
  15. package/dist/embed/embed-page-ReactInfographic-IABAC7DO.js +574 -0
  16. package/dist/embed/embed-page-SkillFlow-GS4OUCJJ.js +1 -0
  17. package/dist/embed/embed-page-SkillFlow-VDPP5DFL.css +1 -0
  18. package/dist/embed/embed-page-TasksSideApp-F4XUHPTG.css +1 -0
  19. package/dist/embed/embed-page-TasksSideApp-I6Z7BOT2.js +241 -0
  20. package/dist/embed/embed-page-TeamWorkspace-DXKGNQ3C.css +1 -0
  21. package/dist/embed/embed-page-TeamWorkspace-LSCUIJDA.js +748 -0
  22. package/dist/embed/embed-page-TopologyRuntimeView-2NQ3OOYI.css +1 -0
  23. package/dist/embed/embed-page-TopologyRuntimeView-RY7NOUB7.js +6 -0
  24. package/dist/embed/embed-page-WorkflowAutomationView-MAYS27YJ.css +1 -0
  25. package/dist/embed/embed-page-WorkflowAutomationView-RNKIKDUX.js +3 -0
  26. package/dist/embed/embed-page-abap-QKV7XZRP.js +1 -0
  27. package/dist/embed/embed-page-abnf-534KGIL5.js +1 -0
  28. package/dist/embed/embed-page-abnf-NNWX7KPS.js +1 -0
  29. package/dist/embed/embed-page-accesslog-K5DAETBI.js +1 -0
  30. package/dist/embed/embed-page-actionscript-MLTGVDIY.js +1 -0
  31. package/dist/embed/embed-page-actionscript-YXZSI3FP.js +1 -0
  32. package/dist/embed/embed-page-ada-SMIJQ6T7.js +1 -0
  33. package/dist/embed/embed-page-ada-Z5BYNU6B.js +1 -0
  34. package/dist/embed/embed-page-agda-WCRTGDJB.js +1 -0
  35. package/dist/embed/embed-page-al-2LSX2G2U.js +1 -0
  36. package/dist/embed/embed-page-all-RTJLYZHS.js +1 -0
  37. package/dist/embed/embed-page-angelscript-4S3XC2EJ.js +1 -0
  38. package/dist/embed/embed-page-antlr4-OLOPZLHD.js +1 -0
  39. package/dist/embed/embed-page-apache-RGO2UM6T.js +1 -0
  40. package/dist/embed/embed-page-apacheconf-EKQ6F4ZQ.js +1 -0
  41. package/dist/embed/embed-page-apex-ZJTOIW4M.js +1 -0
  42. package/dist/embed/embed-page-apl-W7YETB5L.js +1 -0
  43. package/dist/embed/embed-page-applescript-I4PV6U4X.js +1 -0
  44. package/dist/embed/embed-page-applescript-M2D2KKDY.js +1 -0
  45. package/dist/embed/embed-page-aql-V6TCDQAH.js +1 -0
  46. package/dist/embed/embed-page-arcade-TSPLEDM5.js +1 -0
  47. package/dist/embed/embed-page-architecture-U656AL7Q-55BYHO3H.js +1 -0
  48. package/dist/embed/embed-page-architectureDiagram-VXUJARFQ-GDHKRBZH.js +36 -0
  49. package/dist/embed/embed-page-arduino-7N264XVW.js +1 -0
  50. package/dist/embed/embed-page-arduino-XUEUIP7S.js +1 -0
  51. package/dist/embed/embed-page-arff-M7PKJV7Y.js +1 -0
  52. package/dist/embed/embed-page-armasm-OAQGLAMS.js +1 -0
  53. package/dist/embed/embed-page-armasm-PTMJUNBD.js +1 -0
  54. package/dist/embed/embed-page-arturo-VYVR5YRA.js +1 -0
  55. package/dist/embed/embed-page-asciidoc-6GDV5NP4.js +1 -0
  56. package/dist/embed/embed-page-asciidoc-PDLRDQNM.js +1 -0
  57. package/dist/embed/embed-page-asm6502-LVC7KLV5.js +1 -0
  58. package/dist/embed/embed-page-asmatmel-B4D7TBZY.js +1 -0
  59. package/dist/embed/embed-page-aspectj-QZFNA4MK.js +1 -0
  60. package/dist/embed/embed-page-aspnet-4JJQ3PPT.js +1 -0
  61. package/dist/embed/embed-page-autohotkey-4QUCSDML.js +1 -0
  62. package/dist/embed/embed-page-autohotkey-SVPZNOL7.js +1 -0
  63. package/dist/embed/embed-page-autoit-IXYC6T6A.js +1 -0
  64. package/dist/embed/embed-page-autoit-PFZZYGX5.js +1 -0
  65. package/dist/embed/embed-page-avisynth-MVQJIFSP.js +1 -0
  66. package/dist/embed/embed-page-avrasm-XYNKWFKC.js +1 -0
  67. package/dist/embed/embed-page-avro-idl-4AA2QRRU.js +1 -0
  68. package/dist/embed/embed-page-awk-JNS3RERS.js +1 -0
  69. package/dist/embed/embed-page-awk-RMGF56MA.js +1 -0
  70. package/dist/embed/embed-page-axapta-6U5QN2JT.js +1 -0
  71. package/dist/embed/embed-page-bash-UJJ4GKW6.js +1 -0
  72. package/dist/embed/embed-page-bash-VYDNQBY7.js +1 -0
  73. package/dist/embed/embed-page-basic-6KLN4O27.js +1 -0
  74. package/dist/embed/embed-page-basic-EJRJ7W4E.js +1 -0
  75. package/dist/embed/embed-page-batch-AJOBLMJ2.js +1 -0
  76. package/dist/embed/embed-page-bbcode-CIP6MR7G.js +1 -0
  77. package/dist/embed/embed-page-bbj-OPFURIS3.js +1 -0
  78. package/dist/embed/embed-page-bicep-7BI3OTK4.js +1 -0
  79. package/dist/embed/embed-page-birb-LWSJQUWN.js +1 -0
  80. package/dist/embed/embed-page-bison-HDVOA2OF.js +1 -0
  81. package/dist/embed/embed-page-blockDiagram-VD42YOAC-6GQBPG3N.js +122 -0
  82. package/dist/embed/embed-page-bnf-7O24GKM6.js +1 -0
  83. package/dist/embed/embed-page-bnf-TCLPD45L.js +1 -0
  84. package/dist/embed/embed-page-bqn-LADFOREK.js +1 -0
  85. package/dist/embed/embed-page-brainfuck-B2QDW5Y5.js +1 -0
  86. package/dist/embed/embed-page-brainfuck-HUZY5LJA.js +1 -0
  87. package/dist/embed/embed-page-brightscript-4E54PL3L.js +1 -0
  88. package/dist/embed/embed-page-bro-DEBMJONL.js +1 -0
  89. package/dist/embed/embed-page-bsl-5HTEKAYP.js +1 -0
  90. package/dist/embed/embed-page-c-LFRMHVS4.js +1 -0
  91. package/dist/embed/embed-page-c-X5PJHL4T.js +1 -0
  92. package/dist/embed/embed-page-c-like-UPVRYRH5.js +1 -0
  93. package/dist/embed/embed-page-c4Diagram-YG6GDRKO-UBUOGTT3.js +10 -0
  94. package/dist/embed/embed-page-cal-MS5NKCDW.js +1 -0
  95. package/dist/embed/embed-page-capnproto-VVJPMDQX.js +1 -0
  96. package/dist/embed/embed-page-ceylon-TOPAPEAZ.js +1 -0
  97. package/dist/embed/embed-page-cfscript-P3X63VSB.js +1 -0
  98. package/dist/embed/embed-page-chaiscript-QZLDHGV3.js +1 -0
  99. package/dist/embed/embed-page-chunk-2AUFZBHG.js +1 -0
  100. package/dist/embed/embed-page-chunk-2AX46B4A.js +1 -0
  101. package/dist/embed/embed-page-chunk-2BEHY2KL.js +1 -0
  102. package/dist/embed/embed-page-chunk-2CM5KQAO.js +1 -0
  103. package/dist/embed/embed-page-chunk-2DKYYWQC.js +1 -0
  104. package/dist/embed/embed-page-chunk-2GFIRW6Z.js +1 -0
  105. package/dist/embed/embed-page-chunk-2GGHQJ6Z.js +1 -0
  106. package/dist/embed/embed-page-chunk-2IURSVR2.js +7 -0
  107. package/dist/embed/embed-page-chunk-2NLG2PBF.js +1 -0
  108. package/dist/embed/embed-page-chunk-2REOJOLY.js +1 -0
  109. package/dist/embed/embed-page-chunk-2SKSDKSN.js +1 -0
  110. package/dist/embed/embed-page-chunk-2V6IHON2.js +1 -0
  111. package/dist/embed/embed-page-chunk-2VJ7T35I.js +1 -0
  112. package/dist/embed/embed-page-chunk-2WL6TSEG.js +1 -0
  113. package/dist/embed/embed-page-chunk-2XLPEIWW.js +1 -0
  114. package/dist/embed/embed-page-chunk-2YRVPZIU.js +1 -0
  115. package/dist/embed/embed-page-chunk-33GTW5LX.js +1 -0
  116. package/dist/embed/embed-page-chunk-33LYY5FY.js +1 -0
  117. package/dist/embed/embed-page-chunk-342GWWY6.js +1 -0
  118. package/dist/embed/embed-page-chunk-34RH2U7Z.js +1 -0
  119. package/dist/embed/embed-page-chunk-37BFU4NL.js +1 -0
  120. package/dist/embed/embed-page-chunk-3C32LJTO.js +1 -0
  121. package/dist/embed/embed-page-chunk-3D3RUB6Q.js +1 -0
  122. package/dist/embed/embed-page-chunk-3DDNDQND.js +1 -0
  123. package/dist/embed/embed-page-chunk-3FQ3EELN.js +1 -0
  124. package/dist/embed/embed-page-chunk-3GRDXHWH.js +1 -0
  125. package/dist/embed/embed-page-chunk-3GTSDITA.js +1 -0
  126. package/dist/embed/embed-page-chunk-3IP6ESHH.js +1 -0
  127. package/dist/embed/embed-page-chunk-3J7LPOGR.js +1 -0
  128. package/dist/embed/embed-page-chunk-3KBA5YLX.js +1 -0
  129. package/dist/embed/embed-page-chunk-3MESXVLG.js +1 -0
  130. package/dist/embed/embed-page-chunk-3QOIYWK3.js +1 -0
  131. package/dist/embed/embed-page-chunk-3WBHNFJP.js +1 -0
  132. package/dist/embed/embed-page-chunk-3YID7Y73.js +1 -0
  133. package/dist/embed/embed-page-chunk-43APLD2U.js +1 -0
  134. package/dist/embed/embed-page-chunk-447KJWVF.js +1 -0
  135. package/dist/embed/embed-page-chunk-47OYOFAD.js +1 -0
  136. package/dist/embed/embed-page-chunk-4APB7U5B.js +1 -0
  137. package/dist/embed/embed-page-chunk-4BIOW547.js +3 -0
  138. package/dist/embed/embed-page-chunk-4BKXE5ON.js +14 -0
  139. package/dist/embed/embed-page-chunk-4BRWUEYH.js +1 -0
  140. package/dist/embed/embed-page-chunk-4C2ZTZLC.js +1 -0
  141. package/dist/embed/embed-page-chunk-4DT3DP4G.js +3 -0
  142. package/dist/embed/embed-page-chunk-4FS42IYM.js +1 -0
  143. package/dist/embed/embed-page-chunk-4JZFQLML.js +1 -0
  144. package/dist/embed/embed-page-chunk-4LC4UT4R.js +1 -0
  145. package/dist/embed/embed-page-chunk-4MNX7JDW.js +2 -0
  146. package/dist/embed/embed-page-chunk-4NIWV5BC.js +1 -0
  147. package/dist/embed/embed-page-chunk-4O7YNJLI.js +1 -0
  148. package/dist/embed/embed-page-chunk-4OTU4CRR.js +1 -0
  149. package/dist/embed/embed-page-chunk-4PR66FMJ.js +1 -0
  150. package/dist/embed/embed-page-chunk-4R5F5OQK.js +1 -0
  151. package/dist/embed/embed-page-chunk-4SGVKO3D.js +1 -0
  152. package/dist/embed/embed-page-chunk-4TEJCUD5.js +1 -0
  153. package/dist/embed/embed-page-chunk-4WOTSHAW.js +1 -0
  154. package/dist/embed/embed-page-chunk-4X5XHAMX.js +5 -0
  155. package/dist/embed/embed-page-chunk-4XVBSVFM.js +1 -0
  156. package/dist/embed/embed-page-chunk-4ZIJQUGM.js +1 -0
  157. package/dist/embed/embed-page-chunk-53PYTL4U.js +1 -0
  158. package/dist/embed/embed-page-chunk-53QS4RRO.js +1 -0
  159. package/dist/embed/embed-page-chunk-54DGJLXZ.js +1 -0
  160. package/dist/embed/embed-page-chunk-57BJJSAV.js +1 -0
  161. package/dist/embed/embed-page-chunk-5DAOHO64.js +1 -0
  162. package/dist/embed/embed-page-chunk-5HA2MCVW.js +1 -0
  163. package/dist/embed/embed-page-chunk-5HNRARTT.js +1 -0
  164. package/dist/embed/embed-page-chunk-5IG7MZQF.js +1 -0
  165. package/dist/embed/embed-page-chunk-5JDQ456X.js +7 -0
  166. package/dist/embed/embed-page-chunk-5LKQWBUZ.js +339 -0
  167. package/dist/embed/embed-page-chunk-5LZHM64O.js +1 -0
  168. package/dist/embed/embed-page-chunk-5OTSEOBG.js +1 -0
  169. package/dist/embed/embed-page-chunk-5WMGNRUZ.js +79 -0
  170. package/dist/embed/embed-page-chunk-5YNTYDFR.js +1 -0
  171. package/dist/embed/embed-page-chunk-62XZFSLM.js +1 -0
  172. package/dist/embed/embed-page-chunk-6433URSF.js +1 -0
  173. package/dist/embed/embed-page-chunk-6633JIZI.js +1 -0
  174. package/dist/embed/embed-page-chunk-664ZGB66.js +1 -0
  175. package/dist/embed/embed-page-chunk-66JWK64A.js +1 -0
  176. package/dist/embed/embed-page-chunk-66PSFC5S.js +1 -0
  177. package/dist/embed/embed-page-chunk-67RFPBNS.js +1 -0
  178. package/dist/embed/embed-page-chunk-6A6HYD7S.js +1 -0
  179. package/dist/embed/embed-page-chunk-6AF3OC6E.js +1 -0
  180. package/dist/embed/embed-page-chunk-6BL2XYV2.js +1 -0
  181. package/dist/embed/embed-page-chunk-6BUDTOPG.js +54 -0
  182. package/dist/embed/embed-page-chunk-6D23MLVG.js +1 -0
  183. package/dist/embed/embed-page-chunk-6DD7CBYV.js +1 -0
  184. package/dist/embed/embed-page-chunk-6DYN2PCR.js +1 -0
  185. package/dist/embed/embed-page-chunk-6E33CLHM.js +1 -0
  186. package/dist/embed/embed-page-chunk-6FFWZNBJ.js +1 -0
  187. package/dist/embed/embed-page-chunk-6G24DMH3.js +1 -0
  188. package/dist/embed/embed-page-chunk-6JFHQ7NQ.js +1 -0
  189. package/dist/embed/embed-page-chunk-6NWENUQ7.js +1 -0
  190. package/dist/embed/embed-page-chunk-6OKUWTCF.js +1 -0
  191. package/dist/embed/embed-page-chunk-6QTEF2NW.js +1 -0
  192. package/dist/embed/embed-page-chunk-6SFPT5PF.js +1 -0
  193. package/dist/embed/embed-page-chunk-6VRE3UPC.js +1 -0
  194. package/dist/embed/embed-page-chunk-6XNKALVC.js +1 -0
  195. package/dist/embed/embed-page-chunk-6XZZ6A3N.js +1 -0
  196. package/dist/embed/embed-page-chunk-6Y3UYJ6Z.js +1 -0
  197. package/dist/embed/embed-page-chunk-6ZXRL3VU.js +1 -0
  198. package/dist/embed/embed-page-chunk-72JNWX43.js +1 -0
  199. package/dist/embed/embed-page-chunk-734LUAPQ.js +1 -0
  200. package/dist/embed/embed-page-chunk-74YMVV5T.js +1 -0
  201. package/dist/embed/embed-page-chunk-75BP54HX.js +1 -0
  202. package/dist/embed/embed-page-chunk-76S2KVCN.js +1 -0
  203. package/dist/embed/embed-page-chunk-77SKWVKH.js +1 -0
  204. package/dist/embed/embed-page-chunk-7AKQRM6L.js +1 -0
  205. package/dist/embed/embed-page-chunk-7ASML425.js +1 -0
  206. package/dist/embed/embed-page-chunk-7BEP247X.js +1 -0
  207. package/dist/embed/embed-page-chunk-7CFGO35V.js +153 -0
  208. package/dist/embed/embed-page-chunk-7CW4T6JX.js +1 -0
  209. package/dist/embed/embed-page-chunk-7GLQRV3J.js +1 -0
  210. package/dist/embed/embed-page-chunk-7I5CUKLE.js +1 -0
  211. package/dist/embed/embed-page-chunk-7IYYKQJE.js +1 -0
  212. package/dist/embed/embed-page-chunk-7JBDPIC6.js +1 -0
  213. package/dist/embed/embed-page-chunk-7KSOII2E.js +1 -0
  214. package/dist/embed/embed-page-chunk-7MYHMZR7.js +1 -0
  215. package/dist/embed/embed-page-chunk-7OYMAA4V.js +1 -0
  216. package/dist/embed/embed-page-chunk-7Q3EEWYO.js +1 -0
  217. package/dist/embed/embed-page-chunk-7RPAJAU7.js +1 -0
  218. package/dist/embed/embed-page-chunk-7TH7FFVA.js +1 -0
  219. package/dist/embed/embed-page-chunk-7TMVQS3E.js +1 -0
  220. package/dist/embed/embed-page-chunk-7TY2R7O2.js +1 -0
  221. package/dist/embed/embed-page-chunk-7XMMIQFH.js +1 -0
  222. package/dist/embed/embed-page-chunk-A2LQIHX4.js +261 -0
  223. package/dist/embed/embed-page-chunk-A2QFCP3F.js +1 -0
  224. package/dist/embed/embed-page-chunk-A2XJ36CA.js +1 -0
  225. package/dist/embed/embed-page-chunk-A3QFY3IA.js +1 -0
  226. package/dist/embed/embed-page-chunk-A5CPK26D.js +1 -0
  227. package/dist/embed/embed-page-chunk-AAU4RSSU.js +1 -0
  228. package/dist/embed/embed-page-chunk-AB3Q2HOO.js +1 -0
  229. package/dist/embed/embed-page-chunk-ABFWMLOR.js +1 -0
  230. package/dist/embed/embed-page-chunk-ABIN3BPL.js +1 -0
  231. package/dist/embed/embed-page-chunk-ACIRZYZQ.js +1 -0
  232. package/dist/embed/embed-page-chunk-AEGLPY52.js +1 -0
  233. package/dist/embed/embed-page-chunk-AJPIJ5Q6.js +1 -0
  234. package/dist/embed/embed-page-chunk-AKPA6XS3.js +2 -0
  235. package/dist/embed/embed-page-chunk-ANZXYPYQ.js +1 -0
  236. package/dist/embed/embed-page-chunk-AO6KUNOD.js +1 -0
  237. package/dist/embed/embed-page-chunk-APIN6IE2.js +1 -0
  238. package/dist/embed/embed-page-chunk-AQ7P7MPQ.js +1 -0
  239. package/dist/embed/embed-page-chunk-AQLFD3FB.js +1 -0
  240. package/dist/embed/embed-page-chunk-AQTLXHTW.js +1 -0
  241. package/dist/embed/embed-page-chunk-ARHDAWDT.js +1 -0
  242. package/dist/embed/embed-page-chunk-ARM7QQNJ.js +1 -0
  243. package/dist/embed/embed-page-chunk-ARRA262W.js +1 -0
  244. package/dist/embed/embed-page-chunk-AWTS5ZYY.js +1 -0
  245. package/dist/embed/embed-page-chunk-AYOVLRHX.js +2167 -0
  246. package/dist/embed/embed-page-chunk-B43OSKKN.js +1 -0
  247. package/dist/embed/embed-page-chunk-B537QK4H.js +1 -0
  248. package/dist/embed/embed-page-chunk-B6767LVL.js +1 -0
  249. package/dist/embed/embed-page-chunk-BBSIPZIJ.js +2 -0
  250. package/dist/embed/embed-page-chunk-BDE6VTZO.js +1 -0
  251. package/dist/embed/embed-page-chunk-BDR2AV4C.js +1 -0
  252. package/dist/embed/embed-page-chunk-BEZUVEQG.js +1 -0
  253. package/dist/embed/embed-page-chunk-BHFBNKCC.js +1 -0
  254. package/dist/embed/embed-page-chunk-BIXWOREM.js +1 -0
  255. package/dist/embed/embed-page-chunk-BO56ESC4.js +1 -0
  256. package/dist/embed/embed-page-chunk-BOBSU3BS.js +1 -0
  257. package/dist/embed/embed-page-chunk-BOEM7RR2.js +1 -0
  258. package/dist/embed/embed-page-chunk-BOGY5UJK.js +1 -0
  259. package/dist/embed/embed-page-chunk-BOQ4YJRC.js +1 -0
  260. package/dist/embed/embed-page-chunk-BR7RHIPR.js +1 -0
  261. package/dist/embed/embed-page-chunk-BRF3QA4U.js +1 -0
  262. package/dist/embed/embed-page-chunk-BSHGJSTY.js +1 -0
  263. package/dist/embed/embed-page-chunk-BTZ6QKA5.js +1 -0
  264. package/dist/embed/embed-page-chunk-BXUFKFRH.js +1 -0
  265. package/dist/embed/embed-page-chunk-BYGKM25Z.js +1 -0
  266. package/dist/embed/embed-page-chunk-BZI3YCE7.js +1 -0
  267. package/dist/embed/embed-page-chunk-CADGB443.js +1 -0
  268. package/dist/embed/embed-page-chunk-CCNLQNKX.js +1 -0
  269. package/dist/embed/embed-page-chunk-CDFDSWNI.js +1 -0
  270. package/dist/embed/embed-page-chunk-CGMYXHWK.js +1 -0
  271. package/dist/embed/embed-page-chunk-CIVBRTV6.js +1 -0
  272. package/dist/embed/embed-page-chunk-CN3CMET4.js +1 -0
  273. package/dist/embed/embed-page-chunk-CT5EIC3O.js +1 -0
  274. package/dist/embed/embed-page-chunk-CTA4NVOR.js +1 -0
  275. package/dist/embed/embed-page-chunk-CTC4RKCL.js +1 -0
  276. package/dist/embed/embed-page-chunk-CUEEKFI2.js +1 -0
  277. package/dist/embed/embed-page-chunk-CUHPLIQJ.js +1 -0
  278. package/dist/embed/embed-page-chunk-CV7IET55.js +1 -0
  279. package/dist/embed/embed-page-chunk-CYZTUSN2.js +1 -0
  280. package/dist/embed/embed-page-chunk-CZBGTBTK.js +1 -0
  281. package/dist/embed/embed-page-chunk-CZXPKAAI.js +1 -0
  282. package/dist/embed/embed-page-chunk-D2R2NSRR.js +1 -0
  283. package/dist/embed/embed-page-chunk-D5AJQJD5.js +2 -0
  284. package/dist/embed/embed-page-chunk-D63UWHSO.js +1 -0
  285. package/dist/embed/embed-page-chunk-D6DA3A6A.js +1 -0
  286. package/dist/embed/embed-page-chunk-D73UXOFT.js +1 -0
  287. package/dist/embed/embed-page-chunk-DCS7FNFS.js +1 -0
  288. package/dist/embed/embed-page-chunk-DDTPPBJY.js +1 -0
  289. package/dist/embed/embed-page-chunk-DE7BGENS.js +1 -0
  290. package/dist/embed/embed-page-chunk-DEHJLLKN.js +1 -0
  291. package/dist/embed/embed-page-chunk-DHGHAGLL.js +1 -0
  292. package/dist/embed/embed-page-chunk-DIE6AVGX.js +1 -0
  293. package/dist/embed/embed-page-chunk-DM5ESF6C.js +1 -0
  294. package/dist/embed/embed-page-chunk-DQ4UEELI.js +1 -0
  295. package/dist/embed/embed-page-chunk-DVHOG6AY.js +31 -0
  296. package/dist/embed/embed-page-chunk-DWJV4T7Q.js +1 -0
  297. package/dist/embed/embed-page-chunk-DXVMFTPC.js +1 -0
  298. package/dist/embed/embed-page-chunk-DYBQVRXS.js +1 -0
  299. package/dist/embed/embed-page-chunk-DYPHXOEP.js +1 -0
  300. package/dist/embed/embed-page-chunk-DZRJEWQO.js +1 -0
  301. package/dist/embed/embed-page-chunk-E4OFRMJJ.js +1 -0
  302. package/dist/embed/embed-page-chunk-E7ECPW5G.js +1 -0
  303. package/dist/embed/embed-page-chunk-E7MYEYS3.js +1 -0
  304. package/dist/embed/embed-page-chunk-EAFE4NIS.js +1 -0
  305. package/dist/embed/embed-page-chunk-EAUQPBSN.js +1 -0
  306. package/dist/embed/embed-page-chunk-EBXTVXZF.js +1 -0
  307. package/dist/embed/embed-page-chunk-EG5CLCWE.js +1 -0
  308. package/dist/embed/embed-page-chunk-EGTJFOFF.js +1 -0
  309. package/dist/embed/embed-page-chunk-EKYNYNIX.js +1 -0
  310. package/dist/embed/embed-page-chunk-EPEKIAZP.js +37 -0
  311. package/dist/embed/embed-page-chunk-ER4O2WLO.js +1 -0
  312. package/dist/embed/embed-page-chunk-ESAZNCCX.js +1 -0
  313. package/dist/embed/embed-page-chunk-ESCA5JCS.js +1 -0
  314. package/dist/embed/embed-page-chunk-ESJEHJ5L.js +140 -0
  315. package/dist/embed/embed-page-chunk-ESLOGPBN.js +60 -0
  316. package/dist/embed/embed-page-chunk-ETP6AXEM.js +1 -0
  317. package/dist/embed/embed-page-chunk-ETY7U4DI.js +1 -0
  318. package/dist/embed/embed-page-chunk-EUOOO2LS.js +1 -0
  319. package/dist/embed/embed-page-chunk-EWKLGZMO.js +1 -0
  320. package/dist/embed/embed-page-chunk-EY64QEHF.js +1 -0
  321. package/dist/embed/embed-page-chunk-EY7WOIDX.js +1 -0
  322. package/dist/embed/embed-page-chunk-EYRF75EG.js +1 -0
  323. package/dist/embed/embed-page-chunk-EYZS7M3F.js +1 -0
  324. package/dist/embed/embed-page-chunk-F45LQ3RS.js +1 -0
  325. package/dist/embed/embed-page-chunk-F7IBVBXT.js +1 -0
  326. package/dist/embed/embed-page-chunk-FBXKGHOH.js +1 -0
  327. package/dist/embed/embed-page-chunk-FEEJAFK4.js +1 -0
  328. package/dist/embed/embed-page-chunk-FEOK4OPE.js +1 -0
  329. package/dist/embed/embed-page-chunk-FJ3EESJB.js +1 -0
  330. package/dist/embed/embed-page-chunk-FM5K6PQS.js +1 -0
  331. package/dist/embed/embed-page-chunk-FMMAQPSK.js +1 -0
  332. package/dist/embed/embed-page-chunk-FSDLV5QO.js +1 -0
  333. package/dist/embed/embed-page-chunk-FTXNVWT5.js +1 -0
  334. package/dist/embed/embed-page-chunk-FUIKRW55.js +1 -0
  335. package/dist/embed/embed-page-chunk-FVK265KY.js +1 -0
  336. package/dist/embed/embed-page-chunk-FWTICTEC.js +1 -0
  337. package/dist/embed/embed-page-chunk-FWXSX2W4.js +1 -0
  338. package/dist/embed/embed-page-chunk-FYBEULVS.js +1 -0
  339. package/dist/embed/embed-page-chunk-G5HXFDFC.js +1 -0
  340. package/dist/embed/embed-page-chunk-G5KW2SOV.js +1 -0
  341. package/dist/embed/embed-page-chunk-GAF3UVZE.js +1 -0
  342. package/dist/embed/embed-page-chunk-GFOWXZE5.js +1 -0
  343. package/dist/embed/embed-page-chunk-GH22I3LG.js +1 -0
  344. package/dist/embed/embed-page-chunk-GJCMO4YN.js +1 -0
  345. package/dist/embed/embed-page-chunk-GKA7H24K.js +1 -0
  346. package/dist/embed/embed-page-chunk-GL7A7IDD.js +1 -0
  347. package/dist/embed/embed-page-chunk-GNEIDEFX.js +1 -0
  348. package/dist/embed/embed-page-chunk-GPISFLXW.js +1 -0
  349. package/dist/embed/embed-page-chunk-GSWEZJ66.js +1 -0
  350. package/dist/embed/embed-page-chunk-GU7JLLYO.js +1 -0
  351. package/dist/embed/embed-page-chunk-GVZMVAXF.js +70 -0
  352. package/dist/embed/embed-page-chunk-GZBFDD4Y.js +1 -0
  353. package/dist/embed/embed-page-chunk-H3HFE6RK.js +1 -0
  354. package/dist/embed/embed-page-chunk-H3NYTZT4.js +3 -0
  355. package/dist/embed/embed-page-chunk-H7CZ6EXN.js +1 -0
  356. package/dist/embed/embed-page-chunk-H7HZ35QN.js +1 -0
  357. package/dist/embed/embed-page-chunk-H7XTOBKB.js +1 -0
  358. package/dist/embed/embed-page-chunk-HD5CA5Q2.js +1 -0
  359. package/dist/embed/embed-page-chunk-HDAHRUIT.js +1 -0
  360. package/dist/embed/embed-page-chunk-HGSQ4AUI.js +1 -0
  361. package/dist/embed/embed-page-chunk-HJJHFV6J.js +1 -0
  362. package/dist/embed/embed-page-chunk-HK4QMNL5.js +1 -0
  363. package/dist/embed/embed-page-chunk-HNWETJWB.js +1 -0
  364. package/dist/embed/embed-page-chunk-HQCMCYUS.js +1 -0
  365. package/dist/embed/embed-page-chunk-HQUXJKTG.js +1 -0
  366. package/dist/embed/embed-page-chunk-HTEALTO4.js +1 -0
  367. package/dist/embed/embed-page-chunk-HUKTQVZB.js +1 -0
  368. package/dist/embed/embed-page-chunk-HVN56UNP.js +1 -0
  369. package/dist/embed/embed-page-chunk-HVTV25TI.js +1 -0
  370. package/dist/embed/embed-page-chunk-HWNFA7PS.js +1 -0
  371. package/dist/embed/embed-page-chunk-I2JNPKJK.js +1 -0
  372. package/dist/embed/embed-page-chunk-I4BCBOUA.js +1 -0
  373. package/dist/embed/embed-page-chunk-I55FBKLU.js +3 -0
  374. package/dist/embed/embed-page-chunk-I5KTSZJX.js +1 -0
  375. package/dist/embed/embed-page-chunk-I7YQ2TGZ.js +1 -0
  376. package/dist/embed/embed-page-chunk-ICJOJGQ6.js +1 -0
  377. package/dist/embed/embed-page-chunk-IDJWNYLR.js +1 -0
  378. package/dist/embed/embed-page-chunk-IE6O7ZMQ.js +15 -0
  379. package/dist/embed/embed-page-chunk-IFCJLAOB.js +1 -0
  380. package/dist/embed/embed-page-chunk-IFEQPNI2.js +1 -0
  381. package/dist/embed/embed-page-chunk-IGBRMGDS.js +1 -0
  382. package/dist/embed/embed-page-chunk-IGIFLYCQ.js +1 -0
  383. package/dist/embed/embed-page-chunk-IGOT476M.js +1 -0
  384. package/dist/embed/embed-page-chunk-IHNNPY3P.js +1 -0
  385. package/dist/embed/embed-page-chunk-II6ODJLE.js +1 -0
  386. package/dist/embed/embed-page-chunk-IIIA5HUO.js +1 -0
  387. package/dist/embed/embed-page-chunk-IIYOOZDE.js +1 -0
  388. package/dist/embed/embed-page-chunk-IJPRKD63.js +1 -0
  389. package/dist/embed/embed-page-chunk-IK2TPQVX.js +1 -0
  390. package/dist/embed/embed-page-chunk-INGZ5SYE.js +1 -0
  391. package/dist/embed/embed-page-chunk-INUQ73SI.js +1 -0
  392. package/dist/embed/embed-page-chunk-IPI53MN3.js +1 -0
  393. package/dist/embed/embed-page-chunk-IPMWXKCK.js +1 -0
  394. package/dist/embed/embed-page-chunk-IRP2UOPH.js +1 -0
  395. package/dist/embed/embed-page-chunk-ISY7S7N6.js +1 -0
  396. package/dist/embed/embed-page-chunk-IT5VM3N7.js +1 -0
  397. package/dist/embed/embed-page-chunk-IX4WLWCY.js +28 -0
  398. package/dist/embed/embed-page-chunk-IYK5VAB3.js +1 -0
  399. package/dist/embed/embed-page-chunk-IZ6ZGFSG.js +1 -0
  400. package/dist/embed/embed-page-chunk-J4VBM2JB.js +1 -0
  401. package/dist/embed/embed-page-chunk-J7KNZGPV.js +1 -0
  402. package/dist/embed/embed-page-chunk-JADTV5YD.js +1 -0
  403. package/dist/embed/embed-page-chunk-JEW2Y2ED.js +1 -0
  404. package/dist/embed/embed-page-chunk-JFK56NZW.js +1 -0
  405. package/dist/embed/embed-page-chunk-JLWIJ4BP.js +1 -0
  406. package/dist/embed/embed-page-chunk-JNXBKMN6.js +1 -0
  407. package/dist/embed/embed-page-chunk-JOJ4VSO5.js +1 -0
  408. package/dist/embed/embed-page-chunk-JQQ6C3ST.js +1 -0
  409. package/dist/embed/embed-page-chunk-JUZFORQA.js +1 -0
  410. package/dist/embed/embed-page-chunk-JYEMOI5G.js +1 -0
  411. package/dist/embed/embed-page-chunk-JYQTTU7F.js +1 -0
  412. package/dist/embed/embed-page-chunk-K2NBNWDK.js +1 -0
  413. package/dist/embed/embed-page-chunk-K7I5Z2RN.js +1 -0
  414. package/dist/embed/embed-page-chunk-K7JAB46X.js +1 -0
  415. package/dist/embed/embed-page-chunk-KE32OJIP.js +1 -0
  416. package/dist/embed/embed-page-chunk-KEKB3BUG.js +1 -0
  417. package/dist/embed/embed-page-chunk-KG5A66WX.js +525 -0
  418. package/dist/embed/embed-page-chunk-KGP2RGEC.js +1 -0
  419. package/dist/embed/embed-page-chunk-KGX7G7XQ.js +1 -0
  420. package/dist/embed/embed-page-chunk-KM5NL7BL.js +1 -0
  421. package/dist/embed/embed-page-chunk-KQNRWZKR.js +1 -0
  422. package/dist/embed/embed-page-chunk-KUTM5AGJ.js +1 -0
  423. package/dist/embed/embed-page-chunk-KW44NUT4.js +1 -0
  424. package/dist/embed/embed-page-chunk-KWRAXHKX.js +1 -0
  425. package/dist/embed/embed-page-chunk-KZWWYO7Z.js +1 -0
  426. package/dist/embed/embed-page-chunk-L2QFIJ4P.js +1 -0
  427. package/dist/embed/embed-page-chunk-L3RQ76LD.js +1 -0
  428. package/dist/embed/embed-page-chunk-L6GX525D.js +1 -0
  429. package/dist/embed/embed-page-chunk-LDFGGZC6.js +1 -0
  430. package/dist/embed/embed-page-chunk-LEAHYMKH.js +1 -0
  431. package/dist/embed/embed-page-chunk-LH2NUQ2C.js +1 -0
  432. package/dist/embed/embed-page-chunk-LIJVWBYO.js +1 -0
  433. package/dist/embed/embed-page-chunk-LJBLK3MD.js +1 -0
  434. package/dist/embed/embed-page-chunk-LJJJJZT7.js +1 -0
  435. package/dist/embed/embed-page-chunk-LJZ2VDC6.js +1 -0
  436. package/dist/embed/embed-page-chunk-LKBECLX2.js +1 -0
  437. package/dist/embed/embed-page-chunk-LL4XKLOG.js +1 -0
  438. package/dist/embed/embed-page-chunk-LLFEIUVK.js +1 -0
  439. package/dist/embed/embed-page-chunk-LMLHHN2B.js +1 -0
  440. package/dist/embed/embed-page-chunk-LOLMAI3V.js +1 -0
  441. package/dist/embed/embed-page-chunk-LPXAKW7Q.js +1 -0
  442. package/dist/embed/embed-page-chunk-LRB5IXLV.js +1 -0
  443. package/dist/embed/embed-page-chunk-LW3LUJEG.js +1 -0
  444. package/dist/embed/embed-page-chunk-LWERP7BS.js +1 -0
  445. package/dist/embed/embed-page-chunk-M4ACA43K.js +1 -0
  446. package/dist/embed/embed-page-chunk-M5HO3OG6.js +1 -0
  447. package/dist/embed/embed-page-chunk-M7F46E23.js +1 -0
  448. package/dist/embed/embed-page-chunk-MASNBRHM.js +1 -0
  449. package/dist/embed/embed-page-chunk-MB65DZAX.js +14 -0
  450. package/dist/embed/embed-page-chunk-MB77ZI4D.js +1 -0
  451. package/dist/embed/embed-page-chunk-MEC3JUW7.js +1 -0
  452. package/dist/embed/embed-page-chunk-MG5LALIS.js +1 -0
  453. package/dist/embed/embed-page-chunk-MHSEFTKR.js +1 -0
  454. package/dist/embed/embed-page-chunk-MKV2QNSI.js +1 -0
  455. package/dist/embed/embed-page-chunk-MMHCEL7E.js +1 -0
  456. package/dist/embed/embed-page-chunk-MMXDBRLY.js +1 -0
  457. package/dist/embed/embed-page-chunk-MSYFW3OJ.js +1 -0
  458. package/dist/embed/embed-page-chunk-MVLHDASB.js +1 -0
  459. package/dist/embed/embed-page-chunk-N252QSMT.js +1 -0
  460. package/dist/embed/embed-page-chunk-N7NXBLSR.js +1 -0
  461. package/dist/embed/embed-page-chunk-NBNJGF7O.js +1 -0
  462. package/dist/embed/embed-page-chunk-NG7LKEPN.js +1 -0
  463. package/dist/embed/embed-page-chunk-NHOBB2JQ.js +1 -0
  464. package/dist/embed/embed-page-chunk-NIFSD4XH.js +1 -0
  465. package/dist/embed/embed-page-chunk-NJP7LGPJ.js +1 -0
  466. package/dist/embed/embed-page-chunk-NLMEH7HI.js +1 -0
  467. package/dist/embed/embed-page-chunk-NLZ6F3ON.js +1 -0
  468. package/dist/embed/embed-page-chunk-NMUKLFBY.js +1 -0
  469. package/dist/embed/embed-page-chunk-NMZP7U6I.js +1 -0
  470. package/dist/embed/embed-page-chunk-NN7VEJ2G.js +1 -0
  471. package/dist/embed/embed-page-chunk-NNNI4647.js +1 -0
  472. package/dist/embed/embed-page-chunk-NNZA747K.js +1 -0
  473. package/dist/embed/embed-page-chunk-NOMBKADH.js +1 -0
  474. package/dist/embed/embed-page-chunk-NQRVVPLU.js +1 -0
  475. package/dist/embed/embed-page-chunk-O2YMBFJK.js +1 -0
  476. package/dist/embed/embed-page-chunk-O6DJHMEC.js +1 -0
  477. package/dist/embed/embed-page-chunk-OAUK7LXS.js +1 -0
  478. package/dist/embed/embed-page-chunk-OCFVEAMV.js +1 -0
  479. package/dist/embed/embed-page-chunk-OEC4EWNI.js +1 -0
  480. package/dist/embed/embed-page-chunk-OF6SGGWX.js +1 -0
  481. package/dist/embed/embed-page-chunk-OJ7436DP.js +1 -0
  482. package/dist/embed/embed-page-chunk-OK6DC5YX.js +1 -0
  483. package/dist/embed/embed-page-chunk-ONZ74YHS.js +1 -0
  484. package/dist/embed/embed-page-chunk-OOZDPBUK.js +69 -0
  485. package/dist/embed/embed-page-chunk-OPME5GF2.js +1 -0
  486. package/dist/embed/embed-page-chunk-ORPDSJ5S.js +1 -0
  487. package/dist/embed/embed-page-chunk-ORPUVSKY.js +1 -0
  488. package/dist/embed/embed-page-chunk-OWGBADV6.js +3880 -0
  489. package/dist/embed/embed-page-chunk-OWTE7YMF.js +1 -0
  490. package/dist/embed/embed-page-chunk-OZKVHTL6.js +1 -0
  491. package/dist/embed/embed-page-chunk-OZUIA6GJ.js +1 -0
  492. package/dist/embed/embed-page-chunk-P4MXODKA.js +1 -0
  493. package/dist/embed/embed-page-chunk-P56KTNVT.js +1 -0
  494. package/dist/embed/embed-page-chunk-PADSMXWH.js +3 -0
  495. package/dist/embed/embed-page-chunk-PEFXE5Y4.js +1 -0
  496. package/dist/embed/embed-page-chunk-PHVA2KHO.js +1 -0
  497. package/dist/embed/embed-page-chunk-PJJPSDVD.js +1 -0
  498. package/dist/embed/embed-page-chunk-PKNTJERD.js +1 -0
  499. package/dist/embed/embed-page-chunk-PLAF2Q2L.js +1 -0
  500. package/dist/embed/embed-page-chunk-PLNJRORR.js +1 -0
  501. package/dist/embed/embed-page-chunk-PO2WVZC2.js +1 -0
  502. package/dist/embed/embed-page-chunk-PRYNHKKK.js +1 -0
  503. package/dist/embed/embed-page-chunk-PSTS2K7H.js +1 -0
  504. package/dist/embed/embed-page-chunk-PVL27S2O.js +1 -0
  505. package/dist/embed/embed-page-chunk-PVOA7ARZ.js +1 -0
  506. package/dist/embed/embed-page-chunk-PXADN2PY.js +1 -0
  507. package/dist/embed/embed-page-chunk-Q2HL7S3R.js +41 -0
  508. package/dist/embed/embed-page-chunk-Q2LWO44N.js +1 -0
  509. package/dist/embed/embed-page-chunk-Q2YEQQJF.js +1 -0
  510. package/dist/embed/embed-page-chunk-Q32Y7CP2.js +5 -0
  511. package/dist/embed/embed-page-chunk-Q3AOMIJ7.js +1 -0
  512. package/dist/embed/embed-page-chunk-Q4NFAO5G.js +1 -0
  513. package/dist/embed/embed-page-chunk-Q6ZPKMOZ.js +1 -0
  514. package/dist/embed/embed-page-chunk-QA2R2R55.js +165 -0
  515. package/dist/embed/embed-page-chunk-QANF3D34.js +1 -0
  516. package/dist/embed/embed-page-chunk-QBSFVKIB.js +1 -0
  517. package/dist/embed/embed-page-chunk-QCLLEPYT.js +1 -0
  518. package/dist/embed/embed-page-chunk-QDBK4ZDE.js +1 -0
  519. package/dist/embed/embed-page-chunk-QENDQ7H3.js +1 -0
  520. package/dist/embed/embed-page-chunk-QF7NBK3B.js +1 -0
  521. package/dist/embed/embed-page-chunk-QFTY233A.js +1 -0
  522. package/dist/embed/embed-page-chunk-QHV7PE5D.js +3 -0
  523. package/dist/embed/embed-page-chunk-QIJBDPZP.js +1 -0
  524. package/dist/embed/embed-page-chunk-QLA2XU73.js +1 -0
  525. package/dist/embed/embed-page-chunk-QNIB3Q7U.js +1 -0
  526. package/dist/embed/embed-page-chunk-QQLF4AV6.js +1 -0
  527. package/dist/embed/embed-page-chunk-QQUV5KZD.js +1 -0
  528. package/dist/embed/embed-page-chunk-QRKEL65F.js +1 -0
  529. package/dist/embed/embed-page-chunk-QRPDJVB7.js +1 -0
  530. package/dist/embed/embed-page-chunk-QVHTN5HT.js +1 -0
  531. package/dist/embed/embed-page-chunk-R2BGZIR7.js +1 -0
  532. package/dist/embed/embed-page-chunk-R2K4OIQO.js +1 -0
  533. package/dist/embed/embed-page-chunk-R4FTAO2H.js +1 -0
  534. package/dist/embed/embed-page-chunk-R54S6SKK.js +1 -0
  535. package/dist/embed/embed-page-chunk-R5I2GTYT.js +1 -0
  536. package/dist/embed/embed-page-chunk-R672RZXS.js +1 -0
  537. package/dist/embed/embed-page-chunk-RABAC5H3.js +1 -0
  538. package/dist/embed/embed-page-chunk-RG3BI65W.js +1 -0
  539. package/dist/embed/embed-page-chunk-RKPK7MLC.js +1 -0
  540. package/dist/embed/embed-page-chunk-RN7JLKLZ.js +1 -0
  541. package/dist/embed/embed-page-chunk-RNOETEGH.js +1 -0
  542. package/dist/embed/embed-page-chunk-RPK5SOLP.js +1 -0
  543. package/dist/embed/embed-page-chunk-RUOFG3OD.js +1 -0
  544. package/dist/embed/embed-page-chunk-RV2IAP52.js +1 -0
  545. package/dist/embed/embed-page-chunk-RXLB27EG.js +1 -0
  546. package/dist/embed/embed-page-chunk-S4XZPBRM.js +1 -0
  547. package/dist/embed/embed-page-chunk-SAML73QO.js +1 -0
  548. package/dist/embed/embed-page-chunk-SEH5ZYHX.js +1 -0
  549. package/dist/embed/embed-page-chunk-SL4X4KPS.js +1 -0
  550. package/dist/embed/embed-page-chunk-SMMEMIZS.js +1 -0
  551. package/dist/embed/embed-page-chunk-SMZUIXFD.js +1 -0
  552. package/dist/embed/embed-page-chunk-SQ4GANYE.js +1 -0
  553. package/dist/embed/embed-page-chunk-SRW4AAQ4.js +1 -0
  554. package/dist/embed/embed-page-chunk-SU5GXLKX.js +467 -0
  555. package/dist/embed/embed-page-chunk-SV2BM3WO.js +1 -0
  556. package/dist/embed/embed-page-chunk-SWGBMELE.js +1 -0
  557. package/dist/embed/embed-page-chunk-SYAPUMNM.js +1 -0
  558. package/dist/embed/embed-page-chunk-T4AZ556W.js +1 -0
  559. package/dist/embed/embed-page-chunk-T6QXBMXO.js +1 -0
  560. package/dist/embed/embed-page-chunk-TAOVZBLV.js +1 -0
  561. package/dist/embed/embed-page-chunk-TBRAGK3D.js +1 -0
  562. package/dist/embed/embed-page-chunk-TENLHB44.js +1 -0
  563. package/dist/embed/embed-page-chunk-TFSDCDJS.js +1 -0
  564. package/dist/embed/embed-page-chunk-TIGSOALR.js +1 -0
  565. package/dist/embed/embed-page-chunk-TKOSVUN2.js +1 -0
  566. package/dist/embed/embed-page-chunk-TLWGSINF.js +1 -0
  567. package/dist/embed/embed-page-chunk-TMUCZ7XO.js +1 -0
  568. package/dist/embed/embed-page-chunk-TP7772GL.js +1 -0
  569. package/dist/embed/embed-page-chunk-TPCI3CNJ.js +1 -0
  570. package/dist/embed/embed-page-chunk-TPGW6RUI.js +1 -0
  571. package/dist/embed/embed-page-chunk-TPQGFG2C.js +1 -0
  572. package/dist/embed/embed-page-chunk-TSZIWR3X.js +1 -0
  573. package/dist/embed/embed-page-chunk-TUFYJMMA.js +1 -0
  574. package/dist/embed/embed-page-chunk-TWDJUUXZ.js +1 -0
  575. package/dist/embed/embed-page-chunk-TWNAGURL.js +4 -0
  576. package/dist/embed/embed-page-chunk-TWU6UJLL.js +1 -0
  577. package/dist/embed/embed-page-chunk-TYA3PYZB.js +1 -0
  578. package/dist/embed/embed-page-chunk-U32PAI3Y.js +1 -0
  579. package/dist/embed/embed-page-chunk-U3B5KKSV.js +1 -0
  580. package/dist/embed/embed-page-chunk-U3YIXQYB.js +1 -0
  581. package/dist/embed/embed-page-chunk-U7OC25B3.js +1 -0
  582. package/dist/embed/embed-page-chunk-UBWHZLJN.js +1 -0
  583. package/dist/embed/embed-page-chunk-UCGT4CTV.js +1 -0
  584. package/dist/embed/embed-page-chunk-UCR4ZILJ.js +1 -0
  585. package/dist/embed/embed-page-chunk-UGBSF5HI.js +1 -0
  586. package/dist/embed/embed-page-chunk-UGCW7PZD.js +1 -0
  587. package/dist/embed/embed-page-chunk-UIZLGSJE.js +1 -0
  588. package/dist/embed/embed-page-chunk-UJODN4PG.js +1 -0
  589. package/dist/embed/embed-page-chunk-UPUUWWBK.js +1 -0
  590. package/dist/embed/embed-page-chunk-UR5VOXA3.js +1 -0
  591. package/dist/embed/embed-page-chunk-UZNSI2X3.js +1 -0
  592. package/dist/embed/embed-page-chunk-UZW2LQZV.js +1 -0
  593. package/dist/embed/embed-page-chunk-V2V73RFB.js +1 -0
  594. package/dist/embed/embed-page-chunk-V7R2Y72J.js +14 -0
  595. package/dist/embed/embed-page-chunk-VEYJHY36.js +1 -0
  596. package/dist/embed/embed-page-chunk-VNK6MED4.js +1 -0
  597. package/dist/embed/embed-page-chunk-VP2J7NES.js +1 -0
  598. package/dist/embed/embed-page-chunk-VRDH6A7Z.js +1 -0
  599. package/dist/embed/embed-page-chunk-VTUD3VPX.js +1 -0
  600. package/dist/embed/embed-page-chunk-VULBATQG.js +1 -0
  601. package/dist/embed/embed-page-chunk-VUOXEXHU.js +1 -0
  602. package/dist/embed/embed-page-chunk-VVTZ23LK.js +1 -0
  603. package/dist/embed/embed-page-chunk-VW3NF5NT.js +1 -0
  604. package/dist/embed/embed-page-chunk-VY6MAPHR.js +1 -0
  605. package/dist/embed/embed-page-chunk-WAANDEAQ.js +1 -0
  606. package/dist/embed/embed-page-chunk-WCKHIRD5.js +1 -0
  607. package/dist/embed/embed-page-chunk-WDS66MAN.js +1 -0
  608. package/dist/embed/embed-page-chunk-WLZW4FEZ.js +1 -0
  609. package/dist/embed/embed-page-chunk-WNEY2A2R.js +1 -0
  610. package/dist/embed/embed-page-chunk-WQOZWRIS.js +1 -0
  611. package/dist/embed/embed-page-chunk-WUYZIBLV.js +1 -0
  612. package/dist/embed/embed-page-chunk-WYJNNBFP.js +1 -0
  613. package/dist/embed/embed-page-chunk-X55NDWBH.js +1 -0
  614. package/dist/embed/embed-page-chunk-XA4KNRQW.js +1 -0
  615. package/dist/embed/embed-page-chunk-XAJFFWM3.js +1 -0
  616. package/dist/embed/embed-page-chunk-XIJHCNBW.js +1 -0
  617. package/dist/embed/embed-page-chunk-XNZ46IEF.js +1 -0
  618. package/dist/embed/embed-page-chunk-XO5WZF3D.js +1 -0
  619. package/dist/embed/embed-page-chunk-XPDEOKHX.js +1 -0
  620. package/dist/embed/embed-page-chunk-XQNO7AN3.js +1 -0
  621. package/dist/embed/embed-page-chunk-XR3Q4GDZ.js +1 -0
  622. package/dist/embed/embed-page-chunk-XRRCORI5.js +1 -0
  623. package/dist/embed/embed-page-chunk-XTMDFHMJ.js +1 -0
  624. package/dist/embed/embed-page-chunk-XUZKZF3V.js +1 -0
  625. package/dist/embed/embed-page-chunk-XWAJRAFC.js +1 -0
  626. package/dist/embed/embed-page-chunk-XWRBMESB.js +1 -0
  627. package/dist/embed/embed-page-chunk-XXT7RMBT.js +220 -0
  628. package/dist/embed/embed-page-chunk-XY5NGMFT.js +1 -0
  629. package/dist/embed/embed-page-chunk-XYCU2ZON.js +1 -0
  630. package/dist/embed/embed-page-chunk-XZ6CLWS2.js +1 -0
  631. package/dist/embed/embed-page-chunk-XZYJX7MY.js +1 -0
  632. package/dist/embed/embed-page-chunk-Y2JWLZJF.js +1 -0
  633. package/dist/embed/embed-page-chunk-Y4KTS6EE.js +1 -0
  634. package/dist/embed/embed-page-chunk-YBPVSBMU.js +1 -0
  635. package/dist/embed/embed-page-chunk-YEHTVTMO.js +1 -0
  636. package/dist/embed/embed-page-chunk-YFEUMUCL.js +1 -0
  637. package/dist/embed/embed-page-chunk-YFWCKZW7.js +1 -0
  638. package/dist/embed/embed-page-chunk-YHEFVON2.js +1 -0
  639. package/dist/embed/embed-page-chunk-YJBX3AFL.js +1 -0
  640. package/dist/embed/embed-page-chunk-YJZJFCLP.js +1 -0
  641. package/dist/embed/embed-page-chunk-YLUGLAWD.js +1 -0
  642. package/dist/embed/embed-page-chunk-YMMUR7L6.js +1 -0
  643. package/dist/embed/embed-page-chunk-YNIEMXW5.js +1 -0
  644. package/dist/embed/embed-page-chunk-YPK6G5D7.js +1 -0
  645. package/dist/embed/embed-page-chunk-Z26BSJ5Y.js +1 -0
  646. package/dist/embed/embed-page-chunk-Z2GE34ES.js +1 -0
  647. package/dist/embed/embed-page-chunk-Z6N3GKM5.js +1 -0
  648. package/dist/embed/embed-page-chunk-Z6PDLQOB.js +1 -0
  649. package/dist/embed/embed-page-chunk-ZESVZCWO.js +1 -0
  650. package/dist/embed/embed-page-chunk-ZITVGQ52.js +1 -0
  651. package/dist/embed/embed-page-chunk-ZNWEXQQ4.js +1 -0
  652. package/dist/embed/embed-page-chunk-ZQ6WYVOD.js +1 -0
  653. package/dist/embed/embed-page-chunk-ZR7ZLGLV.js +1 -0
  654. package/dist/embed/embed-page-chunk-ZT2EZUXI.js +1 -0
  655. package/dist/embed/embed-page-chunk-ZZCMWB6F.js +1 -0
  656. package/dist/embed/embed-page-cil-ZQIVHSN6.js +1 -0
  657. package/dist/embed/embed-page-cilkc-AJET62TW.js +1 -0
  658. package/dist/embed/embed-page-cilkcpp-FRBVBYEF.js +1 -0
  659. package/dist/embed/embed-page-classDiagram-2ON5EDUG-S5GEC2UC.js +1 -0
  660. package/dist/embed/embed-page-classDiagram-v2-WZHVMYZB-NL3HKXC3.js +1 -0
  661. package/dist/embed/embed-page-clean-OPHY52MY.js +1 -0
  662. package/dist/embed/embed-page-clike-5NRFTOCK.js +1 -0
  663. package/dist/embed/embed-page-clojure-4GC77VYK.js +1 -0
  664. package/dist/embed/embed-page-clojure-7B3FI7TH.js +1 -0
  665. package/dist/embed/embed-page-clojure-repl-56WG27Z3.js +1 -0
  666. package/dist/embed/embed-page-cmake-F3SKZMUJ.js +1 -0
  667. package/dist/embed/embed-page-cmake-UIBPQIVG.js +1 -0
  668. package/dist/embed/embed-page-cobol-7TW6OZHG.js +1 -0
  669. package/dist/embed/embed-page-code-highlighter-TBT4ICNZ.js +1 -0
  670. package/dist/embed/embed-page-coffeescript-BCKZ4N2E.js +1 -0
  671. package/dist/embed/embed-page-coffeescript-N2ENFNNR.js +1 -0
  672. package/dist/embed/embed-page-concurnas-MCN7VYPE.js +1 -0
  673. package/dist/embed/embed-page-cooklang-JSLOQBDM.js +1 -0
  674. package/dist/embed/embed-page-coq-WH3J7SKF.js +1 -0
  675. package/dist/embed/embed-page-coq-XRXAXI5X.js +1 -0
  676. package/dist/embed/embed-page-core-Q6IGWM4Q.js +1 -0
  677. package/dist/embed/embed-page-core-TQNBW2MM.js +1 -0
  678. package/dist/embed/embed-page-cos-MP7YM5FO.js +1 -0
  679. package/dist/embed/embed-page-cose-bilkent-S5V4N54A-KJMAAFJL.js +1 -0
  680. package/dist/embed/embed-page-cpp-FFAXKUCJ.js +1 -0
  681. package/dist/embed/embed-page-cpp-PRCT5QAC.js +1 -0
  682. package/dist/embed/embed-page-crmsh-PF5MF5PC.js +1 -0
  683. package/dist/embed/embed-page-crystal-GYFU35L2.js +1 -0
  684. package/dist/embed/embed-page-crystal-W2TOACW4.js +1 -0
  685. package/dist/embed/embed-page-csharp-DHR2XRZW.js +1 -0
  686. package/dist/embed/embed-page-csharp-UNF62ZBO.js +1 -0
  687. package/dist/embed/embed-page-cshtml-G7ML4LE3.js +1 -0
  688. package/dist/embed/embed-page-csp-UDQUZUZW.js +1 -0
  689. package/dist/embed/embed-page-csp-YPF3N7BE.js +1 -0
  690. package/dist/embed/embed-page-css-774MOM42.js +1 -0
  691. package/dist/embed/embed-page-css-EHGZALYG.js +1 -0
  692. package/dist/embed/embed-page-css-extras-SI7Q5IJ6.js +1 -0
  693. package/dist/embed/embed-page-csv-MT4GPPO7.js +1 -0
  694. package/dist/embed/embed-page-cue-BMTFVAKL.js +1 -0
  695. package/dist/embed/embed-page-cypher-QDHM3LFO.js +1 -0
  696. package/dist/embed/embed-page-d-KHBJT5ZU.js +1 -0
  697. package/dist/embed/embed-page-d-VF7XFFMN.js +1 -0
  698. package/dist/embed/embed-page-dagre-6UL2VRFP-QSIK5LGS.js +4 -0
  699. package/dist/embed/embed-page-dart-3L3U2DJ3.js +1 -0
  700. package/dist/embed/embed-page-dart-6AOCMAXR.js +1 -0
  701. package/dist/embed/embed-page-dataweave-LNNDNKWG.js +1 -0
  702. package/dist/embed/embed-page-dax-J2FYUNXR.js +1 -0
  703. package/dist/embed/embed-page-delphi-T3RKZ33G.js +1 -0
  704. package/dist/embed/embed-page-dhall-MGZ2X6D6.js +1 -0
  705. package/dist/embed/embed-page-diagram-PSM6KHXK-PLOM5KG7.js +24 -0
  706. package/dist/embed/embed-page-diagram-QEK2KX5R-RUNGK25X.js +43 -0
  707. package/dist/embed/embed-page-diagram-S2PKOQOG-LWDHM5TL.js +24 -0
  708. package/dist/embed/embed-page-diff-AZNWSOQ3.js +1 -0
  709. package/dist/embed/embed-page-diff-BYMKQAM5.js +1 -0
  710. package/dist/embed/embed-page-django-5BVMXLOO.js +1 -0
  711. package/dist/embed/embed-page-django-OLTKKRJC.js +1 -0
  712. package/dist/embed/embed-page-dns-LKEA7NVQ.js +1 -0
  713. package/dist/embed/embed-page-dns-zone-file-MLDJYBWW.js +1 -0
  714. package/dist/embed/embed-page-docker-7ZWVGIHF.js +1 -0
  715. package/dist/embed/embed-page-dockerfile-YJABIQ3Q.js +1 -0
  716. package/dist/embed/embed-page-dos-CZOUXBDN.js +1 -0
  717. package/dist/embed/embed-page-dot-USOBKZIN.js +1 -0
  718. package/dist/embed/embed-page-dsconfig-5E37MQM4.js +1 -0
  719. package/dist/embed/embed-page-dts-DPBFPVA5.js +1 -0
  720. package/dist/embed/embed-page-dust-OAZ4NEIP.js +1 -0
  721. package/dist/embed/embed-page-ebnf-XFC6NV6I.js +1 -0
  722. package/dist/embed/embed-page-ebnf-XSYP4JUB.js +1 -0
  723. package/dist/embed/embed-page-echarts-7KZDMH4F.js +1 -0
  724. package/dist/embed/embed-page-editorconfig-FQHUYGTR.js +1 -0
  725. package/dist/embed/embed-page-eiffel-Z22STSPG.js +1 -0
  726. package/dist/embed/embed-page-ejs-VHHMOK6Y.js +1 -0
  727. package/dist/embed/embed-page-elixir-BGO72I74.js +1 -0
  728. package/dist/embed/embed-page-elixir-H3KPRECP.js +1 -0
  729. package/dist/embed/embed-page-elm-HZWFYFUN.js +1 -0
  730. package/dist/embed/embed-page-elm-IZAWNYFC.js +1 -0
  731. package/dist/embed/embed-page-erDiagram-Q2GNP2WA-C6CZYEPF.js +60 -0
  732. package/dist/embed/embed-page-erb-AK646PXX.js +1 -0
  733. package/dist/embed/embed-page-erb-YBV2NO4W.js +1 -0
  734. package/dist/embed/embed-page-erlang-6LMYF4BN.js +1 -0
  735. package/dist/embed/embed-page-erlang-PXGHX7XB.js +1 -0
  736. package/dist/embed/embed-page-erlang-repl-UJPNMOCE.js +1 -0
  737. package/dist/embed/embed-page-etlua-XNKJ7UTQ.js +1 -0
  738. package/dist/embed/embed-page-excel-PCWQ5ZDK.js +1 -0
  739. package/dist/embed/embed-page-excel-formula-CEZ7KVDN.js +1 -0
  740. package/dist/embed/embed-page-factor-3PZO4CCJ.js +1 -0
  741. package/dist/embed/embed-page-false-OX3DNOF4.js +1 -0
  742. package/dist/embed/embed-page-firestore-security-rules-IQBOB7PZ.js +1 -0
  743. package/dist/embed/embed-page-fix-Q3F7Z2HQ.js +1 -0
  744. package/dist/embed/embed-page-flix-LVDGNPRS.js +1 -0
  745. package/dist/embed/embed-page-flow-4UPRJEF2.js +1 -0
  746. package/dist/embed/embed-page-flowDiagram-NV44I4VS-DLT3KEOP.js +162 -0
  747. package/dist/embed/embed-page-fortran-65P3TPQ7.js +1 -0
  748. package/dist/embed/embed-page-fortran-LWYFHCCB.js +1 -0
  749. package/dist/embed/embed-page-fsharp-BSA736XP.js +1 -0
  750. package/dist/embed/embed-page-fsharp-GDIVPYAB.js +1 -0
  751. package/dist/embed/embed-page-ftl-27Y3T2XT.js +1 -0
  752. package/dist/embed/embed-page-gams-7UM23CTD.js +1 -0
  753. package/dist/embed/embed-page-ganttDiagram-JELNMOA3-YXTLQI5X.js +267 -0
  754. package/dist/embed/embed-page-gap-JNDMTZYG.js +1 -0
  755. package/dist/embed/embed-page-gauss-4OCQQOQQ.js +1 -0
  756. package/dist/embed/embed-page-gcode-7ZDB2FDS.js +1 -0
  757. package/dist/embed/embed-page-gcode-U2UWK2IF.js +1 -0
  758. package/dist/embed/embed-page-gdscript-UOAGAMMO.js +1 -0
  759. package/dist/embed/embed-page-gedcom-WSTJUY6R.js +1 -0
  760. package/dist/embed/embed-page-gettext-BNGNGT6W.js +1 -0
  761. package/dist/embed/embed-page-gherkin-CPRNYA24.js +1 -0
  762. package/dist/embed/embed-page-gherkin-IVS5YUAH.js +1 -0
  763. package/dist/embed/embed-page-git-WWKMYMUR.js +1 -0
  764. package/dist/embed/embed-page-gitGraph-F6HP7TQM-AT36TKLZ.js +1 -0
  765. package/dist/embed/embed-page-gitGraphDiagram-NY62KEGX-U36ULO4Y.js +65 -0
  766. package/dist/embed/embed-page-glsl-2QJTMF6X.js +1 -0
  767. package/dist/embed/embed-page-glsl-6C6F26XK.js +1 -0
  768. package/dist/embed/embed-page-gml-67HHHYLB.js +1 -0
  769. package/dist/embed/embed-page-gml-ZFY32X23.js +1 -0
  770. package/dist/embed/embed-page-gn-KO2XPJDA.js +1 -0
  771. package/dist/embed/embed-page-go-HAQ77N2R.js +1 -0
  772. package/dist/embed/embed-page-go-SYFPAV4X.js +1 -0
  773. package/dist/embed/embed-page-go-module-XICPRQ5N.js +1 -0
  774. package/dist/embed/embed-page-golo-KQZ2PQG7.js +1 -0
  775. package/dist/embed/embed-page-gradle-7PN7DUJT.js +1 -0
  776. package/dist/embed/embed-page-gradle-GN34ZONG.js +1 -0
  777. package/dist/embed/embed-page-graphql-CVSK5MA2.js +1 -0
  778. package/dist/embed/embed-page-groovy-3R2X7GQD.js +1 -0
  779. package/dist/embed/embed-page-groovy-YCAJV7XB.js +1 -0
  780. package/dist/embed/embed-page-haml-6VEPXH2O.js +1 -0
  781. package/dist/embed/embed-page-haml-TYLXIXHD.js +1 -0
  782. package/dist/embed/embed-page-handlebars-7Y74ECRG.js +1 -0
  783. package/dist/embed/embed-page-handlebars-WVRARLIY.js +1 -0
  784. package/dist/embed/embed-page-haskell-7U743UEW.js +1 -0
  785. package/dist/embed/embed-page-haskell-BATAJHBH.js +1 -0
  786. package/dist/embed/embed-page-haxe-C234CZTQ.js +1 -0
  787. package/dist/embed/embed-page-haxe-PYBC3T4M.js +1 -0
  788. package/dist/embed/embed-page-hcl-BITT4ESF.js +1 -0
  789. package/dist/embed/embed-page-hlsl-KYOSJMB5.js +1 -0
  790. package/dist/embed/embed-page-hoon-NTFQ2YYJ.js +1 -0
  791. package/dist/embed/embed-page-hpkp-KN6XKLGI.js +1 -0
  792. package/dist/embed/embed-page-hsp-QFZDPSDA.js +1 -0
  793. package/dist/embed/embed-page-hsts-5COZ5S32.js +1 -0
  794. package/dist/embed/embed-page-html2canvas-HMTC4TFR.js +1 -0
  795. package/dist/embed/embed-page-htmlbars-L7NSSG62.js +1 -0
  796. package/dist/embed/embed-page-http-ALSJXSOJ.js +1 -0
  797. package/dist/embed/embed-page-http-E4UEITFW.js +1 -0
  798. package/dist/embed/embed-page-hy-5ROLZHNZ.js +1 -0
  799. package/dist/embed/embed-page-ichigojam-T6UG6OA7.js +1 -0
  800. package/dist/embed/embed-page-icon-74CJY73I.js +1 -0
  801. package/dist/embed/embed-page-icu-message-format-2RX6DV2B.js +1 -0
  802. package/dist/embed/embed-page-idris-OH6VYNRJ.js +1 -0
  803. package/dist/embed/embed-page-iecst-SJFFJ4PC.js +1 -0
  804. package/dist/embed/embed-page-ignore-QLXHF7QX.js +1 -0
  805. package/dist/embed/embed-page-index.es-N6YIYNKZ.js +23 -0
  806. package/dist/embed/embed-page-info-NVLQJR56-2XLQRFF4.js +1 -0
  807. package/dist/embed/embed-page-infoDiagram-WHAUD3N6-2U2VIHJP.js +2 -0
  808. package/dist/embed/embed-page-inform7-6Y7MAAME.js +1 -0
  809. package/dist/embed/embed-page-inform7-HZB3RNF4.js +1 -0
  810. package/dist/embed/embed-page-ini-7C2L4IDF.js +1 -0
  811. package/dist/embed/embed-page-ini-TMKFFGPD.js +1 -0
  812. package/dist/embed/embed-page-io-X5SCSO5G.js +1 -0
  813. package/dist/embed/embed-page-irpf90-A5FIGB26.js +1 -0
  814. package/dist/embed/embed-page-isbl-Q77V4FXF.js +1 -0
  815. package/dist/embed/embed-page-j-MA6BTTGA.js +1 -0
  816. package/dist/embed/embed-page-java-CYPVO64F.js +1 -0
  817. package/dist/embed/embed-page-java-O37XO6YL.js +1 -0
  818. package/dist/embed/embed-page-javadoc-LWLUAHHX.js +1 -0
  819. package/dist/embed/embed-page-javadoclike-BMEJGG2H.js +1 -0
  820. package/dist/embed/embed-page-javascript-GU26522Z.js +1 -0
  821. package/dist/embed/embed-page-javascript-M37PIZZC.js +1 -0
  822. package/dist/embed/embed-page-javastacktrace-ENINDMIF.js +1 -0
  823. package/dist/embed/embed-page-jboss-cli-Q2WN2KZS.js +1 -0
  824. package/dist/embed/embed-page-jexl-EU2C4LRG.js +1 -0
  825. package/dist/embed/embed-page-jolie-WJIQVPRR.js +1 -0
  826. package/dist/embed/embed-page-journeyDiagram-XKPGCS4Q-D4A2GN62.js +139 -0
  827. package/dist/embed/embed-page-jq-BRF5PIAN.js +1 -0
  828. package/dist/embed/embed-page-js-extras-WQMVOPIZ.js +1 -0
  829. package/dist/embed/embed-page-js-templates-YO6IJU6R.js +1 -0
  830. package/dist/embed/embed-page-jsdoc-ZKI7O6VF.js +1 -0
  831. package/dist/embed/embed-page-json-MRFYB7NT.js +1 -0
  832. package/dist/embed/embed-page-json-PSHSOWQY.js +1 -0
  833. package/dist/embed/embed-page-json5-VQKDKRNE.js +1 -0
  834. package/dist/embed/embed-page-jsonp-ANEJBBKD.js +1 -0
  835. package/dist/embed/embed-page-jsstacktrace-XYAXX4Z3.js +1 -0
  836. package/dist/embed/embed-page-jsx-FZEE3QI5.js +1 -0
  837. package/dist/embed/embed-page-julia-5W6JANPT.js +1 -0
  838. package/dist/embed/embed-page-julia-EY2DW2U2.js +1 -0
  839. package/dist/embed/embed-page-julia-repl-O5XO6CSL.js +1 -0
  840. package/dist/embed/embed-page-kanban-definition-3W4ZIXB7-5JTDNV4G.js +89 -0
  841. package/dist/embed/embed-page-katex-BO63LHUI.js +261 -0
  842. package/dist/embed/embed-page-keepalived-OPG3P3WJ.js +1 -0
  843. package/dist/embed/embed-page-keyman-CXJENJBT.js +1 -0
  844. package/dist/embed/embed-page-kotlin-62Q32YH3.js +1 -0
  845. package/dist/embed/embed-page-kotlin-V4IBLBDP.js +1 -0
  846. package/dist/embed/embed-page-kumir-TIJGTYC3.js +1 -0
  847. package/dist/embed/embed-page-kusto-BXI53DND.js +1 -0
  848. package/dist/embed/embed-page-lasso-2CPND7XH.js +1 -0
  849. package/dist/embed/embed-page-latex-F3X5K6QF.js +1 -0
  850. package/dist/embed/embed-page-latex-MVG52AHA.js +1 -0
  851. package/dist/embed/embed-page-latte-J3LVOB6S.js +1 -0
  852. package/dist/embed/embed-page-ldif-5OWTENAQ.js +1 -0
  853. package/dist/embed/embed-page-leaf-EYR425IG.js +1 -0
  854. package/dist/embed/embed-page-less-S6CBMQQZ.js +1 -0
  855. package/dist/embed/embed-page-less-WDPLNQ5B.js +1 -0
  856. package/dist/embed/embed-page-lilypond-IJV67NKP.js +1 -0
  857. package/dist/embed/embed-page-linker-script-MIX3HOEH.js +1 -0
  858. package/dist/embed/embed-page-liquid-CFWS6T2J.js +1 -0
  859. package/dist/embed/embed-page-lisp-C6XPBZ5U.js +1 -0
  860. package/dist/embed/embed-page-lisp-IM4ILKS7.js +1 -0
  861. package/dist/embed/embed-page-livecodeserver-6F3SUK5W.js +1 -0
  862. package/dist/embed/embed-page-livescript-GNIYPIHH.js +1 -0
  863. package/dist/embed/embed-page-livescript-HOLSYBIG.js +1 -0
  864. package/dist/embed/embed-page-llvm-IWL5DLNH.js +1 -0
  865. package/dist/embed/embed-page-llvm-K2USHCCC.js +1 -0
  866. package/dist/embed/embed-page-log-BLJX5RSC.js +1 -0
  867. package/dist/embed/embed-page-lolcode-6COIIRQ6.js +1 -0
  868. package/dist/embed/embed-page-lsl-KDZSWM6S.js +1 -0
  869. package/dist/embed/embed-page-lua-5KEV5KHK.js +1 -0
  870. package/dist/embed/embed-page-lua-F7VBLUI5.js +1 -0
  871. package/dist/embed/embed-page-magma-TTQUX26J.js +1 -0
  872. package/dist/embed/embed-page-makefile-4VQZE7FW.js +1 -0
  873. package/dist/embed/embed-page-makefile-LDN5QGHW.js +1 -0
  874. package/dist/embed/embed-page-markdown-GU3NFA6A.js +1 -0
  875. package/dist/embed/embed-page-markdown-ODPEZXUU.js +1 -0
  876. package/dist/embed/embed-page-markup-W6JMQ64H.js +1 -0
  877. package/dist/embed/embed-page-markup-templating-RYGNVTG7.js +1 -0
  878. package/dist/embed/embed-page-mata-D4O4BNGS.js +1 -0
  879. package/dist/embed/embed-page-mathematica-YSU2VUX4.js +1 -0
  880. package/dist/embed/embed-page-matlab-6TYO6LKK.js +1 -0
  881. package/dist/embed/embed-page-matlab-DCIHZIZM.js +1 -0
  882. package/dist/embed/embed-page-maxima-K2VWPGLA.js +1 -0
  883. package/dist/embed/embed-page-maxscript-3ARRWLS6.js +1 -0
  884. package/dist/embed/embed-page-mel-E3F6H7ZF.js +1 -0
  885. package/dist/embed/embed-page-mel-YGI273IY.js +1 -0
  886. package/dist/embed/embed-page-mercury-LXCDDOJN.js +1 -0
  887. package/dist/embed/embed-page-mermaid-4FMYB3TJ.js +1 -0
  888. package/dist/embed/embed-page-mermaid-TBO3M7GX.js +18 -0
  889. package/dist/embed/embed-page-metafont-33QDNLJC.js +1 -0
  890. package/dist/embed/embed-page-mindmap-definition-VGOIOE7T-LVIRJQDW.js +68 -0
  891. package/dist/embed/embed-page-mipsasm-HSMSNEPP.js +1 -0
  892. package/dist/embed/embed-page-mizar-OTR4FHWG.js +1 -0
  893. package/dist/embed/embed-page-mizar-ZDNSLX4H.js +1 -0
  894. package/dist/embed/embed-page-mojolicious-2VJDUL4M.js +1 -0
  895. package/dist/embed/embed-page-mongodb-E62Y62DN.js +1 -0
  896. package/dist/embed/embed-page-monkey-KOVSP7SE.js +1 -0
  897. package/dist/embed/embed-page-monkey-MWSXB6DH.js +1 -0
  898. package/dist/embed/embed-page-moonscript-7DWCIDI5.js +1 -0
  899. package/dist/embed/embed-page-moonscript-AIMMMW7W.js +1 -0
  900. package/dist/embed/embed-page-n1ql-TKR2PAQ4.js +1 -0
  901. package/dist/embed/embed-page-n1ql-VSPMFQEE.js +1 -0
  902. package/dist/embed/embed-page-n4js-VQSAFSQG.js +1 -0
  903. package/dist/embed/embed-page-nand2tetris-hdl-ZN4LQDMB.js +1 -0
  904. package/dist/embed/embed-page-naniscript-FX42SAZY.js +1 -0
  905. package/dist/embed/embed-page-nasm-FGR3ELJL.js +1 -0
  906. package/dist/embed/embed-page-neon-4JXYQJP3.js +1 -0
  907. package/dist/embed/embed-page-nevod-2EHVRC32.js +1 -0
  908. package/dist/embed/embed-page-nginx-3W4BPZZB.js +1 -0
  909. package/dist/embed/embed-page-nginx-672JEBEN.js +1 -0
  910. package/dist/embed/embed-page-nim-CNSA5KTJ.js +1 -0
  911. package/dist/embed/embed-page-nim-CS7GVCRH.js +1 -0
  912. package/dist/embed/embed-page-nix-H37VR2HL.js +1 -0
  913. package/dist/embed/embed-page-nix-ODG6AI37.js +1 -0
  914. package/dist/embed/embed-page-node-repl-F5RCYIN3.js +1 -0
  915. package/dist/embed/embed-page-nsis-LEW5NHHS.js +1 -0
  916. package/dist/embed/embed-page-nsis-P73IQUMW.js +1 -0
  917. package/dist/embed/embed-page-objectivec-GOD2BEHI.js +1 -0
  918. package/dist/embed/embed-page-objectivec-UO34JBT5.js +1 -0
  919. package/dist/embed/embed-page-ocaml-ODOKMPKS.js +1 -0
  920. package/dist/embed/embed-page-ocaml-PW67TSNU.js +1 -0
  921. package/dist/embed/embed-page-odin-42BCJRMU.js +1 -0
  922. package/dist/embed/embed-page-opencl-FWU2AVTW.js +1 -0
  923. package/dist/embed/embed-page-openqasm-D2QQCO47.js +1 -0
  924. package/dist/embed/embed-page-openscad-LZPRFY2W.js +1 -0
  925. package/dist/embed/embed-page-oxygene-HZG7OO7G.js +1 -0
  926. package/dist/embed/embed-page-oz-MQNQCKRU.js +1 -0
  927. package/dist/embed/embed-page-packet-BFZMPI3H-JUHAABU6.js +1 -0
  928. package/dist/embed/embed-page-parigp-MAX3X22G.js +1 -0
  929. package/dist/embed/embed-page-parser-2WFCRGYE.js +1 -0
  930. package/dist/embed/embed-page-parser3-C3KVU5ZC.js +1 -0
  931. package/dist/embed/embed-page-pascal-LVXMXCNE.js +1 -0
  932. package/dist/embed/embed-page-pascaligo-6RIW5OHU.js +1 -0
  933. package/dist/embed/embed-page-pcaxis-ZO5S5UAO.js +1 -0
  934. package/dist/embed/embed-page-peoplecode-EAE6M4AF.js +1 -0
  935. package/dist/embed/embed-page-perl-CAUIKKUT.js +1 -0
  936. package/dist/embed/embed-page-perl-NCR5YMVT.js +1 -0
  937. package/dist/embed/embed-page-pf-TXMTVH7H.js +1 -0
  938. package/dist/embed/embed-page-pgsql-M7L7YRCD.js +1 -0
  939. package/dist/embed/embed-page-php-IE2N3QI4.js +1 -0
  940. package/dist/embed/embed-page-php-QCBSAYIC.js +1 -0
  941. package/dist/embed/embed-page-php-extras-VRZO47SA.js +1 -0
  942. package/dist/embed/embed-page-php-template-U54UCRKN.js +1 -0
  943. package/dist/embed/embed-page-phpdoc-ZQWB2OXG.js +1 -0
  944. package/dist/embed/embed-page-pie-7BOR55EZ-GU56BHQJ.js +1 -0
  945. package/dist/embed/embed-page-pieDiagram-ADFJNKIX-JXFHXEAJ.js +30 -0
  946. package/dist/embed/embed-page-plaintext-OINTKMAM.js +1 -0
  947. package/dist/embed/embed-page-plant-uml-3RVWLPWM.js +1 -0
  948. package/dist/embed/embed-page-plsql-XQEBXO73.js +1 -0
  949. package/dist/embed/embed-page-pony-UEK5X7OI.js +1 -0
  950. package/dist/embed/embed-page-powerquery-DEKKCZY7.js +1 -0
  951. package/dist/embed/embed-page-powershell-EBW7RZTN.js +1 -0
  952. package/dist/embed/embed-page-powershell-UMB53SPC.js +1 -0
  953. package/dist/embed/embed-page-processing-56OIROQG.js +1 -0
  954. package/dist/embed/embed-page-processing-ZIDQ7SB3.js +1 -0
  955. package/dist/embed/embed-page-profile-6SSPU7PG.js +1 -0
  956. package/dist/embed/embed-page-prolog-7JA2UBRP.js +1 -0
  957. package/dist/embed/embed-page-prolog-L55HYSKT.js +1 -0
  958. package/dist/embed/embed-page-promql-L4YBO3EF.js +1 -0
  959. package/dist/embed/embed-page-properties-O3BOEJXJ.js +1 -0
  960. package/dist/embed/embed-page-properties-VGZTUJ5E.js +1 -0
  961. package/dist/embed/embed-page-protobuf-F7X2PLJJ.js +1 -0
  962. package/dist/embed/embed-page-protobuf-GS5HMEMS.js +1 -0
  963. package/dist/embed/embed-page-psl-HLKSMRWT.js +1 -0
  964. package/dist/embed/embed-page-pug-MI7HPGUX.js +1 -0
  965. package/dist/embed/embed-page-puppet-2HD3DPH2.js +1 -0
  966. package/dist/embed/embed-page-puppet-BRWZHTKL.js +1 -0
  967. package/dist/embed/embed-page-pure-FVSDVQ2B.js +1 -0
  968. package/dist/embed/embed-page-purebasic-PPHAGMQH.js +1 -0
  969. package/dist/embed/embed-page-purebasic-UVZDR2HE.js +1 -0
  970. package/dist/embed/embed-page-purescript-Q3TGKQZY.js +1 -0
  971. package/dist/embed/embed-page-purify-QTVE4GEG.js +8 -0
  972. package/dist/embed/embed-page-python-NO3SIOCK.js +1 -0
  973. package/dist/embed/embed-page-python-YAPGCWHR.js +1 -0
  974. package/dist/embed/embed-page-python-repl-EIGKWV4T.js +1 -0
  975. package/dist/embed/embed-page-q-5YCCZLRO.js +1 -0
  976. package/dist/embed/embed-page-q-FWJ5L5RH.js +1 -0
  977. package/dist/embed/embed-page-qml-PNZK27ST.js +1 -0
  978. package/dist/embed/embed-page-qml-YVZULPLY.js +1 -0
  979. package/dist/embed/embed-page-qore-QU7W2FQD.js +1 -0
  980. package/dist/embed/embed-page-qsharp-FNGNB3PK.js +1 -0
  981. package/dist/embed/embed-page-quadrantDiagram-AYHSOK5B-4BXTDPJ4.js +7 -0
  982. package/dist/embed/embed-page-r-52DQANKK.js +1 -0
  983. package/dist/embed/embed-page-r-B2QMYOFX.js +1 -0
  984. package/dist/embed/embed-page-racket-OA22GPFB.js +1 -0
  985. package/dist/embed/embed-page-radar-NHE76QYJ-A7QQXLRI.js +1 -0
  986. package/dist/embed/embed-page-reason-QQ4RYUQI.js +1 -0
  987. package/dist/embed/embed-page-reasonml-CQAWSREB.js +1 -0
  988. package/dist/embed/embed-page-regex-5JJLL4V6.js +1 -0
  989. package/dist/embed/embed-page-rego-OLGGN4OK.js +1 -0
  990. package/dist/embed/embed-page-renpy-72F6BTO6.js +1 -0
  991. package/dist/embed/embed-page-requirementDiagram-UZGBJVZJ-WA3XXOP7.js +64 -0
  992. package/dist/embed/embed-page-rescript-VYN4PAG7.js +1 -0
  993. package/dist/embed/embed-page-rest-YZNSQW6O.js +1 -0
  994. package/dist/embed/embed-page-rib-U4ELGIV2.js +1 -0
  995. package/dist/embed/embed-page-rip-ZA4CVYFN.js +1 -0
  996. package/dist/embed/embed-page-roboconf-5IGYRDNH.js +1 -0
  997. package/dist/embed/embed-page-roboconf-HKSGWVI6.js +1 -0
  998. package/dist/embed/embed-page-robotframework-ARNA4YNR.js +1 -0
  999. package/dist/embed/embed-page-routeros-DKQKHPKR.js +1 -0
  1000. package/dist/embed/embed-page-rsl-WZYNFUWJ.js +1 -0
  1001. package/dist/embed/embed-page-ruby-DLLZKK7A.js +1 -0
  1002. package/dist/embed/embed-page-ruby-TKJZO362.js +1 -0
  1003. package/dist/embed/embed-page-ruleslanguage-7CSB4CWD.js +1 -0
  1004. package/dist/embed/embed-page-rust-6JUJCSHC.js +1 -0
  1005. package/dist/embed/embed-page-rust-ZZUD5RKM.js +1 -0
  1006. package/dist/embed/embed-page-sankeyDiagram-TZEHDZUN-SAVUI2Q4.js +10 -0
  1007. package/dist/embed/embed-page-sas-6H3LYHVP.js +1 -0
  1008. package/dist/embed/embed-page-sas-EUBD2V4Z.js +1 -0
  1009. package/dist/embed/embed-page-sass-U6G7R7AZ.js +1 -0
  1010. package/dist/embed/embed-page-scala-HFYNBK2U.js +1 -0
  1011. package/dist/embed/embed-page-scala-OJM3677P.js +1 -0
  1012. package/dist/embed/embed-page-scheme-KBT7Z3ND.js +1 -0
  1013. package/dist/embed/embed-page-scheme-QQ2VPTFQ.js +1 -0
  1014. package/dist/embed/embed-page-scilab-LA3HLVKQ.js +1 -0
  1015. package/dist/embed/embed-page-scss-FDEUPWYR.js +1 -0
  1016. package/dist/embed/embed-page-scss-IH2AODYU.js +1 -0
  1017. package/dist/embed/embed-page-sequenceDiagram-WL72ISMW-C2QRTOTL.js +145 -0
  1018. package/dist/embed/embed-page-shell-O7OU7Y7F.js +1 -0
  1019. package/dist/embed/embed-page-shell-session-CPCKA76Q.js +1 -0
  1020. package/dist/embed/embed-page-smali-3HHDEBNE.js +1 -0
  1021. package/dist/embed/embed-page-smali-L7H7BQUY.js +1 -0
  1022. package/dist/embed/embed-page-smalltalk-KQLA6XRI.js +1 -0
  1023. package/dist/embed/embed-page-smalltalk-WMM37MR4.js +1 -0
  1024. package/dist/embed/embed-page-smarty-AF5LZRHA.js +1 -0
  1025. package/dist/embed/embed-page-sml-4ARWLXZU.js +1 -0
  1026. package/dist/embed/embed-page-sml-6BNN3PMR.js +1 -0
  1027. package/dist/embed/embed-page-solidity-5WL56MR7.js +1 -0
  1028. package/dist/embed/embed-page-solution-file-FJJU2R2L.js +1 -0
  1029. package/dist/embed/embed-page-soy-54PPSPCO.js +1 -0
  1030. package/dist/embed/embed-page-sparql-AC7LG2EE.js +1 -0
  1031. package/dist/embed/embed-page-splunk-spl-YBP24JOS.js +1 -0
  1032. package/dist/embed/embed-page-sqf-4E5P576B.js +1 -0
  1033. package/dist/embed/embed-page-sqf-CSHANDQB.js +1 -0
  1034. package/dist/embed/embed-page-sql-MGWNK6FE.js +1 -0
  1035. package/dist/embed/embed-page-sql-ZOJORZUC.js +1 -0
  1036. package/dist/embed/embed-page-sql_more-NACOUKSZ.js +1 -0
  1037. package/dist/embed/embed-page-squirrel-XG35KUR2.js +1 -0
  1038. package/dist/embed/embed-page-stan-GDB32LYB.js +1 -0
  1039. package/dist/embed/embed-page-stan-UJ7WCNJT.js +1 -0
  1040. package/dist/embed/embed-page-stata-DEQ57OIC.js +1 -0
  1041. package/dist/embed/embed-page-stata-WJUFDMUW.js +1 -0
  1042. package/dist/embed/embed-page-stateDiagram-FKZM4ZOC-6LDVHEHS.js +1 -0
  1043. package/dist/embed/embed-page-stateDiagram-v2-4FDKWEC3-UJYGEYF5.js +1 -0
  1044. package/dist/embed/embed-page-step21-6AYDKM5N.js +1 -0
  1045. package/dist/embed/embed-page-stylus-CFL6FZN3.js +1 -0
  1046. package/dist/embed/embed-page-stylus-MLEF22IY.js +1 -0
  1047. package/dist/embed/embed-page-subunit-OZQ2HNNA.js +1 -0
  1048. package/dist/embed/embed-page-supercollider-ZK2ECEDQ.js +1 -0
  1049. package/dist/embed/embed-page-swift-MNLMKF5F.js +1 -0
  1050. package/dist/embed/embed-page-swift-UJP2CPA4.js +1 -0
  1051. package/dist/embed/embed-page-systemd-DQXTIGWD.js +1 -0
  1052. package/dist/embed/embed-page-t4-cs-ZPHNHWPR.js +1 -0
  1053. package/dist/embed/embed-page-t4-templating-OA7FNPXM.js +1 -0
  1054. package/dist/embed/embed-page-t4-vb-XBX2HBI5.js +1 -0
  1055. package/dist/embed/embed-page-taggerscript-XVALJYA3.js +1 -0
  1056. package/dist/embed/embed-page-tap-EMOHKH5F.js +1 -0
  1057. package/dist/embed/embed-page-tap-HZHER7FY.js +1 -0
  1058. package/dist/embed/embed-page-tcl-GN4WSRHR.js +1 -0
  1059. package/dist/embed/embed-page-tcl-T3WWKS3Q.js +1 -0
  1060. package/dist/embed/embed-page-textile-OXFYF2DV.js +1 -0
  1061. package/dist/embed/embed-page-thrift-Q26IKVBC.js +1 -0
  1062. package/dist/embed/embed-page-timeline-definition-IT6M3QCI-OF6FTGVN.js +61 -0
  1063. package/dist/embed/embed-page-toml-ZVNI7WJB.js +1 -0
  1064. package/dist/embed/embed-page-tp-24NWOAQZ.js +1 -0
  1065. package/dist/embed/embed-page-treemap-KMMF4GRG-HPTV3SYE.js +1 -0
  1066. package/dist/embed/embed-page-tremor-443PBNWC.js +1 -0
  1067. package/dist/embed/embed-page-tsx-PX2Z4GDU.js +1 -0
  1068. package/dist/embed/embed-page-tt2-L43LNTGL.js +1 -0
  1069. package/dist/embed/embed-page-turtle-IXYYTHLU.js +1 -0
  1070. package/dist/embed/embed-page-twig-MZBQAWRC.js +1 -0
  1071. package/dist/embed/embed-page-twig-WSAAZNH3.js +1 -0
  1072. package/dist/embed/embed-page-typescript-5UWO3Y3K.js +1 -0
  1073. package/dist/embed/embed-page-typescript-BPIRCQG7.js +1 -0
  1074. package/dist/embed/embed-page-typoscript-UUKPTXPH.js +1 -0
  1075. package/dist/embed/embed-page-unrealscript-G2VHZRFN.js +1 -0
  1076. package/dist/embed/embed-page-uorazor-WYGVL7PT.js +1 -0
  1077. package/dist/embed/embed-page-uri-NRWWZBB7.js +1 -0
  1078. package/dist/embed/embed-page-v-LKVTPKDV.js +1 -0
  1079. package/dist/embed/embed-page-vala-EL5BNKYD.js +1 -0
  1080. package/dist/embed/embed-page-vala-MLIRE3PS.js +1 -0
  1081. package/dist/embed/embed-page-vbnet-5JKSIZ56.js +1 -0
  1082. package/dist/embed/embed-page-vbnet-KOGX2JTL.js +1 -0
  1083. package/dist/embed/embed-page-vbscript-637T6GXI.js +1 -0
  1084. package/dist/embed/embed-page-vbscript-html-YKWMMXG4.js +1 -0
  1085. package/dist/embed/embed-page-velocity-7Q63BBW2.js +1 -0
  1086. package/dist/embed/embed-page-verilog-B6EWQWMJ.js +1 -0
  1087. package/dist/embed/embed-page-verilog-G566LGG4.js +1 -0
  1088. package/dist/embed/embed-page-vhdl-R5JIOJNH.js +1 -0
  1089. package/dist/embed/embed-page-vhdl-RMOYZXLG.js +1 -0
  1090. package/dist/embed/embed-page-vim-47Q56RS4.js +1 -0
  1091. package/dist/embed/embed-page-vim-KBCAYMER.js +1 -0
  1092. package/dist/embed/embed-page-visual-basic-ZYE5FD6G.js +1 -0
  1093. package/dist/embed/embed-page-warpscript-65UOMFFU.js +1 -0
  1094. package/dist/embed/embed-page-wasm-MSBGNWUM.js +1 -0
  1095. package/dist/embed/embed-page-web-idl-7WW5RGOI.js +1 -0
  1096. package/dist/embed/embed-page-wgsl-FG3PI6M7.js +1 -0
  1097. package/dist/embed/embed-page-wiki-DGVS4GPN.js +1 -0
  1098. package/dist/embed/embed-page-wolfram-MOURXWVE.js +1 -0
  1099. package/dist/embed/embed-page-wren-PYL5ZRVR.js +1 -0
  1100. package/dist/embed/embed-page-x86asm-WQ6M3VHZ.js +1 -0
  1101. package/dist/embed/embed-page-xeora-JSPZIDKL.js +1 -0
  1102. package/dist/embed/embed-page-xl-DTY4E7YS.js +1 -0
  1103. package/dist/embed/embed-page-xml-P5QA5BKM.js +1 -0
  1104. package/dist/embed/embed-page-xml-doc-VAJOIYSW.js +1 -0
  1105. package/dist/embed/embed-page-xojo-L2PDU7MC.js +1 -0
  1106. package/dist/embed/embed-page-xquery-EWBQ7NVP.js +1 -0
  1107. package/dist/embed/embed-page-xquery-RUKMMBO2.js +1 -0
  1108. package/dist/embed/embed-page-xychartDiagram-PRI3JC2R-EWLR5Z3I.js +7 -0
  1109. package/dist/embed/embed-page-yaml-76KRB6BP.js +1 -0
  1110. package/dist/embed/embed-page-yaml-RR5MLWRK.js +1 -0
  1111. package/dist/embed/embed-page-yang-J62Y5RPD.js +1 -0
  1112. package/dist/embed/embed-page-zephir-OIOOQGNI.js +1 -0
  1113. package/dist/embed/embed-page-zig-75SL5ZWR.js +1 -0
  1114. package/dist/embed/embed-page.css +1 -0
  1115. package/dist/embed/embed-page.js +6 -0
  1116. package/dist/index.d.mts +19 -40
  1117. package/dist/index.d.ts +19 -40
  1118. package/dist/index.js +2082 -1142
  1119. package/dist/index.js.map +1 -1
  1120. package/dist/index.mjs +1647 -940
  1121. package/dist/index.mjs.map +1 -1
  1122. package/dist/{mcp-configs-SHRMQHIL.mjs → mcp-configs-IIKQM5GM.mjs} +2 -2
  1123. package/dist/mcpTransportRegistry-XMJ5Y2RG.mjs +13 -0
  1124. package/dist/mcpTransportRegistry-XMJ5Y2RG.mjs.map +1 -0
  1125. package/dist/open-DCAOL5CG.mjs +176 -0
  1126. package/dist/open-DCAOL5CG.mjs.map +1 -0
  1127. package/package.json +11 -8
  1128. package/dist/a2a-standard-G3J5ZHQ7.mjs.map +0 -1
  1129. /package/dist/{mcp-configs-SHRMQHIL.mjs.map → mcp-configs-IIKQM5GM.mjs.map} +0 -0
package/dist/index.js CHANGED
@@ -35,8 +35,8 @@ function getContentTypeFromFilename(filename) {
35
35
  const ext = filename.includes(".") ? filename.slice(filename.lastIndexOf(".")).toLowerCase() : "";
36
36
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
37
37
  }
38
- function getFilenameFromPath(path6) {
39
- const segments = path6.replace(/\/+$/, "").split("/");
38
+ function getFilenameFromPath(path7) {
39
+ const segments = path7.replace(/\/+$/, "").split("/");
40
40
  return segments[segments.length - 1] || "download";
41
41
  }
42
42
  var EXT_TO_MIME;
@@ -647,7 +647,8 @@ function convertToConnection(config) {
647
647
  return {
648
648
  ...baseConfig,
649
649
  transport: config.transport === "streamable_http" ? "http" : config.transport,
650
- url: config.url
650
+ url: config.url,
651
+ headers: config.headers
651
652
  };
652
653
  }
653
654
  }
@@ -869,17 +870,17 @@ function generateWechatUin() {
869
870
  buf.writeUInt32BE(Math.floor(Math.random() * 4294967295), 0);
870
871
  return buf.toString("base64url");
871
872
  }
872
- async function apiGet(path6, extraHeaders) {
873
- const url = `${getBaseUrl()}${path6}`;
873
+ async function apiGet(path7, extraHeaders) {
874
+ const url = `${getBaseUrl()}${path7}`;
874
875
  const headers = { ...extraHeaders };
875
876
  const res = await fetch(url, { headers });
876
877
  if (!res.ok) {
877
- throw new Error(`iLink GET ${path6} failed: ${res.status} ${res.statusText}`);
878
+ throw new Error(`iLink GET ${path7} failed: ${res.status} ${res.statusText}`);
878
879
  }
879
880
  return res.json();
880
881
  }
881
- async function apiPost(path6, body, botToken, signal) {
882
- const url = `${getBaseUrl()}${path6}`;
882
+ async function apiPost(path7, body, botToken, signal) {
883
+ const url = `${getBaseUrl()}${path7}`;
883
884
  const headers = {
884
885
  "Content-Type": "application/json",
885
886
  "AuthorizationType": "ilink_bot_token",
@@ -893,7 +894,7 @@ async function apiPost(path6, body, botToken, signal) {
893
894
  signal
894
895
  });
895
896
  if (!res.ok) {
896
- throw new Error(`iLink POST ${path6} failed: ${res.status} ${res.statusText}`);
897
+ throw new Error(`iLink POST ${path7} failed: ${res.status} ${res.statusText}`);
897
898
  }
898
899
  return res.json();
899
900
  }
@@ -1040,18 +1041,18 @@ function extractText(msg) {
1040
1041
  }
1041
1042
  return null;
1042
1043
  }
1043
- var import_zod14, logger5, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections2, seenClientIds, wechatChannelAdapter;
1044
+ var import_zod15, logger5, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections2, seenClientIds, wechatChannelAdapter;
1044
1045
  var init_WechatChannelAdapter = __esm({
1045
1046
  "src/channels/wechat/WechatChannelAdapter.ts"() {
1046
1047
  "use strict";
1047
- import_zod14 = require("zod");
1048
+ import_zod15 = require("zod");
1048
1049
  init_wechat_client();
1049
1050
  init_context_store();
1050
1051
  init_Logger();
1051
1052
  logger5 = new Logger({ serviceName: "lattice/gateway/wechat" });
1052
- wechatConfigSchema = import_zod14.z.object({
1053
- botToken: import_zod14.z.string(),
1054
- uin: import_zod14.z.string().optional()
1053
+ wechatConfigSchema = import_zod15.z.object({
1054
+ botToken: import_zod15.z.string(),
1055
+ uin: import_zod15.z.string().optional()
1055
1056
  });
1056
1057
  MAX_RECONNECT_DELAY_MS = 3e4;
1057
1058
  BASE_RECONNECT_DELAY_MS = 1e3;
@@ -1512,7 +1513,7 @@ function extractFailureReason(task) {
1512
1513
  return extractText2(task.status.message.parts);
1513
1514
  }
1514
1515
  function observationEventKey(task, result, failureReason) {
1515
- const digest = (0, import_node_crypto19.createHash)("sha256").update(JSON.stringify({
1516
+ const digest = (0, import_node_crypto21.createHash)("sha256").update(JSON.stringify({
1516
1517
  state: task.status.state,
1517
1518
  timestamp: task.status.timestamp,
1518
1519
  message: task.status.message,
@@ -1522,7 +1523,7 @@ function observationEventKey(task, result, failureReason) {
1522
1523
  return `a2a-status-observation:${task.id}:${digest}`;
1523
1524
  }
1524
1525
  function snapshotEventKey(task) {
1525
- const digest = (0, import_node_crypto19.createHash)("sha256").update(JSON.stringify(task)).digest("hex");
1526
+ const digest = (0, import_node_crypto21.createHash)("sha256").update(JSON.stringify(task)).digest("hex");
1526
1527
  return `a2a-task-snapshot:${task.id}:${digest}`;
1527
1528
  }
1528
1529
  function isGovernedObservation(state) {
@@ -1534,11 +1535,11 @@ function isA2ATaskSnapshot(value) {
1534
1535
  function snapshotSequence(value) {
1535
1536
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
1536
1537
  }
1537
- var import_node_crypto19, import_node_util, TASK_STATUS_TO_A2A_STATE, TITLE_MAX_LENGTH, A2ATaskScopeConflictError, A2ATaskStoreAdapter;
1538
+ var import_node_crypto21, import_node_util, TASK_STATUS_TO_A2A_STATE, TITLE_MAX_LENGTH, A2ATaskScopeConflictError, A2ATaskStoreAdapter;
1538
1539
  var init_A2ATaskStoreAdapter = __esm({
1539
1540
  "src/services/a2a/A2ATaskStoreAdapter.ts"() {
1540
1541
  "use strict";
1541
- import_node_crypto19 = require("crypto");
1542
+ import_node_crypto21 = require("crypto");
1542
1543
  import_node_util = require("util");
1543
1544
  TASK_STATUS_TO_A2A_STATE = {
1544
1545
  pending: "submitted",
@@ -1641,11 +1642,11 @@ var init_A2ATaskStoreAdapter = __esm({
1641
1642
  async recordSnapshot(task, item) {
1642
1643
  const incomingSequence = snapshotSequence(task.metadata?.snapshotSequence) ?? 0;
1643
1644
  const currentSequence = this.snapshotSequences.get(task.id) ?? 0;
1644
- const sequence2 = Math.max(incomingSequence, currentSequence) + 1;
1645
- this.snapshotSequences.set(task.id, sequence2);
1645
+ const sequence = Math.max(incomingSequence, currentSequence) + 1;
1646
+ this.snapshotSequences.set(task.id, sequence);
1646
1647
  const sequencedTask = {
1647
1648
  ...task,
1648
- metadata: { ...task.metadata ?? {}, snapshotSequence: sequence2 }
1649
+ metadata: { ...task.metadata ?? {}, snapshotSequence: sequence }
1649
1650
  };
1650
1651
  const eventKey = snapshotEventKey(sequencedTask);
1651
1652
  await this.workItemStore.createIfAbsentByEventKey({
@@ -1655,7 +1656,7 @@ var init_A2ATaskStoreAdapter = __esm({
1655
1656
  action: "activity",
1656
1657
  actor: `a2a:${this.scope.assistantId}`,
1657
1658
  summary: "A2A task snapshot",
1658
- detail: { type: "a2a_task_snapshot", snapshotSequence: sequence2, eventKey, task: sequencedTask },
1659
+ detail: { type: "a2a_task_snapshot", snapshotSequence: sequence, eventKey, task: sequencedTask },
1659
1660
  eventKey,
1660
1661
  ...asString(task.metadata?.threadId) ? { threadId: asString(task.metadata?.threadId) } : {},
1661
1662
  ...item.workspaceId ? { workspaceId: item.workspaceId } : {}
@@ -1762,10 +1763,10 @@ var init_A2ATaskStoreAdapter = __esm({
1762
1763
  });
1763
1764
  for (const activity of activities) {
1764
1765
  if (activity.detail?.type !== "a2a_task_snapshot" || !isA2ATaskSnapshot(activity.detail.task)) continue;
1765
- const sequence2 = snapshotSequence(activity.detail.snapshotSequence) ?? snapshotSequence(activity.detail.task.metadata?.snapshotSequence);
1766
+ const sequence = snapshotSequence(activity.detail.snapshotSequence) ?? snapshotSequence(activity.detail.task.metadata?.snapshotSequence);
1766
1767
  const candidate = {
1767
1768
  task: activity.detail.task,
1768
- sequence: sequence2,
1769
+ sequence,
1769
1770
  eventKey: asString(activity.detail.eventKey) ?? activity.eventKey ?? snapshotEventKey(activity.detail.task),
1770
1771
  statusTimestamp: Date.parse(activity.detail.task.status.timestamp ?? ""),
1771
1772
  createdAt: activity.createdAt,
@@ -1895,13 +1896,13 @@ function agentMessage(text) {
1895
1896
  parts: [{ kind: "text", text }]
1896
1897
  };
1897
1898
  }
1898
- var import_uuid11, import_core66, import_protocols27, _AxiomAgentExecutor, AxiomAgentExecutor;
1899
+ var import_uuid11, import_core66, import_protocols29, _AxiomAgentExecutor, AxiomAgentExecutor;
1899
1900
  var init_AxiomAgentExecutor = __esm({
1900
1901
  "src/services/a2a/AxiomAgentExecutor.ts"() {
1901
1902
  "use strict";
1902
1903
  import_uuid11 = require("uuid");
1903
1904
  import_core66 = require("@axiom-lattice/core");
1904
- import_protocols27 = require("@axiom-lattice/protocols");
1905
+ import_protocols29 = require("@axiom-lattice/protocols");
1905
1906
  init_a2aFileRefs();
1906
1907
  init_task_file_refs();
1907
1908
  _AxiomAgentExecutor = class _AxiomAgentExecutor {
@@ -1999,7 +2000,7 @@ ${formatFileRefsSection(inputFiles)}` : text;
1999
2000
  const messageText = [
2000
2001
  `A2A governed task instruction: get and update the existing TaskItem ${ctx.taskId}; do not create a replacement task.`,
2001
2002
  "Before doing the requested work, initialize its canonical description through manage_task with ## Objective, ## Acceptance Criteria, and ## Belief State sections.",
2002
- "Keep lifecycle status truthful. Complete only through manage_task update with a nonblank result and structured beliefImpact; use interrupted, failed, or cancelled when appropriate.",
2003
+ "Keep lifecycle status truthful. Change status only through manage_task set_status; complete with a nonblank result and structured beliefImpact, and use interrupted, failed, or cancelled when appropriate. Use manage_task update for content fields only.",
2003
2004
  "",
2004
2005
  requestText
2005
2006
  ].join("\n");
@@ -2010,16 +2011,16 @@ ${formatFileRefsSection(inputFiles)}` : text;
2010
2011
  custom_run_config: { taskId: ctx.taskId }
2011
2012
  });
2012
2013
  const stream = agent.chunkStream(messageId, [
2013
- import_protocols27.MessageChunkTypes.MESSAGE_COMPLETED
2014
+ import_protocols29.MessageChunkTypes.MESSAGE_COMPLETED
2014
2015
  ]);
2015
2016
  for await (const chunk of stream) {
2016
2017
  if (execution.canceled) return;
2017
2018
  const chunkType = chunk.type;
2018
2019
  const chunkText = chunk.data?.content ?? "";
2019
- if (chunkType === import_protocols27.MessageChunkTypes.INTERRUPT) {
2020
+ if (chunkType === import_protocols29.MessageChunkTypes.INTERRUPT) {
2020
2021
  break;
2021
2022
  }
2022
- if (chunkType === import_protocols27.MessageChunkTypes.AI || chunkType === import_protocols27.MessageChunkTypes.TOOL) {
2023
+ if (chunkType === import_protocols29.MessageChunkTypes.AI || chunkType === import_protocols29.MessageChunkTypes.TOOL) {
2023
2024
  if (chunkText) {
2024
2025
  bus.publish({
2025
2026
  kind: "status-update",
@@ -2936,6 +2937,236 @@ var init_a2a = __esm({
2936
2937
  }
2937
2938
  });
2938
2939
 
2940
+ // src/services/open/openCredentials.ts
2941
+ function resolveSpikeCredential(token) {
2942
+ if (!token) return null;
2943
+ return SPIKE_CREDENTIALS.get(token) ?? null;
2944
+ }
2945
+ var SPIKE_CREDENTIALS;
2946
+ var init_openCredentials = __esm({
2947
+ "src/services/open/openCredentials.ts"() {
2948
+ "use strict";
2949
+ SPIKE_CREDENTIALS = /* @__PURE__ */ new Map([
2950
+ [
2951
+ "spike_all",
2952
+ {
2953
+ credentialId: "spike_all",
2954
+ kind: "api_key",
2955
+ tenantId: "spike-tenant",
2956
+ projectId: "spike-project",
2957
+ grants: [{ domain: "kb" }, { domain: "sandbox" }]
2958
+ }
2959
+ ],
2960
+ [
2961
+ "spike_kb",
2962
+ {
2963
+ credentialId: "spike_kb",
2964
+ kind: "api_key",
2965
+ tenantId: "spike-tenant",
2966
+ projectId: "spike-project",
2967
+ grants: [{ domain: "kb" }]
2968
+ }
2969
+ ]
2970
+ ]);
2971
+ }
2972
+ });
2973
+
2974
+ // src/services/open/mcpTransportRegistry.ts
2975
+ var mcpTransportRegistry_exports = {};
2976
+ __export(mcpTransportRegistry_exports, {
2977
+ clearSessions: () => clearSessions,
2978
+ deleteSession: () => deleteSession,
2979
+ getSession: () => getSession,
2980
+ registerSession: () => registerSession
2981
+ });
2982
+ async function registerSession(sessionId, credential, parts) {
2983
+ sessions.set(sessionId, { ...parts, credential });
2984
+ }
2985
+ async function getSession(sessionId) {
2986
+ return sessions.get(sessionId) ?? null;
2987
+ }
2988
+ async function deleteSession(sessionId) {
2989
+ const entry = sessions.get(sessionId);
2990
+ if (!entry) return;
2991
+ sessions.delete(sessionId);
2992
+ await entry.transport.close().catch(() => void 0);
2993
+ await entry.server.close().catch(() => void 0);
2994
+ }
2995
+ async function clearSessions() {
2996
+ for (const sessionId of [...sessions.keys()]) {
2997
+ await deleteSession(sessionId);
2998
+ }
2999
+ }
3000
+ var sessions;
3001
+ var init_mcpTransportRegistry = __esm({
3002
+ "src/services/open/mcpTransportRegistry.ts"() {
3003
+ "use strict";
3004
+ sessions = /* @__PURE__ */ new Map();
3005
+ }
3006
+ });
3007
+
3008
+ // src/services/open/mcpCatalog.ts
3009
+ function textResult(text) {
3010
+ return [{ type: "text", text }];
3011
+ }
3012
+ function filterCatalogByGrants(credential) {
3013
+ const domains = new Set(credential.grants.map((g) => g.domain));
3014
+ return SPIKE_TOOL_CATALOG.filter((tool) => domains.has(tool.domain));
3015
+ }
3016
+ var import_zod16, SPIKE_TOOL_CATALOG;
3017
+ var init_mcpCatalog = __esm({
3018
+ "src/services/open/mcpCatalog.ts"() {
3019
+ "use strict";
3020
+ import_zod16 = require("zod");
3021
+ SPIKE_TOOL_CATALOG = [
3022
+ {
3023
+ toolName: "kb_search",
3024
+ domain: "kb",
3025
+ description: "Spike: pretend knowledge-base search.",
3026
+ schema: {
3027
+ query: import_zod16.z.string(),
3028
+ limit: import_zod16.z.number().int().optional()
3029
+ },
3030
+ annotations: { readOnlyHint: true, destructiveHint: false },
3031
+ execute: async (args) => {
3032
+ const { query } = args;
3033
+ return textResult(`kb_search spike result for: ${query}`);
3034
+ }
3035
+ },
3036
+ {
3037
+ toolName: "echo",
3038
+ domain: "sandbox",
3039
+ description: "Spike: echoes the message back.",
3040
+ schema: { message: import_zod16.z.string() },
3041
+ annotations: { readOnlyHint: true, destructiveHint: false },
3042
+ execute: async (args) => {
3043
+ const { message } = args;
3044
+ return textResult(`echo: ${message}`);
3045
+ }
3046
+ }
3047
+ ];
3048
+ }
3049
+ });
3050
+
3051
+ // src/services/open/openMcpServer.ts
3052
+ function registerTools(server, tools) {
3053
+ for (const tool of tools) {
3054
+ server.registerTool(
3055
+ tool.toolName,
3056
+ {
3057
+ description: tool.description,
3058
+ inputSchema: tool.schema,
3059
+ annotations: {
3060
+ readOnlyHint: tool.annotations.readOnlyHint,
3061
+ destructiveHint: tool.annotations.destructiveHint
3062
+ }
3063
+ },
3064
+ async (args) => ({ content: await tool.execute(args) })
3065
+ );
3066
+ }
3067
+ }
3068
+ async function buildSessionServer(credential) {
3069
+ const tools = filterCatalogByGrants(credential);
3070
+ const server = new import_mcp.McpServer(OPEN_MCP_SERVER_INFO);
3071
+ registerTools(server, tools);
3072
+ const transport = new import_streamableHttp.StreamableHTTPServerTransport({
3073
+ sessionIdGenerator: () => {
3074
+ const sessionId = (0, import_crypto12.randomUUID)();
3075
+ void registerSession(
3076
+ sessionId,
3077
+ { credentialId: credential.credentialId, kind: credential.kind },
3078
+ { server, transport }
3079
+ );
3080
+ return sessionId;
3081
+ },
3082
+ enableJsonResponse: true,
3083
+ onsessionclosed: (closedId) => {
3084
+ void Promise.resolve().then(() => (init_mcpTransportRegistry(), mcpTransportRegistry_exports)).then(
3085
+ ({ deleteSession: deleteSession2 }) => deleteSession2(closedId)
3086
+ );
3087
+ }
3088
+ });
3089
+ await server.connect(transport);
3090
+ return { server, transport, tools };
3091
+ }
3092
+ var import_mcp, import_streamableHttp, import_crypto12, OPEN_MCP_SERVER_INFO;
3093
+ var init_openMcpServer = __esm({
3094
+ "src/services/open/openMcpServer.ts"() {
3095
+ "use strict";
3096
+ import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
3097
+ import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
3098
+ import_crypto12 = require("crypto");
3099
+ init_mcpTransportRegistry();
3100
+ init_mcpCatalog();
3101
+ OPEN_MCP_SERVER_INFO = {
3102
+ name: "axiom-open",
3103
+ version: "0.1.0"
3104
+ };
3105
+ }
3106
+ });
3107
+
3108
+ // src/routes/open.ts
3109
+ var open_exports = {};
3110
+ __export(open_exports, {
3111
+ registerOpenRoutes: () => registerOpenRoutes
3112
+ });
3113
+ function extractBearer(request) {
3114
+ const header2 = request.headers.authorization;
3115
+ if (!header2?.startsWith("Bearer ")) return void 0;
3116
+ return header2.slice("Bearer ".length).trim() || void 0;
3117
+ }
3118
+ function readSessionId(request) {
3119
+ const raw = request.headers["mcp-session-id"];
3120
+ const value = Array.isArray(raw) ? raw[0] : raw;
3121
+ return typeof value === "string" && value.length > 0 ? value : void 0;
3122
+ }
3123
+ function registerOpenRoutes(app2) {
3124
+ app2.post("/open/mcp", async (request, reply) => {
3125
+ const credential = resolveSpikeCredential(extractBearer(request));
3126
+ if (!credential) {
3127
+ return reply.status(401).send({ error: "AUTH_FAILED" });
3128
+ }
3129
+ const body = request.body;
3130
+ const sessionId = readSessionId(request);
3131
+ if (sessionId) {
3132
+ const session = await getSession(sessionId);
3133
+ if (!session || session.credential.credentialId !== credential.credentialId) {
3134
+ return reply.status(404).send({ error: "SESSION_NOT_FOUND" });
3135
+ }
3136
+ reply.hijack();
3137
+ await session.transport.handleRequest(request.raw, reply.raw, body);
3138
+ return;
3139
+ }
3140
+ if (!(0, import_types.isInitializeRequest)(body)) {
3141
+ return reply.status(400).send({ error: "SESSION_REQUIRED" });
3142
+ }
3143
+ const built = await buildSessionServer(credential);
3144
+ reply.hijack();
3145
+ await built.transport.handleRequest(request.raw, reply.raw, body);
3146
+ });
3147
+ app2.delete(
3148
+ "/open/mcp",
3149
+ async (request, reply) => {
3150
+ const sessionId = readSessionId(request);
3151
+ if (!sessionId) {
3152
+ return reply.status(400).send({ error: "SESSION_REQUIRED" });
3153
+ }
3154
+ await deleteSession(sessionId);
3155
+ return reply.status(204).send();
3156
+ }
3157
+ );
3158
+ }
3159
+ var import_types;
3160
+ var init_open = __esm({
3161
+ "src/routes/open.ts"() {
3162
+ "use strict";
3163
+ import_types = require("@modelcontextprotocol/sdk/types.js");
3164
+ init_openCredentials();
3165
+ init_openMcpServer();
3166
+ init_mcpTransportRegistry();
3167
+ }
3168
+ });
3169
+
2939
3170
  // src/controllers/resources.ts
2940
3171
  var resources_exports = {};
2941
3172
  __export(resources_exports, {
@@ -3171,8 +3402,8 @@ var init_resources = __esm({
3171
3402
  return cookie.includes(`share_unlock_${token}=1`);
3172
3403
  }
3173
3404
  /** Returns true if the path has a file extension indicating it's a file, not a directory */
3174
- _isFilePath(path6) {
3175
- return /\.[a-zA-Z0-9]+$/.test(path6);
3405
+ _isFilePath(path7) {
3406
+ return /\.[a-zA-Z0-9]+$/.test(path7);
3176
3407
  }
3177
3408
  /**
3178
3409
  * Shared file resolution: directory → index.html, volume FS → sandbox, base tag, response.
@@ -3313,8 +3544,8 @@ var import_static = __toESM(require("@fastify/static"));
3313
3544
  var import_path = __toESM(require("path"));
3314
3545
 
3315
3546
  // src/routes/index.ts
3316
- var import_node_crypto18 = require("crypto");
3317
- var import_protocols24 = require("@axiom-lattice/protocols");
3547
+ var import_node_crypto20 = require("crypto");
3548
+ var import_protocols26 = require("@axiom-lattice/protocols");
3318
3549
 
3319
3550
  // src/controllers/assistant.ts
3320
3551
  var import_core = require("@axiom-lattice/core");
@@ -7381,9 +7612,9 @@ var ExportImportService = class {
7381
7612
  if (!files || files.size === 0) return void 0;
7382
7613
  const prefix = `files/${entityType}/${entityId}/`;
7383
7614
  const result = /* @__PURE__ */ new Map();
7384
- for (const [path6, content] of files.entries()) {
7385
- if (path6.startsWith(prefix)) {
7386
- result.set(path6.slice(prefix.length), content);
7615
+ for (const [path7, content] of files.entries()) {
7616
+ if (path7.startsWith(prefix)) {
7617
+ result.set(path7.slice(prefix.length), content);
7387
7618
  }
7388
7619
  }
7389
7620
  return result.size > 0 ? result : void 0;
@@ -9488,21 +9719,21 @@ var WorkspaceController = class {
9488
9719
  async listPath(request) {
9489
9720
  const tenantId = this.getTenantId(request);
9490
9721
  const { workspaceId, projectId } = request.params;
9491
- const path6 = request.query.path || "/";
9722
+ const path7 = request.query.path || "/";
9492
9723
  const assistantId = request.query.assistantId;
9493
- console.log(`[listPath] tenantId=${tenantId} workspaceId=${workspaceId} projectId=${projectId} path=${path6} assistantId=${assistantId}`);
9494
- const { backend } = await this.getBackend(tenantId, workspaceId, projectId, assistantId, path6);
9495
- console.log(`[listPath] backend type=${backend.constructor.name} calling lsInfo(${path6})`);
9496
- const files = await backend.lsInfo(path6);
9724
+ console.log(`[listPath] tenantId=${tenantId} workspaceId=${workspaceId} projectId=${projectId} path=${path7} assistantId=${assistantId}`);
9725
+ const { backend } = await this.getBackend(tenantId, workspaceId, projectId, assistantId, path7);
9726
+ console.log(`[listPath] backend type=${backend.constructor.name} calling lsInfo(${path7})`);
9727
+ const files = await backend.lsInfo(path7);
9497
9728
  console.log(`[listPath] result count=${files.length}`);
9498
9729
  return { success: true, data: files };
9499
9730
  }
9500
9731
  async readFile(request) {
9501
9732
  const tenantId = this.getTenantId(request);
9502
9733
  const { workspaceId, projectId } = request.params;
9503
- const { path: path6, offset = 0, limit = 1e3, assistantId } = request.query;
9504
- const { backend } = await this.getBackend(tenantId, workspaceId, projectId, assistantId, path6);
9505
- const content = await backend.read(path6, Number(offset), Number(limit));
9734
+ const { path: path7, offset = 0, limit = 1e3, assistantId } = request.query;
9735
+ const { backend } = await this.getBackend(tenantId, workspaceId, projectId, assistantId, path7);
9736
+ const content = await backend.read(path7, Number(offset), Number(limit));
9506
9737
  return { success: true, data: { content, offset, limit } };
9507
9738
  }
9508
9739
  /**
@@ -9688,139 +9919,327 @@ function registerWorkspaceRoutes(app2, projectCollaboration) {
9688
9919
  "/api/filesystem/browse",
9689
9920
  controller.browseFilesystem.bind(controller)
9690
9921
  );
9922
+ return controller;
9691
9923
  }
9692
9924
 
9693
- // src/controllers/database-configs.ts
9694
- var import_core27 = require("@axiom-lattice/core");
9695
- var import_crypto5 = require("crypto");
9696
- function getTenantId9(request) {
9697
- const userTenantId = request.user?.tenantId;
9698
- if (userTenantId) {
9699
- return userTenantId;
9925
+ // src/services/collaboration/ProjectAccessService.ts
9926
+ var import_node_crypto3 = require("crypto");
9927
+ var ProjectCollaborationError = class extends Error {
9928
+ /** Creates a project collaboration error. */
9929
+ constructor(code, statusCode, message) {
9930
+ super(message);
9931
+ this.code = code;
9932
+ this.statusCode = statusCode;
9933
+ this.name = "ProjectCollaborationError";
9700
9934
  }
9701
- return request.headers["x-tenant-id"] || "default";
9935
+ };
9936
+ var allowedRoles = {
9937
+ read: /* @__PURE__ */ new Set(["owner", "admin", "member", "viewer"]),
9938
+ send: /* @__PURE__ */ new Set(["owner", "admin", "member"]),
9939
+ manage: /* @__PURE__ */ new Set(["owner", "admin"])
9940
+ };
9941
+ var membershipConflictNames = /* @__PURE__ */ new Set([
9942
+ "DuplicateProjectMembershipError",
9943
+ "ProjectMembershipIdConflictError"
9944
+ ]);
9945
+ function isProjectMembershipConflict(error) {
9946
+ return error instanceof Error && membershipConflictNames.has(error.name);
9702
9947
  }
9703
- async function getDatabaseConfigList(request, reply) {
9704
- const tenantId = getTenantId9(request);
9705
- try {
9706
- const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
9707
- const store2 = storeLattice.store;
9708
- const configs = await store2.getAllConfigs(tenantId);
9709
- console.log("Backend: getAllConfigs returned:", configs);
9710
- if (configs.length > 0) {
9711
- console.log("Backend: First config key:", configs[0].key);
9712
- }
9713
- return {
9714
- success: true,
9715
- message: "Database configurations retrieved successfully",
9716
- data: {
9717
- records: configs,
9718
- total: configs.length
9719
- }
9720
- };
9721
- } catch (error) {
9722
- console.error("Failed to get database configs:", error);
9723
- return {
9724
- success: false,
9725
- message: "Failed to retrieve database configurations",
9726
- data: {
9727
- records: [],
9728
- total: 0
9729
- }
9730
- };
9948
+ var ProjectAccessService = class {
9949
+ /** Creates a project access service from explicitly injected stores. */
9950
+ constructor(deps) {
9951
+ this.deps = deps;
9952
+ this.idFactory = deps.idFactory ?? import_node_crypto3.randomUUID;
9731
9953
  }
9732
- }
9733
- async function getDatabaseConfig(request, reply) {
9734
- const tenantId = getTenantId9(request);
9735
- const { key } = request.params;
9736
- try {
9737
- const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
9738
- const store2 = storeLattice.store;
9739
- const config = await store2.getConfigByKey(tenantId, key);
9740
- if (!config) {
9741
- return {
9742
- success: false,
9743
- message: "Database configuration not found"
9744
- };
9954
+ /** Returns the project and active membership when the user has the requested capability. */
9955
+ async requireProjectAccess(input) {
9956
+ const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
9957
+ if (!project) {
9958
+ throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
9745
9959
  }
9746
- return {
9747
- success: true,
9748
- message: "Database configuration retrieved successfully",
9749
- data: config
9750
- };
9751
- } catch (error) {
9752
- console.error("Failed to get database config:", error);
9753
- return {
9754
- success: false,
9755
- message: "Failed to retrieve database configuration"
9756
- };
9757
- }
9758
- }
9759
- async function createDatabaseConfig(request, reply) {
9760
- const tenantId = getTenantId9(request);
9761
- const body = request.body;
9762
- try {
9763
- const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
9764
- const store2 = storeLattice.store;
9765
- const existing = await store2.getConfigByKey(tenantId, body.key);
9766
- if (existing) {
9767
- reply.code(409);
9768
- return {
9769
- success: false,
9770
- message: "Database configuration with this key already exists"
9771
- };
9960
+ if (project.kind === "public") {
9961
+ return this.requirePublicProjectAccess(project, input);
9772
9962
  }
9773
- const id3 = body.id || (0, import_crypto5.randomUUID)();
9774
- const config = await store2.createConfig(tenantId, id3, body);
9963
+ const membership = await this.deps.membershipStore.findByUser(
9964
+ input.tenantId,
9965
+ input.projectId,
9966
+ input.userId
9967
+ );
9968
+ if (membership?.status === "active") {
9969
+ this.requireCapability(membership, input.capability);
9970
+ return { project, membership };
9971
+ }
9972
+ const memberships = await this.deps.membershipStore.list(input.tenantId, input.projectId);
9973
+ if (memberships.length !== 0) this.accessDenied();
9974
+ if (project.kind === "personal") this.accessDenied();
9975
+ const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
9976
+ if (tenantLink?.role !== "owner" && tenantLink?.role !== "admin") this.accessDenied();
9977
+ let claim;
9775
9978
  try {
9776
- import_core27.sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
9979
+ claim = await this.deps.membershipStore.createInitialOwner({
9980
+ id: this.idFactory(),
9981
+ tenantId: input.tenantId,
9982
+ projectId: input.projectId,
9983
+ userId: input.userId
9984
+ });
9777
9985
  } catch (error) {
9778
- console.warn("Failed to auto-register database:", error);
9779
- }
9780
- reply.code(201);
9781
- return {
9782
- success: true,
9783
- message: "Database configuration created successfully",
9784
- data: config
9785
- };
9786
- } catch (error) {
9787
- console.error("Failed to create database config:", error);
9788
- return {
9789
- success: false,
9790
- message: "Failed to create database configuration"
9791
- };
9792
- }
9793
- }
9794
- async function updateDatabaseConfig(request, reply) {
9795
- const tenantId = getTenantId9(request);
9796
- const { key } = request.params;
9797
- const updates = request.body;
9798
- try {
9799
- const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
9800
- const store2 = storeLattice.store;
9801
- const existing = await store2.getConfigByKey(tenantId, key);
9802
- if (!existing) {
9803
- reply.code(404);
9804
- return {
9805
- success: false,
9806
- message: "Database configuration not found"
9807
- };
9808
- }
9809
- const updated = await store2.updateConfig(tenantId, existing.id, updates);
9810
- if (!updated) {
9811
- return {
9812
- success: false,
9813
- message: "Failed to update database configuration"
9814
- };
9815
- }
9816
- if (updates.config) {
9817
- try {
9818
- import_core27.sqlDatabaseManager.registerDatabase(tenantId, updated.key, updated.config);
9819
- } catch (error) {
9820
- console.warn("Failed to re-register database:", error);
9986
+ if (isProjectMembershipConflict(error)) {
9987
+ throw new ProjectCollaborationError(
9988
+ "PROJECT_MEMBERSHIP_CONFLICT",
9989
+ 409,
9990
+ "Project membership could not be initialized"
9991
+ );
9821
9992
  }
9993
+ throw error;
9822
9994
  }
9823
- return {
9995
+ if (claim.kind === "created" || claim.kind === "existing") {
9996
+ return { project, membership: claim.membership };
9997
+ }
9998
+ const racedMembership = await this.deps.membershipStore.findByUser(
9999
+ input.tenantId,
10000
+ input.projectId,
10001
+ input.userId
10002
+ );
10003
+ if (racedMembership?.status !== "active") this.accessDenied();
10004
+ this.requireCapability(racedMembership, input.capability);
10005
+ return { project, membership: racedMembership };
10006
+ }
10007
+ /** Authorizes an already-existing membership, or any tenant member for public rooms; never mutates persistence. */
10008
+ async requireExistingProjectAccess(input) {
10009
+ const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
10010
+ if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
10011
+ if (project.kind === "public") {
10012
+ return this.requireExistingPublicProjectAccess(project, input);
10013
+ }
10014
+ const membership = await this.deps.membershipStore.findByUser(
10015
+ input.tenantId,
10016
+ input.projectId,
10017
+ input.userId
10018
+ );
10019
+ if (!membership || membership.tenantId !== input.tenantId || membership.projectId !== input.projectId || membership.userId !== input.userId || membership.status !== "active") this.accessDenied();
10020
+ this.requireCapability(membership, input.capability);
10021
+ return { project, membership };
10022
+ }
10023
+ /** Authorizes roster visibility: read for public rooms, manage elsewhere. */
10024
+ async requireRosterAccess(input) {
10025
+ const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
10026
+ if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
10027
+ return this.requireProjectAccess({
10028
+ ...input,
10029
+ capability: project.kind === "public" ? "read" : "manage"
10030
+ });
10031
+ }
10032
+ async requirePublicProjectAccess(project, input) {
10033
+ const membership = await this.deps.membershipStore.findByUser(
10034
+ input.tenantId,
10035
+ input.projectId,
10036
+ input.userId
10037
+ );
10038
+ if (membership?.status === "active") {
10039
+ this.requireCapability(membership, input.capability);
10040
+ return { project, membership };
10041
+ }
10042
+ const materialized = await this.materializePublicMembership(input);
10043
+ this.requireCapability(materialized, input.capability);
10044
+ return { project, membership: materialized };
10045
+ }
10046
+ async requireExistingPublicProjectAccess(project, input) {
10047
+ const membership = await this.deps.membershipStore.findByUser(
10048
+ input.tenantId,
10049
+ input.projectId,
10050
+ input.userId
10051
+ );
10052
+ if (membership?.status === "active") {
10053
+ this.requireCapability(membership, input.capability);
10054
+ return { project, membership };
10055
+ }
10056
+ if (membership) this.accessDenied();
10057
+ const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
10058
+ if (!tenantLink) this.accessDenied();
10059
+ const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
10060
+ const synthetic = {
10061
+ id: `public:${input.userId}`,
10062
+ tenantId: input.tenantId,
10063
+ projectId: input.projectId,
10064
+ userId: input.userId,
10065
+ role,
10066
+ status: "active",
10067
+ joinedAt: project.createdAt,
10068
+ updatedAt: project.updatedAt
10069
+ };
10070
+ this.requireCapability(synthetic, input.capability);
10071
+ return { project, membership: synthetic };
10072
+ }
10073
+ async materializePublicMembership(input) {
10074
+ const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
10075
+ if (!tenantLink) this.accessDenied();
10076
+ const existing = await this.deps.membershipStore.findByUser(
10077
+ input.tenantId,
10078
+ input.projectId,
10079
+ input.userId
10080
+ );
10081
+ if (existing) this.accessDenied();
10082
+ const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
10083
+ try {
10084
+ return await this.deps.membershipStore.create({
10085
+ id: this.idFactory(),
10086
+ tenantId: input.tenantId,
10087
+ projectId: input.projectId,
10088
+ userId: input.userId,
10089
+ role,
10090
+ status: "active"
10091
+ });
10092
+ } catch (error) {
10093
+ if (isProjectMembershipConflict(error)) {
10094
+ const raced = await this.deps.membershipStore.findByUser(
10095
+ input.tenantId,
10096
+ input.projectId,
10097
+ input.userId
10098
+ );
10099
+ if (raced?.status === "active") return raced;
10100
+ }
10101
+ throw error;
10102
+ }
10103
+ }
10104
+ requireCapability(membership, capability2) {
10105
+ if (!allowedRoles[capability2].has(membership.role)) this.accessDenied();
10106
+ }
10107
+ accessDenied() {
10108
+ throw new ProjectCollaborationError("PROJECT_ACCESS_DENIED", 403, "Project access denied");
10109
+ }
10110
+ };
10111
+
10112
+ // src/controllers/database-configs.ts
10113
+ var import_core27 = require("@axiom-lattice/core");
10114
+ var import_crypto5 = require("crypto");
10115
+ function getTenantId9(request) {
10116
+ const userTenantId = request.user?.tenantId;
10117
+ if (userTenantId) {
10118
+ return userTenantId;
10119
+ }
10120
+ return request.headers["x-tenant-id"] || "default";
10121
+ }
10122
+ async function getDatabaseConfigList(request, reply) {
10123
+ const tenantId = getTenantId9(request);
10124
+ try {
10125
+ const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
10126
+ const store2 = storeLattice.store;
10127
+ const configs = await store2.getAllConfigs(tenantId);
10128
+ console.log("Backend: getAllConfigs returned:", configs);
10129
+ if (configs.length > 0) {
10130
+ console.log("Backend: First config key:", configs[0].key);
10131
+ }
10132
+ return {
10133
+ success: true,
10134
+ message: "Database configurations retrieved successfully",
10135
+ data: {
10136
+ records: configs,
10137
+ total: configs.length
10138
+ }
10139
+ };
10140
+ } catch (error) {
10141
+ console.error("Failed to get database configs:", error);
10142
+ return {
10143
+ success: false,
10144
+ message: "Failed to retrieve database configurations",
10145
+ data: {
10146
+ records: [],
10147
+ total: 0
10148
+ }
10149
+ };
10150
+ }
10151
+ }
10152
+ async function getDatabaseConfig(request, reply) {
10153
+ const tenantId = getTenantId9(request);
10154
+ const { key } = request.params;
10155
+ try {
10156
+ const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
10157
+ const store2 = storeLattice.store;
10158
+ const config = await store2.getConfigByKey(tenantId, key);
10159
+ if (!config) {
10160
+ return {
10161
+ success: false,
10162
+ message: "Database configuration not found"
10163
+ };
10164
+ }
10165
+ return {
10166
+ success: true,
10167
+ message: "Database configuration retrieved successfully",
10168
+ data: config
10169
+ };
10170
+ } catch (error) {
10171
+ console.error("Failed to get database config:", error);
10172
+ return {
10173
+ success: false,
10174
+ message: "Failed to retrieve database configuration"
10175
+ };
10176
+ }
10177
+ }
10178
+ async function createDatabaseConfig(request, reply) {
10179
+ const tenantId = getTenantId9(request);
10180
+ const body = request.body;
10181
+ try {
10182
+ const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
10183
+ const store2 = storeLattice.store;
10184
+ const existing = await store2.getConfigByKey(tenantId, body.key);
10185
+ if (existing) {
10186
+ reply.code(409);
10187
+ return {
10188
+ success: false,
10189
+ message: "Database configuration with this key already exists"
10190
+ };
10191
+ }
10192
+ const id3 = body.id || (0, import_crypto5.randomUUID)();
10193
+ const config = await store2.createConfig(tenantId, id3, body);
10194
+ try {
10195
+ import_core27.sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
10196
+ } catch (error) {
10197
+ console.warn("Failed to auto-register database:", error);
10198
+ }
10199
+ reply.code(201);
10200
+ return {
10201
+ success: true,
10202
+ message: "Database configuration created successfully",
10203
+ data: config
10204
+ };
10205
+ } catch (error) {
10206
+ console.error("Failed to create database config:", error);
10207
+ return {
10208
+ success: false,
10209
+ message: "Failed to create database configuration"
10210
+ };
10211
+ }
10212
+ }
10213
+ async function updateDatabaseConfig(request, reply) {
10214
+ const tenantId = getTenantId9(request);
10215
+ const { key } = request.params;
10216
+ const updates = request.body;
10217
+ try {
10218
+ const storeLattice = (0, import_core27.getStoreLattice)("default", "database");
10219
+ const store2 = storeLattice.store;
10220
+ const existing = await store2.getConfigByKey(tenantId, key);
10221
+ if (!existing) {
10222
+ reply.code(404);
10223
+ return {
10224
+ success: false,
10225
+ message: "Database configuration not found"
10226
+ };
10227
+ }
10228
+ const updated = await store2.updateConfig(tenantId, existing.id, updates);
10229
+ if (!updated) {
10230
+ return {
10231
+ success: false,
10232
+ message: "Failed to update database configuration"
10233
+ };
10234
+ }
10235
+ if (updates.config) {
10236
+ try {
10237
+ import_core27.sqlDatabaseManager.registerDatabase(tenantId, updated.key, updated.config);
10238
+ } catch (error) {
10239
+ console.warn("Failed to re-register database:", error);
10240
+ }
10241
+ }
10242
+ return {
9824
10243
  success: true,
9825
10244
  message: "Database configuration updated successfully",
9826
10245
  data: updated
@@ -11745,7 +12164,7 @@ function registerTenantRoutes(app2) {
11745
12164
  // src/controllers/auth.ts
11746
12165
  var import_core35 = require("@axiom-lattice/core");
11747
12166
  var import_uuid8 = require("uuid");
11748
- var import_node_crypto3 = require("crypto");
12167
+ var import_node_crypto4 = require("crypto");
11749
12168
  var defaultAuthConfig = {
11750
12169
  autoApproveUsers: true,
11751
12170
  allowTenantRegistration: true,
@@ -12100,7 +12519,7 @@ var AuthController = class {
12100
12519
  function resolveConsoleTokenSecret(_authRequired) {
12101
12520
  const configured = process.env.AUTH_TOKEN_SECRET || process.env.JWT_SECRET;
12102
12521
  if (configured) return configured;
12103
- devSessionSecret ?? (devSessionSecret = (0, import_node_crypto3.randomBytes)(32).toString("hex"));
12522
+ devSessionSecret ?? (devSessionSecret = (0, import_node_crypto4.randomBytes)(32).toString("hex"));
12104
12523
  console.warn(
12105
12524
  "[auth] AUTH_TOKEN_SECRET/JWT_SECRET is not set; using an in-process generated signing secret (sessions are invalidated on restart). Set AUTH_TOKEN_SECRET for production."
12106
12525
  );
@@ -12109,7 +12528,7 @@ function resolveConsoleTokenSecret(_authRequired) {
12109
12528
  var devSessionSecret;
12110
12529
  function createConsoleSessionToken(payload, secret) {
12111
12530
  const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
12112
- const signature = (0, import_node_crypto3.createHmac)("sha256", secret).update(encodedPayload).digest("base64url");
12531
+ const signature = (0, import_node_crypto4.createHmac)("sha256", secret).update(encodedPayload).digest("base64url");
12113
12532
  return `${encodedPayload}.${signature}`;
12114
12533
  }
12115
12534
  function isConsoleSessionPayload(value) {
@@ -12136,8 +12555,8 @@ function verifySignedConsoleSession(authHeader, secret) {
12136
12555
  try {
12137
12556
  const actualSignature = Buffer.from(encodedSignature, "base64url");
12138
12557
  if (actualSignature.toString("base64url") !== encodedSignature) return void 0;
12139
- const expectedSignature = (0, import_node_crypto3.createHmac)("sha256", secret).update(encodedPayload).digest();
12140
- if (actualSignature.length !== expectedSignature.length || !(0, import_node_crypto3.timingSafeEqual)(actualSignature, expectedSignature)) {
12558
+ const expectedSignature = (0, import_node_crypto4.createHmac)("sha256", secret).update(encodedPayload).digest();
12559
+ if (actualSignature.length !== expectedSignature.length || !(0, import_node_crypto4.timingSafeEqual)(actualSignature, expectedSignature)) {
12141
12560
  return void 0;
12142
12561
  }
12143
12562
  const payload = JSON.parse(
@@ -12167,13 +12586,13 @@ function isStaleConsoleSessionCredential(authHeader) {
12167
12586
  }
12168
12587
  }
12169
12588
  function bypassesConsoleAuth(request) {
12170
- const path6 = request.url.split("?")[0];
12589
+ const path7 = request.url.split("?")[0];
12171
12590
  const method = request.method;
12172
- if (method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/bootstrap$/.test(path6) || (method === "GET" || method === "POST") && /^\/api\/web-apps\/[^/]+\/runtime\/threads$/.test(path6) || (method === "PATCH" || method === "DELETE") && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+$/.test(path6) || method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/messages$/.test(path6) || method === "POST" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/(messages\/stream|abort|attachments)$/.test(path6) || method === "POST" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/interrupts\/[^/]+\/resume$/.test(path6)) return true;
12173
- if (request.method === "GET" && /^\/api\/a2a\/agents\/[^/]+\/\.well-known\/agent-card\.json$/.test(path6)) {
12591
+ if (method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/bootstrap$/.test(path7) || (method === "GET" || method === "POST") && /^\/api\/web-apps\/[^/]+\/runtime\/threads$/.test(path7) || (method === "PATCH" || method === "DELETE") && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+$/.test(path7) || method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/messages$/.test(path7) || method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/files\/(viewfile|downloadfile)$/.test(path7) || method === "GET" && /^\/api\/web-apps\/[^/]+\/runtime\/api\/assistants\/[^/]+\/threads\/[^/]+\/sandbox\/(viewfile|downloadfile)$/.test(path7) || method === "POST" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/(messages\/stream|abort|attachments)$/.test(path7) || method === "POST" && /^\/api\/web-apps\/[^/]+\/runtime\/threads\/[^/]+\/interrupts\/[^/]+\/resume$/.test(path7) || method === "GET" && /^\/api\/web-apps\/[^/]+\/chat$/.test(path7) || method === "GET" && /^\/embed\/[^/]+$/.test(path7) || (method === "POST" || method === "DELETE") && path7 === "/open/mcp") return true;
12592
+ if (request.method === "GET" && /^\/api\/a2a\/agents\/[^/]+\/\.well-known\/agent-card\.json$/.test(path7)) {
12174
12593
  return true;
12175
12594
  }
12176
- return request.method === "POST" && /^\/api\/a2a\/agents\/[^/]+\/jsonrpc$/.test(path6);
12595
+ return request.method === "POST" && /^\/api\/a2a\/agents\/[^/]+\/jsonrpc$/.test(path7);
12177
12596
  }
12178
12597
  function registerConsoleAuthHook(app2, options) {
12179
12598
  app2.addHook("preHandler", async (request, reply) => {
@@ -12196,8 +12615,8 @@ function registerConsoleAuthHook(app2, options) {
12196
12615
  }
12197
12616
  if (PUBLIC_ROUTES.some((route) => request.url === route)) return;
12198
12617
  if (request.url.startsWith("/s/")) return;
12199
- const path6 = request.url.split("?")[0];
12200
- if (request.method === "GET" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/viewfile$/.test(path6) || request.method === "GET" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/downloadfile$/.test(path6) || request.method === "POST" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/uploadfile$/.test(path6) || path6.startsWith("/f/") || path6 === "/f") {
12618
+ const path7 = request.url.split("?")[0];
12619
+ if (request.method === "GET" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/viewfile$/.test(path7) || request.method === "GET" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/downloadfile$/.test(path7) || request.method === "POST" && /^\/api\/workspaces\/[^/]+\/projects\/[^/]+\/uploadfile$/.test(path7) || path7.startsWith("/f/") || path7 === "/f") {
12201
12620
  return;
12202
12621
  }
12203
12622
  await reply.status(401).send({
@@ -13323,8 +13742,8 @@ var log = {
13323
13742
  };
13324
13743
  var connections = /* @__PURE__ */ new Map();
13325
13744
  var pending = /* @__PURE__ */ new Map();
13326
- function getAgentIdFromPath(path6) {
13327
- const match = path6.match(/^\/api\/a2a\/bridge\/proxy\/([^/]+)/);
13745
+ function getAgentIdFromPath(path7) {
13746
+ const match = path7.match(/^\/api\/a2a\/bridge\/proxy\/([^/]+)/);
13328
13747
  return match ? match[1] : null;
13329
13748
  }
13330
13749
  function handleBridgeConnection(socket, _request) {
@@ -13718,7 +14137,7 @@ async function getLocalA2ATemplates(_request, reply) {
13718
14137
  }
13719
14138
 
13720
14139
  // src/routes/a2a-test-connection.ts
13721
- var import_node_crypto4 = require("crypto");
14140
+ var import_node_crypto5 = require("crypto");
13722
14141
  function describeTestConnectionError(error, agentCardUrl) {
13723
14142
  if (!(error instanceof Error)) {
13724
14143
  return `Failed to fetch agent card from ${agentCardUrl}: ${String(error)}`;
@@ -13758,7 +14177,7 @@ async function ensureLocalRuntimeForConnectionTest(localRuntime, agentCardUrl) {
13758
14177
  return { error: portValidation.error };
13759
14178
  }
13760
14179
  const state = await localA2AService.startProvider(
13761
- `test-${(0, import_node_crypto4.randomUUID)()}`,
14180
+ `test-${(0, import_node_crypto5.randomUUID)()}`,
13762
14181
  testRuntime
13763
14182
  );
13764
14183
  if (state.status === "running") return { runtimeId: state.runtimeId };
@@ -13835,193 +14254,6 @@ var import_core51 = require("@axiom-lattice/core");
13835
14254
  var import_protocols10 = require("@axiom-lattice/protocols");
13836
14255
  var import_core42 = require("@axiom-lattice/core");
13837
14256
 
13838
- // src/services/collaboration/ProjectAccessService.ts
13839
- var import_node_crypto5 = require("crypto");
13840
- var ProjectCollaborationError = class extends Error {
13841
- /** Creates a project collaboration error. */
13842
- constructor(code, statusCode, message) {
13843
- super(message);
13844
- this.code = code;
13845
- this.statusCode = statusCode;
13846
- this.name = "ProjectCollaborationError";
13847
- }
13848
- };
13849
- var allowedRoles = {
13850
- read: /* @__PURE__ */ new Set(["owner", "admin", "member", "viewer"]),
13851
- send: /* @__PURE__ */ new Set(["owner", "admin", "member"]),
13852
- manage: /* @__PURE__ */ new Set(["owner", "admin"])
13853
- };
13854
- var membershipConflictNames = /* @__PURE__ */ new Set([
13855
- "DuplicateProjectMembershipError",
13856
- "ProjectMembershipIdConflictError"
13857
- ]);
13858
- function isProjectMembershipConflict(error) {
13859
- return error instanceof Error && membershipConflictNames.has(error.name);
13860
- }
13861
- var ProjectAccessService = class {
13862
- /** Creates a project access service from explicitly injected stores. */
13863
- constructor(deps) {
13864
- this.deps = deps;
13865
- this.idFactory = deps.idFactory ?? import_node_crypto5.randomUUID;
13866
- }
13867
- /** Returns the project and active membership when the user has the requested capability. */
13868
- async requireProjectAccess(input) {
13869
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
13870
- if (!project) {
13871
- throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
13872
- }
13873
- if (project.kind === "public") {
13874
- return this.requirePublicProjectAccess(project, input);
13875
- }
13876
- const membership = await this.deps.membershipStore.findByUser(
13877
- input.tenantId,
13878
- input.projectId,
13879
- input.userId
13880
- );
13881
- if (membership?.status === "active") {
13882
- this.requireCapability(membership, input.capability);
13883
- return { project, membership };
13884
- }
13885
- const memberships = await this.deps.membershipStore.list(input.tenantId, input.projectId);
13886
- if (memberships.length !== 0) this.accessDenied();
13887
- if (project.kind === "personal") this.accessDenied();
13888
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
13889
- if (tenantLink?.role !== "owner" && tenantLink?.role !== "admin") this.accessDenied();
13890
- let claim;
13891
- try {
13892
- claim = await this.deps.membershipStore.createInitialOwner({
13893
- id: this.idFactory(),
13894
- tenantId: input.tenantId,
13895
- projectId: input.projectId,
13896
- userId: input.userId
13897
- });
13898
- } catch (error) {
13899
- if (isProjectMembershipConflict(error)) {
13900
- throw new ProjectCollaborationError(
13901
- "PROJECT_MEMBERSHIP_CONFLICT",
13902
- 409,
13903
- "Project membership could not be initialized"
13904
- );
13905
- }
13906
- throw error;
13907
- }
13908
- if (claim.kind === "created" || claim.kind === "existing") {
13909
- return { project, membership: claim.membership };
13910
- }
13911
- const racedMembership = await this.deps.membershipStore.findByUser(
13912
- input.tenantId,
13913
- input.projectId,
13914
- input.userId
13915
- );
13916
- if (racedMembership?.status !== "active") this.accessDenied();
13917
- this.requireCapability(racedMembership, input.capability);
13918
- return { project, membership: racedMembership };
13919
- }
13920
- /** Authorizes an already-existing membership, or any tenant member for public rooms; never mutates persistence. */
13921
- async requireExistingProjectAccess(input) {
13922
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
13923
- if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
13924
- if (project.kind === "public") {
13925
- return this.requireExistingPublicProjectAccess(project, input);
13926
- }
13927
- const membership = await this.deps.membershipStore.findByUser(
13928
- input.tenantId,
13929
- input.projectId,
13930
- input.userId
13931
- );
13932
- if (!membership || membership.tenantId !== input.tenantId || membership.projectId !== input.projectId || membership.userId !== input.userId || membership.status !== "active") this.accessDenied();
13933
- this.requireCapability(membership, input.capability);
13934
- return { project, membership };
13935
- }
13936
- /** Authorizes roster visibility: read for public rooms, manage elsewhere. */
13937
- async requireRosterAccess(input) {
13938
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
13939
- if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
13940
- return this.requireProjectAccess({
13941
- ...input,
13942
- capability: project.kind === "public" ? "read" : "manage"
13943
- });
13944
- }
13945
- async requirePublicProjectAccess(project, input) {
13946
- const membership = await this.deps.membershipStore.findByUser(
13947
- input.tenantId,
13948
- input.projectId,
13949
- input.userId
13950
- );
13951
- if (membership?.status === "active") {
13952
- this.requireCapability(membership, input.capability);
13953
- return { project, membership };
13954
- }
13955
- const materialized = await this.materializePublicMembership(input);
13956
- this.requireCapability(materialized, input.capability);
13957
- return { project, membership: materialized };
13958
- }
13959
- async requireExistingPublicProjectAccess(project, input) {
13960
- const membership = await this.deps.membershipStore.findByUser(
13961
- input.tenantId,
13962
- input.projectId,
13963
- input.userId
13964
- );
13965
- if (membership?.status === "active") {
13966
- this.requireCapability(membership, input.capability);
13967
- return { project, membership };
13968
- }
13969
- if (membership) this.accessDenied();
13970
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
13971
- if (!tenantLink) this.accessDenied();
13972
- const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
13973
- const synthetic = {
13974
- id: `public:${input.userId}`,
13975
- tenantId: input.tenantId,
13976
- projectId: input.projectId,
13977
- userId: input.userId,
13978
- role,
13979
- status: "active",
13980
- joinedAt: project.createdAt,
13981
- updatedAt: project.updatedAt
13982
- };
13983
- this.requireCapability(synthetic, input.capability);
13984
- return { project, membership: synthetic };
13985
- }
13986
- async materializePublicMembership(input) {
13987
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
13988
- if (!tenantLink) this.accessDenied();
13989
- const existing = await this.deps.membershipStore.findByUser(
13990
- input.tenantId,
13991
- input.projectId,
13992
- input.userId
13993
- );
13994
- if (existing) this.accessDenied();
13995
- const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
13996
- try {
13997
- return await this.deps.membershipStore.create({
13998
- id: this.idFactory(),
13999
- tenantId: input.tenantId,
14000
- projectId: input.projectId,
14001
- userId: input.userId,
14002
- role,
14003
- status: "active"
14004
- });
14005
- } catch (error) {
14006
- if (isProjectMembershipConflict(error)) {
14007
- const raced = await this.deps.membershipStore.findByUser(
14008
- input.tenantId,
14009
- input.projectId,
14010
- input.userId
14011
- );
14012
- if (raced?.status === "active") return raced;
14013
- }
14014
- throw error;
14015
- }
14016
- }
14017
- requireCapability(membership, capability2) {
14018
- if (!allowedRoles[capability2].has(membership.role)) this.accessDenied();
14019
- }
14020
- accessDenied() {
14021
- throw new ProjectCollaborationError("PROJECT_ACCESS_DENIED", 403, "Project access denied");
14022
- }
14023
- };
14024
-
14025
14257
  // src/services/collaboration/ProjectTaskThreadService.ts
14026
14258
  var import_core40 = require("@axiom-lattice/core");
14027
14259
  var import_protocols9 = require("@axiom-lattice/protocols");
@@ -14553,9 +14785,6 @@ function governedUpdate(task, body) {
14553
14785
  if (has("ownerType") && body.ownerType !== task.ownerType || has("ownerId") && body.ownerId !== task.ownerId) {
14554
14786
  return "TASK_OWNERSHIP_IMMUTABLE";
14555
14787
  }
14556
- if (task.ownerType !== "agent") return void 0;
14557
- if (has("parentId") && body.parentId !== task.parentId || has("dependencies") || has("requireReview") || has("result") || has("failureReason") || has("status")) return "TASK_LIFECYCLE_TRANSITION_REQUIRED";
14558
- if (has("context") || has("description")) return "COMPLETION_CONTEXT_MUTATION";
14559
14788
  return void 0;
14560
14789
  }
14561
14790
  function lifecycleStatus(code) {
@@ -14996,7 +15225,8 @@ var AgentWebAppService = class {
14996
15225
  integration: current.integration,
14997
15226
  scope: { ...current.scope, ...patch.scope },
14998
15227
  features: { ...current.features, ...patch.features },
14999
- appearance: { ...current.appearance, ...patch.appearance }
15228
+ appearance: { ...current.appearance, ...patch.appearance },
15229
+ identity: patch.identity ?? current.identity
15000
15230
  };
15001
15231
  await this.validateAssistant(context, current.assistantId);
15002
15232
  const validated = await this.validateConfig(context.tenantId, effective);
@@ -15005,7 +15235,8 @@ var AgentWebAppService = class {
15005
15235
  ...Object.prototype.hasOwnProperty.call(patch, "description") ? { description: validated.description } : {},
15006
15236
  ...patch.scope ? { scope: validated.scope } : {},
15007
15237
  ...patch.features ? { features: validated.features } : {},
15008
- ...patch.appearance ? { appearance: validated.appearance } : {}
15238
+ ...patch.appearance ? { appearance: validated.appearance } : {},
15239
+ ...patch.identity !== void 0 ? { identity: patch.identity } : {}
15009
15240
  };
15010
15241
  return this.writeSnapshot(context, current, update);
15011
15242
  }
@@ -15118,13 +15349,28 @@ var agentWebAppFeaturesSchema = import_zod4.z.object({
15118
15349
  threadManagement: import_zod4.z.boolean(),
15119
15350
  attachments: import_zod4.z.boolean(),
15120
15351
  hitl: import_zod4.z.boolean(),
15121
- genUI: import_zod4.z.boolean()
15352
+ genUI: import_zod4.z.boolean(),
15353
+ files: import_zod4.z.boolean().optional()
15122
15354
  }).strict();
15123
15355
  var agentWebAppAppearanceSchema = import_zod4.z.object({
15124
15356
  title: import_zod4.z.string().max(120).optional(),
15125
15357
  welcomeMessage: import_zod4.z.string().max(1e3).optional(),
15126
15358
  primaryColor: import_zod4.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional()
15127
15359
  }).strict();
15360
+ var agentWebAppIssuerSchema = import_zod4.z.object({
15361
+ iss: import_zod4.z.string().min(1).max(255),
15362
+ aud: import_zod4.z.string().min(1).max(255),
15363
+ alg: import_zod4.z.enum(["HS256", "RS256"]),
15364
+ secret: import_zod4.z.string().min(1).max(512).optional(),
15365
+ jwksUrl: import_zod4.z.string().url().max(2048).optional()
15366
+ }).strict().refine(
15367
+ (value) => value.alg === "HS256" ? value.secret !== void 0 : value.jwksUrl !== void 0,
15368
+ { message: "HS256 requires secret; RS256 requires jwksUrl" }
15369
+ );
15370
+ var agentWebAppIdentitySchema = import_zod4.z.object({
15371
+ policy: import_zod4.z.enum(["unverified", "verified", "both"]),
15372
+ issuers: import_zod4.z.array(agentWebAppIssuerSchema).min(1).max(10)
15373
+ }).strict();
15128
15374
  var createAgentWebAppSchema = import_zod4.z.object({
15129
15375
  assistantId: externalId,
15130
15376
  name: import_zod4.z.string().min(1).max(120),
@@ -15132,14 +15378,16 @@ var createAgentWebAppSchema = import_zod4.z.object({
15132
15378
  integration: import_zod4.z.object({ type: import_zod4.z.literal("react_sdk") }).strict(),
15133
15379
  scope: agentWebAppScopeSchema,
15134
15380
  features: agentWebAppFeaturesSchema,
15135
- appearance: agentWebAppAppearanceSchema
15381
+ appearance: agentWebAppAppearanceSchema,
15382
+ identity: agentWebAppIdentitySchema.optional()
15136
15383
  }).strict();
15137
15384
  var updateAgentWebAppSchema = import_zod4.z.object({
15138
15385
  name: import_zod4.z.string().min(1).max(120).optional(),
15139
15386
  description: import_zod4.z.string().max(1e3).optional(),
15140
15387
  scope: agentWebAppScopeSchema.partial().strict().optional(),
15141
15388
  features: agentWebAppFeaturesSchema.partial().strict().optional(),
15142
- appearance: agentWebAppAppearanceSchema.partial().strict().optional()
15389
+ appearance: agentWebAppAppearanceSchema.partial().strict().optional(),
15390
+ identity: agentWebAppIdentitySchema.optional()
15143
15391
  }).strict().refine((value) => Object.keys(value).length > 0, "Patch must not be empty");
15144
15392
  var listAgentWebAppsQuerySchema = import_zod4.z.object({
15145
15393
  assistantId: externalId.optional()
@@ -15226,6 +15474,7 @@ function invalidRequest(reply, statusCode) {
15226
15474
  }
15227
15475
 
15228
15476
  // src/routes/agent-web-app-runtime.ts
15477
+ var import_node_crypto8 = require("crypto");
15229
15478
  var import_zod6 = require("zod");
15230
15479
 
15231
15480
  // src/services/agent-web-app/AgentWebAppRuntimeService.ts
@@ -15247,7 +15496,16 @@ var AgentWebAppRuntimeService = class {
15247
15496
  constructor(deps) {
15248
15497
  this.deps = deps;
15249
15498
  }
15250
- async bootstrap(webAppId, userId, selection) {
15499
+ /** Identity policy configuration for the web app, or null when the app is missing/unconfigured. */
15500
+ async getIdentityConfig(webAppId) {
15501
+ try {
15502
+ const runtime = await this.resolveRuntime(webAppId, {});
15503
+ return runtime.webApp.identity ?? null;
15504
+ } catch {
15505
+ return null;
15506
+ }
15507
+ }
15508
+ async bootstrap(webAppId, userId, selection, identity) {
15251
15509
  const runtime = await this.resolveRuntime(webAppId, selection);
15252
15510
  const assistant = await this.deps.assistantResolver.resolve(
15253
15511
  runtime.webApp.tenantId,
@@ -15280,7 +15538,7 @@ var AgentWebAppRuntimeService = class {
15280
15538
  defaultModelKey: runtime.webApp.scope.defaultModelKey,
15281
15539
  features: runtime.webApp.features,
15282
15540
  appearance: runtime.webApp.appearance,
15283
- identityAssurance: "unverified"
15541
+ identityAssurance: identity?.assurance ?? "unverified"
15284
15542
  },
15285
15543
  projects,
15286
15544
  models
@@ -15301,6 +15559,14 @@ var AgentWebAppRuntimeService = class {
15301
15559
  this.requireFeature(runtime.webApp.features.threadManagement);
15302
15560
  return this.createOwnedThread(runtime, userId, input.label);
15303
15561
  }
15562
+ /** Fetch one owned thread. */
15563
+ async getThread(webAppId, userId, threadId, selection) {
15564
+ const runtime = await this.resolveRuntime(webAppId, selection);
15565
+ await this.requireOwnedThread(runtime, userId, threadId);
15566
+ const thread = await this.deps.threadStore.getThreadById(runtime.webApp.tenantId, threadId);
15567
+ if (!thread) this.threadNotFound();
15568
+ return toRuntimeThread(thread);
15569
+ }
15304
15570
  /** Update a thread label; omitted or blank labels preserve the existing label. */
15305
15571
  async updateThread(webAppId, userId, threadId, input) {
15306
15572
  const runtime = await this.resolveRuntime(webAppId, input);
@@ -15335,6 +15601,60 @@ var AgentWebAppRuntimeService = class {
15335
15601
  return [{ id: message.id, role: message.role, ...content && (typeof content === "string" || content.length > 0) ? { content } : {} }];
15336
15602
  });
15337
15603
  }
15604
+ async getState(webAppId, userId, threadId, selection) {
15605
+ const runtime = await this.resolveRuntime(webAppId, selection);
15606
+ await this.requireOwnedThread(runtime, userId, threadId);
15607
+ const agent = this.resolveAgent(runtime, threadId);
15608
+ const state = await agent.getCurrentState();
15609
+ const pendingMessages = await agent.getPendingMessages();
15610
+ const normalized = pendingMessages.map((message) => ({
15611
+ ...message,
15612
+ content: typeof message.content === "object" && message.content !== null ? "message" in message.content ? message.content.message : JSON.stringify(message.content) : String(message.content ?? "")
15613
+ }));
15614
+ return { ...state && typeof state === "object" ? state : {}, pendingMessages: normalized };
15615
+ }
15616
+ /** Raw stored messages (Console memory contract, tool/interrupt preserved). */
15617
+ async getConsoleMessages(webAppId, userId, threadId, selection) {
15618
+ const runtime = await this.resolveRuntime(webAppId, selection);
15619
+ await this.requireOwnedThread(runtime, userId, threadId);
15620
+ return this.deps.messageReader.getCurrentMessages({
15621
+ tenantId: runtime.webApp.tenantId,
15622
+ assistantId: runtime.webApp.assistantId,
15623
+ threadId,
15624
+ workspaceId: runtime.project.workspaceId,
15625
+ projectId: runtime.project.id
15626
+ });
15627
+ }
15628
+ /** Background enqueue only (ADR-026): returns the message id; delivery happens over resume_stream. */
15629
+ async enqueueMessage(webAppId, userId, threadId, content, selection) {
15630
+ const runtime = await this.resolveOwnedRuntime(webAppId, userId, threadId, selection);
15631
+ const agent = this.resolveAgent(runtime, threadId);
15632
+ const execution = await this.execute(agent, runtime, { input: { message: content } });
15633
+ return { messageId: execution.messageId };
15634
+ }
15635
+ async removePendingMessage(webAppId, userId, threadId, messageId, selection) {
15636
+ const runtime = await this.resolveRuntime(webAppId, selection);
15637
+ await this.requireOwnedThread(runtime, userId, threadId);
15638
+ const agent = this.resolveAgent(runtime, threadId);
15639
+ if (!await agent.removePendingMessage(messageId)) this.threadNotFound();
15640
+ }
15641
+ /** Thread-lifetime SSE resume from the last known client message id. */
15642
+ async resumeStream(webAppId, userId, threadId, messageId, selection) {
15643
+ const runtime = await this.resolveRuntime(webAppId, selection);
15644
+ await this.requireOwnedThread(runtime, userId, threadId);
15645
+ const agent = this.resolveAgent(runtime, threadId);
15646
+ return { stream: agent.chunkStream(messageId, []) };
15647
+ }
15648
+ async resolveFileScope(webAppId, selection) {
15649
+ const runtime = await this.resolveRuntime(webAppId, selection);
15650
+ return {
15651
+ tenantId: runtime.webApp.tenantId,
15652
+ workspaceId: runtime.project.workspaceId,
15653
+ projectId: runtime.project.id,
15654
+ assistantId: runtime.webApp.assistantId,
15655
+ enabled: runtime.webApp.features.files === true
15656
+ };
15657
+ }
15338
15658
  async streamMessage(webAppId, userId, threadId, input) {
15339
15659
  const runtime = await this.resolveOwnedRuntime(webAppId, userId, threadId, input);
15340
15660
  const refs = this.resolveAttachmentRefs(runtime, userId, threadId, input.attachmentRefs ?? []);
@@ -15579,93 +15899,102 @@ function toRuntimeThread(thread) {
15579
15899
  };
15580
15900
  }
15581
15901
 
15582
- // src/services/agent-web-app/AgentWebAppStreamProjector.ts
15583
- var import_protocols12 = require("@axiom-lattice/protocols");
15584
- function createAgentWebAppStreamProjectionContext(options = {}) {
15585
- return { startedToolIds: /* @__PURE__ */ new Set(), allowInterrupts: options.allowInterrupts ?? true, allowGenUI: options.allowGenUI ?? false };
15902
+ // src/services/agent-web-app/AgentWebAppTokenVerifier.ts
15903
+ var import_node_crypto7 = require("crypto");
15904
+ var WebAppTokenError = class extends Error {
15905
+ constructor(message) {
15906
+ super(message);
15907
+ this.name = "WebAppTokenError";
15908
+ }
15909
+ };
15910
+ var MAX_TOKEN_BYTES = 8 * 1024;
15911
+ var CLOCK_SKEW_SECONDS = 60;
15912
+ var JWKS_TTL_MS = 10 * 60 * 1e3;
15913
+ var jwksCache = /* @__PURE__ */ new Map();
15914
+ function decodeSegment(segment) {
15915
+ const json = Buffer.from(segment, "base64url").toString("utf8");
15916
+ let value;
15917
+ try {
15918
+ value = JSON.parse(json);
15919
+ } catch {
15920
+ throw new WebAppTokenError("Malformed token segment");
15921
+ }
15922
+ if (typeof value !== "object" || value === null) throw new WebAppTokenError("Malformed token segment");
15923
+ return value;
15586
15924
  }
15587
- function projectAgentWebAppChunk(chunk, context) {
15588
- if (chunk.type === import_protocols12.MessageChunkTypes.AI) {
15589
- const events = [];
15590
- const startedToolIds = context?.startedToolIds ?? /* @__PURE__ */ new Set();
15591
- if (typeof chunk.data.content === "string" && chunk.data.content) events.push({ type: "message.delta", text: chunk.data.content });
15592
- if (context?.allowGenUI && Array.isArray(chunk.data.content)) {
15593
- for (const value of chunk.data.content) {
15594
- const block = (0, import_protocols12.parseAgentWebAppGenUIBlock)(value);
15595
- if (block) events.push({ type: "genui.render", block });
15596
- }
15597
- }
15598
- for (const call of chunk.data.tool_call_chunks ?? []) {
15599
- if (call.id && call.name && !startedToolIds.has(call.id)) {
15600
- startedToolIds.add(call.id);
15601
- events.push({ type: "tool.started", id: call.id, name: call.name });
15602
- }
15925
+ async function resolveKey(issuer, kid, fetchImpl) {
15926
+ const cacheKey = issuer.jwksUrl ?? "";
15927
+ const load = async () => {
15928
+ const response = await fetchImpl(issuer.jwksUrl ?? "");
15929
+ if (!response.ok) throw new WebAppTokenError("JWKS fetch failed");
15930
+ const document = await response.json();
15931
+ const keys2 = document.keys;
15932
+ const entry2 = { keys: Array.isArray(keys2) ? keys2 : [], fetchedAt: Date.now() };
15933
+ jwksCache.set(cacheKey, entry2);
15934
+ return entry2;
15935
+ };
15936
+ const cached = jwksCache.get(cacheKey);
15937
+ let entry = cached && Date.now() - cached.fetchedAt < JWKS_TTL_MS ? cached : await load();
15938
+ let jwk = entry.keys.find((key) => kid === void 0 ? true : key.kid === kid);
15939
+ if (!jwk && kid !== void 0) {
15940
+ entry = await load();
15941
+ jwk = entry.keys.find((key) => key.kid === kid);
15942
+ }
15943
+ if (!jwk) throw new WebAppTokenError("No matching JWKS key");
15944
+ return (0, import_node_crypto7.createPublicKey)({ key: jwk, format: "jwk" });
15945
+ }
15946
+ async function verifyWebAppToken(token, issuer, options = {}) {
15947
+ const nowMs = options.now ? options.now() : Date.now();
15948
+ const now = Math.floor(nowMs / 1e3);
15949
+ if (token.length === 0 || Buffer.byteLength(token) > MAX_TOKEN_BYTES) throw new WebAppTokenError("Token size invalid");
15950
+ const parts = token.split(".");
15951
+ if (parts.length !== 3) throw new WebAppTokenError("Token structure invalid");
15952
+ const [rawHeader, rawPayload, rawSignature] = parts;
15953
+ const header2 = decodeSegment(rawHeader);
15954
+ const payload = decodeSegment(rawPayload);
15955
+ if (header2.alg !== issuer.alg) throw new WebAppTokenError("Token algorithm mismatch");
15956
+ if (payload.iss !== issuer.iss) throw new WebAppTokenError("Token issuer mismatch");
15957
+ if (payload.aud !== issuer.aud) throw new WebAppTokenError("Token audience mismatch");
15958
+ const exp = typeof payload.exp === "number" ? payload.exp : void 0;
15959
+ if (exp === void 0 || exp + CLOCK_SKEW_SECONDS < now) throw new WebAppTokenError("Token expired");
15960
+ const nbf = typeof payload.nbf === "number" ? payload.nbf : void 0;
15961
+ if (nbf !== void 0 && nbf - CLOCK_SKEW_SECONDS > now) throw new WebAppTokenError("Token not yet valid");
15962
+ const signature = Buffer.from(rawSignature, "base64url");
15963
+ const data = Buffer.from(`${rawHeader}.${rawPayload}`);
15964
+ if (issuer.alg === "HS256") {
15965
+ if (typeof issuer.secret !== "string" || issuer.secret.length === 0) throw new WebAppTokenError("Issuer secret missing");
15966
+ const expected = (0, import_node_crypto7.createHmac)("sha256", issuer.secret).update(data).digest();
15967
+ if (signature.length !== expected.length || !(0, import_node_crypto7.timingSafeEqual)(signature, expected)) {
15968
+ throw new WebAppTokenError("Token signature invalid");
15603
15969
  }
15604
- for (const call of chunk.data.tool_calls ?? []) {
15605
- if (!startedToolIds.has(call.id)) {
15606
- startedToolIds.add(call.id);
15607
- events.push({ type: "tool.started", id: call.id, name: call.name });
15608
- }
15970
+ } else {
15971
+ if (typeof issuer.jwksUrl !== "string") throw new WebAppTokenError("Issuer JWKS URL missing");
15972
+ const key = await resolveKey(issuer, typeof header2.kid === "string" ? header2.kid : void 0, options.fetchImpl ?? fetch);
15973
+ let valid = false;
15974
+ try {
15975
+ valid = (0, import_node_crypto7.verify)("RSA-SHA256", data, key, signature);
15976
+ } catch {
15977
+ valid = false;
15609
15978
  }
15610
- return events;
15611
- }
15612
- if (chunk.type === import_protocols12.MessageChunkTypes.TOOL && chunk.data.tool_call_id) {
15613
- return [{ type: "tool.completed", id: chunk.data.tool_call_id }];
15979
+ if (!valid) throw new WebAppTokenError("Token signature invalid");
15614
15980
  }
15615
- if (chunk.type === import_protocols12.MessageChunkTypes.INTERRUPT) {
15616
- if (context && !context.allowInterrupts) return [{ type: "stream.completed" }];
15617
- const interrupt = publicInterrupt(chunk);
15618
- return interrupt ? [{ type: "interrupt.created", interrupt }, { type: "stream.completed" }] : [{ type: "stream.completed" }];
15619
- }
15620
- if (chunk.type === import_protocols12.MessageChunkTypes.MESSAGE_COMPLETED) {
15621
- return [
15622
- { type: "message.completed", messageId: chunk.data.id },
15623
- { type: "stream.completed" }
15624
- ];
15981
+ const sub = payload.sub;
15982
+ if (typeof sub !== "string" || sub.length === 0 || sub.length > 128 || !/^[A-Za-z0-9._:@-]+$/.test(sub)) {
15983
+ throw new WebAppTokenError("Token subject invalid");
15625
15984
  }
15626
- if (chunk.type === import_protocols12.MessageChunkTypes.MESSAGE_FAILED) {
15627
- return [
15628
- { type: "error", error: { code: "STREAM_FAILED", message: "Stream failed", retryable: true } },
15629
- { type: "stream.completed" }
15630
- ];
15631
- }
15632
- return [];
15633
- }
15634
- function publicInterrupt(chunk) {
15635
- const value = parseInterruptContent(chunk.data.content);
15636
- if (!value) return void 0;
15637
- const topLevelId = chunk.id;
15638
- const id3 = typeof topLevelId === "string" ? topLevelId : chunk.data.id;
15639
- if (!id3) return void 0;
15640
- return {
15641
- id: id3,
15642
- type: typeof value.type === "string" ? value.type : "input",
15643
- prompt: typeof value.prompt === "string" ? value.prompt : typeof value.message === "string" ? value.message : "Input required",
15644
- ...isRecord3(value.data) ? { data: value.data } : {}
15645
- };
15646
- }
15647
- function parseInterruptContent(content) {
15648
- if (!content) return {};
15649
- if (isRecord3(content)) return content;
15650
- if (typeof content !== "string") return void 0;
15651
- try {
15652
- const parsed = JSON.parse(content);
15653
- return isRecord3(parsed) ? parsed : { prompt: content };
15654
- } catch {
15655
- return { prompt: content };
15656
- }
15657
- }
15658
- function isRecord3(value) {
15659
- return typeof value === "object" && value !== null && !Array.isArray(value);
15985
+ return sub;
15660
15986
  }
15661
15987
 
15662
15988
  // src/routes/agent-web-app-runtime.ts
15989
+ var import_protocols12 = require("@axiom-lattice/protocols");
15663
15990
  var idSchema = import_zod6.z.string().min(1).max(128);
15664
15991
  var paramsSchema = import_zod6.z.object({ webAppId: idSchema }).strict();
15665
15992
  var threadParamsSchema = import_zod6.z.object({ webAppId: idSchema, threadId: idSchema }).strict();
15666
15993
  var interruptParamsSchema = import_zod6.z.object({ webAppId: idSchema, threadId: idSchema, interruptId: idSchema }).strict();
15994
+ var pendingMessageParamsSchema = import_zod6.z.object({ webAppId: idSchema, threadId: idSchema, messageId: idSchema }).strict();
15667
15995
  var bootstrapQuerySchema = import_zod6.z.object({ projectId: idSchema.optional(), modelKey: idSchema.optional() }).strict();
15668
15996
  var projectQuerySchema = import_zod6.z.object({ projectId: idSchema.optional() }).strict();
15997
+ var projectQueryLenientSchema = projectQuerySchema.passthrough();
15669
15998
  var threadBodySchema = import_zod6.z.object({ projectId: idSchema.optional(), label: import_zod6.z.string().max(128).optional() }).strict();
15670
15999
  var streamBodySchema = import_zod6.z.object({
15671
16000
  content: import_zod6.z.string().trim().min(1).max(32768),
@@ -15684,8 +16013,27 @@ var resumeBodySchema = import_zod6.z.object({
15684
16013
  ])
15685
16014
  }).strict();
15686
16015
  var MAX_ATTACHMENT_BYTES = 10 * 1024 * 1024;
16016
+ var stateQuerySchema = import_zod6.z.object({
16017
+ threadId: idSchema,
16018
+ projectId: idSchema.optional(),
16019
+ modelKey: idSchema.optional()
16020
+ }).strict();
16021
+ var resumeSchema = import_zod6.z.object({
16022
+ messageId: idSchema,
16023
+ projectId: idSchema.optional(),
16024
+ modelKey: idSchema.optional()
16025
+ }).strict();
16026
+ var devTokenSchema = import_zod6.z.object({
16027
+ iss: import_zod6.z.string().min(1).max(255).optional(),
16028
+ sub: import_zod6.z.string().regex(/^[A-Za-z0-9._:@-]+$/).max(128).optional(),
16029
+ hours: import_zod6.z.number().gt(0).max(720).optional()
16030
+ }).strict();
16031
+ var fileQuerySchema = import_zod6.z.object({
16032
+ projectId: idSchema.optional(),
16033
+ modelKey: idSchema.optional()
16034
+ }).passthrough();
15687
16035
  function createExternalHeaderIdentityResolver() {
15688
- return { resolve(request) {
16036
+ return { async resolve(request) {
15689
16037
  const raw = request.headers["x-axiom-external-user-id"];
15690
16038
  if (raw === void 0) throw new AgentWebAppRuntimeError("USER_ID_REQUIRED", 401, "External user id is required");
15691
16039
  if (Array.isArray(raw) || typeof raw !== "string") throw new AgentWebAppRuntimeError("INVALID_USER_ID", 400, "External user id is invalid");
@@ -15694,47 +16042,109 @@ function createExternalHeaderIdentityResolver() {
15694
16042
  return { userId, assurance: "unverified" };
15695
16043
  } };
15696
16044
  }
16045
+ function createWebAppIdentityResolver(deps) {
16046
+ const headerResolver = createExternalHeaderIdentityResolver();
16047
+ return {
16048
+ async resolve(request, webAppId) {
16049
+ let config;
16050
+ try {
16051
+ config = await deps.getIdentityConfig(webAppId);
16052
+ } catch {
16053
+ config = void 0;
16054
+ }
16055
+ const policy = config?.policy ?? "unverified";
16056
+ const authHeader = request.headers.authorization;
16057
+ const bearer = typeof authHeader === "string" && authHeader.startsWith("Bearer ") ? authHeader.slice(7).trim() : void 0;
16058
+ if (policy !== "unverified" && bearer !== void 0) {
16059
+ const issuers = config?.issuers ?? [];
16060
+ if (issuers.length === 0) throw new AgentWebAppRuntimeError("INVALID_REQUEST", 401, "No trusted issuer configured");
16061
+ let lastError = new AgentWebAppRuntimeError("INVALID_REQUEST", 401, "Invalid identity token");
16062
+ for (const issuer of issuers) {
16063
+ try {
16064
+ const sub = await verifyWebAppToken(bearer, issuer);
16065
+ return { userId: sub, assurance: "verified" };
16066
+ } catch (error) {
16067
+ if (error instanceof WebAppTokenError) {
16068
+ lastError = error;
16069
+ continue;
16070
+ }
16071
+ throw error;
16072
+ }
16073
+ }
16074
+ const message = lastError instanceof WebAppTokenError ? `Invalid identity token: ${lastError.message}` : "Invalid identity token";
16075
+ throw new AgentWebAppRuntimeError("INVALID_REQUEST", 401, message);
16076
+ }
16077
+ if (policy === "verified") throw new AgentWebAppRuntimeError("USER_ID_REQUIRED", 401, "A verified identity token is required");
16078
+ return headerResolver.resolve(request, webAppId);
16079
+ }
16080
+ };
16081
+ }
15697
16082
  function registerAgentWebAppRuntimeRoutes(app2, deps) {
15698
- const identities = deps.identityResolver ?? createExternalHeaderIdentityResolver();
16083
+ const identities = deps.identityResolver ?? createWebAppIdentityResolver({ getIdentityConfig: (webAppId) => deps.service.getIdentityConfig(webAppId) });
15699
16084
  app2.register(async (routes) => {
15700
16085
  routes.setErrorHandler((error, _request, reply) => normalizeError2(reply, error));
15701
16086
  routes.get("/api/web-apps/:webAppId/runtime/bootstrap", async (request, reply) => handle2(reply, async () => {
15702
16087
  const { webAppId } = paramsSchema.parse(request.params);
15703
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
15704
- return { data: await deps.service.bootstrap(webAppId, identity.userId, withPreview(bootstrapQuerySchema.parse(request.query), identity.preview)) };
16088
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16089
+ return { data: await deps.service.bootstrap(webAppId, identity.userId, withPreview(bootstrapQuerySchema.parse(request.query), identity.preview), { assurance: identity.assurance ?? "unverified" }) };
15705
16090
  }));
15706
16091
  routes.get("/api/web-apps/:webAppId/runtime/threads", async (request, reply) => handle2(reply, async () => {
15707
16092
  const { webAppId } = paramsSchema.parse(request.params);
15708
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16093
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15709
16094
  const records = await deps.service.listThreads(webAppId, identity.userId, withPreview(projectQuerySchema.parse(request.query), identity.preview));
15710
16095
  return { data: { records, total: records.length } };
15711
16096
  }));
15712
16097
  routes.post("/api/web-apps/:webAppId/runtime/threads", async (request, reply) => handle2(reply, async () => {
15713
16098
  const { webAppId } = paramsSchema.parse(request.params);
15714
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16099
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15715
16100
  return { statusCode: 201, data: await deps.service.createThread(webAppId, identity.userId, withPreview(threadBodySchema.parse(request.body), identity.preview)) };
15716
16101
  }));
15717
16102
  routes.patch("/api/web-apps/:webAppId/runtime/threads/:threadId", async (request, reply) => handle2(reply, async () => {
15718
16103
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15719
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16104
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15720
16105
  return { data: await deps.service.updateThread(webAppId, identity.userId, threadId, withPreview(threadBodySchema.parse(request.body), identity.preview)) };
15721
16106
  }));
15722
16107
  routes.delete("/api/web-apps/:webAppId/runtime/threads/:threadId", async (request, reply) => handle2(reply, async () => {
15723
16108
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15724
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16109
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15725
16110
  await deps.service.deleteThread(webAppId, identity.userId, threadId, withPreview(projectQuerySchema.parse(request.query), identity.preview));
15726
16111
  return { data: { id: threadId } };
15727
16112
  }));
15728
16113
  routes.get("/api/web-apps/:webAppId/runtime/threads/:threadId/messages", async (request, reply) => handle2(reply, async () => {
15729
16114
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15730
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16115
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15731
16116
  const messages = await deps.service.getMessages(webAppId, identity.userId, threadId, withPreview(projectQuerySchema.parse(request.query), identity.preview));
15732
16117
  return { data: { messages } };
15733
16118
  }));
16119
+ routes.get("/api/web-apps/:webAppId/runtime/state", async (request, reply) => handle2(reply, async () => {
16120
+ const { webAppId } = paramsSchema.parse(request.params);
16121
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16122
+ const { threadId, projectId, modelKey: modelKey2 } = stateQuerySchema.parse(request.query);
16123
+ const state = await deps.service.getState(webAppId, identity.userId, threadId, withPreview({ projectId, modelKey: modelKey2 }, identity.preview));
16124
+ return { data: state };
16125
+ }));
16126
+ routes.delete("/api/web-apps/:webAppId/runtime/threads/:threadId/pending-messages/:messageId", async (request, reply) => handle2(reply, async () => {
16127
+ const { webAppId, threadId, messageId } = pendingMessageParamsSchema.parse(request.params);
16128
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16129
+ await deps.service.removePendingMessage(webAppId, identity.userId, threadId, messageId, withPreview(projectQuerySchema.parse(request.query), identity.preview));
16130
+ return { data: { removed: true } };
16131
+ }));
15734
16132
  routes.post("/api/web-apps/:webAppId/runtime/threads/:threadId/messages/stream", async (request, reply) => {
15735
16133
  try {
15736
16134
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15737
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16135
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16136
+ const input = streamBodySchema.parse(request.body);
16137
+ const result = await deps.service.streamMessage(webAppId, identity.userId, threadId, withPreview(input, identity.preview));
16138
+ beginSse(reply);
16139
+ await pipeNativeWebAppStream(reply.raw, result.stream);
16140
+ } catch (error) {
16141
+ return normalizeError2(reply, error);
16142
+ }
16143
+ });
16144
+ routes.post("/api/web-apps/:webAppId/runtime/v1/threads/:threadId/messages/stream", async (request, reply) => {
16145
+ try {
16146
+ const { webAppId, threadId } = threadParamsSchema.parse(request.params);
16147
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15738
16148
  const input = streamBodySchema.parse(request.body);
15739
16149
  const result = await deps.service.streamMessage(webAppId, identity.userId, threadId, withPreview(input, identity.preview));
15740
16150
  beginSse(reply);
@@ -15743,15 +16153,27 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
15743
16153
  return normalizeError2(reply, error);
15744
16154
  }
15745
16155
  });
16156
+ routes.post("/api/web-apps/:webAppId/runtime/threads/:threadId/resume", async (request, reply) => {
16157
+ try {
16158
+ const { webAppId, threadId } = threadParamsSchema.parse(request.params);
16159
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16160
+ const { messageId, projectId, modelKey: modelKey2 } = resumeSchema.parse(request.body);
16161
+ const result = await deps.service.resumeStream(webAppId, identity.userId, threadId, messageId, withPreview({ projectId, modelKey: modelKey2 }, identity.preview));
16162
+ beginSse(reply);
16163
+ await pipeNativeWebAppStream(reply.raw, result.stream);
16164
+ } catch (error) {
16165
+ return normalizeError2(reply, error);
16166
+ }
16167
+ });
15746
16168
  routes.post("/api/web-apps/:webAppId/runtime/threads/:threadId/abort", async (request, reply) => handle2(reply, async () => {
15747
16169
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15748
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16170
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15749
16171
  await deps.service.abort(webAppId, identity.userId, threadId, withPreview(projectQuerySchema.parse(request.query), identity.preview));
15750
16172
  return { data: { aborted: true } };
15751
16173
  }));
15752
16174
  routes.post("/api/web-apps/:webAppId/runtime/threads/:threadId/attachments", async (request, reply) => handle2(reply, async () => {
15753
16175
  const { webAppId, threadId } = threadParamsSchema.parse(request.params);
15754
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16176
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15755
16177
  if (!request.isMultipart()) throw new import_zod6.ZodError([]);
15756
16178
  const part = await request.file({ limits: { files: 1, fileSize: MAX_ATTACHMENT_BYTES } });
15757
16179
  if (!part || !part.filename || part.filename.length > 255) throw new import_zod6.ZodError([]);
@@ -15767,7 +16189,7 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
15767
16189
  routes.post("/api/web-apps/:webAppId/runtime/threads/:threadId/interrupts/:interruptId/resume", async (request, reply) => {
15768
16190
  try {
15769
16191
  const { webAppId, threadId, interruptId } = interruptParamsSchema.parse(request.params);
15770
- const identity = resolveRuntimeIdentity(request, webAppId, identities);
16192
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
15771
16193
  const { projectId, modelKey: modelKey2, message, response } = resumeBodySchema.parse(request.body);
15772
16194
  const result = await deps.service.resumeInterrupt(webAppId, identity.userId, threadId, interruptId, withPreview({ projectId, modelKey: modelKey2 }, identity.preview), { message, response });
15773
16195
  beginSse(reply);
@@ -15776,34 +16198,294 @@ function registerAgentWebAppRuntimeRoutes(app2, deps) {
15776
16198
  return normalizeError2(reply, error);
15777
16199
  }
15778
16200
  });
16201
+ routes.post("/api/web-apps/:webAppId/dev/token", async (request, reply) => handle2(reply, async () => {
16202
+ if (process.env.WEB_APP_DEV_TOKEN_ENABLED !== "true") {
16203
+ throw new AgentWebAppRuntimeError("FEATURE_DISABLED", 403, "Dev token issuance is disabled (set WEB_APP_DEV_TOKEN_ENABLED=true)");
16204
+ }
16205
+ const { webAppId } = paramsSchema.parse(request.params);
16206
+ const { iss, sub, hours } = devTokenSchema.parse(request.body ?? {});
16207
+ const config = await deps.service.getIdentityConfig(webAppId);
16208
+ const issuer = (config?.issuers ?? []).find((entry) => entry.alg === "HS256" && (iss === void 0 || entry.iss === iss));
16209
+ if (!issuer || typeof issuer.secret !== "string") {
16210
+ throw new AgentWebAppRuntimeError("INVALID_REQUEST", 400, "Web app has no HS256 issuer configured");
16211
+ }
16212
+ const now = Math.floor(Date.now() / 1e3);
16213
+ const expiresIn = (hours ?? 24) * 3600;
16214
+ const subject = sub ?? "dev-user";
16215
+ const b64url = (input) => Buffer.from(input).toString("base64url");
16216
+ const body = `${b64url(JSON.stringify({ alg: "HS256", typ: "JWT" }))}.${b64url(JSON.stringify({ sub: subject, iss: issuer.iss, aud: issuer.aud, iat: now, exp: now + expiresIn }))}`;
16217
+ const token = `${body}.${(0, import_node_crypto8.createHmac)("sha256", issuer.secret).update(body).digest("base64url")}`;
16218
+ return { data: { token, tokenType: "Bearer", expiresIn, subject } };
16219
+ }));
16220
+ if (deps.taskController) {
16221
+ const tasks = deps.taskController;
16222
+ const withSubject = (handler) => async (request, reply) => {
16223
+ const { webAppId } = paramsSchema.parse(request.params);
16224
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16225
+ const proxy = Object.create(request);
16226
+ proxy.headers = { ...request.headers, "x-user-id": identity.userId };
16227
+ return handler(proxy, reply);
16228
+ };
16229
+ routes.get("/api/web-apps/:webAppId/runtime/tasks", withSubject((request, reply) => tasks.list(request, reply)));
16230
+ routes.post("/api/web-apps/:webAppId/runtime/tasks", withSubject((request, reply) => tasks.create(request, reply)));
16231
+ routes.get("/api/web-apps/:webAppId/runtime/tasks/:taskId", withSubject((request, reply) => tasks.get(request, reply)));
16232
+ routes.put("/api/web-apps/:webAppId/runtime/tasks/:taskId", withSubject((request, reply) => tasks.update(request, reply)));
16233
+ routes.patch("/api/web-apps/:webAppId/runtime/tasks/:taskId", withSubject((request, reply) => tasks.update(request, reply)));
16234
+ routes.delete("/api/web-apps/:webAppId/runtime/tasks/:taskId", withSubject((request, reply) => tasks.remove(request, reply)));
16235
+ routes.patch("/api/web-apps/:webAppId/runtime/tasks/:taskId/complete", withSubject((request, reply) => tasks.complete(request, reply)));
16236
+ routes.get("/api/web-apps/:webAppId/runtime/tasks/:taskId/work-items", withSubject((request, reply) => tasks.workItems(request, reply)));
16237
+ }
16238
+ if (deps.workspaceController) {
16239
+ const workspace = deps.workspaceController;
16240
+ const fileScope = async (webAppId, selection) => {
16241
+ const scope = await deps.service.resolveFileScope(webAppId, selection);
16242
+ if (!scope.enabled) throw new AgentWebAppRuntimeError("FEATURE_DISABLED", 403, "Files are disabled for this web app");
16243
+ return scope;
16244
+ };
16245
+ const scopedRequest = (request, scope, params, query) => {
16246
+ const proxy = Object.create(request);
16247
+ proxy.params = params;
16248
+ proxy.query = query;
16249
+ proxy.headers = { ...request.headers, "x-tenant-id": scope.tenantId };
16250
+ return proxy;
16251
+ };
16252
+ const unwrap = (result) => ({ data: result.data });
16253
+ routes.get("/api/web-apps/:webAppId/runtime/files/listpath", async (request) => {
16254
+ const { webAppId } = paramsSchema.parse(request.params);
16255
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16256
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16257
+ const query = { ...request.query, assistantId: scope.assistantId };
16258
+ const result = await workspace.listPath(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query));
16259
+ return unwrap(result);
16260
+ });
16261
+ routes.get("/api/web-apps/:webAppId/runtime/files/readfile", async (request) => {
16262
+ const { webAppId } = paramsSchema.parse(request.params);
16263
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16264
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16265
+ const query = { ...request.query, assistantId: scope.assistantId };
16266
+ const result = await workspace.readFile(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query));
16267
+ return unwrap(result);
16268
+ });
16269
+ routes.post("/api/web-apps/:webAppId/runtime/files/uploadfile", async (request, reply) => {
16270
+ const { webAppId } = paramsSchema.parse(request.params);
16271
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16272
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16273
+ const scoped = scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, { assistantId: scope.assistantId });
16274
+ await workspace.uploadFile(scoped, reply);
16275
+ return reply;
16276
+ });
16277
+ routes.get("/api/web-apps/:webAppId/runtime/files/viewfile", async (request, reply) => {
16278
+ const { webAppId } = paramsSchema.parse(request.params);
16279
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16280
+ const query = { ...request.query, assistantId: scope.assistantId };
16281
+ await workspace.viewFile(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query), reply);
16282
+ return reply;
16283
+ });
16284
+ routes.get("/api/web-apps/:webAppId/runtime/files/downloadfile", async (request, reply) => {
16285
+ const { webAppId } = paramsSchema.parse(request.params);
16286
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16287
+ const query = { ...request.query, assistantId: scope.assistantId };
16288
+ await workspace.downloadFile(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query), reply);
16289
+ return reply;
16290
+ });
16291
+ routes.get("/api/web-apps/:webAppId/runtime/files/downloadfolder", async (request, reply) => {
16292
+ const { webAppId } = paramsSchema.parse(request.params);
16293
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16294
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16295
+ const query = { ...request.query, assistantId: scope.assistantId };
16296
+ await workspace.downloadFolder(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query), reply);
16297
+ return reply;
16298
+ });
16299
+ const genuiSandboxParams = import_zod6.z.object({ webAppId: idSchema, assistantId: idSchema, threadId: idSchema }).strict();
16300
+ const delegateGenuiFile = (method) => async (request, reply) => {
16301
+ const { webAppId } = genuiSandboxParams.parse(request.params);
16302
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16303
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16304
+ const query = { ...request.query, assistantId: scope.assistantId };
16305
+ await method(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query), reply);
16306
+ return reply;
16307
+ };
16308
+ routes.get("/api/web-apps/:webAppId/runtime/assistants/:assistantId/threads/:threadId/sandbox/downloadfile", delegateGenuiFile(workspace.downloadFile.bind(workspace)));
16309
+ routes.get("/api/web-apps/:webAppId/runtime/assistants/:assistantId/threads/:threadId/sandbox/viewfile", delegateGenuiFile(workspace.viewFile.bind(workspace)));
16310
+ const delegateAnonGenuiFile = (method) => async (request, reply) => {
16311
+ const { webAppId } = genuiSandboxParams.parse(request.params);
16312
+ const scope = await fileScope(webAppId, fileQuerySchema.parse(request.query));
16313
+ const query = { ...request.query, assistantId: scope.assistantId };
16314
+ await method(scopedRequest(request, scope, { workspaceId: scope.workspaceId, projectId: scope.projectId }, query), reply);
16315
+ return reply;
16316
+ };
16317
+ routes.get("/api/web-apps/:webAppId/runtime/api/assistants/:assistantId/threads/:threadId/sandbox/downloadfile", delegateAnonGenuiFile(workspace.downloadFile.bind(workspace)));
16318
+ routes.get("/api/web-apps/:webAppId/runtime/api/assistants/:assistantId/threads/:threadId/sandbox/viewfile", delegateAnonGenuiFile(workspace.viewFile.bind(workspace)));
16319
+ }
16320
+ const mirrorThreadParams = import_zod6.z.object({ webAppId: idSchema, assistantId: idSchema, threadId: idSchema }).strict();
16321
+ const mirrorBody = import_zod6.z.object({ metadata: import_zod6.z.object({ label: import_zod6.z.string().max(300).optional() }).strict().optional(), projectId: idSchema.optional(), modelKey: idSchema.optional() }).strict();
16322
+ const toConsoleThread = (thread, assistantId) => ({
16323
+ id: thread.id,
16324
+ assistantId,
16325
+ metadata: thread.label ? { label: thread.label } : {},
16326
+ createdAt: thread.createdAt,
16327
+ updatedAt: thread.updatedAt
16328
+ });
16329
+ const mirrorAssistantParams = import_zod6.z.object({ webAppId: idSchema, assistantId: idSchema }).strict();
16330
+ const mirrorPendingParams = import_zod6.z.object({ webAppId: idSchema, assistantId: idSchema, threadId: idSchema, messageId: idSchema }).strict();
16331
+ const registerMirror = (prefix) => {
16332
+ routes.get(`${prefix}/assistants/:assistantId/threads`, async (request, reply) => handle2(reply, async () => {
16333
+ const { webAppId, assistantId } = mirrorAssistantParams.parse(request.params);
16334
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16335
+ const threads = await deps.service.listThreads(webAppId, identity.userId, projectQueryLenientSchema.parse(request.query));
16336
+ return { data: { records: threads.map((thread) => toConsoleThread(thread, assistantId)) } };
16337
+ }));
16338
+ routes.post(`${prefix}/assistants/:assistantId/threads`, async (request, reply) => handle2(reply, async () => {
16339
+ const { webAppId, assistantId } = mirrorAssistantParams.parse(request.params);
16340
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16341
+ const body = mirrorBody.parse(request.body ?? {});
16342
+ const created = await deps.service.createThread(webAppId, identity.userId, { label: body.metadata?.label, ...body.projectId ? { projectId: body.projectId } : {} });
16343
+ return { statusCode: 201, data: { id: created.id } };
16344
+ }));
16345
+ routes.get(`${prefix}/assistants/:assistantId/threads/:threadId`, async (request, reply) => handle2(reply, async () => {
16346
+ const { webAppId, assistantId, threadId } = mirrorThreadParams.parse(request.params);
16347
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16348
+ const thread = await deps.service.getThread(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query));
16349
+ return { data: toConsoleThread(thread, assistantId) };
16350
+ }));
16351
+ routes.put(`${prefix}/assistants/:assistantId/threads/:threadId`, async (request, reply) => handle2(reply, async () => {
16352
+ const { webAppId, assistantId, threadId } = mirrorThreadParams.parse(request.params);
16353
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16354
+ const body = mirrorBody.parse(request.body ?? {});
16355
+ const updated = await deps.service.updateThread(webAppId, identity.userId, threadId, { label: body.metadata?.label, ...body.projectId ? { projectId: body.projectId } : {} });
16356
+ return { data: toConsoleThread(updated, assistantId) };
16357
+ }));
16358
+ routes.delete(`${prefix}/assistants/:assistantId/threads/:threadId`, async (request, reply) => handle2(reply, async () => {
16359
+ const { webAppId, threadId } = mirrorThreadParams.parse(request.params);
16360
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16361
+ await deps.service.deleteThread(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query));
16362
+ return { data: { success: true, message: "Thread deleted" } };
16363
+ }));
16364
+ routes.post(`${prefix}/assistants/:assistantId/threads/:threadId/sandbox/uploadfile`, async (request, reply) => handle2(reply, async () => {
16365
+ const { webAppId, threadId } = mirrorThreadParams.parse(request.params);
16366
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16367
+ if (!request.isMultipart()) throw new import_zod6.ZodError([]);
16368
+ const part = await request.file({ limits: { files: 1, fileSize: MAX_ATTACHMENT_BYTES } });
16369
+ if (!part || !part.filename || part.filename.length > 255) throw new import_zod6.ZodError([]);
16370
+ const bytes = await part.toBuffer();
16371
+ if (bytes.length === 0 || part.file.truncated) throw new import_zod6.ZodError([]);
16372
+ const uploaded = await deps.service.uploadAttachment(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query), {
16373
+ name: part.filename,
16374
+ mimeType: part.mimetype || "application/octet-stream",
16375
+ bytes
16376
+ });
16377
+ return { statusCode: 201, data: { id: uploaded.ref, path: uploaded.ref, name: uploaded.name, mimeType: uploaded.mimeType, size: uploaded.size } };
16378
+ }));
16379
+ routes.get(`${prefix}/assistants/:assistantId/:threadId/memory`, async (request) => {
16380
+ const { webAppId, threadId } = mirrorThreadParams.parse(request.params);
16381
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16382
+ const messages = await deps.service.getConsoleMessages(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query));
16383
+ return messages;
16384
+ });
16385
+ routes.get(`${prefix}/assistants/:assistantId/:threadId/state`, async (request) => {
16386
+ const { webAppId, threadId } = mirrorThreadParams.parse(request.params);
16387
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16388
+ return deps.service.getState(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query));
16389
+ });
16390
+ routes.delete(`${prefix}/assistants/:assistantId/threads/:threadId/pending-messages/:messageId`, async (request, reply) => handle2(reply, async () => {
16391
+ const { webAppId, threadId, messageId } = mirrorPendingParams.parse(request.params);
16392
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16393
+ await deps.service.removePendingMessage(webAppId, identity.userId, threadId, messageId, projectQueryLenientSchema.parse(request.query));
16394
+ return { data: { removed: true } };
16395
+ }));
16396
+ routes.post(`${prefix}/assistants/:assistantId/threads/:threadId/abort`, async (request, reply) => handle2(reply, async () => {
16397
+ const { webAppId, threadId } = mirrorThreadParams.parse(request.params);
16398
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16399
+ await deps.service.abort(webAppId, identity.userId, threadId, projectQueryLenientSchema.parse(request.query));
16400
+ return { data: { aborted: true } };
16401
+ }));
16402
+ const runsBodySchema = import_zod6.z.object({
16403
+ thread_id: idSchema.optional(),
16404
+ assistant_id: idSchema.optional(),
16405
+ messages: import_zod6.z.array(import_zod6.z.object({ content: import_zod6.z.string().min(1).max(32768) }).passthrough()).min(1).max(20),
16406
+ background: import_zod6.z.boolean().optional(),
16407
+ streaming: import_zod6.z.boolean().optional(),
16408
+ projectId: idSchema.optional(),
16409
+ modelKey: idSchema.optional()
16410
+ }).passthrough();
16411
+ routes.post(`${prefix}/runs`, async (request, reply) => {
16412
+ try {
16413
+ const { webAppId } = paramsSchema.parse(request.params);
16414
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16415
+ const body = runsBodySchema.parse(request.body ?? {});
16416
+ if (!body.background || body.streaming) {
16417
+ throw new AgentWebAppRuntimeError("INVALID_REQUEST", 400, "Mirror runs supports only background enqueue (stream via resume_stream)");
16418
+ }
16419
+ const threadId = body.thread_id ?? "";
16420
+ if (!threadId) throw new AgentWebAppRuntimeError("INVALID_REQUEST", 400, "thread_id is required");
16421
+ const content = body.messages.map((message) => message.content).join("\n");
16422
+ const { messageId } = await deps.service.enqueueMessage(webAppId, identity.userId, threadId, content, { projectId: body.projectId, modelKey: body.modelKey });
16423
+ return reply.code(202).send({ success: true, messageId, queued: true });
16424
+ } catch (error) {
16425
+ return normalizeError2(reply, error);
16426
+ }
16427
+ });
16428
+ const resumeStreamSchema2 = import_zod6.z.object({
16429
+ assistant_id: idSchema.optional(),
16430
+ thread_id: idSchema,
16431
+ message_id: idSchema,
16432
+ known_content: import_zod6.z.string().optional(),
16433
+ poll_interval: import_zod6.z.number().optional(),
16434
+ projectId: idSchema.optional(),
16435
+ modelKey: idSchema.optional()
16436
+ }).strict();
16437
+ routes.post(`${prefix}/resume_stream`, async (request, reply) => {
16438
+ try {
16439
+ const { webAppId } = paramsSchema.parse(request.params);
16440
+ const identity = await resolveRuntimeIdentity(request, webAppId, identities);
16441
+ const body = resumeStreamSchema2.parse(request.body ?? {});
16442
+ const result = await deps.service.resumeStream(webAppId, identity.userId, body.thread_id, body.message_id, { projectId: body.projectId, modelKey: body.modelKey });
16443
+ beginSse(reply);
16444
+ await pipeNativeWebAppStream(reply.raw, result.stream);
16445
+ } catch (error) {
16446
+ return normalizeError2(reply, error);
16447
+ }
16448
+ });
16449
+ };
16450
+ registerMirror("/api/web-apps/:webAppId/runtime");
16451
+ registerMirror("/api/web-apps/:webAppId/runtime/api");
15779
16452
  });
15780
16453
  }
15781
- function resolveRuntimeIdentity(request, webAppId, identities) {
15782
- if (request.headers["x-axiom-web-app-preview"] !== "true") return identities.resolve(request);
16454
+ async function resolveRuntimeIdentity(request, webAppId, identities) {
16455
+ if (request.headers["x-axiom-web-app-preview"] !== "true") return identities.resolve(request, webAppId);
15783
16456
  const user = request.user;
15784
16457
  if (!user?.id || !user.tenantId) throw new AgentWebAppRuntimeError("USER_ID_REQUIRED", 401, "Authenticated Console preview is required");
15785
- return { userId: `console-preview:${user.id}:${webAppId}`, preview: { tenantId: user.tenantId, userId: user.id } };
16458
+ return { userId: `console-preview:${user.id}:${webAppId}`, assurance: "unverified", preview: { tenantId: user.tenantId, userId: user.id } };
15786
16459
  }
15787
16460
  function withPreview(selection, preview) {
15788
16461
  return { ...selection, ...preview ? { preview } : {} };
15789
16462
  }
15790
16463
  async function pipeAgentWebAppStream(raw, stream, options = {}) {
15791
- const projection = createAgentWebAppStreamProjectionContext(options);
16464
+ const projection = (0, import_protocols12.createAgentWebAppStreamProjectionContext)(options);
15792
16465
  await pipeAsyncIterableToSse(raw, stream, {
15793
- project: (chunk) => projectAgentWebAppChunk(chunk, projection),
16466
+ project: (chunk) => (0, import_protocols12.projectAgentWebAppChunk)(chunk, projection),
15794
16467
  onError: () => [
15795
16468
  { type: "error", error: { code: "STREAM_FAILED", message: "Stream failed", retryable: true } },
15796
16469
  { type: "stream.completed" }
15797
16470
  ]
15798
16471
  });
15799
16472
  }
16473
+ async function pipeNativeWebAppStream(raw, stream) {
16474
+ await pipeAsyncIterableToSse(raw, stream, {
16475
+ onError: () => [{
16476
+ type: "error",
16477
+ data: { id: "", content: "Stream failed" }
16478
+ }]
16479
+ });
16480
+ }
15800
16481
  function beginSse(reply) {
15801
16482
  reply.hijack();
15802
16483
  reply.raw.writeHead(200, {
15803
16484
  "Content-Type": "text/event-stream; charset=utf-8",
15804
16485
  "Cache-Control": "no-cache, no-transform",
15805
16486
  Connection: "keep-alive",
15806
- "X-Accel-Buffering": "no"
16487
+ "X-Accel-Buffering": "no",
16488
+ "Access-Control-Allow-Origin": "*"
15807
16489
  });
15808
16490
  }
15809
16491
  async function handle2(reply, operation) {
@@ -15824,8 +16506,107 @@ function isMultipartRequestError(error) {
15824
16506
  return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" && error.code.startsWith("FST_");
15825
16507
  }
15826
16508
 
16509
+ // src/routes/agent-web-app-embed.ts
16510
+ var import_node_fs2 = require("fs");
16511
+ var import_promises2 = require("fs/promises");
16512
+ var import_node_path2 = __toESM(require("path"));
16513
+ var import_zod7 = require("zod");
16514
+ var idSchema2 = import_zod7.z.string().min(1).max(128).regex(/^[A-Za-z0-9._:@-]+$/);
16515
+ var JS_CONTENT_TYPE = "application/javascript; charset=utf-8";
16516
+ var CSS_CONTENT_TYPE = "text/css; charset=utf-8";
16517
+ var EXACT_ASSETS = {
16518
+ "agent-chat-loader.js": { contentType: JS_CONTENT_TYPE },
16519
+ "embed-page.js": { contentType: JS_CONTENT_TYPE },
16520
+ "embed-page.css": { contentType: CSS_CONTENT_TYPE }
16521
+ };
16522
+ var HASHED_CHUNK_PATTERN = /^embed-page-[A-Za-z0-9._-]+\.(js|css)$/;
16523
+ var CHUNK_CSS_PATTERN = /^embed-page-[A-Za-z0-9._-]+\.css$/;
16524
+ function resolveAsset(asset) {
16525
+ if (asset.includes("..")) return null;
16526
+ const exact2 = EXACT_ASSETS[asset];
16527
+ if (exact2 !== void 0) return { contentType: exact2.contentType, immutable: false };
16528
+ const hashed = HASHED_CHUNK_PATTERN.exec(asset);
16529
+ if (hashed) {
16530
+ return { contentType: hashed[1] === "css" ? CSS_CONTENT_TYPE : JS_CONTENT_TYPE, immutable: true };
16531
+ }
16532
+ return null;
16533
+ }
16534
+ async function listChunkCssFiles(assetsDir) {
16535
+ try {
16536
+ return (await (0, import_promises2.readdir)(assetsDir)).filter((name) => CHUNK_CSS_PATTERN.test(name) && !name.includes("..")).sort();
16537
+ } catch {
16538
+ return [];
16539
+ }
16540
+ }
16541
+ var BUNDLED_MARKER = "agent-chat-loader.js";
16542
+ function resolveBundledEmbedDir() {
16543
+ if (typeof __dirname === "string") {
16544
+ const compiled = import_node_path2.default.resolve(__dirname, "embed");
16545
+ if ((0, import_node_fs2.existsSync)(import_node_path2.default.join(compiled, BUNDLED_MARKER))) return compiled;
16546
+ }
16547
+ let dir = import_node_path2.default.dirname(import_node_path2.default.resolve(process.argv[1] ?? process.cwd()));
16548
+ for (let depth = 0; depth < 8; depth += 1) {
16549
+ const candidate = import_node_path2.default.join(dir, "packages", "gateway", "dist", "embed");
16550
+ if ((0, import_node_fs2.existsSync)(import_node_path2.default.join(candidate, BUNDLED_MARKER))) return candidate;
16551
+ const parent = import_node_path2.default.dirname(dir);
16552
+ if (parent === dir) break;
16553
+ dir = parent;
16554
+ }
16555
+ return null;
16556
+ }
16557
+ function renderChatShell(chunkCssFiles) {
16558
+ const chunkCssLinks = chunkCssFiles.map(
16559
+ (name) => ` <link rel="stylesheet" href="/embed/${name}" />`
16560
+ );
16561
+ return [
16562
+ "<!doctype html>",
16563
+ '<html lang="en">',
16564
+ " <head>",
16565
+ ' <meta charset="utf-8" />',
16566
+ ' <meta name="viewport" content="width=device-width, initial-scale=1" />',
16567
+ " <title>Agent chat</title>",
16568
+ ' <link rel="stylesheet" href="/embed/embed-page.css" />',
16569
+ ...chunkCssLinks,
16570
+ " </head>",
16571
+ " <body>",
16572
+ ' <div id="axiom-embed-root">',
16573
+ " <noscript>This chat requires JavaScript.</noscript>",
16574
+ ' <p class="axiom-embed-loading">Loading chat\u2026</p>',
16575
+ " </div>",
16576
+ ' <script type="module" src="/embed/embed-page.js"></script>',
16577
+ " </body>",
16578
+ "</html>"
16579
+ ].join("\n");
16580
+ }
16581
+ function registerAgentWebAppEmbedRoutes(app2, deps = {}) {
16582
+ const bundledDir = resolveBundledEmbedDir();
16583
+ const assetsDir = deps.assetsDir ?? process.env.AXIOM_EMBED_ASSETS_DIR ?? bundledDir ?? import_node_path2.default.resolve(process.cwd(), "assets/embed");
16584
+ let chunkCssFiles = null;
16585
+ app2.get("/api/web-apps/:webAppId/chat", async (request, reply) => {
16586
+ const parsed = idSchema2.safeParse(request.params.webAppId);
16587
+ if (!parsed.success) {
16588
+ return reply.code(400).send({ success: false, error: { code: "INVALID_REQUEST", message: "Invalid web app id", retryable: false } });
16589
+ }
16590
+ chunkCssFiles ?? (chunkCssFiles = await listChunkCssFiles(assetsDir));
16591
+ return reply.header("content-type", "text/html; charset=utf-8").header("cache-control", "no-store").send(renderChatShell(chunkCssFiles));
16592
+ });
16593
+ app2.get("/embed/:asset", async (request, reply) => {
16594
+ const asset = request.params.asset ?? "";
16595
+ const resolved = resolveAsset(asset);
16596
+ if (resolved === null) {
16597
+ return reply.code(404).send({ success: false, error: { code: "INVALID_REQUEST", message: "Unknown embed asset", retryable: false } });
16598
+ }
16599
+ try {
16600
+ const body = await (0, import_promises2.readFile)(import_node_path2.default.join(assetsDir, asset));
16601
+ return reply.header("content-type", resolved.contentType).header("cache-control", resolved.immutable ? "public, max-age=31536000, immutable" : "public, max-age=300").send(body);
16602
+ } catch {
16603
+ return reply.code(404).send({ success: false, error: { code: "INVALID_REQUEST", message: "Embed asset not built", retryable: false } });
16604
+ }
16605
+ });
16606
+ }
16607
+
15827
16608
  // src/services/agent-web-app/AgentWebAppAttachmentRef.ts
15828
- var import_node_crypto7 = require("crypto");
16609
+ var import_node_crypto9 = require("crypto");
15829
16610
  var TTL_MS = 15 * 6e4;
15830
16611
  function resolveAgentWebAppAttachmentSecret(consoleSecret) {
15831
16612
  return process.env.WEB_APP_ATTACHMENT_SECRET || process.env.AUTH_TOKEN_SECRET || process.env.JWT_SECRET || consoleSecret;
@@ -15834,7 +16615,7 @@ var AgentWebAppAttachmentRefService = class {
15834
16615
  constructor(secret, now = Date.now) {
15835
16616
  this.now = now;
15836
16617
  if (!secret) throw new Error("Attachment signing secret is required");
15837
- this.key = (0, import_node_crypto7.createHash)("sha256").update(secret, "utf8").digest();
16618
+ this.key = (0, import_node_crypto9.createHash)("sha256").update(secret, "utf8").digest();
15838
16619
  }
15839
16620
  sign(input) {
15840
16621
  const payload = {
@@ -15849,8 +16630,8 @@ var AgentWebAppAttachmentRefService = class {
15849
16630
  contentDigest: input.contentDigest,
15850
16631
  exp: this.now() + TTL_MS
15851
16632
  };
15852
- const iv = (0, import_node_crypto7.randomBytes)(12);
15853
- const cipher = (0, import_node_crypto7.createCipheriv)("aes-256-gcm", this.key, iv);
16633
+ const iv = (0, import_node_crypto9.randomBytes)(12);
16634
+ const cipher = (0, import_node_crypto9.createCipheriv)("aes-256-gcm", this.key, iv);
15854
16635
  const ciphertext = Buffer.concat([
15855
16636
  cipher.update(JSON.stringify(payload), "utf8"),
15856
16637
  cipher.final()
@@ -15865,7 +16646,7 @@ var AgentWebAppAttachmentRefService = class {
15865
16646
  const iv = decodeCanonical(encodedIv, 12);
15866
16647
  const ciphertext = decodeCanonical(encodedCiphertext);
15867
16648
  const tag = decodeCanonical(encodedTag, 16);
15868
- const decipher = (0, import_node_crypto7.createDecipheriv)("aes-256-gcm", this.key, iv);
16649
+ const decipher = (0, import_node_crypto9.createDecipheriv)("aes-256-gcm", this.key, iv);
15869
16650
  decipher.setAuthTag(tag);
15870
16651
  const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
15871
16652
  const value = JSON.parse(plaintext.toString("utf8"));
@@ -15896,7 +16677,7 @@ function decodeCanonical(value, expectedBytes) {
15896
16677
  return decoded;
15897
16678
  }
15898
16679
  function digestUser(userId) {
15899
- return (0, import_node_crypto7.createHash)("sha256").update(userId, "utf8").digest("hex");
16680
+ return (0, import_node_crypto9.createHash)("sha256").update(userId, "utf8").digest("hex");
15900
16681
  }
15901
16682
  function isAttachmentPayload(value) {
15902
16683
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
@@ -15909,10 +16690,10 @@ function isAttachmentPayload(value) {
15909
16690
  init_workspace_file_service();
15910
16691
 
15911
16692
  // src/controllers/capability-bundles.ts
15912
- var import_zod8 = require("zod");
16693
+ var import_zod9 = require("zod");
15913
16694
 
15914
16695
  // src/services/capability/CapabilityBundleService.ts
15915
- var import_zod7 = require("zod");
16696
+ var import_zod8 = require("zod");
15916
16697
  var import_core43 = require("@axiom-lattice/core");
15917
16698
  var CapabilityBundleServiceError = class extends Error {
15918
16699
  constructor(code, message, statusCode) {
@@ -15922,7 +16703,7 @@ var CapabilityBundleServiceError = class extends Error {
15922
16703
  this.name = "CapabilityBundleServiceError";
15923
16704
  }
15924
16705
  };
15925
- var uuid = import_zod7.z.string().uuid();
16706
+ var uuid = import_zod8.z.string().uuid();
15926
16707
  function ownRecord(value) {
15927
16708
  if (value === void 0 || value === null) return {};
15928
16709
  if (typeof value !== "object" || Array.isArray(value)) throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "Project config must be an object", 409);
@@ -16125,12 +16906,12 @@ var CapabilityBundleService = class {
16125
16906
  // src/controllers/capability-bundles.ts
16126
16907
  init_Logger();
16127
16908
  var logger3 = new Logger({ serviceName: "lattice/gateway/capability-bundles" });
16128
- var capability = import_zod8.z.unknown();
16129
- var createSchema = import_zod8.z.object({ name: import_zod8.z.string(), description: import_zod8.z.string().optional(), capabilities: import_zod8.z.array(capability) }).strict();
16130
- var updateSchema = createSchema.partial().extend({ expectedUpdatedAt: import_zod8.z.string().optional() });
16131
- var bundleIdSchema = import_zod8.z.string().uuid();
16132
- var bundleParamsSchema = import_zod8.z.object({ bundleId: bundleIdSchema });
16133
- var projectSchema = import_zod8.z.object({ bundleIds: import_zod8.z.array(bundleIdSchema), expectedRevisions: import_zod8.z.record(import_zod8.z.string()).optional() }).strict();
16909
+ var capability = import_zod9.z.unknown();
16910
+ var createSchema = import_zod9.z.object({ name: import_zod9.z.string(), description: import_zod9.z.string().optional(), capabilities: import_zod9.z.array(capability) }).strict();
16911
+ var updateSchema = createSchema.partial().extend({ expectedUpdatedAt: import_zod9.z.string().optional() });
16912
+ var bundleIdSchema = import_zod9.z.string().uuid();
16913
+ var bundleParamsSchema = import_zod9.z.object({ bundleId: bundleIdSchema });
16914
+ var projectSchema = import_zod9.z.object({ bundleIds: import_zod9.z.array(bundleIdSchema), expectedRevisions: import_zod9.z.record(import_zod9.z.string()).optional() }).strict();
16134
16915
  function tenant(request, authRequired2) {
16135
16916
  const authenticated = request.user?.tenantId;
16136
16917
  const header2 = request.headers["x-tenant-id"];
@@ -16260,12 +17041,12 @@ function registerCapabilityBundleRoutes(app2, controller) {
16260
17041
  }
16261
17042
 
16262
17043
  // src/services/collaboration/ProjectRoomService.ts
16263
- var import_node_crypto8 = require("crypto");
17044
+ var import_node_crypto10 = require("crypto");
16264
17045
  var ProjectRoomService = class {
16265
17046
  /** Creates a project room service from explicitly injected collaborators. */
16266
17047
  constructor(deps) {
16267
17048
  this.deps = deps;
16268
- this.idFactory = deps.idFactory ?? import_node_crypto8.randomUUID;
17049
+ this.idFactory = deps.idFactory ?? import_node_crypto10.randomUUID;
16269
17050
  }
16270
17051
  /** Authorizes read access and atomically ensures the project's main room. */
16271
17052
  async ensureMainRoom(input) {
@@ -16284,7 +17065,7 @@ var ProjectRoomService = class {
16284
17065
  };
16285
17066
 
16286
17067
  // src/services/collaboration/ProjectMembershipService.ts
16287
- var import_node_crypto9 = require("crypto");
17068
+ var import_node_crypto11 = require("crypto");
16288
17069
  var ProjectMembershipServiceError = class extends Error {
16289
17070
  constructor(code, statusCode, message) {
16290
17071
  super(message);
@@ -16300,7 +17081,7 @@ function isMembershipConflict(error) {
16300
17081
  var ProjectMembershipService = class {
16301
17082
  constructor(deps) {
16302
17083
  this.deps = deps;
16303
- this.idFactory = deps.idFactory ?? import_node_crypto9.randomUUID;
17084
+ this.idFactory = deps.idFactory ?? import_node_crypto11.randomUUID;
16304
17085
  this.mutationMutex = deps.projectMutationMutex ?? import_core41.projectMutationMutex;
16305
17086
  }
16306
17087
  async list(actor2) {
@@ -16398,6 +17179,14 @@ var ProjectMembershipService = class {
16398
17179
  const room = await this.deps.roomStore.getMainRoom(membership.tenantId, membership.projectId);
16399
17180
  if (!room) throw new Error("Project main room not found");
16400
17181
  this.deps.realtime.membershipChanged({ tenantId: membership.tenantId, roomId: room.id, membership, change, sourceKey });
17182
+ this.deps.realtime.membershipAffected({
17183
+ tenantId: membership.tenantId,
17184
+ userId: membership.userId,
17185
+ change,
17186
+ projectId: membership.projectId,
17187
+ roomId: room.id,
17188
+ sourceKey: `membership-affected:${sourceKey}`
17189
+ });
16401
17190
  }).catch((error) => {
16402
17191
  this.reportRealtimeFailure(membership.id);
16403
17192
  });
@@ -16426,7 +17215,7 @@ var ProjectMembershipService = class {
16426
17215
  };
16427
17216
 
16428
17217
  // src/services/collaboration/ProjectRosterService.ts
16429
- var import_node_crypto10 = require("crypto");
17218
+ var import_node_crypto12 = require("crypto");
16430
17219
  var ProjectRosterServiceError = class extends Error {
16431
17220
  /** Creates a stable roster service error. */
16432
17221
  constructor(code, statusCode, message) {
@@ -16443,7 +17232,7 @@ var ProjectRosterService = class {
16443
17232
  /** Creates a roster service from explicitly injected collaborators. */
16444
17233
  constructor(deps) {
16445
17234
  this.deps = deps;
16446
- this.idFactory = deps.idFactory ?? import_node_crypto10.randomUUID;
17235
+ this.idFactory = deps.idFactory ?? import_node_crypto12.randomUUID;
16447
17236
  this.mutationMutex = deps.projectMutationMutex ?? import_core41.projectMutationMutex;
16448
17237
  }
16449
17238
  /** Lists all bot memberships visible to a project reader. */
@@ -16663,7 +17452,7 @@ var ProjectRosterService = class {
16663
17452
  };
16664
17453
 
16665
17454
  // src/services/collaboration/RoomMessageService.ts
16666
- var import_node_crypto11 = require("crypto");
17455
+ var import_node_crypto13 = require("crypto");
16667
17456
 
16668
17457
  // src/services/collaboration/ProjectBotMembershipSnapshot.ts
16669
17458
  var import_protocols13 = require("@axiom-lattice/protocols");
@@ -16752,7 +17541,7 @@ var RoomMessageService = class {
16752
17541
  constructor(deps, options = {}) {
16753
17542
  this.deps = deps;
16754
17543
  this.idempotentOutcomes = /* @__PURE__ */ new Map();
16755
- this.idFactory = deps.idFactory ?? import_node_crypto11.randomUUID;
17544
+ this.idFactory = deps.idFactory ?? import_node_crypto13.randomUUID;
16756
17545
  const limit = options.idempotentOutcomeLimit ?? 1e3;
16757
17546
  if (!Number.isSafeInteger(limit) || limit < 1) throw new RangeError("idempotentOutcomeLimit must be a positive safe integer");
16758
17547
  this.idempotentOutcomeLimit = limit;
@@ -16933,7 +17722,7 @@ var RoomMessageService = class {
16933
17722
  let idempotencyKey;
16934
17723
  if (value.requestIdempotencyKey !== void 0) {
16935
17724
  if (typeof value.requestIdempotencyKey !== "string" || !/^[\x21-\x7e]{1,200}$/.test(value.requestIdempotencyKey.trim())) throw new RoomMessageServiceError("INVALID_MESSAGE", 400, "Invalid idempotency key");
16936
- idempotencyKey = `room-human:${actor2.userId}:${(0, import_node_crypto11.createHash)("sha256").update(value.requestIdempotencyKey.trim(), "utf8").digest("hex")}`;
17725
+ idempotencyKey = `room-human:${actor2.userId}:${(0, import_node_crypto13.createHash)("sha256").update(value.requestIdempotencyKey.trim(), "utf8").digest("hex")}`;
16937
17726
  }
16938
17727
  return { text, mentions, botIds, ...value.replyToMessageId === void 0 ? {} : { replyToMessageId: value.replyToMessageId }, ...idempotencyKey === void 0 ? {} : { idempotencyKey } };
16939
17728
  }
@@ -16990,7 +17779,7 @@ function cloneRoomMessage(message) {
16990
17779
  };
16991
17780
  }
16992
17781
  function fingerprintRequest(input) {
16993
- return (0, import_node_crypto11.createHash)("sha256").update(JSON.stringify({
17782
+ return (0, import_node_crypto13.createHash)("sha256").update(JSON.stringify({
16994
17783
  text: input.text,
16995
17784
  mentions: input.mentions,
16996
17785
  replyToMessageId: input.replyToMessageId ?? null
@@ -17001,46 +17790,47 @@ function matchesNormalizedPayload(message, input) {
17001
17790
  }
17002
17791
 
17003
17792
  // src/routes/project-rooms.ts
17004
- var import_zod10 = require("zod");
17793
+ var import_zod11 = require("zod");
17794
+ var import_protocols14 = require("@axiom-lattice/protocols");
17005
17795
 
17006
17796
  // src/schemas/project-room.ts
17007
- var import_zod9 = require("zod");
17008
- var id2 = import_zod9.z.string().trim().min(1).max(128);
17009
- var isoDate = import_zod9.z.string().datetime({ offset: true }).transform((value) => new Date(value));
17010
- var expectedUpdatedAt = import_zod9.z.object({ expectedUpdatedAt: isoDate }).strict();
17011
- var projectRoomParamsSchema = import_zod9.z.object({ projectId: id2 }).strict();
17012
- var membershipParamsSchema = import_zod9.z.object({ projectId: id2, membershipId: id2 }).strict();
17013
- var roomMessagesQuerySchema = import_zod9.z.object({
17014
- beforeCreatedAt: import_zod9.z.string().datetime({ offset: true }).transform((value) => new Date(value)).optional(),
17797
+ var import_zod10 = require("zod");
17798
+ var id2 = import_zod10.z.string().trim().min(1).max(128);
17799
+ var isoDate = import_zod10.z.string().datetime({ offset: true }).transform((value) => new Date(value));
17800
+ var expectedUpdatedAt = import_zod10.z.object({ expectedUpdatedAt: isoDate }).strict();
17801
+ var projectRoomParamsSchema = import_zod10.z.object({ projectId: id2 }).strict();
17802
+ var membershipParamsSchema = import_zod10.z.object({ projectId: id2, membershipId: id2 }).strict();
17803
+ var roomMessagesQuerySchema = import_zod10.z.object({
17804
+ beforeCreatedAt: import_zod10.z.string().datetime({ offset: true }).transform((value) => new Date(value)).optional(),
17015
17805
  beforeId: id2.optional(),
17016
- limit: import_zod9.z.coerce.number().int().min(1).max(100).optional()
17806
+ limit: import_zod10.z.coerce.number().int().min(1).max(100).optional()
17017
17807
  }).strict().refine((value) => value.beforeCreatedAt === void 0 === (value.beforeId === void 0), { message: "Both cursor fields are required" });
17018
- var createRoomMessageSchema = import_zod9.z.object({
17019
- text: import_zod9.z.string(),
17020
- mentions: import_zod9.z.array(import_zod9.z.union([
17021
- import_zod9.z.object({ type: import_zod9.z.literal("team") }).strict(),
17022
- import_zod9.z.object({ type: import_zod9.z.literal("bot"), membershipId: id2 }).strict()
17808
+ var createRoomMessageSchema = import_zod10.z.object({
17809
+ text: import_zod10.z.string(),
17810
+ mentions: import_zod10.z.array(import_zod10.z.union([
17811
+ import_zod10.z.object({ type: import_zod10.z.literal("team") }).strict(),
17812
+ import_zod10.z.object({ type: import_zod10.z.literal("bot"), membershipId: id2 }).strict()
17023
17813
  ])).optional(),
17024
17814
  replyToMessageId: id2.optional()
17025
17815
  }).strict();
17026
- var addProjectMemberSchema = import_zod9.z.object({ userId: id2, role: import_zod9.z.enum(["owner", "admin", "member", "viewer"]) }).strict();
17027
- var updateProjectMemberSchema = import_zod9.z.object({ role: import_zod9.z.enum(["owner", "admin", "member", "viewer"]), expectedUpdatedAt: isoDate }).strict();
17816
+ var addProjectMemberSchema = import_zod10.z.object({ userId: id2, role: import_zod10.z.enum(["owner", "admin", "member", "viewer"]) }).strict();
17817
+ var updateProjectMemberSchema = import_zod10.z.object({ role: import_zod10.z.enum(["owner", "admin", "member", "viewer"]), expectedUpdatedAt: isoDate }).strict();
17028
17818
  var mutationExpectedUpdatedAtSchema = expectedUpdatedAt;
17029
- var roomMessageRetryParamsSchema = import_zod9.z.object({ projectId: id2, messageId: id2 }).strict();
17030
- var emptyObjectSchema = import_zod9.z.object({}).strict();
17031
- var idempotencyKeySchema = import_zod9.z.string().refine((value) => value.trim().length >= 1 && value.trim().length <= 200 && /^[\x20-\x7e]+$/.test(value.trim()), "Invalid idempotency key").transform((value) => value.trim());
17032
- var addProjectBotSchema = import_zod9.z.object({
17819
+ var roomMessageRetryParamsSchema = import_zod10.z.object({ projectId: id2, messageId: id2 }).strict();
17820
+ var emptyObjectSchema = import_zod10.z.object({}).strict();
17821
+ var idempotencyKeySchema = import_zod10.z.string().refine((value) => value.trim().length >= 1 && value.trim().length <= 200 && /^[\x20-\x7e]+$/.test(value.trim()), "Invalid idempotency key").transform((value) => value.trim());
17822
+ var addProjectBotSchema = import_zod10.z.object({
17033
17823
  assistantId: id2,
17034
- role: import_zod9.z.enum(["coordinator", "specialist"]),
17035
- title: import_zod9.z.string(),
17036
- responsibility: import_zod9.z.string().optional(),
17037
- mentionName: import_zod9.z.string()
17824
+ role: import_zod10.z.enum(["coordinator", "specialist"]),
17825
+ title: import_zod10.z.string(),
17826
+ responsibility: import_zod10.z.string().optional(),
17827
+ mentionName: import_zod10.z.string()
17038
17828
  }).strict();
17039
- var updateProjectBotSchema = import_zod9.z.object({
17040
- role: import_zod9.z.enum(["coordinator", "specialist"]).optional(),
17041
- title: import_zod9.z.string().optional(),
17042
- responsibility: import_zod9.z.string().optional(),
17043
- mentionName: import_zod9.z.string().optional(),
17829
+ var updateProjectBotSchema = import_zod10.z.object({
17830
+ role: import_zod10.z.enum(["coordinator", "specialist"]).optional(),
17831
+ title: import_zod10.z.string().optional(),
17832
+ responsibility: import_zod10.z.string().optional(),
17833
+ mentionName: import_zod10.z.string().optional(),
17044
17834
  expectedUpdatedAt: isoDate
17045
17835
  }).strict().refine((value) => value.role !== void 0 || value.title !== void 0 || value.responsibility !== void 0 || value.mentionName !== void 0, { message: "At least one mutable field is required" });
17046
17836
 
@@ -17058,7 +17848,8 @@ function registerProjectRoomRoutes(app2, deps) {
17058
17848
  const params = projectRoomParamsSchema.parse(request.params);
17059
17849
  const query = roomMessagesQuerySchema.parse(request.query);
17060
17850
  const before = query.beforeCreatedAt === void 0 && query.beforeId === void 0 ? void 0 : { createdAt: query.beforeCreatedAt, id: query.beforeId };
17061
- return { data: await deps.messageService.list(actor(request, params.projectId), { ...before ? { before } : {}, ...query.limit === void 0 ? {} : { limit: query.limit } }) };
17851
+ const messages = await deps.messageService.list(actor(request, params.projectId), { ...before ? { before } : {}, ...query.limit === void 0 ? {} : { limit: query.limit } });
17852
+ return { data: messages.map(toProjectRoomMessage) };
17062
17853
  }));
17063
17854
  app2.post("/api/projects/:projectId/room/messages", async (request, reply) => run(reply, async () => {
17064
17855
  const params = projectRoomParamsSchema.parse(request.params);
@@ -17069,7 +17860,7 @@ function registerProjectRoomRoutes(app2, deps) {
17069
17860
  const idempotencyKey = rawIdempotencyKey === void 0 ? void 0 : idempotencyKeySchema.parse(rawIdempotencyKey);
17070
17861
  const result = await deps.messageService.createAndDispatch(requestActor, { ...input, ...idempotencyKey === void 0 ? {} : { requestIdempotencyKey: idempotencyKey } });
17071
17862
  const allSucceeded = result.dispatch.length > 0 && result.dispatch.every((entry) => entry.success);
17072
- return { statusCode: allSucceeded ? result.replayed ? 200 : 201 : 202, data: result };
17863
+ return { statusCode: allSucceeded ? result.replayed ? 200 : 201 : 202, data: { message: toProjectRoomMessage(result.message), dispatch: result.dispatch, replayed: result.replayed } };
17073
17864
  }));
17074
17865
  app2.post("/api/projects/:projectId/room/messages/:messageId/retry", async (request, reply) => run(reply, async () => {
17075
17866
  const params = roomMessageRetryParamsSchema.parse(request.params);
@@ -17078,6 +17869,12 @@ function registerProjectRoomRoutes(app2, deps) {
17078
17869
  const dispatch = await deps.messageService.retry(actor(request, params.projectId), params.messageId);
17079
17870
  return { statusCode: dispatch.length > 0 && dispatch.every((entry) => entry.success) ? 200 : 202, data: dispatch };
17080
17871
  }));
17872
+ app2.post("/api/projects/:projectId/room/read-state", async (request, reply) => run(reply, async () => {
17873
+ const params = projectRoomParamsSchema.parse(request.params);
17874
+ emptyObjectSchema.parse(request.body ?? {});
17875
+ await deps.readStateService.mark(actor(request, params.projectId));
17876
+ return { data: { marked: true } };
17877
+ }));
17081
17878
  app2.get("/api/projects/:projectId/members", async (request, reply) => run(reply, async () => ({ data: await deps.membershipService.list(actor(request, projectRoomParamsSchema.parse(request.params).projectId)) })));
17082
17879
  app2.post("/api/projects/:projectId/members", async (request, reply) => run(reply, async () => {
17083
17880
  const p = projectRoomParamsSchema.parse(request.params);
@@ -17100,19 +17897,24 @@ function actor(request, projectId) {
17100
17897
  projectRoomParamsSchema.parse({ projectId });
17101
17898
  return { tenantId: user.tenantId, userId: user.id, projectId };
17102
17899
  }
17900
+ function toProjectRoomMessage(message) {
17901
+ const publicMessage = (0, import_protocols14.toProjectRoomPublicMessage)(message);
17902
+ if (publicMessage === void 0) throw new Error("Room message could not be mapped to its public DTO");
17903
+ return publicMessage;
17904
+ }
17103
17905
  async function run(reply, operation) {
17104
17906
  try {
17105
17907
  const result = await operation();
17106
17908
  return reply.code(result.statusCode ?? 200).send({ success: true, data: result.data });
17107
17909
  } catch (error) {
17108
- if (error instanceof import_zod10.ZodError) return reply.code(400).send({ success: false, error: { code: "INVALID_REQUEST", message: "Invalid request", retryable: false } });
17910
+ if (error instanceof import_zod11.ZodError) return reply.code(400).send({ success: false, error: { code: "INVALID_REQUEST", message: "Invalid request", retryable: false } });
17109
17911
  if (error instanceof ProjectRoomAuthError || error instanceof ProjectCollaborationError || error instanceof ProjectMembershipServiceError || error instanceof ProjectRosterServiceError || error instanceof RoomMessageServiceError) return reply.code(error.statusCode).send({ success: false, error: { code: error.code, message: error.message, retryable: error instanceof RoomMessageServiceError && error.retryable } });
17110
17912
  return reply.code(500).send({ success: false, error: { code: "INTERNAL_ERROR", message: "Internal server error", retryable: false } });
17111
17913
  }
17112
17914
  }
17113
17915
 
17114
17916
  // src/routes/project-roster.ts
17115
- var import_zod11 = require("zod");
17917
+ var import_zod12 = require("zod");
17116
17918
  var ProjectRosterAuthError = class extends Error {
17117
17919
  constructor() {
17118
17920
  super(...arguments);
@@ -17152,16 +17954,17 @@ async function execute(reply, operation) {
17152
17954
  const result = await operation();
17153
17955
  return reply.code(result.statusCode ?? 200).send({ success: true, data: result.data });
17154
17956
  } catch (error) {
17155
- if (error instanceof import_zod11.ZodError) return reply.code(400).send({ success: false, error: { code: "INVALID_REQUEST", message: "Invalid request", retryable: false } });
17957
+ if (error instanceof import_zod12.ZodError) return reply.code(400).send({ success: false, error: { code: "INVALID_REQUEST", message: "Invalid request", retryable: false } });
17156
17958
  if (error instanceof ProjectRosterAuthError || error instanceof ProjectCollaborationError || error instanceof ProjectRosterServiceError) return reply.code(error.statusCode).send({ success: false, error: { code: error.code, message: error.message, retryable: false } });
17157
17959
  return reply.code(500).send({ success: false, error: { code: "INTERNAL_ERROR", message: "Internal server error", retryable: false } });
17158
17960
  }
17159
17961
  }
17160
17962
 
17161
17963
  // src/routes/cospace.ts
17162
- var import_node_crypto12 = require("crypto");
17163
- var import_zod12 = require("zod");
17964
+ var import_node_crypto14 = require("crypto");
17965
+ var import_zod13 = require("zod");
17164
17966
  var import_core44 = require("@axiom-lattice/core");
17967
+ var import_protocols15 = require("@axiom-lattice/protocols");
17165
17968
  var CoSpaceAuthError = class extends Error {
17166
17969
  constructor() {
17167
17970
  super(...arguments);
@@ -17176,8 +17979,20 @@ function getActor2(request) {
17176
17979
  }
17177
17980
  return { tenantId: user.tenantId, userId: user.id };
17178
17981
  }
17982
+ async function computeUnread(deps, tenantId, userId, roomId, lastMessage) {
17983
+ if (!lastMessage) return 0;
17984
+ const readState = await deps.readStateStore.get(tenantId, roomId, userId);
17985
+ const horizon = readState?.lastReadAt;
17986
+ if (horizon && lastMessage.createdAt.getTime() <= horizon.getTime()) return 0;
17987
+ return deps.messageStore.countAfter({
17988
+ tenantId,
17989
+ roomId,
17990
+ after: horizon ?? /* @__PURE__ */ new Date(0),
17991
+ excludeAuthorUserId: userId
17992
+ });
17993
+ }
17179
17994
  function registerCoSpaceRoutes(app2, deps) {
17180
- const idFactory = deps.idFactory ?? (() => (0, import_node_crypto12.randomUUID)());
17995
+ const idFactory = deps.idFactory ?? (() => (0, import_node_crypto14.randomUUID)());
17181
17996
  app2.get(
17182
17997
  "/api/workspaces/:workspaceId/rooms",
17183
17998
  async (request, reply) => {
@@ -17226,6 +18041,7 @@ function registerCoSpaceRoutes(app2, deps) {
17226
18041
  limit: 1
17227
18042
  });
17228
18043
  const lastMessage = messages[0];
18044
+ const publicLastMessage = lastMessage === void 0 ? void 0 : (0, import_protocols15.toProjectRoomPublicMessage)(lastMessage);
17229
18045
  const memberships = await deps.membershipStore.list(
17230
18046
  actor2.tenantId,
17231
18047
  project.id
@@ -17241,19 +18057,26 @@ function registerCoSpaceRoutes(app2, deps) {
17241
18057
  rooms.push({
17242
18058
  project,
17243
18059
  room,
17244
- lastMessage,
18060
+ lastMessage: publicLastMessage,
17245
18061
  participantCount: memberships.filter(
17246
18062
  (m) => m.status === "active"
17247
18063
  ).length,
17248
- participantNames
18064
+ participantNames,
18065
+ unreadCount: await computeUnread(
18066
+ deps,
18067
+ actor2.tenantId,
18068
+ actor2.userId,
18069
+ room.id,
18070
+ lastMessage
18071
+ )
17249
18072
  });
17250
18073
  } catch (e) {
17251
18074
  console.error("[CoSpace] Failed to process room for project:", project.id, e);
17252
18075
  }
17253
18076
  }
17254
18077
  rooms.sort((a, b) => {
17255
- const aTime = a.lastMessage?.createdAt?.getTime() ?? 0;
17256
- const bTime = b.lastMessage?.createdAt?.getTime() ?? 0;
18078
+ const aTime = a.lastMessage ? Date.parse(a.lastMessage.createdAt) : 0;
18079
+ const bTime = b.lastMessage ? Date.parse(b.lastMessage.createdAt) : 0;
17257
18080
  return bTime - aTime;
17258
18081
  });
17259
18082
  const publicRoom = await deps.publicRoom.ensure(actor2.tenantId, params.workspaceId);
@@ -17263,6 +18086,7 @@ function registerCoSpaceRoutes(app2, deps) {
17263
18086
  roomId: publicRoom.room.id,
17264
18087
  limit: 1
17265
18088
  });
18089
+ const publicLastMessage = publicMessages[0];
17266
18090
  const publicMemberships = await deps.membershipStore.list(
17267
18091
  actor2.tenantId,
17268
18092
  publicRoom.project.id
@@ -17278,10 +18102,17 @@ function registerCoSpaceRoutes(app2, deps) {
17278
18102
  rooms.unshift({
17279
18103
  project: publicRoom.project,
17280
18104
  room: publicRoom.room,
17281
- lastMessage: publicMessages[0],
18105
+ lastMessage: publicLastMessage === void 0 ? void 0 : (0, import_protocols15.toProjectRoomPublicMessage)(publicLastMessage),
17282
18106
  participantCount: publicMemberships.filter((m) => m.status === "active").length,
17283
18107
  participantNames: publicParticipantNames,
17284
- isPublic: true
18108
+ isPublic: true,
18109
+ unreadCount: await computeUnread(
18110
+ deps,
18111
+ actor2.tenantId,
18112
+ actor2.userId,
18113
+ publicRoom.room.id,
18114
+ publicLastMessage
18115
+ )
17285
18116
  });
17286
18117
  }
17287
18118
  return { data: { rooms } };
@@ -17646,7 +18477,7 @@ function registerCoSpaceRoutes(app2, deps) {
17646
18477
  data: result.data
17647
18478
  });
17648
18479
  } catch (error) {
17649
- if (error instanceof import_zod12.ZodError) {
18480
+ if (error instanceof import_zod13.ZodError) {
17650
18481
  return reply.code(400).send({
17651
18482
  success: false,
17652
18483
  error: {
@@ -17917,7 +18748,7 @@ var RoomTargetResolver = class {
17917
18748
  };
17918
18749
 
17919
18750
  // src/services/collaboration/RoomDispatchService.ts
17920
- var import_protocols14 = require("@axiom-lattice/protocols");
18751
+ var import_protocols16 = require("@axiom-lattice/protocols");
17921
18752
 
17922
18753
  // src/router/InternalRoomDispatch.ts
17923
18754
  var INTERNAL_ROOM_DISPATCH = Symbol("internal-room-dispatch");
@@ -18015,7 +18846,7 @@ function snapshotDispatchSource(value) {
18015
18846
  };
18016
18847
  }
18017
18848
  function snapshotMentions(value) {
18018
- const rows = (0, import_protocols14.snapshotExactArray)(value);
18849
+ const rows = (0, import_protocols16.snapshotExactArray)(value);
18019
18850
  if (!rows) return void 0;
18020
18851
  const result = [];
18021
18852
  for (const row of rows) {
@@ -18033,16 +18864,16 @@ function snapshotMentions(value) {
18033
18864
  function exactValues(value, required, optional = []) {
18034
18865
  try {
18035
18866
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
18036
- return (0, import_protocols14.snapshotExactRecord)(value, required, optional);
18867
+ return (0, import_protocols16.snapshotExactRecord)(value, required, optional);
18037
18868
  } catch {
18038
18869
  return void 0;
18039
18870
  }
18040
18871
  }
18041
18872
 
18042
18873
  // src/services/collaboration/CoordinatorWakeNotifier.ts
18043
- var import_node_crypto13 = require("crypto");
18874
+ var import_node_crypto15 = require("crypto");
18044
18875
  var import_core45 = require("@axiom-lattice/core");
18045
- var import_protocols15 = require("@axiom-lattice/protocols");
18876
+ var import_protocols17 = require("@axiom-lattice/protocols");
18046
18877
  var SYNTHETIC_WAKE_AUTHOR = "coordinator-wake";
18047
18878
  var CoordinatorWakeNotifier = class {
18048
18879
  /** Creates a bounded Project Task lifecycle observer that wakes the Room Coordinator. */
@@ -18055,7 +18886,7 @@ var CoordinatorWakeNotifier = class {
18055
18886
  this.accepted = /* @__PURE__ */ new Set();
18056
18887
  this.maxPending = deps.maxPending ?? 1024;
18057
18888
  if (!Number.isSafeInteger(this.maxPending) || this.maxPending < 1) throw new RangeError("maxPending must be a positive safe integer");
18058
- this.idFactory = deps.idFactory ?? import_node_crypto13.randomUUID;
18889
+ this.idFactory = deps.idFactory ?? import_node_crypto15.randomUUID;
18059
18890
  }
18060
18891
  /** Admits one notification without awaiting any store or dispatch operation. */
18061
18892
  handle(value) {
@@ -18196,7 +19027,7 @@ var CoordinatorWakeNotifier = class {
18196
19027
  }
18197
19028
  }
18198
19029
  parse(value) {
18199
- const row = (0, import_protocols15.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
19030
+ const row = (0, import_protocols17.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
18200
19031
  const actions = ["in_progress", "interrupted", "failed", "completed", "cancelled", "reassigned"];
18201
19032
  const statuses = ["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"];
18202
19033
  if (!row || !actions.includes(String(row.action)) || !statuses.includes(String(row.status)) || !["tenantId", "workspaceId", "projectId", "taskId", "eventKey", "updatedAt"].every((key) => typeof row[key] === "string" && row[key].length > 0) || !Number.isFinite(Date.parse(row.updatedAt)) || row.threadId !== void 0 && typeof row.threadId !== "string") return void 0;
@@ -18234,9 +19065,9 @@ function safeId(value) {
18234
19065
  }
18235
19066
 
18236
19067
  // src/services/collaboration/ProjectTaskExecutionMutex.ts
18237
- var import_protocols16 = require("@axiom-lattice/protocols");
19068
+ var import_protocols18 = require("@axiom-lattice/protocols");
18238
19069
  function machineKey(scope) {
18239
- const snapshot = (0, import_protocols16.snapshotExactRecord)(scope, ["tenantId", "assistantId", "projectId"]);
19070
+ const snapshot = (0, import_protocols18.snapshotExactRecord)(scope, ["tenantId", "assistantId", "projectId"]);
18240
19071
  if (!snapshot) throw new Error("Invalid Project task machine scope");
18241
19072
  const values = [snapshot.tenantId, snapshot.assistantId, snapshot.projectId];
18242
19073
  for (const value of values) {
@@ -18313,7 +19144,7 @@ var ProjectTaskExecutionMutex = class {
18313
19144
 
18314
19145
  // src/services/collaboration/ProjectTaskExecutionService.ts
18315
19146
  var import_core46 = require("@axiom-lattice/core");
18316
- var import_protocols17 = require("@axiom-lattice/protocols");
19147
+ var import_protocols19 = require("@axiom-lattice/protocols");
18317
19148
  var SYSTEM_ACTOR = "system";
18318
19149
  var QUEUE_CLASSIFICATION_ATTEMPTS = 3;
18319
19150
  var ProjectTaskExecutionError = class extends Error {
@@ -18868,7 +19699,7 @@ function buildTrustedTaskContext(task, thread, inputMessageId) {
18868
19699
  };
18869
19700
  }
18870
19701
  function taskThreadMetadata(thread) {
18871
- const row = (0, import_protocols17.snapshotExactRecord)(thread.metadata, [
19702
+ const row = (0, import_protocols19.snapshotExactRecord)(thread.metadata, [
18872
19703
  "source",
18873
19704
  "kind",
18874
19705
  "workspaceId",
@@ -18909,7 +19740,7 @@ function classifyRecoveryRows(task, thread, pending2, processingBefore, processi
18909
19740
  }
18910
19741
  function validRecoveryRow(row, task, thread) {
18911
19742
  try {
18912
- const trusted = (0, import_protocols17.parseTrustedRunContext)(row.trusted_run_context).projectTask;
19743
+ const trusted = (0, import_protocols19.parseTrustedRunContext)(row.trusted_run_context).projectTask;
18913
19744
  const metadata = taskThreadMetadata(thread);
18914
19745
  return row.execution_mode === "followup" && !!trusted && trusted.tenantId === task.tenantId && trusted.workspaceId === task.workspaceId && trusted.projectId === task.projectId && trusted.assistantId === task.ownerId && trusted.taskId === task.id && trusted.threadId === thread.id && trusted.inputMessageId === row.id && !!metadata && trusted.roomId === metadata.roomId && trusted.membershipId === metadata.membershipId && metadata.assistantId === task.ownerId && metadata.taskId === task.id;
18915
19746
  } catch {
@@ -18918,7 +19749,7 @@ function validRecoveryRow(row, task, thread) {
18918
19749
  }
18919
19750
 
18920
19751
  // src/services/collaboration/ProjectTaskObserver.ts
18921
- var import_node_crypto14 = require("crypto");
19752
+ var import_node_crypto16 = require("crypto");
18922
19753
  var import_core47 = require("@axiom-lattice/core");
18923
19754
  var SYSTEM_ACTOR2 = "system";
18924
19755
  var TERMINAL_ACTIONS = ["completed", "failed", "interrupted", "cancelled"];
@@ -19455,7 +20286,7 @@ var ProjectTaskObserver = class {
19455
20286
  action: "activity",
19456
20287
  summary: "Project task recovery warning",
19457
20288
  detail: { type: "project_task_recovery_warning", phase, message },
19458
- eventKey: `project-task-recovery-warning:${task.id}:${phase}:${(0, import_node_crypto14.createHash)("sha256").update(message).digest("hex")}`
20289
+ eventKey: `project-task-recovery-warning:${task.id}:${phase}:${(0, import_node_crypto16.createHash)("sha256").update(message).digest("hex")}`
19459
20290
  });
19460
20291
  }
19461
20292
  async safeWarning(task, phase, error) {
@@ -19522,7 +20353,7 @@ var ProjectTaskObserver = class {
19522
20353
  }
19523
20354
  }
19524
20355
  async persistOverflowWarning(event) {
19525
- const scopeDigest = (0, import_node_crypto14.createHash)("sha256").update(JSON.stringify([event.tenantId, event.workspaceId, event.projectId])).digest("hex");
20356
+ const scopeDigest = (0, import_node_crypto16.createHash)("sha256").update(JSON.stringify([event.tenantId, event.workspaceId, event.projectId])).digest("hex");
19526
20357
  try {
19527
20358
  await this.deps.workItems.createIfAbsentByEventKey({
19528
20359
  tenantId: event.tenantId,
@@ -19623,9 +20454,9 @@ function combineSignals(left, right) {
19623
20454
  }
19624
20455
 
19625
20456
  // src/services/collaboration/RoomProjectionService.ts
19626
- var import_node_crypto15 = require("crypto");
20457
+ var import_node_crypto17 = require("crypto");
19627
20458
  var import_core48 = require("@axiom-lattice/core");
19628
- var import_protocols18 = require("@axiom-lattice/protocols");
20459
+ var import_protocols20 = require("@axiom-lattice/protocols");
19629
20460
  var RoomProjectionService = class {
19630
20461
  /** @param deps Message, lifecycle-event, Task, warning, logging, and ID dependencies. */
19631
20462
  constructor(deps) {
@@ -19685,7 +20516,7 @@ var RoomProjectionService = class {
19685
20516
  tenantId: input.tenantId,
19686
20517
  workspaceId: input.workspaceId,
19687
20518
  projectId: input.projectId,
19688
- actions: [...import_protocols18.PROJECT_TASK_LIFECYCLE_ACTIONS],
20519
+ actions: [...import_protocols20.PROJECT_TASK_LIFECYCLE_ACTIONS],
19689
20520
  before,
19690
20521
  limit: input.pageSize
19691
20522
  });
@@ -19792,7 +20623,7 @@ function safeRepairIdentity(value, scope) {
19792
20623
  return taskId && eventKey && tenantId === scope.tenantId && workspaceId === scope.workspaceId && projectId === scope.projectId ? { taskId, eventKey } : void 0;
19793
20624
  }
19794
20625
  function tupleKey(prefix, values) {
19795
- const digest = (0, import_node_crypto15.createHash)("sha256").update(JSON.stringify(values)).digest("hex");
20626
+ const digest = (0, import_node_crypto17.createHash)("sha256").update(JSON.stringify(values)).digest("hex");
19796
20627
  return `${prefix}:${digest}`;
19797
20628
  }
19798
20629
  function parseProjectionInput(taskValue, itemValue) {
@@ -19807,7 +20638,7 @@ function parseProjectionInput(taskValue, itemValue) {
19807
20638
  }
19808
20639
  }
19809
20640
  function snapshotProjectableWorkItem(value) {
19810
- const row = (0, import_protocols18.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
20641
+ const row = (0, import_protocols20.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
19811
20642
  "workspaceId",
19812
20643
  "projectId",
19813
20644
  "threadId",
@@ -19817,10 +20648,10 @@ function snapshotProjectableWorkItem(value) {
19817
20648
  "eventKey"
19818
20649
  ]);
19819
20650
  const createdAt = cloneExactDate(row?.createdAt);
19820
- if (!row || !createdAt || typeof row.id !== "string" || !row.id || typeof row.taskId !== "string" || !row.taskId || typeof row.tenantId !== "string" || !row.tenantId || typeof row.workspaceId !== "string" || !row.workspaceId || typeof row.projectId !== "string" || !row.projectId || typeof row.actor !== "string" || !row.actor || typeof row.eventKey !== "string" || !row.eventKey || !import_protocols18.PROJECT_TASK_LIFECYCLE_ACTIONS.includes(row.action) || row.threadId !== void 0 && typeof row.threadId !== "string" || row.summary !== void 0 && typeof row.summary !== "string" || row.attempt !== void 0 && (typeof row.attempt !== "number" || !Number.isFinite(row.attempt))) return void 0;
20651
+ if (!row || !createdAt || typeof row.id !== "string" || !row.id || typeof row.taskId !== "string" || !row.taskId || typeof row.tenantId !== "string" || !row.tenantId || typeof row.workspaceId !== "string" || !row.workspaceId || typeof row.projectId !== "string" || !row.projectId || typeof row.actor !== "string" || !row.actor || typeof row.eventKey !== "string" || !row.eventKey || !import_protocols20.PROJECT_TASK_LIFECYCLE_ACTIONS.includes(row.action) || row.threadId !== void 0 && typeof row.threadId !== "string" || row.summary !== void 0 && typeof row.summary !== "string" || row.attempt !== void 0 && (typeof row.attempt !== "number" || !Number.isFinite(row.attempt))) return void 0;
19821
20652
  try {
19822
20653
  const detail = row.detail === void 0 ? void 0 : snapshotJsonValue(row.detail);
19823
- if (detail !== void 0 && !isRecord4(detail)) return void 0;
20654
+ if (detail !== void 0 && !isRecord3(detail)) return void 0;
19824
20655
  return {
19825
20656
  id: row.id,
19826
20657
  taskId: row.taskId,
@@ -19844,12 +20675,12 @@ function parseIso(value) {
19844
20675
  return typeof value === "string" && value.length > 0 && Number.isFinite(Date.parse(value));
19845
20676
  }
19846
20677
  function parseInterruption(value) {
19847
- const common = (0, import_protocols18.snapshotExactRecord)(value, ["type", "summary", "requestedAt"]);
20678
+ const common = (0, import_protocols20.snapshotExactRecord)(value, ["type", "summary", "requestedAt"]);
19848
20679
  if (common && (common.type === "missing_input" || common.type === "user_decision") && typeof common.summary === "string" && common.summary.length > 0 && parseIso(common.requestedAt)) {
19849
20680
  return { type: common.type, summary: common.summary, requestedAt: common.requestedAt };
19850
20681
  }
19851
- const external = (0, import_protocols18.snapshotExactRecord)(value, ["type", "summary", "requestedAt", "dependencyTaskIds"]);
19852
- const ids = (0, import_protocols18.snapshotExactArray)(external?.dependencyTaskIds);
20682
+ const external = (0, import_protocols20.snapshotExactRecord)(value, ["type", "summary", "requestedAt", "dependencyTaskIds"]);
20683
+ const ids = (0, import_protocols20.snapshotExactArray)(external?.dependencyTaskIds);
19853
20684
  if (external?.type === "external_dependency" && typeof external.summary === "string" && external.summary.length > 0 && parseIso(external.requestedAt) && ids && ids.length > 0 && ids.every((id3) => typeof id3 === "string" && id3.length > 0) && new Set(ids).size === ids.length) {
19854
20685
  return {
19855
20686
  type: "external_dependency",
@@ -19858,58 +20689,58 @@ function parseInterruption(value) {
19858
20689
  dependencyTaskIds: [...ids]
19859
20690
  };
19860
20691
  }
19861
- const review = (0, import_protocols18.snapshotExactRecord)(value, ["type", "evidenceId"]);
20692
+ const review = (0, import_protocols20.snapshotExactRecord)(value, ["type", "evidenceId"]);
19862
20693
  return review?.type === "review_required" && typeof review.evidenceId === "string" && review.evidenceId.length > 0 ? { type: "review_required", evidenceId: review.evidenceId } : void 0;
19863
20694
  }
19864
20695
  function parseBeliefImpact(value) {
19865
- const rows = (0, import_protocols18.snapshotExactArray)(value);
20696
+ const rows = (0, import_protocols20.snapshotExactArray)(value);
19866
20697
  if (!rows) return void 0;
19867
20698
  const impacts = [];
19868
20699
  for (const row of rows) {
19869
- const entry = (0, import_protocols18.snapshotExactRecord)(row, ["key", "after", "basis"]);
20700
+ const entry = (0, import_protocols20.snapshotExactRecord)(row, ["key", "after", "basis"]);
19870
20701
  if (!entry || typeof entry.key !== "string" || !entry.key || typeof entry.after !== "number" || !Number.isFinite(entry.after) || typeof entry.basis !== "string" || !entry.basis) return void 0;
19871
20702
  impacts.push({ key: entry.key, after: entry.after, basis: entry.basis });
19872
20703
  }
19873
20704
  return impacts;
19874
20705
  }
19875
20706
  function parseCompletion(item) {
19876
- const row = (0, import_protocols18.snapshotExactRecord)(item.detail, ["evidenceId", "eventKey", "result", "beliefImpact"]);
20707
+ const row = (0, import_protocols20.snapshotExactRecord)(item.detail, ["evidenceId", "eventKey", "result", "beliefImpact"]);
19877
20708
  const beliefImpact = parseBeliefImpact(row?.beliefImpact);
19878
20709
  if (!row || typeof row.evidenceId !== "string" || !row.evidenceId || typeof row.eventKey !== "string" || !row.eventKey || item.eventKey !== `${row.eventKey}:completed` || typeof row.result !== "string" || !beliefImpact) return void 0;
19879
20710
  return { evidenceId: row.evidenceId, eventKey: row.eventKey, result: row.result, beliefImpact };
19880
20711
  }
19881
20712
  function parseProjection(item) {
19882
20713
  if (item.action === "in_progress") {
19883
- const started = (0, import_protocols18.snapshotExactRecord)(item.detail, ["previousStatus"]);
20714
+ const started = (0, import_protocols20.snapshotExactRecord)(item.detail, ["previousStatus"]);
19884
20715
  if (started?.previousStatus === "pending") return { kind: "started", text: "Task started" };
19885
- const resumed = (0, import_protocols18.snapshotExactRecord)(item.detail, ["type", "previousInterruption"]);
20716
+ const resumed = (0, import_protocols20.snapshotExactRecord)(item.detail, ["type", "previousInterruption"]);
19886
20717
  if (resumed?.type === "interruption_resume" && parseInterruption(resumed.previousInterruption)) {
19887
20718
  return { kind: "resumed", text: "Task resumed" };
19888
20719
  }
19889
- const rejected = (0, import_protocols18.snapshotExactRecord)(item.detail, ["type", "evidenceId", "note"]);
20720
+ const rejected = (0, import_protocols20.snapshotExactRecord)(item.detail, ["type", "evidenceId", "note"]);
19890
20721
  if (rejected?.type === "review_rejected" && typeof rejected.evidenceId === "string" && rejected.evidenceId && typeof rejected.note === "string" && rejected.note) {
19891
20722
  return { kind: "resumed", text: "Task resumed after review rejection" };
19892
20723
  }
19893
- const stale = (0, import_protocols18.snapshotExactRecord)(item.detail, ["type", "evidenceId"]);
20724
+ const stale = (0, import_protocols20.snapshotExactRecord)(item.detail, ["type", "evidenceId"]);
19894
20725
  return stale?.type === "review_stale" && typeof stale.evidenceId === "string" && stale.evidenceId ? { kind: "resumed", text: "Task resumed after stale review" } : void 0;
19895
20726
  }
19896
20727
  if (item.action === "interrupted") {
19897
20728
  return parseInterruption(item.detail) ? { kind: "interrupted", text: "Task interrupted" } : void 0;
19898
20729
  }
19899
20730
  if (item.action === "failed") {
19900
- const row = (0, import_protocols18.snapshotExactRecord)(item.detail, ["failureReason"]);
20731
+ const row = (0, import_protocols20.snapshotExactRecord)(item.detail, ["failureReason"]);
19901
20732
  return typeof row?.failureReason === "string" && row.failureReason ? { kind: "failed", text: "Task failed" } : void 0;
19902
20733
  }
19903
20734
  if (item.action === "completed") {
19904
20735
  return parseCompletion(item) ? { kind: "completed", text: "Task completed" } : void 0;
19905
20736
  }
19906
20737
  if (item.action === "cancelled") {
19907
- const empty = (0, import_protocols18.snapshotExactRecord)(item.detail, []);
19908
- const summarized = (0, import_protocols18.snapshotExactRecord)(item.detail, ["summary"]);
20738
+ const empty = (0, import_protocols20.snapshotExactRecord)(item.detail, []);
20739
+ const summarized = (0, import_protocols20.snapshotExactRecord)(item.detail, ["summary"]);
19909
20740
  return empty || typeof summarized?.summary === "string" && summarized.summary ? { kind: "cancelled", text: "Task cancelled" } : void 0;
19910
20741
  }
19911
20742
  if (item.action === "reassigned") {
19912
- const row = (0, import_protocols18.snapshotExactRecord)(
20743
+ const row = (0, import_protocols20.snapshotExactRecord)(
19913
20744
  item.detail,
19914
20745
  ["previousOwnerId", "previousThreadId", "ownerId", "membershipId", "threadId"]
19915
20746
  );
@@ -19918,7 +20749,7 @@ function parseProjection(item) {
19918
20749
  return void 0;
19919
20750
  }
19920
20751
  function assertCanonicalProjection(value, expected) {
19921
- const row = (0, import_protocols18.snapshotExactRecord)(value, [
20752
+ const row = (0, import_protocols20.snapshotExactRecord)(value, [
19922
20753
  "id",
19923
20754
  "tenantId",
19924
20755
  "workspaceId",
@@ -19932,9 +20763,9 @@ function assertCanonicalProjection(value, expected) {
19932
20763
  "idempotencyKey",
19933
20764
  "createdAt"
19934
20765
  ]);
19935
- const author = (0, import_protocols18.snapshotExactRecord)(row?.author, ["type"]);
19936
- const content = (0, import_protocols18.snapshotExactRecord)(row?.content, ["type", "text"]);
19937
- const mentions = (0, import_protocols18.snapshotExactArray)(row?.mentions);
20766
+ const author = (0, import_protocols20.snapshotExactRecord)(row?.author, ["type"]);
20767
+ const content = (0, import_protocols20.snapshotExactRecord)(row?.content, ["type", "text"]);
20768
+ const mentions = (0, import_protocols20.snapshotExactArray)(row?.mentions);
19938
20769
  const createdAt = cloneExactDate(row?.createdAt);
19939
20770
  if (!row || !createdAt || author?.type !== "system" || content?.type !== "text" || content.text !== expected.content.text || !mentions || mentions.length !== 0 || typeof row.id !== "string" || !row.id || row.tenantId !== expected.tenantId || row.workspaceId !== expected.workspaceId || row.projectId !== expected.projectId || row.roomId !== expected.roomId || row.source !== "task" || row.sourceId !== expected.sourceId || row.idempotencyKey !== expected.idempotencyKey) {
19940
20771
  throw new Error("Invalid canonical task projection");
@@ -19955,7 +20786,7 @@ function assertCanonicalProjection(value, expected) {
19955
20786
  };
19956
20787
  }
19957
20788
  function snapshotLifecycleCursor(value) {
19958
- const row = (0, import_protocols18.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
20789
+ const row = (0, import_protocols20.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
19959
20790
  "workspaceId",
19960
20791
  "projectId",
19961
20792
  "threadId",
@@ -19967,7 +20798,7 @@ function snapshotLifecycleCursor(value) {
19967
20798
  const createdAt = cloneExactDate(row?.createdAt);
19968
20799
  return row && typeof row.id === "string" && row.id.length > 0 && createdAt ? { id: row.id, createdAt } : void 0;
19969
20800
  }
19970
- function isRecord4(value) {
20801
+ function isRecord3(value) {
19971
20802
  return typeof value === "object" && value !== null && !Array.isArray(value);
19972
20803
  }
19973
20804
 
@@ -19975,8 +20806,8 @@ function isRecord4(value) {
19975
20806
  var import_core50 = require("@axiom-lattice/core");
19976
20807
 
19977
20808
  // src/services/collaboration/ProjectRoomEventBroker.ts
19978
- var import_node_crypto16 = require("crypto");
19979
- var import_protocols19 = require("@axiom-lattice/protocols");
20809
+ var import_node_crypto18 = require("crypto");
20810
+ var import_protocols21 = require("@axiom-lattice/protocols");
19980
20811
  var DEFAULT_MAX_EVENTS_PER_ROOM = 1e3;
19981
20812
  var DEFAULT_MAX_EVENT_AGE_MS = 10 * 60 * 1e3;
19982
20813
  var DEFAULT_MAX_ROOMS = 1e3;
@@ -20000,7 +20831,7 @@ var ProjectRoomEventBroker = class {
20000
20831
  this.subscriberCount = 0;
20001
20832
  this.usageClock = 0;
20002
20833
  this.closed = false;
20003
- this.epoch = options.epoch ?? (0, import_node_crypto16.randomUUID)();
20834
+ this.epoch = options.epoch ?? (0, import_node_crypto18.randomUUID)();
20004
20835
  if (!UUID_PATTERN.test(this.epoch)) {
20005
20836
  throw new TypeError("Project Room event epoch must be a lowercase canonical UUID");
20006
20837
  }
@@ -20039,7 +20870,7 @@ var ProjectRoomEventBroker = class {
20039
20870
  const canonicalScope = snapshotScope(scope);
20040
20871
  const key = scopeKey2(canonicalScope);
20041
20872
  const now = this.currentTime();
20042
- if (this.sequence >= Number.MAX_SAFE_INTEGER) throw new import_protocols19.ProjectRoomBrokerCapacityError();
20873
+ if (this.sequence >= Number.MAX_SAFE_INTEGER) throw new import_protocols21.ProjectRoomBrokerCapacityError();
20043
20874
  const nextSequence = this.sequence + 1;
20044
20875
  const event = snapshotJson({
20045
20876
  ...snapshotDraft(draft),
@@ -20222,11 +21053,11 @@ var ProjectRoomEventBroker = class {
20222
21053
  }
20223
21054
  resolveCursor(key, afterEventId, plan) {
20224
21055
  if (afterEventId === void 0) return void 0;
20225
- const cursor = (0, import_protocols19.parseProjectRoomEventId)(afterEventId);
20226
- if (!cursor) throw new import_protocols19.ProjectRoomCursorError("CURSOR_EXPIRED");
20227
- if (cursor.epoch !== this.epoch) throw new import_protocols19.ProjectRoomCursorError("SERVER_RESTART");
21056
+ const cursor = (0, import_protocols21.parseProjectRoomEventId)(afterEventId);
21057
+ if (!cursor) throw new import_protocols21.ProjectRoomCursorError("CURSOR_EXPIRED");
21058
+ if (cursor.epoch !== this.epoch) throw new import_protocols21.ProjectRoomCursorError("SERVER_RESTART");
20228
21059
  if (plan.sequences.has(cursor.sequence) || this.sequenceScopes.get(cursor.sequence) !== key) {
20229
- throw new import_protocols19.ProjectRoomCursorError("CURSOR_EXPIRED");
21060
+ throw new import_protocols21.ProjectRoomCursorError("CURSOR_EXPIRED");
20230
21061
  }
20231
21062
  return cursor.sequence;
20232
21063
  }
@@ -20318,8 +21149,8 @@ function snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
20318
21149
  }
20319
21150
 
20320
21151
  // src/services/collaboration/ProjectRoomRealtimePublisher.ts
20321
- var import_node_crypto17 = require("crypto");
20322
- var import_protocols20 = require("@axiom-lattice/protocols");
21152
+ var import_node_crypto19 = require("crypto");
21153
+ var import_protocols22 = require("@axiom-lattice/protocols");
20323
21154
  var BrokerProjectRoomRealtimePublisher = class {
20324
21155
  /** Creates a publisher around a broker and structured warning logger. */
20325
21156
  constructor(deps) {
@@ -20333,7 +21164,7 @@ var BrokerProjectRoomRealtimePublisher = class {
20333
21164
  /** Publishes a canonical message after projecting it to its public shape. */
20334
21165
  messageCreated(message) {
20335
21166
  this.publish("message.created", () => {
20336
- const projection = (0, import_protocols20.snapshotProjectRoomMessageRealtime)(message);
21167
+ const projection = (0, import_protocols22.snapshotProjectRoomMessageRealtime)(message);
20337
21168
  if (!projection) return void 0;
20338
21169
  return {
20339
21170
  sourceKey: `message:${projection.publicMessage.id}`,
@@ -20348,7 +21179,7 @@ var BrokerProjectRoomRealtimePublisher = class {
20348
21179
  this.publish("roster.changed", () => {
20349
21180
  const membership = snapshotInput(input, "roster");
20350
21181
  if (membership.membership.tenantId !== membership.tenantId || membership.membership.roomId !== membership.roomId || !safeId2(membership.membership.projectId)) throw new TypeError("Invalid roster scope");
20351
- const projection = (0, import_protocols20.snapshotProjectRoomBotMembershipRealtime)(membership.membership);
21182
+ const projection = (0, import_protocols22.snapshotProjectRoomBotMembershipRealtime)(membership.membership);
20352
21183
  if (!projection) return void 0;
20353
21184
  return {
20354
21185
  sourceKey: membership.sourceKey,
@@ -20363,7 +21194,7 @@ var BrokerProjectRoomRealtimePublisher = class {
20363
21194
  this.publish("membership.changed", () => {
20364
21195
  const membership = snapshotInput(input, "membership");
20365
21196
  if (membership.membership.tenantId !== membership.tenantId || !safeId2(membership.membership.projectId)) throw new TypeError("Invalid membership scope");
20366
- const projection = (0, import_protocols20.snapshotProjectRoomMembershipRealtime)(membership.membership);
21197
+ const projection = (0, import_protocols22.snapshotProjectRoomMembershipRealtime)(membership.membership);
20367
21198
  if (!projection) return void 0;
20368
21199
  return {
20369
21200
  sourceKey: membership.sourceKey,
@@ -20389,12 +21220,52 @@ var BrokerProjectRoomRealtimePublisher = class {
20389
21220
  };
20390
21221
  });
20391
21222
  }
21223
+ /** Publishes a membership notice onto the affected user's channel scope. */
21224
+ membershipAffected(input) {
21225
+ this.publish("membership.affected", () => {
21226
+ const value = (0, import_protocols22.snapshotExactRecord)(input, ["tenantId", "userId", "change", "projectId", "roomId", "sourceKey"]);
21227
+ if (!value || !safeId2(value.tenantId) || !safeId2(value.userId) || !safeId2(value.projectId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || !["added", "removed", "role_changed"].includes(value.change)) {
21228
+ throw new TypeError("Invalid membership input");
21229
+ }
21230
+ const scope = (0, import_protocols22.projectRoomUserEventScope)(value.tenantId, value.userId);
21231
+ return {
21232
+ sourceKey: value.sourceKey,
21233
+ id: value.sourceKey,
21234
+ scope,
21235
+ draft: {
21236
+ type: "membership.affected",
21237
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
21238
+ data: { change: value.change, projectId: value.projectId, roomId: value.roomId }
21239
+ }
21240
+ };
21241
+ });
21242
+ }
21243
+ /** Publishes a read-marker update onto the acting user's channel scope. */
21244
+ readChanged(input) {
21245
+ this.publish("read.changed", () => {
21246
+ const value = (0, import_protocols22.snapshotExactRecord)(input, ["tenantId", "userId", "projectId", "roomId", "lastReadAt", "sourceKey"]);
21247
+ if (!value || !safeId2(value.tenantId) || !safeId2(value.userId) || !safeId2(value.projectId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || typeof value.lastReadAt !== "string" || !Number.isFinite(Date.parse(value.lastReadAt))) {
21248
+ throw new TypeError("Invalid read input");
21249
+ }
21250
+ const scope = (0, import_protocols22.projectRoomUserEventScope)(value.tenantId, value.userId);
21251
+ return {
21252
+ sourceKey: value.sourceKey,
21253
+ id: value.sourceKey,
21254
+ scope,
21255
+ draft: {
21256
+ type: "read.changed",
21257
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
21258
+ data: { projectId: value.projectId, roomId: value.roomId, lastReadAt: new Date(Date.parse(value.lastReadAt)).toISOString() }
21259
+ }
21260
+ };
21261
+ });
21262
+ }
20392
21263
  publish(type, build) {
20393
21264
  let event;
20394
21265
  try {
20395
21266
  event = build();
20396
21267
  if (!event) throw new Error("Invalid Project Room realtime projection");
20397
- const dedupeKey = (0, import_node_crypto17.createHash)("sha256").update(JSON.stringify([type, event.scope.tenantId, event.scope.projectId, event.scope.roomId, event.sourceKey])).digest("hex");
21268
+ const dedupeKey = (0, import_node_crypto19.createHash)("sha256").update(JSON.stringify([type, event.scope.tenantId, event.scope.projectId, event.scope.roomId, event.sourceKey])).digest("hex");
20398
21269
  if (this.sourceKeys.has(dedupeKey)) return;
20399
21270
  this.deps.broker.publish(event.scope, event.draft);
20400
21271
  this.sourceKeys.set(dedupeKey, true);
@@ -20417,13 +21288,13 @@ var BrokerProjectRoomRealtimePublisher = class {
20417
21288
  };
20418
21289
  function snapshotInput(input, kind) {
20419
21290
  const keys2 = kind === "message" ? ["tenantId", "roomId", "message", "sourceKey"] : kind === "roster" ? ["tenantId", "roomId", "membership", "sourceKey"] : ["tenantId", "roomId", "membership", "sourceKey"];
20420
- const value = (0, import_protocols20.snapshotExactRecord)(input, [...keys2, "change"]);
21291
+ const value = (0, import_protocols22.snapshotExactRecord)(input, [...keys2, "change"]);
20421
21292
  const validChange = kind === "roster" ? ["added", "updated", "paused", "resumed", "removed"].includes(value?.change) : ["added", "role_changed", "removed"].includes(value?.change);
20422
21293
  if (!value || !safeId2(value.tenantId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || !validChange) throw new TypeError(`Invalid ${kind} input`);
20423
21294
  return value;
20424
21295
  }
20425
21296
  function snapshotTaskInput(input) {
20426
- const value = (0, import_protocols20.snapshotExactRecord)(input, ["tenantId", "roomId", "projectId", "taskId", "status", "ownerMembershipId", "updatedAt", "sourceKey"]);
21297
+ const value = (0, import_protocols22.snapshotExactRecord)(input, ["tenantId", "roomId", "projectId", "taskId", "status", "ownerMembershipId", "updatedAt", "sourceKey"]);
20427
21298
  if (!value || !safeId2(value.tenantId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey)) throw new TypeError("Invalid task input");
20428
21299
  if (!safeId2(value.projectId) || !safeId2(value.taskId) || !safeId2(value.ownerMembershipId) || !["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"].includes(value.status)) throw new TypeError("Invalid task input");
20429
21300
  if (typeof value.updatedAt !== "string") throw new TypeError("Invalid task timestamp");
@@ -20447,384 +21318,16 @@ function safeErrorCode(error) {
20447
21318
  return error instanceof Error && error.name === "Error" ? "Error" : "UnknownError";
20448
21319
  }
20449
21320
 
20450
- // src/services/collaboration/ProjectRoomRealtimeService.ts
20451
- var import_protocols21 = require("@axiom-lattice/protocols");
20452
-
20453
- // src/services/collaboration/ProjectRoomSseWriter.ts
20454
- var DEFAULT_MAX_FRAMES = 256;
20455
- var DEFAULT_MAX_BYTES = 1024 * 1024;
20456
- var DEFAULT_DRAIN_TIMEOUT_MS = 1e4;
20457
- function serializeBusiness(event) {
20458
- return `id: ${event.id}
20459
- event: ${event.type}
20460
- data: ${JSON.stringify(event)}
20461
-
20462
- `;
20463
- }
20464
- function serializeControl(event) {
20465
- return `event: ${event.type}
20466
- data: ${JSON.stringify(event.data)}
20467
-
20468
- `;
20469
- }
20470
- var ProjectRoomSseWriter = class {
20471
- /** Creates a writer over a raw HTTP response/socket. */
20472
- constructor(raw, options = {}) {
20473
- this.raw = raw;
20474
- this.frames = [];
20475
- this.queuedBytes = 0;
20476
- this.blockedBytes = 0;
20477
- this.writing = false;
20478
- this.closed = false;
20479
- this.terminal = false;
20480
- this.slowConsumerAttempted = false;
20481
- this.closeListener = () => this.close();
20482
- this.errorListener = () => this.close();
20483
- this.drainListener = () => {
20484
- if (this.closed || !this.writing) return;
20485
- this.clearDrainTimer();
20486
- this.blockedBytes = 0;
20487
- this.writing = false;
20488
- this.flush();
20489
- };
20490
- this.maxFrames = positive(options.maxFrames ?? DEFAULT_MAX_FRAMES, "maxFrames");
20491
- this.maxBytes = positive(options.maxBytes ?? DEFAULT_MAX_BYTES, "maxBytes");
20492
- this.drainTimeoutMs = positive(options.drainTimeoutMs ?? DEFAULT_DRAIN_TIMEOUT_MS, "drainTimeoutMs");
20493
- this.onClose = options.onClose;
20494
- raw.on("close", this.closeListener).on("error", this.errorListener).on("drain", this.drainListener);
20495
- }
20496
- /** Enqueues one public business event. */
20497
- enqueueBusiness(event) {
20498
- this.enqueue(serializeBusiness(event));
20499
- }
20500
- /** Enqueues one connection control event. */
20501
- enqueueControl(event) {
20502
- this.enqueue(serializeControl(event));
20503
- }
20504
- /** Writes a heartbeat comment when the socket is not currently blocked. */
20505
- heartbeat() {
20506
- if (!this.closed && !this.writing) this.writeFrame(": heartbeat\n\n");
20507
- }
20508
- /** Closes the writer and removes every socket listener exactly once. */
20509
- close() {
20510
- if (this.closed) return;
20511
- this.closed = true;
20512
- this.clearDrainTimer();
20513
- if (this.terminalTimer !== void 0) clearTimeout(this.terminalTimer);
20514
- this.terminalResolve?.();
20515
- this.terminalResolve = void 0;
20516
- this.terminalFinish = void 0;
20517
- this.raw.off("close", this.closeListener).off("error", this.errorListener).off("drain", this.drainListener);
20518
- this.frames.length = 0;
20519
- this.queuedBytes = 0;
20520
- try {
20521
- this.raw.end();
20522
- } catch {
20523
- this.raw.destroy();
20524
- }
20525
- this.onClose?.();
20526
- }
20527
- /** Stops ordinary delivery and attempts one terminal control before ending. */
20528
- closeWithControl(control, deadlineMs = 250) {
20529
- if (this.closed) return Promise.resolve();
20530
- if (this.terminal) return new Promise((resolve4) => {
20531
- this.terminalResolve = resolve4;
20532
- });
20533
- this.terminal = true;
20534
- this.frames.length = 0;
20535
- this.queuedBytes = 0;
20536
- const frame = serializeControl(control);
20537
- const finish = () => {
20538
- if (this.closed) return;
20539
- if (this.terminalTimer !== void 0) clearTimeout(this.terminalTimer);
20540
- this.terminalTimer = void 0;
20541
- this.close();
20542
- };
20543
- this.terminalFinish = finish;
20544
- const promise = new Promise((resolve4) => {
20545
- this.terminalResolve = resolve4;
20546
- });
20547
- if (!this.writing) {
20548
- try {
20549
- if (this.raw.write(frame)) finish();
20550
- else this.armTerminalDeadline(deadlineMs, finish);
20551
- } catch {
20552
- finish();
20553
- }
20554
- } else {
20555
- this.frames.push(frame);
20556
- this.flushTerminal(finish);
20557
- this.armTerminalDeadline(deadlineMs, finish);
20558
- }
20559
- return promise;
20560
- }
20561
- enqueue(frame) {
20562
- if (this.closed || this.terminal) return;
20563
- const bytes = Buffer.byteLength(frame, "utf8");
20564
- const inFlightFrames = this.writing ? 1 : 0;
20565
- if (bytes > this.maxBytes || this.frames.length + inFlightFrames + 1 > this.maxFrames || this.queuedBytes + this.blockedBytes + bytes > this.maxBytes) return this.failSlowConsumer();
20566
- this.frames.push(frame);
20567
- this.queuedBytes += bytes;
20568
- this.flush();
20569
- }
20570
- flush() {
20571
- if (this.closed || this.writing || this.frames.length === 0) return;
20572
- const frame = this.frames.shift();
20573
- if (!frame) return;
20574
- this.queuedBytes -= Buffer.byteLength(frame, "utf8");
20575
- if (this.terminal) this.writeTerminalFrame(frame, this.terminalFinish ?? (() => this.close()));
20576
- else this.writeFrame(frame);
20577
- }
20578
- flushTerminal(finish) {
20579
- if (this.closed || this.writing || this.frames.length === 0) return;
20580
- const frame = this.frames.shift();
20581
- if (!frame) return;
20582
- this.writeTerminalFrame(frame, finish);
20583
- }
20584
- writeTerminalFrame(frame, finish) {
20585
- try {
20586
- if (!this.raw.write(frame)) {
20587
- this.writing = true;
20588
- this.blockedBytes = Buffer.byteLength(frame, "utf8");
20589
- } else {
20590
- this.writing = false;
20591
- this.blockedBytes = 0;
20592
- (finish ?? (() => this.close()))();
20593
- }
20594
- } catch {
20595
- this.close();
20596
- }
20597
- }
20598
- armTerminalDeadline(deadlineMs, finish) {
20599
- this.terminalTimer = setTimeout(finish, deadlineMs);
20600
- this.terminalTimer.unref?.();
20601
- }
20602
- writeFrame(frame) {
20603
- if (this.closed) return;
20604
- try {
20605
- if (!this.raw.write(frame)) {
20606
- this.writing = true;
20607
- this.blockedBytes = Buffer.byteLength(frame, "utf8");
20608
- this.drainTimer = setTimeout(() => {
20609
- this.drainTimer = void 0;
20610
- this.failSlowConsumer();
20611
- }, this.drainTimeoutMs);
20612
- this.drainTimer.unref?.();
20613
- } else {
20614
- this.writing = false;
20615
- this.blockedBytes = 0;
20616
- this.flush();
20617
- }
20618
- } catch {
20619
- this.close();
20620
- }
20621
- }
20622
- clearDrainTimer() {
20623
- if (this.drainTimer !== void 0) clearTimeout(this.drainTimer);
20624
- this.drainTimer = void 0;
20625
- }
20626
- failSlowConsumer() {
20627
- if (this.closed) return;
20628
- this.frames.length = 0;
20629
- this.queuedBytes = 0;
20630
- if (!this.slowConsumerAttempted) {
20631
- this.slowConsumerAttempted = true;
20632
- try {
20633
- this.raw.write(serializeControl({ type: "resync", data: { reason: "SLOW_CONSUMER" } }));
20634
- } catch {
20635
- }
20636
- }
20637
- this.close();
20638
- }
20639
- };
20640
- function positive(value, name) {
20641
- if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError(`${name} must be positive`);
20642
- return value;
20643
- }
20644
-
20645
- // src/services/collaboration/ProjectRoomRealtimeService.ts
20646
- var MAX_REPLAY_EVENTS = 1e4;
20647
- var MAX_NODE_TIMER_DELAY = 2147e6;
20648
- var ProjectRoomRealtimeService = class {
20649
- /** Creates a service using one process-local broker and read-only authorizer. */
20650
- constructor(deps) {
20651
- this.deps = deps;
20652
- this.connections = /* @__PURE__ */ new Set();
20653
- this.closed = false;
20654
- this.activeConnections = /* @__PURE__ */ new Map();
20655
- this.now = deps.now ?? Date.now;
20656
- this.authRecheckMs = deps.authRecheckMs ?? 15e3;
20657
- this.heartbeatMs = deps.heartbeatMs ?? 15e3;
20658
- }
20659
- /** Returns whether the actor's tenant/user/project stream quota has capacity. */
20660
- canConnect(actor2) {
20661
- if (this.closed) return false;
20662
- return (this.activeConnections.get(connectionKey(actor2)) ?? 0) < (this.deps.maxConnectionsPerUserProject ?? 5);
20663
- }
20664
- /** Starts a connection; authorization is assumed to have been performed by the route. */
20665
- connect(input) {
20666
- if (!this.canConnect(input.actor)) {
20667
- input.raw.end();
20668
- return;
20669
- }
20670
- const quotaKey = connectionKey(input.actor);
20671
- this.activeConnections.set(quotaKey, (this.activeConnections.get(quotaKey) ?? 0) + 1);
20672
- const writer = new ProjectRoomSseWriter(input.raw, { onClose: () => connection.close() });
20673
- let phase = "initializing";
20674
- let subscription;
20675
- let accessTimer;
20676
- let heartbeatTimer;
20677
- let expiryTimer;
20678
- const lifetimeAbort = new AbortController();
20679
- let accessAbort;
20680
- let closed = false;
20681
- const buffered = [];
20682
- const clearTimer = (timer) => {
20683
- if (timer !== void 0) clearTimeout(timer);
20684
- };
20685
- const cleanup = () => {
20686
- if (closed) return;
20687
- closed = true;
20688
- phase = "closed";
20689
- clearTimer(accessTimer);
20690
- clearTimer(heartbeatTimer);
20691
- clearTimer(expiryTimer);
20692
- lifetimeAbort.abort();
20693
- accessAbort?.abort();
20694
- subscription?.unsubscribe();
20695
- writer.close();
20696
- this.connections.delete(connection);
20697
- const remainingConnections = (this.activeConnections.get(quotaKey) ?? 1) - 1;
20698
- if (remainingConnections === 0) this.activeConnections.delete(quotaKey);
20699
- else this.activeConnections.set(quotaKey, remainingConnections);
20700
- };
20701
- const revoke = (reason) => {
20702
- if (closed) return;
20703
- void writer.closeWithControl({ type: "access.revoked", data: { reason } }).then(cleanup, cleanup);
20704
- };
20705
- const scheduleAccessCheck = () => {
20706
- if (closed) return;
20707
- accessTimer = setTimeout(() => {
20708
- accessTimer = void 0;
20709
- if (closed) return;
20710
- accessAbort = new AbortController();
20711
- const combined = combineSignals2(lifetimeAbort.signal, accessAbort.signal);
20712
- Promise.resolve().then(() => this.deps.requireReadAccess(input.actor, combined.signal)).then(() => {
20713
- combined.cleanup();
20714
- accessAbort = void 0;
20715
- scheduleAccessCheck();
20716
- }, (_error) => {
20717
- combined.cleanup();
20718
- accessAbort = void 0;
20719
- if (!closed) revoke("PROJECT_ACCESS_REVOKED");
20720
- });
20721
- }, this.authRecheckMs);
20722
- accessTimer.unref?.();
20723
- };
20724
- const connection = { close: cleanup };
20725
- this.connections.add(connection);
20726
- const scheduleHeartbeat = () => {
20727
- if (closed) return;
20728
- heartbeatTimer = setTimeout(() => {
20729
- heartbeatTimer = void 0;
20730
- if (closed) return;
20731
- writer.heartbeat();
20732
- scheduleHeartbeat();
20733
- }, this.heartbeatMs);
20734
- heartbeatTimer.unref?.();
20735
- };
20736
- scheduleHeartbeat();
20737
- const remaining = input.actor.tokenExpiresAt - this.now();
20738
- if (remaining <= 0) {
20739
- revoke("TOKEN_EXPIRED");
20740
- return;
20741
- }
20742
- const maxTimerDelay = this.deps.maxTimerDelay ?? MAX_NODE_TIMER_DELAY;
20743
- const scheduleExpiry = () => {
20744
- if (closed) return;
20745
- const delay2 = input.actor.tokenExpiresAt - this.now();
20746
- if (delay2 <= 0) {
20747
- revoke("TOKEN_EXPIRED");
20748
- return;
20749
- }
20750
- expiryTimer = setTimeout(() => {
20751
- expiryTimer = void 0;
20752
- scheduleExpiry();
20753
- }, Math.min(delay2, maxTimerDelay));
20754
- expiryTimer.unref?.();
20755
- };
20756
- scheduleExpiry();
20757
- try {
20758
- subscription = this.deps.broker.subscribe(
20759
- { tenantId: input.actor.tenantId, roomId: input.roomId, projectId: input.actor.projectId },
20760
- input.lastEventId,
20761
- (event) => {
20762
- if (phase === "initializing") buffered.push(event);
20763
- else if (phase === "direct") writer.enqueueBusiness(event);
20764
- }
20765
- );
20766
- if (subscription.replay.length > MAX_REPLAY_EVENTS) {
20767
- void writer.closeWithControl({ type: "resync", data: { reason: "CURSOR_EXPIRED" } }).then(cleanup, cleanup);
20768
- return;
20769
- }
20770
- let lastSequence = sequence(subscription.headEventId);
20771
- for (const event of subscription.replay) {
20772
- writer.enqueueBusiness(event);
20773
- lastSequence = sequence(event.id);
20774
- }
20775
- writer.enqueueControl({ type: "ready", data: { epoch: this.deps.broker.epoch, headEventId: subscription.headEventId } });
20776
- while (buffered.length > 0) {
20777
- for (const event of buffered.splice(0).sort((left, right) => sequence(left.id) - sequence(right.id))) {
20778
- if (sequence(event.id) > lastSequence) {
20779
- writer.enqueueBusiness(event);
20780
- lastSequence = sequence(event.id);
20781
- }
20782
- }
20783
- }
20784
- phase = "direct";
20785
- scheduleAccessCheck();
20786
- } catch (error) {
20787
- if (error instanceof import_protocols21.ProjectRoomCursorError) void writer.closeWithControl({ type: "resync", data: { reason: error.code } }).then(cleanup, cleanup);
20788
- else cleanup();
20789
- }
20790
- }
20791
- /** Closes every connection and prevents new connections. */
20792
- close() {
20793
- if (this.closed) return;
20794
- this.closed = true;
20795
- for (const connection of [...this.connections]) connection.close();
20796
- }
20797
- };
20798
- function sequence(id3) {
20799
- return id3 === null ? 0 : Number(id3.slice(id3.lastIndexOf(":") + 1));
20800
- }
20801
- function connectionKey(actor2) {
20802
- return JSON.stringify([actor2.tenantId, actor2.userId, actor2.projectId]);
20803
- }
20804
- function combineSignals2(first, second) {
20805
- const controller = new AbortController();
20806
- const abort = () => controller.abort();
20807
- if (first.aborted || second.aborted) abort();
20808
- else {
20809
- first.addEventListener("abort", abort, { once: true });
20810
- second.addEventListener("abort", abort, { once: true });
20811
- }
20812
- return { signal: controller.signal, cleanup: () => {
20813
- first.removeEventListener("abort", abort);
20814
- second.removeEventListener("abort", abort);
20815
- } };
20816
- }
20817
-
20818
- // src/services/collaboration/ProjectRoomTaskEventSubscriber.ts
20819
- var import_core49 = require("@axiom-lattice/core");
20820
- var import_protocols22 = require("@axiom-lattice/protocols");
20821
- var ProjectRoomTaskEventSubscriber = class {
20822
- /** Creates a bounded Project task lifecycle observer. */
20823
- constructor(deps) {
20824
- this.deps = deps;
20825
- this.queues = /* @__PURE__ */ new Map();
20826
- this.pendingCount = 0;
20827
- this.accepting = true;
21321
+ // src/services/collaboration/ProjectRoomTaskEventSubscriber.ts
21322
+ var import_core49 = require("@axiom-lattice/core");
21323
+ var import_protocols23 = require("@axiom-lattice/protocols");
21324
+ var ProjectRoomTaskEventSubscriber = class {
21325
+ /** Creates a bounded Project task lifecycle observer. */
21326
+ constructor(deps) {
21327
+ this.deps = deps;
21328
+ this.queues = /* @__PURE__ */ new Map();
21329
+ this.pendingCount = 0;
21330
+ this.accepting = true;
20828
21331
  this.closed = false;
20829
21332
  this.accepted = /* @__PURE__ */ new Set();
20830
21333
  this.maxPending = deps.maxPending ?? 1024;
@@ -20927,117 +21430,509 @@ var ProjectRoomTaskEventSubscriber = class {
20927
21430
  }
20928
21431
  }
20929
21432
  parse(value) {
20930
- const row = (0, import_protocols22.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
21433
+ const row = (0, import_protocols23.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
20931
21434
  const actions = ["in_progress", "interrupted", "failed", "completed", "cancelled", "reassigned"];
20932
21435
  const statuses = ["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"];
20933
21436
  if (!row || !actions.includes(String(row.action)) || !statuses.includes(String(row.status)) || !["tenantId", "workspaceId", "projectId", "taskId", "eventKey", "updatedAt"].every((key) => typeof row[key] === "string" && row[key].length > 0) || !Number.isFinite(Date.parse(row.updatedAt)) || row.threadId !== void 0 && typeof row.threadId !== "string") return void 0;
20934
21437
  return row;
20935
21438
  }
20936
- warn(message, context) {
21439
+ warn(message, context) {
21440
+ try {
21441
+ this.deps.log.warn(message, context);
21442
+ } catch {
21443
+ }
21444
+ }
21445
+ overflow(taskId) {
21446
+ this.warn("project-room:task-realtime-overflow", { code: "TASK_REALTIME_QUEUE_FULL", taskId });
21447
+ return Promise.resolve();
21448
+ }
21449
+ };
21450
+ function safeId3(value) {
21451
+ return typeof value === "string" && value.length > 0 ? value : void 0;
21452
+ }
21453
+
21454
+ // src/services/collaboration/ProjectRoomRealtimeRuntime.ts
21455
+ var ProjectRoomRealtimeRuntime = class {
21456
+ constructor(deps) {
21457
+ this.deps = deps;
21458
+ this.accepted = /* @__PURE__ */ new Set();
21459
+ this.broker = deps.broker;
21460
+ this.publisher = deps.publisher;
21461
+ this.shutdownTimeoutMs = deps.shutdownTimeoutMs ?? 5e3;
21462
+ this.unsubscribe = deps.subscribe(((event) => {
21463
+ let work;
21464
+ try {
21465
+ work = Promise.resolve(deps.subscriber.handle(event));
21466
+ } catch (error) {
21467
+ work = Promise.reject(error);
21468
+ }
21469
+ const accepted = work.catch((error) => {
21470
+ deps.log.warn("project-room:task-subscriber-failed", { error: error instanceof Error ? error.name : "UnknownError" });
21471
+ });
21472
+ this.accepted.add(accepted);
21473
+ void accepted.finally(() => this.accepted.delete(accepted));
21474
+ }));
21475
+ }
21476
+ /** Stops admission, drains accepted work, and closes transport resources exactly once. */
21477
+ close() {
21478
+ this.closing ?? (this.closing = this.dispose());
21479
+ return this.closing;
21480
+ }
21481
+ async dispose() {
21482
+ this.unsubscribe();
21483
+ this.deps.subscriber.closeAdmission();
21484
+ const accepted = [...this.accepted];
21485
+ const drained = await boundedAllSettled(accepted, this.shutdownTimeoutMs);
21486
+ if (!drained) this.deps.log.warn("project-room:runtime-drain-timeout", {
21487
+ timeoutMs: this.shutdownTimeoutMs,
21488
+ pending: accepted.length
21489
+ });
21490
+ await this.deps.subscriber.drain(drained ? this.shutdownTimeoutMs : 0);
21491
+ this.broker.close();
21492
+ }
21493
+ };
21494
+ function createProjectRoomRealtimeRuntime(deps) {
21495
+ const broker = new ProjectRoomEventBroker({ log: deps.log });
21496
+ const publisher = new BrokerProjectRoomRealtimePublisher({ broker, log: deps.log });
21497
+ const subscriber = new ProjectRoomTaskEventSubscriber({
21498
+ tasks: deps.tasks,
21499
+ rooms: deps.rooms,
21500
+ memberships: deps.memberships,
21501
+ realtime: publisher,
21502
+ log: deps.log
21503
+ });
21504
+ return new ProjectRoomRealtimeRuntime({
21505
+ broker,
21506
+ publisher,
21507
+ subscriber,
21508
+ subscribe: (listener) => import_core50.taskLifecycleNotifier.subscribe(listener),
21509
+ log: deps.log,
21510
+ shutdownTimeoutMs: deps.shutdownTimeoutMs
21511
+ });
21512
+ }
21513
+ async function boundedAllSettled(promises, timeoutMs) {
21514
+ if (promises.length === 0) return true;
21515
+ let timer;
21516
+ const timeout = new Promise((resolve4) => {
21517
+ timer = setTimeout(() => resolve4(false), timeoutMs);
21518
+ timer.unref?.();
21519
+ });
21520
+ const result = await Promise.race([Promise.allSettled(promises).then(() => true), timeout]);
21521
+ if (timer) clearTimeout(timer);
21522
+ return result;
21523
+ }
21524
+
21525
+ // src/services/collaboration/WorkspaceRoomEventsService.ts
21526
+ var import_protocols24 = require("@axiom-lattice/protocols");
21527
+
21528
+ // src/services/collaboration/ProjectRoomSseWriter.ts
21529
+ var DEFAULT_MAX_FRAMES = 256;
21530
+ var DEFAULT_MAX_BYTES = 1024 * 1024;
21531
+ var DEFAULT_DRAIN_TIMEOUT_MS = 1e4;
21532
+ function serializeBusiness(event) {
21533
+ return `id: ${event.id}
21534
+ event: ${event.type}
21535
+ data: ${JSON.stringify(event)}
21536
+
21537
+ `;
21538
+ }
21539
+ function serializeControl(event) {
21540
+ return `event: ${event.type}
21541
+ data: ${JSON.stringify(event.data)}
21542
+
21543
+ `;
21544
+ }
21545
+ var ProjectRoomSseWriter = class {
21546
+ /** Creates a writer over a raw HTTP response/socket. */
21547
+ constructor(raw, options = {}) {
21548
+ this.raw = raw;
21549
+ this.frames = [];
21550
+ this.queuedBytes = 0;
21551
+ this.blockedBytes = 0;
21552
+ this.writing = false;
21553
+ this.closed = false;
21554
+ this.terminal = false;
21555
+ this.slowConsumerAttempted = false;
21556
+ this.closeListener = () => this.close();
21557
+ this.errorListener = () => this.close();
21558
+ this.drainListener = () => {
21559
+ if (this.closed || !this.writing) return;
21560
+ this.clearDrainTimer();
21561
+ this.blockedBytes = 0;
21562
+ this.writing = false;
21563
+ this.flush();
21564
+ };
21565
+ this.maxFrames = positive(options.maxFrames ?? DEFAULT_MAX_FRAMES, "maxFrames");
21566
+ this.maxBytes = positive(options.maxBytes ?? DEFAULT_MAX_BYTES, "maxBytes");
21567
+ this.drainTimeoutMs = positive(options.drainTimeoutMs ?? DEFAULT_DRAIN_TIMEOUT_MS, "drainTimeoutMs");
21568
+ this.onClose = options.onClose;
21569
+ raw.on("close", this.closeListener).on("error", this.errorListener).on("drain", this.drainListener);
21570
+ }
21571
+ /** Enqueues one public business event. */
21572
+ enqueueBusiness(event) {
21573
+ this.enqueue(serializeBusiness(event));
21574
+ }
21575
+ /** Enqueues one connection control event. */
21576
+ enqueueControl(event) {
21577
+ this.enqueue(serializeControl(event));
21578
+ }
21579
+ /** Enqueues a pre-serialized SSE frame (used by scoped multi-room streams). */
21580
+ enqueueRaw(frame) {
21581
+ this.enqueue(frame);
21582
+ }
21583
+ /** Writes a heartbeat comment when the socket is not currently blocked. */
21584
+ heartbeat() {
21585
+ if (!this.closed && !this.writing) this.writeFrame(": heartbeat\n\n");
21586
+ }
21587
+ /** Closes the writer and removes every socket listener exactly once. */
21588
+ close() {
21589
+ if (this.closed) return;
21590
+ this.closed = true;
21591
+ this.clearDrainTimer();
21592
+ if (this.terminalTimer !== void 0) clearTimeout(this.terminalTimer);
21593
+ this.terminalResolve?.();
21594
+ this.terminalResolve = void 0;
21595
+ this.terminalFinish = void 0;
21596
+ this.raw.off("close", this.closeListener).off("error", this.errorListener).off("drain", this.drainListener);
21597
+ this.frames.length = 0;
21598
+ this.queuedBytes = 0;
21599
+ try {
21600
+ this.raw.end();
21601
+ } catch {
21602
+ this.raw.destroy();
21603
+ }
21604
+ this.onClose?.();
21605
+ }
21606
+ /** Stops ordinary delivery and attempts one terminal control before ending. */
21607
+ closeWithControl(control, deadlineMs = 250) {
21608
+ if (this.closed) return Promise.resolve();
21609
+ if (this.terminal) return new Promise((resolve4) => {
21610
+ this.terminalResolve = resolve4;
21611
+ });
21612
+ this.terminal = true;
21613
+ this.frames.length = 0;
21614
+ this.queuedBytes = 0;
21615
+ const frame = serializeControl(control);
21616
+ const finish = () => {
21617
+ if (this.closed) return;
21618
+ if (this.terminalTimer !== void 0) clearTimeout(this.terminalTimer);
21619
+ this.terminalTimer = void 0;
21620
+ this.close();
21621
+ };
21622
+ this.terminalFinish = finish;
21623
+ const promise = new Promise((resolve4) => {
21624
+ this.terminalResolve = resolve4;
21625
+ });
21626
+ if (!this.writing) {
21627
+ try {
21628
+ if (this.raw.write(frame)) finish();
21629
+ else this.armTerminalDeadline(deadlineMs, finish);
21630
+ } catch {
21631
+ finish();
21632
+ }
21633
+ } else {
21634
+ this.frames.push(frame);
21635
+ this.flushTerminal(finish);
21636
+ this.armTerminalDeadline(deadlineMs, finish);
21637
+ }
21638
+ return promise;
21639
+ }
21640
+ enqueue(frame) {
21641
+ if (this.closed || this.terminal) return;
21642
+ const bytes = Buffer.byteLength(frame, "utf8");
21643
+ const inFlightFrames = this.writing ? 1 : 0;
21644
+ if (bytes > this.maxBytes || this.frames.length + inFlightFrames + 1 > this.maxFrames || this.queuedBytes + this.blockedBytes + bytes > this.maxBytes) return this.failSlowConsumer();
21645
+ this.frames.push(frame);
21646
+ this.queuedBytes += bytes;
21647
+ this.flush();
21648
+ }
21649
+ flush() {
21650
+ if (this.closed || this.writing || this.frames.length === 0) return;
21651
+ const frame = this.frames.shift();
21652
+ if (!frame) return;
21653
+ this.queuedBytes -= Buffer.byteLength(frame, "utf8");
21654
+ if (this.terminal) this.writeTerminalFrame(frame, this.terminalFinish ?? (() => this.close()));
21655
+ else this.writeFrame(frame);
21656
+ }
21657
+ flushTerminal(finish) {
21658
+ if (this.closed || this.writing || this.frames.length === 0) return;
21659
+ const frame = this.frames.shift();
21660
+ if (!frame) return;
21661
+ this.writeTerminalFrame(frame, finish);
21662
+ }
21663
+ writeTerminalFrame(frame, finish) {
21664
+ try {
21665
+ if (!this.raw.write(frame)) {
21666
+ this.writing = true;
21667
+ this.blockedBytes = Buffer.byteLength(frame, "utf8");
21668
+ } else {
21669
+ this.writing = false;
21670
+ this.blockedBytes = 0;
21671
+ (finish ?? (() => this.close()))();
21672
+ }
21673
+ } catch {
21674
+ this.close();
21675
+ }
21676
+ }
21677
+ armTerminalDeadline(deadlineMs, finish) {
21678
+ this.terminalTimer = setTimeout(finish, deadlineMs);
21679
+ this.terminalTimer.unref?.();
21680
+ }
21681
+ writeFrame(frame) {
21682
+ if (this.closed) return;
20937
21683
  try {
20938
- this.deps.log.warn(message, context);
21684
+ if (!this.raw.write(frame)) {
21685
+ this.writing = true;
21686
+ this.blockedBytes = Buffer.byteLength(frame, "utf8");
21687
+ this.drainTimer = setTimeout(() => {
21688
+ this.drainTimer = void 0;
21689
+ this.failSlowConsumer();
21690
+ }, this.drainTimeoutMs);
21691
+ this.drainTimer.unref?.();
21692
+ } else {
21693
+ this.writing = false;
21694
+ this.blockedBytes = 0;
21695
+ this.flush();
21696
+ }
20939
21697
  } catch {
21698
+ this.close();
20940
21699
  }
20941
21700
  }
20942
- overflow(taskId) {
20943
- this.warn("project-room:task-realtime-overflow", { code: "TASK_REALTIME_QUEUE_FULL", taskId });
20944
- return Promise.resolve();
21701
+ clearDrainTimer() {
21702
+ if (this.drainTimer !== void 0) clearTimeout(this.drainTimer);
21703
+ this.drainTimer = void 0;
21704
+ }
21705
+ failSlowConsumer() {
21706
+ if (this.closed) return;
21707
+ this.frames.length = 0;
21708
+ this.queuedBytes = 0;
21709
+ if (!this.slowConsumerAttempted) {
21710
+ this.slowConsumerAttempted = true;
21711
+ try {
21712
+ this.raw.write(serializeControl({ type: "resync", data: { reason: "SLOW_CONSUMER" } }));
21713
+ } catch {
21714
+ }
21715
+ }
21716
+ this.close();
20945
21717
  }
20946
21718
  };
20947
- function safeId3(value) {
20948
- return typeof value === "string" && value.length > 0 ? value : void 0;
21719
+ function positive(value, name) {
21720
+ if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError(`${name} must be positive`);
21721
+ return value;
20949
21722
  }
20950
21723
 
20951
- // src/services/collaboration/ProjectRoomRealtimeRuntime.ts
20952
- var ProjectRoomRealtimeRuntime = class {
21724
+ // src/services/collaboration/WorkspaceRoomEventsService.ts
21725
+ var MAX_NODE_TIMER_DELAY = 2147e6;
21726
+ var WorkspaceRoomEventsService = class {
21727
+ /** Creates a service over the shared process-local broker. */
20953
21728
  constructor(deps) {
20954
21729
  this.deps = deps;
20955
- this.accepted = /* @__PURE__ */ new Set();
20956
- this.broker = deps.broker;
20957
- this.publisher = deps.publisher;
20958
- this.service = deps.service;
20959
- this.shutdownTimeoutMs = deps.shutdownTimeoutMs ?? 5e3;
20960
- this.unsubscribe = deps.subscribe(((event) => {
20961
- let work;
20962
- try {
20963
- work = Promise.resolve(deps.subscriber.handle(event));
20964
- } catch (error) {
20965
- work = Promise.reject(error);
20966
- }
20967
- const accepted = work.catch((error) => {
20968
- deps.log.warn("project-room:task-subscriber-failed", { error: error instanceof Error ? error.name : "UnknownError" });
20969
- });
20970
- this.accepted.add(accepted);
20971
- void accepted.finally(() => this.accepted.delete(accepted));
20972
- }));
21730
+ this.connections = /* @__PURE__ */ new Map();
21731
+ this.closed = false;
21732
+ this.now = deps.now ?? Date.now;
21733
+ this.heartbeatMs = deps.heartbeatMs ?? 15e3;
21734
+ this.authRecheckMs = deps.authRecheckMs ?? 15e3;
21735
+ this.maxConnectionsPerUser = deps.maxConnectionsPerUser ?? 2;
21736
+ this.maxTimerDelay = deps.maxTimerDelay ?? MAX_NODE_TIMER_DELAY;
20973
21737
  }
20974
- /** Stops admission, drains accepted work, and closes transport resources exactly once. */
21738
+ /** Starts a live-only connection; the route performs authentication beforehand. */
21739
+ connect(input) {
21740
+ if (this.closed) {
21741
+ input.raw.end();
21742
+ return;
21743
+ }
21744
+ const userKey = JSON.stringify([input.actor.tenantId, input.actor.userId]);
21745
+ const active = this.connections.get(userKey) ?? /* @__PURE__ */ new Set();
21746
+ if (active.size >= this.maxConnectionsPerUser) {
21747
+ const oldest = [...active].sort((left, right) => left.startedAt - right.startedAt)[0];
21748
+ oldest?.supersede();
21749
+ }
21750
+ const connection = this.buildConnection(input.actor, input.workspaceId, input.raw);
21751
+ active.add(connection);
21752
+ this.connections.set(userKey, active);
21753
+ }
21754
+ /** Closes every connection and stops admitting new ones. */
20975
21755
  close() {
20976
- this.closing ?? (this.closing = this.dispose());
20977
- return this.closing;
21756
+ if (this.closed) return;
21757
+ this.closed = true;
21758
+ for (const active of [...this.connections.values()]) for (const connection of [...active]) connection.close();
21759
+ this.connections.clear();
20978
21760
  }
20979
- async dispose() {
20980
- this.unsubscribe();
20981
- this.deps.subscriber.closeAdmission();
20982
- const accepted = [...this.accepted];
20983
- const drained = await boundedAllSettled(accepted, this.shutdownTimeoutMs);
20984
- if (!drained) this.deps.log.warn("project-room:runtime-drain-timeout", {
20985
- timeoutMs: this.shutdownTimeoutMs,
20986
- pending: accepted.length
21761
+ buildConnection(actor2, workspaceId, raw) {
21762
+ let phase = "initializing";
21763
+ const subscriptions = /* @__PURE__ */ new Map();
21764
+ let heartbeatTimer;
21765
+ let accessTimer;
21766
+ let expiryTimer;
21767
+ let closed = false;
21768
+ const recordRef = {};
21769
+ let rebuildTail = Promise.resolve(true);
21770
+ const lifetimeAbort = new AbortController();
21771
+ const clear = (timer) => {
21772
+ if (timer !== void 0) clearTimeout(timer);
21773
+ };
21774
+ const userScope = (0, import_protocols24.projectRoomUserEventScope)(actor2.tenantId, actor2.userId);
21775
+ const userScopeKey = JSON.stringify([userScope.tenantId, userScope.roomId, userScope.projectId]);
21776
+ const roomScopeKey = (scope) => JSON.stringify([scope.tenantId, scope.roomId, scope.projectId]);
21777
+ const serializeScoped = (scope, event) => scope === null ? `id: ${event.id}
21778
+ event: ${event.type}
21779
+ data: ${JSON.stringify(event)}
21780
+
21781
+ ` : `id: ${event.id}
21782
+ event: ${event.type}
21783
+ data: ${JSON.stringify({ ...event, scope })}
21784
+
21785
+ `;
21786
+ const writer = new ProjectRoomSseWriter(raw, { onClose: () => cleanup() });
21787
+ const cleanup = () => {
21788
+ if (closed) return;
21789
+ closed = true;
21790
+ phase = "closed";
21791
+ clear(heartbeatTimer);
21792
+ clear(accessTimer);
21793
+ clear(expiryTimer);
21794
+ lifetimeAbort.abort();
21795
+ for (const entry of subscriptions.values()) entry.unsubscribe();
21796
+ subscriptions.clear();
21797
+ writer.close();
21798
+ const userKey = JSON.stringify([actor2.tenantId, actor2.userId]);
21799
+ const active = this.connections.get(userKey);
21800
+ if (active && recordRef.current !== void 0) {
21801
+ active.delete(recordRef.current);
21802
+ if (active.size === 0) this.connections.delete(userKey);
21803
+ }
21804
+ };
21805
+ const revoke = (reason) => {
21806
+ if (closed) return;
21807
+ void writer.closeWithControl({ type: "access.revoked", data: { reason } }).then(cleanup, cleanup);
21808
+ };
21809
+ const record = {
21810
+ startedAt: this.now(),
21811
+ supersede: () => revoke("CONNECTION_SUPERSEDED"),
21812
+ close: cleanup
21813
+ };
21814
+ recordRef.current = record;
21815
+ const rebuildSubscriptions = async () => {
21816
+ try {
21817
+ const rooms = await this.deps.listMemberRooms({ tenantId: actor2.tenantId, userId: actor2.userId, workspaceId });
21818
+ if (closed) return true;
21819
+ const wanted = /* @__PURE__ */ new Map();
21820
+ for (const room of rooms) {
21821
+ const scope = { tenantId: actor2.tenantId, roomId: room.roomId, projectId: room.projectId };
21822
+ wanted.set(roomScopeKey(scope), scope);
21823
+ }
21824
+ for (const [key, entry] of [...subscriptions]) {
21825
+ if (key === userScopeKey || wanted.has(key)) continue;
21826
+ entry.unsubscribe();
21827
+ subscriptions.delete(key);
21828
+ }
21829
+ for (const [key, scope] of wanted) {
21830
+ if (subscriptions.has(key)) continue;
21831
+ const subscription = this.deps.broker.subscribe(scope, void 0, roomListener(scope));
21832
+ subscriptions.set(key, { scope, unsubscribe: subscription.unsubscribe });
21833
+ }
21834
+ if (!subscriptions.has(userScopeKey)) {
21835
+ const subscription = this.deps.broker.subscribe(userScope, void 0, userListener);
21836
+ subscriptions.set(userScopeKey, { scope: userScope, unsubscribe: subscription.unsubscribe });
21837
+ }
21838
+ return true;
21839
+ } catch (error) {
21840
+ this.deps.log.warn("workspace-room-events:resubscribe-failed", {
21841
+ error: error instanceof Error ? error.message : String(error)
21842
+ });
21843
+ return false;
21844
+ }
21845
+ };
21846
+ const enqueueRebuild = () => {
21847
+ rebuildTail = rebuildTail.then(rebuildSubscriptions, rebuildSubscriptions);
21848
+ };
21849
+ const userListener = (event) => {
21850
+ if (phase === "live") writer.enqueueRaw(serializeScoped(null, event));
21851
+ if (event.type === "membership.affected") enqueueRebuild();
21852
+ };
21853
+ const roomListener = (scope) => (event) => {
21854
+ if (phase === "live") writer.enqueueRaw(serializeScoped(scope, event));
21855
+ };
21856
+ const scheduleExpiry = () => {
21857
+ if (closed) return;
21858
+ const delay2 = actor2.tokenExpiresAt - this.now();
21859
+ if (delay2 <= 0) {
21860
+ revoke("TOKEN_EXPIRED");
21861
+ return;
21862
+ }
21863
+ expiryTimer = setTimeout(() => {
21864
+ expiryTimer = void 0;
21865
+ scheduleExpiry();
21866
+ }, Math.min(delay2, this.maxTimerDelay));
21867
+ expiryTimer.unref?.();
21868
+ };
21869
+ const scheduleHeartbeat = () => {
21870
+ if (closed) return;
21871
+ heartbeatTimer = setTimeout(() => {
21872
+ heartbeatTimer = void 0;
21873
+ if (closed) return;
21874
+ writer.heartbeat();
21875
+ scheduleHeartbeat();
21876
+ }, this.heartbeatMs);
21877
+ heartbeatTimer.unref?.();
21878
+ };
21879
+ const scheduleAccessCheck = () => {
21880
+ if (closed) return;
21881
+ accessTimer = setTimeout(() => {
21882
+ accessTimer = void 0;
21883
+ if (closed) return;
21884
+ const projectIds = [...subscriptions.values()].map((entry) => entry.scope.projectId).filter((projectId) => projectId !== import_protocols24.PROJECT_ROOM_USER_CHANNEL_PROJECT);
21885
+ Promise.all(projectIds.map((projectId) => Promise.resolve().then(() => this.deps.requireReadAccess({ tenantId: actor2.tenantId, userId: actor2.userId, projectId })))).then(() => {
21886
+ if (!closed) scheduleAccessCheck();
21887
+ }, () => {
21888
+ if (!closed) revoke("PROJECT_ACCESS_REVOKED");
21889
+ });
21890
+ }, this.authRecheckMs);
21891
+ accessTimer.unref?.();
21892
+ };
21893
+ scheduleHeartbeat();
21894
+ enqueueRebuild();
21895
+ const initialRebuild = rebuildTail;
21896
+ void initialRebuild.then((ok) => {
21897
+ if (closed) return;
21898
+ if (!ok) {
21899
+ cleanup();
21900
+ return;
21901
+ }
21902
+ writer.enqueueControl({ type: "ready", data: { epoch: this.deps.broker.epoch, headEventId: null } });
21903
+ phase = "live";
21904
+ scheduleExpiry();
21905
+ scheduleAccessCheck();
20987
21906
  });
20988
- await this.deps.subscriber.drain(drained ? this.shutdownTimeoutMs : 0);
20989
- this.service.close();
20990
- this.broker.close();
21907
+ return record;
20991
21908
  }
20992
21909
  };
20993
- function createProjectRoomRealtimeRuntime(deps) {
20994
- const broker = new ProjectRoomEventBroker({ log: deps.log });
20995
- const publisher = new BrokerProjectRoomRealtimePublisher({ broker, log: deps.log });
20996
- const service2 = new ProjectRoomRealtimeService({ broker, log: deps.log, requireReadAccess: deps.requireReadAccess });
20997
- const subscriber = new ProjectRoomTaskEventSubscriber({
20998
- tasks: deps.tasks,
20999
- rooms: deps.rooms,
21000
- memberships: deps.memberships,
21001
- realtime: publisher,
21002
- log: deps.log
21003
- });
21004
- return new ProjectRoomRealtimeRuntime({
21005
- broker,
21006
- publisher,
21007
- service: service2,
21008
- subscriber,
21009
- subscribe: (listener) => import_core50.taskLifecycleNotifier.subscribe(listener),
21010
- log: deps.log,
21011
- shutdownTimeoutMs: deps.shutdownTimeoutMs
21012
- });
21013
- }
21014
- async function boundedAllSettled(promises, timeoutMs) {
21015
- if (promises.length === 0) return true;
21016
- let timer;
21017
- const timeout = new Promise((resolve4) => {
21018
- timer = setTimeout(() => resolve4(false), timeoutMs);
21019
- timer.unref?.();
21020
- });
21021
- const result = await Promise.race([Promise.allSettled(promises).then(() => true), timeout]);
21022
- if (timer) clearTimeout(timer);
21023
- return result;
21910
+
21911
+ // src/services/collaboration/WorkspaceMemberRoomLister.ts
21912
+ function createWorkspaceMemberRoomLister(deps) {
21913
+ return async (input) => {
21914
+ const projects = await deps.projects.getProjectsByWorkspace(input.tenantId, input.workspaceId);
21915
+ const memberRooms = [];
21916
+ for (const project of projects) {
21917
+ const membership = await deps.memberships.findByUser(input.tenantId, project.id, input.userId);
21918
+ if (!membership || membership.status !== "active") continue;
21919
+ const room = await deps.rooms.getMainRoom(input.tenantId, project.id);
21920
+ if (room) memberRooms.push({ projectId: project.id, roomId: room.id });
21921
+ }
21922
+ return memberRooms;
21923
+ };
21024
21924
  }
21025
21925
 
21026
- // src/routes/project-room-events.ts
21027
- var import_protocols23 = require("@axiom-lattice/protocols");
21028
- function registerProjectRoomEventRoutes(app2, deps) {
21029
- app2.get("/api/projects/:projectId/room/events", async (request, reply) => {
21926
+ // src/routes/workspace-room-events.ts
21927
+ var import_protocols25 = require("@axiom-lattice/protocols");
21928
+ function registerWorkspaceRoomEventRoutes(app2, deps) {
21929
+ app2.get("/api/workspaces/:workspaceId/room-events", async (request, reply) => {
21030
21930
  try {
21031
- const projectId = exactProjectId(request.params);
21032
- const headers = strictHeaders(request, true);
21931
+ const params = exactParams(request.params);
21932
+ const headers = strictHeaders(request);
21033
21933
  if (request.body !== void 0 || Object.keys(request.query).length !== 0) return invalid(reply);
21034
21934
  const session = verifyConsoleSessionAuthHeader(headers.authorization, deps.tokenSecret);
21035
21935
  if (!session?.tenantId) return unauthorized(reply);
21036
- await deps.access.requireExistingProjectAccess({ tenantId: session.tenantId, userId: session.id, projectId, capability: "read" });
21037
- const room = exactRoom(await deps.rooms.getMainRoom(session.tenantId, projectId), session.tenantId, projectId);
21038
- if (!room) return reply.code(404).send({ success: false, error: { code: "PROJECT_ROOM_NOT_FOUND", message: "Project room not found", retryable: false } });
21039
- const actor2 = { tenantId: session.tenantId, userId: session.id, projectId, tokenExpiresAt: session.expiresAt };
21040
- if (!deps.realtime.canConnect(actor2)) return reply.code(429).send({ success: false, error: { code: "PROJECT_ROOM_STREAM_LIMIT", message: "Project room stream limit reached", retryable: true } });
21041
21936
  reply.hijack();
21042
21937
  reply.raw.writeHead(200, {
21043
21938
  "Content-Type": "text/event-stream",
@@ -21046,53 +21941,35 @@ function registerProjectRoomEventRoutes(app2, deps) {
21046
21941
  "X-Accel-Buffering": "no",
21047
21942
  "Access-Control-Allow-Origin": "*"
21048
21943
  });
21049
- deps.realtime.connect({ actor: actor2, roomId: room.id, ...headers.lastEventId ? { lastEventId: headers.lastEventId } : {}, raw: reply.raw });
21050
- } catch (error) {
21051
- return routeError(reply, error);
21052
- }
21053
- });
21054
- app2.get("/api/projects/:projectId/room/realtime-mode", async (request, reply) => {
21055
- try {
21056
- const projectId = exactProjectId(request.params);
21057
- const headers = strictHeaders(request, false);
21058
- if (request.body !== void 0 || Object.keys(request.query).length !== 0) return invalid(reply);
21059
- const session = verifyConsoleSessionAuthHeader(headers.authorization, deps.tokenSecret);
21060
- if (!session?.tenantId) return unauthorized(reply);
21061
- await deps.access.requireExistingProjectAccess({ tenantId: session.tenantId, userId: session.id, projectId, capability: "read" });
21062
- return reply.send({ success: true, data: { mode: "single-gateway", supportedGatewayProcesses: 1, durableReplay: false, epoch: deps.broker.epoch } });
21944
+ deps.service.connect({
21945
+ actor: { tenantId: session.tenantId, userId: session.id, tokenExpiresAt: session.expiresAt },
21946
+ workspaceId: params.workspaceId,
21947
+ raw: reply.raw
21948
+ });
21063
21949
  } catch (error) {
21064
21950
  return routeError(reply, error);
21065
21951
  }
21066
21952
  });
21067
21953
  }
21068
- function strictHeaders(request, requireSse) {
21954
+ function exactParams(params) {
21955
+ const value = (0, import_protocols25.snapshotExactRecord)(params, ["workspaceId"]);
21956
+ if (!value || typeof value.workspaceId !== "string" || !value.workspaceId.trim()) throw new InvalidRealtimeRequestError();
21957
+ return { workspaceId: value.workspaceId };
21958
+ }
21959
+ function strictHeaders(request) {
21069
21960
  const raw = request.raw.rawHeaders;
21070
21961
  const values = (name) => raw.flatMap((value, index) => index % 2 === 0 && value.toLowerCase() === name ? [raw[index + 1]] : []);
21071
21962
  const authorization = values("authorization");
21072
21963
  const accept = values("accept");
21073
21964
  const cursor = values("last-event-id");
21074
- if (authorization.length !== 1 || authorization[0].includes(",") || cursor.length > 1 || cursor.some((value) => value.includes(",")) || requireSse && (accept.length !== 1 || !isSseAccept(accept[0]))) {
21075
- throw new InvalidRealtimeRequestError();
21076
- }
21077
- const lastEventId = cursor[0]?.trim();
21078
- if (lastEventId !== void 0 && (!lastEventId || !(0, import_protocols23.isProjectRoomEventId)(lastEventId))) throw new InvalidRealtimeRequestError();
21079
- return { authorization: authorization[0], ...lastEventId ? { lastEventId } : {} };
21965
+ if (authorization.length !== 1 || authorization[0].includes(",") || cursor.length > 0 || accept.length !== 1 || !isSseAccept(accept[0])) throw new InvalidRealtimeRequestError();
21966
+ return { authorization: authorization[0] };
21080
21967
  }
21081
21968
  function isSseAccept(value) {
21082
21969
  if (value.includes(",")) return false;
21083
21970
  const [mediaType, ...parameters] = value.split(";");
21084
21971
  return mediaType.trim() === "text/event-stream" && parameters.every((parameter) => /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\s*=\s*(?:[!#$%&'*+.^_`|~0-9A-Za-z-]+|"[^"]*")$/.test(parameter.trim()));
21085
21972
  }
21086
- function exactProjectId(params) {
21087
- const value = (0, import_protocols23.snapshotExactRecord)(params, ["projectId"]);
21088
- if (!value || typeof value.projectId !== "string" || !value.projectId.trim()) throw new InvalidRealtimeRequestError();
21089
- return value.projectId;
21090
- }
21091
- function exactRoom(value, tenantId, projectId) {
21092
- if (!value || typeof value !== "object") return void 0;
21093
- const room = value;
21094
- return typeof room.id === "string" && room.id && room.tenantId === tenantId && room.projectId === projectId ? { id: room.id } : void 0;
21095
- }
21096
21973
  var InvalidRealtimeRequestError = class extends Error {
21097
21974
  };
21098
21975
  function invalid(reply) {
@@ -21103,7 +21980,6 @@ function unauthorized(reply) {
21103
21980
  }
21104
21981
  function routeError(reply, error) {
21105
21982
  if (error instanceof InvalidRealtimeRequestError) return invalid(reply);
21106
- if (error instanceof ProjectCollaborationError) return reply.code(error.statusCode).send({ success: false, error: { code: error.code, message: error.message, retryable: false } });
21107
21983
  return reply.code(500).send({ success: false, error: { code: "INTERNAL_ERROR", message: "Internal server error", retryable: false } });
21108
21984
  }
21109
21985
 
@@ -21204,7 +22080,7 @@ function snapshotDataRecord(value) {
21204
22080
  for (const key of Reflect.ownKeys(descriptors)) {
21205
22081
  if (typeof key !== "string") return void 0;
21206
22082
  const descriptor = descriptors[key];
21207
- const data = (0, import_protocols24.descriptorDataValue)(descriptor);
22083
+ const data = (0, import_protocols26.descriptorDataValue)(descriptor);
21208
22084
  if (!data) return void 0;
21209
22085
  result[key] = data.value;
21210
22086
  }
@@ -21219,7 +22095,7 @@ function isPublicRoomAddress(message) {
21219
22095
  }
21220
22096
  async function validateReassignmentThread(threads, input) {
21221
22097
  const thread = snapshotThread(await threads.getThreadById(input.tenantId, input.newThreadId));
21222
- const metadata = (0, import_protocols24.snapshotExactRecord)(thread?.metadata, [
22098
+ const metadata = (0, import_protocols26.snapshotExactRecord)(thread?.metadata, [
21223
22099
  "source",
21224
22100
  "kind",
21225
22101
  "workspaceId",
@@ -21242,6 +22118,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21242
22118
  const projectRoomStore = (0, import_core51.getStoreLattice)("default", "projectRoom").store;
21243
22119
  const projectBotMembershipStore = (0, import_core51.getStoreLattice)("default", "projectBotMembership").store;
21244
22120
  const projectRoomMessageStore = (0, import_core51.getStoreLattice)("default", "projectRoomMessage").store;
22121
+ const projectRoomReadStateStore = (0, import_core51.getStoreLattice)("default", "projectRoomReadState").store;
21245
22122
  const threadStore = (0, import_core51.getStoreLattice)("default", "thread").store;
21246
22123
  const taskStore = (0, import_core51.getStoreLattice)("default", "task").store;
21247
22124
  const taskWorkItemStore = (0, import_core51.getStoreLattice)("default", "taskWorkItem").store;
@@ -21253,23 +22130,30 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21253
22130
  tasks: taskStore,
21254
22131
  rooms: projectRoomStore,
21255
22132
  memberships: projectBotMembershipStore,
21256
- log: realtimeLog,
21257
- requireReadAccess: async (actor2) => {
21258
- await accessService.requireExistingProjectAccess({
21259
- tenantId: actor2.tenantId,
21260
- userId: actor2.userId,
21261
- projectId: actor2.projectId,
21262
- capability: "read"
21263
- });
21264
- }
22133
+ log: realtimeLog
21265
22134
  }) : void 0;
21266
22135
  if (projectRoomRealtimeRuntime) {
21267
22136
  app2.addHook("onClose", async () => projectRoomRealtimeRuntime?.close());
21268
- registerProjectRoomEventRoutes(app2, {
21269
- access: accessService,
21270
- rooms: projectRoomStore,
21271
- realtime: projectRoomRealtimeRuntime.service,
22137
+ const workspaceRoomEventsService = new WorkspaceRoomEventsService({
21272
22138
  broker: projectRoomRealtimeRuntime.broker,
22139
+ listMemberRooms: createWorkspaceMemberRoomLister({
22140
+ projects: projectStore,
22141
+ memberships: projectMembershipStore,
22142
+ rooms: projectRoomStore
22143
+ }),
22144
+ requireReadAccess: async (input) => {
22145
+ await accessService.requireExistingProjectAccess({
22146
+ tenantId: input.tenantId,
22147
+ userId: input.userId,
22148
+ projectId: input.projectId,
22149
+ capability: "read"
22150
+ });
22151
+ },
22152
+ log: realtimeLog
22153
+ });
22154
+ app2.addHook("onClose", async () => workspaceRoomEventsService.close());
22155
+ registerWorkspaceRoomEventRoutes(app2, {
22156
+ service: workspaceRoomEventsService,
21273
22157
  tokenSecret: resolveConsoleTokenSecret(process.env.AUTH_REQUIRED === "true")
21274
22158
  });
21275
22159
  }
@@ -21333,7 +22217,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21333
22217
  });
21334
22218
  }
21335
22219
  if (projectTaskComposition) app2.addHook("onClose", async () => projectTaskComposition.lease.release());
21336
- const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: import_node_crypto18.randomUUID });
22220
+ const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: import_node_crypto20.randomUUID });
21337
22221
  const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? (0, import_core51.createTaskLifecycleService)({ taskStore, workItemStore: taskWorkItemStore });
21338
22222
  const reassignmentAuthorizer = (0, import_core51.createProjectTaskReassignmentAuthorizer)(
21339
22223
  new import_core51.ProjectTaskOwnerPolicy(projectBotMembershipStore),
@@ -21351,7 +22235,24 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21351
22235
  saveBot: projectBotMembershipStore.save.bind(projectBotMembershipStore),
21352
22236
  ensureCoordinator: (tenantId) => coordinatorProvisioner.ensure(tenantId)
21353
22237
  });
21354
- registerProjectRoomRoutes(app2, { roomService, membershipService, messageService });
22238
+ const readStateService = {
22239
+ mark: async (actorRef) => {
22240
+ await accessService.requireExistingProjectAccess({ ...actorRef, capability: "read" });
22241
+ const room = await projectRoomStore.getMainRoom(actorRef.tenantId, actorRef.projectId);
22242
+ if (!room) return;
22243
+ const lastReadAt = /* @__PURE__ */ new Date();
22244
+ await projectRoomReadStateStore.markRead({ tenantId: actorRef.tenantId, roomId: room.id, userId: actorRef.userId, lastReadAt });
22245
+ projectRoomRealtimeRuntime?.publisher.readChanged({
22246
+ tenantId: actorRef.tenantId,
22247
+ userId: actorRef.userId,
22248
+ projectId: actorRef.projectId,
22249
+ roomId: room.id,
22250
+ lastReadAt: lastReadAt.toISOString(),
22251
+ sourceKey: `read:${actorRef.userId}:${room.id}:${lastReadAt.getTime()}`
22252
+ });
22253
+ }
22254
+ };
22255
+ registerProjectRoomRoutes(app2, { roomService, membershipService, messageService, readStateService });
21355
22256
  registerProjectRosterRoutes(app2, { service: rosterService });
21356
22257
  registerCoSpaceRoutes(app2, {
21357
22258
  projectStore: {
@@ -21373,7 +22274,11 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21373
22274
  },
21374
22275
  messageStore: {
21375
22276
  list: projectRoomMessageStore.list.bind(projectRoomMessageStore),
21376
- create: projectRoomMessageStore.create.bind(projectRoomMessageStore)
22277
+ create: projectRoomMessageStore.create.bind(projectRoomMessageStore),
22278
+ countAfter: projectRoomMessageStore.countAfter.bind(projectRoomMessageStore)
22279
+ },
22280
+ readStateStore: {
22281
+ get: projectRoomReadStateStore.get.bind(projectRoomReadStateStore)
21377
22282
  },
21378
22283
  userTenantLinkStore: {
21379
22284
  getUsersByTenant: userTenantLinkStore.getUsersByTenant.bind(userTenantLinkStore)
@@ -21416,6 +22321,46 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21416
22321
  })
21417
22322
  });
21418
22323
  registerAgentWebAppRuntimeRoutes(app2, {
22324
+ workspaceController: new WorkspaceController(createProjectCollaborationInitializer({
22325
+ membershipStore: projectMembershipStore,
22326
+ roomStore: projectRoomStore,
22327
+ userTenantLinkStore
22328
+ })),
22329
+ taskController: createTaskController({
22330
+ access: {
22331
+ requireProjectAccess: async (input) => {
22332
+ const apps = await webAppStore.list(input.tenantId);
22333
+ const allowed = apps.some((app3) => app3.status === "active" && app3.scope.allowedProjectIds.includes(input.projectId));
22334
+ if (!allowed) throw new ProjectCollaborationError("PROJECT_ACCESS_DENIED", 403, "Project is not exposed through this web app");
22335
+ const project = await projectStore.getProjectById(input.tenantId, input.projectId);
22336
+ if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
22337
+ return {
22338
+ project,
22339
+ membership: {
22340
+ id: `webapp_guest_${input.projectId}_${input.userId}`,
22341
+ tenantId: input.tenantId,
22342
+ projectId: input.projectId,
22343
+ userId: input.userId,
22344
+ role: "member",
22345
+ status: "active",
22346
+ joinedAt: /* @__PURE__ */ new Date(),
22347
+ updatedAt: /* @__PURE__ */ new Date()
22348
+ }
22349
+ };
22350
+ }
22351
+ },
22352
+ tasks: taskStore,
22353
+ workItems: taskWorkItemStore,
22354
+ bots: projectBotMembershipStore,
22355
+ rooms: projectRoomStore,
22356
+ threadService: taskThreadService,
22357
+ reassignmentAuthorizer,
22358
+ lifecycle: taskLifecycle,
22359
+ projectMutationMutex: import_core51.projectMutationMutex,
22360
+ executionMutex: projectTaskComposition?.mutex ?? {
22361
+ runExclusive: (_scope, operation) => operation()
22362
+ }
22363
+ }),
21419
22364
  service: new AgentWebAppRuntimeService({
21420
22365
  webAppStore,
21421
22366
  threadStore: (0, import_core51.getStoreLattice)("default", "thread").store,
@@ -21423,7 +22368,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21423
22368
  assistantResolver: {
21424
22369
  resolve: async (tenantId, assistantId) => {
21425
22370
  const stored = await assistantStore.getAssistantById(tenantId, assistantId);
21426
- if (stored) return stored;
22371
+ if (stored) return { id: stored.id, name: stored.name, description: stored.description };
21427
22372
  await import_core51.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId);
21428
22373
  const config = import_core51.agentLatticeManager.getAgentConfigWithTenant(tenantId, assistantId);
21429
22374
  return config ? { id: assistantId, name: config.name, description: config.description } : null;
@@ -21466,6 +22411,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21466
22411
  }
21467
22412
  })
21468
22413
  });
22414
+ registerAgentWebAppEmbedRoutes(app2, {});
21469
22415
  registerA2ABridgeRoutes(app2);
21470
22416
  registerSTTRoutes(app2);
21471
22417
  app2.get("/api/local-a2a", getLocalA2AStatus);
@@ -21790,9 +22736,9 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
21790
22736
  function tryCreateProjectTaskRuntime(input) {
21791
22737
  let projectWorkItems;
21792
22738
  try {
21793
- projectWorkItems = (0, import_protocols24.requireProjectTaskWorkItemStore)(input.taskWorkItemStore);
22739
+ projectWorkItems = (0, import_protocols26.requireProjectTaskWorkItemStore)(input.taskWorkItemStore);
21794
22740
  } catch (error) {
21795
- if (error instanceof import_protocols24.ProjectTaskStoreUnsupportedError) {
22741
+ if (error instanceof import_protocols26.ProjectTaskStoreUnsupportedError) {
21796
22742
  input.log?.warn("project-task:runtime-unavailable", {
21797
22743
  code: error.code,
21798
22744
  missingMethods: error.missingMethods
@@ -21837,7 +22783,7 @@ function tryCreateProjectTaskRuntime(input) {
21837
22783
  function createRuntime(input, stores, log2) {
21838
22784
  const controller = new AbortController();
21839
22785
  const mutex = new ProjectTaskExecutionMutex();
21840
- const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: import_node_crypto18.randomUUID });
22786
+ const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: import_node_crypto20.randomUUID });
21841
22787
  const lifecycle = (0, import_core51.createTaskLifecycleService)({ taskStore: input.taskStore, workItemStore: input.taskWorkItemStore });
21842
22788
  const projection = new RoomProjectionService({
21843
22789
  messages: input.projectRoomMessageStore,
@@ -21846,7 +22792,7 @@ function createRuntime(input, stores, log2) {
21846
22792
  warnings: input.taskWorkItemStore,
21847
22793
  log: log2,
21848
22794
  realtime: input.realtime,
21849
- idFactory: import_node_crypto18.randomUUID
22795
+ idFactory: import_node_crypto20.randomUUID
21850
22796
  });
21851
22797
  const agentFor = (task, thread) => import_core51.agentInstanceManager.getAgent({
21852
22798
  tenant_id: task.tenantId,
@@ -23701,7 +24647,7 @@ var import_core65 = require("@axiom-lattice/core");
23701
24647
 
23702
24648
  // src/router/MessageRouter.ts
23703
24649
  var import_core64 = require("@axiom-lattice/core");
23704
- var import_protocols25 = require("@axiom-lattice/protocols");
24650
+ var import_protocols27 = require("@axiom-lattice/protocols");
23705
24651
  var import_crypto11 = require("crypto");
23706
24652
  var BindingNotFoundError = class extends Error {
23707
24653
  constructor(message) {
@@ -23731,10 +24677,10 @@ var CORRELATED_REPLY_REQUIRED_KEYS = [
23731
24677
  "state"
23732
24678
  ];
23733
24679
  function exactDataValues(value, required, optional = []) {
23734
- return (0, import_protocols25.snapshotExactRecord)(value, required, optional);
24680
+ return (0, import_protocols27.snapshotExactRecord)(value, required, optional);
23735
24681
  }
23736
24682
  function uniqueNonemptyStrings(value) {
23737
- const snapshot = (0, import_protocols25.snapshotExactArray)(value);
24683
+ const snapshot = (0, import_protocols27.snapshotExactArray)(value);
23738
24684
  if (!snapshot || snapshot.length === 0 || snapshot.some((entry) => typeof entry !== "string" || entry.length === 0)) return void 0;
23739
24685
  const values = snapshot;
23740
24686
  return new Set(values).size === values.length ? values : void 0;
@@ -24171,9 +25117,9 @@ var MessageRouter = class {
24171
25117
  };
24172
25118
 
24173
25119
  // src/channels/room/RoomChannelAdapter.ts
24174
- var import_zod13 = require("zod");
24175
- var import_protocols26 = require("@axiom-lattice/protocols");
24176
- var roomConfigSchema = import_zod13.z.object({}).strict();
25120
+ var import_zod14 = require("zod");
25121
+ var import_protocols28 = require("@axiom-lattice/protocols");
25122
+ var roomConfigSchema = import_zod14.z.object({}).strict();
24177
25123
  function createRoomChannelAdapter(writer) {
24178
25124
  return {
24179
25125
  channel: "room",
@@ -24216,7 +25162,7 @@ function exactStrings(value, keys2) {
24216
25162
  function exactValues2(value, required, optional = []) {
24217
25163
  try {
24218
25164
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
24219
- return (0, import_protocols26.snapshotExactRecord)(value, required, optional);
25165
+ return (0, import_protocols28.snapshotExactRecord)(value, required, optional);
24220
25166
  } catch {
24221
25167
  return void 0;
24222
25168
  }
@@ -24261,14 +25207,14 @@ async function prepareProjectTaskRuntime(runtime, log2) {
24261
25207
  }
24262
25208
 
24263
25209
  // src/index.ts
24264
- var import_protocols28 = require("@axiom-lattice/protocols");
25210
+ var import_protocols30 = require("@axiom-lattice/protocols");
24265
25211
  process.on("unhandledRejection", (reason, promise) => {
24266
25212
  console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
24267
25213
  });
24268
25214
  var DEFAULT_LOGGER_CONFIG = {
24269
25215
  name: "default",
24270
25216
  description: "Default logger for lattice-gateway service",
24271
- type: import_protocols28.LoggerType.PINO,
25217
+ type: import_protocols30.LoggerType.PINO,
24272
25218
  serviceName: "lattice/gateway",
24273
25219
  loggerName: "lattice/gateway"
24274
25220
  };
@@ -24441,26 +25387,11 @@ var start = async (config) => {
24441
25387
  const projectRoomRealtimeMode = resolveProjectRoomRealtimeMode();
24442
25388
  let projectRoomRealtimeRuntime;
24443
25389
  if (projectRoomRealtimeMode === "single-gateway") {
24444
- const projectStore = (0, import_core70.getStoreLattice)("default", "project").store;
24445
- const membershipStore = (0, import_core70.getStoreLattice)("default", "projectMembership").store;
24446
- const access = new ProjectAccessService({
24447
- projectStore,
24448
- membershipStore,
24449
- userTenantLinkStore: (0, import_core70.getStoreLattice)("default", "userTenantLink").store
24450
- });
24451
25390
  projectRoomRealtimeRuntime = createProjectRoomRealtimeRuntime({
24452
25391
  tasks: (0, import_core70.getStoreLattice)("default", "task").store,
24453
25392
  rooms: (0, import_core70.getStoreLattice)("default", "projectRoom").store,
24454
25393
  memberships: (0, import_core70.getStoreLattice)("default", "projectBotMembership").store,
24455
- log: { warn: (message, context) => logger6.warn(message, context) },
24456
- requireReadAccess: async (actor2) => {
24457
- await access.requireExistingProjectAccess({
24458
- tenantId: actor2.tenantId,
24459
- userId: actor2.userId,
24460
- projectId: actor2.projectId,
24461
- capability: "read"
24462
- });
24463
- }
25394
+ log: { warn: (message, context) => logger6.warn(message, context) }
24464
25395
  });
24465
25396
  }
24466
25397
  let channelDeps;
@@ -24547,6 +25478,15 @@ var start = async (config) => {
24547
25478
  error: err instanceof Error ? err.message : String(err)
24548
25479
  });
24549
25480
  }
25481
+ try {
25482
+ const { registerOpenRoutes: registerOpenRoutes2 } = await Promise.resolve().then(() => (init_open(), open_exports));
25483
+ registerOpenRoutes2(app);
25484
+ logger6.info("Open MCP spike routes registered");
25485
+ } catch (err) {
25486
+ logger6.warn("Open MCP spike routes unavailable", {
25487
+ error: err instanceof Error ? err.message : String(err)
25488
+ });
25489
+ }
24550
25490
  if (!import_core70.sandboxLatticeManager.hasLattice("default")) {
24551
25491
  import_core70.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
24552
25492
  logger6.info("Registered sandbox manager from env configuration");