@holoscript/core 6.0.3 → 6.1.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 (368) hide show
  1. package/README.md +40 -40
  2. package/bin/holoscript.cjs +3 -0
  3. package/dist/GLTFPipeline-SFIORFJU.js +16 -0
  4. package/dist/GLTFPipeline-VNNDPONV.cjs +37 -0
  5. package/dist/{HoloScriptPlusParser-BZR5DELQ.js → HoloScriptPlusParser-7FBIFUFC.js} +6 -5
  6. package/dist/{HoloScriptPlusParser-SBMYDNXO.cjs → HoloScriptPlusParser-A2W7OCN2.cjs} +17 -16
  7. package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
  8. package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
  9. package/dist/{USDZExporter-MHEHXZB4.cjs → USDZExporter-3FWJ25JI.cjs} +344 -16
  10. package/dist/{USDZExporter-YA55ZS35.js → USDZExporter-D2HQLQYK.js} +344 -16
  11. package/dist/agents/index.cjs +19 -0
  12. package/dist/agents/index.d.ts +100 -0
  13. package/dist/agents/index.js +17 -0
  14. package/dist/chunk-22W6NGYN.js +725 -0
  15. package/dist/{chunk-XSUZMPVQ.cjs → chunk-27MPVJVZ.cjs} +64 -28
  16. package/dist/{chunk-W76ETJTI.js → chunk-2A7FURVO.js} +44 -8
  17. package/dist/{chunk-C7BNX4XJ.js → chunk-2B7WVIDZ.js} +11 -8
  18. package/dist/chunk-2BSMSUCE.js +1941 -0
  19. package/dist/chunk-2HLIGOKU.cjs +5546 -0
  20. package/dist/{chunk-GC3YU46J.js → chunk-2M2DPHKB.js} +4 -4
  21. package/dist/{chunk-A6GO3DPZ.cjs → chunk-2YSNA2F2.cjs} +321 -49
  22. package/dist/{chunk-ZL6VJ6SN.js → chunk-33XCOVE3.js} +5 -5
  23. package/dist/chunk-3FOKASKO.cjs +348 -0
  24. package/dist/{chunk-XSF76QRU.js → chunk-4C57PR42.js} +3 -3
  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-4SY77NA4.cjs +413 -0
  29. package/dist/{chunk-74YCHHTE.js → chunk-4UUKPCY4.js} +670 -116
  30. package/dist/{chunk-VZNKJZTT.cjs → chunk-52ULD552.cjs} +178 -113
  31. package/dist/{chunk-65RFOWZI.js → chunk-5CKA5SXU.js} +441 -23
  32. package/dist/chunk-5FSKKMR7.cjs +2092 -0
  33. package/dist/{chunk-FF3Q7ADR.js → chunk-5JEU52DW.js} +5 -3
  34. package/dist/chunk-5N54COB6.cjs +327 -0
  35. package/dist/chunk-5S7RKFGR.cjs +446 -0
  36. package/dist/{chunk-EJA7G2C4.cjs → chunk-5WUNN6ZN.cjs} +2 -2
  37. package/dist/{chunk-ELLQPFAF.js → chunk-6ASWLXXN.js} +24 -10
  38. package/dist/chunk-6CTRH7HT.cjs +1985 -0
  39. package/dist/{chunk-ARNKA274.cjs → chunk-6EX3I5P4.cjs} +6 -6
  40. package/dist/chunk-6FGQNDR4.js +5731 -0
  41. package/dist/{chunk-X4YVN7H3.cjs → chunk-6KMK2UXT.cjs} +152 -56
  42. package/dist/{chunk-KUJRR4FJ.js → chunk-6L4VE27M.js} +36 -24
  43. package/dist/{chunk-RT7LJRSF.cjs → chunk-6S6TKNEA.cjs} +7357 -8312
  44. package/dist/chunk-77V4GTCA.js +596 -0
  45. package/dist/{chunk-XH7SE4HH.cjs → chunk-7AD52FRS.cjs} +19 -19
  46. package/dist/chunk-7OPW2KO7.cjs +639 -0
  47. package/dist/chunk-A6KINLZJ.js +236 -0
  48. package/dist/chunk-AIA52I7T.cjs +543 -0
  49. package/dist/chunk-AIX25INK.cjs +602 -0
  50. package/dist/{chunk-WN3YF33G.cjs → chunk-AO4I2Z7M.cjs} +15 -17
  51. package/dist/{chunk-TSWTWZ42.cjs → chunk-BPICAGBV.cjs} +376 -209
  52. package/dist/chunk-BRQJKJGT.cjs +20 -0
  53. package/dist/{chunk-3FXV5S25.cjs → chunk-C37BHB7N.cjs} +6 -3
  54. package/dist/{chunk-XNMEH2BI.js → chunk-CBJY23VL.js} +3 -3
  55. package/dist/chunk-CIWWXYHZ.cjs +50 -0
  56. package/dist/{chunk-NTMZSDXM.cjs → chunk-DIL6DDDN.cjs} +101 -45
  57. package/dist/chunk-DMXC24WV.js +404 -0
  58. package/dist/{chunk-SPDELRRV.cjs → chunk-DTGBOSEM.cjs} +12 -12
  59. package/dist/chunk-E7JP3BS3.cjs +61 -0
  60. package/dist/{chunk-HJJLD366.js → chunk-EKBKLK7P.js} +3 -3
  61. package/dist/chunk-EKYL4PE3.cjs +404 -0
  62. package/dist/{chunk-7N3JIJMT.js → chunk-EMMC5CSQ.js} +12 -8
  63. package/dist/{chunk-EUFLX2PI.js → chunk-EOBB6A4B.js} +7263 -8214
  64. package/dist/chunk-EOFNVCM6.js +325 -0
  65. package/dist/{chunk-NKRKT6V2.js → chunk-ER4GATIU.js} +11 -10
  66. package/dist/{chunk-N5FTS757.cjs → chunk-EXKSFGSX.cjs} +7 -148
  67. package/dist/{chunk-LK5IAVH6.cjs → chunk-EXUP2BUM.cjs} +27 -27
  68. package/dist/chunk-FDSGHPAK.js +130 -0
  69. package/dist/chunk-FEWUHQNM.cjs +144 -0
  70. package/dist/{chunk-5TOFIR6L.js → chunk-FGGJQRLZ.js} +5 -142
  71. package/dist/chunk-FHP6LXJS.js +415 -0
  72. package/dist/{chunk-7LCYLPW2.cjs → chunk-FJPADH77.cjs} +7 -4
  73. package/dist/{chunk-HBZYCASG.js → chunk-FXKTYFYA.js} +203 -36
  74. package/dist/chunk-GCMWDSBZ.cjs +729 -0
  75. package/dist/chunk-GJNCFRJU.cjs +125 -0
  76. package/dist/{chunk-I3XGTIHM.cjs → chunk-GMP623FG.cjs} +16 -13
  77. package/dist/{chunk-CNVM7J3M.js → chunk-GN3KDX4W.js} +149 -53
  78. package/dist/{chunk-WFJIDI2N.cjs → chunk-GQYKQSTC.cjs} +10 -10
  79. package/dist/chunk-GTU2Z2WW.cjs +262 -0
  80. package/dist/chunk-GZG4KA4E.js +529 -0
  81. package/dist/{chunk-DIEDKX5B.cjs → chunk-H3MGK7TX.cjs} +45 -33
  82. package/dist/{chunk-DN7UFU63.cjs → chunk-H5DZIHJP.cjs} +14 -17
  83. package/dist/{chunk-DH5G2JUA.cjs → chunk-HANL7K2Q.cjs} +66 -53
  84. package/dist/{chunk-EGIZHYJP.cjs → chunk-HCCQLAA4.cjs} +2 -13
  85. package/dist/{chunk-HHS6FMOU.cjs → chunk-HGVXZDSK.cjs} +178 -29
  86. package/dist/{chunk-LBPEZQAF.js → chunk-HRODTEEO.js} +30 -10
  87. package/dist/{chunk-ZGTGVSTZ.js → chunk-HYNTS5CP.js} +2 -2
  88. package/dist/{chunk-RE3OKSYF.cjs → chunk-HZCQO4JM.cjs} +6 -6
  89. package/dist/{chunk-NCUHGRTZ.js → chunk-I2O7TW6B.js} +12 -8
  90. package/dist/chunk-IHESJZSW.js +4490 -0
  91. package/dist/{chunk-7H5UNJZD.cjs → chunk-IRWWS72C.cjs} +64 -22
  92. package/dist/{chunk-EMO7HAKJ.cjs → chunk-IVIA7K75.cjs} +691 -133
  93. package/dist/chunk-IVY74O6C.js +247 -0
  94. package/dist/chunk-J32ZJZJH.js +554 -0
  95. package/dist/chunk-JD7CIZ33.js +1949 -0
  96. package/dist/{chunk-7X2IEJIE.cjs → chunk-JIYN45TV.cjs} +41 -42
  97. package/dist/{chunk-XDXZM3ZP.cjs → chunk-KHPCJRI3.cjs} +24 -21
  98. package/dist/chunk-KKFZ3B6J.cjs +557 -0
  99. package/dist/chunk-KPJL34Y7.cjs +186 -0
  100. package/dist/{chunk-7KPI4EKH.cjs → chunk-KQTPCYTG.cjs} +130 -50
  101. package/dist/{chunk-F5LVGHNT.js → chunk-KX76JUQY.js} +3 -3
  102. package/dist/chunk-L4LFINPO.js +623 -0
  103. package/dist/{chunk-2UX5LRAP.cjs → chunk-L63H3SQ4.cjs} +46 -32
  104. package/dist/{chunk-NLPSZT4C.js → chunk-LAOCQJ2M.js} +64 -8
  105. package/dist/chunk-LM2VU56C.cjs +37 -0
  106. package/dist/chunk-M56JSP4A.js +400 -0
  107. package/dist/chunk-MBOOR7X4.js +18 -0
  108. package/dist/{chunk-PQLGZKMC.cjs → chunk-MJVIRCUV.cjs} +31 -27
  109. package/dist/{chunk-AC4BSHFV.js → chunk-MSMIFMBL.js} +135 -18
  110. package/dist/{chunk-56IF4NTA.js → chunk-MXFUTKCO.js} +18 -18
  111. package/dist/{chunk-NRUB55IT.cjs → chunk-MXJ5SS53.cjs} +450 -32
  112. package/dist/chunk-MXWNGCRS.js +2176 -0
  113. package/dist/chunk-MYY4PMWX.cjs +264 -0
  114. package/dist/chunk-N75IH2HY.js +258 -0
  115. package/dist/chunk-NG77ATEW.cjs +778 -0
  116. package/dist/chunk-NW5G5FBQ.js +215 -0
  117. package/dist/{chunk-4FCZDTD5.js → chunk-OEFY723R.js} +29 -16
  118. package/dist/chunk-OEV5RMZO.cjs +3042 -0
  119. package/dist/{chunk-VSXOIUCF.cjs → chunk-OIQYIIO3.cjs} +7 -7
  120. package/dist/{chunk-32TWR3HE.js → chunk-OL46QLBJ.js} +3 -12
  121. package/dist/chunk-OPZ7XDDI.js +487 -0
  122. package/dist/chunk-OSYNRVOV.cjs +243 -0
  123. package/dist/{chunk-HUFNKFA6.js → chunk-P7YIA5LN.js} +93 -13
  124. package/dist/chunk-PGANYCAG.cjs +220 -0
  125. package/dist/{chunk-CO2VM2DK.js → chunk-QAVXL2IH.js} +62 -20
  126. package/dist/{chunk-BO2OKHIY.js → chunk-QCCBXSCE.js} +1640 -1311
  127. package/dist/{chunk-WYH4GVZ5.js → chunk-QPOQ7VPI.js} +16 -13
  128. package/dist/{chunk-V42NTCFH.js → chunk-QTPMJRGS.js} +2331 -17
  129. package/dist/{chunk-FEFHPUEM.cjs → chunk-QWNQ523V.cjs} +1705 -1382
  130. package/dist/{chunk-VK5AXKO3.js → chunk-R3IVNY6P.js} +166 -101
  131. package/dist/chunk-R75BSDH7.cjs +50 -0
  132. package/dist/{chunk-AIUXRS74.cjs → chunk-RMHC2VG7.cjs} +2358 -41
  133. package/dist/chunk-RUXGBKPS.cjs +4517 -0
  134. package/dist/{chunk-PLMYCCA4.js → chunk-S5IFXW6E.js} +113 -9
  135. package/dist/{chunk-27LWW5FU.cjs → chunk-S6YWHCKV.cjs} +5 -5
  136. package/dist/{chunk-SUCBB66F.js → chunk-SIEXCILW.js} +3 -3
  137. package/dist/{chunk-CLYEIWA5.cjs → chunk-SLU6UPJI.cjs} +5 -3
  138. package/dist/{chunk-H6WMMLQK.cjs → chunk-T5J7ZKP3.cjs} +454 -61
  139. package/dist/chunk-TDCNJHWO.js +341 -0
  140. package/dist/{chunk-IHOUYQIA.js → chunk-TG7O4WBC.js} +5 -5
  141. package/dist/chunk-THCK6ECW.js +2085 -0
  142. package/dist/chunk-TJHVSBP2.js +439 -0
  143. package/dist/chunk-TK74TR4H.js +5541 -0
  144. package/dist/{chunk-BU5ZAFMC.js → chunk-U4NBQJBY.js} +11 -13
  145. package/dist/{chunk-Y5MUAYTO.js → chunk-UD3DSHZM.js} +10 -13
  146. package/dist/chunk-UDMYRFDZ.js +3038 -0
  147. package/dist/{chunk-PPULB4GG.cjs → chunk-UOIGFQXC.cjs} +90 -68
  148. package/dist/{chunk-EPWRXL6S.js → chunk-URG2SJLK.js} +41 -42
  149. package/dist/{chunk-VJVCD5T5.cjs → chunk-V73NPPTM.cjs} +152 -35
  150. package/dist/chunk-VECQYRXL.js +474 -0
  151. package/dist/chunk-VEXPG4WN.js +1989 -0
  152. package/dist/{chunk-4SMUJFHL.js → chunk-VMLKSV26.js} +9 -6
  153. package/dist/{chunk-HKCVM6OK.cjs → chunk-VSK7W3O5.cjs} +47 -27
  154. package/dist/chunk-VVKVQZI6.js +55 -0
  155. package/dist/{chunk-KDB6BUMB.js → chunk-W55Z7QIX.js} +172 -25
  156. package/dist/{chunk-BY3B7ZYV.cjs → chunk-W6P2GBHH.cjs} +3 -3
  157. package/dist/{chunk-PBA6NXCT.cjs → chunk-W6RW64BB.cjs} +11 -8
  158. package/dist/chunk-WDT3JTGM.cjs +483 -0
  159. package/dist/{chunk-26TLYBFD.js → chunk-WKX5AMOY.js} +3 -3
  160. package/dist/chunk-WNNE3PO3.js +34 -0
  161. package/dist/chunk-WRLUBRKS.cjs +1943 -0
  162. package/dist/chunk-WRNEH5MO.js +3169 -0
  163. package/dist/{chunk-54FHG2MX.js → chunk-WRWEX5ZF.js} +7 -4
  164. package/dist/chunk-X3GJPRVK.cjs +3246 -0
  165. package/dist/{chunk-4KJ2R7VP.cjs → chunk-XFXGA5IW.cjs} +126 -22
  166. package/dist/{chunk-L3Z2HIWJ.cjs → chunk-XHIV6326.cjs} +4 -4
  167. package/dist/chunk-XJAN7CZG.cjs +432 -0
  168. package/dist/chunk-XL6INWKT.js +121 -0
  169. package/dist/{chunk-KYM4XRFG.js → chunk-XMWZG36H.js} +4 -4
  170. package/dist/{chunk-BKIGPPVM.js → chunk-XSFNHP2E.js} +6 -3
  171. package/dist/{chunk-ODGMVILH.js → chunk-XT6JY5W5.js} +25 -3
  172. package/dist/chunk-XXZJEFKW.cjs +490 -0
  173. package/dist/chunk-Y3MWXQSB.cjs +5737 -0
  174. package/dist/chunk-YF2I3MV3.js +46 -0
  175. package/dist/{chunk-CMYAWUX3.js → chunk-YIMN575O.js} +445 -53
  176. package/dist/chunk-YIVFJNYV.js +176 -0
  177. package/dist/{chunk-V2ILLPHK.cjs → chunk-YKGPCZEE.cjs} +10 -10
  178. package/dist/chunk-YQELFNJV.js +39 -0
  179. package/dist/chunk-YSCKYJOB.cjs +2196 -0
  180. package/dist/chunk-Z5XMPRNC.cjs +5390 -0
  181. package/dist/{chunk-3FYZOR7S.cjs → chunk-ZDSYWBIE.cjs} +18 -18
  182. package/dist/{chunk-CQDOF3G7.cjs → chunk-ZKSS47EV.cjs} +24 -19
  183. package/dist/chunk-ZUL5AVTX.cjs +1993 -0
  184. package/dist/chunk-ZXBZVXDW.js +5386 -0
  185. package/dist/{chunk-AW7WAELW.js → chunk-ZZ7RO2UQ.js} +314 -46
  186. package/dist/cli/holoscript-runner.cjs +203 -206
  187. package/dist/cli/holoscript-runner.js +147 -150
  188. package/dist/codebase/index.cjs +1 -1
  189. package/dist/codebase/index.d.ts +25 -0
  190. package/dist/codebase/index.js +1 -1
  191. package/dist/compiler/agent-inference.cjs +10 -8
  192. package/dist/compiler/agent-inference.js +6 -4
  193. package/dist/compiler/android-xr.cjs +12 -8
  194. package/dist/compiler/android-xr.js +10 -6
  195. package/dist/compiler/android.cjs +12 -9
  196. package/dist/compiler/android.js +10 -7
  197. package/dist/compiler/ar.cjs +9 -7
  198. package/dist/compiler/ar.js +7 -5
  199. package/dist/compiler/babylon.cjs +12 -9
  200. package/dist/compiler/babylon.js +11 -8
  201. package/dist/compiler/business-quest.cjs +43 -0
  202. package/dist/compiler/business-quest.js +4 -0
  203. package/dist/compiler/coco.cjs +1 -1
  204. package/dist/compiler/coco.js +1 -1
  205. package/dist/compiler/context.cjs +25 -0
  206. package/dist/compiler/context.d.ts +28 -0
  207. package/dist/compiler/context.js +8 -0
  208. package/dist/compiler/domain-block-utils.cjs +161 -151
  209. package/dist/compiler/domain-block-utils.js +7 -5
  210. package/dist/compiler/dtdl.cjs +10 -8
  211. package/dist/compiler/dtdl.js +7 -5
  212. package/dist/compiler/gltf-pipeline.cjs +9 -9
  213. package/dist/compiler/gltf-pipeline.js +2 -2
  214. package/dist/compiler/godot.cjs +9 -7
  215. package/dist/compiler/godot.js +8 -6
  216. package/dist/compiler/incremental.cjs +12 -8
  217. package/dist/compiler/incremental.js +7 -3
  218. package/dist/compiler/index.cjs +5152 -814
  219. package/dist/compiler/index.d.ts +404 -21
  220. package/dist/compiler/index.js +5063 -859
  221. package/dist/compiler/ios.cjs +11 -9
  222. package/dist/compiler/ios.js +9 -7
  223. package/dist/compiler/llm-provider-capabilities.cjs +25 -0
  224. package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
  225. package/dist/compiler/llm-provider-capabilities.js +8 -0
  226. package/dist/compiler/multi-layer.cjs +14 -17
  227. package/dist/compiler/multi-layer.js +13 -10
  228. package/dist/compiler/nodetoy.cjs +5 -5
  229. package/dist/compiler/nodetoy.js +2 -2
  230. package/dist/compiler/openxr.cjs +10 -7
  231. package/dist/compiler/openxr.js +9 -6
  232. package/dist/compiler/playcanvas.cjs +10 -8
  233. package/dist/compiler/playcanvas.js +9 -7
  234. package/dist/compiler/r3f.cjs +17 -14
  235. package/dist/compiler/r3f.d.ts +22 -0
  236. package/dist/compiler/r3f.js +12 -9
  237. package/dist/compiler/remotion.cjs +1 -1
  238. package/dist/compiler/remotion.js +1 -1
  239. package/dist/compiler/reproducibility.cjs +1 -1
  240. package/dist/compiler/reproducibility.js +1 -1
  241. package/dist/compiler/sdf.cjs +10 -8
  242. package/dist/compiler/sdf.js +8 -6
  243. package/dist/compiler/semantic-scene.cjs +7 -7
  244. package/dist/compiler/semantic-scene.js +2 -2
  245. package/dist/compiler/state.cjs +9 -6
  246. package/dist/compiler/state.js +7 -4
  247. package/dist/compiler/trait-composition.cjs +11 -8
  248. package/dist/compiler/trait-composition.js +7 -4
  249. package/dist/compiler/unity.cjs +10 -7
  250. package/dist/compiler/unity.js +9 -6
  251. package/dist/compiler/unreal.cjs +11 -8
  252. package/dist/compiler/unreal.js +9 -6
  253. package/dist/compiler/urdf.cjs +20 -14
  254. package/dist/compiler/urdf.js +8 -6
  255. package/dist/compiler/usd-physics.cjs +10 -8
  256. package/dist/compiler/usd-physics.js +7 -5
  257. package/dist/compiler/visionos.cjs +10 -7
  258. package/dist/compiler/visionos.js +9 -6
  259. package/dist/compiler/vrchat.cjs +10 -8
  260. package/dist/compiler/vrchat.js +8 -6
  261. package/dist/compiler/vrr.cjs +10 -8
  262. package/dist/compiler/vrr.js +8 -6
  263. package/dist/compiler/wasm.cjs +13 -11
  264. package/dist/compiler/wasm.js +8 -6
  265. package/dist/compiler/webgpu.cjs +9 -7
  266. package/dist/compiler/webgpu.js +8 -6
  267. package/dist/constants.d.ts +4 -0
  268. package/dist/coordinators/index.cjs +1266 -0
  269. package/dist/coordinators/index.d.ts +260 -0
  270. package/dist/coordinators/index.js +1259 -0
  271. package/dist/debugger.cjs +9 -7
  272. package/dist/debugger.js +7 -5
  273. package/dist/entries/interop.cjs +23 -21
  274. package/dist/entries/interop.d.ts +9 -0
  275. package/dist/entries/interop.js +5 -3
  276. package/dist/entries/scripting.cjs +18 -17
  277. package/dist/entries/scripting.d.ts +7 -0
  278. package/dist/entries/scripting.js +8 -7
  279. package/dist/hololand/index.cjs +146 -0
  280. package/dist/hololand/index.d.ts +70 -0
  281. package/dist/hololand/index.js +5 -0
  282. package/dist/index.cjs +21396 -39967
  283. package/dist/index.d.ts +1496 -40
  284. package/dist/index.js +21066 -40142
  285. package/dist/math/tropical-spmv.cjs +45 -0
  286. package/dist/math/tropical-spmv.js +4 -0
  287. package/dist/math/vec3.cjs +14 -14
  288. package/dist/math/vec3.js +2 -2
  289. package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
  290. package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
  291. package/dist/paper-0c-spike/index.cjs +150 -0
  292. package/dist/paper-0c-spike/index.d.ts +29 -0
  293. package/dist/paper-0c-spike/index.js +141 -0
  294. package/dist/parser.cjs +45 -10
  295. package/dist/parser.d.ts +11 -0
  296. package/dist/parser.js +10 -7
  297. package/dist/{playwright-7DTEQCBD.cjs → playwright-3AT3AKTV.cjs} +1985 -1985
  298. package/dist/{playwright-BIZXMLD2.js → playwright-VZPDVUEQ.js} +3 -3
  299. package/dist/reconstruction/index.cjs +153 -0
  300. package/dist/reconstruction/index.d.ts +105 -0
  301. package/dist/reconstruction/index.js +8 -0
  302. package/dist/runtime.cjs +7 -5
  303. package/dist/runtime.js +6 -4
  304. package/dist/self-improvement/index.cjs +563 -0
  305. package/dist/self-improvement/index.d.ts +0 -48
  306. package/dist/self-improvement/index.js +545 -0
  307. package/dist/storage/index.cjs +10 -9
  308. package/dist/storage/index.d.ts +24 -0
  309. package/dist/storage/index.js +3 -2
  310. package/dist/testing.cjs +25 -0
  311. package/dist/testing.d.ts +70 -0
  312. package/dist/testing.js +4 -0
  313. package/dist/tools/index.d.ts +33 -0
  314. package/dist/traitDocs/traitDocs.cjs +33 -0
  315. package/dist/traitDocs/traitDocs.d.ts +69 -0
  316. package/dist/traitDocs/traitDocs.js +7 -0
  317. package/dist/traits/botanical-lotus.cjs +41 -0
  318. package/dist/traits/botanical-lotus.d.ts +172 -0
  319. package/dist/traits/botanical-lotus.js +4 -0
  320. package/dist/traits/engines/index.cjs +520 -0
  321. package/dist/traits/engines/index.d.ts +111 -0
  322. package/dist/traits/engines/index.js +380 -0
  323. package/dist/traits/index.cjs +14387 -4320
  324. package/dist/traits/index.d.ts +197 -0
  325. package/dist/traits/index.js +16455 -6958
  326. package/dist/traits/simulation-solver-factory.cjs +13 -0
  327. package/dist/traits/simulation-solver-factory.d.ts +23 -0
  328. package/dist/traits/simulation-solver-factory.js +4 -0
  329. package/dist/traits/webcam-gaze.cjs +35 -0
  330. package/dist/traits/webcam-gaze.d.ts +17 -0
  331. package/dist/traits/webcam-gaze.js +4 -0
  332. package/dist/type-checker.cjs +6 -5
  333. package/dist/type-checker.js +4 -3
  334. package/dist/world/index.cjs +947 -0
  335. package/dist/world/index.d.ts +147 -0
  336. package/dist/world/index.js +939 -0
  337. package/dist/world-model/index.cjs +1446 -0
  338. package/dist/world-model/index.d.ts +119 -0
  339. package/dist/world-model/index.js +1414 -0
  340. package/dist/wot/index.cjs +7 -7
  341. package/dist/wot/index.js +2 -2
  342. package/package.json +150 -23
  343. package/dist/GLTFPipeline-3KLWWUQO.cjs +0 -34
  344. package/dist/GLTFPipeline-LYII2ZVQ.js +0 -13
  345. package/dist/chunk-3KEU5QYY.cjs +0 -175
  346. package/dist/chunk-6OQBLABR.js +0 -5240
  347. package/dist/chunk-6WNCRE6F.js +0 -126
  348. package/dist/chunk-C2QHVHZF.js +0 -4066
  349. package/dist/chunk-CN4NOESF.cjs +0 -416
  350. package/dist/chunk-DXVCEFZB.js +0 -2027
  351. package/dist/chunk-ENV7K6XA.js +0 -282
  352. package/dist/chunk-H7XMORZI.js +0 -2731
  353. package/dist/chunk-HAN4V3PF.cjs +0 -2037
  354. package/dist/chunk-HF4OFY25.cjs +0 -4097
  355. package/dist/chunk-LER4WXW5.cjs +0 -286
  356. package/dist/chunk-M6FU6S22.js +0 -2911
  357. package/dist/chunk-MWEFR6YQ.js +0 -1857
  358. package/dist/chunk-PJMOXFPR.cjs +0 -1861
  359. package/dist/chunk-QHVVVN47.cjs +0 -2033
  360. package/dist/chunk-QWKUKVRE.js +0 -2026
  361. package/dist/chunk-UITWA6DV.cjs +0 -2829
  362. package/dist/chunk-UQW6SLM5.js +0 -172
  363. package/dist/chunk-WUXIRGZP.cjs +0 -2915
  364. package/dist/chunk-X67XRI2T.js +0 -410
  365. package/dist/chunk-Y7VK5TH3.cjs +0 -129
  366. package/dist/chunk-YCMQQQ5U.cjs +0 -5244
  367. package/dist/post-quantum-JTTAAGO3.cjs +0 -6
  368. package/dist/post-quantum-RVPVDEPI.js +0 -4
