@holoscript/core 8.0.7 → 8.0.9

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 (462) hide show
  1. package/bin/holoscript.cjs +5 -1
  2. package/dist/GLTFPipeline-L76YTXKA.js +15 -0
  3. package/dist/GLTFPipeline-ZWJN7GI6.cjs +36 -0
  4. package/dist/HoloCompositionParser-K76KTEEE.js +12 -0
  5. package/dist/HoloCompositionParser-UZH6Y4HO.cjs +45 -0
  6. package/dist/HoloScriptCodeParser-2D4ERFUZ.js +6 -0
  7. package/dist/HoloScriptCodeParser-UDRLDA7I.cjs +23 -0
  8. package/dist/HoloScriptPlusParser-FTMCGWXD.js +13 -0
  9. package/dist/HoloScriptPlusParser-LQR5GIKF.cjs +30 -0
  10. package/dist/HoloScriptRuntime-UTRLJI5L.js +12 -0
  11. package/dist/HoloScriptRuntime-YBYXJHJN.cjs +21 -0
  12. package/dist/SceneIRCompiler-63KA3M2F.js +17 -0
  13. package/dist/SceneIRCompiler-KWUFHZ4O.cjs +42 -0
  14. package/dist/{USDZExporter-AUHZODOF.cjs → USDZExporter-ML4UMIGC.cjs} +3 -3
  15. package/dist/{USDZExporter-GXB4AUSG.js → USDZExporter-ZFKLQ76G.js} +3 -3
  16. package/dist/agents/index.cjs +1 -1
  17. package/dist/agents/index.js +1 -1
  18. package/dist/audit/AuditLogger.d.ts +106 -0
  19. package/dist/audit/AuditQueryBuilder.d.ts +79 -0
  20. package/dist/audit/ComplianceReporter.d.ts +90 -0
  21. package/dist/audit/index.d.ts +13 -0
  22. package/dist/{chunk-FGMDMJM7.js → chunk-2BYAUHBO.js} +3 -3
  23. package/dist/{chunk-EDPYCLRC.cjs → chunk-2E6PP5UE.cjs} +83 -59
  24. package/dist/{chunk-GASCWJK5.js → chunk-2EGGAZT3.js} +65 -287
  25. package/dist/{chunk-SIEXCILW.js → chunk-2I3XAGMF.js} +3 -3
  26. package/dist/{chunk-OS533P33.cjs → chunk-2KKOYZYI.cjs} +1074 -1655
  27. package/dist/chunk-2MQKNDNH.js +51 -0
  28. package/dist/{chunk-7DMMMBCY.cjs → chunk-2X3IPCBK.cjs} +10 -10
  29. package/dist/chunk-2ZOTBO25.cjs +202 -0
  30. package/dist/chunk-356N4NPM.cjs +152 -0
  31. package/dist/{chunk-X3GJPRVK.cjs → chunk-36NPLOI4.cjs} +92 -81
  32. package/dist/{chunk-SLU6UPJI.cjs → chunk-37HHY7RH.cjs} +5 -5
  33. package/dist/{chunk-YDPEHCCI.cjs → chunk-3CDDRUER.cjs} +3 -118
  34. package/dist/chunk-3F7ZZWIN.js +1651 -0
  35. package/dist/chunk-3ILD7TKP.cjs +187 -0
  36. package/dist/{chunk-X27QRG4C.cjs → chunk-3IUHTGDD.cjs} +153 -41
  37. package/dist/{chunk-PXNZ6TME.js → chunk-4376VHNJ.js} +60 -36
  38. package/dist/{chunk-YKGPCZEE.cjs → chunk-4FIBOJW6.cjs} +10 -10
  39. package/dist/chunk-4Q7RKQQI.cjs +14195 -0
  40. package/dist/{chunk-YCM6QQRT.cjs → chunk-566ZB4LZ.cjs} +180 -8
  41. package/dist/{chunk-2Y3V22SG.js → chunk-5CURIYGT.js} +3 -3
  42. package/dist/{chunk-QBWNJXNR.js → chunk-5FYMCVBY.js} +5 -5
  43. package/dist/{chunk-ZA34AN3R.js → chunk-5LVFTGKH.js} +841 -12
  44. package/dist/chunk-63AUAIL6.js +48 -0
  45. package/dist/chunk-655FATJU.js +110 -0
  46. package/dist/{chunk-TQ377OLB.cjs → chunk-65S62L4D.cjs} +28 -22
  47. package/dist/chunk-6NTAZN5Z.cjs +502 -0
  48. package/dist/chunk-6TRX6AR2.js +9376 -0
  49. package/dist/chunk-6ZCCLKS2.cjs +51 -0
  50. package/dist/{chunk-MDR235RZ.js → chunk-734OB5SK.js} +721 -8
  51. package/dist/{chunk-Q2Q34NF3.js → chunk-77QI552M.js} +6 -6
  52. package/dist/{chunk-WKX5AMOY.js → chunk-7I74JWPW.js} +3 -3
  53. package/dist/{chunk-5FSKKMR7.cjs → chunk-7IDJDMPU.cjs} +232 -4
  54. package/dist/chunk-7VBKRGIZ.cjs +847 -0
  55. package/dist/{chunk-KCPHASCO.js → chunk-AATYYLYK.js} +5 -5
  56. package/dist/{chunk-WFKVS2K4.cjs → chunk-AUZRKIHQ.cjs} +1101 -55
  57. package/dist/{chunk-DTGBOSEM.cjs → chunk-AWXFEAQL.cjs} +12 -12
  58. package/dist/{chunk-THCK6ECW.js → chunk-B3CWTCK2.js} +231 -3
  59. package/dist/chunk-BCP4E7MD.cjs +997 -0
  60. package/dist/chunk-BG7RPYJP.js +91 -0
  61. package/dist/{chunk-VF257YKO.js → chunk-BP4KTMLY.js} +117 -5
  62. package/dist/{chunk-YN6IETRZ.js → chunk-BQJ3YBF3.js} +6424 -987
  63. package/dist/{chunk-KOUAQL2B.cjs → chunk-CANAL6CT.cjs} +1569 -168
  64. package/dist/{chunk-FDSGHPAK.js → chunk-CBSDJF3B.js} +3 -3
  65. package/dist/{chunk-FEWUHQNM.cjs → chunk-CFVK26P4.cjs} +4 -4
  66. package/dist/{chunk-M7K4LE66.cjs → chunk-CI33NINL.cjs} +4 -4
  67. package/dist/{chunk-2OWDB4FB.js → chunk-CKV5NYAE.js} +6 -6
  68. package/dist/{chunk-LPS5AMQD.cjs → chunk-CM4NHXVO.cjs} +24 -24
  69. package/dist/chunk-D3HSRXYB.js +115 -0
  70. package/dist/{chunk-FNHJRI32.js → chunk-DBH3D2MU.js} +1561 -160
  71. package/dist/{chunk-GW3LKD5C.js → chunk-DJNH4HFW.js} +3 -3
  72. package/dist/{chunk-2GCNOI2U.cjs → chunk-DN6F4DHH.cjs} +9 -3
  73. package/dist/chunk-DQRJ5RJG.js +432 -0
  74. package/dist/{chunk-C7ZBSV2Q.js → chunk-DUG3OQAS.js} +106 -43
  75. package/dist/chunk-ECUYJOJ2.cjs +199 -0
  76. package/dist/chunk-EEMTCAK7.js +182 -0
  77. package/dist/{chunk-3SKLAUDD.cjs → chunk-EI3J6LTW.cjs} +359 -581
  78. package/dist/{chunk-SSSN7VAM.js → chunk-EM2OGPYE.js} +4 -4
  79. package/dist/{chunk-56VOWURB.cjs → chunk-ENZCIQZC.cjs} +522 -453
  80. package/dist/chunk-ESBXUYOC.cjs +836 -0
  81. package/dist/{chunk-L5U4W6JC.js → chunk-ESSEF6U2.js} +4 -4
  82. package/dist/chunk-ET3AN4W3.js +824 -0
  83. package/dist/chunk-EXKSFGSX.cjs +14 -14
  84. package/dist/{chunk-I76GIKN7.cjs → chunk-F3YT6GUF.cjs} +17 -17
  85. package/dist/{chunk-WRWEX5ZF.js → chunk-F75DZBBI.js} +3 -3
  86. package/dist/{chunk-4JGRWHZJ.js → chunk-FG6PYGIZ.js} +12 -6
  87. package/dist/chunk-FGGJQRLZ.js +14 -14
  88. package/dist/{chunk-SXOSDZD6.js → chunk-FWCHPCD4.js} +128 -10
  89. package/dist/{chunk-XW6IXEQH.cjs → chunk-G35CAQ7I.cjs} +5 -5
  90. package/dist/{chunk-7VMGP2FW.js → chunk-G6KACNMO.js} +132 -188
  91. package/dist/{chunk-FJPADH77.cjs → chunk-GAWJJAGT.cjs} +6 -6
  92. package/dist/chunk-GGR7QUKK.cjs +4724 -0
  93. package/dist/chunk-GIBF4BHH.js +14098 -0
  94. package/dist/{chunk-AWB7QYY6.cjs → chunk-GILYQ5VH.cjs} +6 -6
  95. package/dist/{chunk-FWVYAMNW.cjs → chunk-GKFCHGCM.cjs} +4 -4
  96. package/dist/{chunk-Y3ZFVUUU.js → chunk-GLEJ2TLS.js} +3 -3
  97. package/dist/{chunk-3GWWJT7L.js → chunk-GP3OKSKT.js} +13 -13
  98. package/dist/chunk-GTIPOEHN.js +196 -0
  99. package/dist/{chunk-LMJ5EBV7.cjs → chunk-GZPUA2TL.cjs} +16 -15
  100. package/dist/{chunk-IELX2OKI.js → chunk-H4LJ4HEA.js} +3 -115
  101. package/dist/{chunk-ACVWFGBI.cjs → chunk-HCX4SMFK.cjs} +3 -3
  102. package/dist/{chunk-HYNTS5CP.js → chunk-HHRZ6STP.js} +24 -2
  103. package/dist/chunk-HIDEIEFG.js +48 -0
  104. package/dist/{chunk-W6RW64BB.cjs → chunk-HSWBIDZM.cjs} +228 -5
  105. package/dist/{chunk-GSOUNWEL.js → chunk-HVX7QQYK.js} +1035 -1616
  106. package/dist/{chunk-TRCGG42I.cjs → chunk-IFW5IW4L.cjs} +6502 -1019
  107. package/dist/{chunk-F5LKJ6F5.cjs → chunk-IJU6AS67.cjs} +32 -28
  108. package/dist/{chunk-TVANHNJ7.js → chunk-IK6Z2HNC.js} +173 -3
  109. package/dist/{chunk-QGMUTVVH.cjs → chunk-IS7NTKY5.cjs} +20 -20
  110. package/dist/{chunk-YFVQWSNJ.js → chunk-IXWGYWH6.js} +3 -3
  111. package/dist/chunk-J2DAS2PL.js +148 -0
  112. package/dist/chunk-JBQXZIWB.js +148 -0
  113. package/dist/chunk-JBYBMBMW.js +261 -0
  114. package/dist/{chunk-LWUOUCYL.js → chunk-JEJ7TT54.js} +5 -5
  115. package/dist/{chunk-DUCB6LGL.js → chunk-JOTCTHN5.js} +211 -5
  116. package/dist/{chunk-47RUFYKR.js → chunk-K56UVEXV.js} +3 -3
  117. package/dist/{chunk-XSFNHP2E.js → chunk-KB26H447.js} +3 -3
  118. package/dist/{chunk-3NGDZZR4.js → chunk-KEYG7HGY.js} +430 -37
  119. package/dist/{chunk-DY72BMU5.js → chunk-KFVNCW4Q.js} +4 -4
  120. package/dist/chunk-KPGC7SK2.js +192 -0
  121. package/dist/chunk-KROXXBK5.cjs +53 -0
  122. package/dist/{chunk-ZPZAVHXL.cjs → chunk-LB3ZZMKT.cjs} +137 -19
  123. package/dist/chunk-LDYZWNJW.cjs +1654 -0
  124. package/dist/{chunk-ULMSSHCJ.cjs → chunk-LMB555QB.cjs} +405 -38
  125. package/dist/{chunk-CBJY23VL.js → chunk-MD4IVS42.js} +3 -3
  126. package/dist/{chunk-VMLKSV26.js → chunk-MDDWEBCX.js} +226 -3
  127. package/dist/chunk-MUWH4QK5.cjs +94 -0
  128. package/dist/{chunk-T6W3Z3SH.cjs → chunk-N2ILK7BF.cjs} +4 -4
  129. package/dist/{chunk-6EX3I5P4.cjs → chunk-N74QRJGP.cjs} +6 -6
  130. package/dist/chunk-NFFHLX37.cjs +132 -0
  131. package/dist/chunk-NJSYWX7H.js +190 -0
  132. package/dist/{chunk-SH5PPVK7.cjs → chunk-NQN5LFN4.cjs} +165 -221
  133. package/dist/chunk-NTQRFOPP.cjs +56 -0
  134. package/dist/{chunk-YFWRJW4B.js → chunk-NWMJPTVL.js} +51 -55
  135. package/dist/{chunk-63ZGNR2T.cjs → chunk-OC6GV5QH.cjs} +42 -42
  136. package/dist/{chunk-7E7GCQCK.js → chunk-OG3MBHM3.js} +9 -3
  137. package/dist/chunk-OMNHTCS4.cjs +264 -0
  138. package/dist/chunk-OQXB6NNC.cjs +117 -0
  139. package/dist/{chunk-Y57W2CT5.cjs → chunk-OV46CCA2.cjs} +51 -55
  140. package/dist/{chunk-6PRZIHGL.cjs → chunk-OV6HHKLE.cjs} +21 -266
  141. package/dist/{chunk-C37BHB7N.cjs → chunk-P26YYPOO.cjs} +5 -5
  142. package/dist/{chunk-2BZHWUSR.cjs → chunk-P7JEKJTZ.cjs} +16 -16
  143. package/dist/{chunk-NGBXXZLL.cjs → chunk-PDXX5UI4.cjs} +45 -45
  144. package/dist/{chunk-FHQFPYV4.js → chunk-PJFTTSKE.js} +8 -7
  145. package/dist/{chunk-GVFJ6T4S.cjs → chunk-PVODJEJ7.cjs} +721 -8
  146. package/dist/{chunk-ZZ7RO2UQ.js → chunk-Q265VZJ4.js} +3 -3
  147. package/dist/{chunk-E7JP3BS3.cjs → chunk-Q47JEE2C.cjs} +4 -4
  148. package/dist/chunk-QBY7LRN2.js +281 -0
  149. package/dist/{chunk-Z6PMDS4G.js → chunk-QDQWKSU3.js} +1090 -53
  150. package/dist/{chunk-GH6C2QGW.cjs → chunk-QEDMOGF3.cjs} +857 -16
  151. package/dist/{chunk-5WUNN6ZN.cjs → chunk-QHSAVOOL.cjs} +24 -2
  152. package/dist/chunk-QJNCDVYM.cjs +137 -0
  153. package/dist/chunk-QM7FJB5W.js +4717 -0
  154. package/dist/chunk-QQFB4RT2.cjs +448 -0
  155. package/dist/chunk-QSYBHQAD.cjs +196 -0
  156. package/dist/{chunk-UGXHYIWT.cjs → chunk-QUJ3ZB55.cjs} +28 -28
  157. package/dist/{chunk-2YSNA2F2.cjs → chunk-QVJMDVYZ.cjs} +5 -5
  158. package/dist/chunk-RAJMAX6D.js +131 -0
  159. package/dist/{chunk-VVKVQZI6.js → chunk-RAN3ECAS.js} +3 -3
  160. package/dist/chunk-RKGUZBOC.js +79 -0
  161. package/dist/{chunk-HLFDZ35S.cjs → chunk-RRQIAJLQ.cjs} +8 -8
  162. package/dist/{chunk-PABONWKI.js → chunk-RXQNRZ5F.js} +3 -3
  163. package/dist/{chunk-7ZHYEITD.cjs → chunk-S4O7CFHQ.cjs} +10 -11
  164. package/dist/chunk-SE7ANBGN.js +128 -0
  165. package/dist/{chunk-X2AVEAZM.cjs → chunk-SJIRCTIS.cjs} +176 -2
  166. package/dist/{chunk-WXQ57LAO.js → chunk-SQXAZHDG.js} +4 -4
  167. package/dist/chunk-SR73L5ZP.cjs +84 -0
  168. package/dist/{chunk-OABEO6HH.js → chunk-SZOLTWWD.js} +2349 -214
  169. package/dist/{chunk-5JEU52DW.js → chunk-TPZ3BN2D.js} +3 -3
  170. package/dist/{chunk-QFU53KRH.js → chunk-TSTFYGGX.js} +4 -5
  171. package/dist/{chunk-EBS32AJI.cjs → chunk-TZCFKZ6Z.cjs} +5 -5
  172. package/dist/chunk-UCVZXQ63.js +724 -0
  173. package/dist/chunk-UGQ3QNV6.js +992 -0
  174. package/dist/chunk-UNMVGZVW.js +142 -0
  175. package/dist/{chunk-TEVX443G.js → chunk-UTUD6GJI.js} +178 -6
  176. package/dist/chunk-UXBYA7DV.cjs +155 -0
  177. package/dist/chunk-V6GXFSK7.cjs +443 -0
  178. package/dist/chunk-VHORVGCG.cjs +761 -0
  179. package/dist/{chunk-B4EKV6HQ.js → chunk-VKCTYLDN.js} +500 -442
  180. package/dist/{chunk-O3MGZDCT.cjs → chunk-VTEXJOSD.cjs} +63 -63
  181. package/dist/chunk-VVAAZITA.cjs +287 -0
  182. package/dist/{chunk-V7AKE5VT.cjs → chunk-W2GA3EQB.cjs} +435 -42
  183. package/dist/chunk-W4GABFCR.js +37 -0
  184. package/dist/chunk-WKEK4NCA.js +490 -0
  185. package/dist/{chunk-5A4TCHOC.cjs → chunk-WNYXT4TE.cjs} +4 -4
  186. package/dist/{chunk-S762UEV5.js → chunk-WTH23ISI.js} +6 -6
  187. package/dist/{chunk-BTKZGHAV.js → chunk-WWNCM473.js} +10 -6
  188. package/dist/{chunk-7X5PNIQJ.js → chunk-X3YFRH6K.js} +27 -25
  189. package/dist/{chunk-4YNYPHH3.cjs → chunk-X75H75UY.cjs} +2351 -213
  190. package/dist/{chunk-LYJJI7ZK.cjs → chunk-XCUDDFKC.cjs} +216 -9
  191. package/dist/chunk-YAO4HPJL.cjs +120 -0
  192. package/dist/chunk-YKY2JBER.cjs +9443 -0
  193. package/dist/chunk-YP5CHEYU.cjs +154 -0
  194. package/dist/{chunk-WRNEH5MO.js → chunk-YW3I2FQL.js} +18 -7
  195. package/dist/{chunk-BRNUPDHJ.js → chunk-Z557DVYN.js} +386 -19
  196. package/dist/{chunk-VSACG2AR.js → chunk-Z6LZUYZF.js} +21 -264
  197. package/dist/chunk-ZHPMP447.cjs +43 -0
  198. package/dist/{chunk-LODTHGST.cjs → chunk-ZK7KX5CD.cjs} +133 -70
  199. package/dist/{chunk-CCPSNT6B.cjs → chunk-ZRPALBQB.cjs} +5 -5
  200. package/dist/chunk-ZVFHPMC5.js +824 -0
  201. package/dist/chunk-ZVQMKUGJ.js +443 -0
  202. package/dist/cli/holoscript-runner.cjs +86 -48
  203. package/dist/cli/holoscript-runner.js +54 -16
  204. package/dist/codebase/index.cjs +1 -1
  205. package/dist/codebase/index.js +1 -1
  206. package/dist/compiler/agent-inference.cjs +11 -11
  207. package/dist/compiler/agent-inference.js +9 -6
  208. package/dist/compiler/android-xr.cjs +13 -12
  209. package/dist/compiler/android-xr.js +11 -10
  210. package/dist/compiler/android.cjs +12 -12
  211. package/dist/compiler/android.js +10 -10
  212. package/dist/compiler/business-quest.cjs +10 -10
  213. package/dist/compiler/business-quest.js +2 -2
  214. package/dist/compiler/coco.cjs +1 -1
  215. package/dist/compiler/coco.js +1 -1
  216. package/dist/compiler/context.cjs +9 -9
  217. package/dist/compiler/context.js +6 -6
  218. package/dist/compiler/daimon-seed.cjs +36 -0
  219. package/dist/compiler/daimon-seed.js +12 -0
  220. package/dist/compiler/domain-block-utils.cjs +205 -156
  221. package/dist/compiler/domain-block-utils.js +8 -7
  222. package/dist/compiler/dtdl.cjs +10 -10
  223. package/dist/compiler/dtdl.js +7 -7
  224. package/dist/compiler/gltf-pipeline.cjs +9 -9
  225. package/dist/compiler/gltf-pipeline.js +2 -2
  226. package/dist/compiler/godot.cjs +10 -9
  227. package/dist/compiler/godot.js +9 -8
  228. package/dist/compiler/incremental.cjs +11 -11
  229. package/dist/compiler/incremental.js +6 -6
  230. package/dist/compiler/index.cjs +2585 -3273
  231. package/dist/compiler/index.d.ts +149 -35
  232. package/dist/compiler/index.js +2197 -3102
  233. package/dist/compiler/ios.cjs +11 -11
  234. package/dist/compiler/ios.js +9 -9
  235. package/dist/compiler/llm-provider-capabilities.cjs +9 -9
  236. package/dist/compiler/llm-provider-capabilities.js +6 -6
  237. package/dist/compiler/nodetoy.cjs +1 -1
  238. package/dist/compiler/nodetoy.js +1 -1
  239. package/dist/compiler/openxr.cjs +11 -10
  240. package/dist/compiler/openxr.js +10 -9
  241. package/dist/compiler/remotion.cjs +1 -1
  242. package/dist/compiler/remotion.js +1 -1
  243. package/dist/compiler/reproducibility.cjs +1 -1
  244. package/dist/compiler/reproducibility.js +1 -1
  245. package/dist/compiler/sdf.cjs +11 -10
  246. package/dist/compiler/sdf.js +9 -8
  247. package/dist/compiler/semantic-scene.cjs +7 -7
  248. package/dist/compiler/semantic-scene.js +2 -2
  249. package/dist/compiler/state.cjs +9 -9
  250. package/dist/compiler/state.js +7 -7
  251. package/dist/compiler/trait-composition.cjs +11 -11
  252. package/dist/compiler/trait-composition.js +7 -7
  253. package/dist/compiler/traits/ProvenanceSemiring.d.ts +167 -0
  254. package/dist/compiler/traits/Semiring.d.ts +26 -0
  255. package/dist/compiler/unity.cjs +11 -10
  256. package/dist/compiler/unity.js +10 -9
  257. package/dist/compiler/unreal.cjs +12 -11
  258. package/dist/compiler/unreal.js +10 -9
  259. package/dist/compiler/urdf.cjs +18 -17
  260. package/dist/compiler/urdf.js +9 -8
  261. package/dist/compiler/usd-physics.cjs +11 -10
  262. package/dist/compiler/usd-physics.js +8 -7
  263. package/dist/compiler/visionos.cjs +11 -10
  264. package/dist/compiler/visionos.js +10 -9
  265. package/dist/compiler/vrchat.cjs +11 -10
  266. package/dist/compiler/vrchat.js +9 -8
  267. package/dist/compiler/wasm.cjs +14 -13
  268. package/dist/compiler/wasm.js +9 -8
  269. package/dist/compiler/webgpu.cjs +10 -9
  270. package/dist/compiler/webgpu.js +9 -8
  271. package/dist/constants.cjs +398 -0
  272. package/dist/constants.js +9 -0
  273. package/dist/coordinators/index.cjs +4 -1
  274. package/dist/coordinators/index.js +4 -1
  275. package/dist/debugger.cjs +11 -9
  276. package/dist/debugger.js +9 -7
  277. package/dist/{dist-ACXG6IH5.cjs → dist-GRMOP2UL.cjs} +341 -65
  278. package/dist/{dist-VD4L6V7Q.js → dist-ZBUKU2JG.js} +333 -63
  279. package/dist/entries/interop.cjs +23 -23
  280. package/dist/entries/interop.js +3 -3
  281. package/dist/entries/scripting.cjs +12 -11
  282. package/dist/entries/scripting.js +8 -7
  283. package/dist/evolution/index.cjs +66 -0
  284. package/dist/evolution/index.d.ts +162 -0
  285. package/dist/evolution/index.js +17 -0
  286. package/dist/hololand/index.cjs +41 -37
  287. package/dist/hololand/index.js +3 -3
  288. package/dist/index.cjs +12394 -3224
  289. package/dist/index.d.ts +260 -18
  290. package/dist/index.js +10755 -2182
  291. package/dist/keyword-registry/PluginKeywordRegistry.d.ts +138 -0
  292. package/dist/keyword-registry/index.cjs +29 -0
  293. package/dist/keyword-registry/index.d.ts +1 -0
  294. package/dist/keyword-registry/index.js +4 -0
  295. package/dist/math/tropical-spmv.cjs +11 -11
  296. package/dist/math/tropical-spmv.d.ts +1 -0
  297. package/dist/math/tropical-spmv.js +2 -2
  298. package/dist/math/tropicalSpmv.d.ts +43 -0
  299. package/dist/math/vec3.cjs +1 -1
  300. package/dist/math/vec3.js +1 -1
  301. package/dist/matter/StagedMatter.d.ts +82 -0
  302. package/dist/matter/index.cjs +17 -0
  303. package/dist/matter/index.d.ts +1 -0
  304. package/dist/matter/index.js +4 -0
  305. package/dist/{ml-dsa-Z7JDKW4L.js → ml-dsa-J6VKVT4K.js} +3 -3
  306. package/dist/{ml-dsa-FSKBTE3W.cjs → ml-dsa-MTIK4ZUQ.cjs} +23 -23
  307. package/dist/paper-0c-spike/index.cjs +1 -1
  308. package/dist/paper-0c-spike/index.js +1 -1
  309. package/dist/parameter-envelope/ParameterEnvelope.d.ts +128 -0
  310. package/dist/parameter-envelope/index.cjs +17 -0
  311. package/dist/parameter-envelope/index.d.ts +2 -0
  312. package/dist/parameter-envelope/index.js +4 -0
  313. package/dist/parser/HoloCompositionTypes.d.ts +2013 -0
  314. package/dist/parser/PipelineParser.d.ts +162 -0
  315. package/dist/parser.cjs +36 -20
  316. package/dist/parser.js +13 -9
  317. package/dist/plugin-manifest/ManifestAutoLoader.d.ts +35 -0
  318. package/dist/plugin-manifest/PluginManifest.d.ts +156 -0
  319. package/dist/plugin-manifest/index.cjs +25 -0
  320. package/dist/plugin-manifest/index.d.ts +2 -0
  321. package/dist/plugin-manifest/index.js +4 -0
  322. package/dist/plugin-solver-contract/PluginSolverContract.d.ts +288 -0
  323. package/dist/plugin-solver-contract/index.cjs +41 -0
  324. package/dist/plugin-solver-contract/index.d.ts +1 -0
  325. package/dist/plugin-solver-contract/index.js +4 -0
  326. package/dist/policy/ContentPolicyGate.d.ts +51 -0
  327. package/dist/policy/PolicyPack.d.ts +120 -0
  328. package/dist/policy/blocklist.d.ts +32 -0
  329. package/dist/policy/defaults.d.ts +44 -0
  330. package/dist/policy/index.cjs +106 -0
  331. package/dist/policy/index.d.ts +17 -0
  332. package/dist/policy/index.js +5 -0
  333. package/dist/policy/jsonLogic.d.ts +31 -0
  334. package/dist/policy/types.d.ts +174 -0
  335. package/dist/proof-composition/ProofCompositionLaw.d.ts +93 -0
  336. package/dist/proof-composition/index.cjs +25 -0
  337. package/dist/proof-composition/index.d.ts +1 -0
  338. package/dist/proof-composition/index.js +4 -0
  339. package/dist/receipts/hash-policy.d.ts +85 -0
  340. package/dist/reconstruction/index.cjs +75 -47
  341. package/dist/reconstruction/index.js +5 -5
  342. package/dist/runtime/plugin-trait-registrar.d.ts +36 -0
  343. package/dist/runtime.cjs +81 -79
  344. package/dist/runtime.js +9 -7
  345. package/dist/scene-presets-EDKYZ5GW.js +4 -0
  346. package/dist/scene-presets-NCW2CFRS.cjs +17 -0
  347. package/dist/self-improvement/index.cjs +1 -1
  348. package/dist/self-improvement/index.js +1 -1
  349. package/dist/{src-PT2FERDV.cjs → src-G3D7ZATQ.cjs} +545 -21
  350. package/dist/{src-J6CM4AUR.js → src-UXYA7HM6.js} +539 -16
  351. package/dist/storage/index.cjs +10 -10
  352. package/dist/storage/index.js +3 -3
  353. package/dist/testing.cjs +1 -1
  354. package/dist/testing.js +1 -1
  355. package/dist/tools/index.cjs +3631 -0
  356. package/dist/tools/index.js +3581 -0
  357. package/dist/traitDocs/traitDocs.cjs +9 -9
  358. package/dist/traitDocs/traitDocs.d.ts +1 -0
  359. package/dist/traitDocs/traitDocs.js +3 -3
  360. package/dist/traits/ControlLoopTrait.d.ts +154 -0
  361. package/dist/traits/KinematicChainTrait.d.ts +116 -0
  362. package/dist/traits/SensorSamplingTrait.d.ts +154 -0
  363. package/dist/traits/TraitTypes.d.ts +270 -0
  364. package/dist/traits/TransactionTrait.d.ts +121 -0
  365. package/dist/traits/botanical-lotus.cjs +54 -50
  366. package/dist/traits/botanical-lotus.js +2 -5
  367. package/dist/traits/control-loop.cjs +21 -0
  368. package/dist/traits/control-loop.d.ts +1 -0
  369. package/dist/traits/control-loop.js +4 -0
  370. package/dist/traits/engines/cloth-verlet.d.ts +65 -0
  371. package/dist/traits/engines/index.cjs +19 -19
  372. package/dist/traits/engines/index.d.ts +15 -275
  373. package/dist/traits/engines/index.js +3 -3
  374. package/dist/traits/engines/motion-data-schema.d.ts +119 -0
  375. package/dist/traits/engines/motion-matching.d.ts +102 -0
  376. package/dist/traits/engines/noise.d.ts +25 -0
  377. package/dist/traits/engines/onnx-adapter.d.ts +173 -0
  378. package/dist/traits/engines/onnx-motion-matching.d.ts +163 -0
  379. package/dist/traits/engines/pfnn-network.d.ts +92 -0
  380. package/dist/traits/engines/synthetic-walk-cycle.d.ts +38 -0
  381. package/dist/traits/engines/tensor-ops.d.ts +15 -0
  382. package/dist/traits/index.cjs +2789 -1259
  383. package/dist/traits/index.d.ts +35 -0
  384. package/dist/traits/index.js +1692 -411
  385. package/dist/traits/kinematic-chain.cjs +25 -0
  386. package/dist/traits/kinematic-chain.d.ts +1 -0
  387. package/dist/traits/kinematic-chain.js +4 -0
  388. package/dist/traits/sensor-sampling.cjs +33 -0
  389. package/dist/traits/sensor-sampling.d.ts +1 -0
  390. package/dist/traits/sensor-sampling.js +4 -0
  391. package/dist/traits/simulation-solver-factory.cjs +1 -1
  392. package/dist/traits/simulation-solver-factory.js +1 -1
  393. package/dist/traits/transaction.cjs +29 -0
  394. package/dist/traits/transaction.d.ts +1 -0
  395. package/dist/traits/transaction.js +4 -0
  396. package/dist/traits/webcam-gaze.cjs +1 -1
  397. package/dist/traits/webcam-gaze.js +1 -1
  398. package/dist/type-checker.cjs +7 -6
  399. package/dist/type-checker.js +5 -4
  400. package/dist/types/AdvancedTypeSystem.d.ts +489 -0
  401. package/dist/types/HoloScriptPlus.d.ts +810 -0
  402. package/dist/types/base.d.ts +248 -0
  403. package/dist/types.d.ts +799 -0
  404. package/dist/world/index.cjs +3 -4
  405. package/dist/world/index.js +3 -4
  406. package/dist/world-model/index.cjs +1 -1
  407. package/dist/world-model/index.js +1 -1
  408. package/dist/wot/index.cjs +1 -1
  409. package/dist/wot/index.js +1 -1
  410. package/package.json +80 -13
  411. package/dist/GLTFPipeline-3EJLL3TS.cjs +0 -38
  412. package/dist/GLTFPipeline-3OWJV2VK.js +0 -17
  413. package/dist/HoloScriptPlusParser-ADWRY5OS.cjs +0 -698
  414. package/dist/HoloScriptPlusParser-JLJDXHSC.js +0 -693
  415. package/dist/HoloScriptPlusParser-QCGFPWIL.cjs +0 -27
  416. package/dist/HoloScriptPlusParser-WENAFEFV.js +0 -10
  417. package/dist/HoloScriptRuntime-GGRVEU4T.cjs +0 -19
  418. package/dist/HoloScriptRuntime-GJK6VJPH.js +0 -10
  419. package/dist/chunk-22Q5A6RV.js +0 -979
  420. package/dist/chunk-4C57PR42.js +0 -468
  421. package/dist/chunk-4W5G5QVL.cjs +0 -847
  422. package/dist/chunk-5ET6L4NS.js +0 -487
  423. package/dist/chunk-C4GSLCHE.cjs +0 -7153
  424. package/dist/chunk-F2G6CWFT.js +0 -7089
  425. package/dist/chunk-G6PNEASF.cjs +0 -814
  426. package/dist/chunk-GTA4Q3A3.js +0 -1491
  427. package/dist/chunk-HCCQLAA4.cjs +0 -74
  428. package/dist/chunk-HFSVMKM3.cjs +0 -72
  429. package/dist/chunk-KAIVDEIG.cjs +0 -4539
  430. package/dist/chunk-KQU64CIX.cjs +0 -1508
  431. package/dist/chunk-MSYSQ2AJ.js +0 -4533
  432. package/dist/chunk-NHJLP37F.js +0 -70
  433. package/dist/chunk-NHYRRAGI.cjs +0 -490
  434. package/dist/chunk-OIQYIIO3.cjs +0 -473
  435. package/dist/chunk-OL46QLBJ.js +0 -61
  436. package/dist/chunk-SKZPC5AG.cjs +0 -984
  437. package/dist/chunk-SLHLXUMO.js +0 -445
  438. package/dist/chunk-UOIGFQXC.cjs +0 -9750
  439. package/dist/chunk-UOL6Y5TD.cjs +0 -759
  440. package/dist/chunk-UVFI7XIR.cjs +0 -452
  441. package/dist/chunk-VEPGBETF.js +0 -844
  442. package/dist/chunk-XQ5MWMP2.js +0 -756
  443. package/dist/chunk-XT6JY5W5.js +0 -9684
  444. package/dist/chunk-YRRAUB35.js +0 -811
  445. package/dist/compiler/GasOptimizationAnalyzer.d.ts +0 -73
  446. package/dist/compiler/NFTMarketplaceCompiler.d.ts +0 -23
  447. package/dist/compiler/ar.cjs +0 -23
  448. package/dist/compiler/ar.js +0 -11
  449. package/dist/compiler/babylon.cjs +0 -21
  450. package/dist/compiler/babylon.js +0 -15
  451. package/dist/compiler/multi-layer.cjs +0 -24
  452. package/dist/compiler/multi-layer.js +0 -15
  453. package/dist/compiler/playcanvas.cjs +0 -19
  454. package/dist/compiler/playcanvas.js +0 -13
  455. package/dist/compiler/r3f.cjs +0 -39
  456. package/dist/compiler/r3f.d.ts +0 -22
  457. package/dist/compiler/r3f.js +0 -17
  458. package/dist/compiler/vrr.cjs +0 -24
  459. package/dist/compiler/vrr.js +0 -12
  460. package/dist/parser/NFTMarketplaceTypes.d.ts +0 -191
  461. package/dist/playwright-3AT3AKTV.cjs +0 -98673
  462. package/dist/playwright-VZPDVUEQ.js +0 -98660
