@holoscript/core 7.0.0 → 8.0.1

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 (350) hide show
  1. package/README.md +4 -4
  2. package/bin/holoscript.cjs +3 -0
  3. package/dist/GLTFPipeline-N6B6PJ6G.cjs +38 -0
  4. package/dist/GLTFPipeline-P3WMNYCN.js +17 -0
  5. package/dist/HoloScriptPlusParser-7FBIFUFC.js +693 -0
  6. package/dist/HoloScriptPlusParser-A2W7OCN2.cjs +698 -0
  7. package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
  8. package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
  9. package/dist/HoloScriptRuntime-CBYJX3LZ.js +10 -0
  10. package/dist/HoloScriptRuntime-VJ374RER.cjs +19 -0
  11. package/dist/USDZExporter-3FWJ25JI.cjs +1037 -0
  12. package/dist/USDZExporter-D2HQLQYK.js +1035 -0
  13. package/dist/agents/index.cjs +19 -0
  14. package/dist/agents/index.d.ts +100 -0
  15. package/dist/agents/index.js +17 -0
  16. package/dist/chunk-2BSMSUCE.js +1941 -0
  17. package/dist/chunk-2IWC4FP7.cjs +1189 -0
  18. package/dist/chunk-2M2DPHKB.js +762 -0
  19. package/dist/chunk-2X7NGX3M.js +2426 -0
  20. package/dist/chunk-2YSNA2F2.cjs +1274 -0
  21. package/dist/chunk-3FOKASKO.cjs +348 -0
  22. package/dist/chunk-3WZEJHUQ.cjs +116 -0
  23. package/dist/chunk-4C57PR42.js +468 -0
  24. package/dist/chunk-4GU5GCIY.js +1384 -0
  25. package/dist/chunk-4N4SXXWF.js +769 -0
  26. package/dist/chunk-4PDEPEQW.cjs +41 -0
  27. package/dist/chunk-4R6SBXDB.js +45 -0
  28. package/dist/chunk-4SDKXQ4C.js +811 -0
  29. package/dist/chunk-4V2E7U7Q.cjs +2015 -0
  30. package/dist/chunk-5FSKKMR7.cjs +2092 -0
  31. package/dist/chunk-5GLCTO44.js +161 -0
  32. package/dist/chunk-5H2G27PK.cjs +627 -0
  33. package/dist/chunk-5JEU52DW.js +382 -0
  34. package/dist/chunk-5NWINHR5.cjs +689 -0
  35. package/dist/chunk-5S7RKFGR.cjs +446 -0
  36. package/dist/chunk-5WUNN6ZN.cjs +428 -0
  37. package/dist/chunk-6CTRH7HT.cjs +1985 -0
  38. package/dist/chunk-6EX3I5P4.cjs +130 -0
  39. package/dist/chunk-6Q7RC2MK.cjs +1418 -0
  40. package/dist/chunk-7H33U5SM.cjs +413 -0
  41. package/dist/chunk-7M3PNU2M.cjs +672 -0
  42. package/dist/chunk-7T25IEZ2.js +449 -0
  43. package/dist/chunk-7V4JI5TB.cjs +6947 -0
  44. package/dist/chunk-A6KINLZJ.js +236 -0
  45. package/dist/chunk-ADADVMXY.js +404 -0
  46. package/dist/chunk-AIA52I7T.cjs +543 -0
  47. package/dist/chunk-ALC6K7GL.cjs +4402 -0
  48. package/dist/chunk-ANXZFVY2.js +113 -0
  49. package/dist/chunk-AOVGZ25K.cjs +56583 -0
  50. package/dist/chunk-AVJHHUC5.cjs +718 -0
  51. package/dist/chunk-BGY3SDG3.js +4396 -0
  52. package/dist/chunk-BOVPWH4H.js +3857 -0
  53. package/dist/chunk-BRQJKJGT.cjs +20 -0
  54. package/dist/chunk-C37BHB7N.cjs +636 -0
  55. package/dist/chunk-CBJY23VL.js +126 -0
  56. package/dist/chunk-CCATWPXM.js +778 -0
  57. package/dist/chunk-CIWWXYHZ.cjs +50 -0
  58. package/dist/chunk-CMT5NMMS.js +669 -0
  59. package/dist/chunk-CR4FMIWL.cjs +1049 -0
  60. package/dist/chunk-CR7XRXRN.cjs +639 -0
  61. package/dist/chunk-CSD27UNQ.js +2176 -0
  62. package/dist/chunk-D3STJ56J.js +714 -0
  63. package/dist/chunk-DAJXW4KX.js +725 -0
  64. package/dist/chunk-DHO2YRIM.js +756 -0
  65. package/dist/chunk-DTGBOSEM.cjs +319 -0
  66. package/dist/chunk-E6XXE66V.js +2252 -0
  67. package/dist/chunk-E7JP3BS3.cjs +61 -0
  68. package/dist/chunk-EKBKLK7P.js +1169 -0
  69. package/dist/chunk-EKYL4PE3.cjs +404 -0
  70. package/dist/chunk-EXKSFGSX.cjs +274 -0
  71. package/dist/chunk-EXUP2BUM.cjs +1173 -0
  72. package/dist/chunk-FDSGHPAK.js +130 -0
  73. package/dist/chunk-FEWUHQNM.cjs +144 -0
  74. package/dist/chunk-FFAOS5HQ.js +70 -0
  75. package/dist/chunk-FGGJQRLZ.js +270 -0
  76. package/dist/chunk-FHP6LXJS.js +415 -0
  77. package/dist/chunk-FJPADH77.cjs +666 -0
  78. package/dist/chunk-FL33V6U7.js +421 -0
  79. package/dist/chunk-FYSPZT4V.cjs +169 -0
  80. package/dist/chunk-GIOYPNTH.js +5575 -0
  81. package/dist/chunk-GJNCFRJU.cjs +125 -0
  82. package/dist/chunk-GMP623FG.cjs +1508 -0
  83. package/dist/chunk-GQHQOPXZ.cjs +5580 -0
  84. package/dist/chunk-GTU2Z2WW.cjs +262 -0
  85. package/dist/chunk-GYZE55MO.js +2007 -0
  86. package/dist/chunk-GZG4KA4E.js +529 -0
  87. package/dist/chunk-H652NHX5.js +600 -0
  88. package/dist/chunk-HCCQLAA4.cjs +74 -0
  89. package/dist/chunk-HKEXJUWS.cjs +4007 -0
  90. package/dist/chunk-HNDK4IQU.cjs +5737 -0
  91. package/dist/chunk-HR2OSYVQ.js +56165 -0
  92. package/dist/chunk-HYNTS5CP.js +422 -0
  93. package/dist/chunk-I6XZ5DZF.cjs +488 -0
  94. package/dist/chunk-ILRBGFVD.cjs +72 -0
  95. package/dist/chunk-IUDGEUDO.cjs +1409 -0
  96. package/dist/chunk-IUTY5WQ2.cjs +424 -0
  97. package/dist/chunk-IVY74O6C.js +247 -0
  98. package/dist/chunk-IWC5DM2M.cjs +611 -0
  99. package/dist/chunk-J32ZJZJH.js +554 -0
  100. package/dist/chunk-J52VSAQ7.js +6884 -0
  101. package/dist/chunk-J6M4FPK5.js +421 -0
  102. package/dist/chunk-J7XZV333.js +844 -0
  103. package/dist/chunk-JBNDTXXV.cjs +2433 -0
  104. package/dist/chunk-JC5YBPSF.cjs +984 -0
  105. package/dist/chunk-JD7CIZ33.js +1949 -0
  106. package/dist/chunk-JIBL5LRK.js +4287 -0
  107. package/dist/chunk-JIYN45TV.cjs +2525 -0
  108. package/dist/chunk-K574J76X.cjs +457 -0
  109. package/dist/chunk-KHDZJE5D.cjs +2196 -0
  110. package/dist/chunk-KKFZ3B6J.cjs +557 -0
  111. package/dist/chunk-KKP7JKN4.cjs +6002 -0
  112. package/dist/chunk-KPJL34Y7.cjs +186 -0
  113. package/dist/chunk-KQCN6AKJ.cjs +3042 -0
  114. package/dist/chunk-L5LKKENW.cjs +424 -0
  115. package/dist/chunk-LHAXPADA.js +882 -0
  116. package/dist/chunk-LM2VU56C.cjs +37 -0
  117. package/dist/chunk-M56JSP4A.js +400 -0
  118. package/dist/chunk-MBOOR7X4.js +18 -0
  119. package/dist/chunk-MQWAT42R.cjs +4310 -0
  120. package/dist/chunk-MXFUTKCO.js +56 -0
  121. package/dist/chunk-MYY4PMWX.cjs +264 -0
  122. package/dist/chunk-N75IH2HY.js +258 -0
  123. package/dist/chunk-NCWCUZNS.cjs +72 -0
  124. package/dist/chunk-NG77ATEW.cjs +778 -0
  125. package/dist/chunk-NW5G5FBQ.js +215 -0
  126. package/dist/chunk-OBIYPYYS.cjs +1993 -0
  127. package/dist/chunk-OH2FAIVU.js +608 -0
  128. package/dist/chunk-OIQYIIO3.cjs +473 -0
  129. package/dist/chunk-OL46QLBJ.js +61 -0
  130. package/dist/chunk-OMXII44L.js +5386 -0
  131. package/dist/chunk-OSYNRVOV.cjs +243 -0
  132. package/dist/chunk-PGANYCAG.cjs +220 -0
  133. package/dist/chunk-PHENW4MQ.js +65 -0
  134. package/dist/chunk-PY37LNDP.js +686 -0
  135. package/dist/chunk-Q56TT7IL.js +483 -0
  136. package/dist/chunk-QD32ADK6.js +1046 -0
  137. package/dist/chunk-QPOQ7VPI.js +1491 -0
  138. package/dist/chunk-QPSKHBJP.js +5963 -0
  139. package/dist/chunk-QXH7QDSZ.js +1989 -0
  140. package/dist/chunk-R24NNAEG.js +1399 -0
  141. package/dist/chunk-R75BSDH7.cjs +50 -0
  142. package/dist/chunk-RARB3MBR.js +207 -0
  143. package/dist/chunk-ROHLEP2W.cjs +847 -0
  144. package/dist/chunk-S3MDHNKB.cjs +490 -0
  145. package/dist/chunk-S6YWHCKV.cjs +410 -0
  146. package/dist/chunk-SIEXCILW.js +229 -0
  147. package/dist/chunk-SLU6UPJI.cjs +410 -0
  148. package/dist/chunk-SMIWS6DE.cjs +212 -0
  149. package/dist/chunk-T5J7ZKP3.cjs +4885 -0
  150. package/dist/chunk-TDCNJHWO.js +341 -0
  151. package/dist/chunk-TG7O4WBC.js +406 -0
  152. package/dist/chunk-THCK6ECW.js +2085 -0
  153. package/dist/chunk-TJHVSBP2.js +439 -0
  154. package/dist/chunk-TVHSPJ4N.cjs +606 -0
  155. package/dist/chunk-TWUXUCEW.cjs +781 -0
  156. package/dist/chunk-U44IKGG7.cjs +5390 -0
  157. package/dist/chunk-UFZZ7TSN.cjs +886 -0
  158. package/dist/chunk-UJXISJBN.js +487 -0
  159. package/dist/chunk-UOIGFQXC.cjs +9750 -0
  160. package/dist/chunk-URG2SJLK.js +2521 -0
  161. package/dist/chunk-UWJHCOH2.js +623 -0
  162. package/dist/chunk-V6MKC2FZ.js +979 -0
  163. package/dist/chunk-VJ3L7CHT.cjs +169 -0
  164. package/dist/chunk-VMLKSV26.js +1216 -0
  165. package/dist/chunk-VVKVQZI6.js +55 -0
  166. package/dist/chunk-W6RW64BB.cjs +1219 -0
  167. package/dist/chunk-WKX5AMOY.js +309 -0
  168. package/dist/chunk-WNNE3PO3.js +34 -0
  169. package/dist/chunk-WRKUDAZJ.js +3038 -0
  170. package/dist/chunk-WRLUBRKS.cjs +1943 -0
  171. package/dist/chunk-WRNEH5MO.js +3169 -0
  172. package/dist/chunk-WRWEX5ZF.js +658 -0
  173. package/dist/chunk-X3GJPRVK.cjs +3246 -0
  174. package/dist/chunk-X3UVCWNL.cjs +2257 -0
  175. package/dist/chunk-XB274MW5.cjs +814 -0
  176. package/dist/chunk-XHIV6326.cjs +793 -0
  177. package/dist/chunk-XIVIE43A.cjs +729 -0
  178. package/dist/chunk-XJAN7CZG.cjs +432 -0
  179. package/dist/chunk-XKTPFXGA.js +164 -0
  180. package/dist/chunk-XL6INWKT.js +121 -0
  181. package/dist/chunk-XSFNHP2E.js +632 -0
  182. package/dist/chunk-XT6JY5W5.js +9684 -0
  183. package/dist/chunk-XUILI4KB.cjs +430 -0
  184. package/dist/chunk-YF2I3MV3.js +46 -0
  185. package/dist/chunk-YIMN575O.js +4847 -0
  186. package/dist/chunk-YIVFJNYV.js +176 -0
  187. package/dist/chunk-YKGPCZEE.cjs +237 -0
  188. package/dist/chunk-YN2YWTXW.js +5731 -0
  189. package/dist/chunk-YN6V7R3L.cjs +327 -0
  190. package/dist/chunk-YQELFNJV.js +39 -0
  191. package/dist/chunk-YVD3CSO3.js +1183 -0
  192. package/dist/chunk-YVOAF4ML.js +623 -0
  193. package/dist/chunk-YWOBW2PV.cjs +759 -0
  194. package/dist/chunk-YYXH45E2.js +426 -0
  195. package/dist/chunk-ZDSYWBIE.cjs +69 -0
  196. package/dist/chunk-ZU7NIRT6.js +325 -0
  197. package/dist/chunk-ZZ7RO2UQ.js +1243 -0
  198. package/dist/cli/holoscript-runner.cjs +2255 -0
  199. package/dist/cli/holoscript-runner.js +2230 -0
  200. package/dist/codebase/index.cjs +336 -0
  201. package/dist/codebase/index.js +331 -0
  202. package/dist/compiler/agent-inference.cjs +31 -0
  203. package/dist/compiler/agent-inference.js +8 -0
  204. package/dist/compiler/android-xr.cjs +24 -0
  205. package/dist/compiler/android-xr.js +14 -0
  206. package/dist/compiler/android.cjs +24 -0
  207. package/dist/compiler/android.js +14 -0
  208. package/dist/compiler/ar.cjs +23 -0
  209. package/dist/compiler/ar.js +11 -0
  210. package/dist/compiler/babylon.cjs +21 -0
  211. package/dist/compiler/babylon.js +15 -0
  212. package/dist/compiler/business-quest.cjs +43 -0
  213. package/dist/compiler/business-quest.js +4 -0
  214. package/dist/compiler/coco.cjs +27 -0
  215. package/dist/compiler/coco.js +4 -0
  216. package/dist/compiler/context.cjs +25 -0
  217. package/dist/compiler/context.d.ts +28 -0
  218. package/dist/compiler/context.js +8 -0
  219. package/dist/compiler/domain-block-utils.cjs +609 -0
  220. package/dist/compiler/domain-block-utils.js +11 -0
  221. package/dist/compiler/dtdl.cjs +27 -0
  222. package/dist/compiler/dtdl.js +11 -0
  223. package/dist/compiler/gltf-pipeline.cjs +39 -0
  224. package/dist/compiler/gltf-pipeline.js +4 -0
  225. package/dist/compiler/godot.cjs +18 -0
  226. package/dist/compiler/godot.js +12 -0
  227. package/dist/compiler/incremental.cjs +34 -0
  228. package/dist/compiler/incremental.js +9 -0
  229. package/dist/compiler/index.cjs +5408 -0
  230. package/dist/compiler/index.d.ts +334 -21
  231. package/dist/compiler/index.js +5069 -0
  232. package/dist/compiler/ios.cjs +23 -0
  233. package/dist/compiler/ios.js +13 -0
  234. package/dist/compiler/llm-provider-capabilities.cjs +25 -0
  235. package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
  236. package/dist/compiler/llm-provider-capabilities.js +8 -0
  237. package/dist/compiler/multi-layer.cjs +24 -0
  238. package/dist/compiler/multi-layer.js +15 -0
  239. package/dist/compiler/nodetoy.cjs +23 -0
  240. package/dist/compiler/nodetoy.d.ts +69 -0
  241. package/dist/compiler/nodetoy.js +4 -0
  242. package/dist/compiler/openxr.cjs +19 -0
  243. package/dist/compiler/openxr.js +13 -0
  244. package/dist/compiler/playcanvas.cjs +19 -0
  245. package/dist/compiler/playcanvas.js +13 -0
  246. package/dist/compiler/r3f.cjs +39 -0
  247. package/dist/compiler/r3f.d.ts +22 -0
  248. package/dist/compiler/r3f.js +17 -0
  249. package/dist/compiler/remotion.cjs +23 -0
  250. package/dist/compiler/remotion.js +4 -0
  251. package/dist/compiler/reproducibility.cjs +39 -0
  252. package/dist/compiler/reproducibility.js +4 -0
  253. package/dist/compiler/sdf.cjs +24 -0
  254. package/dist/compiler/sdf.js +12 -0
  255. package/dist/compiler/semantic-scene.cjs +31 -0
  256. package/dist/compiler/semantic-scene.js +4 -0
  257. package/dist/compiler/state.cjs +21 -0
  258. package/dist/compiler/state.js +11 -0
  259. package/dist/compiler/trait-composition.cjs +30 -0
  260. package/dist/compiler/trait-composition.js +9 -0
  261. package/dist/compiler/unity.cjs +19 -0
  262. package/dist/compiler/unity.js +13 -0
  263. package/dist/compiler/unreal.cjs +23 -0
  264. package/dist/compiler/unreal.js +13 -0
  265. package/dist/compiler/urdf.cjs +52 -0
  266. package/dist/compiler/urdf.js +12 -0
  267. package/dist/compiler/usd-physics.cjs +26 -0
  268. package/dist/compiler/usd-physics.js +9 -0
  269. package/dist/compiler/visionos.cjs +19 -0
  270. package/dist/compiler/visionos.js +13 -0
  271. package/dist/compiler/vrchat.cjs +22 -0
  272. package/dist/compiler/vrchat.js +12 -0
  273. package/dist/compiler/vrr.cjs +24 -0
  274. package/dist/compiler/vrr.js +12 -0
  275. package/dist/compiler/wasm.cjs +36 -0
  276. package/dist/compiler/wasm.js +12 -0
  277. package/dist/compiler/webgpu.cjs +18 -0
  278. package/dist/compiler/webgpu.js +12 -0
  279. package/dist/coordinators/index.cjs +1266 -0
  280. package/dist/coordinators/index.d.ts +72 -1
  281. package/dist/coordinators/index.js +1259 -0
  282. package/dist/debugger.cjs +24 -0
  283. package/dist/debugger.js +11 -0
  284. package/dist/dist-ACXG6IH5.cjs +3113 -0
  285. package/dist/dist-VD4L6V7Q.js +3076 -0
  286. package/dist/entries/interop.cjs +64 -0
  287. package/dist/entries/interop.js +7 -0
  288. package/dist/entries/scripting.cjs +55 -0
  289. package/dist/entries/scripting.js +10 -0
  290. package/dist/hololand/index.cjs +146 -0
  291. package/dist/hololand/index.d.ts +70 -0
  292. package/dist/hololand/index.js +5 -0
  293. package/dist/index.cjs +44660 -0
  294. package/dist/index.d.ts +978 -21
  295. package/dist/index.js +41422 -0
  296. package/dist/math/tropical-spmv.cjs +45 -0
  297. package/dist/math/tropical-spmv.js +4 -0
  298. package/dist/math/vec3.cjs +57 -0
  299. package/dist/math/vec3.js +4 -0
  300. package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
  301. package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
  302. package/dist/paper-0c-spike/index.cjs +150 -0
  303. package/dist/paper-0c-spike/index.js +141 -0
  304. package/dist/parser.cjs +61 -0
  305. package/dist/parser.d.ts +11 -0
  306. package/dist/parser.js +12 -0
  307. package/dist/playwright-3AT3AKTV.cjs +98673 -0
  308. package/dist/playwright-VZPDVUEQ.js +98660 -0
  309. package/dist/reconstruction/index.cjs +153 -0
  310. package/dist/reconstruction/index.d.ts +29 -2
  311. package/dist/reconstruction/index.js +8 -0
  312. package/dist/runtime.cjs +316 -0
  313. package/dist/runtime.d.ts +61 -0
  314. package/dist/runtime.js +31 -0
  315. package/dist/self-improvement/index.cjs +563 -0
  316. package/dist/self-improvement/index.js +545 -0
  317. package/dist/src-4ROC227P.cjs +2094 -0
  318. package/dist/src-HCCCSYP7.js +2073 -0
  319. package/dist/storage/index.cjs +38 -0
  320. package/dist/storage/index.js +5 -0
  321. package/dist/testing.cjs +25 -0
  322. package/dist/testing.d.ts +70 -0
  323. package/dist/testing.js +4 -0
  324. package/dist/traitDocs/traitDocs.cjs +33 -0
  325. package/dist/traitDocs/traitDocs.js +7 -0
  326. package/dist/traits/botanical-lotus.cjs +177 -0
  327. package/dist/traits/botanical-lotus.d.ts +502 -0
  328. package/dist/traits/botanical-lotus.js +7 -0
  329. package/dist/traits/engines/index.cjs +520 -0
  330. package/dist/traits/engines/index.js +380 -0
  331. package/dist/traits/index.cjs +24548 -0
  332. package/dist/traits/index.d.ts +171 -35
  333. package/dist/traits/index.js +21638 -0
  334. package/dist/traits/simulation-solver-factory.cjs +13 -0
  335. package/dist/traits/simulation-solver-factory.d.ts +23 -0
  336. package/dist/traits/simulation-solver-factory.js +4 -0
  337. package/dist/traits/webcam-gaze.cjs +35 -0
  338. package/dist/traits/webcam-gaze.d.ts +17 -0
  339. package/dist/traits/webcam-gaze.js +4 -0
  340. package/dist/type-checker.cjs +19 -0
  341. package/dist/type-checker.js +6 -0
  342. package/dist/world/index.cjs +947 -0
  343. package/dist/world/index.d.ts +147 -0
  344. package/dist/world/index.js +939 -0
  345. package/dist/world-model/index.cjs +1446 -0
  346. package/dist/world-model/index.d.ts +119 -0
  347. package/dist/world-model/index.js +1414 -0
  348. package/dist/wot/index.cjs +29 -0
  349. package/dist/wot/index.js +4 -0
  350. package/package.json +93 -49