@@ -1,469 +1,642 @@
1
- import { init_R3FCompiler, MATERIAL_PRESETS } from './chunk-HBZYCASG.js';
2
- import { init_DomainBlockCompilerMixin, compileDomainBlocks, inputToUSDA, compileInputBlock, navigationToUSDA, compileNavigationBlock, renderingToUSDA, compileRenderingBlock, proceduralToUSDA, compileProceduralBlock, web3ToUSDA, compileWeb3Block, architectureToUSDA, compileArchitectureBlock, musicToUSDA, compileMusicBlock, educationToUSDA, compileEducationBlock, datavizToUSDA, compileDataVizBlock, iotToUSDA, compileIoTBlock, compileRoboticsBlock, roboticsToUSDA, compileHealthcareBlock, healthcareToUSDA, compilePaymentBlock, paymentToUSDA, compileNarrativeBlock, narrativeToUSDA, compileWeatherBlock, weatherToUSD, compileAudioSourceBlock, audioSourceToUSD, compilePostProcessingBlock, postProcessingToUSD, compileParticleBlock, particlesToUSD, compilePhysicsBlock, compileMaterialBlock, materialToUSD } from './chunk-KDB6BUMB.js';
3
- import { init_CompilerBase, CompilerBase, init_ANSNamespace, ANSCapabilityPath } from './chunk-QWKUKVRE.js';
4
- import { __export, __esm } from './chunk-32TWR3HE.js';
1
+ import { init_R3FCompiler, MATERIAL_PRESETS } from './chunk-FXKTYFYA.js';
2
+ import { init_ProvenanceSemiring, ProvenanceSemiring } from './chunk-TJHVSBP2.js';
3
+ import { init_TraitCompositor, TraitCompositor } from './chunk-4C57PR42.js';
4
+ import { init_PlatformConditional, platformCategory, PLATFORM_CAPABILITIES, PLATFORM_CATEGORIES } from './chunk-GZG4KA4E.js';
5
+ import { init_DomainBlockCompilerMixin, compileDomainBlocks, inputToUSDA, compileInputBlock, navigationToUSDA, compileNavigationBlock, renderingToUSDA, compileRenderingBlock, proceduralToUSDA, compileProceduralBlock, web3ToUSDA, compileWeb3Block, architectureToUSDA, compileArchitectureBlock, musicToUSDA, compileMusicBlock, educationToUSDA, compileEducationBlock, datavizToUSDA, compileDataVizBlock, iotToUSDA, compileIoTBlock, compileRoboticsBlock, roboticsToUSDA, compileHealthcareBlock, healthcareToUSDA, compilePaymentBlock, paymentToUSDA, compileNarrativeBlock, narrativeToUSDA, compileWeatherBlock, weatherToUSD, compileAudioSourceBlock, audioSourceToUSD, compilePostProcessingBlock, postProcessingToUSD, compileParticleBlock, particlesToUSD, compilePhysicsBlock, compileMaterialBlock, materialToUSD } from './chunk-W55Z7QIX.js';
6
+ import { init_CompilerBase, CompilerBase } from './chunk-QTPMJRGS.js';
7
+ import { parsePipeline } from './chunk-J32ZJZJH.js';
8
+ import { __export, __esm } from './chunk-OL46QLBJ.js';
9
+ import { ANSCapabilityPath } from '@holoscript/core-types/ans';
5
10
 