@@ -1,7 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunk6PRZIHGL_cjs = require('./chunk-6PRZIHGL.cjs');
4
- var chunk3SKLAUDD_cjs = require('./chunk-3SKLAUDD.cjs');
3
+ var chunkOV6HHKLE_cjs = require('./chunk-OV6HHKLE.cjs');
4
+ var chunkYP5CHEYU_cjs = require('./chunk-YP5CHEYU.cjs');
5
+ var chunkOMNHTCS4_cjs = require('./chunk-OMNHTCS4.cjs');
6
+ var chunkEI3J6LTW_cjs = require('./chunk-EI3J6LTW.cjs');
7
+ var chunkNTQRFOPP_cjs = require('./chunk-NTQRFOPP.cjs');
5
8
  var crypto = require('crypto');
6
9
 
7
10
  function _interopNamespace(e) {
@@ -24,6 +27,30 @@ function _interopNamespace(e) {
24
27
 
25
28
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
26
29
 
30
+ // src/traits/FrameDeclarationTrait.ts
31
+ var DEFAULT_FRAME = {
32
+ domain: "*",
33
+ horizon: "",
34
+ capability_tier: 2,
35
+ trust_tier: 2};
36
+ function coerceConfig(raw) {
37
+ const domain = typeof raw.domain === "string" ? raw.domain : DEFAULT_FRAME.domain;
38
+ const horizon = typeof raw.horizon === "string" ? raw.horizon : DEFAULT_FRAME.horizon;
39
+ let capability_tier = DEFAULT_FRAME.capability_tier;
40
+ const rawCT = raw.capability_tier;
41
+ if (rawCT === 0 || rawCT === 1 || rawCT === 2 || rawCT === 3) {
42
+ capability_tier = rawCT;
43
+ }
44
+ let trust_tier = DEFAULT_FRAME.trust_tier;
45
+ const rawTT = raw.trust_tier;
46
+ if (rawTT === 0 || rawTT === 1 || rawTT === 2 || rawTT === 3) {
47
+ trust_tier = rawTT;
48
+ }
49
+ const allowed_tools = Array.isArray(raw.allowed_tools) ? raw.allowed_tools.filter((t) => typeof t === "string") : [];
50
+ const denied_domains = Array.isArray(raw.denied_domains) ? raw.denied_domains.filter((d) => typeof d === "string") : [];
51
+ return { domain, horizon, capability_tier, trust_tier, allowed_tools, denied_domains };
52
+ }
53
+
27
54
  // src/parser/HybridChunker.ts
28
55
  function countTokens(text) {
29
56
  return Math.ceil(text.length / 4);
@@ -983,7 +1010,7 @@ function similarity(a, b) {
983
1010
  function findSimilarTrait(input, threshold = 0.5) {
984
1011
  let bestMatch;
985
1012
  let bestScore = threshold;
986
- for (const trait of chunk3SKLAUDD_cjs.VR_TRAITS) {
1013
+ for (const trait of chunkEI3J6LTW_cjs.VR_TRAITS) {
987
1014
  const score = similarity(input, trait);
988
1015
  if (score > bestScore) {
989
1016
  bestScore = score;
@@ -1164,13 +1191,18 @@ var Lexer = class {
1164
1191
  this.tokens.push(this.createToken("DEDENT", ""));
1165
1192
  this.pendingDedents--;
1166
1193
  }
1194
+ if (this.column === 1) {
1195
+ const beforePos = this.pos;
1196
+ const beforeTokenCount = this.tokens.length;
1197
+ const beforePendingDedents = this.pendingDedents;
1198
+ this.handleIndentation();
1199
+ if (this.pos !== beforePos || this.tokens.length !== beforeTokenCount || this.pendingDedents !== beforePendingDedents) {
1200
+ continue;
1201
+ }
1202
+ }
1167
1203
  const char = this.source[this.pos];
1168
1204
  if (char === " " || char === " ") {
1169
- if (this.column === 1) {
1170
- this.handleIndentation();
1171
- } else {
1172
- this.advance();
1173
- }
1205
+ this.advance();
1174
1206
  continue;
1175
1207
  }
1176
1208
  if (char === "/" && this.peek(1) === "/") {
@@ -1776,19 +1808,21 @@ var Lexer = class {
1776
1808
  return this.isIdentifierStart(char) || this.isDigit(char) || char === "-";
1777
1809
  }
1778
1810
  };
1779
- var HoloScriptPlusParser = class {
1811
+ var HoloScriptPlusParser = class _HoloScriptPlusParser {
1780
1812
  constructor(options = {}) {
1781
1813
  this.tokens = [];
1782
1814
  this.pos = 0;
1783
1815
  this.source = "";
1784
1816
  this.errors = [];
1785
1817
  this.warnings = [];
1818
+ this.blockConfigDirectives = /* @__PURE__ */ new WeakSet();
1819
+ this.blockConfigDirectiveLocations = /* @__PURE__ */ new WeakMap();
1786
1820
  this.imports = [];
1787
1821
  this.hasState = false;
1788
1822
  this.hasVRTraits = false;
1789
1823
  this.hasControlFlow = false;
1790
1824
  this.compiledExpressions = /* @__PURE__ */ new Map();
1791
- this.errorRecovery = new chunk6PRZIHGL_cjs.ErrorRecovery();
1825
+ this.errorRecovery = new chunkOV6HHKLE_cjs.ErrorRecovery();
1792
1826
  /**
1793
1827
  * Internal incremental parser for parseIncremental.
1794
1828
  * Uses ChunkBasedIncrementalParser with AST-aware chunking and
@@ -1814,7 +1848,7 @@ var HoloScriptPlusParser = class {
1814
1848
  getQuickFixes() {
1815
1849
  const fixes = /* @__PURE__ */ new Map();
1816
1850
  for (const error of this.errors) {
1817
- const errorFixes = chunk6PRZIHGL_cjs.generateQuickFixes(
1851
+ const errorFixes = chunkOV6HHKLE_cjs.generateQuickFixes(
1818
1852
  {
1819
1853
  code: error.code,
1820
1854
  message: error.message,
@@ -1835,7 +1869,7 @@ var HoloScriptPlusParser = class {
1835
1869
  */
1836
1870
  getEnrichedErrors() {
1837
1871
  return this.errors.map(
1838
- (error) => chunk6PRZIHGL_cjs.enrichErrorWithSuggestions(
1872
+ (error) => chunkOV6HHKLE_cjs.enrichErrorWithSuggestions(
1839
1873
  {
1840
1874
  code: error.code,
1841
1875
  message: error.message,
@@ -1851,6 +1885,8 @@ var HoloScriptPlusParser = class {
1851
1885
  this.source = source;
1852
1886
  this.errors = [];
1853
1887
  this.warnings = [];
1888
+ this.blockConfigDirectives = /* @__PURE__ */ new WeakSet();
1889
+ this.blockConfigDirectiveLocations = /* @__PURE__ */ new WeakMap();
1854
1890
  this.imports = [];
1855
1891
  this.hasState = false;
1856
1892
  this.hasVRTraits = false;
@@ -1861,8 +1897,110 @@ var HoloScriptPlusParser = class {
1861
1897
  const lexer = new Lexer(source);
1862
1898
  this.tokens = lexer.tokenize();
1863
1899
  const root = this.parseDocument();
1900
+ this.desugarSafeDaemon(root);
1864
1901
  return this.buildResult(root);
1865
1902
  }
1903
+ /** Canonical safety-trait configs that `@safe_daemon` expands into. */
1904
+ static safeDaemonDefaults() {
1905
+ return {
1906
+ rate_limiter: { strategy: "token_bucket", max_tokens: 20, refill_rate: 4, window_ms: 6e4 },
1907
+ circuit_breaker: {
1908
+ failure_threshold: 5,
1909
+ window_ms: 3e5,
1910
+ reset_timeout_ms: 6e5,
1911
+ success_threshold: 2,
1912
+ failure_rate_threshold: 0,
1913
+ min_requests: 5
1914
+ },
1915
+ timeout_guard: { default_timeout_ms: 3e4, fallback_action: "abort" },
1916
+ economy: {
1917
+ initial_balance: 5,
1918
+ default_spend_limit: 1,
1919
+ spend_limit_period: 36e5,
1920
+ max_transaction_history: 200,
1921
+ escrow_enabled: false
1922
+ },
1923
+ structured_logger: {
1924
+ min_level: "info",
1925
+ max_entries: 500,
1926
+ rotation_count: 100,
1927
+ emit_events: true,
1928
+ console_output: true
1929
+ }
1930
+ };
1931
+ }
1932
+ /**
1933
+ * Expand a `@safe_daemon { ... }` config into the five safety traits it
1934
+ * stands for (@rate_limiter + @circuit_breaker + @timeout_guard + @economy +
1935
+ * @structured_logger). Supports flat convenience overrides (budget / rate /
1936
+ * timeout_ms / …) and nested per-trait overrides (economy: { ... }).
1937
+ */
1938
+ expandSafeDaemon(config) {
1939
+ const c = config && typeof config === "object" ? config : {};
1940
+ const out = _HoloScriptPlusParser.safeDaemonDefaults();
1941
+ const num = (v) => typeof v === "number";
1942
+ if (num(c.budget)) out.economy.initial_balance = c.budget;
1943
+ if (num(c.spend_limit)) out.economy.default_spend_limit = c.spend_limit;
1944
+ if (num(c.rate)) out.rate_limiter.refill_rate = c.rate;
1945
+ if (num(c.max_tokens)) out.rate_limiter.max_tokens = c.max_tokens;
1946
+ if (num(c.window_ms)) out.rate_limiter.window_ms = c.window_ms;
1947
+ if (num(c.failure_threshold)) out.circuit_breaker.failure_threshold = c.failure_threshold;
1948
+ if (num(c.reset_timeout_ms)) out.circuit_breaker.reset_timeout_ms = c.reset_timeout_ms;
1949
+ if (num(c.timeout_ms)) out.timeout_guard.default_timeout_ms = c.timeout_ms;
1950
+ if (typeof c.log_level === "string") out.structured_logger.min_level = c.log_level;
1951
+ for (const t of ["rate_limiter", "circuit_breaker", "timeout_guard", "economy", "structured_logger"]) {
1952
+ const override = c[t];
1953
+ if (override && typeof override === "object") Object.assign(out[t], override);
1954
+ }
1955
+ return Object.entries(out);
1956
+ }
1957
+ /**
1958
+ * Walk the parsed AST and expand every `@safe_daemon` into its five safety
1959
+ * traits, wherever traits are stored: a node's `traits` Map (composition /
1960
+ * world / object), a brain's `traits` Record, and any `directives` array.
1961
+ * Existing per-trait declarations are not overwritten.
1962
+ */
1963
+ desugarSafeDaemon(root) {
1964
+ const seen = /* @__PURE__ */ new Set();
1965
+ const visit = (node) => {
1966
+ if (!node || typeof node !== "object" || seen.has(node)) return;
1967
+ seen.add(node);
1968
+ const n = node;
1969
+ if (n.traits instanceof Map && n.traits.has("safe_daemon")) {
1970
+ const cfg = n.traits.get("safe_daemon");
1971
+ n.traits.delete("safe_daemon");
1972
+ for (const [name, c] of this.expandSafeDaemon(cfg)) {
1973
+ if (!n.traits.has(name)) n.traits.set(name, c);
1974
+ }
1975
+ this.hasVRTraits = true;
1976
+ }
1977
+ if (n.traits && !(n.traits instanceof Map) && typeof n.traits === "object") {
1978
+ const rec = n.traits;
1979
+ if ("safe_daemon" in rec) {
1980
+ const cfg = rec["safe_daemon"];
1981
+ delete rec["safe_daemon"];
1982
+ for (const [name, c] of this.expandSafeDaemon(cfg)) {
1983
+ if (!(name in rec)) rec[name] = c;
1984
+ }
1985
+ }
1986
+ }
1987
+ if (Array.isArray(n.directives)) {
1988
+ const dirs = n.directives;
1989
+ const idx = dirs.findIndex((d) => d && d.type === "trait" && d.name === "safe_daemon");
1990
+ if (idx >= 0) {
1991
+ const cfg = dirs[idx].config;
1992
+ const expanded = this.expandSafeDaemon(cfg).map(([name, c]) => ({ type: "trait", name, config: c }));
1993
+ const existing = new Set(dirs.map((d) => d.name));
1994
+ dirs.splice(idx, 1, ...expanded.filter((e) => !existing.has(e.name)));
1995
+ }
1996
+ }
1997
+ for (const key of ["children", "body", "states"]) {
1998
+ const child = n[key];
1999
+ if (Array.isArray(child)) child.forEach(visit);
2000
+ }
2001
+ };
2002
+ visit(root);
2003
+ }
1866
2004
  /**
1867
2005
  * Performs an incremental parse using ChunkBasedIncrementalParser with
1868
2006
  * AST-aware chunking, hash-based caching, and dependency tracking.
@@ -2036,28 +2174,48 @@ var HoloScriptPlusParser = class {
2036
2174
  }
2037
2175
  const isNodeStart = this.check("IDENTIFIER") || this.check("STATE_MACHINE") || this.check("STATE") || this.check("TRANSITION") || this.check("INITIAL");
2038
2176
  if (isNodeStart) {
2039
- const node = this.parseNode();
2040
- const existingDirectives = node.directives || [];
2041
- node.directives = [...currentDirectives, ...existingDirectives];
2042
- if (node.type === "template") {
2043
- for (const d of currentDirectives) {
2044
- if (d.type === "version") {
2045
- node.version = d.version;
2046
- } else if (d.type === "migrate") {
2047
- if (!node.migrations) node.migrations = [];
2048
- node.migrations.push({
2049
- type: "Migration",
2050
- fromVersion: d.fromVersion,
2051
- body: d.body
2052
- });
2177
+ if (this.check("IDENTIFIER") && this.current().value === "connect") {
2178
+ const connectNode = this.parseHsConnectStatement();
2179
+ topLevelNodes.push(connectNode);
2180
+ } else if (this.check("IDENTIFIER") && this.current().value === "execute") {
2181
+ const executeNode = this.parseHsExecuteStatement();
2182
+ topLevelNodes.push(executeNode);
2183
+ } else if (this.check("IDENTIFIER") && chunkYP5CHEYU_cjs.isBrainKeyword(this.current().value)) {
2184
+ const brainNode = this.parseBrainDeclaration();
2185
+ brainNode.directives = [
2186
+ ...currentDirectives,
2187
+ ...brainNode.directives || []
2188
+ ];
2189
+ topLevelNodes.push(brainNode);
2190
+ } else {
2191
+ const node = this.parseNode();
2192
+ const existingDirectives = node.directives || [];
2193
+ node.directives = [...currentDirectives, ...existingDirectives];
2194
+ if (node.type === "template") {
2195
+ for (const d of currentDirectives) {
2196
+ if (d.type === "version") {
2197
+ node.version = d.version;
2198
+ } else if (d.type === "migrate") {
2199
+ if (!node.migrations) node.migrations = [];
2200
+ node.migrations.push({
2201
+ type: "Migration",
2202
+ fromVersion: d.fromVersion,
2203
+ body: d.body
2204
+ });
2205
+ }
2053
2206
  }
2054
2207
  }
2208
+ topLevelNodes.push(node);
2055
2209
  }
2056
- topLevelNodes.push(node);
2057
2210
  } else {
2058
2211
  if (currentDirectives.length > 0) {
2059
2212
  if (this.check("EOF")) {
2060
2213
  globalDirectives.push(...currentDirectives);
2214
+ } else if (this.check("LBRACE")) {
2215
+ const block = this.parseBlockContent();
2216
+ const last = currentDirectives[currentDirectives.length - 1];
2217
+ last.config = { ...last.config || {}, ...block };
2218
+ globalDirectives.push(...currentDirectives);
2061
2219
  } else {
2062
2220
  this.error(
2063
2221
  `Expected node after directives, got ${this.current().type}. Valid nodes: orb, template, logic, object, world, composition, scene, group`,
@@ -2073,21 +2231,6 @@ var HoloScriptPlusParser = class {
2073
2231
  throw new Error("ParseError");
2074
2232
  }
2075
2233
  }
2076
- if (this.check("IDENTIFIER") && this.current().value === "connect") {
2077
- const connection = this.parseConnectionStatement();
2078
- const node = {
2079
- type: "connection",
2080
- properties: connection,
2081
- directives: [],
2082
- children: [],
2083
- traits: /* @__PURE__ */ new Map(),
2084
- loc: {
2085
- start: { line: this.current().line, column: 0 },
2086
- end: { line: this.current().line, column: 0 }
2087
- }
2088
- };
2089
- topLevelNodes.push(node);
2090
- }
2091
2234
  } catch (e) {
2092
2235
  const errorMessage = e instanceof Error ? e.message : String(e);
2093
2236
  if (errorMessage !== "ParseError" && errorMessage !== "Unexpected token") {
@@ -2127,7 +2270,12 @@ var HoloScriptPlusParser = class {
2127
2270
  ]) || this.expect("IDENTIFIER", "Expected element type");
2128
2271
  const type = typeToken.value;
2129
2272
  if (type === "template") {
2130
- const templateName = this.expect("STRING", "Expected template name").value;
2273
+ let templateName;
2274
+ if (this.check("IDENTIFIER")) {
2275
+ templateName = this.advance().value;
2276
+ } else {
2277
+ templateName = this.expect("STRING", "Expected template name").value;
2278
+ }
2131
2279
  const templateBody = this.parseBlockContent();
2132
2280
  let version;
2133
2281
  const migrations = [];
@@ -2189,6 +2337,20 @@ var HoloScriptPlusParser = class {
2189
2337
  }
2190
2338
  };
2191
2339
  }
2340
+ if (type === "react") {
2341
+ return this.parseHsPlusReactBlock(startToken);
2342
+ }
2343
+ if (["transform", "filter", "branch", "validate"].includes(type)) {
2344
+ const savedPos = this.pos;
2345
+ let blockName = "anonymous";
2346
+ if (this.check("IDENTIFIER") || this.check("STRING")) {
2347
+ blockName = this.advance().value;
2348
+ }
2349
+ if (this.check("LBRACE")) {
2350
+ return this.parsePipelineBlock(type, blockName, startToken);
2351
+ }
2352
+ this.pos = savedPos;
2353
+ }
2192
2354
  if ([
2193
2355
  "module",
2194
2356
  "script",
@@ -2242,6 +2404,9 @@ var HoloScriptPlusParser = class {
2242
2404
  if (type === "assert" || startToken.type === "ASSERT") {
2243
2405
  return this.parseAssertNode();
2244
2406
  }
2407
+ if (type === "timeline") {
2408
+ return this.parseTimelineNode(startToken);
2409
+ }
2245
2410
  if (type === "environment") {
2246
2411
  const envBody = this.parseEnvironmentBlock();
2247
2412
  return {
@@ -2326,6 +2491,7 @@ var HoloScriptPlusParser = class {
2326
2491
  const children = [];
2327
2492
  const directives = [];
2328
2493
  const traits = /* @__PURE__ */ new Map();
2494
+ let ambiguousPreBodyTrait = null;
2329
2495
  if (templateRef) {
2330
2496
  properties.__templateRef = templateRef;
2331
2497
  }
@@ -2345,6 +2511,9 @@ var HoloScriptPlusParser = class {
2345
2511
  traits.set(directive.name, directive.config);
2346
2512
  this.hasVRTraits = true;
2347
2513
  directives.push(directive);
2514
+ if (this.blockConfigDirectives.has(directive) && this.traitConfigLooksLikeNodeBody(directive.config)) {
2515
+ ambiguousPreBodyTrait = directive;
2516
+ }
2348
2517
  } else {
2349
2518
  directives.push(directive);
2350
2519
  }
@@ -2395,6 +2564,13 @@ var HoloScriptPlusParser = class {
2395
2564
  this.synchronizeProperty();
2396
2565
  }
2397
2566
  }
2567
+ if (!this.check("LBRACE") && ambiguousPreBodyTrait) {
2568
+ this.errorAt(
2569
+ this.blockConfigDirectiveLocations.get(ambiguousPreBodyTrait) || startToken,
2570
+ `Trait @${ambiguousPreBodyTrait.name} used a block that looks like an object body, but no object body follows. Use @${ambiguousPreBodyTrait.name}(...) for trait config, or add a separate { ... } object body.`,
2571
+ "HSP101"
2572
+ );
2573
+ }
2398
2574
  if (this.check("LBRACE")) {
2399
2575
  this.advance();
2400
2576
  this.skipNewlines();
@@ -2439,7 +2615,7 @@ var HoloScriptPlusParser = class {
2439
2615
  properties[key] = spreadNode;
2440
2616
  } else {
2441
2617
  const token = this.current();
2442
- const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "HASH" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
2618
+ const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "HASH" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "ON_ERROR" || token.type === "TRANSITION";
2443
2619
  if (isKeyToken) {
2444
2620
  const saved = this.pos;
2445
2621
  const name = this.advance().value;
@@ -2471,7 +2647,9 @@ var HoloScriptPlusParser = class {
2471
2647
  "on_entry",
2472
2648
  "on_exit",
2473
2649
  "page",
2474
- "include"
2650
+ "include",
2651
+ "brain",
2652
+ "react"
2475
2653
  ];
2476
2654
  if (name === "transition" && this.check("STRING")) {
2477
2655
  const event = this.advance().value;
@@ -2550,7 +2728,12 @@ var HoloScriptPlusParser = class {
2550
2728
  }
2551
2729
  if (this.check("COLON") || this.check("EQUALS")) {
2552
2730
  this.advance();
2553
- properties[name] = this.parseValue();
2731
+ const pipeNext = this.peek(1);
2732
+ if (this.check("PIPE") && (!pipeNext || pipeNext.type === "NEWLINE" || pipeNext.type === "EOF")) {
2733
+ properties[name] = this.parseBlockScalar(this.tokens[saved]);
2734
+ } else {
2735
+ properties[name] = this.parseValue();
2736
+ }
2554
2737
  } else if (childNodeKeywords.includes(name) && (this.check("LBRACE") || this.check("STRING"))) {
2555
2738
  this.pos = saved;
2556
2739
  children.push(this.parseNode());
@@ -2607,15 +2790,24 @@ var HoloScriptPlusParser = class {
2607
2790
  const isKeyword = ["STATE_MACHINE", "STATE", "ON_ENTRY", "ON_EXIT", "TRANSITION"].includes(
2608
2791
  nameToken.type
2609
2792
  );
2610
- if (nameToken.type !== "IDENTIFIER" && !isKeyword) {
2793
+ let name;
2794
+ if (nameToken.type === "IDENTIFIER" || isKeyword) {
2795
+ this.advance();
2796
+ name = nameToken.value;
2797
+ } else if (nameToken.type === "NUMBER" && /^\d+[a-zA-Z]\w*$/.test(nameToken.value)) {
2798
+ this.advance();
2799
+ name = nameToken.value;
2800
+ const next = this.current();
2801
+ if (next.type === "IDENTIFIER" && next.line === nameToken.line && next.column === nameToken.column + nameToken.value.length) {
2802
+ name += this.advance().value;
2803
+ }
2804
+ } else {
2611
2805
  this.error(
2612
2806
  `Expected directive name, got ${nameToken.type}. Directives start with @ followed by name (e.g., @grabbable)`,
2613
2807
  "HSP201"
2614
2808
  );
2615
2809
  return null;
2616
2810
  }
2617
- this.advance();
2618
- const name = nameToken.value;
2619
2811
  if (name === "version") {
2620
2812
  this.expect("LPAREN", "Expected ( after @version");
2621
2813
  const versionToken = this.expect("NUMBER", "Expected version number");
@@ -2635,20 +2827,149 @@ var HoloScriptPlusParser = class {
2635
2827
  const body = this.check("LBRACE") ? this.parseCodeBlock() : "";
2636
2828
  return { type: "migrate", fromVersion, body };
2637
2829
  }
2638
- if (chunk3SKLAUDD_cjs.VR_TRAITS.includes(name)) {
2830
+ if (name === "quest") {
2831
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2832
+ return { type: "quest", ...config2 };
2833
+ }
2834
+ if (name === "faction") {
2835
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2836
+ return { type: "faction", ...config2 };
2837
+ }
2838
+ if (name === "loot") {
2839
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2840
+ return { type: "loot", ...config2 };
2841
+ }
2842
+ if (name === "ability") {
2843
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2844
+ return { type: "ability", ...config2 };
2845
+ }
2846
+ if (name === "authority") {
2847
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2848
+ return { type: "authority", ...config2 };
2849
+ }
2850
+ if (name === "wallet_gated") {
2851
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2852
+ return { type: "wallet_gated", ...config2 };
2853
+ }
2854
+ if (name === "world_chunk") {
2855
+ const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
2856
+ return { type: "world_chunk", ...config2 };
2857
+ }
2858
+ if (name === "personality") {
2859
+ let value;
2860
+ if (this.check("IDENTIFIER")) {
2861
+ value = this.advance().value;
2862
+ } else if (this.check("STRING")) {
2863
+ value = this.advance().value;
2864
+ } else {
2865
+ value = "neutral";
2866
+ }
2867
+ return { type: "personality", value };
2868
+ }
2869
+ if (name === "faction_alignment") {
2870
+ let value;
2871
+ if (this.check("IDENTIFIER")) {
2872
+ value = this.advance().value;
2873
+ if (this.check("IDENTIFIER")) {
2874
+ value += "_" + this.advance().value;
2875
+ }
2876
+ } else if (this.check("STRING")) {
2877
+ value = this.advance().value;
2878
+ } else {
2879
+ value = "true_neutral";
2880
+ }
2881
+ return { type: "faction_alignment", value };
2882
+ }
2883
+ if (name === "memory_persistence") {
2884
+ let value = true;
2885
+ if (this.check("BOOLEAN")) {
2886
+ value = this.advance().value === "true";
2887
+ } else if (this.check("IDENTIFIER")) {
2888
+ const raw = this.advance().value;
2889
+ value = raw !== "false";
2890
+ }
2891
+ return { type: "memory_persistence", value };
2892
+ }
2893
+ if (name === "preferred_ability") {
2894
+ let abilityName;
2895
+ if (this.check("STRING")) {
2896
+ abilityName = this.advance().value;
2897
+ } else if (this.check("IDENTIFIER")) {
2898
+ abilityName = this.advance().value;
2899
+ } else {
2900
+ abilityName = "";
2901
+ }
2902
+ let when;
2903
+ if (this.check("AT")) {
2904
+ const saved = this.pos;
2905
+ this.advance();
2906
+ if (this.check("IDENTIFIER") && this.current().value === "when") {
2907
+ this.advance();
2908
+ if (this.check("LBRACE")) {
2909
+ when = this.parseCodeBlock();
2910
+ }
2911
+ } else {
2912
+ this.pos = saved;
2913
+ }
2914
+ }
2915
+ return { type: "preferred_ability", ability: abilityName, when };
2916
+ }
2917
+ if (name === "flee_threshold") {
2918
+ let value = 0.25;
2919
+ if (this.check("NUMBER")) {
2920
+ value = parseFloat(this.advance().value);
2921
+ }
2922
+ return { type: "flee_threshold", value };
2923
+ }
2924
+ if (name === "patrol_speed") {
2925
+ let value = 1;
2926
+ if (this.check("NUMBER")) {
2927
+ value = parseFloat(this.advance().value);
2928
+ } else if (this.check("IDENTIFIER")) {
2929
+ value = this.advance().value;
2930
+ }
2931
+ return { type: "patrol_speed", value };
2932
+ }
2933
+ if (name === "waypoints") {
2934
+ let points = [];
2935
+ if (this.check("LBRACKET")) {
2936
+ points = this.parseValue();
2937
+ } else if (this.check("LBRACE")) {
2938
+ points = this.parseBlockContent();
2939
+ }
2940
+ return { type: "waypoints", points };
2941
+ }
2942
+ if (chunkEI3J6LTW_cjs.VR_TRAITS.includes(name)) {
2639
2943
  if (!this.options.enableVRTraits) {
2640
2944
  this.warn(`VR trait @${name} is disabled`);
2641
2945
  return null;
2642
2946
  }
2643
2947
  let config2 = {};
2948
+ let configStyle2 = "none";
2644
2949
  if (this.check("LPAREN")) {
2950
+ configStyle2 = "paren";
2645
2951
  config2 = this.parseTraitConfig();
2646
2952
  } else if (this.check("LBRACE")) {
2953
+ configStyle2 = "block";
2647
2954
  config2 = this.parseBlockContent();
2955
+ } else if (this.check("COLON")) {
2956
+ configStyle2 = "colon";
2957
+ this.advance();
2958
+ if (this.check("LPAREN")) {
2959
+ config2 = this.parseTraitConfig();
2960
+ } else if (this.check("LBRACE")) {
2961
+ config2 = this.parseBlockContent();
2962
+ } else {
2963
+ config2 = { value: this.parseValue() };
2964
+ }
2965
+ }
2966
+ const directive2 = { type: "trait", name, config: config2 };
2967
+ if (configStyle2 === "block") {
2968
+ this.markBlockConfigDirective(directive2, nameToken);
2648
2969
  }
2649
- return this.parseTraitSumTail({ type: "trait", name, config: config2 });
2970
+ return this.parseTraitSumTail(directive2);
2650
2971
  }
2651
- if (chunk6PRZIHGL_cjs.LIFECYCLE_HOOKS.includes(name)) {
2972
+ if (chunkOMNHTCS4_cjs.LIFECYCLE_HOOKS.includes(name)) {
2652
2973
  const params = [];
2653
2974
  if (this.check("LPAREN")) {
2654
2975
  this.advance();
@@ -2753,15 +3074,22 @@ var HoloScriptPlusParser = class {
2753
3074
  this.warn("Expected 'from' after named import specifiers");
2754
3075
  }
2755
3076
  }
3077
+ let wildcardAlias;
2756
3078
  if (this.check("ASTERISK") || this.check("IDENTIFIER") && this.current().value === "*") {
2757
3079
  this.advance();
2758
3080
  isWildcard = true;
2759
3081
  if (this.check("IDENTIFIER") && this.current().value === "as") {
2760
3082
  this.advance();
3083
+ if (this.check("IDENTIFIER") && this.current().value !== "from") {
3084
+ wildcardAlias = this.advance().value;
3085
+ }
3086
+ }
3087
+ if (this.check("IDENTIFIER") && this.current().value === "from") {
3088
+ this.advance();
2761
3089
  }
2762
3090
  }
2763
3091
  const path = this.expect("STRING", "Expected import path string").value;
2764
- let alias = path.split("/").pop()?.replace(/\.[^.]+$/, "") || "import";
3092
+ let alias = wildcardAlias || path.split("/").pop()?.replace(/\.[^.]+$/, "") || "import";
2765
3093
  if (!namedImports && this.check("IDENTIFIER") && this.current().value === "as") {
2766
3094
  this.advance();
2767
3095
  alias = this.expect("IDENTIFIER", "Expected alias after as").value;
@@ -2957,7 +3285,7 @@ var HoloScriptPlusParser = class {
2957
3285
  return { type: "hololand_event", event: eventName, params };
2958
3286
  }
2959
3287
  }
2960
- if (chunk6PRZIHGL_cjs.STRUCTURAL_DIRECTIVES.includes(name)) {
3288
+ if (chunkOMNHTCS4_cjs.STRUCTURAL_DIRECTIVES.includes(name)) {
2961
3289
  let nodeName;
2962
3290
  if (this.check("STRING")) {
2963
3291
  nodeName = this.advance().value;
@@ -2971,9 +3299,12 @@ var HoloScriptPlusParser = class {
2971
3299
  this.warn(`Unknown directive @${name}`);
2972
3300
  }
2973
3301
  let config = {};
3302
+ let configStyle = "none";
2974
3303
  if (this.check("LPAREN")) {
3304
+ configStyle = "paren";
2975
3305
  config = this.parseTraitConfig();
2976
3306
  } else if (this.check("LBRACE")) {
3307
+ configStyle = "block";
2977
3308
  config = this.parseBlockContent();
2978
3309
  }
2979
3310
  if (this.check("COLON")) {
@@ -2984,7 +3315,32 @@ var HoloScriptPlusParser = class {
2984
3315
  config.body = this.parseCodeBlock();
2985
3316
  }
2986
3317
  }
2987
- return this.parseTraitSumTail({ type: "trait", name, config });
3318
+ const directive = { type: "trait", name, config };
3319
+ if (configStyle === "block") {
3320
+ this.markBlockConfigDirective(directive, nameToken);
3321
+ }
3322
+ return this.parseTraitSumTail(directive);
3323
+ }
3324
+ markBlockConfigDirective(directive, token) {
3325
+ this.blockConfigDirectives.add(directive);
3326
+ this.blockConfigDirectiveLocations.set(directive, token);
3327
+ }
3328
+ traitConfigLooksLikeNodeBody(config) {
3329
+ if (!config || typeof config !== "object") return false;
3330
+ const nodeBodyKeys = /* @__PURE__ */ new Set([
3331
+ "geometry",
3332
+ "position",
3333
+ "rotation",
3334
+ "scale",
3335
+ "size",
3336
+ "color",
3337
+ "material",
3338
+ "model",
3339
+ "mesh",
3340
+ "src",
3341
+ "url"
3342
+ ]);
3343
+ return Object.keys(config).some((key) => nodeBodyKeys.has(key));
2988
3344
  }
2989
3345
  parseTraitSumTail(first) {
2990
3346
  if (!this.check("PLUS")) {
@@ -3023,95 +3379,962 @@ var HoloScriptPlusParser = class {
3023
3379
  this.expect("RPAREN", "Expected )");
3024
3380
  return value;
3025
3381
  }
3026
- parseConnectionStatement() {
3027
- this.expect("IDENTIFIER", "Expected connect");
3028
- const from = this.expect("IDENTIFIER", "Expected from name").value;
3029
- this.expect("IDENTIFIER", "Expected to");
3030
- const to = this.expect("IDENTIFIER", "Expected to name").value;
3031
- return { from, to };
3032
- }
3382
+ // ===========================================================================
3383
+ // Brain Declaration Parsing
3384
+ // ===========================================================================
3033
3385
  /**
3034
- * Parse block content: { key: value, ... }
3386
+ * Parse a top-level `brain` declaration.
3387
+ *
3388
+ * Grammar:
3389
+ * brain <Name> [ : @<brainType> ] {
3390
+ * @personality <value>
3391
+ * @faction_alignment <value>
3392
+ * @memory_persistence true|false
3393
+ * @preferred_ability "<Name>" [ @when { <expr> } ]
3394
+ * @flee_threshold <number>
3395
+ * @patrol_speed <number|identifier>
3396
+ * @waypoints [...]
3397
+ * state <stateName> {
3398
+ * transition to <target> [ @when { <expr> } ]
3399
+ * <action statements ...>
3400
+ * }
3401
+ * }
3035
3402
  */
3036
- parseBlockContent() {
3037
- const content = {};
3403
+ parseBrainDeclaration() {
3404
+ this.advance();
3405
+ const name = this.check("IDENTIFIER") ? this.advance().value : "unnamed_brain";
3406
+ let brainType = "behavior_tree";
3407
+ if (this.check("COLON")) {
3408
+ this.advance();
3409
+ if (this.check("AT")) {
3410
+ this.advance();
3411
+ if (this.check("IDENTIFIER")) {
3412
+ const raw = this.advance().value;
3413
+ if (raw === "behavior_tree" || raw === "decision_tree" || raw === "neural" || raw === "scripted") {
3414
+ brainType = raw;
3415
+ }
3416
+ }
3417
+ }
3418
+ }
3419
+ const brain = {
3420
+ type: "brain",
3421
+ name,
3422
+ brainType,
3423
+ states: [],
3424
+ traits: {}
3425
+ };
3038
3426
  if (!this.check("LBRACE")) {
3039
- return content;
3427
+ this.warn(`brain "${name}" missing body block { }`);
3428
+ return brain;
3040
3429
  }
3041
3430
  this.advance();
3042
3431
  this.skipNewlines();
3043
3432
  while (!this.check("RBRACE") && !this.check("EOF")) {
3044
3433
  this.skipNewlines();
3045
3434
  if (this.check("RBRACE") || this.check("EOF")) break;
3046
- this.skipNewlines();
3047
- if (this.check("RBRACE") || this.check("EOF")) break;
3048
- const token = this.current();
3049
- const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
3050
- if (isKeyToken) {
3051
- const next = this.peek(1);
3052
- if (next.type === "COLON" || next.type === "EQUALS") {
3053
- const key = this.advance().value;
3054
- this.advance();
3055
- content[key] = this.parseValue();
3056
- } else if (next.type === "STRING" || next.type === "LBRACE" || next.type === "IDENTIFIER") {
3057
- const node = this.parseNode();
3058
- const type = node.type;
3059
- const name = node.name || `unnamed_${type}_${Object.keys(content).length}`;
3060
- content[name] = node;
3061
- } else {
3062
- const key = this.advance().value;
3063
- content[key] = true;
3064
- }
3065
- } else if (this.check("SPREAD")) {
3435
+ if (this.check("AT")) {
3066
3436
  this.advance();
3067
- const val = this.parseValue();
3068
- const spreadKey = `__spread_${Object.keys(content).length}`;
3069
- content[spreadKey] = { type: "spread", argument: val };
3070
- } else if (this.check("AT")) {
3071
- const directive = this.parseDirective();
3072
- if (directive) {
3073
- const dirKey = ("name" in directive ? directive.name : void 0) || directive.type;
3074
- content[`@${dirKey}`] = directive;
3437
+ if (!this.check("IDENTIFIER")) {
3438
+ this.warn("Expected directive name after @");
3439
+ continue;
3075
3440
  }
3076
- } else if (this.check("LBRACE")) {
3077
- let depth = 1;
3441
+ const dirName = this.advance().value;
3442
+ if (dirName === "personality") {
3443
+ const val = this.check("IDENTIFIER") ? this.advance().value : this.check("STRING") ? this.advance().value : "neutral";
3444
+ brain.personality = val;
3445
+ } else if (dirName === "faction_alignment") {
3446
+ let val = this.check("IDENTIFIER") ? this.advance().value : this.check("STRING") ? this.advance().value : "true_neutral";
3447
+ if (this.check("IDENTIFIER")) val += "_" + this.advance().value;
3448
+ brain.factionAlignment = val;
3449
+ } else if (dirName === "memory_persistence") {
3450
+ const raw = this.check("BOOLEAN") ? this.advance().value : this.check("IDENTIFIER") ? this.advance().value : "true";
3451
+ brain.memoryPersistence = raw !== "false";
3452
+ } else if (dirName === "preferred_ability") {
3453
+ const abilityName = this.check("STRING") ? this.advance().value : this.check("IDENTIFIER") ? this.advance().value : "";
3454
+ let when;
3455
+ if (this.check("AT")) {
3456
+ const saved = this.pos;
3457
+ this.advance();
3458
+ if (this.check("IDENTIFIER") && this.current().value === "when") {
3459
+ this.advance();
3460
+ if (this.check("LBRACE")) when = this.parseCodeBlock();
3461
+ } else {
3462
+ this.pos = saved;
3463
+ }
3464
+ }
3465
+ brain.preferredAbility = { name: abilityName, when };
3466
+ } else if (dirName === "flee_threshold") {
3467
+ brain.fleeThreshold = this.check("NUMBER") ? parseFloat(this.advance().value) : 0.25;
3468
+ } else if (dirName === "patrol_speed") {
3469
+ brain.patrolSpeed = this.check("NUMBER") ? parseFloat(this.advance().value) : this.check("IDENTIFIER") ? this.advance().value : 1;
3470
+ } else if (dirName === "waypoints") {
3471
+ brain.waypoints = this.check("LBRACKET") ? this.parseValue() : [];
3472
+ } else if (dirName === "goal") {
3473
+ const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
3474
+ if (!brain.goals) brain.goals = [];
3475
+ brain.goals.push({
3476
+ name: typeof cfg.name === "string" ? cfg.name : String(cfg.name ?? `goal_${brain.goals.length}`),
3477
+ desiredState: cfg.desiredState && typeof cfg.desiredState === "object" ? cfg.desiredState : void 0,
3478
+ priority: typeof cfg.priority === "number" ? cfg.priority : void 0
3479
+ });
3480
+ } else if (dirName === "escalation") {
3481
+ const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
3482
+ if (!brain.escalations) brain.escalations = [];
3483
+ brain.escalations.push({
3484
+ on: typeof cfg.on === "string" ? cfg.on : String(cfg.on ?? ""),
3485
+ action: typeof cfg.action === "string" ? cfg.action : "notify"
3486
+ });
3487
+ } else if (dirName === "provider_policy") {
3488
+ const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
3489
+ brain.providerPolicy = {
3490
+ prefer: typeof cfg.prefer === "string" ? cfg.prefer : void 0,
3491
+ fallback: typeof cfg.fallback === "string" ? cfg.fallback : void 0,
3492
+ requires: typeof cfg.requires === "string" ? cfg.requires : void 0
3493
+ };
3494
+ } else if (dirName === "frame_declaration") {
3495
+ const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
3496
+ brain.frameDeclaration = coerceConfig(cfg);
3497
+ } else if (dirName === "behavior_tree") {
3498
+ const config = this.check("LBRACE") ? this.parseBlockContent() : {};
3499
+ brain.traits["behavior_tree"] = config;
3500
+ } else {
3501
+ const config = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
3502
+ brain.traits[dirName] = config;
3503
+ }
3504
+ this.skipNewlines();
3505
+ continue;
3506
+ }
3507
+ if (this.check("STATE") || this.check("IDENTIFIER") && this.current().value === "state") {
3078
3508
  this.advance();
3079
- while (depth > 0 && !this.check("EOF")) {
3080
- if (this.check("LBRACE")) depth++;
3081
- if (this.check("RBRACE")) depth--;
3509
+ const stateName = this.check("IDENTIFIER") ? this.advance().value : "unnamed";
3510
+ const brainState = {
3511
+ name: stateName,
3512
+ transitions: [],
3513
+ actions: [],
3514
+ traits: {}
3515
+ };
3516
+ if (this.check("LBRACE")) {
3082
3517
  this.advance();
3518
+ this.skipNewlines();
3519
+ while (!this.check("RBRACE") && !this.check("EOF")) {
3520
+ this.skipNewlines();
3521
+ if (this.check("RBRACE") || this.check("EOF")) break;
3522
+ if (this.check("TRANSITION") || this.check("IDENTIFIER") && this.current().value === "transition") {
3523
+ this.advance();
3524
+ let to = "";
3525
+ if (this.check("IDENTIFIER") && this.current().value === "to") {
3526
+ this.advance();
3527
+ }
3528
+ if (this.check("IDENTIFIER")) to = this.advance().value;
3529
+ else if (this.check("STRING")) to = this.advance().value;
3530
+ let when;
3531
+ if (this.check("AT")) {
3532
+ const saved = this.pos;
3533
+ this.advance();
3534
+ if (this.check("IDENTIFIER") && this.current().value === "when") {
3535
+ this.advance();
3536
+ if (this.check("LBRACE")) when = this.parseCodeBlock();
3537
+ } else {
3538
+ this.pos = saved;
3539
+ }
3540
+ }
3541
+ brainState.transitions.push({ to, when });
3542
+ } else if (this.check("AT")) {
3543
+ this.advance();
3544
+ const innerDir = this.check("IDENTIFIER") ? this.advance().value : "";
3545
+ const config = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
3546
+ brainState.traits[innerDir] = config;
3547
+ } else if (this.check("IDENTIFIER") && chunkYP5CHEYU_cjs.isCognitiveVerb(this.current().value)) {
3548
+ const saved = this.pos;
3549
+ const verb = this.advance().value;
3550
+ if (this.check("LBRACE")) {
3551
+ const config = this.parseBlockContent();
3552
+ if (!brainState.cognitiveActions) brainState.cognitiveActions = [];
3553
+ brainState.cognitiveActions.push({ kind: "cognitive", verb, config });
3554
+ } else {
3555
+ this.pos = saved;
3556
+ const parts = [this.advance().value];
3557
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3558
+ parts.push(this.advance().value);
3559
+ }
3560
+ brainState.actions.push(parts.join(" "));
3561
+ }
3562
+ } else if (this.check("IDENTIFIER") && this.tokens[this.pos + 1]?.type === "LBRACE" && chunkYP5CHEYU_cjs.nearestCognitiveVerb(this.current().value)) {
3563
+ const typo = this.current().value;
3564
+ const suggestion = chunkYP5CHEYU_cjs.nearestCognitiveVerb(typo);
3565
+ this.warn(`Unknown cognitive verb '${typo}' \u2014 did you mean '${suggestion}'?`);
3566
+ this.advance();
3567
+ this.parseBlockContent();
3568
+ brainState.actions.push(typo);
3569
+ } else if (this.check("IDENTIFIER")) {
3570
+ const parts = [this.advance().value];
3571
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3572
+ parts.push(this.advance().value);
3573
+ }
3574
+ brainState.actions.push(parts.join(" "));
3575
+ } else {
3576
+ this.advance();
3577
+ }
3578
+ this.skipNewlines();
3579
+ }
3580
+ this.expect("RBRACE", "Expected } to close state block");
3083
3581
  }
3084
- } else if (this.check("LPAREN")) {
3085
- this.skipParens();
3582
+ brain.states.push(brainState);
3583
+ this.skipNewlines();
3584
+ continue;
3585
+ }
3586
+ if (this.check("IDENTIFIER")) {
3587
+ const parts = [this.advance().value];
3588
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3589
+ parts.push(this.advance().value);
3590
+ }
3591
+ brain.traits["_actions"] = [
3592
+ ...brain.traits["_actions"] || [],
3593
+ parts.join(" ")
3594
+ ];
3086
3595
  } else {
3087
3596
  this.advance();
3088
3597
  }
3089
- if (this.check("COMMA")) this.advance();
3090
3598
  this.skipNewlines();
3091
3599
  }
3092
- this.expect("RBRACE", "Expected }");
3093
- return content;
3600
+ this.expect("RBRACE", "Expected } to close brain declaration");
3601
+ return brain;
3094
3602
  }
3095
3603
  /**
3096
- * Parse bindings block: { bind(expr) -> target, ... }
3604
+ * Parse a .hs `connect` statement.
3605
+ * Syntax (full .hs format):
3606
+ * connect <source> -> <target>
3607
+ * where <source> and <target> are dotted member chains, optionally followed
3608
+ * by assignment for state connections:
3609
+ * connect alarm_bell.alarm_triggered -> guard_captain.state.alert_level = 3
3610
+ *
3611
+ * Strategy: consume the `connect` keyword, then collect all tokens up to
3612
+ * (but not including) the next NEWLINE / EOF as a raw string. This is
3613
+ * intentionally permissive — the connect statement has a rich surface syntax
3614
+ * (dotted paths, ARROW, assignments) that the generic property parser cannot
3615
+ * handle. Semantic validation of the wiring is a separate compilation phase.
3097
3616
  */
3098
- parseBindingsBlock() {
3099
- const bindings = [];
3100
- if (!this.check("LBRACE")) {
3101
- return bindings;
3617
+ parseHsConnectStatement() {
3618
+ const startToken = this.current();
3619
+ this.advance();
3620
+ const toks = [];
3621
+ while (!this.check("NEWLINE") && !this.check("EOF")) {
3622
+ toks.push(this.advance());
3102
3623
  }
3624
+ const arrowIdx = toks.findIndex((t) => t.type === "ARROW");
3625
+ const fromToks = arrowIdx >= 0 ? toks.slice(0, arrowIdx) : toks;
3626
+ const toToks = arrowIdx >= 0 ? toks.slice(arrowIdx + 1) : [];
3627
+ return {
3628
+ type: "connection",
3629
+ properties: {
3630
+ from: this.joinTokensSmart(fromToks),
3631
+ to: this.joinTokensSmart(toToks),
3632
+ raw: this.joinTokensSmart(toks)
3633
+ },
3634
+ directives: [],
3635
+ children: [],
3636
+ traits: /* @__PURE__ */ new Map(),
3637
+ loc: {
3638
+ start: { line: startToken.line, column: startToken.column },
3639
+ end: { line: this.current().line, column: this.current().column }
3640
+ }
3641
+ };
3642
+ }
3643
+ /**
3644
+ * Parse a .hs `execute` statement.
3645
+ * Syntax:
3646
+ * execute <target>(<args>) [repeat forever | every <interval>]
3647
+ * Examples:
3648
+ * execute guard_captain.patrol() repeat forever
3649
+ * execute temp_sensor_A.read() every 1000ms
3650
+ *
3651
+ * Strategy: consume `execute` then collect all tokens to end of line.
3652
+ * The target is the leading member chain plus one balanced call-paren
3653
+ * group; everything after it is the schedule clause.
3654
+ */
3655
+ parseHsExecuteStatement() {
3656
+ const startToken = this.current();
3103
3657
  this.advance();
3104
- this.skipNewlines();
3105
- while (!this.check("RBRACE") && !this.check("EOF")) {
3106
- this.skipNewlines();
3107
- if (this.check("RBRACE") || this.check("EOF")) break;
3108
- if (this.check("IDENTIFIER") && this.current().value === "bind") {
3109
- this.advance();
3110
- if (this.check("LPAREN")) {
3111
- this.advance();
3112
- let source = "";
3113
- let parenDepth = 1;
3114
- while (parenDepth > 0 && !this.check("EOF")) {
3658
+ const toks = [];
3659
+ while (!this.check("NEWLINE") && !this.check("EOF")) {
3660
+ toks.push(this.advance());
3661
+ }
3662
+ let end = toks.length;
3663
+ let depth = 0;
3664
+ for (let i = 0; i < toks.length; i++) {
3665
+ const t = toks[i];
3666
+ if (t.type === "LPAREN") {
3667
+ depth++;
3668
+ } else if (t.type === "RPAREN") {
3669
+ depth--;
3670
+ if (depth === 0) {
3671
+ end = i + 1;
3672
+ break;
3673
+ }
3674
+ } else if (depth === 0 && t.type !== "IDENTIFIER" && t.type !== "DOT" && t.type !== "NUMBER") {
3675
+ end = i;
3676
+ break;
3677
+ }
3678
+ }
3679
+ const target = this.joinTokensSmart(toks.slice(0, end));
3680
+ const schedule = this.joinTokensSmart(toks.slice(end));
3681
+ return {
3682
+ type: "execute",
3683
+ properties: { target, schedule, raw: this.joinTokensSmart(toks) },
3684
+ directives: [],
3685
+ children: [],
3686
+ traits: /* @__PURE__ */ new Map(),
3687
+ loc: {
3688
+ start: { line: startToken.line, column: startToken.column },
3689
+ end: { line: this.current().line, column: this.current().column }
3690
+ }
3691
+ };
3692
+ }
3693
+ // ===========================================================================
3694
+ // Pipeline DSL block parsing (transform / filter / branch / validate)
3695
+ // ===========================================================================
3696
+ /**
3697
+ * Reassemble token values into readable source text: no spaces around
3698
+ * member/call/index punctuation, string literals re-quoted.
3699
+ */
3700
+ joinTokensSmart(tokens) {
3701
+ const NO_SPACE_BEFORE = /* @__PURE__ */ new Set([
3702
+ "DOT",
3703
+ "COMMA",
3704
+ "LPAREN",
3705
+ "RPAREN",
3706
+ "LBRACKET",
3707
+ "RBRACKET",
3708
+ "OPTIONAL_DOT"
3709
+ ]);
3710
+ const NO_SPACE_AFTER = /* @__PURE__ */ new Set(["DOT", "LPAREN", "LBRACKET", "OPTIONAL_DOT", "EXCLAMATION"]);
3711
+ let out = "";
3712
+ let prev = null;
3713
+ for (const t of tokens) {
3714
+ const text = t.type === "STRING" ? JSON.stringify(t.value) : t.value;
3715
+ if (prev && !NO_SPACE_BEFORE.has(t.type) && !NO_SPACE_AFTER.has(prev.type)) {
3716
+ out += " ";
3717
+ }
3718
+ out += text;
3719
+ prev = t;
3720
+ }
3721
+ return out;
3722
+ }
3723
+ /** Capture a dotted/indexed path: sku, a.b.c, results[0].id, entries[] */
3724
+ capturePipelinePath() {
3725
+ const toks = [];
3726
+ if (this.check("IDENTIFIER") || this.check("STRING") || this.check("UNDERSCORE")) {
3727
+ toks.push(this.advance());
3728
+ }
3729
+ for (; ; ) {
3730
+ if (this.check("DOT")) {
3731
+ toks.push(this.advance());
3732
+ if (this.check("IDENTIFIER") || this.check("NUMBER") || this.check("UNDERSCORE")) {
3733
+ toks.push(this.advance());
3734
+ }
3735
+ continue;
3736
+ }
3737
+ if (this.check("LBRACKET")) {
3738
+ let depth = 0;
3739
+ do {
3740
+ const t = this.advance();
3741
+ toks.push(t);
3742
+ if (t.type === "LBRACKET") depth++;
3743
+ else if (t.type === "RBRACKET") depth--;
3744
+ } while (depth > 0 && !this.check("EOF"));
3745
+ continue;
3746
+ }
3747
+ break;
3748
+ }
3749
+ return { raw: this.joinTokensSmart(toks), tokens: toks };
3750
+ }
3751
+ /** Capture a transform op call: trim() / multiply(100) / increment_if(a == b.c) */
3752
+ capturePipelineOp() {
3753
+ const toks = [];
3754
+ if (this.check("IDENTIFIER")) {
3755
+ toks.push(this.advance());
3756
+ }
3757
+ if (this.check("LPAREN")) {
3758
+ let depth = 0;
3759
+ do {
3760
+ const t = this.advance();
3761
+ toks.push(t);
3762
+ if (t.type === "LPAREN") depth++;
3763
+ else if (t.type === "RPAREN") depth--;
3764
+ } while (depth > 0 && !this.check("EOF"));
3765
+ }
3766
+ return this.joinTokensSmart(toks);
3767
+ }
3768
+ /** True when an ARROW appears before the end of the current statement line. */
3769
+ hasArrowBeforeEOL() {
3770
+ for (let look = this.pos; look < this.tokens.length; look++) {
3771
+ const t = this.tokens[look].type;
3772
+ if (t === "ARROW") return true;
3773
+ if (t === "NEWLINE" || t === "EOF" || t === "RBRACE" || t === "LBRACE") return false;
3774
+ }
3775
+ return false;
3776
+ }
3777
+ /**
3778
+ * Capture expression tokens to end of line, honoring `||` / `&&`
3779
+ * line continuations:
3780
+ * where: stock != previous.stock
3781
+ * || costCents != previous.costCents
3782
+ */
3783
+ captureExpressionToEOL() {
3784
+ const toks = [];
3785
+ for (; ; ) {
3786
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3787
+ toks.push(this.advance());
3788
+ }
3789
+ if (this.check("NEWLINE")) {
3790
+ let look = this.pos;
3791
+ while (look < this.tokens.length && ["NEWLINE", "INDENT", "DEDENT"].includes(this.tokens[look].type)) {
3792
+ look++;
3793
+ }
3794
+ const next = this.tokens[look];
3795
+ if (next && (next.type === "OR" || next.type === "AND")) {
3796
+ this.pos = look;
3797
+ continue;
3798
+ }
3799
+ }
3800
+ break;
3801
+ }
3802
+ return toks;
3803
+ }
3804
+ /**
3805
+ * YAML-style block scalar property value:
3806
+ * prompt: |
3807
+ * Extract wisdom from this content.
3808
+ * Return JSON.
3809
+ * Captures the following lines from raw source while they are blank or
3810
+ * indented deeper than the key line, dedents, and skips their tokens.
3811
+ */
3812
+ parseBlockScalar(keyToken) {
3813
+ this.advance();
3814
+ const keyIndent = keyToken.column - 1;
3815
+ const lines = this.source.split("\n");
3816
+ const collected = [];
3817
+ let lastLine = keyToken.line;
3818
+ for (let ln = keyToken.line + 1; ln <= lines.length; ln++) {
3819
+ const text = lines[ln - 1];
3820
+ if (text.trim() === "") {
3821
+ collected.push("");
3822
+ lastLine = ln;
3823
+ continue;
3824
+ }
3825
+ const indent = text.length - text.trimStart().length;
3826
+ if (indent <= keyIndent) break;
3827
+ collected.push(text);
3828
+ lastLine = ln;
3829
+ }
3830
+ while (!this.check("EOF") && this.current().line <= lastLine) {
3831
+ this.advance();
3832
+ }
3833
+ const nonBlank = collected.filter((l) => l.trim() !== "");
3834
+ const minIndent = nonBlank.length ? Math.min(...nonBlank.map((l) => l.length - l.trimStart().length)) : 0;
3835
+ return collected.map((l) => l.slice(minIndent)).join("\n").replace(/\s+$/, "");
3836
+ }
3837
+ /** Property value inside a pipeline DSL block. */
3838
+ parsePipelinePropertyValue(keyToken) {
3839
+ if (this.check("PIPE")) {
3840
+ const next = this.peek(1);
3841
+ if (!next || next.type === "NEWLINE" || next.type === "EOF") {
3842
+ return this.parseBlockScalar(keyToken);
3843
+ }
3844
+ }
3845
+ if (this.check("LBRACE") || this.check("LBRACKET")) {
3846
+ return this.parseValue();
3847
+ }
3848
+ const toks = this.captureExpressionToEOL();
3849
+ if (toks.length === 1) {
3850
+ const t = toks[0];
3851
+ if (t.type === "STRING") return t.value;
3852
+ if (t.type === "NUMBER") {
3853
+ const n = Number(t.value);
3854
+ return Number.isNaN(n) ? t.value : n;
3855
+ }
3856
+ if (t.value === "true") return true;
3857
+ if (t.value === "false") return false;
3858
+ return t.value;
3859
+ }
3860
+ return this.joinTokensSmart(toks);
3861
+ }
3862
+ /**
3863
+ * Body parser for pipeline DSL blocks. Handles, per statement:
3864
+ * key: value → property (incl. block scalars)
3865
+ * src.path[0] -> dst.path : op() : op2(...) → mapping child
3866
+ * when <cond> -> <target> → when child (branch)
3867
+ * default -> <target> → default child (branch)
3868
+ * field.path : rule, rule(...) → constraint child (validate /
3869
+ * dotted fields anywhere)
3870
+ * Statements are captured structurally with their raw text preserved;
3871
+ * semantic validation of the wiring is a separate compilation phase.
3872
+ */
3873
+ parsePipelineBlock(kind, name, startToken) {
3874
+ this.expect("LBRACE", `Expected { after ${kind} ${name}`);
3875
+ const properties = {};
3876
+ const children = [];
3877
+ const directives = [];
3878
+ const traits = /* @__PURE__ */ new Map();
3879
+ const childLoc = (tok) => ({
3880
+ start: { line: tok.line, column: tok.column },
3881
+ end: { line: this.current().line, column: this.current().column }
3882
+ });
3883
+ while (!this.check("RBRACE") && !this.check("EOF")) {
3884
+ try {
3885
+ this.skipNewlines();
3886
+ if (this.check("RBRACE") || this.check("EOF")) break;
3887
+ if (this.check("AT")) {
3888
+ const directive = this.parseDirective();
3889
+ if (directive) {
3890
+ if (directive.type === "trait") {
3891
+ traits.set(directive.name, directive.config);
3892
+ this.hasVRTraits = true;
3893
+ }
3894
+ directives.push(directive);
3895
+ }
3896
+ } else if (kind === "branch" && this.check("IDENTIFIER") && this.current().value === "when") {
3897
+ const stmtStart = this.advance();
3898
+ const condToks = [];
3899
+ while (!this.check("ARROW") && !this.check("NEWLINE") && !this.check("EOF")) {
3900
+ condToks.push(this.advance());
3901
+ }
3902
+ let target = "";
3903
+ if (this.check("ARROW")) {
3904
+ this.advance();
3905
+ const targetToks = [];
3906
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3907
+ targetToks.push(this.advance());
3908
+ }
3909
+ target = this.joinTokensSmart(targetToks);
3910
+ }
3911
+ children.push({
3912
+ type: "when",
3913
+ condition: this.joinTokensSmart(condToks),
3914
+ target,
3915
+ loc: childLoc(stmtStart)
3916
+ });
3917
+ } else if (this.hasArrowBeforeEOL()) {
3918
+ const stmtStart = this.current();
3919
+ const lhsToks = [];
3920
+ while (!this.check("ARROW") && !this.check("NEWLINE") && !this.check("EOF")) {
3921
+ lhsToks.push(this.advance());
3922
+ }
3923
+ if (this.check("ARROW")) this.advance();
3924
+ const from = this.joinTokensSmart(lhsToks);
3925
+ if (kind === "branch") {
3926
+ const targetToks = [];
3927
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
3928
+ targetToks.push(this.advance());
3929
+ }
3930
+ children.push({
3931
+ type: from === "default" ? "default" : "route",
3932
+ from,
3933
+ target: this.joinTokensSmart(targetToks),
3934
+ loc: childLoc(stmtStart)
3935
+ });
3936
+ } else {
3937
+ const to = this.capturePipelinePath();
3938
+ const ops = [];
3939
+ while (this.check("COLON")) {
3940
+ this.advance();
3941
+ ops.push(this.capturePipelineOp());
3942
+ }
3943
+ children.push({
3944
+ type: "mapping",
3945
+ from,
3946
+ to: to.raw,
3947
+ ops,
3948
+ loc: childLoc(stmtStart)
3949
+ });
3950
+ }
3951
+ } else if (this.check("IDENTIFIER") || this.check("STRING")) {
3952
+ const keyToken = this.current();
3953
+ const path = this.capturePipelinePath();
3954
+ if (this.check("COLON")) {
3955
+ this.advance();
3956
+ const pathIsDotted = path.tokens.some((t) => t.type === "DOT" || t.type === "LBRACKET");
3957
+ if (kind === "validate" || pathIsDotted) {
3958
+ const ruleToks = this.captureExpressionToEOL();
3959
+ children.push({
3960
+ type: "constraint",
3961
+ field: path.raw,
3962
+ rules: this.joinTokensSmart(ruleToks),
3963
+ loc: childLoc(keyToken)
3964
+ });
3965
+ } else {
3966
+ properties[path.raw] = this.parsePipelinePropertyValue(keyToken);
3967
+ }
3968
+ } else {
3969
+ properties[path.raw] = true;
3970
+ }
3971
+ } else if (this.check("COMMA")) {
3972
+ this.advance();
3973
+ } else {
3974
+ this.error(
3975
+ `Unexpected token ${this.current().type} "${this.current().value}" in ${kind} block`,
3976
+ "HSP001"
3977
+ );
3978
+ this.synchronizeProperty();
3979
+ }
3980
+ this.skipNewlines();
3981
+ } catch (e) {
3982
+ const errorMessage = e instanceof Error ? e.message : String(e);
3983
+ if (errorMessage !== "ParseError") console.error(e);
3984
+ this.synchronizeProperty();
3985
+ }
3986
+ }
3987
+ this.expect("RBRACE", "Expected }");
3988
+ return {
3989
+ type: kind,
3990
+ name,
3991
+ id: name,
3992
+ properties,
3993
+ directives,
3994
+ children,
3995
+ traits,
3996
+ loc: {
3997
+ start: { line: startToken.line, column: startToken.column },
3998
+ end: { line: this.current().line, column: this.current().column }
3999
+ }
4000
+ };
4001
+ }
4002
+ /** @deprecated Use parseHsConnectStatement for .hs connect syntax */
4003
+ parseConnectionStatement() {
4004
+ this.expect("IDENTIFIER", "Expected connect");
4005
+ const from = this.expect("IDENTIFIER", "Expected from name").value;
4006
+ this.expect("IDENTIFIER", "Expected to");
4007
+ const to = this.expect("IDENTIFIER", "Expected to name").value;
4008
+ return { from, to };
4009
+ }
4010
+ /**
4011
+ * Map a reaction trigger to its routing bucket (mirrors the .hs parser's
4012
+ * reactionCategory; the movement-trigger list comes from the locomotion SSOT).
4013
+ */
4014
+ hsplusReactionCategory(trigger) {
4015
+ if (chunkNTQRFOPP_cjs.isLocomotionReactionTrigger(trigger)) return "movement";
4016
+ switch (trigger) {
4017
+ case "on_interact":
4018
+ case "on_grab":
4019
+ case "on_release":
4020
+ case "on_use":
4021
+ case "on_hover":
4022
+ return "interaction";
4023
+ case "on_collision":
4024
+ case "on_collide":
4025
+ case "on_proximity":
4026
+ return "collision";
4027
+ case "on_spawn":
4028
+ case "on_death":
4029
+ case "on_enter":
4030
+ case "on_exit":
4031
+ case "on_tick":
4032
+ return "lifecycle";
4033
+ case "on_combat":
4034
+ case "on_cast":
4035
+ return "combat";
4036
+ case "on_signal":
4037
+ case "on_input":
4038
+ return "signal";
4039
+ default:
4040
+ return "custom";
4041
+ }
4042
+ }
4043
+ /**
4044
+ * Parse a declarative reaction block attached to an entity:
4045
+ * react {
4046
+ * on_grab(hand) => highlight()
4047
+ * on_proximity(player) => alert(player)
4048
+ * on_use => { open(); play_sound("creak") }
4049
+ * }
4050
+ * A leading `on` word is optional (`on collide(...)` == `on_collide(...)`).
4051
+ * Each entry becomes a `reaction` child node carrying trigger/params/body and
4052
+ * an inferred ReactionCategory. Body is captured raw (an expression or block).
4053
+ */
4054
+ parseHsPlusReactBlock(startToken) {
4055
+ const startLoc = { line: startToken.line, column: startToken.column };
4056
+ const reactions = [];
4057
+ this.skipNewlines();
4058
+ if (this.check("LBRACE")) {
4059
+ this.advance();
4060
+ this.skipNewlines();
4061
+ while (!this.check("RBRACE") && !this.check("EOF")) {
4062
+ this.skipNewlines();
4063
+ if (this.check("RBRACE") || this.check("EOF")) break;
4064
+ let triggerPrefix = "";
4065
+ if (this.check("IDENTIFIER") && this.current().value === "on" && this.tokens[this.pos + 1]?.type === "IDENTIFIER") {
4066
+ this.advance();
4067
+ triggerPrefix = "on_";
4068
+ }
4069
+ if (!this.check("IDENTIFIER")) {
4070
+ this.advance();
4071
+ continue;
4072
+ }
4073
+ const trigger = triggerPrefix + this.advance().value;
4074
+ const params = [];
4075
+ if (this.check("LPAREN")) {
4076
+ this.advance();
4077
+ while (!this.check("RPAREN") && !this.check("EOF")) {
4078
+ if (this.check("IDENTIFIER")) params.push(this.advance().value);
4079
+ else this.advance();
4080
+ if (this.check("COMMA")) this.advance();
4081
+ }
4082
+ if (this.check("RPAREN")) this.advance();
4083
+ }
4084
+ if (this.check("ARROW")) this.advance();
4085
+ let body = "";
4086
+ if (this.check("LBRACE")) {
4087
+ body = this.parseRawBlock();
4088
+ } else {
4089
+ const parts = [];
4090
+ while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
4091
+ parts.push(this.advance().value);
4092
+ }
4093
+ body = parts.join(" ").trim();
4094
+ }
4095
+ reactions.push({
4096
+ type: "reaction",
4097
+ name: trigger,
4098
+ event: trigger,
4099
+ body,
4100
+ properties: {
4101
+ trigger,
4102
+ params,
4103
+ category: this.hsplusReactionCategory(trigger)
4104
+ }
4105
+ });
4106
+ this.skipNewlines();
4107
+ }
4108
+ if (this.check("RBRACE")) this.advance();
4109
+ }
4110
+ return {
4111
+ type: "react-block",
4112
+ name: "react",
4113
+ children: reactions,
4114
+ properties: { count: reactions.length },
4115
+ directives: [],
4116
+ traits: /* @__PURE__ */ new Map(),
4117
+ loc: {
4118
+ start: startLoc,
4119
+ end: { line: this.current().line, column: this.current().column }
4120
+ }
4121
+ };
4122
+ }
4123
+ /**
4124
+ * Parse a `timeline <name> { …properties, track-blocks, children }` node.
4125
+ * (Theatre.js harvest S1.) Produces the same shape as the canonical Rust
4126
+ * grammar: a `timeline` node whose `children` include structured `track`
4127
+ * nodes (`{ type: 'track', target, keyframes: [...] }`). Non-track lines are
4128
+ * handled the generic way: `key: value` → property, nested block keyword →
4129
+ * child node. The `timeline` keyword has already been consumed by the caller.
4130
+ */
4131
+ parseTimelineNode(startToken) {
4132
+ let name;
4133
+ if (this.check("STRING") || this.check("IDENTIFIER")) {
4134
+ name = this.advance().value;
4135
+ }
4136
+ const properties = {};
4137
+ const children = [];
4138
+ const directives = [];
4139
+ const traits = /* @__PURE__ */ new Map();
4140
+ if (this.check("LBRACE")) {
4141
+ this.advance();
4142
+ this.skipNewlines();
4143
+ while (!this.check("RBRACE") && !this.check("EOF")) {
4144
+ this.skipNewlines();
4145
+ if (this.check("RBRACE") || this.check("EOF")) break;
4146
+ if (this.check("AT")) {
4147
+ const directive = this.parseDirective();
4148
+ if (directive) {
4149
+ if (directive.type === "trait") {
4150
+ traits.set(directive.name, directive.config);
4151
+ this.hasVRTraits = true;
4152
+ }
4153
+ directives.push(directive);
4154
+ }
4155
+ this.skipNewlines();
4156
+ continue;
4157
+ }
4158
+ const token = this.current();
4159
+ const next = this.peek(1);
4160
+ if (token.type === "IDENTIFIER" && token.value === "track" && (next.type === "STRING" || next.type === "IDENTIFIER") && this.peek(2).type === "LBRACE") {
4161
+ this.advance();
4162
+ children.push(this.parseTrackNode(token));
4163
+ if (this.check("COMMA")) this.advance();
4164
+ this.skipNewlines();
4165
+ continue;
4166
+ }
4167
+ if ((token.type === "IDENTIFIER" || token.type === "STRING") && (next.type === "COLON" || next.type === "EQUALS")) {
4168
+ const key = this.advance().value;
4169
+ this.advance();
4170
+ properties[key] = this.parseValue();
4171
+ if (this.check("COMMA")) this.advance();
4172
+ this.skipNewlines();
4173
+ continue;
4174
+ }
4175
+ if (token.type === "IDENTIFIER" || token.type === "STRING") {
4176
+ children.push(this.parseNode());
4177
+ if (this.check("COMMA")) this.advance();
4178
+ this.skipNewlines();
4179
+ continue;
4180
+ }
4181
+ this.advance();
4182
+ this.skipNewlines();
4183
+ }
4184
+ this.expect("RBRACE", "Expected } to close timeline block");
4185
+ }
4186
+ return {
4187
+ type: "timeline",
4188
+ name,
4189
+ id: name,
4190
+ properties,
4191
+ directives,
4192
+ children,
4193
+ traits,
4194
+ loc: {
4195
+ start: { line: startToken.line, column: startToken.column },
4196
+ end: { line: this.current().line, column: this.current().column }
4197
+ }
4198
+ };
4199
+ }
4200
+ /**
4201
+ * Parse a keyframe-track inside a timeline:
4202
+ * track "<target>" { key <time> { <value> } [easing <ease>] ; … }
4203
+ * Mirrors the Rust `TrackNode`/`KeyframeNode`. `;` is skipped by the lexer,
4204
+ * so keyframe separators are implicit. The `track` keyword has already been
4205
+ * consumed by the caller. Returns `{ type: 'track', target, keyframes }`.
4206
+ */
4207
+ parseTrackNode(startToken) {
4208
+ const target = this.check("STRING") ? this.advance().value : this.expect("IDENTIFIER", "Expected track target name").value;
4209
+ const keyframes = [];
4210
+ this.expect("LBRACE", "Expected { to open track block");
4211
+ this.skipNewlines();
4212
+ while (!this.check("RBRACE") && !this.check("EOF")) {
4213
+ this.skipNewlines();
4214
+ if (this.check("RBRACE") || this.check("EOF")) break;
4215
+ if (this.check("COMMA")) {
4216
+ this.advance();
4217
+ continue;
4218
+ }
4219
+ if (this.check("IDENTIFIER") && this.current().value === "key") {
4220
+ this.advance();
4221
+ let timeSign = 1;
4222
+ if (this.check("MINUS")) {
4223
+ this.advance();
4224
+ timeSign = -1;
4225
+ }
4226
+ const timeTok = this.expect("NUMBER", "Expected numeric time after key");
4227
+ const time = timeSign * Number(timeTok.value);
4228
+ this.expect("LBRACE", "Expected { value block after key time");
4229
+ const value = this.parseValue();
4230
+ this.expect("RBRACE", "Expected } to close key value block");
4231
+ let easing;
4232
+ if (this.check("IDENTIFIER") && this.current().value === "easing") {
4233
+ this.advance();
4234
+ if (this.check("IDENTIFIER") || this.check("STRING")) {
4235
+ easing = this.advance().value;
4236
+ }
4237
+ }
4238
+ keyframes.push(easing === void 0 ? { time, value } : { time, value, easing });
4239
+ this.skipNewlines();
4240
+ continue;
4241
+ }
4242
+ this.advance();
4243
+ this.skipNewlines();
4244
+ }
4245
+ this.expect("RBRACE", "Expected } to close track block");
4246
+ return {
4247
+ type: "track",
4248
+ target,
4249
+ keyframes,
4250
+ loc: {
4251
+ start: { line: startToken.line, column: startToken.column },
4252
+ end: { line: this.current().line, column: this.current().column }
4253
+ }
4254
+ };
4255
+ }
4256
+ /**
4257
+ * Parse block content: { key: value, ... }
4258
+ */
4259
+ parseBlockContent() {
4260
+ const content = {};
4261
+ if (!this.check("LBRACE")) {
4262
+ return content;
4263
+ }
4264
+ this.advance();
4265
+ this.skipNewlines();
4266
+ while (!this.check("RBRACE") && !this.check("EOF")) {
4267
+ this.skipNewlines();
4268
+ if (this.check("RBRACE") || this.check("EOF")) break;
4269
+ this.skipNewlines();
4270
+ if (this.check("RBRACE") || this.check("EOF")) break;
4271
+ const token = this.current();
4272
+ const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
4273
+ if (isKeyToken) {
4274
+ const next = this.peek(1);
4275
+ if (next.type === "COLON" || next.type === "EQUALS") {
4276
+ const key = this.advance().value;
4277
+ this.advance();
4278
+ content[key] = this.parseValue();
4279
+ } else if (next.type === "STRING" || next.type === "LBRACE" || next.type === "IDENTIFIER") {
4280
+ const node = this.parseNode();
4281
+ const type = node.type;
4282
+ const name = node.name || `unnamed_${type}_${Object.keys(content).length}`;
4283
+ content[name] = node;
4284
+ } else {
4285
+ const key = this.advance().value;
4286
+ content[key] = true;
4287
+ }
4288
+ } else if (this.check("SPREAD")) {
4289
+ this.advance();
4290
+ const val = this.parseValue();
4291
+ const spreadKey = `__spread_${Object.keys(content).length}`;
4292
+ content[spreadKey] = { type: "spread", argument: val };
4293
+ } else if (this.check("AT")) {
4294
+ const directive = this.parseDirective();
4295
+ if (directive) {
4296
+ const dirKey = ("name" in directive ? directive.name : void 0) || directive.type;
4297
+ content[`@${dirKey}`] = directive;
4298
+ }
4299
+ } else if (this.check("LBRACE")) {
4300
+ let depth = 1;
4301
+ this.advance();
4302
+ while (depth > 0 && !this.check("EOF")) {
4303
+ if (this.check("LBRACE")) depth++;
4304
+ if (this.check("RBRACE")) depth--;
4305
+ this.advance();
4306
+ }
4307
+ } else if (this.check("LPAREN")) {
4308
+ this.skipParens();
4309
+ } else {
4310
+ this.advance();
4311
+ }
4312
+ if (this.check("COMMA")) this.advance();
4313
+ this.skipNewlines();
4314
+ }
4315
+ this.expect("RBRACE", "Expected }");
4316
+ return content;
4317
+ }
4318
+ /**
4319
+ * Parse bindings block: { bind(expr) -> target, ... }
4320
+ */
4321
+ parseBindingsBlock() {
4322
+ const bindings = [];
4323
+ if (!this.check("LBRACE")) {
4324
+ return bindings;
4325
+ }
4326
+ this.advance();
4327
+ this.skipNewlines();
4328
+ while (!this.check("RBRACE") && !this.check("EOF")) {
4329
+ this.skipNewlines();
4330
+ if (this.check("RBRACE") || this.check("EOF")) break;
4331
+ if (this.check("IDENTIFIER") && this.current().value === "bind") {
4332
+ this.advance();
4333
+ if (this.check("LPAREN")) {
4334
+ this.advance();
4335
+ let source = "";
4336
+ let parenDepth = 1;
4337
+ while (parenDepth > 0 && !this.check("EOF")) {
3115
4338
  if (this.check("LPAREN")) parenDepth++;
3116
4339
  if (this.check("RPAREN")) {
3117
4340
  parenDepth--;
@@ -3216,7 +4439,8 @@ var HoloScriptPlusParser = class {
3216
4439
  "camera",
3217
4440
  "timeline",
3218
4441
  "page",
3219
- "include"
4442
+ "include",
4443
+ "react"
3220
4444
  ];
3221
4445
  while (!this.check("RBRACE") && !this.check("EOF")) {
3222
4446
  const currentDirectives = [];
@@ -3735,7 +4959,9 @@ var HoloScriptPlusParser = class {
3735
4959
  if (startToken.type === "STATE_MACHINE") {
3736
4960
  this.advance();
3737
4961
  }
3738
- const name = this.expect("IDENTIFIER", "Expected state machine name").value;
4962
+ const name = this.parseStateMachineIdentifier("Expected state machine name");
4963
+ const inputs = [];
4964
+ const listeners = [];
3739
4965
  const states = [];
3740
4966
  const transitions = [];
3741
4967
  let initialState = "";
@@ -3748,7 +4974,13 @@ var HoloScriptPlusParser = class {
3748
4974
  if (current.type === "INITIAL" || current.value === "initial") {
3749
4975
  this.advance();
3750
4976
  this.expect("COLON", "Expected : after initial");
3751
- initialState = this.expect("STRING", "Expected initial state name").value;
4977
+ initialState = this.parseStateMachineIdentifier("Expected initial state name");
4978
+ } else if (current.value === "input") {
4979
+ inputs.push(this.parseStateMachineInputDeclaration());
4980
+ } else if (current.value === "listen") {
4981
+ listeners.push(this.parseStateMachineListenerDeclaration());
4982
+ } else if (this.isStateMachineTransitionShorthandStart()) {
4983
+ transitions.push(this.parseStateMachineTransitionShorthand());
3752
4984
  } else if (current.type === "STATE" || current.value === "state") {
3753
4985
  states.push(this.parseStateNode());
3754
4986
  } else if (current.type === "TRANSITION" || current.value === "transitions") {
@@ -3763,6 +4995,8 @@ var HoloScriptPlusParser = class {
3763
4995
  type: "state-machine",
3764
4996
  name,
3765
4997
  initialState,
4998
+ inputs,
4999
+ listeners,
3766
5000
  states,
3767
5001
  transitions,
3768
5002
  loc: {
@@ -3773,9 +5007,10 @@ var HoloScriptPlusParser = class {
3773
5007
  }
3774
5008
  parseStateNode() {
3775
5009
  this.advance();
3776
- const name = this.expect("IDENTIFIER", "Expected state name").value;
5010
+ const name = this.parseStateMachineIdentifier("Expected state name");
3777
5011
  let onEntry;
3778
5012
  let onExit;
5013
+ const metadata = {};
3779
5014
  this.expect("LBRACE", "Expected { after state name");
3780
5015
  this.skipNewlines();
3781
5016
  while (!this.check("RBRACE") && !this.check("EOF")) {
@@ -3788,19 +5023,39 @@ var HoloScriptPlusParser = class {
3788
5023
  } else if (current.type === "ON_EXIT" || current.value === "on_exit") {
3789
5024
  this.advance();
3790
5025
  onExit = this.parseCodeBlock();
5026
+ } else if (this.isStateMachineStateMetadataKey(current.value) && this.peek(1).type === "COLON") {
5027
+ const key = this.advance().value;
5028
+ this.expect("COLON", `Expected : after ${key}`);
5029
+ metadata[key] = this.parseValue();
3791
5030
  } else {
3792
5031
  this.advance();
3793
5032
  }
3794
5033
  this.skipNewlines();
3795
5034
  }
3796
5035
  this.expect("RBRACE", "Expected }");
3797
- return { name, onEntry, onExit };
5036
+ return { name, onEntry, onExit, ...metadata };
5037
+ }
5038
+ isStateMachineStateMetadataKey(key) {
5039
+ return key === "clip" || key === "clips" || key === "parameter" || key === "parameters" || key === "thresholds" || key === "blendType" || key === "blend_type" || key === "blend" || key === "blendMode" || key === "blend_mode" || key === "mask" || key === "baseline";
3798
5040
  }
3799
5041
  parseOnErrorNode() {
3800
5042
  const startToken = this.previous();
5043
+ const params = [];
5044
+ if (this.check("LPAREN")) {
5045
+ this.advance();
5046
+ while (!this.check("RPAREN") && !this.check("EOF") && !this.check("LBRACE")) {
5047
+ if (this.check("IDENTIFIER")) {
5048
+ params.push(this.advance().value);
5049
+ } else {
5050
+ this.advance();
5051
+ }
5052
+ }
5053
+ if (this.check("RPAREN")) this.advance();
5054
+ }
3801
5055
  const body = this.parseControlFlowBody();
3802
5056
  return {
3803
5057
  type: "on_error",
5058
+ params,
3804
5059
  body,
3805
5060
  loc: {
3806
5061
  start: { line: startToken.line, column: startToken.column },
@@ -3835,17 +5090,153 @@ var HoloScriptPlusParser = class {
3835
5090
  while (!this.check("RBRACE") && !this.check("EOF")) {
3836
5091
  this.skipNewlines();
3837
5092
  if (this.check("RBRACE") || this.check("EOF")) break;
3838
- const from = this.expect("IDENTIFIER", "Expected source state").value;
3839
- this.expect("ARROW", "Expected ->");
3840
- const to = this.expect("IDENTIFIER", "Expected target state").value;
3841
- this.expect("COLON", "Expected :");
3842
- const event = this.expect("IDENTIFIER", "Expected event name").value;
3843
- transitions.push({ from, to, event });
5093
+ if (this.isStateMachineTransitionShorthandStart()) {
5094
+ transitions.push(this.parseStateMachineTransitionShorthand());
5095
+ } else {
5096
+ const from = this.parseStateMachineIdentifier("Expected source state");
5097
+ this.expect("ARROW", "Expected ->");
5098
+ const to = this.parseStateMachineIdentifier("Expected target state");
5099
+ this.expect("COLON", "Expected :");
5100
+ const event = this.parseStateMachineIdentifier("Expected event name");
5101
+ transitions.push({ from, to, event });
5102
+ }
3844
5103
  this.skipNewlines();
3845
5104
  }
3846
5105
  this.expect("RBRACE", "Expected }");
3847
5106
  return transitions;
3848
5107
  }
5108
+ parseStateMachineInputDeclaration() {
5109
+ this.advance();
5110
+ const name = this.parseStateMachineIdentifier("Expected input name");
5111
+ this.expect("COLON", "Expected : after input name");
5112
+ const rawType = this.parseStateMachineIdentifier("Expected input type");
5113
+ const inputType = rawType === "number" ? "float" : rawType === "boolean" ? "bool" : rawType;
5114
+ let defaultValue;
5115
+ if (this.check("EQUALS")) {
5116
+ this.advance();
5117
+ defaultValue = this.parseValue();
5118
+ }
5119
+ return {
5120
+ type: "animation-input",
5121
+ name,
5122
+ inputType,
5123
+ rawType,
5124
+ default: defaultValue
5125
+ };
5126
+ }
5127
+ parseStateMachineListenerDeclaration() {
5128
+ this.advance();
5129
+ const event = this.parseStateMachineDottedIdentifier("Expected listener event");
5130
+ this.expect("ARROW", "Expected -> after listener event");
5131
+ if (this.current().value === "fire") {
5132
+ this.advance();
5133
+ return {
5134
+ type: "animation-listener",
5135
+ event,
5136
+ action: "fire",
5137
+ parameter: this.parseStateMachineDottedIdentifier("Expected trigger input")
5138
+ };
5139
+ }
5140
+ if (this.current().value === "reset") {
5141
+ this.advance();
5142
+ return {
5143
+ type: "animation-listener",
5144
+ event,
5145
+ action: "reset",
5146
+ parameter: this.parseStateMachineDottedIdentifier("Expected trigger input")
5147
+ };
5148
+ }
5149
+ const parameter = this.parseStateMachineDottedIdentifier("Expected animation input");
5150
+ this.expect("EQUALS", "Expected = in listener binding");
5151
+ const parsedValue = this.parseValue();
5152
+ const listener = {
5153
+ type: "animation-listener",
5154
+ event,
5155
+ action: "set",
5156
+ parameter
5157
+ };
5158
+ if (parsedValue && typeof parsedValue === "object" && "__ref" in parsedValue) {
5159
+ const ref = parsedValue.__ref;
5160
+ if (typeof ref === "string" && (ref === "event" || ref.startsWith("event."))) {
5161
+ listener.source = ref;
5162
+ } else if (typeof ref === "string") {
5163
+ listener.value = ref;
5164
+ } else {
5165
+ listener.value = String(ref ?? "");
5166
+ }
5167
+ } else if (typeof parsedValue === "number" || typeof parsedValue === "boolean" || typeof parsedValue === "string") {
5168
+ listener.value = parsedValue;
5169
+ } else {
5170
+ listener.value = String(parsedValue ?? "");
5171
+ }
5172
+ return listener;
5173
+ }
5174
+ isStateMachineTransitionShorthandStart() {
5175
+ return this.isStateMachineIdentifierToken(0) && this.peek(1).type === "ARROW";
5176
+ }
5177
+ parseStateMachineTransitionShorthand() {
5178
+ const fromRaw = this.parseStateMachineIdentifier("Expected source state");
5179
+ const from = fromRaw.toLowerCase() === "any" ? "any" : fromRaw;
5180
+ this.expect("ARROW", "Expected ->");
5181
+ const to = this.parseStateMachineIdentifier("Expected target state");
5182
+ const transition = { from, to };
5183
+ while (!this.check("NEWLINE") && !this.check("RBRACE") && !this.check("COMMA") && !this.check("EOF")) {
5184
+ if (!this.isStateMachineIdentifierToken(0)) break;
5185
+ const clause = this.current().value.toLowerCase();
5186
+ this.advance();
5187
+ if (clause === "when") {
5188
+ transition.when = this.parseExpression();
5189
+ } else if (clause === "on") {
5190
+ transition.event = this.parseStateMachineIdentifier("Expected trigger input");
5191
+ } else if (clause === "over" || clause === "duration") {
5192
+ transition.duration = this.parseValue();
5193
+ } else if (clause === "easing") {
5194
+ transition.easing = this.parseStateMachineIdentifier("Expected easing name");
5195
+ } else if (clause === "exittime" || clause === "exit_time") {
5196
+ transition.exitTime = this.parseValue();
5197
+ transition.hasExitTime = true;
5198
+ } else if (clause === "pausewhenexiting" || clause === "pause_when_exiting") {
5199
+ transition.pauseWhenExiting = this.parseOptionalStateMachineBoolean();
5200
+ } else if (clause === "priority") {
5201
+ transition.priority = this.parseValue();
5202
+ } else if (clause === "cantransitiontoself" || clause === "can_transition_to_self") {
5203
+ transition.canTransitionToSelf = this.parseOptionalStateMachineBoolean();
5204
+ } else {
5205
+ break;
5206
+ }
5207
+ }
5208
+ return transition;
5209
+ }
5210
+ parseOptionalStateMachineBoolean() {
5211
+ if (this.check("COLON")) this.advance();
5212
+ if (this.check("BOOLEAN")) return this.advance().value === "true";
5213
+ if (this.check("IDENTIFIER")) {
5214
+ const value = this.current().value.toLowerCase();
5215
+ if (value === "true" || value === "false") {
5216
+ this.advance();
5217
+ return value === "true";
5218
+ }
5219
+ }
5220
+ return true;
5221
+ }
5222
+ parseStateMachineIdentifier(message) {
5223
+ if (this.check("IDENTIFIER") || this.check("STRING")) {
5224
+ return this.advance().value;
5225
+ }
5226
+ return this.expect("IDENTIFIER", message).value;
5227
+ }
5228
+ parseStateMachineDottedIdentifier(message) {
5229
+ let value = this.parseStateMachineIdentifier(message);
5230
+ while (this.check("DOT")) {
5231
+ this.advance();
5232
+ value += `.${this.parseStateMachineIdentifier("Expected property name after dot")}`;
5233
+ }
5234
+ return value;
5235
+ }
5236
+ isStateMachineIdentifierToken(offset) {
5237
+ const token = this.peek(offset);
5238
+ return token.type === "IDENTIFIER" || token.type === "STRING";
5239
+ }
3849
5240
  parseControlFlowBody() {
3850
5241
  const nodes = [];
3851
5242
  if (this.check("LBRACE")) {
@@ -3889,41 +5280,10 @@ var HoloScriptPlusParser = class {
3889
5280
  return nodes;
3890
5281
  }
3891
5282
  parseCodeBlock() {
3892
- let code = "";
3893
- let braceDepth = 0;
3894
- if (this.check("LBRACE")) {
3895
- this.advance();
3896
- braceDepth = 1;
3897
- try {
3898
- while (braceDepth > 0 && !this.check("EOF")) {
3899
- const token = this.advance();
3900
- if (token.type === "LBRACE") {
3901
- braceDepth++;
3902
- code += "{";
3903
- } else if (token.type === "RBRACE") {
3904
- braceDepth--;
3905
- if (braceDepth > 0) {
3906
- code += "}";
3907
- }
3908
- } else if (token.type === "STRING") {
3909
- code += `"${token.value}"`;
3910
- code += " ";
3911
- } else {
3912
- code += token.value;
3913
- if (token.type === "NEWLINE") {
3914
- code += "\n";
3915
- } else {
3916
- code += " ";
3917
- }
3918
- }
3919
- }
3920
- } catch (e) {
3921
- const errorMessage = e instanceof Error ? e.message : String(e);
3922
- if (errorMessage !== "ParseError") console.error(e);
3923
- this.synchronize();
3924
- }
5283
+ if (!this.check("LBRACE")) {
5284
+ return "";
3925
5285
  }
3926
- return code.trim();
5286
+ return this.parseRawBlock();
3927
5287
  }
3928
5288
  parseInlineExpression() {
3929
5289
  let expr = "";
@@ -4175,6 +5535,9 @@ var HoloScriptPlusParser = class {
4175
5535
  }
4176
5536
  return this.parseParenExpression();
4177
5537
  }
5538
+ if (token.type === "ARROW" && token.value === "->") {
5539
+ return this.parseTransitionShorthand();
5540
+ }
4178
5541
  if (token.type === "MATCH") {
4179
5542
  return this.parseMatchExpression();
4180
5543
  }
@@ -4230,6 +5593,36 @@ var HoloScriptPlusParser = class {
4230
5593
  err.message = "ParseError";
4231
5594
  throw err;
4232
5595
  }
5596
+ /**
5597
+ * Parse a state-machine transition shorthand value:
5598
+ * -> "target"
5599
+ * -> "target" action(callback_name)
5600
+ * -> "target" guard(state.credits >= 10) action(begin)
5601
+ * Used as the value of on_<event> keys inside @state_machine states config.
5602
+ * Modifiers (action / guard) may appear in any order, each at most once
5603
+ * meaningfully (last one wins, matching general object semantics).
5604
+ */
5605
+ parseTransitionShorthand() {
5606
+ this.advance();
5607
+ let target = "";
5608
+ if (this.check("STRING") || this.check("IDENTIFIER")) {
5609
+ target = this.advance().value;
5610
+ } else {
5611
+ this.error(
5612
+ `Expected target state after -> in transition. Got ${this.current().type} "${this.current().value}"`,
5613
+ "HSP300"
5614
+ );
5615
+ }
5616
+ const transition = { type: "transition", target };
5617
+ while (this.check("IDENTIFIER") && (this.current().value === "action" || this.current().value === "guard") && this.peek(1).type === "LPAREN") {
5618
+ const kind = this.advance().value;
5619
+ this.advance();
5620
+ const arg = this.parseExpression();
5621
+ this.expect("RPAREN", `Expected ) after ${kind} argument in transition`);
5622
+ transition[kind] = arg;
5623
+ }
5624
+ return transition;
5625
+ }
4233
5626
  parseParenExpression() {
4234
5627
  this.expect("LPAREN", "Expected (");
4235
5628
  const items = [];
@@ -4614,6 +6007,14 @@ var HoloScriptPlusParser = class {
4614
6007
  })
4615
6008
  );
4616
6009
  }
6010
+ errorAt(token, message, code = "HSP001") {
6011
+ this.errors.push(
6012
+ createRichError(code, message, token.line, token.column, {
6013
+ source: this.source,
6014
+ severity: "error"
6015
+ })
6016
+ );
6017
+ }
4617
6018
  errorWithSuggestion(message, suggestion, code = "HSP001") {
4618
6019
  const token = this.current();
4619
6020
  this.errors.push(
@@ -4658,7 +6059,7 @@ var HoloScriptPlusParser = class {
4658
6059
  code: "HSP001"
4659
6060
  };
4660
6061
  }
4661
- if (current.type === "IDENTIFIER" && chunk3SKLAUDD_cjs.VR_TRAITS.includes(current.value)) {
6062
+ if (current.type === "IDENTIFIER" && chunkEI3J6LTW_cjs.VR_TRAITS.includes(current.value)) {
4662
6063
  if (prev?.type !== "AT") {
4663
6064
  return {
4664
6065
  message: `'${current.value}' is a trait and requires '@' prefix`,
@@ -4884,5 +6285,5 @@ exports.getSourceContext = getSourceContext;
4884
6285
  exports.globalParseCache = globalParseCache;
4885
6286
  exports.parse = parse;
4886
6287
  exports.parseIncrementalChunks = parseIncrementalChunks;
4887
- //# sourceMappingURL=chunk-KOUAQL2B.cjs.map
4888
- //# sourceMappingURL=chunk-KOUAQL2B.cjs.map
6288
+ //# sourceMappingURL=chunk-CANAL6CT.cjs.map
6289
+ //# sourceMappingURL=chunk-CANAL6CT.cjs.map