@@ -0,0 +1,1266 @@
1
+ 'use strict';
2
+
3
+ require('../chunk-HCCQLAA4.cjs');
4
+
5
+ // src/coordinators/AssetLoadCoordinator.ts
6
+ var ASSET_LOAD_EVENTS = [
7
+ // GLTF
8
+ "gltf:loaded",
9
+ "gltf:loading_progress",
10
+ "gltf:load_error",
11
+ "gltf:load_started",
12
+ // USD
13
+ "usd:loaded",
14
+ "usd:loading_progress",
15
+ "usd:load_error",
16
+ "usd:load_started",
17
+ // FBX
18
+ "fbx:loaded",
19
+ "fbx:loading_progress",
20
+ "fbx:load_error",
21
+ "fbx:load_started",
22
+ // Format-agnostic shared channel — all three traits ALSO emit these
23
+ // for cross-format observers that don't care about the source format.
24
+ "on_asset_loaded",
25
+ "on_asset_progress",
26
+ "on_asset_error"
27
+ ];
28
+ var AssetLoadCoordinator = class {
29
+ constructor(source) {
30
+ this.states = /* @__PURE__ */ new Map();
31
+ this.listeners = /* @__PURE__ */ new Set();
32
+ for (const event of ASSET_LOAD_EVENTS) {
33
+ source.on(event, (payload) => this.handleEvent(event, payload));
34
+ }
35
+ }
36
+ handleEvent(event, payload) {
37
+ if (!payload || typeof payload !== "object") return;
38
+ const p = payload;
39
+ const url = p.url ?? p.modelId ?? p.assetId;
40
+ if (!url || typeof url !== "string") return;
41
+ const format = this.formatFromEvent(event);
42
+ const phase = this.phaseFromEvent(event);
43
+ const existing = this.states.get(url);
44
+ const next = {
45
+ url,
46
+ format: existing?.format && existing.format !== "unknown" ? existing.format : format,
47
+ status: "idle",
48
+ progress: existing?.progress ?? 0,
49
+ updatedAt: Date.now()
50
+ };
51
+ if (phase === "started") {
52
+ next.status = "loading";
53
+ next.progress = 0;
54
+ } else if (phase === "progress") {
55
+ next.status = "loading";
56
+ const progressVal = p.progress;
57
+ if (typeof progressVal === "number" && progressVal >= 0 && progressVal <= 1) {
58
+ next.progress = progressVal;
59
+ }
60
+ } else if (phase === "loaded") {
61
+ next.status = "loaded";
62
+ next.progress = 1;
63
+ } else if (phase === "error") {
64
+ next.status = "error";
65
+ next.error = typeof p.error === "string" ? p.error : typeof p.message === "string" ? p.message : "unknown error";
66
+ }
67
+ this.states.set(url, next);
68
+ this.notifyListeners(next);
69
+ }
70
+ formatFromEvent(event) {
71
+ if (event.startsWith("gltf:")) return "gltf";
72
+ if (event.startsWith("usd:")) return "usd";
73
+ if (event.startsWith("fbx:")) return "fbx";
74
+ return "unknown";
75
+ }
76
+ phaseFromEvent(event) {
77
+ if (event.endsWith(":loaded") || event === "on_asset_loaded") return "loaded";
78
+ if (event.endsWith(":load_error") || event === "on_asset_error") return "error";
79
+ if (event.endsWith(":loading_progress") || event === "on_asset_progress") return "progress";
80
+ if (event.endsWith(":load_started")) return "started";
81
+ return "unknown";
82
+ }
83
+ notifyListeners(state) {
84
+ for (const listener of this.listeners) {
85
+ try {
86
+ listener(state);
87
+ } catch (_) {
88
+ }
89
+ }
90
+ }
91
+ /** Subscribe to all asset-state changes. Returns an unsubscribe function. */
92
+ subscribe(listener) {
93
+ this.listeners.add(listener);
94
+ return () => {
95
+ this.listeners.delete(listener);
96
+ };
97
+ }
98
+ /** Read the current state of one asset (or undefined if never seen). */
99
+ getAssetState(url) {
100
+ return this.states.get(url);
101
+ }
102
+ /** Read all tracked asset states (snapshot copy — safe to iterate). */
103
+ getAllStates() {
104
+ return Array.from(this.states.values());
105
+ }
106
+ /** Aggregate stats across all tracked assets. */
107
+ getStats() {
108
+ const all = Array.from(this.states.values());
109
+ const loading = all.filter((s) => s.status === "loading");
110
+ const loaded = all.filter((s) => s.status === "loaded");
111
+ const failed = all.filter((s) => s.status === "error");
112
+ const averageProgress = loading.length > 0 ? loading.reduce((sum, s) => sum + s.progress, 0) / loading.length : 0;
113
+ return {
114
+ total: all.length,
115
+ loading: loading.length,
116
+ loaded: loaded.length,
117
+ failed: failed.length,
118
+ averageProgress
119
+ };
120
+ }
121
+ /** Clear all tracked state — typically called on scene change. */
122
+ reset() {
123
+ this.states.clear();
124
+ }
125
+ /** Number of distinct event types this coordinator subscribes to (diagnostic). */
126
+ get subscribedEventCount() {
127
+ return ASSET_LOAD_EVENTS.length;
128
+ }
129
+ };
130
+
131
+ // src/coordinators/SecurityEventBus.ts
132
+ var SECURITY_EVENTS = [
133
+ // --- RBAC (authz) ---
134
+ "rbac_initialized",
135
+ "rbac_error",
136
+ "rbac_role_assigned",
137
+ "rbac_role_revoked",
138
+ "rbac_permission_result",
139
+ "rbac_custom_role_created",
140
+ "rbac_custom_role_deleted",
141
+ "rbac_user_roles",
142
+ "rbac_access_log",
143
+ "rbac_capability_result",
144
+ "rbac_capability_granted",
145
+ "rbac_capability_revoked",
146
+ "rbac_tenant_changed",
147
+ "rbac_capability_delegated",
148
+ "rbac_tenant_id",
149
+ "rbac_agent_capabilities",
150
+ "rbac_sync_roles",
151
+ // --- SSO (auth) ---
152
+ "sso_initialized",
153
+ "sso_error",
154
+ "sso_session_revoked",
155
+ "sso_session_expired",
156
+ "sso_idp_registered",
157
+ "sso_idp_removed",
158
+ "sso_auth_error",
159
+ "sso_saml_authn_request",
160
+ "sso_oidc_auth_redirect",
161
+ "sso_user_provisioned",
162
+ "sso_authenticated",
163
+ "sso_global_logout",
164
+ "sso_saml_slo_request",
165
+ "sso_session_validation",
166
+ "sso_info",
167
+ // --- Quota ---
168
+ "quota_initialized",
169
+ "quota_error",
170
+ "quota_reset",
171
+ "quota_grace_expired",
172
+ "quota_grace_started",
173
+ "quota_exceeded",
174
+ "quota_threshold_reached",
175
+ "quota_consumed",
176
+ "quota_released",
177
+ "quota_limit_changed",
178
+ "quota_tier_applied",
179
+ "quota_info",
180
+ "quota_usage_report_result",
181
+ // --- Tenant ---
182
+ "tenant_provisioned",
183
+ "tenant_error",
184
+ "tenant_decommissioned",
185
+ "tenant_status_changed",
186
+ "tenant_trait_registered",
187
+ "tenant_trait_unregistered",
188
+ "tenant_tier_changed",
189
+ "tenant_info",
190
+ "cross_tenant_grant_created",
191
+ "cross_tenant_grant_revoked",
192
+ "cross_tenant_grant_denied",
193
+ "cross_tenant_grant_expired",
194
+ // --- AuditLog (cross-cutting) ---
195
+ "audit_log",
196
+ "audit_entry_created",
197
+ "audit_siem_notify",
198
+ "audit_critical_event",
199
+ "audit_query_result",
200
+ "audit_integrity_result",
201
+ "audit_stats_result",
202
+ "audit_export_result",
203
+ "audit_error",
204
+ // --- ForgetPolicy ---
205
+ "forget_policy_attached",
206
+ "forget_policy_detached",
207
+ "forget_evaluate",
208
+ "forget_audit_entry",
209
+ "forget_apply",
210
+ "forget_audit_log",
211
+ "forget_error"
212
+ ];
213
+ var DEFAULT_AUDIT_BUFFER_SIZE = 256;
214
+ var SecurityEventBus = class {
215
+ constructor(source, auditBufferSize = DEFAULT_AUDIT_BUFFER_SIZE) {
216
+ this.sessions = /* @__PURE__ */ new Map();
217
+ this.agents = /* @__PURE__ */ new Map();
218
+ this.quotas = /* @__PURE__ */ new Map();
219
+ // key = `${resource}:${subject}`
220
+ this.tenants = /* @__PURE__ */ new Map();
221
+ this.auditLog = [];
222
+ this.listeners = /* @__PURE__ */ new Set();
223
+ this.auditBufferSize = Math.max(0, Math.floor(auditBufferSize));
224
+ for (const event of SECURITY_EVENTS) {
225
+ source.on(event, (payload) => this.handleEvent(event, payload));
226
+ }
227
+ }
228
+ // ---- Event ingestion ---------------------------------------------------
229
+ handleEvent(event, payload) {
230
+ const domain = this.domainFromEvent(event);
231
+ const observedAt = Date.now();
232
+ if (domain === "auth") this.applyAuthEvent(event, payload, observedAt);
233
+ else if (domain === "authz") this.applyAuthzEvent(event, payload, observedAt);
234
+ else if (domain === "quota") this.applyQuotaEvent(event, payload, observedAt);
235
+ else if (domain === "tenant") this.applyTenantEvent(event, payload, observedAt);
236
+ if (domain === "audit" || event === "audit_log" || event === "forget_audit_log" || event === "forget_audit_entry") {
237
+ this.appendAudit(event, payload, observedAt);
238
+ }
239
+ this.notifyListeners({ domain, event, payload, observedAt });
240
+ }
241
+ domainFromEvent(event) {
242
+ if (event.startsWith("sso_")) return "auth";
243
+ if (event.startsWith("rbac_")) return "authz";
244
+ if (event.startsWith("quota_")) return "quota";
245
+ if (event.startsWith("tenant_") || event.startsWith("cross_tenant_")) return "tenant";
246
+ if (event.startsWith("audit_")) return "audit";
247
+ if (event.startsWith("forget_")) return "forget";
248
+ return "unknown";
249
+ }
250
+ applyAuthEvent(event, payload, observedAt) {
251
+ if (!payload || typeof payload !== "object") return;
252
+ const p = payload;
253
+ const sessionId = p.sessionId ?? p.sid;
254
+ if (!sessionId || typeof sessionId !== "string") return;
255
+ const existing = this.sessions.get(sessionId);
256
+ let status = null;
257
+ if (event === "sso_authenticated") status = "authenticated";
258
+ else if (event === "sso_session_expired") status = "expired";
259
+ else if (event === "sso_session_revoked" || event === "sso_global_logout") status = "revoked";
260
+ if (status === null) return;
261
+ const next = {
262
+ sessionId,
263
+ status,
264
+ idp: typeof p.idp === "string" ? p.idp : existing?.idp,
265
+ userId: typeof p.userId === "string" ? p.userId : existing?.userId,
266
+ updatedAt: observedAt
267
+ };
268
+ this.sessions.set(sessionId, next);
269
+ }
270
+ applyAuthzEvent(event, payload, observedAt) {
271
+ if (!payload || typeof payload !== "object") return;
272
+ const p = payload;
273
+ const agentId = p.agentId ?? p.userId ?? p.subject;
274
+ if (!agentId || typeof agentId !== "string") return;
275
+ const existing = this.agents.get(agentId) ?? {
276
+ roles: /* @__PURE__ */ new Set(),
277
+ capabilities: /* @__PURE__ */ new Set()};
278
+ const roles = new Set(existing.roles);
279
+ const capabilities = new Set(existing.capabilities);
280
+ let tenantId = existing.tenantId;
281
+ if (event === "rbac_role_assigned" && typeof p.role === "string") roles.add(p.role);
282
+ else if (event === "rbac_role_revoked" && typeof p.role === "string") roles.delete(p.role);
283
+ else if (event === "rbac_capability_granted" && typeof p.capability === "string") capabilities.add(p.capability);
284
+ else if (event === "rbac_capability_revoked" && typeof p.capability === "string") capabilities.delete(p.capability);
285
+ else if (event === "rbac_tenant_changed" && typeof p.tenantId === "string") tenantId = p.tenantId;
286
+ else if (event === "rbac_user_roles" && Array.isArray(p.roles)) {
287
+ roles.clear();
288
+ for (const r of p.roles) if (typeof r === "string") roles.add(r);
289
+ } else if (event === "rbac_agent_capabilities" && Array.isArray(p.capabilities)) {
290
+ capabilities.clear();
291
+ for (const c of p.capabilities) if (typeof c === "string") capabilities.add(c);
292
+ } else {
293
+ return;
294
+ }
295
+ this.agents.set(agentId, { agentId, tenantId, roles, capabilities, updatedAt: observedAt });
296
+ }
297
+ applyQuotaEvent(event, payload, observedAt) {
298
+ if (!payload || typeof payload !== "object") return;
299
+ const p = payload;
300
+ const resource = typeof p.resource === "string" ? p.resource : void 0;
301
+ const subject = typeof p.tenantId === "string" && p.tenantId || typeof p.agentId === "string" && p.agentId || typeof p.subject === "string" && p.subject || void 0;
302
+ if (!resource || !subject) return;
303
+ const key = `${resource}:${subject}`;
304
+ const existing = this.quotas.get(key) ?? {
305
+ consumed: 0,
306
+ limit: 0,
307
+ status: "ok"};
308
+ let status = existing.status;
309
+ let consumed = existing.consumed;
310
+ let limit = existing.limit;
311
+ if (typeof p.consumed === "number") consumed = p.consumed;
312
+ if (typeof p.limit === "number") limit = p.limit;
313
+ if (event === "quota_exceeded") status = "exceeded";
314
+ else if (event === "quota_grace_started") status = "grace";
315
+ else if (event === "quota_grace_expired") status = "exceeded";
316
+ else if (event === "quota_threshold_reached") status = "threshold_reached";
317
+ else if (event === "quota_reset" || event === "quota_released" || event === "quota_consumed") {
318
+ if (limit > 0 && consumed >= limit) status = "exceeded";
319
+ else if (limit > 0 && consumed >= limit * 0.9) status = "threshold_reached";
320
+ else status = "ok";
321
+ }
322
+ this.quotas.set(key, { resource, subject, consumed, limit, status, updatedAt: observedAt });
323
+ }
324
+ applyTenantEvent(event, payload, observedAt) {
325
+ if (!payload || typeof payload !== "object") return;
326
+ const p = payload;
327
+ const tenantId = typeof p.tenantId === "string" ? p.tenantId : void 0;
328
+ if (!tenantId) return;
329
+ const existing = this.tenants.get(tenantId);
330
+ let status = existing?.status;
331
+ let tier = existing?.tier;
332
+ if (event === "tenant_provisioned") status = "provisioned";
333
+ else if (event === "tenant_decommissioned") status = "decommissioned";
334
+ else if (event === "tenant_status_changed" && typeof p.status === "string") {
335
+ const s = p.status;
336
+ if (s === "active" || s === "suspended" || s === "provisioned" || s === "decommissioned") status = s;
337
+ } else if (event === "tenant_tier_changed" && typeof p.tier === "string") {
338
+ tier = p.tier;
339
+ } else {
340
+ return;
341
+ }
342
+ if (!status) return;
343
+ this.tenants.set(tenantId, { tenantId, status, tier, updatedAt: observedAt });
344
+ }
345
+ appendAudit(event, payload, observedAt) {
346
+ if (this.auditBufferSize === 0) return;
347
+ const p = payload && typeof payload === "object" ? payload : {};
348
+ const entry = {
349
+ event,
350
+ action: typeof p.action === "string" ? p.action : void 0,
351
+ actor: typeof p.actor === "string" && p.actor || typeof p.agentId === "string" && p.agentId || typeof p.userId === "string" && p.userId || void 0,
352
+ tenantId: typeof p.tenantId === "string" ? p.tenantId : void 0,
353
+ outcome: p.outcome === "success" || p.outcome === "denied" || p.outcome === "error" ? p.outcome : void 0,
354
+ observedAt
355
+ };
356
+ this.auditLog.push(entry);
357
+ if (this.auditLog.length > this.auditBufferSize) {
358
+ this.auditLog.splice(0, this.auditLog.length - this.auditBufferSize);
359
+ }
360
+ }
361
+ notifyListeners(envelope) {
362
+ for (const listener of this.listeners) {
363
+ try {
364
+ listener(envelope);
365
+ } catch (_) {
366
+ }
367
+ }
368
+ }
369
+ // ---- Public API --------------------------------------------------------
370
+ /** Subscribe to all security events. Returns an unsubscribe function. */
371
+ subscribe(listener) {
372
+ this.listeners.add(listener);
373
+ return () => {
374
+ this.listeners.delete(listener);
375
+ };
376
+ }
377
+ getSession(sessionId) {
378
+ return this.sessions.get(sessionId);
379
+ }
380
+ getAllSessions() {
381
+ return Array.from(this.sessions.values());
382
+ }
383
+ getAgent(agentId) {
384
+ const a = this.agents.get(agentId);
385
+ if (!a) return void 0;
386
+ return { ...a, roles: new Set(a.roles), capabilities: new Set(a.capabilities) };
387
+ }
388
+ getAllAgents() {
389
+ return Array.from(this.agents.values()).map((a) => ({
390
+ ...a,
391
+ roles: new Set(a.roles),
392
+ capabilities: new Set(a.capabilities)
393
+ }));
394
+ }
395
+ getQuota(resource, subject) {
396
+ return this.quotas.get(`${resource}:${subject}`);
397
+ }
398
+ getAllQuotas() {
399
+ return Array.from(this.quotas.values());
400
+ }
401
+ getTenant(tenantId) {
402
+ return this.tenants.get(tenantId);
403
+ }
404
+ getAllTenants() {
405
+ return Array.from(this.tenants.values());
406
+ }
407
+ /** Snapshot of the rolling audit-log buffer (oldest first). */
408
+ getAuditLog() {
409
+ return this.auditLog.slice();
410
+ }
411
+ getStats() {
412
+ const sessions = Array.from(this.sessions.values());
413
+ const tenants = Array.from(this.tenants.values());
414
+ const quotas = Array.from(this.quotas.values());
415
+ return {
416
+ sessions: {
417
+ authenticated: sessions.filter((s) => s.status === "authenticated").length,
418
+ expired: sessions.filter((s) => s.status === "expired").length,
419
+ revoked: sessions.filter((s) => s.status === "revoked").length
420
+ },
421
+ agents: { tracked: this.agents.size },
422
+ tenants: {
423
+ active: tenants.filter((t) => t.status === "active" || t.status === "provisioned").length,
424
+ suspended: tenants.filter((t) => t.status === "suspended").length,
425
+ decommissioned: tenants.filter((t) => t.status === "decommissioned").length
426
+ },
427
+ quotas: {
428
+ tracked: quotas.length,
429
+ exceeded: quotas.filter((q) => q.status === "exceeded").length,
430
+ grace: quotas.filter((q) => q.status === "grace").length
431
+ },
432
+ auditLog: { entries: this.auditLog.length, capacity: this.auditBufferSize }
433
+ };
434
+ }
435
+ /** Clear all tracked state — typically called on tenant teardown or test reset. */
436
+ reset() {
437
+ this.sessions.clear();
438
+ this.agents.clear();
439
+ this.quotas.clear();
440
+ this.tenants.clear();
441
+ this.auditLog = [];
442
+ }
443
+ /** Number of distinct event types this bus subscribes to (diagnostic). */
444
+ get subscribedEventCount() {
445
+ return SECURITY_EVENTS.length;
446
+ }
447
+ };
448
+
449
+ // src/coordinators/GenerativeJobMonitor.ts
450
+ var GENERATIVE_JOB_EVENTS = [
451
+ // --- AiInpainting ---
452
+ "inpainting:ready",
453
+ "inpainting:cancelled",
454
+ "inpainting:mask_set",
455
+ "inpainting:started",
456
+ "inpainting:result",
457
+ "inpainting:original_restored",
458
+ "inpainting:error",
459
+ // --- AiTextureGen ---
460
+ "texture_gen:ready",
461
+ "texture_gen:cancelled",
462
+ "texture_gen:queued",
463
+ "texture_gen:started",
464
+ "texture_gen:applied",
465
+ // --- ControlNet ---
466
+ "controlnet:ready",
467
+ "controlnet:cancelled",
468
+ "controlnet:started",
469
+ "controlnet:result",
470
+ "controlnet:error",
471
+ "controlnet:map_requested",
472
+ // --- DiffusionRealtime ---
473
+ "diffusion_rt:ready",
474
+ "diffusion_rt:stopped",
475
+ "diffusion_rt:started",
476
+ "diffusion_rt:frame_ready",
477
+ "diffusion_rt:prompt_updated"
478
+ ];
479
+ var KIND_PREFIXES = [
480
+ ["inpainting:", "inpainting"],
481
+ ["texture_gen:", "texture_gen"],
482
+ ["controlnet:", "controlnet"],
483
+ ["diffusion_rt:", "diffusion_rt"]
484
+ ];
485
+ var GenerativeJobMonitor = class {
486
+ constructor(source) {
487
+ this.jobs = /* @__PURE__ */ new Map();
488
+ this.listeners = /* @__PURE__ */ new Set();
489
+ /** Tracks which trait kinds have fired their `<kind>:ready` event. */
490
+ this.readyKinds = /* @__PURE__ */ new Set();
491
+ for (const event of GENERATIVE_JOB_EVENTS) {
492
+ source.on(event, (payload) => this.handleEvent(event, payload));
493
+ }
494
+ }
495
+ // ---- Event ingestion ---------------------------------------------------
496
+ handleEvent(event, payload) {
497
+ const kind = this.kindFromEvent(event);
498
+ if (!kind) return;
499
+ const phase = this.phaseFromEvent(event);
500
+ const observedAt = Date.now();
501
+ if (phase === "ready") {
502
+ this.readyKinds.add(kind);
503
+ this.notifyListeners({
504
+ jobId: `__ready:${kind}`,
505
+ kind,
506
+ status: "completed",
507
+ startedAt: observedAt,
508
+ updatedAt: observedAt
509
+ });
510
+ return;
511
+ }
512
+ if (phase === "config") return;
513
+ if (!payload || typeof payload !== "object") return;
514
+ const p = payload;
515
+ const jobId = this.jobIdFromPayload(p, kind);
516
+ if (!jobId) return;
517
+ const existing = this.jobs.get(jobId);
518
+ const startedAt = existing?.startedAt ?? observedAt;
519
+ let status = null;
520
+ let durationMs = existing?.durationMs;
521
+ let error = existing?.error;
522
+ if (phase === "queued") {
523
+ status = "queued";
524
+ } else if (phase === "started") {
525
+ status = "running";
526
+ } else if (phase === "success") {
527
+ status = "completed";
528
+ durationMs = observedAt - startedAt;
529
+ } else if (phase === "cancelled") {
530
+ status = "cancelled";
531
+ durationMs = observedAt - startedAt;
532
+ } else if (phase === "error") {
533
+ status = "errored";
534
+ durationMs = observedAt - startedAt;
535
+ error = typeof p.error === "string" ? p.error : typeof p.message === "string" ? p.message : "unknown error";
536
+ }
537
+ if (status === null) return;
538
+ const next = {
539
+ jobId,
540
+ kind,
541
+ status,
542
+ startedAt,
543
+ updatedAt: observedAt,
544
+ durationMs,
545
+ error
546
+ };
547
+ this.jobs.set(jobId, next);
548
+ this.notifyListeners(next);
549
+ }
550
+ kindFromEvent(event) {
551
+ for (const [prefix, kind] of KIND_PREFIXES) {
552
+ if (event.startsWith(prefix)) return kind;
553
+ }
554
+ return null;
555
+ }
556
+ phaseFromEvent(event) {
557
+ const suffix = event.slice(event.indexOf(":") + 1);
558
+ if (suffix === "ready") return "ready";
559
+ if (suffix === "queued") return "queued";
560
+ if (suffix === "started") return "started";
561
+ if (suffix === "result" || suffix === "applied" || suffix === "original_restored" || suffix === "frame_ready")
562
+ return "success";
563
+ if (suffix === "cancelled" || suffix === "stopped") return "cancelled";
564
+ if (suffix === "error") return "error";
565
+ if (suffix === "mask_set" || suffix === "map_requested" || suffix === "prompt_updated") return "config";
566
+ return "unknown";
567
+ }
568
+ /**
569
+ * Resolve the stable job ID from a payload, falling back across the
570
+ * fields each trait happens to use. Mirrors the heuristic in
571
+ * AssetLoadCoordinator.handleEvent.
572
+ */
573
+ jobIdFromPayload(p, kind) {
574
+ if (kind === "diffusion_rt" && typeof p.frameNumber === "number") {
575
+ const sid = typeof p.sessionId === "string" ? p.sessionId : "rt";
576
+ return `${sid}:${p.frameNumber}`;
577
+ }
578
+ const candidates = [p.requestId, p.jobId, p.textureId, p.sessionId, p.nodeId, p.id];
579
+ for (const c of candidates) {
580
+ if (typeof c === "string" && c.length > 0) return c;
581
+ }
582
+ return void 0;
583
+ }
584
+ notifyListeners(state) {
585
+ for (const listener of this.listeners) {
586
+ try {
587
+ listener(state);
588
+ } catch (_) {
589
+ }
590
+ }
591
+ }
592
+ // ---- Public API --------------------------------------------------------
593
+ /** Subscribe to all job-state changes. Returns an unsubscribe function. */
594
+ subscribe(listener) {
595
+ this.listeners.add(listener);
596
+ return () => {
597
+ this.listeners.delete(listener);
598
+ };
599
+ }
600
+ getJob(jobId) {
601
+ return this.jobs.get(jobId);
602
+ }
603
+ getAllJobs() {
604
+ return Array.from(this.jobs.values());
605
+ }
606
+ getJobsByKind(kind) {
607
+ return Array.from(this.jobs.values()).filter((j) => j.kind === kind);
608
+ }
609
+ isReady(kind) {
610
+ return this.readyKinds.has(kind);
611
+ }
612
+ getStats() {
613
+ const empty = () => ({
614
+ queued: 0,
615
+ running: 0,
616
+ completed: 0,
617
+ cancelled: 0,
618
+ errored: 0,
619
+ meanLatencyMs: 0
620
+ });
621
+ const byKind = {
622
+ inpainting: empty(),
623
+ texture_gen: empty(),
624
+ controlnet: empty(),
625
+ diffusion_rt: empty()
626
+ };
627
+ const latencyTotals = {
628
+ inpainting: { sum: 0, count: 0 },
629
+ texture_gen: { sum: 0, count: 0 },
630
+ controlnet: { sum: 0, count: 0 },
631
+ diffusion_rt: { sum: 0, count: 0 }
632
+ };
633
+ for (const job of this.jobs.values()) {
634
+ const stats = byKind[job.kind];
635
+ if (job.status === "queued") stats.queued++;
636
+ else if (job.status === "running") stats.running++;
637
+ else if (job.status === "completed") {
638
+ stats.completed++;
639
+ if (typeof job.durationMs === "number") {
640
+ latencyTotals[job.kind].sum += job.durationMs;
641
+ latencyTotals[job.kind].count++;
642
+ }
643
+ } else if (job.status === "cancelled") stats.cancelled++;
644
+ else if (job.status === "errored") stats.errored++;
645
+ }
646
+ for (const k of Object.keys(byKind)) {
647
+ const t = latencyTotals[k];
648
+ byKind[k].meanLatencyMs = t.count > 0 ? t.sum / t.count : 0;
649
+ }
650
+ return {
651
+ total: this.jobs.size,
652
+ byKind,
653
+ anyReady: this.readyKinds.size > 0
654
+ };
655
+ }
656
+ /** Clear all tracked jobs — typically called on scene change. */
657
+ reset() {
658
+ this.jobs.clear();
659
+ this.readyKinds.clear();
660
+ }
661
+ /** Number of distinct event types this monitor subscribes to (diagnostic). */
662
+ get subscribedEventCount() {
663
+ return GENERATIVE_JOB_EVENTS.length;
664
+ }
665
+ };
666
+
667
+ // src/coordinators/SessionPresenceCoordinator.ts
668
+ var PRESENCE_EVENTS = [
669
+ // --- SharePlay ---
670
+ "shareplay:ready",
671
+ "shareplay:ended",
672
+ "shareplay:started",
673
+ "shareplay:joined",
674
+ "shareplay:participant_joined",
675
+ "shareplay:participant_left",
676
+ "shareplay:state_synced",
677
+ // --- SpatialVoice ---
678
+ "spatial_voice_create",
679
+ "spatial_voice_destroy",
680
+ "spatial_voice_position",
681
+ "spatial_voice_peer_joined",
682
+ "spatial_voice_peer_left",
683
+ "spatial_voice_muted",
684
+ "spatial_voice_unmuted",
685
+ "on_voice_activity",
686
+ // --- Messaging ---
687
+ "messaging_connected",
688
+ "messaging_disconnected",
689
+ "messaging_error",
690
+ "messaging_stats",
691
+ "message_received",
692
+ "message_sent",
693
+ "command_parsed",
694
+ // (`command_<name>` events are dynamic — not subscribed here. Consumers
695
+ // that care about specific commands subscribe directly through the
696
+ // event source.)
697
+ // --- WorldHeartbeat ---
698
+ "heartbeat_initialized",
699
+ "heartbeat_tick",
700
+ "heartbeat_failover",
701
+ "heartbeat_error"
702
+ ];
703
+ var SessionPresenceCoordinator = class {
704
+ constructor(source) {
705
+ this.sessions = /* @__PURE__ */ new Map();
706
+ this.voice = /* @__PURE__ */ new Map();
707
+ this.messaging = /* @__PURE__ */ new Map();
708
+ this.heartbeats = /* @__PURE__ */ new Map();
709
+ this.listeners = /* @__PURE__ */ new Set();
710
+ for (const event of PRESENCE_EVENTS) {
711
+ source.on(event, (payload) => this.handleEvent(event, payload));
712
+ }
713
+ }
714
+ // ---- Event ingestion ---------------------------------------------------
715
+ handleEvent(event, payload) {
716
+ const domain = this.domainFromEvent(event);
717
+ const observedAt = Date.now();
718
+ if (domain === "shareplay") this.applySharePlayEvent(event, payload, observedAt);
719
+ else if (domain === "voice") this.applyVoiceEvent(event, payload, observedAt);
720
+ else if (domain === "messaging") this.applyMessagingEvent(event, payload, observedAt);
721
+ else if (domain === "heartbeat") this.applyHeartbeatEvent(event, payload, observedAt);
722
+ this.notifyListeners({ domain, event, payload, observedAt });
723
+ }
724
+ domainFromEvent(event) {
725
+ if (event.startsWith("shareplay:")) return "shareplay";
726
+ if (event.startsWith("spatial_voice_") || event === "on_voice_activity") return "voice";
727
+ if (event.startsWith("messaging_") || event === "message_received" || event === "message_sent" || event === "command_parsed")
728
+ return "messaging";
729
+ if (event.startsWith("heartbeat_")) return "heartbeat";
730
+ return "unknown";
731
+ }
732
+ // ---- SharePlay ---------------------------------------------------------
733
+ applySharePlayEvent(event, payload, observedAt) {
734
+ if (!payload || typeof payload !== "object") return;
735
+ const p = payload;
736
+ if (event === "shareplay:ready") return;
737
+ const sessionId = typeof p.sessionId === "string" ? p.sessionId : void 0;
738
+ if (!sessionId) return;
739
+ const existing = this.sessions.get(sessionId);
740
+ const participants = new Set(existing?.participants ?? []);
741
+ let status = existing?.status ?? "idle";
742
+ if (event === "shareplay:started") status = "started";
743
+ else if (event === "shareplay:joined") status = "joined";
744
+ else if (event === "shareplay:ended") status = "ended";
745
+ else if (event === "shareplay:participant_joined") {
746
+ const pid = typeof p.participantId === "string" ? p.participantId : void 0;
747
+ if (pid) participants.add(pid);
748
+ } else if (event === "shareplay:participant_left") {
749
+ const pid = typeof p.participantId === "string" ? p.participantId : void 0;
750
+ if (pid) participants.delete(pid);
751
+ }
752
+ this.sessions.set(sessionId, {
753
+ sessionId,
754
+ status,
755
+ participants,
756
+ activityTitle: existing?.activityTitle,
757
+ updatedAt: observedAt
758
+ });
759
+ }
760
+ // ---- SpatialVoice ------------------------------------------------------
761
+ applyVoiceEvent(event, payload, observedAt) {
762
+ if (!payload || typeof payload !== "object") return;
763
+ const p = payload;
764
+ const nodeId = typeof p.nodeId === "string" ? p.nodeId : void 0;
765
+ if (event === "spatial_voice_create" && nodeId) {
766
+ this.voice.set(nodeId, {
767
+ nodeId,
768
+ peers: /* @__PURE__ */ new Set(),
769
+ muted: false,
770
+ lastVoiceActivityAt: 0,
771
+ updatedAt: observedAt
772
+ });
773
+ return;
774
+ }
775
+ if (event === "spatial_voice_destroy" && nodeId) {
776
+ this.voice.delete(nodeId);
777
+ return;
778
+ }
779
+ if (event === "spatial_voice_peer_joined" && nodeId) {
780
+ const peerId = typeof p.peerId === "string" ? p.peerId : void 0;
781
+ const existing = this.voice.get(nodeId);
782
+ if (!existing || !peerId) return;
783
+ const peers = new Set(existing.peers);
784
+ peers.add(peerId);
785
+ this.voice.set(nodeId, { ...existing, peers, updatedAt: observedAt });
786
+ return;
787
+ }
788
+ if (event === "spatial_voice_peer_left" && nodeId) {
789
+ const peerId = typeof p.peerId === "string" ? p.peerId : void 0;
790
+ const existing = this.voice.get(nodeId);
791
+ if (!existing || !peerId) return;
792
+ const peers = new Set(existing.peers);
793
+ peers.delete(peerId);
794
+ this.voice.set(nodeId, { ...existing, peers, updatedAt: observedAt });
795
+ return;
796
+ }
797
+ for (const existing of this.voice.values()) {
798
+ let next = existing;
799
+ if (event === "spatial_voice_muted") next = { ...existing, muted: true, updatedAt: observedAt };
800
+ else if (event === "spatial_voice_unmuted") next = { ...existing, muted: false, updatedAt: observedAt };
801
+ else if (event === "on_voice_activity")
802
+ next = { ...existing, lastVoiceActivityAt: observedAt, updatedAt: observedAt };
803
+ else continue;
804
+ this.voice.set(existing.nodeId, next);
805
+ }
806
+ }
807
+ // ---- Messaging ---------------------------------------------------------
808
+ applyMessagingEvent(event, payload, observedAt) {
809
+ if (!payload || typeof payload !== "object") return;
810
+ const p = payload;
811
+ const platform = typeof p.platform === "string" ? p.platform : void 0;
812
+ if (!platform) return;
813
+ const existing = this.messaging.get(platform) ?? {
814
+ status: "disconnected",
815
+ messagesReceived: 0,
816
+ messagesSent: 0};
817
+ let status = existing.status;
818
+ let error = existing.error;
819
+ let received = existing.messagesReceived;
820
+ let sent = existing.messagesSent;
821
+ if (event === "messaging_connected") {
822
+ status = "connected";
823
+ error = void 0;
824
+ } else if (event === "messaging_disconnected") {
825
+ status = "disconnected";
826
+ } else if (event === "messaging_error") {
827
+ status = "errored";
828
+ error = typeof p.error === "string" ? p.error : "unknown error";
829
+ } else if (event === "message_received") {
830
+ received++;
831
+ } else if (event === "message_sent") {
832
+ sent++;
833
+ } else ;
834
+ this.messaging.set(platform, {
835
+ platform,
836
+ status,
837
+ messagesReceived: received,
838
+ messagesSent: sent,
839
+ error,
840
+ updatedAt: observedAt
841
+ });
842
+ }
843
+ // ---- WorldHeartbeat ----------------------------------------------------
844
+ applyHeartbeatEvent(event, payload, observedAt) {
845
+ if (!payload || typeof payload !== "object") return;
846
+ const p = payload;
847
+ const nodeId = typeof p.nodeId === "string" && p.nodeId || typeof p.worldId === "string" && p.worldId || typeof p.id === "string" && p.id || void 0;
848
+ if (!nodeId) return;
849
+ const existing = this.heartbeats.get(nodeId) ?? {
850
+ status: "initialized",
851
+ ticks: 0,
852
+ lastTickAt: 0};
853
+ let status = existing.status;
854
+ let ticks = existing.ticks;
855
+ let lastTickAt = existing.lastTickAt;
856
+ let error = existing.error;
857
+ if (event === "heartbeat_initialized") {
858
+ status = "initialized";
859
+ error = void 0;
860
+ } else if (event === "heartbeat_tick") {
861
+ status = "alive";
862
+ ticks++;
863
+ lastTickAt = observedAt;
864
+ } else if (event === "heartbeat_failover") {
865
+ status = "failover";
866
+ } else if (event === "heartbeat_error") {
867
+ status = "errored";
868
+ error = typeof p.error === "string" ? p.error : typeof p.message === "string" ? p.message : "unknown error";
869
+ }
870
+ this.heartbeats.set(nodeId, { nodeId, status, ticks, lastTickAt, error, updatedAt: observedAt });
871
+ }
872
+ notifyListeners(envelope) {
873
+ for (const listener of this.listeners) {
874
+ try {
875
+ listener(envelope);
876
+ } catch (_) {
877
+ }
878
+ }
879
+ }
880
+ // ---- Public API --------------------------------------------------------
881
+ /** Subscribe to all presence events. Returns an unsubscribe function. */
882
+ subscribe(listener) {
883
+ this.listeners.add(listener);
884
+ return () => {
885
+ this.listeners.delete(listener);
886
+ };
887
+ }
888
+ // SharePlay
889
+ getSession(sessionId) {
890
+ const s = this.sessions.get(sessionId);
891
+ return s ? { ...s, participants: new Set(s.participants) } : void 0;
892
+ }
893
+ getAllSessions() {
894
+ return Array.from(this.sessions.values()).map((s) => ({ ...s, participants: new Set(s.participants) }));
895
+ }
896
+ // SpatialVoice
897
+ getVoiceNode(nodeId) {
898
+ const v = this.voice.get(nodeId);
899
+ return v ? { ...v, peers: new Set(v.peers) } : void 0;
900
+ }
901
+ getAllVoiceNodes() {
902
+ return Array.from(this.voice.values()).map((v) => ({ ...v, peers: new Set(v.peers) }));
903
+ }
904
+ // Messaging
905
+ getMessagingConnection(platform) {
906
+ return this.messaging.get(platform);
907
+ }
908
+ getAllMessagingConnections() {
909
+ return Array.from(this.messaging.values());
910
+ }
911
+ // Heartbeat
912
+ getHeartbeat(nodeId) {
913
+ return this.heartbeats.get(nodeId);
914
+ }
915
+ getAllHeartbeats() {
916
+ return Array.from(this.heartbeats.values());
917
+ }
918
+ getStats() {
919
+ const sessions = Array.from(this.sessions.values());
920
+ const voice = Array.from(this.voice.values());
921
+ const messaging = Array.from(this.messaging.values());
922
+ const heartbeats = Array.from(this.heartbeats.values());
923
+ const totalParticipants = sessions.reduce((sum, s) => sum + s.participants.size, 0);
924
+ const totalPeers = voice.reduce((sum, v) => sum + v.peers.size, 0);
925
+ return {
926
+ sessions: {
927
+ active: sessions.filter((s) => s.status === "started" || s.status === "joined").length,
928
+ ended: sessions.filter((s) => s.status === "ended").length,
929
+ participants: totalParticipants
930
+ },
931
+ voice: {
932
+ nodes: voice.length,
933
+ peers: totalPeers,
934
+ muted: voice.filter((v) => v.muted).length
935
+ },
936
+ messaging: {
937
+ connections: messaging.length,
938
+ connected: messaging.filter((m) => m.status === "connected").length,
939
+ errored: messaging.filter((m) => m.status === "errored").length
940
+ },
941
+ heartbeat: {
942
+ tracked: heartbeats.length,
943
+ alive: heartbeats.filter((h) => h.status === "alive").length,
944
+ failover: heartbeats.filter((h) => h.status === "failover").length,
945
+ errored: heartbeats.filter((h) => h.status === "errored").length
946
+ }
947
+ };
948
+ }
949
+ /** Clear all tracked state — typically called on world teardown / scene change. */
950
+ reset() {
951
+ this.sessions.clear();
952
+ this.voice.clear();
953
+ this.messaging.clear();
954
+ this.heartbeats.clear();
955
+ }
956
+ /** Number of distinct event types this coordinator subscribes to (diagnostic). */
957
+ get subscribedEventCount() {
958
+ return PRESENCE_EVENTS.length;
959
+ }
960
+ };
961
+
962
+ // src/coordinators/NeuralForgeCoordinator.ts
963
+ var NEURAL_FORGE_EVENTS = [
964
+ "neural_forge_connected",
965
+ "neural_synthesis_request",
966
+ "neural_synthesis_timeout",
967
+ "neural_shard_created",
968
+ "neural_cognition_evolved"
969
+ ];
970
+ var NeuralForgeCoordinator = class {
971
+ constructor(source) {
972
+ this.nodes = /* @__PURE__ */ new Map();
973
+ this.listeners = /* @__PURE__ */ new Set();
974
+ /** Tracks which nodes have fired neural_forge_connected. */
975
+ this.connectedNodes = /* @__PURE__ */ new Set();
976
+ for (const event of NEURAL_FORGE_EVENTS) {
977
+ source.on(event, (payload) => this.handleEvent(event, payload));
978
+ }
979
+ }
980
+ // ---- Event ingestion ---------------------------------------------------
981
+ handleEvent(event, payload) {
982
+ if (!payload || typeof payload !== "object") return;
983
+ const p = payload;
984
+ const nodeObj = p.node;
985
+ const nodeId = nodeObj?.id ?? p.nodeId ?? p.sourceId;
986
+ if (!nodeId || typeof nodeId !== "string") return;
987
+ const observedAt = Date.now();
988
+ switch (event) {
989
+ case "neural_forge_connected": {
990
+ this.connectedNodes.add(nodeId);
991
+ const existing = this.nodes.get(nodeId);
992
+ const next = {
993
+ nodeId,
994
+ status: existing?.status ?? "connected",
995
+ shardCount: existing?.shardCount ?? 0,
996
+ weights: existing?.weights ?? {},
997
+ lastSynthesisAt: existing?.lastSynthesisAt ?? null,
998
+ pendingExternalSynthesis: existing?.pendingExternalSynthesis ?? false,
999
+ pendingSince: existing?.pendingSince ?? null,
1000
+ experienceLogLength: existing?.experienceLogLength ?? 0,
1001
+ updatedAt: observedAt
1002
+ };
1003
+ this.nodes.set(nodeId, next);
1004
+ this.notifyListeners(next);
1005
+ break;
1006
+ }
1007
+ case "neural_synthesis_request": {
1008
+ const mode = p.mode;
1009
+ const experiences = p.experiences;
1010
+ const weights = p.currentWeights;
1011
+ const existing = this.nodes.get(nodeId);
1012
+ const next = {
1013
+ nodeId,
1014
+ status: mode === "external" ? "synthesizing" : existing?.status ?? "idle",
1015
+ shardCount: existing?.shardCount ?? 0,
1016
+ weights: weights ?? existing?.weights ?? {},
1017
+ lastSynthesisAt: existing?.lastSynthesisAt ?? null,
1018
+ pendingExternalSynthesis: mode === "external",
1019
+ pendingSince: mode === "external" ? observedAt : null,
1020
+ experienceLogLength: Array.isArray(experiences) ? experiences.length : existing?.experienceLogLength ?? 0,
1021
+ updatedAt: observedAt
1022
+ };
1023
+ this.nodes.set(nodeId, next);
1024
+ this.notifyListeners(next);
1025
+ break;
1026
+ }
1027
+ case "neural_synthesis_timeout": {
1028
+ const experienceCount = p.experienceCount;
1029
+ const existing = this.nodes.get(nodeId);
1030
+ const next = {
1031
+ nodeId,
1032
+ status: "timeout_fallback",
1033
+ shardCount: existing?.shardCount ?? 0,
1034
+ weights: existing?.weights ?? {},
1035
+ lastSynthesisAt: existing?.lastSynthesisAt ?? null,
1036
+ pendingExternalSynthesis: false,
1037
+ pendingSince: null,
1038
+ experienceLogLength: experienceCount ?? (existing?.experienceLogLength ?? 0),
1039
+ updatedAt: observedAt
1040
+ };
1041
+ this.nodes.set(nodeId, next);
1042
+ this.notifyListeners(next);
1043
+ break;
1044
+ }
1045
+ case "neural_shard_created": {
1046
+ p.shard;
1047
+ const existing = this.nodes.get(nodeId);
1048
+ const next = {
1049
+ nodeId,
1050
+ status: existing?.pendingExternalSynthesis ? "synthesizing" : existing?.status ?? "idle",
1051
+ shardCount: (existing?.shardCount ?? 0) + 1,
1052
+ weights: existing?.weights ?? {},
1053
+ lastSynthesisAt: observedAt,
1054
+ pendingExternalSynthesis: existing?.pendingExternalSynthesis ?? false,
1055
+ pendingSince: existing?.pendingSince ?? null,
1056
+ experienceLogLength: existing?.experienceLogLength ?? 0,
1057
+ updatedAt: observedAt
1058
+ };
1059
+ this.nodes.set(nodeId, next);
1060
+ this.notifyListeners(next);
1061
+ break;
1062
+ }
1063
+ case "neural_cognition_evolved": {
1064
+ const weights = p.currentWeights;
1065
+ const existing = this.nodes.get(nodeId);
1066
+ if (!existing) {
1067
+ const next = {
1068
+ nodeId,
1069
+ status: "idle",
1070
+ shardCount: 0,
1071
+ weights: weights ?? {},
1072
+ lastSynthesisAt: null,
1073
+ pendingExternalSynthesis: false,
1074
+ pendingSince: null,
1075
+ experienceLogLength: 0,
1076
+ updatedAt: observedAt
1077
+ };
1078
+ this.nodes.set(nodeId, next);
1079
+ this.notifyListeners(next);
1080
+ } else {
1081
+ existing.weights = weights ?? existing.weights;
1082
+ existing.updatedAt = observedAt;
1083
+ this.notifyListeners(existing);
1084
+ }
1085
+ break;
1086
+ }
1087
+ }
1088
+ }
1089
+ notifyListeners(state) {
1090
+ for (const listener of this.listeners) {
1091
+ try {
1092
+ listener(state);
1093
+ } catch (_) {
1094
+ }
1095
+ }
1096
+ }
1097
+ // ---- Public API --------------------------------------------------------
1098
+ /** Subscribe to all neural-node state changes. Returns an unsubscribe function. */
1099
+ subscribe(listener) {
1100
+ this.listeners.add(listener);
1101
+ return () => {
1102
+ this.listeners.delete(listener);
1103
+ };
1104
+ }
1105
+ /** Get the state of a specific node (undefined if never seen). */
1106
+ getNodeState(nodeId) {
1107
+ return this.nodes.get(nodeId);
1108
+ }
1109
+ /** Get all tracked node states (snapshot — safe to iterate). */
1110
+ getAllStates() {
1111
+ return Array.from(this.nodes.values());
1112
+ }
1113
+ /** Whether a specific node has fired neural_forge_connected. */
1114
+ isConnected(nodeId) {
1115
+ return this.connectedNodes.has(nodeId);
1116
+ }
1117
+ /** Aggregate stats across all tracked nodes. */
1118
+ getStats() {
1119
+ const all = Array.from(this.nodes.values());
1120
+ return {
1121
+ total: all.length,
1122
+ synthesizing: all.filter((s) => s.status === "synthesizing").length,
1123
+ timeoutFallback: all.filter((s) => s.status === "timeout_fallback").length,
1124
+ totalShards: all.reduce((sum, s) => sum + s.shardCount, 0),
1125
+ anyConnected: this.connectedNodes.size > 0
1126
+ };
1127
+ }
1128
+ /** Clear all tracked state — typically called on scene change. */
1129
+ reset() {
1130
+ this.nodes.clear();
1131
+ this.connectedNodes.clear();
1132
+ }
1133
+ /** Number of distinct event types this coordinator subscribes to (diagnostic). */
1134
+ get subscribedEventCount() {
1135
+ return NEURAL_FORGE_EVENTS.length;
1136
+ }
1137
+ };
1138
+
1139
+ // src/coordinators/ObjectTrackingCoordinator.ts
1140
+ var OBJECT_TRACKING_EVENTS = [
1141
+ "tracking:init",
1142
+ "tracking:updated",
1143
+ "tracking:lost",
1144
+ "tracking:recovery_attempt",
1145
+ "tracking:anchor_removed"
1146
+ ];
1147
+ function isRecord(value) {
1148
+ return typeof value === "object" && value !== null;
1149
+ }
1150
+ function readString(value) {
1151
+ return typeof value === "string" && value.length > 0 ? value : void 0;
1152
+ }
1153
+ function readNumber(value) {
1154
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1155
+ }
1156
+ function readVector3(value) {
1157
+ if (!Array.isArray(value) || value.length !== 3 || !value.every((n) => Number.isFinite(n))) {
1158
+ return void 0;
1159
+ }
1160
+ return [...value];
1161
+ }
1162
+ function clampConfidence(value, fallback) {
1163
+ const confidence = readNumber(value);
1164
+ if (confidence === void 0) return fallback;
1165
+ return Math.max(0, Math.min(1, confidence));
1166
+ }
1167
+ var ObjectTrackingCoordinator = class {
1168
+ constructor(source) {
1169
+ this.targets = /* @__PURE__ */ new Map();
1170
+ this.listeners = /* @__PURE__ */ new Set();
1171
+ for (const event of OBJECT_TRACKING_EVENTS) {
1172
+ source.on(event, (payload) => this.handleEvent(event, payload));
1173
+ }
1174
+ }
1175
+ handleEvent(event, payload) {
1176
+ if (!isRecord(payload)) return;
1177
+ const key = this.resolveKey(payload);
1178
+ if (!key) return;
1179
+ const observedAt = Date.now();
1180
+ const existing = this.targets.get(key);
1181
+ const next = existing ? { ...existing, updatedAt: observedAt } : {
1182
+ nodeId: key,
1183
+ anchorId: null,
1184
+ status: "initialized",
1185
+ position: null,
1186
+ rotation: null,
1187
+ confidence: 0,
1188
+ recoveryAttempts: 0,
1189
+ timestampMs: null,
1190
+ updatedAt: observedAt
1191
+ };
1192
+ next.target = readString(payload.target) ?? next.target;
1193
+ next.anchorId = readString(payload.anchorId) ?? next.anchorId;
1194
+ if (event === "tracking:init") {
1195
+ next.status = "initialized";
1196
+ } else if (event === "tracking:updated") {
1197
+ next.status = "tracking";
1198
+ next.position = readVector3(payload.position) ?? next.position;
1199
+ next.rotation = readVector3(payload.rotation) ?? next.rotation;
1200
+ next.confidence = clampConfidence(payload.confidence, next.confidence);
1201
+ next.source = readString(payload.source) ?? next.source;
1202
+ next.timestampMs = readNumber(payload.timestampMs) ?? next.timestampMs;
1203
+ } else if (event === "tracking:lost") {
1204
+ next.status = "lost";
1205
+ next.confidence = 0;
1206
+ } else if (event === "tracking:recovery_attempt") {
1207
+ next.status = "recovering";
1208
+ next.recoveryAttempts = readNumber(payload.attempt) ?? next.recoveryAttempts + 1;
1209
+ } else if (event === "tracking:anchor_removed") {
1210
+ next.status = "removed";
1211
+ }
1212
+ this.targets.set(key, next);
1213
+ this.notifyListeners(next);
1214
+ }
1215
+ resolveKey(payload) {
1216
+ const nodeId = readString(payload.nodeId);
1217
+ if (nodeId) return nodeId;
1218
+ const anchorId = readString(payload.anchorId);
1219
+ if (anchorId) return `anchor:${anchorId}`;
1220
+ const target = readString(payload.target);
1221
+ return target ? `target:${target}` : void 0;
1222
+ }
1223
+ notifyListeners(state) {
1224
+ for (const listener of this.listeners) {
1225
+ try {
1226
+ listener(state);
1227
+ } catch {
1228
+ }
1229
+ }
1230
+ }
1231
+ subscribe(listener) {
1232
+ this.listeners.add(listener);
1233
+ return () => this.listeners.delete(listener);
1234
+ }
1235
+ getTrackingState(nodeId) {
1236
+ return this.targets.get(nodeId);
1237
+ }
1238
+ getAllStates() {
1239
+ return Array.from(this.targets.values());
1240
+ }
1241
+ getStats() {
1242
+ const states = this.getAllStates();
1243
+ return {
1244
+ total: states.length,
1245
+ tracking: states.filter((s) => s.status === "tracking").length,
1246
+ lost: states.filter((s) => s.status === "lost").length,
1247
+ recovering: states.filter((s) => s.status === "recovering").length,
1248
+ removed: states.filter((s) => s.status === "removed").length
1249
+ };
1250
+ }
1251
+ reset() {
1252
+ this.targets.clear();
1253
+ }
1254
+ get subscribedEventCount() {
1255
+ return OBJECT_TRACKING_EVENTS.length;
1256
+ }
1257
+ };
1258
+
1259
+ exports.AssetLoadCoordinator = AssetLoadCoordinator;
1260
+ exports.GenerativeJobMonitor = GenerativeJobMonitor;
1261
+ exports.NeuralForgeCoordinator = NeuralForgeCoordinator;
1262
+ exports.ObjectTrackingCoordinator = ObjectTrackingCoordinator;
1263
+ exports.SecurityEventBus = SecurityEventBus;
1264
+ exports.SessionPresenceCoordinator = SessionPresenceCoordinator;
1265
+ //# sourceMappingURL=index.cjs.map
1266
+ //# sourceMappingURL=index.cjs.map