6
- // src/compiler/Native2DCompiler.ts
7
- var Native2DCompiler_exports = {};
8
- __export(Native2DCompiler_exports, {
9
- Native2DCompiler: () => Native2DCompiler
11
+ // src/compiler/ThreeJSCompiler.ts
12
+ var ThreeJSCompiler_exports = {};
13
+ __export(ThreeJSCompiler_exports, {
14
+ ThreeJSCompiler: () => ThreeJSCompiler
10
15
  });
11
- var Native2DCompiler;
12
- var init_Native2DCompiler = __esm({
13
- "src/compiler/Native2DCompiler.ts"() {
16
+ var SHAPE_TO_THREE_GEOMETRY, ThreeJSCompiler;
17
+ var init_ThreeJSCompiler = __esm({
18
+ "src/compiler/ThreeJSCompiler.ts"() {
19
+ init_TraitCompositor();
20
+ init_ProvenanceSemiring();
14
21
  init_CompilerBase();
15
- Native2DCompiler = class extends CompilerBase {
16
- constructor() {
17
- super(...arguments);
18
- this.compilerName = "Native2DCompiler";
19
- // ============================================================================
20
- // REACT GENERATION
21
- // ============================================================================
22
- /** Collected during node traversal — used to generate imports and hooks */
23
- this._slotImports = /* @__PURE__ */ new Map();
24
- this._uiImports = /* @__PURE__ */ new Set();
25
- this._stateFields = /* @__PURE__ */ new Map();
26
- this._fetchCalls = [];
27
- this._options = {};
28
- }
29
- // @ts-expect-error During migration
30
- compile(composition, agentToken, outputPath, options) {
22
+ SHAPE_TO_THREE_GEOMETRY = {
23
+ sphere: "SphereGeometry",
24
+ orb: "SphereGeometry",
25
+ cube: "BoxGeometry",
26
+ box: "BoxGeometry",
27
+ cylinder: "CylinderGeometry",
28
+ cone: "ConeGeometry",
29
+ pyramid: "ConeGeometry",
30
+ plane: "PlaneGeometry",
31
+ ground: "PlaneGeometry",
32
+ torus: "TorusGeometry",
33
+ ring: "TorusGeometry",
34
+ capsule: "CapsuleGeometry"
35
+ };
36
+ ThreeJSCompiler = class extends CompilerBase {
37
+ constructor(options = {}) {
38
+ super();
39
+ this.compilerName = "ThreeJSCompiler";
40
+ this.lines = [];
41
+ this.indentLevel = 0;
42
+ this.options = {
43
+ className: options.className ?? "GeneratedScene",
44
+ enableShadows: options.enableShadows ?? true,
45
+ enablePostProcessing: options.enablePostProcessing ?? false,
46
+ indent: options.indent ?? " ",
47
+ provenanceHash: options.provenanceHash ?? ""
48
+ };
49
+ }
50
+ getRequiredCapability() {
51
+ return ANSCapabilityPath.R3F;
52
+ }
53
+ compile(composition, agentToken, outputPath) {
31
54
  this.validateCompilerAccess(agentToken, outputPath);
32
- const isReact = options?.format === "react";
33
- const elements = composition.ui?.elements || composition.objects || [];
34
- if (isReact) {
35
- const code = this.generateReactComponent(composition.name, elements, composition, options);
36
- if (options?.generateDocs) {
37
- return {
38
- output: code,
39
- documentation: this.generateDocumentation(composition, code, options.docsOptions)
40
- };
41
- }
42
- return code;
43
- } else {
44
- const code = this.generateHTMLPage(composition.name, elements, composition);
45
- if (options?.generateDocs) {
46
- return {
47
- output: code,
48
- documentation: this.generateDocumentation(composition, code, options.docsOptions)
49
- };
50
- }
51
- return code;
52
- }
53
- }
54
- generateReactComponent(name, objects, composition, options) {
55
- this._slotImports.clear();
56
- this._uiImports.clear();
57
- this._stateFields.clear();
58
- this._fetchCalls = [];
59
- this._options = options || {};
60
- const safeName = name.replace(/[^a-zA-Z0-9]/g, "");
61
- if (composition?.state?.properties) {
62
- for (const prop of composition.state.properties) {
63
- this._stateFields.set(prop.key, prop.value ?? null);
64
- }
55
+ this.lines = [];
56
+ this.indentLevel = 0;
57
+ this.emit("// Auto-generated by HoloScript ThreeJSCompiler");
58
+ this.emit(
59
+ `// Source: composition "${this.escapeStringValue(composition.name, "TypeScript")}"`
60
+ );
61
+ if (this.options.provenanceHash) {
62
+ this.emit(`// Provenance Hash: ${this.options.provenanceHash}`);
65
63
  }
66
- const jsx = objects.map((obj) => this.generateReactNode(obj)).join("\n ");
67
- const imports = [];
68
- const reactImports = /* @__PURE__ */ new Set();
69
- if (this._stateFields.size > 0) reactImports.add("useState");
70
- if (this._fetchCalls.length > 0) reactImports.add("useEffect");
71
- imports.push(
72
- reactImports.size > 0 ? `import React, { ${[...reactImports].join(", ")} } from 'react';` : `import React from 'react';`
64
+ this.emit("");
65
+ this.emitImports(composition);
66
+ this.emit("");
67
+ this.emit(`export class ${this.options.className} {`);
68
+ this.indent();
69
+ this.emit("private scene: THREE.Scene;");
70
+ this.emit("private renderer: THREE.WebGLRenderer;");
71
+ this.emit("private camera: THREE.PerspectiveCamera;");
72
+ this.emit("private canvas: HTMLCanvasElement;");
73
+ this.emit("private frameId: number = 0;");
74
+ this.emit("");
75
+ this.emit("constructor(canvas: HTMLCanvasElement) {");
76
+ this.indent();
77
+ this.emit("this.canvas = canvas;");
78
+ this.emit("this.scene = new THREE.Scene();");
79
+ this.emit(
80
+ "this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: false });"
73
81
  );
74
- if (this._uiImports.size > 0) {
75
- imports.push(`import { ${[...this._uiImports].join(", ")} } from '@holoscript/ui';`);
76
- }
77
- for (const [, slot] of this._slotImports) {
78
- imports.push(`import { ${slot.component} } from '${slot.importPath}';`);
79
- }
80
- const stateHooks = [];
81
- for (const [key, value] of this._stateFields) {
82
- const capitalKey = key.charAt(0).toUpperCase() + key.slice(1);
83
- const initValue = JSON.stringify(value);
84
- stateHooks.push(` const [${key}, set${capitalKey}] = useState(${initValue === void 0 ? "null" : initValue});`);
85
- }
86
- const fetchEffects = [];
87
- for (const f of this._fetchCalls) {
88
- fetchEffects.push(` useEffect(() => {
89
- fetch(\`${f.endpoint}\`${f.method !== "GET" ? `, { method: '${f.method}' }` : ""})
90
- .then(r => r.json())
91
- .then(set${f.name.charAt(0).toUpperCase() + f.name.slice(1)})
92
- .catch(console.error);
93
- }, []);`);
94
- }
95
- return `${imports.join("\n")}
96
-
97
- // @generated by HoloScript Native2DCompiler \u2014 DO NOT EDIT
98
- export function ${safeName}Component() {
99
- ${stateHooks.join("\n")}
100
- ${fetchEffects.join("\n")}
101
-
102
- return (
103
- <div className="holoscript-2d-root w-full h-full">
104
- ${jsx}
105
- </div>
106
- );
107
- }
108
-
109
- export default ${safeName}Component;
110
- `;
111
- }
112
- generateReactNode(obj) {
113
- const traits = this.extractTraits(obj);
114
- if (traits.slot) {
115
- const slotName = traits.slot.name || obj.name || "Slot";
116
- const configuredSlot = this._options.slots?.[String(slotName)];
117
- const component = traits.slot.component || configuredSlot?.component || slotName;
118
- const importPath = traits.slot.import || configuredSlot?.importPath || `@/components/${component}`;
119
- this._slotImports.set(slotName, { component, importPath });
120
- const propsStr = traits.slot.props ? ` {...${JSON.stringify(traits.slot.props)}}` : "";
121
- return `<div data-holo-slot="${slotName}">
122
- <${component}${propsStr} />
123
- </div>`;
124
- }
125
- if (traits.fetch) {
126
- const name = traits.fetch.into || "data";
127
- const endpoint = traits.fetch.endpoint || "/api/data";
128
- const method = traits.fetch.method || "GET";
129
- this._fetchCalls.push({ name, endpoint, method });
130
- if (!this._stateFields.has(name)) {
131
- this._stateFields.set(name, null);
132
- }
82
+ this.emit("this.renderer.setPixelRatio(window.devicePixelRatio);");
83
+ this.emit("this.renderer.setSize(canvas.clientWidth, canvas.clientHeight);");
84
+ if (this.options.enableShadows) {
85
+ this.emit("this.renderer.shadowMap.enabled = true;");
86
+ this.emit("this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;");
133
87
  }
134
- let tag = traits.theme?.tag || traits.panel?.tag || (typeof obj.type === "string" ? obj.type.toLowerCase() : void 0) || "div";
135
- if ([
136
- "nav",
137
- "section",
138
- "main",
139
- "footer",
140
- "form",
141
- "style",
142
- "a",
143
- "header",
144
- "h1",
145
- "h2",
146
- "h3"
147
- ].includes(tag)) ; else if (tag === "container") {
148
- tag = "div";
149
- } else if (traits.link || tag === "link") {
150
- tag = "a";
151
- } else if (traits.button || tag === "button") {
152
- tag = "button";
153
- } else if (traits.image || tag === "image") {
154
- tag = "img";
155
- } else if (traits.input || tag === "input") {
156
- tag = "input";
157
- } else if (traits.text || tag === "text") {
158
- tag = this.mapTextVariantToTag(traits.text?.variant || "body");
88
+ this.emit(
89
+ "this.camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);"
90
+ );
91
+ this.emit("this.camera.position.set(0, 2, 10);");
92
+ this.dedent();
93
+ this.emit("}");
94
+ this.emit("");
95
+ this.emit("async build(): Promise<void> {");
96
+ this.indent();
97
+ if (composition.environment) this.emitEnvironment(composition.environment);
98
+ if (composition.lights?.length) {
99
+ for (const light of composition.lights) this.emitLight(light);
159
100
  } else {
160
- tag = "div";
161
- }
162
- const styles = this.buildStyles(traits);
163
- const classes = this.buildClasses(traits);
164
- let props = ``;
165
- if (traits.theme?.className) {
166
- classes.push(traits.theme.className);
167
- }
168
- if (traits.theme?.id) {
169
- props += ` id="${traits.theme.id}"`;
170
- }
171
- const combinedStyles = { ...styles };
172
- if (traits.theme?.style) {
173
- traits.theme.style.split(";").forEach((rule) => {
174
- const [key, ...valueParts] = rule.split(":");
175
- const value = valueParts.join(":");
176
- if (key && value) {
177
- const camelKey = key.trim().replace(/-([a-z])/g, (g) => g[1].toUpperCase());
178
- combinedStyles[camelKey] = value.trim();
179
- }
180
- });
101
+ this.emit("// Default lighting");
102
+ this.emit("const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);");
103
+ this.emit("this.scene.add(ambientLight);");
104
+ this.emit("const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);");
105
+ this.emit("dirLight.position.set(5, 10, 5);");
106
+ if (this.options.enableShadows) {
107
+ this.emit("dirLight.castShadow = true;");
108
+ this.emit("dirLight.shadow.mapSize.set(2048, 2048);");
109
+ }
110
+ this.emit("this.scene.add(dirLight);");
111
+ this.emit("");
181
112
  }
182
- if (Object.keys(combinedStyles).length > 0) {
183
- props += ` style={${JSON.stringify(combinedStyles)}}`;
113
+ if (composition.camera) this.emitCamera(composition.camera);
114
+ if (composition.objects?.length) {
115
+ for (const obj of composition.objects) this.emitObject(obj);
184
116
  }
185
- if (classes.length > 0) {
186
- props += ` className="${classes.join(" ")}"`;
117
+ if (composition.spatialGroups?.length) {
118
+ for (const g of composition.spatialGroups) this.emitGroup(g);
187
119
  }
188
- if (traits.theme?.attributes) {
189
- try {
190
- const parsedAttrs = JSON.parse(traits.theme.attributes);
191
- for (const [key, value] of Object.entries(parsedAttrs)) {
192
- props += ` ${key}="${value}"`;
193
- }
194
- } catch (e) {
195
- }
120
+ if (composition.zones?.length) {
121
+ for (const z of composition.zones) this.emitZone(z);
122
+ }
123
+ if (composition.audio?.length) {
124
+ for (const a of composition.audio) this.emitAudio(a);
196
125
  }
197
- if (traits.button?.onClick || traits.form?.onSubmit) {
198
- const action = traits.button?.onClick || traits.form?.onSubmit;
199
- if (action) {
200
- const cleanAction = action.replace(/["']/g, "'");
201
- if (cleanAction.includes("navigate")) {
202
- props += ` onClick={() => ${cleanAction}}`;
203
- } else if (cleanAction.includes("submit")) {
204
- props += ` onSubmit={${cleanAction}}`;
205
- } else if (cleanAction.includes("window.open")) {
206
- props += ` onClick={() => ${cleanAction}}`;
126
+ this.emitRenderLoop();
127
+ this.dedent();
128
+ this.emit("}");
129
+ this.emit("");
130
+ this.emit("dispose(): void {");
131
+ this.indent();
132
+ this.emit("cancelAnimationFrame(this.frameId);");
133
+ this.emit("this.renderer.dispose();");
134
+ this.emit("this.scene.clear();");
135
+ this.dedent();
136
+ this.emit("}");
137
+ this.dedent();
138
+ this.emit("}");
139
+ return this.lines.join("\n");
140
+ }
141
+ // --- Imports ---
142
+ emitImports(_composition) {
143
+ this.emit('import * as THREE from "three";');
144
+ if (this.options.enablePostProcessing) {
145
+ this.emit('import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";');
146
+ this.emit(
147
+ 'import { RenderPass } from "three/addons/postprocessing/RenderPass.js";'
148
+ );
149
+ this.emit(
150
+ 'import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";'
151
+ );
152
+ }
153
+ }
154
+ // --- Environment ---
155
+ emitEnvironment(env) {
156
+ for (const prop of env.properties) {
157
+ if (prop.key === "background" || prop.key === "skybox" || prop.key === "preset") {
158
+ if (typeof prop.value === "string" && prop.value.startsWith("#")) {
159
+ this.emit(`this.scene.background = new THREE.Color(${this.toThreeColorHex(prop.value)});`);
207
160
  } else {
208
- props += ` onClick={() => console.log('${cleanAction}')}`;
161
+ this.emit(`// skybox: "${prop.value}" \u2014 load via THREE.CubeTextureLoader`);
162
+ }
163
+ } else if (prop.key === "fog" && typeof prop.value === "object") {
164
+ const fog = prop.value;
165
+ const near = fog.near ?? 10;
166
+ const far = fog.far ?? 100;
167
+ const color = this.toThreeColorHex(fog.color ?? "#cccccc");
168
+ this.emit(`this.scene.fog = new THREE.Fog(${color}, ${near}, ${far});`);
169
+ } else if (prop.key === "ambient_light") {
170
+ this.emit(
171
+ `this.scene.add(new THREE.AmbientLight(0xffffff, ${prop.value ?? 0.5}));`
172
+ );
173
+ } else if (prop.key === "ground") {
174
+ this.emit(
175
+ `const groundGeom = new THREE.PlaneGeometry(100, 100);`
176
+ );
177
+ this.emit(
178
+ `const groundMat = new THREE.MeshStandardMaterial({ color: 0x888888, roughness: 0.8 });`
179
+ );
180
+ this.emit(`const ground = new THREE.Mesh(groundGeom, groundMat);`);
181
+ this.emit(`ground.rotation.x = -Math.PI / 2;`);
182
+ if (this.options.enableShadows) {
183
+ this.emit(`ground.receiveShadow = true;`);
209
184
  }
185
+ this.emit(`this.scene.add(ground);`);
210
186
  }
211
187
  }
212
- if (traits.image?.src) props += ` src="${traits.image.src}"`;
213
- if (traits.image?.alt) props += ` alt="${traits.image.alt}"`;
214
- if (traits.link?.href) props += ` href="${traits.link.href}"`;
215
- if (traits.input?.placeholder) props += ` placeholder="${traits.input.placeholder}"`;
216
- if (traits.input?.type) props += ` type="${traits.input.type}"`;
217
- if (traits.input?.required) props += ` required`;
218
- if (traits.button?.type) props += ` type="${traits.button.type}"`;
219
- const childrenMarkup = (obj.children || obj.objects || []).map((child) => this.generateReactNode(child)).join("\n");
220
- const content = traits.text?.content || traits.button?.content || traits.link?.content || traits.icon?.name;
221
- let safeContent = "";
222
- if (content) {
223
- safeContent = `{\`${content.replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`}`;
224
- }
225
- if (tag === "style") {
226
- const escapedStyle = (content || "").replace(/`/g, "\\`").replace(/\$/g, "\\$");
227
- return `<style dangerouslySetInnerHTML={{ __html: \`${escapedStyle}\` }} />`;
228
- }
229
- if (tag === "img" || tag === "input") {
230
- return `<${tag}${props} />`;
231
- }
232
- return `<${tag}${props}>
233
- ${safeContent}
234
- ${childrenMarkup}
235
- </${tag}>`;
236
- }
237
- // ============================================================================
238
- // HTML GENERATION
239
- // ============================================================================
240
- generateHTMLPage(name, objects, composition) {
241
- const content = objects.map((obj) => this.generateHTMLNode(obj)).join("\n ");
242
- let bgColor = "#ffffff";
243
- let color = "#000000";
244
- if (composition.environment?.properties) {
245
- const themeProp = composition.environment.properties.find((p) => p.key === "theme");
246
- const bgProp = composition.environment.properties.find((p) => p.key === "backgroundColor");
247
- if (themeProp?.value === "dark" || composition.traits?.some((t) => t.name === "theme" && t.config?.dark)) {
248
- bgColor = bgProp?.value || "#050510";
249
- color = "#ffffff";
188
+ this.emit("");
189
+ }
190
+ // --- Objects ---
191
+ emitObject(obj, parentVar) {
192
+ const v = this.sanitizeName(obj.name);
193
+ let geom = "cube";
194
+ let modelSrc;
195
+ let textContent;
196
+ let position;
197
+ let rotation;
198
+ let scale;
199
+ let size;
200
+ const mat = {};
201
+ for (const p of obj.properties) {
202
+ switch (p.key) {
203
+ case "geometry":
204
+ case "mesh":
205
+ case "type":
206
+ if (typeof p.value === "string") geom = p.value;
207
+ break;
208
+ case "position":
209
+ if (Array.isArray(p.value)) position = p.value;
210
+ break;
211
+ case "rotation":
212
+ if (Array.isArray(p.value)) rotation = p.value;
213
+ break;
214
+ case "scale":
215
+ scale = p.value;
216
+ break;
217
+ case "size":
218
+ size = p.value;
219
+ break;
220
+ case "color":
221
+ mat.color = p.value;
222
+ break;
223
+ case "roughness":
224
+ mat.roughness = p.value;
225
+ break;
226
+ case "metalness":
227
+ case "metallic":
228
+ mat.metalness = p.value;
229
+ break;
230
+ case "opacity":
231
+ mat.opacity = p.value;
232
+ break;
233
+ case "emissive":
234
+ mat.emissive = p.value;
235
+ break;
236
+ case "emissive_intensity":
237
+ case "emissiveIntensity":
238
+ mat.emissiveIntensity = p.value;
239
+ break;
240
+ case "material":
241
+ if (typeof p.value === "object" && p.value !== null)
242
+ Object.assign(mat, p.value);
243
+ break;
244
+ case "model":
245
+ case "src":
246
+ case "source":
247
+ if (typeof p.value === "string") modelSrc = p.value;
248
+ break;
249
+ case "text":
250
+ if (typeof p.value === "string") textContent = p.value;
251
+ break;
250
252
  }
251
253
  }
252
- return `<!DOCTYPE html>
253
- <html lang="en">
254
- <head>
255
- <meta charset="UTF-8">
256
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
257
- <title>${name}</title>
258
- <script src="https://cdn.tailwindcss.com"></script>
259
- <style>
260
- body { margin: 0; padding: 0; background-color: ${bgColor}; color: ${color}; font-family: system-ui, -apple-system, sans-serif; }
261
- /* Basic resets and custom trait animations to mirror React Framer variants */
262
- .glow-btn:hover { box-shadow: 0 0 15px rgba(255,255,255,0.5); }
263
- .lift-card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
264
- .lift-card:hover { transform: translateY(-4px); box-shadow: 0 10px 20px rgba(0,0,0,0.2); }
265
- </style>
266
- </head>
267
- <body>
268
- <div id="holoscript-native-root">
269
- ${content}
270
- </div>
271
- <script>
272
- function navigate(path) { window.location.href = path; }
273
- function submitNewsletter(e) { e.preventDefault(); alert('Subscribed!'); }
274
- </script>
275
- </body>
276
- </html>`;
277
- }
278
- generateHTMLNode(obj) {
279
- const node = obj;
280
- const traits = this.extractTraits(obj);
281
- const nodeType = typeof node.type === "string" ? node.type.toLowerCase() : void 0;
282
- let tag = traits.theme?.tag || traits.panel?.tag || nodeType || "div";
283
- if ([
284
- "nav",
285
- "section",
286
- "main",
287
- "footer",
288
- "form",
289
- "style",
290
- "a",
291
- "header",
292
- "h1",
293
- "h2",
294
- "h3"
295
- ].includes(tag)) ; else if (tag === "container") {
296
- tag = "div";
297
- } else if (traits.link || tag === "link") {
298
- tag = "a";
299
- } else if (traits.button || tag === "button") {
300
- tag = "button";
301
- } else if (traits.image || tag === "image") {
302
- tag = "img";
303
- } else if (traits.input || tag === "input") {
304
- tag = "input";
305
- } else if (traits.text || tag === "text") {
306
- tag = this.mapTextVariantToTag(traits.text?.variant || "body");
254
+ this.emit(`// Object: ${this.escapeStringValue(obj.name, "TypeScript")}`);
255
+ if (modelSrc) {
256
+ this.emit(`// GLTFLoader required for model: "${modelSrc}"`);
257
+ this.emit(`// import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";`);
258
+ this.emit(`const ${v}Loader = new GLTFLoader();`);
259
+ this.emit(
260
+ `const ${v}Gltf = await new Promise<THREE.Group>((resolve, reject) => { ${v}Loader.load("${modelSrc}", (g) => resolve(g.scene), undefined, reject); });`
261
+ );
262
+ this.emit(`const ${v} = ${v}Gltf;`);
263
+ this.emit(`this.scene.add(${v});`);
264
+ } else if (geom === "text" || textContent) {
265
+ this.emit(`// Text geometry requires THREE.FontLoader / troika-three-text`);
266
+ this.emit(`const ${v}Geom = new THREE.PlaneGeometry(2, 0.5);`);
267
+ this.emit(
268
+ `const ${v}Mat = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true });`
269
+ );
270
+ this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
271
+ this.emit(`// Text content: "${textContent || ""}"`);
272
+ this.emit(`this.scene.add(${v});`);
307
273
  } else {
308
- tag = "div";
274
+ const geomArgs = this.geometryArgs(geom, size);
275
+ const geomClass = SHAPE_TO_THREE_GEOMETRY[geom] ?? "BoxGeometry";
276
+ this.emit(`const ${v}Geom = new THREE.${geomClass}(${geomArgs});`);
277
+ const matProps = this.buildMaterialProps(mat);
278
+ this.emit(`const ${v}Mat = new THREE.MeshStandardMaterial({ ${matProps} });`);
279
+ this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
280
+ this.emit(`this.scene.add(${v});`);
309
281
  }
310
- const styles = this.buildStyles(traits);
311
- const classes = this.buildClasses(traits);
312
- let props = ``;
313
- if (traits.theme?.className) {
314
- classes.push(traits.theme.className);
282
+ if (position)
283
+ this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
284
+ if (rotation)
285
+ this.emit(`${v}.rotation.set(${rotation[0]}, ${rotation[1]}, ${rotation[2]});`);
286
+ if (scale) {
287
+ if (Array.isArray(scale)) {
288
+ this.emit(`${v}.scale.set(${scale[0]}, ${scale[1]}, ${scale[2]});`);
289
+ } else {
290
+ this.emit(`${v}.scale.setScalar(${scale});`);
291
+ }
315
292
  }
316
- if (traits.theme?.id) {
317
- props += ` id="${traits.theme.id}"`;
293
+ if (parentVar) this.emit(`${parentVar}.add(${v});`);
294
+ const physicsTraits = (obj.traits || []).filter(
295
+ (t) => t.name === "physics" || t.name === "collidable"
296
+ );
297
+ if (physicsTraits.length > 0) {
298
+ const semiring = new ProvenanceSemiring();
299
+ const applications = physicsTraits.map((t) => ({
300
+ name: t.name,
301
+ config: t.config || {},
302
+ context: obj.provenance?.context
303
+ }));
304
+ const { config: physicsConfig } = semiring.add(applications);
305
+ const isStatic = (physicsConfig.type || "dynamic") === "static";
306
+ this.emit(
307
+ `// @physics \u2014 mass: ${physicsConfig.mass ?? 1}, type: ${isStatic ? "static" : "dynamic"}`
308
+ );
309
+ this.emit(
310
+ `// Use a physics library (cannon-es, rapier, ammo.js) to attach a rigid body to ${v}`
311
+ );
318
312
  }
319
- if (Object.keys(styles).length > 0 || traits.theme?.style) {
320
- let styleStr = Object.entries(styles).map(([k, v]) => `${this.camelToKebab(k)}: ${v}`).join("; ");
321
- if (traits.theme?.style) {
322
- styleStr += (styleStr ? "; " : "") + traits.theme.style;
313
+ for (const trait of obj.traits || []) {
314
+ if (trait.name === "physics" || trait.name === "collidable") {
315
+ continue;
316
+ } else if (trait.name === "shadow") {
317
+ if (this.options.enableShadows) {
318
+ this.emit(`${v}.castShadow = true;`);
319
+ this.emit(`${v}.receiveShadow = true;`);
320
+ }
321
+ } else if (trait.name === "grabbable") {
322
+ this.emit(`// @grabbable \u2014 attach raycaster pointer-down handler to ${v}`);
323
+ } else if (trait.name === "hoverable") {
324
+ this.emit(`// @hoverable \u2014 attach raycaster pointer-move handler to ${v}`);
325
+ } else if (trait.name === "gaussian_splat") {
326
+ this.emit(
327
+ `// @gaussian_splat \u2014 use @mkkellogg/gaussian-splats-3d or three-splat for ${v}`
328
+ );
329
+ } else if (trait.name === "object_tracking") {
330
+ this.emit(`// @object_tracking \u2014 WebXR hit-test for ${v}`);
331
+ } else if (trait.name === "eye_tracked") {
332
+ this.emit(`// @eye_tracked \u2014 WebXR eye tracking for ${v}`);
333
+ } else if (trait.name === "controlnet") {
334
+ this.emit(
335
+ `// @controlnet(model: "${trait.config?.model || "canny"}") \u2014 route to inference API for ${v}`
336
+ );
337
+ } else {
338
+ this.emit(
339
+ `// @${this.escapeStringValue(trait.name, "TypeScript")}: ${JSON.stringify(trait.config || {})}`
340
+ );
323
341
  }
324
- props += ` style="${styleStr}"`;
325
- }
326
- if (classes.length > 0) {
327
- props += ` class="${classes.join(" ")}"`;
328
342
  }
329
- if (traits.theme?.attributes) {
330
- try {
331
- const parsedAttrs = JSON.parse(traits.theme.attributes);
332
- for (const [key, value] of Object.entries(parsedAttrs)) {
333
- props += ` ${key}="${value}"`;
343
+ if (obj.traits && obj.traits.length > 0) {
344
+ const traitNames = obj.traits.map((t) => t.name);
345
+ const compositor = new TraitCompositor();
346
+ const composed = compositor.compose(traitNames);
347
+ if (Object.keys(composed).length > 0) {
348
+ this.emit(`// TraitCompositor: composed ${traitNames.join(" + ")}`);
349
+ const composedProps = this.buildMaterialProps(composed);
350
+ if (composedProps) {
351
+ this.emit(
352
+ `Object.assign((${v}.material as THREE.MeshStandardMaterial), { ${composedProps} });`
353
+ );
334
354
  }
335
- } catch (e) {
336
355
  }
337
356
  }
338
- if (traits.button?.onClick) props += ` onclick="${traits.button.onClick}"`;
339
- if (traits.form?.onSubmit) props += ` onsubmit="${traits.form.onSubmit}"`;
340
- if (traits.image?.src) props += ` src="${traits.image.src}"`;
341
- if (traits.image?.alt) props += ` alt="${traits.image.alt}"`;
342
- if (traits.link?.href) props += ` href="${traits.link.href}"`;
343
- if (traits.input?.placeholder) props += ` placeholder="${traits.input.placeholder}"`;
344
- if (traits.input?.type) props += ` type="${traits.input.type}"`;
345
- if (traits.input?.required) props += ` required`;
346
- const children = node.children || node.objects || [];
347
- const childrenMarkup = children.map((child) => this.generateHTMLNode(child)).join("\n");
348
- const content = traits.text?.content || traits.button?.content || traits.link?.content || traits.icon?.name;
349
- if (tag === "img" || tag === "input") {
350
- return `<${tag}${props}>`;
351
- }
352
- return `<${tag}${props}>
353
- ${content ? content : ""}
354
- ${childrenMarkup}
355
- </${tag}>`;
356
- }
357
- // ============================================================================
358
- // UTILITIES
359
- // ============================================================================
360
- extractTraits(obj) {
361
- const map = {};
362
- const node = obj;
363
- if (!node.traits) return map;
364
- for (const t of node.traits) {
365
- map[t.name] = t.config || {};
366
- if (t.name === "tailwind" && typeof t.config === "string") {
367
- map[t.name] = { classes: t.config };
357
+ if (obj.children?.length) {
358
+ for (const child of obj.children) this.emitObject(child, v);
359
+ }
360
+ this.emit("");
361
+ }
362
+ // --- Groups ---
363
+ emitGroup(group, parentVar) {
364
+ const v = this.sanitizeName(group.name);
365
+ this.emit(
366
+ `const ${v} = new THREE.Group(); // "${this.escapeStringValue(group.name, "TypeScript")}"`
367
+ );
368
+ for (const p of group.properties) {
369
+ if (p.key === "position" && Array.isArray(p.value))
370
+ this.emit(`${v}.position.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
371
+ else if (p.key === "rotation" && Array.isArray(p.value))
372
+ this.emit(`${v}.rotation.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
373
+ else if (p.key === "scale") {
374
+ if (Array.isArray(p.value)) {
375
+ this.emit(`${v}.scale.set(${p.value[0]}, ${p.value[1]}, ${p.value[2]});`);
376
+ } else {
377
+ this.emit(`${v}.scale.setScalar(${p.value});`);
378
+ }
368
379
  }
369
380
  }
370
- return map;
371
- }
372
- mapTextVariantToTag(variant) {
373
- switch (variant) {
374
- case "h1":
375
- return "h1";
376
- case "h2":
377
- return "h2";
378
- case "h3":
379
- return "h3";
380
- case "subtitle":
381
- return "h4";
382
- case "caption":
383
- return "span";
384
- case "emoji":
385
- return "span";
386
- default:
387
- return "p";
381
+ const addTarget = parentVar ? parentVar : "this.scene";
382
+ this.emit(`${addTarget}.add(${v});`);
383
+ for (const obj of group.objects) this.emitObject(obj, v);
384
+ if (group.groups) {
385
+ for (const sub of group.groups) this.emitGroup(sub, v);
388
386
  }
387
+ this.emit("");
389
388
  }
390
- buildStyles(traits) {
391
- const styles = {};
392
- const layout = traits.layout;
393
- const theme = traits.theme;
394
- if (layout) {
395
- if (layout.flex) {
396
- styles.display = "flex";
397
- styles.flexDirection = layout.flex === "row" ? "row" : "column";
389
+ // --- Lights ---
390
+ emitLight(light) {
391
+ const v = this.sanitizeName(light.name);
392
+ let position;
393
+ let color;
394
+ let intensity;
395
+ let direction;
396
+ let castShadow = false;
397
+ let angle;
398
+ let distance;
399
+ let penumbra;
400
+ for (const p of light.properties) {
401
+ if (p.key === "position" && Array.isArray(p.value)) position = p.value;
402
+ else if (p.key === "color") color = p.value;
403
+ else if (p.key === "intensity") intensity = p.value;
404
+ else if (p.key === "direction" && Array.isArray(p.value)) direction = p.value;
405
+ else if (p.key === "cast_shadow" || p.key === "castShadow") castShadow = !!p.value;
406
+ else if (p.key === "angle") angle = p.value;
407
+ else if (p.key === "distance") distance = p.value;
408
+ else if (p.key === "penumbra") penumbra = p.value;
409
+ }
410
+ const colorHex = this.toThreeColorHex(color ?? "#ffffff");
411
+ const intStr = intensity !== void 0 ? String(intensity) : "1.0";
412
+ switch (light.lightType) {
413
+ case "hemisphere":
414
+ case "ambient":
415
+ this.emit(`const ${v} = new THREE.AmbientLight(${colorHex}, ${intStr});`);
416
+ this.emit(`this.scene.add(${v});`);
417
+ break;
418
+ case "directional": {
419
+ this.emit(`const ${v} = new THREE.DirectionalLight(${colorHex}, ${intStr});`);
420
+ const pos = position ?? direction ?? [5, 10, 5];
421
+ this.emit(`${v}.position.set(${pos[0]}, ${pos[1]}, ${pos[2]});`);
422
+ if (castShadow && this.options.enableShadows) {
423
+ this.emit(`${v}.castShadow = true;`);
424
+ this.emit(`${v}.shadow.mapSize.set(2048, 2048);`);
425
+ this.emit(`${v}.shadow.camera.near = 0.1;`);
426
+ this.emit(`${v}.shadow.camera.far = 500;`);
427
+ }
428
+ this.emit(`this.scene.add(${v});`);
429
+ break;
398
430
  }
399
- if (layout.grid) {
400
- styles.display = "grid";
401
- styles.gridTemplateColumns = `repeat(${layout.columns || 1}, minmax(0, 1fr))`;
431
+ case "point": {
432
+ const distStr = distance !== void 0 ? String(distance) : "0";
433
+ this.emit(
434
+ `const ${v} = new THREE.PointLight(${colorHex}, ${intStr}, ${distStr});`
435
+ );
436
+ if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
437
+ if (castShadow && this.options.enableShadows) this.emit(`${v}.castShadow = true;`);
438
+ this.emit(`this.scene.add(${v});`);
439
+ break;
402
440
  }
403
- if (layout.justify) styles.justifyContent = layout.justify;
404
- if (layout.align) styles.alignItems = layout.align;
405
- if (layout.gap) styles.gap = typeof layout.gap === "number" ? `${layout.gap}px` : layout.gap;
406
- if (layout.padding)
407
- styles.padding = typeof layout.padding === "number" ? `${layout.padding}px` : layout.padding;
408
- }
409
- if (theme) {
410
- if (theme.backgroundColor) styles.backgroundColor = theme.backgroundColor;
411
- if (theme.color) styles.color = theme.color;
412
- if (theme.padding)
413
- styles.padding = typeof theme.padding === "number" ? `${theme.padding}px` : theme.padding;
414
- if (theme.borderRadius)
415
- styles.borderRadius = typeof theme.borderRadius === "number" ? `${theme.borderRadius}px` : theme.borderRadius;
416
- if (theme.border) styles.border = theme.border;
417
- if (theme.borderTop) styles.borderTop = theme.borderTop;
418
- }
419
- if (traits.text) {
420
- if (traits.text.align) styles.textAlign = traits.text.align;
421
- if (traits.text.maxWidth)
422
- styles.maxWidth = typeof traits.text.maxWidth === "number" ? `${traits.text.maxWidth}px` : traits.text.maxWidth;
423
- if (traits.text.weight) styles.fontWeight = traits.text.weight;
424
- }
425
- return styles;
426
- }
427
- buildClasses(traits) {
428
- const classes = [];
429
- if (traits.text) {
430
- if (traits.text.variant === "h1") classes.push("text-5xl font-bold tracking-tight");
431
- if (traits.text.variant === "h2") classes.push("text-3xl font-bold");
432
- if (traits.text.variant === "h3") classes.push("text-xl font-semibold");
433
- if (traits.text.variant === "subtitle") classes.push("text-xl text-gray-400");
434
- if (traits.text.variant === "caption") classes.push("text-sm text-gray-500");
435
- if (traits.text.variant === "emoji") classes.push("text-2xl");
436
- }
437
- if (traits.button) {
438
- classes.push("px-4 py-2 rounded-lg font-medium transition-all");
439
- if (traits.button.variant === "primary")
440
- classes.push("bg-blue-600 hover:bg-blue-700 text-white");
441
- if (traits.button.variant === "outline")
442
- classes.push("border border-gray-600 hover:bg-gray-800 text-white");
443
- if (traits.button.variant === "ghost")
444
- classes.push("hover:bg-gray-800 text-gray-300 hover:text-white");
445
- if (traits.button.variant === "glow")
446
- classes.push("bg-indigo-600 text-white glow-btn hover:bg-indigo-500");
447
- if (traits.button.size === "lg") classes.push("px-6 py-3 text-lg");
448
- if (traits.button.size === "sm") classes.push("px-3 py-1 text-sm");
449
- }
450
- if (traits.card) {
451
- if (traits.card.shadow === "md") classes.push("shadow-md");
452
- if (traits.card.shadow === "lg") classes.push("shadow-lg");
453
- if (traits.card.hover === "glow") classes.push("lift-card");
454
- }
455
- if (traits.input) {
456
- classes.push(
457
- "px-4 py-2 rounded-lg border border-gray-700 bg-gray-900 text-white focus:ring-2 focus:ring-indigo-500 outline-none"
441
+ case "spot": {
442
+ const angleRad = angle !== void 0 ? `${angle} * Math.PI / 180` : "Math.PI / 6";
443
+ const pen = penumbra ?? 0.1;
444
+ this.emit(
445
+ `const ${v} = new THREE.SpotLight(${colorHex}, ${intStr}, ${distance ?? 0}, ${angleRad}, ${pen});`
446
+ );
447
+ if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
448
+ if (castShadow && this.options.enableShadows) this.emit(`${v}.castShadow = true;`);
449
+ this.emit(`this.scene.add(${v});`);
450
+ break;
451
+ }
452
+ default:
453
+ this.emit(`// Light "${light.lightType}" not mapped \u2014 using AmbientLight fallback`);
454
+ this.emit(`const ${v} = new THREE.AmbientLight(${colorHex}, ${intStr});`);
455
+ this.emit(`this.scene.add(${v});`);
456
+ }
457
+ this.emit("");
458
+ }
459
+ // --- Camera ---
460
+ emitCamera(camera) {
461
+ let position;
462
+ let target;
463
+ let fov;
464
+ let near;
465
+ let far;
466
+ for (const p of camera.properties) {
467
+ if (p.key === "position" && Array.isArray(p.value)) position = p.value;
468
+ else if (p.key === "target" && Array.isArray(p.value)) target = p.value;
469
+ else if (p.key === "fov") fov = p.value;
470
+ else if (p.key === "near") near = p.value;
471
+ else if (p.key === "far") far = p.value;
472
+ }
473
+ if (fov !== void 0) this.emit(`this.camera.fov = ${fov};`);
474
+ if (near !== void 0) this.emit(`this.camera.near = ${near};`);
475
+ if (far !== void 0) this.emit(`this.camera.far = ${far};`);
476
+ if (position)
477
+ this.emit(
478
+ `this.camera.position.set(${position[0]}, ${position[1]}, ${position[2]});`
479
+ );
480
+ if (target) {
481
+ this.emit(
482
+ `this.camera.lookAt(new THREE.Vector3(${target[0]}, ${target[1]}, ${target[2]}));`
458
483
  );
459
484
  }
460
- if (traits.tailwind?.classes) {
461
- classes.push(traits.tailwind.classes);
485
+ this.emit(`this.camera.updateProjectionMatrix();`);
486
+ this.emit("");
487
+ }
488
+ // --- Audio ---
489
+ emitAudio(audio) {
490
+ const v = this.sanitizeName(audio.name);
491
+ let src = "";
492
+ let loop = false;
493
+ let volume = 1;
494
+ let spatial = false;
495
+ for (const p of audio.properties) {
496
+ if (p.key === "src" || p.key === "source") src = String(p.value);
497
+ else if (p.key === "loop") loop = !!p.value;
498
+ else if (p.key === "volume") volume = p.value;
499
+ else if (p.key === "spatial") spatial = !!p.value;
500
+ }
501
+ if (spatial) {
502
+ this.emit(`const ${v}Listener = new THREE.AudioListener();`);
503
+ this.emit(`this.camera.add(${v}Listener);`);
504
+ this.emit(`const ${v} = new THREE.PositionalAudio(${v}Listener);`);
505
+ } else {
506
+ this.emit(`const ${v}Listener = new THREE.AudioListener();`);
507
+ this.emit(`this.camera.add(${v}Listener);`);
508
+ this.emit(`const ${v} = new THREE.Audio(${v}Listener);`);
462
509
  }
463
- return classes;
510
+ this.emit(`const ${v}Loader = new THREE.AudioLoader();`);
511
+ this.emit(
512
+ `${v}Loader.load("${src}", (buffer) => { ${v}.setBuffer(buffer); ${v}.setLoop(${loop}); ${v}.setVolume(${volume}); ${v}.play(); });`
513
+ );
514
+ this.emit("");
464
515
  }
465
- camelToKebab(str) {
466
- return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
516
+ // --- Zones ---
517
+ emitZone(zone) {
518
+ const v = this.sanitizeName(zone.name);
519
+ let shape = "box";
520
+ let position;
521
+ let size;
522
+ let radius;
523
+ for (const p of zone.properties) {
524
+ if (p.key === "shape") shape = String(p.value);
525
+ else if (p.key === "position" && Array.isArray(p.value)) position = p.value;
526
+ else if (p.key === "size") size = p.value;
527
+ else if (p.key === "radius") radius = p.value;
528
+ }
529
+ if (shape === "sphere") {
530
+ this.emit(
531
+ `const ${v}Geom = new THREE.SphereGeometry(${radius ?? 5}, 16, 16);`
532
+ );
533
+ } else {
534
+ const s = Array.isArray(size) ? size : [size ?? 5, size ?? 5, size ?? 5];
535
+ this.emit(`const ${v}Geom = new THREE.BoxGeometry(${s[0]}, ${s[1]}, ${s[2]});`);
536
+ }
537
+ this.emit(
538
+ `const ${v}Mat = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true, visible: false });`
539
+ );
540
+ this.emit(`const ${v} = new THREE.Mesh(${v}Geom, ${v}Mat);`);
541
+ if (position) this.emit(`${v}.position.set(${position[0]}, ${position[1]}, ${position[2]});`);
542
+ this.emit(`this.scene.add(${v}); // trigger zone (invisible)`);
543
+ if (zone.handlers?.length) {
544
+ this.emit(
545
+ `// Zone handlers: attach raycaster intersection checks for ${v}`
546
+ );
547
+ for (const h of zone.handlers) {
548
+ this.emit(
549
+ `// on ${this.escapeStringValue(h.event, "TypeScript")}: implement via raycaster.intersectObject(${v})`
550
+ );
551
+ }
552
+ }
553
+ this.emit("");
554
+ }
555
+ // --- Render Loop ---
556
+ emitRenderLoop() {
557
+ this.emit("// Render loop");
558
+ this.emit("const animate = (): void => {");
559
+ this.indent();
560
+ this.emit("this.frameId = requestAnimationFrame(animate);");
561
+ this.emit("this.renderer.render(this.scene, this.camera);");
562
+ this.dedent();
563
+ this.emit("};");
564
+ this.emit("animate();");
565
+ this.emit("");
566
+ this.emit("// Resize handler");
567
+ this.emit('window.addEventListener("resize", () => {');
568
+ this.indent();
569
+ this.emit("const w = this.canvas.clientWidth, h = this.canvas.clientHeight;");
570
+ this.emit("this.renderer.setSize(w, h);");
571
+ this.emit("this.camera.aspect = w / h;");
572
+ this.emit("this.camera.updateProjectionMatrix();");
573
+ this.dedent();
574
+ this.emit("});");
575
+ }
576
+ // --- Value Helpers ---
577
+ toThreeColorHex(value) {
578
+ if (typeof value === "string" && value.startsWith("#")) {
579
+ return `0x${value.slice(1)}`;
580
+ }
581
+ if (typeof value === "number") return `0x${value.toString(16).padStart(6, "0")}`;
582
+ return "0xffffff";
583
+ }
584
+ buildMaterialProps(mat) {
585
+ const parts = [];
586
+ if (mat.color !== void 0) {
587
+ parts.push(`color: ${this.toThreeColorHex(mat.color)}`);
588
+ }
589
+ if (mat.roughness !== void 0) parts.push(`roughness: ${mat.roughness}`);
590
+ if (mat.metalness !== void 0) parts.push(`metalness: ${mat.metalness}`);
591
+ if (mat.opacity !== void 0 && mat.opacity < 1) {
592
+ parts.push(`opacity: ${mat.opacity}`, "transparent: true");
593
+ }
594
+ if (mat.emissive !== void 0) {
595
+ parts.push(`emissive: ${this.toThreeColorHex(mat.emissive)}`);
596
+ }
597
+ if (mat.emissiveIntensity !== void 0) {
598
+ parts.push(`emissiveIntensity: ${mat.emissiveIntensity}`);
599
+ }
600
+ return parts.join(", ");
601
+ }
602
+ geometryArgs(type, size) {
603
+ const s = typeof size === "number" ? size : 1;
604
+ switch (type) {
605
+ case "sphere":
606
+ case "orb":
607
+ return `${s * 0.5}, 32, 32`;
608
+ case "cube":
609
+ case "box":
610
+ return `${s}, ${s}, ${s}`;
611
+ case "cylinder":
612
+ return `${s * 0.5}, ${s * 0.5}, ${s * 2}, 32`;
613
+ case "cone":
614
+ case "pyramid":
615
+ return `${s * 0.5}, ${s * 2}, ${type === "pyramid" ? 4 : 32}`;
616
+ case "plane":
617
+ case "ground":
618
+ return `${s}, ${s}`;
619
+ case "torus":
620
+ case "ring":
621
+ return `${s * 0.5}, ${s * 0.15}, 16, 64`;
622
+ case "capsule":
623
+ return `${s * 0.3}, ${s * 0.6}, 4, 16`;
624
+ default:
625
+ return `${s}, ${s}, ${s}`;
626
+ }
627
+ }
628
+ // --- Emit Helpers ---
629
+ emit(line) {
630
+ this.lines.push(this.options.indent.repeat(this.indentLevel) + line);
631
+ }
632
+ indent() {
633
+ this.indentLevel++;
634
+ }
635
+ dedent() {
636
+ this.indentLevel = Math.max(0, this.indentLevel - 1);
637
+ }
638
+ sanitizeName(name) {
639
+ return name.replace(/[^a-zA-Z0-9_]/g, "_");
467
640
  }
468
641
  };
469
642
  }
@@ -479,7 +652,6 @@ var A2AAgentCardCompiler, A2AAgentCardCompiler_default;
479
652
  var init_A2AAgentCardCompiler = __esm({
480
653
  "src/compiler/A2AAgentCardCompiler.ts"() {
481
654
  init_CompilerBase();
482
- init_ANSNamespace();
483
655
  A2AAgentCardCompiler = class extends CompilerBase {
484
656
  constructor(options = {}) {
485
657
  super();
@@ -633,9 +805,7 @@ var init_A2AAgentCardCompiler = __esm({
633
805
  }
634
806
  }
635
807
  if (examples.length === 0) {
636
- examples.push(
637
- `Create a ${this.escapeStringValue(template.name, "JSON")} instance`
638
- );
808
+ examples.push(`Create a ${this.escapeStringValue(template.name, "JSON")} instance`);
639
809
  }
640
810
  return {
641
811
  id: this.sanitizeId(template.name),
@@ -663,9 +833,7 @@ var init_A2AAgentCardCompiler = __esm({
663
833
  }
664
834
  const examples = [];
665
835
  if (objTraitNames.includes("sensor")) {
666
- examples.push(
667
- `Read sensor data from ${this.escapeStringValue(obj.name, "JSON")}`
668
- );
836
+ examples.push(`Read sensor data from ${this.escapeStringValue(obj.name, "JSON")}`);
669
837
  }
670
838
  if (objTraitNames.includes("networked")) {
671
839
  examples.push(
@@ -756,26 +924,10 @@ var init_A2AAgentCardCompiler = __esm({
756
924
  * Compile a domain-specific block into a specialized skill.
757
925
  */
758
926
  compileDomainBlockSkill(block) {
759
- const domainTags = {
760
- iot: ["iot", "sensor", "telemetry", "digital-twin"],
761
- robotics: ["robotics", "control", "actuator", "simulation"],
762
- dataviz: ["data-visualization", "analytics", "dashboard"],
763
- education: ["education", "learning", "curriculum"],
764
- healthcare: ["healthcare", "medical", "monitoring"],
765
- music: ["music", "audio", "composition"],
766
- architecture: ["architecture", "building", "design"],
767
- web3: ["web3", "blockchain", "smart-contract"],
768
- physics: ["physics", "simulation", "collision"],
769
- material: ["material", "rendering", "pbr"],
770
- vfx: ["vfx", "particles", "visual-effects"],
771
- weather: ["weather", "atmosphere", "environmental"],
772
- navigation: ["navigation", "pathfinding", "ai"],
773
- procedural: ["procedural", "generation", "algorithms"]
774
- };
775
927
  const tags = [
776
928
  block.domain,
777
929
  block.keyword,
778
- ...domainTags[block.domain] || [block.domain],
930
+ ...block.domainTags?.length ? block.domainTags : [],
779
931
  ...block.traits
780
932
  ];
781
933
  return {
@@ -943,9 +1095,7 @@ var init_A2AAgentCardCompiler = __esm({
943
1095
  */
944
1096
  generateDescription(composition) {
945
1097
  const parts = [];
946
- parts.push(
947
- `HoloScript agent "${this.escapeStringValue(composition.name, "JSON")}"`
948
- );
1098
+ parts.push(`HoloScript agent "${this.escapeStringValue(composition.name, "JSON")}"`);
949
1099
  const features = [];
950
1100
  if (composition.templates?.length) {
951
1101
  features.push(`${composition.templates.length} template(s)`);
@@ -1564,7 +1714,6 @@ var NIRCompiler, NIRCompiler_default;
1564
1714
  var init_NIRCompiler = __esm({
1565
1715
  "src/compiler/NIRCompiler.ts"() {
1566
1716
  init_CompilerBase();
1567
- init_ANSNamespace();
1568
1717
  init_NIRTraitMap();
1569
1718
  NIRCompiler = class extends CompilerBase {
1570
1719
  constructor(options = {}) {
@@ -1911,691 +2060,21 @@ var init_NIRCompiler = __esm({
1911
2060
  }
1912
2061
  });
1913
2062
 
1914
- // src/parser/PipelineParser.ts
1915
- function stripComments(source) {
1916
- const lines = source.split("\n");
1917
- return lines.map((line) => {
1918
- let inString = null;
1919
- for (let i = 0; i < line.length; i++) {
1920
- const ch = line[i];
1921
- if (inString) {
1922
- if (ch === inString && line[i - 1] !== "\\") inString = null;
1923
- } else if (ch === '"' || ch === "'") {
1924
- inString = ch;
1925
- } else if (ch === "/" && line[i + 1] === "/") {
1926
- return line.substring(0, i);
1927
- }
1928
- }
1929
- return line;
1930
- }).join("\n");
1931
- }
1932
- function parseDuration(value) {
1933
- const match = value.match(/^(\d+)(s|m|h|d)$/);
1934
- if (!match) return void 0;
1935
- return { value: parseInt(match[1], 10), unit: match[2] };
1936
- }
1937
- function extractBlock(source, keyword, name) {
1938
- const results = [];
1939
- const namePattern = "(\\w+)";
1940
- const regex = new RegExp(`${keyword}\\s+${namePattern}\\s*\\{`, "g");
1941
- let match;
1942
- while ((match = regex.exec(source)) !== null) {
1943
- const blockName = match[1];
1944
- const startLine = source.substring(0, match.index).split("\n").length;
1945
- const startIdx = source.indexOf("{", match.index);
1946
- let depth = 1;
1947
- let i = startIdx + 1;
1948
- while (i < source.length && depth > 0) {
1949
- if (source[i] === "{") depth++;
1950
- if (source[i] === "}") depth--;
1951
- i++;
1952
- }
1953
- results.push({
1954
- content: source.substring(startIdx + 1, i - 1),
1955
- name: blockName,
1956
- startLine
1957
- });
1958
- }
1959
- return results;
1960
- }
1961
- function parseProperties(content) {
1962
- const props = {};
1963
- const lines = content.split("\n");
1964
- for (const line of lines) {
1965
- const trimmed = line.trim();
1966
- if (!trimmed || trimmed.startsWith("//")) continue;
1967
- const kvMatch = trimmed.match(/^(\w+)\s*:\s+(.+)$/);
1968
- if (kvMatch) {
1969
- const key = kvMatch[1];
1970
- let val = kvMatch[2].trim();
1971
- if (typeof val === "string" && val.endsWith(",")) {
1972
- val = val.slice(0, -1).trim();
1973
- }
1974
- if (typeof val === "string") {
1975
- const strVal = val;
1976
- if (strVal.startsWith('"') && strVal.endsWith('"')) {
1977
- val = strVal.slice(1, -1);
1978
- } else if (strVal.startsWith("'") && strVal.endsWith("'")) {
1979
- val = strVal.slice(1, -1);
1980
- } else if (strVal === "true") {
1981
- val = true;
1982
- } else if (strVal === "false") {
1983
- val = false;
1984
- } else if (/^\d+$/.test(strVal)) {
1985
- val = parseInt(strVal, 10);
1986
- } else if (/^\d+\.\d+$/.test(strVal)) {
1987
- val = parseFloat(strVal);
1988
- }
1989
- }
1990
- props[key] = val;
1991
- }
1992
- }
1993
- return props;
1994
- }
1995
- function parseNestedBlock(content, keyword) {
1996
- const blocks = extractBlock(content, keyword);
1997
- if (blocks.length === 0) return void 0;
1998
- return parseProperties(blocks[0].content);
1999
- }
2000
- function parseFieldMappings(content) {
2001
- const mappings = [];
2002
- const lines = content.split("\n");
2003
- for (const line of lines) {
2004
- const trimmed = line.trim();
2005
- if (!trimmed || trimmed.startsWith("//")) continue;
2006
- const mapMatch = trimmed.match(/^(\w+)\s*->\s*(\w+)(?:\s*:\s*(.+))?$/);
2007
- if (mapMatch) {
2008
- const transforms = mapMatch[3] ? mapMatch[3].split(":").map((t) => t.trim()).filter(Boolean) : [];
2009
- mappings.push({
2010
- from: mapMatch[1],
2011
- to: mapMatch[2],
2012
- transforms
2013
- });
2014
- }
2015
- }
2016
- return mappings;
2017
- }
2018
- function parseValidateFields(content) {
2019
- const fields = [];
2020
- const lines = content.split("\n");
2021
- for (const line of lines) {
2022
- const trimmed = line.trim();
2023
- if (!trimmed || trimmed.startsWith("//")) continue;
2024
- const vMatch = trimmed.match(/^(\w+)\s*:\s*(.+)$/);
2025
- if (vMatch) {
2026
- const rules = vMatch[2].split(",").map((r) => r.trim()).filter(Boolean);
2027
- fields.push({ field: vMatch[1], rules });
2028
- }
2029
- }
2030
- return fields;
2031
- }
2032
- function parseBranchRoutes(content) {
2033
- const routes = [];
2034
- const lines = content.split("\n");
2035
- for (const line of lines) {
2036
- const trimmed = line.trim();
2037
- if (!trimmed || trimmed.startsWith("//")) continue;
2038
- const whenMatch = trimmed.match(/^when\s+(.+?)\s*->\s*sink\s+(\w+)$/);
2039
- if (whenMatch) {
2040
- routes.push({ condition: whenMatch[1], sinkName: whenMatch[2] });
2041
- continue;
2042
- }
2043
- const defaultMatch = trimmed.match(/^default\s*->\s*sink\s+(\w+)$/);
2044
- if (defaultMatch) {
2045
- routes.push({ condition: "default", sinkName: defaultMatch[1] });
2046
- }
2047
- }
2048
- return routes;
2049
- }
2050
- function parseStringArray(content) {
2051
- const match = content.match(/\[([\s\S]*?)\]/);
2052
- if (!match) return [];
2053
- return match[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
2054
- }
2055
- function parsePipeline(source) {
2056
- const errors = [];
2057
- const clean = stripComments(source);
2058
- const pipelineBlocks = extractBlock(clean, "pipeline");
2059
- if (pipelineBlocks.length === 0) {
2060
- const quotedMatch = clean.match(/pipeline\s+["']([^"']+)["']\s*\{/);
2061
- if (!quotedMatch) {
2062
- return { success: false, errors: [{ message: "No pipeline block found" }] };
2063
- }
2064
- const startIdx = clean.indexOf("{", quotedMatch.index);
2065
- let depth = 1;
2066
- let i = startIdx + 1;
2067
- while (i < clean.length && depth > 0) {
2068
- if (clean[i] === "{") depth++;
2069
- if (clean[i] === "}") depth--;
2070
- i++;
2071
- }
2072
- const pipelineContent = clean.substring(startIdx + 1, i - 1);
2073
- return parsePipelineContent(quotedMatch[1], pipelineContent, errors);
2074
- }
2075
- return parsePipelineContent(pipelineBlocks[0].name, pipelineBlocks[0].content, errors);
2076
- }
2077
- function parsePipelineContent(name, content, errors) {
2078
- const invalidKeywords = [
2079
- "environment",
2080
- "spatial_group",
2081
- "template",
2082
- "object",
2083
- "orb",
2084
- "theme",
2085
- "light",
2086
- "camera",
2087
- "audio",
2088
- "zone",
2089
- "timeline",
2090
- "particle_system",
2091
- "effects",
2092
- "ui",
2093
- "npc",
2094
- "quest",
2095
- "dialogue",
2096
- "ability",
2097
- "achievement",
2098
- "talent_tree",
2099
- "behavior",
2100
- "state_machine",
2101
- "shape",
2102
- "terrain",
2103
- "waypoints",
2104
- "spawn_group",
2105
- "composition",
2106
- "constraint",
2107
- "sub_orb",
2108
- "norm",
2109
- "metanorm"
2110
- ];
2111
- for (const keyword of invalidKeywords) {
2112
- if (new RegExp(`\\b${keyword}\\b`).test(content)) {
2113
- errors.push({
2114
- message: `SyntaxError: '${keyword}' is not valid in a pipeline context. Use .holo for spatial compositions or .hsplus for behaviors.`
2115
- });
2116
- }
2117
- }
2118
- const props = parseProperties(content);
2119
- const schedule = typeof props.schedule === "string" ? props.schedule : void 0;
2120
- const timeout = typeof props.timeout === "string" ? parseDuration(props.timeout) : void 0;
2121
- let retry;
2122
- const retryBlock = parseNestedBlock(content, "retry");
2123
- if (retryBlock) {
2124
- retry = {
2125
- max: typeof retryBlock.max === "number" ? retryBlock.max : 3,
2126
- backoff: retryBlock.backoff || "exponential"
2127
- };
2128
- }
2129
- const sources = [];
2130
- for (const block of extractBlock(content, "source")) {
2131
- const p = parseProperties(block.content);
2132
- sources.push({
2133
- kind: "source",
2134
- name: block.name,
2135
- type: p.type || "rest",
2136
- endpoint: p.endpoint,
2137
- path: p.path,
2138
- pattern: p.pattern,
2139
- since: p.since,
2140
- method: p.method,
2141
- auth: parseNestedBlock(block.content, "auth"),
2142
- pagination: parseNestedBlock(block.content, "pagination"),
2143
- properties: p
2144
- });
2145
- }
2146
- const transforms = [];
2147
- for (const block of extractBlock(content, "transform")) {
2148
- const p = parseProperties(block.content);
2149
- const mappings = parseFieldMappings(block.content);
2150
- const hasType = p.type !== void 0;
2151
- transforms.push({
2152
- kind: "transform",
2153
- name: block.name,
2154
- type: hasType ? p.type : mappings.length > 0 ? "field_mapping" : void 0,
2155
- mappings: mappings.length > 0 ? mappings : void 0,
2156
- model: p.model,
2157
- prompt: p.prompt,
2158
- input: p.input,
2159
- output: p.output,
2160
- server: p.server,
2161
- tool: p.tool,
2162
- method: p.method,
2163
- url: p.url,
2164
- timeout: typeof p.timeout === "string" ? parseDuration(p.timeout) : void 0,
2165
- where: p.where,
2166
- properties: p
2167
- });
2168
- }
2169
- const filters = [];
2170
- for (const block of extractBlock(content, "filter")) {
2171
- const p = parseProperties(block.content);
2172
- if (!p.where) {
2173
- errors.push({ message: `Filter "${block.name}" missing 'where' clause`, line: block.startLine, block: block.name });
2174
- }
2175
- filters.push({
2176
- kind: "filter",
2177
- name: block.name,
2178
- where: p.where || ""
2179
- });
2180
- }
2181
- const validates = [];
2182
- for (const block of extractBlock(content, "validate")) {
2183
- validates.push({
2184
- kind: "validate",
2185
- name: block.name,
2186
- fields: parseValidateFields(block.content)
2187
- });
2188
- }
2189
- const merges = [];
2190
- for (const block of extractBlock(content, "merge")) {
2191
- const p = parseProperties(block.content);
2192
- const fromArr = typeof p.from === "string" ? parseStringArray(p.from) : [];
2193
- merges.push({
2194
- kind: "merge",
2195
- name: block.name,
2196
- from: fromArr,
2197
- dedup: parseNestedBlock(block.content, "dedup"),
2198
- strategy: p.strategy
2199
- });
2200
- }
2201
- const branches = [];
2202
- for (const block of extractBlock(content, "branch")) {
2203
- branches.push({
2204
- kind: "branch",
2205
- name: block.name,
2206
- routes: parseBranchRoutes(block.content)
2207
- });
2208
- }
2209
- const sinks = [];
2210
- for (const block of extractBlock(content, "sink")) {
2211
- const p = parseProperties(block.content);
2212
- sinks.push({
2213
- kind: "sink",
2214
- name: block.name,
2215
- type: p.type || "rest",
2216
- endpoint: p.endpoint,
2217
- path: p.path,
2218
- method: p.method,
2219
- auth: parseNestedBlock(block.content, "auth"),
2220
- batch: parseNestedBlock(block.content, "batch"),
2221
- onError: parseNestedBlock(block.content, "on_error"),
2222
- format: p.format,
2223
- append: p.append,
2224
- server: p.server,
2225
- tool: p.tool,
2226
- properties: p
2227
- });
2228
- }
2229
- const steps = [
2230
- ...sources,
2231
- ...merges,
2232
- ...transforms,
2233
- ...filters,
2234
- ...validates,
2235
- ...branches,
2236
- ...sinks
2237
- ];
2238
- if (sources.length === 0) {
2239
- errors.push({ message: "Pipeline has no sources" });
2240
- }
2241
- if (sinks.length === 0) {
2242
- errors.push({ message: "Pipeline has no sinks" });
2243
- }
2244
- const pipeline = {
2245
- name,
2246
- schedule,
2247
- timeout,
2248
- retry,
2249
- steps,
2250
- sources,
2251
- transforms,
2252
- filters,
2253
- validates,
2254
- merges,
2255
- branches,
2256
- sinks
2257
- };
2258
- return { success: errors.length === 0, pipeline, errors };
2259
- }
2260
- function isPipelineSource(source) {
2261
- return /pipeline\s+["']?\w/.test(source);
2262
- }
2263
-
2264
- // src/compiler/platform/PlatformConditional.ts
2265
- var PLATFORM_CATEGORIES = {
2266
- vr: ["quest3", "pcvr", "visionos", "android-xr"],
2267
- ar: ["visionos-ar", "android-xr-ar", "webxr"],
2268
- mobile: ["ios", "android"],
2269
- desktop: ["windows", "macos", "linux", "web"],
2270
- automotive: ["android-auto", "carplay"],
2271
- wearable: ["watchos", "wearos"]
2272
- };
2273
- var ALL_PLATFORMS = Object.values(
2274
- PLATFORM_CATEGORIES
2275
- ).flat();
2276
- function platformCategory(target) {
2277
- for (const [cat, platforms] of Object.entries(PLATFORM_CATEGORIES)) {
2278
- if (platforms.includes(target)) return cat;
2279
- }
2280
- return "desktop";
2281
- }
2282
- var PLATFORM_CAPABILITIES = {
2283
- quest3: {
2284
- spatialTracking: true,
2285
- handTracking: true,
2286
- eyeTracking: true,
2287
- haptics: true,
2288
- spatialAudio: true,
2289
- gpu3D: true,
2290
- arCamera: true,
2291
- gps: false,
2292
- npu: true,
2293
- webxrSupport: true,
2294
- frameBudgetMs: 11.1,
2295
- agentBudgetMs: 5,
2296
- computeModel: "edge-first"
2297
- },
2298
- pcvr: {
2299
- spatialTracking: true,
2300
- handTracking: true,
2301
- eyeTracking: true,
2302
- haptics: true,
2303
- spatialAudio: true,
2304
- gpu3D: true,
2305
- arCamera: false,
2306
- gps: false,
2307
- npu: false,
2308
- webxrSupport: true,
2309
- frameBudgetMs: 11.1,
2310
- agentBudgetMs: 5,
2311
- computeModel: "edge-first"
2312
- },
2313
- visionos: {
2314
- spatialTracking: true,
2315
- handTracking: true,
2316
- eyeTracking: true,
2317
- haptics: false,
2318
- spatialAudio: true,
2319
- gpu3D: true,
2320
- arCamera: true,
2321
- gps: false,
2322
- npu: true,
2323
- webxrSupport: false,
2324
- frameBudgetMs: 11.1,
2325
- agentBudgetMs: 5,
2326
- computeModel: "edge-first"
2327
- },
2328
- "android-xr": {
2329
- spatialTracking: true,
2330
- handTracking: true,
2331
- eyeTracking: true,
2332
- haptics: true,
2333
- spatialAudio: true,
2334
- gpu3D: true,
2335
- arCamera: true,
2336
- gps: true,
2337
- npu: true,
2338
- webxrSupport: true,
2339
- frameBudgetMs: 11.1,
2340
- agentBudgetMs: 5,
2341
- computeModel: "edge-first"
2342
- },
2343
- "visionos-ar": {
2344
- spatialTracking: true,
2345
- handTracking: true,
2346
- eyeTracking: true,
2347
- haptics: false,
2348
- spatialAudio: true,
2349
- gpu3D: true,
2350
- arCamera: true,
2351
- gps: true,
2352
- npu: true,
2353
- webxrSupport: false,
2354
- frameBudgetMs: 16.6,
2355
- agentBudgetMs: 10,
2356
- computeModel: "edge-first"
2357
- },
2358
- "android-xr-ar": {
2359
- spatialTracking: true,
2360
- handTracking: true,
2361
- eyeTracking: false,
2362
- haptics: true,
2363
- spatialAudio: true,
2364
- gpu3D: true,
2365
- arCamera: true,
2366
- gps: true,
2367
- npu: true,
2368
- webxrSupport: true,
2369
- frameBudgetMs: 16.6,
2370
- agentBudgetMs: 10,
2371
- computeModel: "edge-first"
2372
- },
2373
- webxr: {
2374
- spatialTracking: true,
2375
- handTracking: false,
2376
- eyeTracking: false,
2377
- haptics: false,
2378
- spatialAudio: false,
2379
- gpu3D: true,
2380
- arCamera: true,
2381
- gps: false,
2382
- npu: false,
2383
- webxrSupport: true,
2384
- frameBudgetMs: 16.6,
2385
- agentBudgetMs: 15,
2386
- computeModel: "cloud-first"
2387
- },
2388
- ios: {
2389
- spatialTracking: false,
2390
- handTracking: false,
2391
- eyeTracking: false,
2392
- haptics: true,
2393
- spatialAudio: false,
2394
- gpu3D: true,
2395
- arCamera: true,
2396
- gps: true,
2397
- npu: true,
2398
- webxrSupport: false,
2399
- frameBudgetMs: 16.6,
2400
- agentBudgetMs: 100,
2401
- computeModel: "cloud-first"
2402
- },
2403
- android: {
2404
- spatialTracking: false,
2405
- handTracking: false,
2406
- eyeTracking: false,
2407
- haptics: true,
2408
- spatialAudio: false,
2409
- gpu3D: true,
2410
- arCamera: true,
2411
- gps: true,
2412
- npu: true,
2413
- webxrSupport: true,
2414
- frameBudgetMs: 16.6,
2415
- agentBudgetMs: 100,
2416
- computeModel: "cloud-first"
2417
- },
2418
- windows: {
2419
- spatialTracking: false,
2420
- handTracking: false,
2421
- eyeTracking: false,
2422
- haptics: false,
2423
- spatialAudio: false,
2424
- gpu3D: true,
2425
- arCamera: false,
2426
- gps: false,
2427
- npu: false,
2428
- webxrSupport: true,
2429
- frameBudgetMs: 16.6,
2430
- agentBudgetMs: 200,
2431
- computeModel: "cloud-first"
2432
- },
2433
- macos: {
2434
- spatialTracking: false,
2435
- handTracking: false,
2436
- eyeTracking: false,
2437
- haptics: false,
2438
- spatialAudio: false,
2439
- gpu3D: true,
2440
- arCamera: false,
2441
- gps: false,
2442
- npu: true,
2443
- webxrSupport: true,
2444
- frameBudgetMs: 16.6,
2445
- agentBudgetMs: 200,
2446
- computeModel: "cloud-first"
2447
- },
2448
- linux: {
2449
- spatialTracking: false,
2450
- handTracking: false,
2451
- eyeTracking: false,
2452
- haptics: false,
2453
- spatialAudio: false,
2454
- gpu3D: true,
2455
- arCamera: false,
2456
- gps: false,
2457
- npu: false,
2458
- webxrSupport: true,
2459
- frameBudgetMs: 16.6,
2460
- agentBudgetMs: 200,
2461
- computeModel: "cloud-first"
2462
- },
2463
- web: {
2464
- spatialTracking: false,
2465
- handTracking: false,
2466
- eyeTracking: false,
2467
- haptics: false,
2468
- spatialAudio: false,
2469
- gpu3D: true,
2470
- arCamera: false,
2471
- gps: false,
2472
- npu: false,
2473
- webxrSupport: true,
2474
- frameBudgetMs: 16.6,
2475
- agentBudgetMs: 200,
2476
- computeModel: "cloud-first"
2477
- },
2478
- "android-auto": {
2479
- spatialTracking: false,
2480
- handTracking: false,
2481
- eyeTracking: false,
2482
- haptics: false,
2483
- spatialAudio: true,
2484
- gpu3D: false,
2485
- arCamera: false,
2486
- gps: true,
2487
- npu: false,
2488
- webxrSupport: false,
2489
- frameBudgetMs: 30,
2490
- agentBudgetMs: 15,
2491
- computeModel: "safety-critical"
2492
- },
2493
- carplay: {
2494
- spatialTracking: false,
2495
- handTracking: false,
2496
- eyeTracking: false,
2497
- haptics: false,
2498
- spatialAudio: true,
2499
- gpu3D: false,
2500
- arCamera: false,
2501
- gps: true,
2502
- npu: false,
2503
- webxrSupport: false,
2504
- frameBudgetMs: 30,
2505
- agentBudgetMs: 15,
2506
- computeModel: "safety-critical"
2507
- },
2508
- watchos: {
2509
- spatialTracking: false,
2510
- handTracking: false,
2511
- eyeTracking: false,
2512
- haptics: true,
2513
- spatialAudio: false,
2514
- gpu3D: false,
2515
- arCamera: false,
2516
- gps: true,
2517
- npu: true,
2518
- webxrSupport: false,
2519
- frameBudgetMs: 33.3,
2520
- agentBudgetMs: 50,
2521
- computeModel: "cloud-first"
2522
- },
2523
- wearos: {
2524
- spatialTracking: false,
2525
- handTracking: false,
2526
- eyeTracking: false,
2527
- haptics: true,
2528
- spatialAudio: false,
2529
- gpu3D: false,
2530
- arCamera: false,
2531
- gps: true,
2532
- npu: false,
2533
- webxrSupport: false,
2534
- frameBudgetMs: 33.3,
2535
- agentBudgetMs: 50,
2536
- computeModel: "cloud-first"
2537
- }
2538
- };
2539
- var DEFAULT_EMBODIMENT = {
2540
- vr: "Avatar3D",
2541
- ar: "SpatialPersona",
2542
- mobile: "UI2D",
2543
- desktop: "FullGUI",
2544
- automotive: "VoiceHUD",
2545
- wearable: "UI2D"
2546
- };
2547
- function resolvePlatforms(condition) {
2548
- let platforms = /* @__PURE__ */ new Set();
2549
- if (condition.include) {
2550
- for (const p of condition.include) platforms.add(p);
2551
- }
2552
- if (condition.includeCategories) {
2553
- for (const cat of condition.includeCategories) {
2554
- for (const p of PLATFORM_CATEGORIES[cat]) platforms.add(p);
2555
- }
2556
- }
2557
- if (!condition.include && !condition.includeCategories) {
2558
- for (const p of ALL_PLATFORMS) platforms.add(p);
2559
- }
2560
- if (condition.exclude) {
2561
- for (const p of condition.exclude) platforms.delete(p);
2562
- }
2563
- if (condition.requireCapabilities) {
2564
- platforms = new Set(
2565
- [...platforms].filter((p) => {
2566
- const caps = PLATFORM_CAPABILITIES[p];
2567
- return condition.requireCapabilities.every((cap) => {
2568
- const val = caps[cap];
2569
- return typeof val === "boolean" ? val : Number(val) > 0;
2570
- });
2571
- })
2572
- );
2573
- }
2574
- return [...platforms];
2575
- }
2576
- function matchesPlatform(target, condition) {
2577
- return resolvePlatforms(condition).includes(target);
2578
- }
2579
- function selectBlock(target, blocks) {
2580
- for (const block of blocks) {
2581
- if (matchesPlatform(target, block.condition)) return block.body;
2582
- }
2583
- return void 0;
2584
- }
2585
- function embodimentFor(target) {
2586
- return DEFAULT_EMBODIMENT[platformCategory(target)];
2587
- }
2588
- function agentBudgetFor(target) {
2589
- return PLATFORM_CAPABILITIES[target].agentBudgetMs;
2590
- }
2591
- function hasCapability(target, cap) {
2592
- const val = PLATFORM_CAPABILITIES[target][cap];
2593
- return typeof val === "boolean" ? val : Number(val) > 0;
2594
- }
2595
-
2596
2063
  // src/compiler/USDZPipeline.ts
2597
2064
  init_DomainBlockCompilerMixin();
2598
2065
  init_R3FCompiler();
2066
+ function presetString(p, k) {
2067
+ const v = p[k];
2068
+ return typeof v === "string" ? v : void 0;
2069
+ }
2070
+ function presetNumber(p, k) {
2071
+ const v = p[k];
2072
+ return typeof v === "number" && Number.isFinite(v) ? v : void 0;
2073
+ }
2074
+ function presetBoolean(p, k) {
2075
+ const v = p[k];
2076
+ return typeof v === "boolean" ? v : void 0;
2077
+ }
2599
2078
  var _USDZPipeline = class _USDZPipeline {
2600
2079
  constructor(options = {}) {
2601
2080
  this.materials = /* @__PURE__ */ new Map();
@@ -2816,31 +2295,47 @@ ${domainBlocksOutput}` : materials,
2816
2295
  const presetName = typeof material === "string" ? material : typeof materialPreset === "string" ? materialPreset : void 0;
2817
2296
  if (presetName && MATERIAL_PRESETS[presetName]) {
2818
2297
  const preset = MATERIAL_PRESETS[presetName];
2819
- if (preset.color) mat.baseColor = this.hexToRGB(preset.color);
2820
- if (preset.metalness !== void 0) mat.metallic = preset.metalness;
2821
- if (preset.roughness !== void 0) mat.roughness = preset.roughness;
2822
- if (preset.opacity !== void 0) mat.opacity = preset.opacity;
2823
- if (preset.emissive) mat.emissiveColor = this.hexToRGB(preset.emissive);
2824
- if (preset.emissiveIntensity !== void 0)
2825
- mat.emissiveIntensity = preset.emissiveIntensity;
2826
- if (preset.transmission !== void 0) mat.transmission = preset.transmission;
2827
- if (preset.ior !== void 0) mat.ior = preset.ior;
2828
- if (preset.thickness !== void 0) mat.thickness = preset.thickness;
2829
- if (preset.clearcoat !== void 0) mat.clearcoat = preset.clearcoat;
2830
- if (preset.clearcoatRoughness !== void 0)
2831
- mat.clearcoatRoughness = preset.clearcoatRoughness;
2832
- if (preset.sheen !== void 0) mat.sheen = preset.sheen;
2833
- if (preset.sheenRoughness !== void 0) mat.sheenRoughness = preset.sheenRoughness;
2834
- if (preset.sheenColor) mat.sheenColor = this.hexToRGB(preset.sheenColor);
2835
- if (preset.iridescence !== void 0) mat.iridescence = preset.iridescence;
2836
- if (preset.iridescenceIOR !== void 0) mat.iridescenceIOR = preset.iridescenceIOR;
2837
- if (preset.anisotropy !== void 0) mat.anisotropy = preset.anisotropy;
2838
- if (preset.anisotropyRotation !== void 0)
2839
- mat.anisotropyRotation = preset.anisotropyRotation;
2840
- if (preset.attenuationColor) mat.attenuationColor = this.hexToRGB(preset.attenuationColor);
2841
- if (preset.attenuationDistance !== void 0)
2842
- mat.attenuationDistance = preset.attenuationDistance;
2843
- if (preset.transparent && mat.opacity === void 0) mat.opacity = 0.99;
2298
+ const colorStr = presetString(preset, "color");
2299
+ if (colorStr) mat.baseColor = this.hexToRGB(colorStr);
2300
+ const metal = presetNumber(preset, "metalness");
2301
+ if (metal !== void 0) mat.metallic = metal;
2302
+ const rough = presetNumber(preset, "roughness");
2303
+ if (rough !== void 0) mat.roughness = rough;
2304
+ const op = presetNumber(preset, "opacity");
2305
+ if (op !== void 0) mat.opacity = op;
2306
+ const emissiveStr = presetString(preset, "emissive");
2307
+ if (emissiveStr) mat.emissiveColor = this.hexToRGB(emissiveStr);
2308
+ const emissiveInt = presetNumber(preset, "emissiveIntensity");
2309
+ if (emissiveInt !== void 0) mat.emissiveIntensity = emissiveInt;
2310
+ const trans = presetNumber(preset, "transmission");
2311
+ if (trans !== void 0) mat.transmission = trans;
2312
+ const ior = presetNumber(preset, "ior");
2313
+ if (ior !== void 0) mat.ior = ior;
2314
+ const thick = presetNumber(preset, "thickness");
2315
+ if (thick !== void 0) mat.thickness = thick;
2316
+ const cc = presetNumber(preset, "clearcoat");
2317
+ if (cc !== void 0) mat.clearcoat = cc;
2318
+ const ccr = presetNumber(preset, "clearcoatRoughness");
2319
+ if (ccr !== void 0) mat.clearcoatRoughness = ccr;
2320
+ const sheen = presetNumber(preset, "sheen");
2321
+ if (sheen !== void 0) mat.sheen = sheen;
2322
+ const sheenR = presetNumber(preset, "sheenRoughness");
2323
+ if (sheenR !== void 0) mat.sheenRoughness = sheenR;
2324
+ const sheenColorStr = presetString(preset, "sheenColor");
2325
+ if (sheenColorStr) mat.sheenColor = this.hexToRGB(sheenColorStr);
2326
+ const irid = presetNumber(preset, "iridescence");
2327
+ if (irid !== void 0) mat.iridescence = irid;
2328
+ const iridIor = presetNumber(preset, "iridescenceIOR");
2329
+ if (iridIor !== void 0) mat.iridescenceIOR = iridIor;
2330
+ const aniso = presetNumber(preset, "anisotropy");
2331
+ if (aniso !== void 0) mat.anisotropy = aniso;
2332
+ const anisoRot = presetNumber(preset, "anisotropyRotation");
2333
+ if (anisoRot !== void 0) mat.anisotropyRotation = anisoRot;
2334
+ const attColorStr = presetString(preset, "attenuationColor");
2335
+ if (attColorStr) mat.attenuationColor = this.hexToRGB(attColorStr);
2336
+ const attDist = presetNumber(preset, "attenuationDistance");
2337
+ if (attDist !== void 0) mat.attenuationDistance = attDist;
2338
+ if (presetBoolean(preset, "transparent") && mat.opacity === void 0) mat.opacity = 0.99;
2844
2339
  }
2845
2340
  if (typeof color === "string") {
2846
2341
  mat.baseColor = this.hexToRGB(color);
@@ -3382,6 +2877,864 @@ _USDZPipeline.TEXTURE_CHANNEL_MAP = {
3382
2877
  };
3383
2878
  var USDZPipeline = _USDZPipeline;
3384
2879
 
2880
+ // src/compiler/GaussianSplattingCompiler.ts
2881
+ init_CompilerBase();
2882
+ var GAUSSIAN_SPLAT_TRAIT_NAME = "gaussian_splat";
2883
+ var MULTIPLAYER_TRAIT_NAME = "multiplayer";
2884
+ function detectMultiUserSharedSort(composition) {
2885
+ const objects = composition.objects ?? [];
2886
+ for (const obj of objects) {
2887
+ if (objectHasBothTraits(obj)) return true;
2888
+ }
2889
+ return false;
2890
+ }
2891
+ function objectHasBothTraits(obj) {
2892
+ const traits = obj.traits ?? [];
2893
+ let hasSplat = false;
2894
+ let hasMultiplayer = false;
2895
+ for (const t of traits) {
2896
+ if (t.name === GAUSSIAN_SPLAT_TRAIT_NAME) hasSplat = true;
2897
+ else if (t.name === MULTIPLAYER_TRAIT_NAME) hasMultiplayer = true;
2898
+ if (hasSplat && hasMultiplayer) return true;
2899
+ }
2900
+ const childrenLike = obj.children ?? obj.objects ?? [];
2901
+ for (const child of childrenLike) {
2902
+ if (objectHasBothTraits(child)) return true;
2903
+ }
2904
+ return false;
2905
+ }
2906
+ var SHARED_SORT_SHADER_PATH = "packages/engine/src/gpu/shaders/splat-shared-sort.wgsl";
2907
+ var GaussianSplattingCompiler = class extends CompilerBase {
2908
+ constructor(options = {}) {
2909
+ super();
2910
+ this.compilerName = "GaussianSplattingCompiler";
2911
+ this.options = {
2912
+ format: options.format ?? "glb",
2913
+ colorSpace: options.colorSpace ?? "srgb_rec709_display",
2914
+ generator: options.generator ?? "HoloScript GaussianSplattingCompiler v1.0.0",
2915
+ copyright: options.copyright ?? "",
2916
+ shDegree: options.shDegree ?? 0
2917
+ };
2918
+ }
2919
+ getRequiredCapability() {
2920
+ return ANSCapabilityPath.GLTF;
2921
+ }
2922
+ compile(composition, agentToken, outputPath) {
2923
+ this.validateCompilerAccess(agentToken, outputPath);
2924
+ const { data, warnings } = this.extractGaussianData(composition);
2925
+ const result = this.buildGLTF(data);
2926
+ if (warnings && warnings.length > 0) {
2927
+ result.warnings = warnings;
2928
+ }
2929
+ return result;
2930
+ }
2931
+ /**
2932
+ * Extended compile that runs the standard glTF export AND reports
2933
+ * compile-time WebGPU emit flags derived from trait co-occurrence.
2934
+ *
2935
+ * The standard `compile()` API is left unchanged so existing call sites
2936
+ * (MCP `compile_to_3dgs`, ExportManager) keep their contract. Callers that
2937
+ * need the shared-sort flag opt in via this method.
2938
+ *
2939
+ * @see detectMultiUserSharedSort (the detection rule)
2940
+ * @see SHARED_SORT_SHADER_PATH (the kernel artifact path)
2941
+ */
2942
+ compileExtended(composition, agentToken, outputPath) {
2943
+ const gltf = this.compile(composition, agentToken, outputPath);
2944
+ const multiUserSharedSort = detectMultiUserSharedSort(composition);
2945
+ return {
2946
+ gltf,
2947
+ multiUserSharedSort,
2948
+ sharedSortShaderPath: multiUserSharedSort ? SHARED_SORT_SHADER_PATH : void 0
2949
+ };
2950
+ }
2951
+ /**
2952
+ * Instance accessor for the multi-user shared-sort detector. Mirrors the
2953
+ * standalone `detectMultiUserSharedSort()` export — provided so callers
2954
+ * holding a compiler instance can run the check without a second import.
2955
+ */
2956
+ detectMultiUserSharedSort(composition) {
2957
+ return detectMultiUserSharedSort(composition);
2958
+ }
2959
+ // ─── Data extraction ────────────────────────────────────────────────────────
2960
+ extractGaussianData(composition) {
2961
+ for (const obj of composition.objects ?? []) {
2962
+ const trait = obj.traits?.find((t) => t.name === "gaussian_splat");
2963
+ if (trait && trait.config) {
2964
+ const p = trait.config;
2965
+ const positions = this.parseFloatArray(p.positions);
2966
+ const scales = this.parseFloatArray(p.scales);
2967
+ const rotations = this.parseFloatArray(p.rotations);
2968
+ let colors = this.parseFloatArray(p.colors);
2969
+ const opacities = this.parseFloatArray(p.opacities);
2970
+ if (positions && scales && rotations && colors && opacities) {
2971
+ const count = positions.length / 3;
2972
+ if (scales.length === count * 3 && rotations.length === count * 4 && (colors.length === count * 4 || colors.length === count * 3) && opacities.length === count) {
2973
+ if (colors.length === count * 3) {
2974
+ colors = this.expandRgbToRgba(colors, count);
2975
+ }
2976
+ return {
2977
+ data: {
2978
+ positions,
2979
+ scales,
2980
+ rotations,
2981
+ colors,
2982
+ opacities,
2983
+ shCoefficients: this.parseFloatArray(p.shCoefficients),
2984
+ count
2985
+ }
2986
+ };
2987
+ }
2988
+ }
2989
+ if (positions && colors) {
2990
+ const count = positions.length / 3;
2991
+ if (colors.length === count * 3 || colors.length === count * 4) {
2992
+ return { data: this.computeCovarianceFromPointCloud(positions, colors) };
2993
+ }
2994
+ }
2995
+ }
2996
+ }
2997
+ return {
2998
+ data: this.generateDemoGrid(),
2999
+ warnings: ["No valid @gaussian_splat trait data found; falling back to demo grid"]
3000
+ };
3001
+ }
3002
+ expandRgbToRgba(rgb, count) {
3003
+ const rgba = new Float32Array(count * 4);
3004
+ for (let i = 0; i < count; i++) {
3005
+ rgba[i * 4] = rgb[i * 3];
3006
+ rgba[i * 4 + 1] = rgb[i * 3 + 1];
3007
+ rgba[i * 4 + 2] = rgb[i * 3 + 2];
3008
+ rgba[i * 4 + 3] = 1;
3009
+ }
3010
+ return rgba;
3011
+ }
3012
+ parseFloatArray(value) {
3013
+ if (value instanceof Float32Array) return value;
3014
+ if (Array.isArray(value)) {
3015
+ const nums = value.map((v) => typeof v === "number" ? v : Number(v));
3016
+ return new Float32Array(nums);
3017
+ }
3018
+ return void 0;
3019
+ }
3020
+ // ─── Covariance from point cloud (HoloMap raw output) ───────────────────────
3021
+ /**
3022
+ * Compute per-point Gaussian parameters from a raw point cloud.
3023
+ *
3024
+ * For each point we find k nearest neighbours, compute the 3x3 covariance
3025
+ * matrix of that neighbourhood, eigen-decompose it via Jacobi rotations,
3026
+ * and derive:
3027
+ * - scales = sqrt(eigenvalues) (isotropic minimum clamp)
3028
+ * - rotation = quaternion from eigenvector basis
3029
+ * - opacity = 1.0 (uniform)
3030
+ * - colors = passed through (RGB expanded to RGBA if needed)
3031
+ */
3032
+ computeCovarianceFromPointCloud(positions, colors) {
3033
+ const n = Math.floor(positions.length / 3);
3034
+ const k = Math.min(12, Math.max(4, n - 1));
3035
+ const scales = new Float32Array(n * 3);
3036
+ const rotations = new Float32Array(n * 4);
3037
+ const opacities = new Float32Array(n);
3038
+ let rgbaColors;
3039
+ if (colors.length === n * 3) {
3040
+ rgbaColors = this.expandRgbToRgba(colors, n);
3041
+ } else {
3042
+ rgbaColors = colors;
3043
+ }
3044
+ const grid = this.buildSpatialGrid(positions, n);
3045
+ for (let i = 0; i < n; i++) {
3046
+ const px = positions[i * 3];
3047
+ const py = positions[i * 3 + 1];
3048
+ const pz = positions[i * 3 + 2];
3049
+ const neighbours = this.findKNearestNeighbours(grid, positions, n, px, py, pz, k, i);
3050
+ let meanX = 0, meanY = 0, meanZ = 0;
3051
+ for (const idx of neighbours) {
3052
+ meanX += positions[idx * 3];
3053
+ meanY += positions[idx * 3 + 1];
3054
+ meanZ += positions[idx * 3 + 2];
3055
+ }
3056
+ const invM = 1 / neighbours.length;
3057
+ meanX *= invM;
3058
+ meanY *= invM;
3059
+ meanZ *= invM;
3060
+ let c00 = 0, c01 = 0, c02 = 0, c11 = 0, c12 = 0, c22 = 0;
3061
+ for (const idx of neighbours) {
3062
+ const dx = positions[idx * 3] - meanX;
3063
+ const dy = positions[idx * 3 + 1] - meanY;
3064
+ const dz = positions[idx * 3 + 2] - meanZ;
3065
+ c00 += dx * dx;
3066
+ c01 += dx * dy;
3067
+ c02 += dx * dz;
3068
+ c11 += dy * dy;
3069
+ c12 += dy * dz;
3070
+ c22 += dz * dz;
3071
+ }
3072
+ const invLen = 1 / (neighbours.length - 1 || 1);
3073
+ c00 *= invLen;
3074
+ c01 *= invLen;
3075
+ c02 *= invLen;
3076
+ c11 *= invLen;
3077
+ c12 *= invLen;
3078
+ c22 *= invLen;
3079
+ const ev = this.jacobiEigenvalues3([
3080
+ c00,
3081
+ c01,
3082
+ c02,
3083
+ c01,
3084
+ c11,
3085
+ c12,
3086
+ c02,
3087
+ c12,
3088
+ c22
3089
+ ]);
3090
+ const minScale = 1e-3;
3091
+ scales[i * 3] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[0])));
3092
+ scales[i * 3 + 1] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[1])));
3093
+ scales[i * 3 + 2] = Math.max(minScale, Math.sqrt(Math.abs(ev.values[2])));
3094
+ const q = this.rotationMatrixToQuaternion(ev.vectors);
3095
+ rotations[i * 4] = q[0];
3096
+ rotations[i * 4 + 1] = q[1];
3097
+ rotations[i * 4 + 2] = q[2];
3098
+ rotations[i * 4 + 3] = q[3];
3099
+ opacities[i] = 1;
3100
+ }
3101
+ return {
3102
+ positions,
3103
+ scales,
3104
+ rotations,
3105
+ colors: rgbaColors,
3106
+ opacities,
3107
+ count: n
3108
+ };
3109
+ }
3110
+ /** Simple uniform-grid spatial hash for k-NN acceleration. */
3111
+ buildSpatialGrid(positions, n) {
3112
+ let minX = Infinity, minY = Infinity, minZ = Infinity;
3113
+ let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
3114
+ for (let i = 0; i < n; i++) {
3115
+ const x = positions[i * 3];
3116
+ const y = positions[i * 3 + 1];
3117
+ const z = positions[i * 3 + 2];
3118
+ if (x < minX) minX = x;
3119
+ if (y < minY) minY = y;
3120
+ if (z < minZ) minZ = z;
3121
+ if (x > maxX) maxX = x;
3122
+ if (y > maxY) maxY = y;
3123
+ if (z > maxZ) maxZ = z;
3124
+ }
3125
+ const extent = Math.max(maxX - minX, maxY - minY, maxZ - minZ, 1e-6);
3126
+ const cellsPerAxis = Math.max(1, Math.round(Math.pow(n / 8, 1 / 3)));
3127
+ const cellSize = extent / cellsPerAxis;
3128
+ const grid = /* @__PURE__ */ new Map();
3129
+ for (let i = 0; i < n; i++) {
3130
+ const cx = Math.floor((positions[i * 3] - minX) / cellSize);
3131
+ const cy = Math.floor((positions[i * 3 + 1] - minY) / cellSize);
3132
+ const cz = Math.floor((positions[i * 3 + 2] - minZ) / cellSize);
3133
+ const key = `${cx},${cy},${cz}`;
3134
+ const arr = grid.get(key);
3135
+ if (arr) {
3136
+ arr.push(i);
3137
+ } else {
3138
+ grid.set(key, [i]);
3139
+ }
3140
+ }
3141
+ return grid;
3142
+ }
3143
+ findKNearestNeighbours(grid, positions, n, px, py, pz, k, selfIdx) {
3144
+ if (n <= 2048) {
3145
+ const dists = [];
3146
+ for (let i = 0; i < n; i++) {
3147
+ const dx = positions[i * 3] - px;
3148
+ const dy = positions[i * 3 + 1] - py;
3149
+ const dz = positions[i * 3 + 2] - pz;
3150
+ dists.push({ idx: i, d2: dx * dx + dy * dy + dz * dz });
3151
+ }
3152
+ dists.sort((a, b) => a.d2 - b.d2);
3153
+ return dists.slice(0, k + 1).map((d) => d.idx);
3154
+ }
3155
+ const radius = this.estimateSearchRadius(positions, n);
3156
+ const radius2 = radius * radius;
3157
+ const candidates = [];
3158
+ for (let i = 0; i < n; i++) {
3159
+ const dx = positions[i * 3] - px;
3160
+ const dy = positions[i * 3 + 1] - py;
3161
+ const dz = positions[i * 3 + 2] - pz;
3162
+ const d2 = dx * dx + dy * dy + dz * dz;
3163
+ if (d2 <= radius2) {
3164
+ candidates.push({ idx: i, d2 });
3165
+ }
3166
+ }
3167
+ candidates.sort((a, b) => a.d2 - b.d2);
3168
+ return candidates.slice(0, k + 1).map((c) => c.idx);
3169
+ }
3170
+ estimateSearchRadius(positions, n) {
3171
+ const sampleCount = Math.min(256, n);
3172
+ let totalDist = 0;
3173
+ let counted = 0;
3174
+ const step = Math.max(1, Math.floor(n / sampleCount));
3175
+ for (let i = 0; i < n; i += step) {
3176
+ let minD2 = Infinity;
3177
+ const px = positions[i * 3];
3178
+ const py = positions[i * 3 + 1];
3179
+ const pz = positions[i * 3 + 2];
3180
+ for (let j = 0; j < n; j++) {
3181
+ if (i === j) continue;
3182
+ const dx = positions[j * 3] - px;
3183
+ const dy = positions[j * 3 + 1] - py;
3184
+ const dz = positions[j * 3 + 2] - pz;
3185
+ const d2 = dx * dx + dy * dy + dz * dz;
3186
+ if (d2 < minD2) minD2 = d2;
3187
+ }
3188
+ if (minD2 < Infinity) {
3189
+ totalDist += Math.sqrt(minD2);
3190
+ counted++;
3191
+ }
3192
+ }
3193
+ const avg = counted > 0 ? totalDist / counted : 0.1;
3194
+ return avg * 3;
3195
+ }
3196
+ /** Jacobi eigenvalue decomposition for a 3x3 symmetric matrix.
3197
+ * Returns eigenvalues (descending) and eigenvectors as column-major 3x3.
3198
+ */
3199
+ jacobiEigenvalues3(a) {
3200
+ let m = [
3201
+ [a[0], a[1], a[2]],
3202
+ [a[3], a[4], a[5]],
3203
+ [a[6], a[7], a[8]]
3204
+ ];
3205
+ let v = [
3206
+ [1, 0, 0],
3207
+ [0, 1, 0],
3208
+ [0, 0, 1]
3209
+ ];
3210
+ const eps = 1e-10;
3211
+ const maxSweeps = 50;
3212
+ for (let sweep = 0; sweep < maxSweeps; sweep++) {
3213
+ let offDiagSum = 0;
3214
+ for (let p = 0; p < 3; p++) {
3215
+ for (let q = p + 1; q < 3; q++) {
3216
+ offDiagSum += Math.abs(m[p][q]);
3217
+ if (Math.abs(m[p][q]) < eps) continue;
3218
+ const tau = (m[q][q] - m[p][p]) / (2 * m[p][q]);
3219
+ let t;
3220
+ if (tau >= 0) {
3221
+ t = 1 / (tau + Math.sqrt(1 + tau * tau));
3222
+ } else {
3223
+ t = 1 / (tau - Math.sqrt(1 + tau * tau));
3224
+ }
3225
+ const c = 1 / Math.sqrt(1 + t * t);
3226
+ const s = t * c;
3227
+ const mpp = m[p][p];
3228
+ const mqq = m[q][q];
3229
+ const mpq = m[p][q];
3230
+ m[p][p] = c * c * mpp - 2 * s * c * mpq + s * s * mqq;
3231
+ m[q][q] = s * s * mpp + 2 * s * c * mpq + c * c * mqq;
3232
+ m[p][q] = 0;
3233
+ m[q][p] = 0;
3234
+ for (let r = 0; r < 3; r++) {
3235
+ if (r !== p && r !== q) {
3236
+ const mr_p = m[r][p];
3237
+ const mr_q = m[r][q];
3238
+ m[r][p] = c * mr_p - s * mr_q;
3239
+ m[p][r] = m[r][p];
3240
+ m[r][q] = s * mr_p + c * mr_q;
3241
+ m[q][r] = m[r][q];
3242
+ }
3243
+ }
3244
+ for (let r = 0; r < 3; r++) {
3245
+ const vr_p = v[r][p];
3246
+ const vr_q = v[r][q];
3247
+ v[r][p] = c * vr_p - s * vr_q;
3248
+ v[r][q] = s * vr_p + c * vr_q;
3249
+ }
3250
+ }
3251
+ }
3252
+ if (offDiagSum < eps) break;
3253
+ }
3254
+ const vals = [m[0][0], m[1][1], m[2][2]];
3255
+ const cols = [
3256
+ [v[0][0], v[1][0], v[2][0]],
3257
+ [v[0][1], v[1][1], v[2][1]],
3258
+ [v[0][2], v[1][2], v[2][2]]
3259
+ ];
3260
+ const order = [0, 1, 2].sort((i, j) => vals[j] - vals[i]);
3261
+ return {
3262
+ values: [vals[order[0]], vals[order[1]], vals[order[2]]],
3263
+ vectors: [
3264
+ cols[order[0]][0],
3265
+ cols[order[1]][0],
3266
+ cols[order[2]][0],
3267
+ cols[order[0]][1],
3268
+ cols[order[1]][1],
3269
+ cols[order[2]][1],
3270
+ cols[order[0]][2],
3271
+ cols[order[1]][2],
3272
+ cols[order[2]][2]
3273
+ ]
3274
+ };
3275
+ }
3276
+ rotationMatrixToQuaternion(m) {
3277
+ const trace = m[0] + m[4] + m[8];
3278
+ let qw, qx, qy, qz;
3279
+ if (trace > 0) {
3280
+ const s = 0.5 / Math.sqrt(trace + 1);
3281
+ qw = 0.25 / s;
3282
+ qx = (m[5] - m[7]) * s;
3283
+ qy = (m[6] - m[2]) * s;
3284
+ qz = (m[1] - m[3]) * s;
3285
+ } else if (m[0] > m[4] && m[0] > m[8]) {
3286
+ const s = 2 * Math.sqrt(1 + m[0] - m[4] - m[8]);
3287
+ qw = (m[5] - m[7]) / s;
3288
+ qx = 0.25 * s;
3289
+ qy = (m[3] + m[1]) / s;
3290
+ qz = (m[6] + m[2]) / s;
3291
+ } else if (m[4] > m[8]) {
3292
+ const s = 2 * Math.sqrt(1 + m[4] - m[0] - m[8]);
3293
+ qw = (m[6] - m[2]) / s;
3294
+ qx = (m[3] + m[1]) / s;
3295
+ qy = 0.25 * s;
3296
+ qz = (m[7] + m[5]) / s;
3297
+ } else {
3298
+ const s = 2 * Math.sqrt(1 + m[8] - m[0] - m[4]);
3299
+ qw = (m[1] - m[3]) / s;
3300
+ qx = (m[6] + m[2]) / s;
3301
+ qy = (m[7] + m[5]) / s;
3302
+ qz = 0.25 * s;
3303
+ }
3304
+ const norm = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw) || 1;
3305
+ return [qx / norm, qy / norm, qz / norm, qw / norm];
3306
+ }
3307
+ generateDemoGrid() {
3308
+ const count = 8;
3309
+ const positions = new Float32Array(count * 3);
3310
+ const scales = new Float32Array(count * 3);
3311
+ const rotations = new Float32Array(count * 4);
3312
+ const colors = new Float32Array(count * 4);
3313
+ const opacities = new Float32Array(count);
3314
+ let i = 0;
3315
+ for (let x = 0; x < 2; x++) {
3316
+ for (let y = 0; y < 2; y++) {
3317
+ for (let z = 0; z < 2; z++) {
3318
+ positions[i * 3] = x * 0.5;
3319
+ positions[i * 3 + 1] = y * 0.5;
3320
+ positions[i * 3 + 2] = z * 0.5;
3321
+ scales[i * 3] = 0.1;
3322
+ scales[i * 3 + 1] = 0.1;
3323
+ scales[i * 3 + 2] = 0.1;
3324
+ rotations[i * 4] = 0;
3325
+ rotations[i * 4 + 1] = 0;
3326
+ rotations[i * 4 + 2] = 0;
3327
+ rotations[i * 4 + 3] = 1;
3328
+ colors[i * 4] = 0.8;
3329
+ colors[i * 4 + 1] = 0.3;
3330
+ colors[i * 4 + 2] = 0.3;
3331
+ colors[i * 4 + 3] = 1;
3332
+ opacities[i] = 1;
3333
+ i++;
3334
+ }
3335
+ }
3336
+ }
3337
+ return { positions, scales, rotations, colors, opacities, count };
3338
+ }
3339
+ // ─── glTF builder ─────────────────────────────────────────────────────────
3340
+ buildGLTF(data) {
3341
+ const N = data.count;
3342
+ const bufferData = this.buildBuffer(data);
3343
+ const bufferViews = this.buildBufferViews(N);
3344
+ const accessors = this.buildAccessors(N);
3345
+ const primitive = {
3346
+ attributes: {
3347
+ POSITION: 0,
3348
+ _ROTATION: 1,
3349
+ _SCALE: 2,
3350
+ _OPACITY: 3,
3351
+ COLOR_0: 4
3352
+ },
3353
+ mode: 0,
3354
+ // POINTS
3355
+ extensions: {
3356
+ KHR_gaussian_splatting: {
3357
+ colorSpace: this.options.colorSpace
3358
+ }
3359
+ }
3360
+ };
3361
+ const mesh = {
3362
+ name: "GaussianSplatMesh",
3363
+ primitives: [primitive]
3364
+ };
3365
+ const node = {
3366
+ name: "GaussianSplatNode",
3367
+ mesh: 0
3368
+ };
3369
+ const gltf = {
3370
+ asset: {
3371
+ version: "2.0",
3372
+ generator: this.options.generator,
3373
+ ...this.options.copyright ? { copyright: this.options.copyright } : {}
3374
+ },
3375
+ scene: 0,
3376
+ scenes: [{ name: "Scene", nodes: [0] }],
3377
+ nodes: [node],
3378
+ meshes: [mesh],
3379
+ accessors,
3380
+ bufferViews,
3381
+ buffers: [{ byteLength: bufferData.byteLength }],
3382
+ extensionsUsed: ["KHR_gaussian_splatting"]
3383
+ };
3384
+ const stats = {
3385
+ nodeCount: 1,
3386
+ meshCount: 1,
3387
+ materialCount: 0,
3388
+ textureCount: 0,
3389
+ animationCount: 0,
3390
+ totalVertices: N,
3391
+ totalTriangles: 0,
3392
+ fileSizeBytes: 0
3393
+ };
3394
+ if (this.options.format === "glb") {
3395
+ const binary = this.createGLB(gltf, bufferData);
3396
+ stats.fileSizeBytes = binary.byteLength;
3397
+ return { binary, stats };
3398
+ }
3399
+ stats.fileSizeBytes = JSON.stringify(gltf).length + bufferData.byteLength;
3400
+ return { json: gltf, buffer: bufferData, stats };
3401
+ }
3402
+ // ─── Binary layout ──────────────────────────────────────────────────────────
3403
+ buildBuffer(data) {
3404
+ const N = data.count;
3405
+ const logScales = new Float32Array(N * 3);
3406
+ for (let i = 0; i < N * 3; i++) {
3407
+ logScales[i] = Math.log(Math.max(data.scales[i], 1e-8));
3408
+ }
3409
+ const size = N * 3 * 4 + N * 4 * 4 + N * 3 * 4 + N * 4 + N * 4 * 4;
3410
+ const buf = new Uint8Array(size);
3411
+ let off = 0;
3412
+ const write = (arr) => {
3413
+ const view = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
3414
+ buf.set(view, off);
3415
+ off += arr.byteLength;
3416
+ };
3417
+ write(data.positions);
3418
+ write(data.rotations);
3419
+ write(logScales);
3420
+ write(data.opacities);
3421
+ write(data.colors);
3422
+ return buf;
3423
+ }
3424
+ buildBufferViews(N) {
3425
+ let off = 0;
3426
+ const views = [];
3427
+ const add = (len) => {
3428
+ views.push({ buffer: 0, byteOffset: off, byteLength: len });
3429
+ off += len;
3430
+ return views.length - 1;
3431
+ };
3432
+ add(N * 3 * 4);
3433
+ add(N * 4 * 4);
3434
+ add(N * 3 * 4);
3435
+ add(N * 4);
3436
+ add(N * 4 * 4);
3437
+ return views;
3438
+ }
3439
+ buildAccessors(N) {
3440
+ let bv = 0;
3441
+ const accs = [];
3442
+ const add = (type, compType, count) => {
3443
+ accs.push({ bufferView: bv++, componentType: compType, count, type });
3444
+ };
3445
+ add("VEC3", 5126, N);
3446
+ add("VEC4", 5126, N);
3447
+ add("VEC3", 5126, N);
3448
+ add("SCALAR", 5126, N);
3449
+ add("VEC4", 5126, N);
3450
+ return accs;
3451
+ }
3452
+ // ─── GLB assembler (mirrors GLTFPipeline) ─────────────────────────────────
3453
+ createGLB(gltf, buffer) {
3454
+ const jsonString = JSON.stringify(gltf);
3455
+ const jsonBuffer = new TextEncoder().encode(jsonString);
3456
+ const jsonPadding = (4 - jsonBuffer.byteLength % 4) % 4;
3457
+ const paddedJsonLength = jsonBuffer.byteLength + jsonPadding;
3458
+ const binPadding = (4 - buffer.byteLength % 4) % 4;
3459
+ const paddedBinLength = buffer.byteLength + binPadding;
3460
+ const totalSize = 12 + 8 + paddedJsonLength + 8 + paddedBinLength;
3461
+ const output = new ArrayBuffer(totalSize);
3462
+ const view = new DataView(output);
3463
+ const bytes = new Uint8Array(output);
3464
+ let offset = 0;
3465
+ view.setUint32(offset, 1179937895, true);
3466
+ offset += 4;
3467
+ view.setUint32(offset, 2, true);
3468
+ offset += 4;
3469
+ view.setUint32(offset, totalSize, true);
3470
+ offset += 4;
3471
+ view.setUint32(offset, paddedJsonLength, true);
3472
+ offset += 4;
3473
+ view.setUint32(offset, 1313821514, true);
3474
+ offset += 4;
3475
+ bytes.set(jsonBuffer, offset);
3476
+ offset += jsonBuffer.byteLength;
3477
+ for (let i = 0; i < jsonPadding; i++) bytes[offset++] = 32;
3478
+ view.setUint32(offset, paddedBinLength, true);
3479
+ offset += 4;
3480
+ view.setUint32(offset, 5130562, true);
3481
+ offset += 4;
3482
+ bytes.set(buffer, offset);
3483
+ offset += buffer.byteLength;
3484
+ for (let i = 0; i < binPadding; i++) bytes[offset++] = 0;
3485
+ return new Uint8Array(output);
3486
+ }
3487
+ };
3488
+ function createGaussianSplattingCompiler(options) {
3489
+ return new GaussianSplattingCompiler(options);
3490
+ }
3491
+
3492
+ // src/compiler/SpatialPartitionPass.ts
3493
+ var MAX_DEPTH = 8;
3494
+ var SCALE_PER_SPLAT_UNIT = 1e-6;
3495
+ var MIN_SCALE = 1e-9;
3496
+ var SpatialPartitionPass = class {
3497
+ constructor(options = {}) {
3498
+ this.maxDepth = options.maxDepth ?? MAX_DEPTH;
3499
+ this.scalePerSplatUnit = options.scalePerSplatUnit ?? SCALE_PER_SPLAT_UNIT;
3500
+ this.includeUnpositioned = options.includeUnpositioned ?? true;
3501
+ }
3502
+ /**
3503
+ * Run the pass over a HoloComposition and return the serializable result.
3504
+ */
3505
+ run(composition) {
3506
+ const rawSources = [];
3507
+ this.collectFromComposition(composition, rawSources);
3508
+ if (rawSources.length === 0) {
3509
+ return this.emptyResult(composition.name);
3510
+ }
3511
+ const maxScaleInScene = Math.max(
3512
+ ...rawSources.map((s) => Math.max(s.maxSplats * this.scalePerSplatUnit, MIN_SCALE))
3513
+ );
3514
+ const anchors = [];
3515
+ const lodDist = {};
3516
+ let objectsWalked = 0;
3517
+ for (const src of rawSources) {
3518
+ objectsWalked++;
3519
+ if (!this.includeUnpositioned && !src.hasPosition) continue;
3520
+ const scale = Math.max(src.maxSplats * this.scalePerSplatUnit, MIN_SCALE);
3521
+ const lodLevel = this.computeLODLevel(scale, maxScaleInScene);
3522
+ const provenanceHash = src.sourceFile ? deterministicHash(`file:${src.sourceFile}:${src.maxSplats}`) : deterministicHash(`${src.objectName}:${lodLevel}:${src.maxSplats}`);
3523
+ const anchor = {
3524
+ id: `spa_${sanitiseId(src.objectName)}_l${lodLevel}`,
3525
+ position: src.position,
3526
+ scale,
3527
+ lodLevel,
3528
+ gaussianCount: src.maxSplats,
3529
+ importance: src.importance,
3530
+ provenanceHash,
3531
+ ...src.sourceFile ? { sourceFile: src.sourceFile } : {}
3532
+ };
3533
+ anchors.push(anchor);
3534
+ lodDist[lodLevel] = (lodDist[lodLevel] ?? 0) + 1;
3535
+ }
3536
+ anchors.sort((a, b) => a.lodLevel - b.lodLevel);
3537
+ const bounds = computeBounds(anchors);
3538
+ const merkleRoot = computeMerkleRoot(anchors);
3539
+ const totalGaussians = anchors.reduce((s, a) => s + a.gaussianCount, 0);
3540
+ const maxLodLevel = anchors.length > 0 ? Math.max(...anchors.map((a) => a.lodLevel)) : 0;
3541
+ return {
3542
+ schema: "spatial-partition/v1",
3543
+ compositionName: composition.name,
3544
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3545
+ anchors,
3546
+ bounds,
3547
+ merkleRoot,
3548
+ totalGaussians,
3549
+ stats: {
3550
+ objectsWalked,
3551
+ anchorsEmitted: anchors.length,
3552
+ lodLevelDistribution: lodDist,
3553
+ maxLodLevel,
3554
+ maxScaleInScene
3555
+ }
3556
+ };
3557
+ }
3558
+ // ── LOD level computation (same algorithm as OctreeLODSystem.computeLODLevelFromScale) ──
3559
+ computeLODLevel(scale, maxScaleInScene) {
3560
+ if (scale <= 0 || maxScaleInScene <= 0) return this.maxDepth - 1;
3561
+ if (scale >= maxScaleInScene) return 0;
3562
+ const ratio = maxScaleInScene / scale;
3563
+ const level = Math.floor(Math.log2(ratio));
3564
+ return Math.min(Math.max(0, level), this.maxDepth - 1);
3565
+ }
3566
+ // ── AST Walk (mirrors GaussianBudgetAnalyzer.collectGaussianSources) ─────────
3567
+ collectFromComposition(composition, out) {
3568
+ if (composition.objects) {
3569
+ for (const obj of composition.objects) {
3570
+ this.collectFromObject(obj, out);
3571
+ }
3572
+ }
3573
+ if (composition.spatialGroups) {
3574
+ for (const group of composition.spatialGroups) {
3575
+ this.collectFromGroup(group, out);
3576
+ }
3577
+ }
3578
+ if (composition.conditionals) {
3579
+ for (const cond of composition.conditionals) {
3580
+ if (cond.objects) {
3581
+ for (const obj of cond.objects) this.collectFromObject(obj, out);
3582
+ }
3583
+ if (cond.elseObjects) {
3584
+ for (const obj of cond.elseObjects) this.collectFromObject(obj, out);
3585
+ }
3586
+ }
3587
+ }
3588
+ if (composition.iterators) {
3589
+ for (const iter of composition.iterators) {
3590
+ if (iter.objects) {
3591
+ for (const obj of iter.objects) this.collectFromObject(obj, out);
3592
+ }
3593
+ }
3594
+ }
3595
+ }
3596
+ collectFromObject(obj, out) {
3597
+ if (obj.traits) {
3598
+ for (const trait of obj.traits) {
3599
+ if (trait.name === "gaussian_splat") {
3600
+ const src = this.extractSource(obj, trait);
3601
+ if (src) out.push(src);
3602
+ }
3603
+ }
3604
+ }
3605
+ if (obj.children) {
3606
+ for (const child of obj.children) {
3607
+ this.collectFromObject(child, out);
3608
+ }
3609
+ }
3610
+ }
3611
+ collectFromGroup(group, out) {
3612
+ if (group.objects) {
3613
+ for (const obj of group.objects) this.collectFromObject(obj, out);
3614
+ }
3615
+ if (group.groups) {
3616
+ for (const sub of group.groups) this.collectFromGroup(sub, out);
3617
+ }
3618
+ }
3619
+ extractSource(obj, trait) {
3620
+ const config = trait.config ?? {};
3621
+ const maxSplats = typeof config.max_splats === "number" ? config.max_splats : 5e4;
3622
+ const sourceFile = typeof config.src === "string" ? config.src : typeof config.source === "string" ? config.source : void 0;
3623
+ const importance = typeof config.importance === "number" ? Math.max(0, Math.min(1, config.importance)) : 0.5;
3624
+ let posArr = null;
3625
+ if (obj.position && typeof obj.position.x === "number") {
3626
+ posArr = [obj.position.x, obj.position.y, obj.position.z];
3627
+ } else {
3628
+ const posProp = obj.properties?.find((p) => p.key === "position")?.value;
3629
+ if (Array.isArray(posProp) && posProp.length >= 3) {
3630
+ posArr = [Number(posProp[0]), Number(posProp[1]), Number(posProp[2])];
3631
+ } else if (posProp !== null && typeof posProp === "object" && !Array.isArray(posProp) && typeof posProp["x"] === "number") {
3632
+ const pobj = posProp;
3633
+ posArr = [pobj.x, pobj.y, pobj.z];
3634
+ }
3635
+ }
3636
+ return {
3637
+ objectName: obj.name ?? `unnamed_${Math.random().toString(36).slice(2, 7)}`,
3638
+ position: posArr ?? [0, 0, 0],
3639
+ hasPosition: posArr !== null,
3640
+ maxSplats,
3641
+ sourceFile,
3642
+ importance
3643
+ };
3644
+ }
3645
+ // ── Empty-composition fast path ─────────────────────────────────────────────
3646
+ emptyResult(compositionName) {
3647
+ return {
3648
+ schema: "spatial-partition/v1",
3649
+ compositionName,
3650
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3651
+ anchors: [],
3652
+ bounds: {
3653
+ min: { x: 0, y: 0, z: 0 },
3654
+ max: { x: 0, y: 0, z: 0 },
3655
+ center: { x: 0, y: 0, z: 0 },
3656
+ halfSize: 0
3657
+ },
3658
+ merkleRoot: "0".repeat(64),
3659
+ totalGaussians: 0,
3660
+ stats: {
3661
+ objectsWalked: 0,
3662
+ anchorsEmitted: 0,
3663
+ lodLevelDistribution: {},
3664
+ maxLodLevel: 0,
3665
+ maxScaleInScene: 0
3666
+ }
3667
+ };
3668
+ }
3669
+ };
3670
+ function deterministicHash(input) {
3671
+ let h0 = 2166136261;
3672
+ let h1 = 3521423859;
3673
+ for (let i = 0; i < input.length; i++) {
3674
+ const c = input.charCodeAt(i);
3675
+ h0 = Math.imul(h0 ^ c, 16777619) >>> 0;
3676
+ h1 = Math.imul(h1 ^ c, 16777619) >>> 0;
3677
+ }
3678
+ const hex0 = h0.toString(16).padStart(8, "0");
3679
+ const hex1 = h1.toString(16).padStart(8, "0");
3680
+ const base = (hex0 + hex1).repeat(4).slice(0, 64);
3681
+ return base;
3682
+ }
3683
+ function computeMerkleRoot(anchors) {
3684
+ if (anchors.length === 0) return "0".repeat(64);
3685
+ const sorted = [...anchors].sort((a, b) => a.id.localeCompare(b.id));
3686
+ const bytes = new Uint8Array(32);
3687
+ for (const anchor of sorted) {
3688
+ const hash = anchor.provenanceHash.slice(0, 64).padEnd(64, "0");
3689
+ for (let i = 0; i < 32; i++) {
3690
+ const byteHex = hash.slice(i * 2, i * 2 + 2);
3691
+ bytes[i] ^= parseInt(byteHex, 16) || 0;
3692
+ }
3693
+ }
3694
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
3695
+ }
3696
+ function computeBounds(anchors) {
3697
+ if (anchors.length === 0) {
3698
+ return {
3699
+ min: { x: 0, y: 0, z: 0 },
3700
+ max: { x: 0, y: 0, z: 0 },
3701
+ center: { x: 0, y: 0, z: 0 },
3702
+ halfSize: 0
3703
+ };
3704
+ }
3705
+ let minX = Infinity, minY = Infinity, minZ = Infinity;
3706
+ let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
3707
+ for (const a of anchors) {
3708
+ const r = a.scale;
3709
+ minX = Math.min(minX, a.position[0] - r);
3710
+ minY = Math.min(minY, a.position[1] - r);
3711
+ minZ = Math.min(minZ, a.position[2] - r);
3712
+ maxX = Math.max(maxX, a.position[0] + r);
3713
+ maxY = Math.max(maxY, a.position[1] + r);
3714
+ maxZ = Math.max(maxZ, a.position[2] + r);
3715
+ }
3716
+ const cx = (minX + maxX) / 2;
3717
+ const cy = (minY + maxY) / 2;
3718
+ const cz = (minZ + maxZ) / 2;
3719
+ const halfSize = Math.max(
3720
+ (maxX - minX) / 2,
3721
+ (maxY - minY) / 2,
3722
+ (maxZ - minZ) / 2
3723
+ );
3724
+ return {
3725
+ min: { x: minX, y: minY, z: minZ },
3726
+ max: { x: maxX, y: maxY, z: maxZ },
3727
+ center: { x: cx, y: cy, z: cz },
3728
+ halfSize
3729
+ };
3730
+ }
3731
+ function sanitiseId(s) {
3732
+ return s.replace(/[^a-zA-Z0-9_]/g, "_").slice(0, 32);
3733
+ }
3734
+ function spatialPartition(composition, options) {
3735
+ return new SpatialPartitionPass(options).run(composition);
3736
+ }
3737
+
3385
3738
  // src/types/effects.ts
3386
3739
  function effectCategory(effect) {
3387
3740
  return effect.split(":")[0];
@@ -3546,6 +3899,7 @@ var TRAIT_EFFECTS = {
3546
3899
  // Audio traits
3547
3900
  "@audio": ["audio:play"],
3548
3901
  "@spatial_audio": ["audio:spatial"],
3902
+ "@gem_resonance": ["audio:spatial", "state:read"],
3549
3903
  "@reverb": ["audio:reverb"],
3550
3904
  "@music": ["audio:play", "audio:global"],
3551
3905
  // State traits
@@ -3756,6 +4110,7 @@ var TRAIT_EFFECTS = {
3756
4110
  "@mitosis": [],
3757
4111
  "@mock": [],
3758
4112
  "@model_load": [],
4113
+ "@modbus": ["io:network"],
3759
4114
  "@motion_reduced": ["io:read", "io:write"],
3760
4115
  "@mqtt_pub": ["io:network"],
3761
4116
  "@mqtt_sink": ["io:network"],
@@ -3773,6 +4128,7 @@ var TRAIT_EFFECTS = {
3773
4128
  "@object_tracking": ["state:read"],
3774
4129
  "@occlusion": ["io:read", "io:write"],
3775
4130
  "@openxr_hal": [],
4131
+ "@opc_ua": ["io:network"],
3776
4132
  "@orbital": [],
3777
4133
  "@package_signing": ["authority:own"],
3778
4134
  "@pagerduty": [],
@@ -3965,7 +4321,9 @@ function inferFromTraits(traitNames) {
3965
4321
  sources.set(e, existing);
3966
4322
  }
3967
4323
  } else {
3968
- warnings.push(`Unknown trait '${normalized}': cannot infer effects. Assuming pure.`);
4324
+ warnings.push(
4325
+ `Unknown trait '${normalized}': cannot infer effects, so the safety checker assumes pure. Register the trait in TRAIT_EFFECTS or add an explicit @effect declaration before relying on this inference.`
4326
+ );
3969
4327
  }
3970
4328
  }
3971
4329
  return { row: new EffectRow(allEffects), sources, warnings };
@@ -4256,6 +4614,7 @@ var TRAIT_RESOURCE_COSTS = {
4256
4614
  // ── Audio ──
4257
4615
  "@audio": { audioSources: 1 },
4258
4616
  "@spatial_audio": { audioSources: 1 },
4617
+ "@gem_resonance": { audioSources: 1 },
4259
4618
  "@environmental_audio": { audioSources: 4, memoryMB: 2 },
4260
4619
  "@voice_mesh": { audioSources: 1, networkMsgs: 10 },
4261
4620
  "@voice_input": { audioSources: 1, memoryMB: 1 },
@@ -4268,6 +4627,8 @@ var TRAIT_RESOURCE_COSTS = {
4268
4627
  "@lobby": { networkMsgs: 5, memoryMB: 2 },
4269
4628
  "@mqtt_sink": { networkMsgs: 5 },
4270
4629
  "@mqtt_source": { networkMsgs: 5 },
4630
+ "@modbus": { networkMsgs: 5 },
4631
+ "@opc_ua": { networkMsgs: 5 },
4271
4632
  "@sync_tier": { networkMsgs: 2 },
4272
4633
  "@crdt_room": { networkMsgs: 10, memoryMB: 4 },
4273
4634
  "@shareplay": { networkMsgs: 5, memoryMB: 2 },
@@ -4981,6 +5342,7 @@ function quickSafetyCheck(traits, calls, options = {}) {
4981
5342
  }
4982
5343
 
4983
5344
  // src/compiler/platform/CrossRealityTraitRegistry.ts
5345
+ init_PlatformConditional();
4984
5346
  var CATEGORY_DEFAULT_EMBODIMENT = {
4985
5347
  vr: "FullAvatar",
4986
5348
  ar: "FloatingAgent",
@@ -5268,6 +5630,7 @@ function createCrossRealityTraitRegistry() {
5268
5630
  }
5269
5631
 
5270
5632
  // src/compiler/platform/ModalitySelector.ts
5633
+ init_PlatformConditional();
5271
5634
  var EMBODIMENT_TO_TARGET = {
5272
5635
  FullAvatar: { primary: "openxr", fallback: "r3f" },
5273
5636
  FloatingAgent: { primary: "visionos", fallback: "r3f" },
@@ -5307,14 +5670,10 @@ function selectModality(platform, options = {}) {
5307
5670
  reasoning.push(`Embodiment forced to ${embodiment} by caller`);
5308
5671
  } else if (platform in PLATFORM_EMBODIMENT_OVERRIDES) {
5309
5672
  embodiment = PLATFORM_EMBODIMENT_OVERRIDES[platform];
5310
- reasoning.push(
5311
- `Embodiment ${embodiment} from platform-specific override for ${platform}`
5312
- );
5673
+ reasoning.push(`Embodiment ${embodiment} from platform-specific override for ${platform}`);
5313
5674
  } else {
5314
5675
  embodiment = CATEGORY_DEFAULT_EMBODIMENT[category];
5315
- reasoning.push(
5316
- `Embodiment ${embodiment} from category default for ${category}`
5317
- );
5676
+ reasoning.push(`Embodiment ${embodiment} from category default for ${category}`);
5318
5677
  }
5319
5678
  let exportTarget;
5320
5679
  let fallbackTarget;
@@ -5325,16 +5684,12 @@ function selectModality(platform, options = {}) {
5325
5684
  } else if (platform in PLATFORM_TARGET_OVERRIDES) {
5326
5685
  exportTarget = PLATFORM_TARGET_OVERRIDES[platform];
5327
5686
  fallbackTarget = EMBODIMENT_TO_TARGET[embodiment]?.fallback ?? null;
5328
- reasoning.push(
5329
- `ExportTarget ${exportTarget} from platform-specific override for ${platform}`
5330
- );
5687
+ reasoning.push(`ExportTarget ${exportTarget} from platform-specific override for ${platform}`);
5331
5688
  } else {
5332
5689
  const mapping = EMBODIMENT_TO_TARGET[embodiment];
5333
5690
  exportTarget = mapping.primary;
5334
5691
  fallbackTarget = mapping.fallback;
5335
- reasoning.push(
5336
- `ExportTarget ${exportTarget} from embodiment mapping for ${embodiment}`
5337
- );
5692
+ reasoning.push(`ExportTarget ${exportTarget} from embodiment mapping for ${embodiment}`);
5338
5693
  }
5339
5694
  const canRenderSpatial = capabilities.gpu3D && capabilities.frameBudgetMs <= 16.6;
5340
5695
  reasoning.push(
@@ -5376,8 +5731,10 @@ function bestCategoryForTraits(requiredCapabilities) {
5376
5731
  const canSupport = platforms.some((platform) => {
5377
5732
  const caps = PLATFORM_CAPABILITIES[platform];
5378
5733
  return Object.entries(requiredCapabilities).every(([key, required]) => {
5379
- if (typeof required === "boolean") return !required || caps[key] === true;
5380
- if (typeof required === "number") return caps[key] <= required;
5734
+ if (typeof required === "boolean")
5735
+ return !required || caps[key] === true;
5736
+ if (typeof required === "number")
5737
+ return caps[key] <= required;
5381
5738
  return true;
5382
5739
  });
5383
5740
  });
@@ -5399,7 +5756,7 @@ var CompilerBridge = class {
5399
5756
  if (this.initialized) return;
5400
5757
  try {
5401
5758
  const [parserModule, compilerModule] = await Promise.all([
5402
- import('./parser.js'),
5759
+ import('./HoloScriptPlusParser-F2Z56FJR.js'),
5403
5760
  import('./compiler/r3f.js')
5404
5761
  ]);
5405
5762
  this.modules = {
@@ -5528,6 +5885,16 @@ function getCompilerBridge() {
5528
5885
  function json(value) {
5529
5886
  return JSON.stringify(value, null, 2);
5530
5887
  }
5888
+ function unsupportedPipelineStep(kind, type, name) {
5889
+ const typeLabel = type || "unknown";
5890
+ return `[PipelineNodeCompiler] Unsupported pipeline ${kind} type "${typeLabel}" (step: ${name}). PipelineNodeCompiler does not yet emit code for this type.`;
5891
+ }
5892
+ function unsupportedNodeThrow(kind, type, name) {
5893
+ return `(() => { throw new Error(${json(unsupportedPipelineStep(kind, type, name))}); })()`;
5894
+ }
5895
+ function unsupportedPythonRaise(kind, type, name) {
5896
+ return `raise NotImplementedError(${json(unsupportedPipelineStep(kind, type, name))})`;
5897
+ }
5531
5898
  function emitSource(source) {
5532
5899
  switch (source.type) {
5533
5900
  case "rest":
@@ -5538,15 +5905,29 @@ function emitSource(source) {
5538
5905
  case "list":
5539
5906
  return json(source.items || []);
5540
5907
  default:
5541
- return "[]";
5908
+ return unsupportedNodeThrow("source", source.type, source.name);
5542
5909
  }
5543
5910
  }
5544
5911
  function emitFieldMappingTransform(t) {
5545
5912
  const mappings = t.mappings || [];
5546
- const mapExpr = mappings.map((m) => `${json(m.to)}: applyTransforms(item[${json(m.from)}], ${json(m.transforms || [])})`).join(",\n ");
5547
- return `data = data.map((item) => ({
5913
+ const unwrapMappings = mappings.filter((m) => m.from.endsWith("[]"));
5914
+ const valueMappings = mappings.filter((m) => !m.from.endsWith("[]"));
5915
+ const lines = [];
5916
+ for (const mapping of unwrapMappings) {
5917
+ lines.push(
5918
+ `data = data.flatMap((item) => unwrapPathValues(item, ${json(mapping.from)}).map((value) => ({ ...item, ${json(mapping.to)}: applyTransforms(value, ${json(mapping.transforms || [])}) })));`
5919
+ );
5920
+ }
5921
+ if (valueMappings.length === 0) {
5922
+ return lines.join("\n");
5923
+ }
5924
+ const mapExpr = valueMappings.map(
5925
+ (m) => `${json(m.to)}: applyTransforms(getPathValue(item, ${json(m.from)}), ${json(m.transforms || [])})`
5926
+ ).join(",\n ");
5927
+ lines.push(`data = data.map((item) => ({
5548
5928
  ${mapExpr}
5549
- }));`;
5929
+ }));`);
5930
+ return lines.join("\n");
5550
5931
  }
5551
5932
  function emitTransform(t) {
5552
5933
  if ((t.type === "field_mapping" || !t.type) && t.mappings && t.mappings.length > 0) {
@@ -5578,11 +5959,11 @@ function emitSink(sink) {
5578
5959
  return `await writeOutput(${json(sink.path || "./pipeline-output.jsonl")}, data, ${json(sink.format || "jsonl")}, ${json(Boolean(sink.append))});`;
5579
5960
  case "rest":
5580
5961
  case "webhook":
5581
- return `await fetch(${json(sink.endpoint || "")}, { method: ${json(sink.method || "POST")}, headers: { 'content-type': 'application/json' }, body: JSON.stringify(data) });`;
5962
+ return `await postJSON(${json(sink.endpoint || "")}, data, { method: ${json(sink.method || "POST")} });`;
5582
5963
  case "mcp":
5583
5964
  return `console.warn(${json(`[${sink.name}] mcp sink requires host integration: ${sink.server || ""}/${sink.tool || ""}`)});`;
5584
5965
  default:
5585
- return `// sink ${sink.name} (${sink.type}) not implemented`;
5966
+ return `${unsupportedNodeThrow("sink", sink.type, sink.name)};`;
5586
5967
  }
5587
5968
  }
5588
5969
  function emitPythonSource(source) {
@@ -5595,12 +5976,14 @@ function emitPythonSource(source) {
5595
5976
  case "list":
5596
5977
  return `datasets[${json(source.name)}] = ${json(source.items || [])}`;
5597
5978
  default:
5598
- return `datasets[${json(source.name)}] = []`;
5979
+ return unsupportedPythonRaise("source", source.type, source.name);
5599
5980
  }
5600
5981
  }
5601
5982
  function emitPythonFieldMappingTransform(t) {
5602
5983
  const mappings = t.mappings || [];
5603
- const mappingLines = mappings.map((m) => `${json(m.to)}: apply_transforms(item.get(${json(m.from)}), ${json(m.transforms || [])}),`).join("\n ");
5984
+ const mappingLines = mappings.map(
5985
+ (m) => `${json(m.to)}: apply_transforms(item.get(${json(m.from)}), ${json(m.transforms || [])}),`
5986
+ ).join("\n ");
5604
5987
  return `data = [
5605
5988
  {
5606
5989
  ${mappingLines}
@@ -5642,7 +6025,7 @@ function emitPythonSink(sink) {
5642
6025
  case "mcp":
5643
6026
  return `print(${json(`[${sink.name}] mcp sink requires host integration: ${sink.server || ""}/${sink.tool || ""}`)})`;
5644
6027
  default:
5645
- return `# sink ${sink.name} (${sink.type}) not implemented`;
6028
+ return unsupportedPythonRaise("sink", sink.type, sink.name);
5646
6029
  }
5647
6030
  }
5648
6031
  function compilePipelineToNode(pipeline, options = {}) {
@@ -5659,18 +6042,55 @@ function compilePipelineToNode(pipeline, options = {}) {
5659
6042
  */
5660
6043
 
5661
6044
  import fs from 'node:fs/promises';
6045
+ import path from 'node:path';
6046
+
6047
+ const RUN_DATE = new Date().toISOString().slice(0, 10);
6048
+
6049
+ function resolveTemplate(value, context = {}) {
6050
+ if (typeof value !== 'string') return value;
6051
+ return value
6052
+ .replace(/\\$\\{date\\}/g, RUN_DATE)
6053
+ .replace(/\\$\\{env\\.([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_match, name) => process.env[name] ?? '')
6054
+ .replace(/\\$\\{([A-Za-z_][A-Za-z0-9_.]*)\\}/g, (_match, key) => {
6055
+ const found = key.split('.').reduce((acc, part) => (acc && typeof acc === 'object' ? acc[part] : undefined), context);
6056
+ return found === undefined || found === null ? '' : String(found);
6057
+ });
6058
+ }
6059
+
6060
+ function normalizeOutputPath(rawPath, format) {
6061
+ const resolved = resolveTemplate(rawPath);
6062
+ if (!resolved) return format === 'json' ? './pipeline-output.json' : './pipeline-output.jsonl';
6063
+ if (path.extname(resolved)) return resolved;
6064
+ return path.join(resolved, format === 'json' ? 'pipeline-output.json' : 'pipeline-output.jsonl');
6065
+ }
5662
6066
 
5663
6067
  async function fetchJSON(url, init) {
5664
- if (!url) return [];
5665
- const res = await fetch(url, init);
6068
+ const resolvedUrl = resolveTemplate(url);
6069
+ if (!resolvedUrl) return [];
6070
+ const res = await fetch(resolvedUrl, init);
5666
6071
  if (!res.ok) throw new Error(\`Request failed: \${res.status} \${res.statusText}\`);
5667
6072
  const body = await res.json();
5668
6073
  return Array.isArray(body) ? body : [body];
5669
6074
  }
5670
6075
 
6076
+ async function postJSON(url, data, init) {
6077
+ const resolvedUrl = resolveTemplate(url, { data });
6078
+ if (!resolvedUrl) {
6079
+ console.warn('[PipelineNodeCompiler] skipping empty webhook/rest sink endpoint');
6080
+ return;
6081
+ }
6082
+ const res = await fetch(resolvedUrl, {
6083
+ ...init,
6084
+ headers: { 'content-type': 'application/json', ...(init?.headers || {}) },
6085
+ body: JSON.stringify(data),
6086
+ });
6087
+ if (!res.ok) throw new Error(\`Request failed: \${res.status} \${res.statusText}\`);
6088
+ }
6089
+
5671
6090
  async function readJSONArray(filePath) {
5672
- if (!filePath) return [];
5673
- const raw = await fs.readFile(filePath, 'utf8');
6091
+ const resolvedPath = resolveTemplate(filePath);
6092
+ if (!resolvedPath) return [];
6093
+ const raw = await fs.readFile(resolvedPath, 'utf8');
5674
6094
  const parsed = JSON.parse(raw);
5675
6095
  return Array.isArray(parsed) ? parsed : [parsed];
5676
6096
  }
@@ -5688,6 +6108,22 @@ function applyTransforms(value, transforms) {
5688
6108
  return v;
5689
6109
  }
5690
6110
 
6111
+ function getPathValue(item, pathExpr) {
6112
+ const cleanPath = String(pathExpr || '').replace(/\\[\\]$/, '');
6113
+ if (!cleanPath) return item;
6114
+ return cleanPath.split('.').reduce((acc, part) => {
6115
+ if (acc == null || typeof acc !== 'object') return undefined;
6116
+ return acc[part];
6117
+ }, item);
6118
+ }
6119
+
6120
+ function unwrapPathValues(item, pathExpr) {
6121
+ const value = getPathValue(item, pathExpr);
6122
+ if (Array.isArray(value)) return value;
6123
+ if (value == null) return [];
6124
+ return [value];
6125
+ }
6126
+
5691
6127
  function evalCondition(item, condition) {
5692
6128
  try {
5693
6129
  const fn = new Function('item', \`with (item) { return (\${condition}); }\`);
@@ -5708,17 +6144,20 @@ function validateItem(item, fields) {
5708
6144
  return true;
5709
6145
  }
5710
6146
 
5711
- async function writeOutput(path, data, format, append) {
6147
+ async function writeOutput(rawPath, data, format, append) {
6148
+ const outputPath = normalizeOutputPath(rawPath, format);
6149
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
6150
+
5712
6151
  if (format === 'json') {
5713
6152
  const text = JSON.stringify(data, null, 2);
5714
- if (append) await fs.appendFile(path, text + '\\n');
5715
- else await fs.writeFile(path, text);
6153
+ if (append) await fs.appendFile(outputPath, text + '\\n');
6154
+ else await fs.writeFile(outputPath, text);
5716
6155
  return;
5717
6156
  }
5718
6157
 
5719
6158
  const lines = data.map((d) => JSON.stringify(d)).join('\\n') + '\\n';
5720
- if (append) await fs.appendFile(path, lines);
5721
- else await fs.writeFile(path, lines);
6159
+ if (append) await fs.appendFile(outputPath, lines);
6160
+ else await fs.writeFile(outputPath, lines);
5722
6161
  }
5723
6162
 
5724
6163
  export async function runPipeline() {
@@ -5940,116 +6379,6 @@ function compilePipelineSource(source, options = {}) {
5940
6379
  return compilePipelineSourceToNode(source, options.node);
5941
6380
  }
5942
6381
 
5943
- // src/compiler/NextJSCompiler.ts
5944
- init_CompilerBase();
5945
- init_Native2DCompiler();
5946
- function findTrait(composition, traitName) {
5947
- const traits = composition.traits;
5948
- if (!traits) return null;
5949
- const found = traits.find((t) => t.name === traitName);
5950
- return found?.config || null;
5951
- }
5952
- var NextJSCompiler = class extends CompilerBase {
5953
- constructor(options = {}) {
5954
- super();
5955
- this.options = options;
5956
- this.compilerName = "NextJSCompiler";
5957
- }
5958
- /**
5959
- * Compile HoloComposition AST to Next.js App Router Code
5960
- *
5961
- * @param composition - HoloScript AST
5962
- * @param agentToken - JWT or UCAN token proving agent identity
5963
- * @param outputPath - Optional output file path for scope validation
5964
- * @param sceneGraph - Optional pre-computed SSG
5965
- */
5966
- async compile(composition, agentToken, outputPath, _sceneGraph) {
5967
- this.validateCompilerAccess(agentToken, outputPath);
5968
- return this.buildNextRoute(composition);
5969
- }
5970
- validateCompilerAccess(agentToken, outputPath) {
5971
- if (typeof agentToken === "object" && agentToken !== null) {
5972
- this.validateCapabilityAccess(agentToken, outputPath);
5973
- } else {
5974
- this.validateASTAccess(agentToken);
5975
- this.validateCodeGeneration(agentToken);
5976
- if (outputPath) {
5977
- this.validateOutputPath(agentToken, outputPath);
5978
- }
5979
- this.validateSpatialZoneAccess(agentToken);
5980
- }
5981
- }
5982
- buildNextRoute(composition) {
5983
- const compiler = new Native2DCompiler();
5984
- const pageTrait = findTrait(composition, "page");
5985
- const metaTrait = findTrait(composition, "metadata");
5986
- const route = pageTrait?.route || `/${composition.name.toLowerCase().replace(/\s+/g, "-")}`;
5987
- const isClient = pageTrait?.client !== false;
5988
- const slotMap = this.options.slots || {};
5989
- if (pageTrait?.redirect) {
5990
- const redirectUrl = pageTrait.redirect;
5991
- const lines2 = [
5992
- `// @generated by HoloScript NextJSCompiler \u2014 DO NOT EDIT`,
5993
- `import { redirect } from 'next/navigation';`,
5994
- ``,
5995
- `export default function RedirectPage() {`,
5996
- ` redirect(${JSON.stringify(redirectUrl)});`,
5997
- `}`
5998
- ];
5999
- if (metaTrait) {
6000
- const metaEntries = [];
6001
- if (metaTrait.title) metaEntries.push(` title: ${JSON.stringify(metaTrait.title)},`);
6002
- if (metaTrait.description) metaEntries.push(` description: ${JSON.stringify(metaTrait.description)},`);
6003
- lines2.push("");
6004
- lines2.push(`export const metadata = {`);
6005
- lines2.push(metaEntries.join("\n"));
6006
- lines2.push(`};`);
6007
- }
6008
- const routePath2 = route.replace(/^\//, "") || "index";
6009
- return {
6010
- path: `${routePath2}/page.tsx`,
6011
- code: lines2.join("\n")
6012
- };
6013
- }
6014
- const compilerOptions = {
6015
- format: "react",
6016
- useUIComponents: true,
6017
- slots: slotMap
6018
- };
6019
- const elements = composition.ui?.elements || composition.objects || [];
6020
- const componentCode = compiler.generateReactComponent(
6021
- composition.name,
6022
- elements,
6023
- composition,
6024
- compilerOptions
6025
- );
6026
- const pageSafeComponentCode = componentCode.replace(
6027
- /export\s+function\s+([A-Za-z0-9_]+)\s*\(/,
6028
- "function $1("
6029
- );
6030
- const lines = [];
6031
- if (isClient) {
6032
- lines.push("'use client';");
6033
- lines.push("");
6034
- }
6035
- lines.push(pageSafeComponentCode);
6036
- if (metaTrait && !isClient) {
6037
- const metaEntries = [];
6038
- if (metaTrait.title) metaEntries.push(` title: ${JSON.stringify(metaTrait.title)},`);
6039
- if (metaTrait.description) metaEntries.push(` description: ${JSON.stringify(metaTrait.description)},`);
6040
- lines.push("");
6041
- lines.push(`export const metadata = {`);
6042
- lines.push(metaEntries.join("\n"));
6043
- lines.push(`};`);
6044
- }
6045
- const routePath = route.replace(/^\//, "") || "index";
6046
- return {
6047
- path: `${routePath}/page.tsx`,
6048
- code: lines.join("\n")
6049
- };
6050
- }
6051
- };
6052
-
6053
- export { A2AAgentCardCompiler, A2AAgentCardCompiler_exports, ALL_PLATFORMS, BUILTIN_RESOURCES, CAPABILITY_HIERARCHY, CATEGORY_DEFAULT_EMBODIMENT, CompilerBridge, CrossRealityTraitRegistry, DEFAULT_EMBODIMENT, EFFECT_TO_CAPABILITY, EffectChecker, EffectRow, HANDOFF_PATH_RULES, LinearTypeChecker, MVC_BUDGET_CONSTRAINTS, NIRCompiler, NIRCompiler_exports, Native2DCompiler, Native2DCompiler_exports, NextJSCompiler, PLATFORM_BUDGETS, PLATFORM_CAPABILITIES, PLATFORM_CATEGORIES, PLATFORM_EMBODIMENT_OVERRIDES, ResourceBudgetAnalyzer, TRAIT_EFFECTS, TRAIT_RESOURCE_COSTS, TRAIT_RESOURCE_MAP, TRUST_LEVEL_CAPABILITIES, USDZPipeline, agentBudgetFor, bestCategoryForTraits, buildSafetyReport, checkCapabilities, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, createCrossRealityTraitRegistry, createEffectChecker, dangerLevel, deriveRequirements, embodimentFor, expandCapabilities, formatReport, generateCertificate, getCompilerBridge, getCrossRealityTraitRegistry, hasCapability, inferFromBuiltins, inferFromTraits, init_A2AAgentCardCompiler, init_NIRCompiler, init_Native2DCompiler, isPipelineSource, isSafeTraitSet, knownBuiltins, knownTraits, matchesPlatform, parsePipeline, platformCategory, quickSafetyCheck, resetCrossRealityTraitRegistry, resolvePlatforms, runSafetyPass, selectBlock, selectModality, selectModalityForAll };
6054
- //# sourceMappingURL=chunk-BO2OKHIY.js.map
6055
- //# sourceMappingURL=chunk-BO2OKHIY.js.map
6382
+ export { A2AAgentCardCompiler, A2AAgentCardCompiler_exports, BUILTIN_RESOURCES, CAPABILITY_HIERARCHY, CATEGORY_DEFAULT_EMBODIMENT, CompilerBridge, CrossRealityTraitRegistry, EFFECTS_BY_CATEGORY, EFFECT_TO_CAPABILITY, EffectChecker, EffectRow, GaussianSplattingCompiler, HANDOFF_PATH_RULES, LinearTypeChecker, MVC_BUDGET_CONSTRAINTS, NIRCompiler, NIRCompiler_exports, PLATFORM_BUDGETS, PLATFORM_EMBODIMENT_OVERRIDES, ResourceBudgetAnalyzer, SHARED_SORT_SHADER_PATH, SpatialPartitionPass, TRAIT_EFFECTS, TRAIT_RESOURCE_COSTS, TRAIT_RESOURCE_MAP, TRUST_LEVEL_CAPABILITIES, ThreeJSCompiler, ThreeJSCompiler_exports, USDZPipeline, bestCategoryForTraits, buildSafetyReport, checkCapabilities, compilePipelineSource, compilePipelineSourceToNode, compilePipelineSourceToPython, compilePipelineToNode, compilePipelineToPython, createCrossRealityTraitRegistry, createEffectChecker, createGaussianSplattingCompiler, dangerLevel, deriveRequirements, detectMultiUserSharedSort, effectCategory, expandCapabilities, formatReport, generateCertificate, getCompilerBridge, getCrossRealityTraitRegistry, inferFromBuiltins, inferFromTraits, init_A2AAgentCardCompiler, init_NIRCompiler, init_ThreeJSCompiler, isSafeTraitSet, knownBuiltins, knownTraits, quickSafetyCheck, resetCrossRealityTraitRegistry, runSafetyPass, selectModality, selectModalityForAll, spatialPartition };
6383
+ //# sourceMappingURL=chunk-QCCBXSCE.js.map
6384
+ //# sourceMappingURL=chunk-QCCBXSCE.js.map