@elizaos/app-core 2.0.0-alpha.73 → 2.0.0-alpha.75

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 (1143) hide show
  1. package/App.d.ts +5 -0
  2. package/App.d.ts.map +1 -0
  3. package/App.js +220 -0
  4. package/actions/character.d.ts +39 -0
  5. package/actions/character.d.ts.map +1 -0
  6. package/actions/character.js +247 -0
  7. package/actions/chat-helpers.d.ts +47 -0
  8. package/actions/chat-helpers.d.ts.map +1 -0
  9. package/actions/chat-helpers.js +79 -0
  10. package/actions/cloud.d.ts +17 -0
  11. package/actions/cloud.d.ts.map +1 -0
  12. package/actions/cloud.js +43 -0
  13. package/actions/index.d.ts +12 -0
  14. package/actions/index.d.ts.map +1 -0
  15. package/actions/index.js +11 -0
  16. package/actions/lifecycle.d.ts +43 -0
  17. package/actions/lifecycle.d.ts.map +1 -0
  18. package/actions/lifecycle.js +118 -0
  19. package/actions/onboarding.d.ts +12 -0
  20. package/actions/onboarding.d.ts.map +1 -0
  21. package/actions/onboarding.js +26 -0
  22. package/actions/triggers.d.ts +23 -0
  23. package/actions/triggers.d.ts.map +1 -0
  24. package/actions/triggers.js +148 -0
  25. package/api/client.d.ts +2736 -0
  26. package/api/client.d.ts.map +1 -0
  27. package/api/client.js +2492 -0
  28. package/api/index.d.ts +2 -0
  29. package/api/index.d.ts.map +1 -0
  30. package/autonomy/index.d.ts +48 -0
  31. package/autonomy/index.d.ts.map +1 -0
  32. package/autonomy/index.js +330 -0
  33. package/bridge/capacitor-bridge.d.ts +153 -0
  34. package/bridge/capacitor-bridge.d.ts.map +1 -0
  35. package/bridge/capacitor-bridge.js +193 -0
  36. package/bridge/electrobun-rpc.d.ts +28 -0
  37. package/bridge/electrobun-rpc.d.ts.map +1 -0
  38. package/bridge/electrobun-rpc.js +35 -0
  39. package/bridge/electrobun-runtime.d.ts +3 -0
  40. package/bridge/electrobun-runtime.d.ts.map +1 -0
  41. package/bridge/electrobun-runtime.js +17 -0
  42. package/bridge/index.d.ts +6 -0
  43. package/bridge/index.d.ts.map +1 -0
  44. package/bridge/native-plugins.d.ts +82 -0
  45. package/bridge/native-plugins.d.ts.map +1 -0
  46. package/bridge/native-plugins.js +39 -0
  47. package/bridge/plugin-bridge.d.ts +116 -0
  48. package/bridge/plugin-bridge.d.ts.map +1 -0
  49. package/bridge/plugin-bridge.js +203 -0
  50. package/bridge/storage-bridge.d.ts +39 -0
  51. package/bridge/storage-bridge.d.ts.map +1 -0
  52. package/bridge/storage-bridge.js +135 -0
  53. package/chat/index.d.ts +57 -0
  54. package/chat/index.d.ts.map +1 -0
  55. package/chat/index.js +160 -0
  56. package/coding/index.d.ts +25 -0
  57. package/coding/index.d.ts.map +1 -0
  58. package/coding/index.js +25 -0
  59. package/components/AdvancedPageView.d.ts +17 -0
  60. package/components/AdvancedPageView.d.ts.map +1 -0
  61. package/components/AdvancedPageView.js +146 -0
  62. package/components/AgentActivityBox.d.ts +7 -0
  63. package/components/AgentActivityBox.d.ts.map +1 -0
  64. package/components/AgentActivityBox.js +25 -0
  65. package/components/ApiKeyConfig.d.ts +26 -0
  66. package/components/ApiKeyConfig.d.ts.map +1 -0
  67. package/components/ApiKeyConfig.js +119 -0
  68. package/components/AppsPageView.d.ts +7 -0
  69. package/components/AppsPageView.d.ts.map +1 -0
  70. package/components/AppsPageView.js +31 -0
  71. package/components/AppsView.d.ts +8 -0
  72. package/components/AppsView.d.ts.map +1 -0
  73. package/components/AppsView.js +149 -0
  74. package/components/AvatarLoader.d.ts +13 -0
  75. package/components/AvatarLoader.d.ts.map +1 -0
  76. package/components/AvatarLoader.js +53 -0
  77. package/components/AvatarSelector.d.ts +23 -0
  78. package/components/AvatarSelector.d.ts.map +1 -0
  79. package/components/AvatarSelector.js +105 -0
  80. package/components/BscTradePanel.d.ts +22 -0
  81. package/components/BscTradePanel.d.ts.map +1 -0
  82. package/components/BscTradePanel.js +221 -0
  83. package/components/BugReportModal.d.ts +2 -0
  84. package/components/BugReportModal.d.ts.map +1 -0
  85. package/components/BugReportModal.js +219 -0
  86. package/components/CharacterRoster.d.ts +31 -0
  87. package/components/CharacterRoster.d.ts.map +1 -0
  88. package/components/CharacterRoster.js +41 -0
  89. package/components/CharacterView.d.ts +8 -0
  90. package/components/CharacterView.d.ts.map +1 -0
  91. package/components/CharacterView.js +685 -0
  92. package/components/ChatAvatar.d.ts +8 -0
  93. package/components/ChatAvatar.d.ts.map +1 -0
  94. package/components/ChatAvatar.js +89 -0
  95. package/components/ChatComposer.d.ts +37 -0
  96. package/components/ChatComposer.d.ts.map +1 -0
  97. package/components/ChatComposer.js +136 -0
  98. package/components/ChatMessage.d.ts +24 -0
  99. package/components/ChatMessage.d.ts.map +1 -0
  100. package/components/ChatMessage.js +167 -0
  101. package/components/ChatModalView.d.ts +10 -0
  102. package/components/ChatModalView.d.ts.map +1 -0
  103. package/components/ChatModalView.js +57 -0
  104. package/components/ChatView.d.ts +14 -0
  105. package/components/ChatView.d.ts.map +1 -0
  106. package/components/ChatView.js +526 -0
  107. package/components/CloudOnboarding.d.ts +7 -0
  108. package/components/CloudOnboarding.d.ts.map +1 -0
  109. package/components/CloudOnboarding.js +22 -0
  110. package/components/CloudSourceControls.d.ts +13 -0
  111. package/components/CloudSourceControls.d.ts.map +1 -0
  112. package/components/CloudSourceControls.js +16 -0
  113. package/components/CodingAgentSettingsSection.d.ts +2 -0
  114. package/components/CodingAgentSettingsSection.d.ts.map +1 -0
  115. package/components/CodingAgentSettingsSection.js +270 -0
  116. package/components/CommandPalette.d.ts +2 -0
  117. package/components/CommandPalette.d.ts.map +1 -0
  118. package/components/CommandPalette.js +181 -0
  119. package/components/CompanionSceneHost.d.ts +14 -0
  120. package/components/CompanionSceneHost.d.ts.map +1 -0
  121. package/components/CompanionSceneHost.js +360 -0
  122. package/components/CompanionShell.d.ts +17 -0
  123. package/components/CompanionShell.d.ts.map +1 -0
  124. package/components/CompanionShell.js +15 -0
  125. package/components/CompanionView.d.ts +2 -0
  126. package/components/CompanionView.d.ts.map +1 -0
  127. package/components/CompanionView.js +22 -0
  128. package/components/ConfigPageView.d.ts +11 -0
  129. package/components/ConfigPageView.d.ts.map +1 -0
  130. package/components/ConfigPageView.js +303 -0
  131. package/components/ConfigSaveFooter.d.ts +8 -0
  132. package/components/ConfigSaveFooter.d.ts.map +1 -0
  133. package/components/ConfigSaveFooter.js +10 -0
  134. package/components/ConfirmModal.d.ts +61 -0
  135. package/components/ConfirmModal.d.ts.map +1 -0
  136. package/components/ConfirmModal.js +164 -0
  137. package/components/ConnectionFailedBanner.d.ts +6 -0
  138. package/components/ConnectionFailedBanner.d.ts.map +1 -0
  139. package/components/ConnectionFailedBanner.js +22 -0
  140. package/components/ConnectorsPageView.d.ts +7 -0
  141. package/components/ConnectorsPageView.d.ts.map +1 -0
  142. package/components/ConnectorsPageView.js +8 -0
  143. package/components/ConversationsSidebar.d.ts +9 -0
  144. package/components/ConversationsSidebar.d.ts.map +1 -0
  145. package/components/ConversationsSidebar.js +116 -0
  146. package/components/CustomActionEditor.d.ts +10 -0
  147. package/components/CustomActionEditor.d.ts.map +1 -0
  148. package/components/CustomActionEditor.js +578 -0
  149. package/components/CustomActionsPanel.d.ts +9 -0
  150. package/components/CustomActionsPanel.d.ts.map +1 -0
  151. package/components/CustomActionsPanel.js +107 -0
  152. package/components/CustomActionsView.d.ts +2 -0
  153. package/components/CustomActionsView.d.ts.map +1 -0
  154. package/components/CustomActionsView.js +134 -0
  155. package/components/DatabasePageView.d.ts +5 -0
  156. package/components/DatabasePageView.d.ts.map +1 -0
  157. package/components/DatabasePageView.js +28 -0
  158. package/components/DatabaseView.d.ts +9 -0
  159. package/components/DatabaseView.d.ts.map +1 -0
  160. package/components/DatabaseView.js +311 -0
  161. package/components/ElizaCloudDashboard.d.ts +2 -0
  162. package/components/ElizaCloudDashboard.d.ts.map +1 -0
  163. package/components/ElizaCloudDashboard.js +657 -0
  164. package/components/EmotePicker.d.ts +2 -0
  165. package/components/EmotePicker.d.ts.map +1 -0
  166. package/components/EmotePicker.js +343 -0
  167. package/components/ErrorBoundary.d.ts +22 -0
  168. package/components/ErrorBoundary.d.ts.map +1 -0
  169. package/components/ErrorBoundary.js +31 -0
  170. package/components/FineTuningView.d.ts +2 -0
  171. package/components/FineTuningView.d.ts.map +1 -0
  172. package/components/FineTuningView.js +433 -0
  173. package/components/FlaminaGuide.d.ts +10 -0
  174. package/components/FlaminaGuide.d.ts.map +1 -0
  175. package/components/FlaminaGuide.js +64 -0
  176. package/components/GameView.d.ts +11 -0
  177. package/components/GameView.d.ts.map +1 -0
  178. package/components/GameView.js +294 -0
  179. package/components/GameViewOverlay.d.ts +8 -0
  180. package/components/GameViewOverlay.d.ts.map +1 -0
  181. package/components/GameViewOverlay.js +70 -0
  182. package/components/GlobalEmoteOverlay.d.ts +2 -0
  183. package/components/GlobalEmoteOverlay.d.ts.map +1 -0
  184. package/components/GlobalEmoteOverlay.js +112 -0
  185. package/components/Header.d.ts +9 -0
  186. package/components/Header.d.ts.map +1 -0
  187. package/components/Header.js +123 -0
  188. package/components/HeartbeatsView.d.ts +2 -0
  189. package/components/HeartbeatsView.d.ts.map +1 -0
  190. package/components/HeartbeatsView.js +378 -0
  191. package/components/InventoryView.d.ts +10 -0
  192. package/components/InventoryView.d.ts.map +1 -0
  193. package/components/InventoryView.js +176 -0
  194. package/components/KnowledgeView.d.ts +20 -0
  195. package/components/KnowledgeView.d.ts.map +1 -0
  196. package/components/KnowledgeView.js +480 -0
  197. package/components/LanguageDropdown.d.ts +30 -0
  198. package/components/LanguageDropdown.d.ts.map +1 -0
  199. package/components/LanguageDropdown.js +99 -0
  200. package/components/LifoMonitorPanel.d.ts +21 -0
  201. package/components/LifoMonitorPanel.d.ts.map +1 -0
  202. package/components/LifoMonitorPanel.js +24 -0
  203. package/components/LifoSandboxView.d.ts +5 -0
  204. package/components/LifoSandboxView.d.ts.map +1 -0
  205. package/components/LifoSandboxView.js +333 -0
  206. package/components/LoadingScreen.d.ts +13 -0
  207. package/components/LoadingScreen.d.ts.map +1 -0
  208. package/components/LoadingScreen.js +70 -0
  209. package/components/LogsPageView.d.ts +2 -0
  210. package/components/LogsPageView.d.ts.map +1 -0
  211. package/components/LogsPageView.js +7 -0
  212. package/components/LogsView.d.ts +5 -0
  213. package/components/LogsView.d.ts.map +1 -0
  214. package/components/LogsView.js +71 -0
  215. package/components/MediaGalleryView.d.ts +9 -0
  216. package/components/MediaGalleryView.d.ts.map +1 -0
  217. package/components/MediaGalleryView.js +236 -0
  218. package/components/MediaSettingsSection.d.ts +11 -0
  219. package/components/MediaSettingsSection.d.ts.map +1 -0
  220. package/components/MediaSettingsSection.js +329 -0
  221. package/components/MessageContent.d.ts +51 -0
  222. package/components/MessageContent.d.ts.map +1 -0
  223. package/components/MessageContent.js +553 -0
  224. package/components/OnboardingWizard.d.ts +2 -0
  225. package/components/OnboardingWizard.d.ts.map +1 -0
  226. package/components/OnboardingWizard.js +96 -0
  227. package/components/PairingView.d.ts +5 -0
  228. package/components/PairingView.d.ts.map +1 -0
  229. package/components/PairingView.js +29 -0
  230. package/components/PermissionsSection.d.ts +20 -0
  231. package/components/PermissionsSection.d.ts.map +1 -0
  232. package/components/PermissionsSection.js +573 -0
  233. package/components/PluginsPageView.d.ts +5 -0
  234. package/components/PluginsPageView.d.ts.map +1 -0
  235. package/components/PluginsPageView.js +8 -0
  236. package/components/PluginsView.d.ts +21 -0
  237. package/components/PluginsView.d.ts.map +1 -0
  238. package/components/PluginsView.js +1534 -0
  239. package/components/ProviderSwitcher.d.ts +42 -0
  240. package/components/ProviderSwitcher.d.ts.map +1 -0
  241. package/components/ProviderSwitcher.js +493 -0
  242. package/components/RestartBanner.d.ts +2 -0
  243. package/components/RestartBanner.d.ts.map +1 -0
  244. package/components/RestartBanner.js +36 -0
  245. package/components/RuntimeView.d.ts +10 -0
  246. package/components/RuntimeView.d.ts.map +1 -0
  247. package/components/RuntimeView.js +165 -0
  248. package/components/SaveCommandModal.d.ts +12 -0
  249. package/components/SaveCommandModal.d.ts.map +1 -0
  250. package/components/SaveCommandModal.js +84 -0
  251. package/components/SecretsView.d.ts +9 -0
  252. package/components/SecretsView.d.ts.map +1 -0
  253. package/components/SecretsView.js +249 -0
  254. package/components/SettingsView.d.ts +9 -0
  255. package/components/SettingsView.d.ts.map +1 -0
  256. package/components/SettingsView.js +230 -0
  257. package/components/ShellOverlays.d.ts +8 -0
  258. package/components/ShellOverlays.d.ts.map +1 -0
  259. package/components/ShellOverlays.js +10 -0
  260. package/components/ShortcutsOverlay.d.ts +2 -0
  261. package/components/ShortcutsOverlay.d.ts.map +1 -0
  262. package/components/ShortcutsOverlay.js +79 -0
  263. package/components/SkillsView.d.ts +11 -0
  264. package/components/SkillsView.d.ts.map +1 -0
  265. package/components/SkillsView.js +358 -0
  266. package/components/StartupFailureView.d.ts +8 -0
  267. package/components/StartupFailureView.d.ts.map +1 -0
  268. package/components/StartupFailureView.js +16 -0
  269. package/components/StreamView.d.ts +16 -0
  270. package/components/StreamView.d.ts.map +1 -0
  271. package/components/StreamView.js +300 -0
  272. package/components/StripeEmbeddedCheckout.d.ts +24 -0
  273. package/components/StripeEmbeddedCheckout.d.ts.map +1 -0
  274. package/components/StripeEmbeddedCheckout.js +101 -0
  275. package/components/SubscriptionStatus.d.ts +23 -0
  276. package/components/SubscriptionStatus.d.ts.map +1 -0
  277. package/components/SubscriptionStatus.js +301 -0
  278. package/components/SystemWarningBanner.d.ts +6 -0
  279. package/components/SystemWarningBanner.d.ts.map +1 -0
  280. package/components/SystemWarningBanner.js +46 -0
  281. package/components/ThemeToggle.d.ts +21 -0
  282. package/components/ThemeToggle.d.ts.map +1 -0
  283. package/components/ThemeToggle.js +24 -0
  284. package/components/TrajectoriesView.d.ts +12 -0
  285. package/components/TrajectoriesView.d.ts.map +1 -0
  286. package/components/TrajectoriesView.js +183 -0
  287. package/components/TrajectoryDetailView.d.ts +13 -0
  288. package/components/TrajectoryDetailView.d.ts.map +1 -0
  289. package/components/TrajectoryDetailView.js +112 -0
  290. package/components/TriggersView.d.ts +2 -0
  291. package/components/TriggersView.d.ts.map +1 -0
  292. package/components/VectorBrowserView.d.ts +10 -0
  293. package/components/VectorBrowserView.d.ts.map +1 -0
  294. package/components/VectorBrowserView.js +997 -0
  295. package/components/VoiceConfigView.d.ts +11 -0
  296. package/components/VoiceConfigView.d.ts.map +1 -0
  297. package/components/VoiceConfigView.js +329 -0
  298. package/components/VrmStage.d.ts +28 -0
  299. package/components/VrmStage.d.ts.map +1 -0
  300. package/components/VrmStage.js +178 -0
  301. package/components/WhatsAppQrOverlay.d.ts +8 -0
  302. package/components/WhatsAppQrOverlay.d.ts.map +1 -0
  303. package/components/WhatsAppQrOverlay.js +63 -0
  304. package/components/apps/AppDetailPane.d.ts +15 -0
  305. package/components/apps/AppDetailPane.d.ts.map +1 -0
  306. package/components/apps/AppDetailPane.js +13 -0
  307. package/components/apps/AppsCatalogGrid.d.ts +20 -0
  308. package/components/apps/AppsCatalogGrid.d.ts.map +1 -0
  309. package/components/apps/AppsCatalogGrid.js +18 -0
  310. package/components/apps/extensions/registry.d.ts +4 -0
  311. package/components/apps/extensions/registry.d.ts.map +1 -0
  312. package/components/apps/extensions/registry.js +7 -0
  313. package/components/apps/extensions/types.d.ts +7 -0
  314. package/components/apps/extensions/types.d.ts.map +1 -0
  315. package/components/apps/extensions/types.js +1 -0
  316. package/components/apps/helpers.d.ts +7 -0
  317. package/components/apps/helpers.d.ts.map +1 -0
  318. package/components/apps/helpers.js +44 -0
  319. package/components/avatar/VrmAnimationLoader.d.ts +30 -0
  320. package/components/avatar/VrmAnimationLoader.d.ts.map +1 -0
  321. package/components/avatar/VrmAnimationLoader.js +99 -0
  322. package/components/avatar/VrmBlinkController.d.ts +37 -0
  323. package/components/avatar/VrmBlinkController.d.ts.map +1 -0
  324. package/components/avatar/VrmBlinkController.js +98 -0
  325. package/components/avatar/VrmCameraManager.d.ts +57 -0
  326. package/components/avatar/VrmCameraManager.d.ts.map +1 -0
  327. package/components/avatar/VrmCameraManager.js +277 -0
  328. package/components/avatar/VrmEngine.d.ts +246 -0
  329. package/components/avatar/VrmEngine.d.ts.map +1 -0
  330. package/components/avatar/VrmEngine.js +2076 -0
  331. package/components/avatar/VrmFootShadow.d.ts +18 -0
  332. package/components/avatar/VrmFootShadow.d.ts.map +1 -0
  333. package/components/avatar/VrmFootShadow.js +83 -0
  334. package/components/avatar/VrmViewer.d.ts +60 -0
  335. package/components/avatar/VrmViewer.d.ts.map +1 -0
  336. package/components/avatar/VrmViewer.js +396 -0
  337. package/components/avatar/mixamoVRMRigMap.d.ts +3 -0
  338. package/components/avatar/mixamoVRMRigMap.d.ts.map +1 -0
  339. package/components/avatar/mixamoVRMRigMap.js +56 -0
  340. package/components/avatar/retargetMixamoFbxToVrm.d.ts +9 -0
  341. package/components/avatar/retargetMixamoFbxToVrm.d.ts.map +1 -0
  342. package/components/avatar/retargetMixamoFbxToVrm.js +88 -0
  343. package/components/avatar/retargetMixamoGltfToVrm.d.ts +11 -0
  344. package/components/avatar/retargetMixamoGltfToVrm.d.ts.map +1 -0
  345. package/components/avatar/retargetMixamoGltfToVrm.js +80 -0
  346. package/components/chainConfig.d.ts +89 -0
  347. package/components/chainConfig.d.ts.map +1 -0
  348. package/components/chainConfig.js +287 -0
  349. package/components/companion/CompanionHeader.d.ts +15 -0
  350. package/components/companion/CompanionHeader.d.ts.map +1 -0
  351. package/components/companion/CompanionHeader.js +7 -0
  352. package/components/companion/CompanionSceneHost.d.ts +2 -0
  353. package/components/companion/CompanionSceneHost.d.ts.map +1 -0
  354. package/components/companion/CompanionSceneHost.js +1 -0
  355. package/components/companion/VrmStage.d.ts +3 -0
  356. package/components/companion/VrmStage.d.ts.map +1 -0
  357. package/components/companion/VrmStage.js +1 -0
  358. package/components/companion/index.d.ts +18 -0
  359. package/components/companion/index.d.ts.map +1 -0
  360. package/components/companion/index.js +17 -0
  361. package/components/companion/walletUtils.d.ts +95 -0
  362. package/components/companion/walletUtils.d.ts.map +1 -0
  363. package/components/companion/walletUtils.js +167 -0
  364. package/components/companion-shell-styles.d.ts +38 -0
  365. package/components/companion-shell-styles.d.ts.map +1 -0
  366. package/components/companion-shell-styles.js +248 -0
  367. package/components/confirm-delete-control.d.ts +16 -0
  368. package/components/confirm-delete-control.d.ts.map +1 -0
  369. package/components/confirm-delete-control.js +12 -0
  370. package/components/conversations/ConversationListItem.d.ts +31 -0
  371. package/components/conversations/ConversationListItem.d.ts.map +1 -0
  372. package/components/conversations/ConversationListItem.js +52 -0
  373. package/components/conversations/conversation-utils.d.ts +9 -0
  374. package/components/conversations/conversation-utils.d.ts.map +1 -0
  375. package/components/conversations/conversation-utils.js +138 -0
  376. package/components/format.d.ts +54 -0
  377. package/components/format.d.ts.map +1 -0
  378. package/components/format.js +82 -0
  379. package/components/index.d.ts +96 -0
  380. package/components/index.d.ts.map +1 -0
  381. package/components/index.js +95 -0
  382. package/components/inventory/CopyableAddress.d.ts +8 -0
  383. package/components/inventory/CopyableAddress.d.ts.map +1 -0
  384. package/components/inventory/CopyableAddress.js +18 -0
  385. package/components/inventory/InventoryToolbar.d.ts +25 -0
  386. package/components/inventory/InventoryToolbar.d.ts.map +1 -0
  387. package/components/inventory/InventoryToolbar.js +28 -0
  388. package/components/inventory/NftGrid.d.ts +13 -0
  389. package/components/inventory/NftGrid.d.ts.map +1 -0
  390. package/components/inventory/NftGrid.js +29 -0
  391. package/components/inventory/TokenLogo.d.ts +12 -0
  392. package/components/inventory/TokenLogo.d.ts.map +1 -0
  393. package/components/inventory/TokenLogo.js +33 -0
  394. package/components/inventory/TokensTable.d.ts +24 -0
  395. package/components/inventory/TokensTable.d.ts.map +1 -0
  396. package/components/inventory/TokensTable.js +26 -0
  397. package/components/inventory/constants.d.ts +52 -0
  398. package/components/inventory/constants.d.ts.map +1 -0
  399. package/components/inventory/constants.js +121 -0
  400. package/components/inventory/index.d.ts +9 -0
  401. package/components/inventory/index.d.ts.map +1 -0
  402. package/components/inventory/index.js +8 -0
  403. package/components/inventory/media-url.d.ts +6 -0
  404. package/components/inventory/media-url.d.ts.map +1 -0
  405. package/components/inventory/media-url.js +28 -0
  406. package/components/inventory/useInventoryData.d.ts +53 -0
  407. package/components/inventory/useInventoryData.d.ts.map +1 -0
  408. package/components/inventory/useInventoryData.js +332 -0
  409. package/components/knowledge-upload-image.d.ts +27 -0
  410. package/components/knowledge-upload-image.d.ts.map +1 -0
  411. package/components/knowledge-upload-image.js +146 -0
  412. package/components/labels.d.ts +6 -0
  413. package/components/labels.d.ts.map +1 -0
  414. package/components/labels.js +40 -0
  415. package/components/onboarding/ActivateStep.d.ts +2 -0
  416. package/components/onboarding/ActivateStep.d.ts.map +1 -0
  417. package/components/onboarding/ActivateStep.js +10 -0
  418. package/components/onboarding/ConnectionStep.d.ts +2 -0
  419. package/components/onboarding/ConnectionStep.d.ts.map +1 -0
  420. package/components/onboarding/ConnectionStep.js +609 -0
  421. package/components/onboarding/IdentityStep.d.ts +2 -0
  422. package/components/onboarding/IdentityStep.d.ts.map +1 -0
  423. package/components/onboarding/IdentityStep.js +102 -0
  424. package/components/onboarding/OnboardingPanel.d.ts +9 -0
  425. package/components/onboarding/OnboardingPanel.d.ts.map +1 -0
  426. package/components/onboarding/OnboardingPanel.js +24 -0
  427. package/components/onboarding/OnboardingStepNav.d.ts +2 -0
  428. package/components/onboarding/OnboardingStepNav.d.ts.map +1 -0
  429. package/components/onboarding/OnboardingStepNav.js +23 -0
  430. package/components/onboarding/PermissionsStep.d.ts +2 -0
  431. package/components/onboarding/PermissionsStep.d.ts.map +1 -0
  432. package/components/onboarding/PermissionsStep.js +7 -0
  433. package/components/onboarding/RpcStep.d.ts +2 -0
  434. package/components/onboarding/RpcStep.d.ts.map +1 -0
  435. package/components/onboarding/RpcStep.js +125 -0
  436. package/components/permissions/PermissionIcon.d.ts +4 -0
  437. package/components/permissions/PermissionIcon.d.ts.map +1 -0
  438. package/components/permissions/PermissionIcon.js +12 -0
  439. package/components/permissions/StreamingPermissions.d.ts +20 -0
  440. package/components/permissions/StreamingPermissions.d.ts.map +1 -0
  441. package/components/permissions/StreamingPermissions.js +177 -0
  442. package/components/plugins/showcase-data.d.ts +7 -0
  443. package/components/plugins/showcase-data.d.ts.map +1 -0
  444. package/components/plugins/showcase-data.js +464 -0
  445. package/components/shared/ShellHeaderControls.d.ts +27 -0
  446. package/components/shared/ShellHeaderControls.d.ts.map +1 -0
  447. package/components/shared/ShellHeaderControls.js +60 -0
  448. package/components/shared-companion-scene-context.d.ts +3 -0
  449. package/components/shared-companion-scene-context.d.ts.map +1 -0
  450. package/components/shared-companion-scene-context.js +13 -0
  451. package/components/skeletons.d.ts +17 -0
  452. package/components/skeletons.d.ts.map +1 -0
  453. package/components/skeletons.js +22 -0
  454. package/components/stream/ActivityFeed.d.ts +5 -0
  455. package/components/stream/ActivityFeed.d.ts.map +1 -0
  456. package/components/stream/ActivityFeed.js +57 -0
  457. package/components/stream/AvatarPip.d.ts +5 -0
  458. package/components/stream/AvatarPip.d.ts.map +1 -0
  459. package/components/stream/AvatarPip.js +6 -0
  460. package/components/stream/ChatContent.d.ts +6 -0
  461. package/components/stream/ChatContent.d.ts.map +1 -0
  462. package/components/stream/ChatContent.js +69 -0
  463. package/components/stream/ChatTicker.d.ts +5 -0
  464. package/components/stream/ChatTicker.d.ts.map +1 -0
  465. package/components/stream/ChatTicker.js +34 -0
  466. package/components/stream/IdleContent.d.ts +5 -0
  467. package/components/stream/IdleContent.d.ts.map +1 -0
  468. package/components/stream/IdleContent.js +17 -0
  469. package/components/stream/StatusBar.d.ts +36 -0
  470. package/components/stream/StatusBar.d.ts.map +1 -0
  471. package/components/stream/StatusBar.js +140 -0
  472. package/components/stream/StreamSettings.d.ts +33 -0
  473. package/components/stream/StreamSettings.d.ts.map +1 -0
  474. package/components/stream/StreamSettings.js +99 -0
  475. package/components/stream/StreamTerminal.d.ts +2 -0
  476. package/components/stream/StreamTerminal.d.ts.map +1 -0
  477. package/components/stream/StreamTerminal.js +52 -0
  478. package/components/stream/StreamVoiceConfig.d.ts +10 -0
  479. package/components/stream/StreamVoiceConfig.d.ts.map +1 -0
  480. package/components/stream/StreamVoiceConfig.js +88 -0
  481. package/components/stream/helpers.d.ts +32 -0
  482. package/components/stream/helpers.d.ts.map +1 -0
  483. package/components/stream/helpers.js +110 -0
  484. package/components/stream/overlays/OverlayLayer.d.ts +20 -0
  485. package/components/stream/overlays/OverlayLayer.d.ts.map +1 -0
  486. package/components/stream/overlays/OverlayLayer.js +24 -0
  487. package/components/stream/overlays/built-in/ActionTickerWidget.d.ts +8 -0
  488. package/components/stream/overlays/built-in/ActionTickerWidget.d.ts.map +1 -0
  489. package/components/stream/overlays/built-in/ActionTickerWidget.js +44 -0
  490. package/components/stream/overlays/built-in/AlertPopupWidget.d.ts +7 -0
  491. package/components/stream/overlays/built-in/AlertPopupWidget.d.ts.map +1 -0
  492. package/components/stream/overlays/built-in/AlertPopupWidget.js +62 -0
  493. package/components/stream/overlays/built-in/BrandingWidget.d.ts +7 -0
  494. package/components/stream/overlays/built-in/BrandingWidget.d.ts.map +1 -0
  495. package/components/stream/overlays/built-in/BrandingWidget.js +36 -0
  496. package/components/stream/overlays/built-in/CustomHtmlWidget.d.ts +26 -0
  497. package/components/stream/overlays/built-in/CustomHtmlWidget.d.ts.map +1 -0
  498. package/components/stream/overlays/built-in/CustomHtmlWidget.js +78 -0
  499. package/components/stream/overlays/built-in/PeonGlassWidget.d.ts +11 -0
  500. package/components/stream/overlays/built-in/PeonGlassWidget.d.ts.map +1 -0
  501. package/components/stream/overlays/built-in/PeonGlassWidget.js +188 -0
  502. package/components/stream/overlays/built-in/PeonHudWidget.d.ts +10 -0
  503. package/components/stream/overlays/built-in/PeonHudWidget.d.ts.map +1 -0
  504. package/components/stream/overlays/built-in/PeonHudWidget.js +168 -0
  505. package/components/stream/overlays/built-in/PeonSakuraWidget.d.ts +11 -0
  506. package/components/stream/overlays/built-in/PeonSakuraWidget.d.ts.map +1 -0
  507. package/components/stream/overlays/built-in/PeonSakuraWidget.js +213 -0
  508. package/components/stream/overlays/built-in/ThoughtBubbleWidget.d.ts +8 -0
  509. package/components/stream/overlays/built-in/ThoughtBubbleWidget.d.ts.map +1 -0
  510. package/components/stream/overlays/built-in/ThoughtBubbleWidget.js +59 -0
  511. package/components/stream/overlays/built-in/ViewerCountWidget.d.ts +7 -0
  512. package/components/stream/overlays/built-in/ViewerCountWidget.d.ts.map +1 -0
  513. package/components/stream/overlays/built-in/ViewerCountWidget.js +34 -0
  514. package/components/stream/overlays/built-in/index.d.ts +13 -0
  515. package/components/stream/overlays/built-in/index.d.ts.map +1 -0
  516. package/components/stream/overlays/built-in/index.js +12 -0
  517. package/components/stream/overlays/registry.d.ts +11 -0
  518. package/components/stream/overlays/registry.d.ts.map +1 -0
  519. package/components/stream/overlays/registry.js +16 -0
  520. package/components/stream/overlays/types.d.ts +67 -0
  521. package/components/stream/overlays/types.d.ts.map +1 -0
  522. package/components/stream/overlays/types.js +7 -0
  523. package/components/stream/overlays/useOverlayLayout.d.ts +27 -0
  524. package/components/stream/overlays/useOverlayLayout.d.ts.map +1 -0
  525. package/components/stream/overlays/useOverlayLayout.js +162 -0
  526. package/components/trajectory-format.d.ts +6 -0
  527. package/components/trajectory-format.d.ts.map +1 -0
  528. package/components/trajectory-format.js +43 -0
  529. package/components/ui-badges.d.ts +23 -0
  530. package/components/ui-badges.d.ts.map +1 -0
  531. package/components/ui-badges.js +38 -0
  532. package/components/ui-switch.d.ts +14 -0
  533. package/components/ui-switch.d.ts.map +1 -0
  534. package/components/ui-switch.js +15 -0
  535. package/components/vector-browser-three.d.ts +4 -0
  536. package/components/vector-browser-three.d.ts.map +1 -0
  537. package/components/vector-browser-three.js +21 -0
  538. package/config/branding.d.ts +49 -0
  539. package/config/branding.d.ts.map +1 -0
  540. package/config/branding.js +16 -0
  541. package/config/config-catalog.d.ts +376 -0
  542. package/config/config-catalog.d.ts.map +1 -0
  543. package/config/config-catalog.js +724 -0
  544. package/config/config-field.d.ts +68 -0
  545. package/config/config-field.d.ts.map +1 -0
  546. package/config/config-field.js +840 -0
  547. package/config/config-renderer.d.ts +176 -0
  548. package/config/config-renderer.d.ts.map +1 -0
  549. package/config/config-renderer.js +405 -0
  550. package/config/index.d.ts +6 -0
  551. package/config/index.d.ts.map +1 -0
  552. package/config/index.js +5 -0
  553. package/config/ui-renderer.d.ts +26 -0
  554. package/config/ui-renderer.d.ts.map +1 -0
  555. package/config/ui-renderer.js +815 -0
  556. package/config/ui-spec.d.ts +164 -0
  557. package/config/ui-spec.d.ts.map +1 -0
  558. package/config/ui-spec.js +13 -0
  559. package/events/index.d.ts +47 -0
  560. package/events/index.d.ts.map +1 -0
  561. package/events/index.js +43 -0
  562. package/hooks/index.d.ts +15 -0
  563. package/hooks/index.d.ts.map +1 -0
  564. package/hooks/useBugReport.d.ts +14 -0
  565. package/hooks/useBugReport.d.ts.map +1 -0
  566. package/hooks/useBugReport.js +18 -0
  567. package/hooks/useCanvasWindow.d.ts +38 -0
  568. package/hooks/useCanvasWindow.d.ts.map +1 -0
  569. package/hooks/useCanvasWindow.js +273 -0
  570. package/hooks/useChatAvatarVoice.d.ts +10 -0
  571. package/hooks/useChatAvatarVoice.d.ts.map +1 -0
  572. package/hooks/useChatAvatarVoice.js +71 -0
  573. package/hooks/useClickOutside.d.ts +6 -0
  574. package/hooks/useClickOutside.d.ts.map +1 -0
  575. package/hooks/useClickOutside.js +25 -0
  576. package/hooks/useContextMenu.d.ts +17 -0
  577. package/hooks/useContextMenu.d.ts.map +1 -0
  578. package/hooks/useContextMenu.js +100 -0
  579. package/hooks/useKeyboardShortcuts.d.ts +17 -0
  580. package/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  581. package/hooks/useKeyboardShortcuts.js +67 -0
  582. package/hooks/useLifoSync.d.ts +18 -0
  583. package/hooks/useLifoSync.d.ts.map +1 -0
  584. package/hooks/useLifoSync.js +113 -0
  585. package/hooks/useMemoryMonitor.d.ts +87 -0
  586. package/hooks/useMemoryMonitor.d.ts.map +1 -0
  587. package/hooks/useMemoryMonitor.js +209 -0
  588. package/hooks/useRenderGuard.d.ts +17 -0
  589. package/hooks/useRenderGuard.d.ts.map +1 -0
  590. package/hooks/useRenderGuard.js +36 -0
  591. package/hooks/useRetakeCapture.d.ts +12 -0
  592. package/hooks/useRetakeCapture.d.ts.map +1 -0
  593. package/hooks/useRetakeCapture.js +60 -0
  594. package/hooks/useStreamPopoutNavigation.d.ts +3 -0
  595. package/hooks/useStreamPopoutNavigation.d.ts.map +1 -0
  596. package/hooks/useStreamPopoutNavigation.js +17 -0
  597. package/hooks/useTimeout.d.ts +11 -0
  598. package/hooks/useTimeout.d.ts.map +1 -0
  599. package/hooks/useTimeout.js +32 -0
  600. package/hooks/useVoiceChat.d.ts +94 -0
  601. package/hooks/useVoiceChat.d.ts.map +1 -0
  602. package/hooks/useVoiceChat.js +1074 -0
  603. package/hooks/useWhatsAppPairing.d.ts +11 -0
  604. package/hooks/useWhatsAppPairing.d.ts.map +1 -0
  605. package/hooks/useWhatsAppPairing.js +95 -0
  606. package/i18n/index.d.ts +7 -0
  607. package/i18n/index.d.ts.map +1 -0
  608. package/i18n/index.js +53 -0
  609. package/i18n/locales/en.json +1239 -0
  610. package/i18n/locales/es.json +1236 -0
  611. package/i18n/locales/ko.json +1236 -0
  612. package/i18n/locales/pt.json +1236 -0
  613. package/i18n/locales/zh-CN.json +1236 -0
  614. package/i18n/messages.d.ts +6 -0
  615. package/i18n/messages.d.ts.map +1 -0
  616. package/i18n/messages.js +14 -0
  617. package/index.d.ts +5 -0
  618. package/index.d.ts.map +1 -0
  619. package/navigation/index.d.ts +27 -0
  620. package/navigation/index.d.ts.map +1 -0
  621. package/navigation/index.js +232 -0
  622. package/onboarding-config.d.ts +25 -0
  623. package/onboarding-config.d.ts.map +1 -0
  624. package/onboarding-config.js +76 -0
  625. package/package.json +143 -53
  626. package/platform/browser-launch.d.ts +2 -0
  627. package/platform/browser-launch.d.ts.map +1 -0
  628. package/platform/browser-launch.js +109 -0
  629. package/platform/index.d.ts +14 -0
  630. package/platform/index.d.ts.map +1 -0
  631. package/platform/index.js +24 -0
  632. package/platform/init.d.ts +40 -0
  633. package/platform/init.d.ts.map +1 -0
  634. package/platform/init.js +160 -0
  635. package/platform/lifo.d.ts +51 -0
  636. package/platform/lifo.d.ts.map +1 -0
  637. package/platform/lifo.js +138 -0
  638. package/providers/index.d.ts +19 -0
  639. package/providers/index.d.ts.map +1 -0
  640. package/providers/index.js +80 -0
  641. package/shell-params.d.ts +12 -0
  642. package/shell-params.d.ts.map +1 -0
  643. package/shell-params.js +19 -0
  644. package/state/AppContext.d.ts +12 -0
  645. package/state/AppContext.d.ts.map +1 -0
  646. package/state/AppContext.js +5060 -0
  647. package/state/index.d.ts +7 -0
  648. package/state/index.d.ts.map +1 -0
  649. package/state/internal.d.ts +7 -0
  650. package/state/internal.d.ts.map +1 -0
  651. package/state/internal.js +6 -0
  652. package/state/onboarding-resume.d.ts +11 -0
  653. package/state/onboarding-resume.d.ts.map +1 -0
  654. package/state/onboarding-resume.js +189 -0
  655. package/state/parsers.d.ts +26 -0
  656. package/state/parsers.d.ts.map +1 -0
  657. package/state/parsers.js +255 -0
  658. package/state/persistence.d.ts +59 -0
  659. package/state/persistence.d.ts.map +1 -0
  660. package/state/persistence.js +326 -0
  661. package/state/shell-routing.d.ts +12 -0
  662. package/state/shell-routing.d.ts.map +1 -0
  663. package/state/shell-routing.js +25 -0
  664. package/state/types.d.ts +421 -0
  665. package/state/types.d.ts.map +1 -0
  666. package/state/types.js +75 -0
  667. package/state/ui-preferences.d.ts +3 -0
  668. package/state/ui-preferences.d.ts.map +1 -0
  669. package/state/ui-preferences.js +1 -0
  670. package/state/useApp.d.ts +4 -0
  671. package/state/useApp.d.ts.map +1 -0
  672. package/state/useApp.js +22 -0
  673. package/state/vrm.d.ts +30 -0
  674. package/state/vrm.d.ts.map +1 -0
  675. package/state/vrm.js +82 -0
  676. package/styles/anime.css +6321 -0
  677. package/styles/onboarding-game.css +1092 -0
  678. package/types/index.d.ts +657 -0
  679. package/types/index.d.ts.map +1 -0
  680. package/types/index.js +1 -0
  681. package/utils/asset-url.d.ts +26 -0
  682. package/utils/asset-url.d.ts.map +1 -0
  683. package/utils/asset-url.js +99 -0
  684. package/utils/assistant-text.d.ts +2 -0
  685. package/utils/assistant-text.d.ts.map +1 -0
  686. package/utils/assistant-text.js +161 -0
  687. package/utils/clipboard.d.ts +2 -0
  688. package/utils/clipboard.d.ts.map +1 -0
  689. package/utils/clipboard.js +38 -0
  690. package/utils/desktop-dialogs.d.ts +19 -0
  691. package/utils/desktop-dialogs.d.ts.map +1 -0
  692. package/utils/desktop-dialogs.js +50 -0
  693. package/utils/eliza-globals.d.ts +11 -0
  694. package/utils/eliza-globals.d.ts.map +1 -0
  695. package/utils/eliza-globals.js +33 -0
  696. package/utils/index.d.ts +8 -0
  697. package/utils/index.d.ts.map +1 -0
  698. package/utils/number-parsing.d.ts +44 -0
  699. package/utils/number-parsing.d.ts.map +1 -0
  700. package/utils/number-parsing.js +56 -0
  701. package/utils/openExternalUrl.d.ts +2 -0
  702. package/utils/openExternalUrl.d.ts.map +1 -0
  703. package/utils/openExternalUrl.js +17 -0
  704. package/utils/spoken-text.d.ts +2 -0
  705. package/utils/spoken-text.d.ts.map +1 -0
  706. package/utils/spoken-text.js +56 -0
  707. package/utils/streaming-text.d.ts +3 -0
  708. package/utils/streaming-text.d.ts.map +1 -0
  709. package/utils/streaming-text.js +87 -0
  710. package/voice/index.d.ts +2 -0
  711. package/voice/index.d.ts.map +1 -0
  712. package/voice/types.d.ts +25 -0
  713. package/voice/types.d.ts.map +1 -0
  714. package/voice/types.js +166 -0
  715. package/wallet-rpc.d.ts +8 -0
  716. package/wallet-rpc.d.ts.map +1 -0
  717. package/wallet-rpc.js +131 -0
  718. package/.turbo/turbo-build.log +0 -5
  719. package/src/App.tsx +0 -504
  720. package/src/actions/character.test.ts +0 -139
  721. package/src/actions/character.ts +0 -334
  722. package/src/actions/chat-helpers.ts +0 -100
  723. package/src/actions/cloud.ts +0 -59
  724. package/src/actions/index.ts +0 -12
  725. package/src/actions/lifecycle.ts +0 -175
  726. package/src/actions/onboarding.ts +0 -38
  727. package/src/actions/triggers.ts +0 -190
  728. package/src/ambient.d.ts +0 -33
  729. package/src/api/client.ts +0 -5659
  730. package/src/autonomy/index.ts +0 -477
  731. package/src/bridge/capacitor-bridge.ts +0 -295
  732. package/src/bridge/electrobun-rpc.ts +0 -78
  733. package/src/bridge/electrobun-runtime.ts +0 -28
  734. package/src/bridge/native-plugins.ts +0 -138
  735. package/src/bridge/plugin-bridge.ts +0 -352
  736. package/src/bridge/storage-bridge.ts +0 -162
  737. package/src/chat/index.ts +0 -250
  738. package/src/coding/index.ts +0 -43
  739. package/src/components/AdvancedPageView.tsx +0 -382
  740. package/src/components/AgentActivityBox.tsx +0 -49
  741. package/src/components/ApiKeyConfig.tsx +0 -222
  742. package/src/components/AppsPageView.tsx +0 -52
  743. package/src/components/AppsView.tsx +0 -293
  744. package/src/components/AvatarLoader.tsx +0 -104
  745. package/src/components/AvatarSelector.tsx +0 -223
  746. package/src/components/BscTradePanel.tsx +0 -549
  747. package/src/components/BugReportModal.tsx +0 -499
  748. package/src/components/CharacterRoster.tsx +0 -143
  749. package/src/components/CharacterView.tsx +0 -1575
  750. package/src/components/ChatAvatar.test.ts +0 -97
  751. package/src/components/ChatAvatar.tsx +0 -147
  752. package/src/components/ChatComposer.tsx +0 -330
  753. package/src/components/ChatMessage.tsx +0 -448
  754. package/src/components/ChatModalView.test.tsx +0 -118
  755. package/src/components/ChatModalView.tsx +0 -125
  756. package/src/components/ChatView.tsx +0 -992
  757. package/src/components/CloudOnboarding.tsx +0 -81
  758. package/src/components/CloudSourceControls.tsx +0 -85
  759. package/src/components/CodingAgentSettingsSection.tsx +0 -537
  760. package/src/components/CommandPalette.tsx +0 -284
  761. package/src/components/CompanionSceneHost.tsx +0 -517
  762. package/src/components/CompanionShell.tsx +0 -31
  763. package/src/components/CompanionView.tsx +0 -110
  764. package/src/components/ConfigPageView.tsx +0 -763
  765. package/src/components/ConfigSaveFooter.tsx +0 -41
  766. package/src/components/ConfirmModal.tsx +0 -379
  767. package/src/components/ConnectionFailedBanner.tsx +0 -91
  768. package/src/components/ConnectorsPageView.tsx +0 -13
  769. package/src/components/ConversationsSidebar.tsx +0 -279
  770. package/src/components/CustomActionEditor.tsx +0 -1127
  771. package/src/components/CustomActionsPanel.tsx +0 -288
  772. package/src/components/CustomActionsView.tsx +0 -325
  773. package/src/components/DatabasePageView.tsx +0 -55
  774. package/src/components/DatabaseView.tsx +0 -814
  775. package/src/components/ElizaCloudDashboard.tsx +0 -1696
  776. package/src/components/EmotePicker.tsx +0 -529
  777. package/src/components/ErrorBoundary.tsx +0 -76
  778. package/src/components/FineTuningView.tsx +0 -1080
  779. package/src/components/FlaminaGuide.test.tsx +0 -61
  780. package/src/components/FlaminaGuide.tsx +0 -212
  781. package/src/components/GameView.tsx +0 -551
  782. package/src/components/GameViewOverlay.tsx +0 -133
  783. package/src/components/GlobalEmoteOverlay.tsx +0 -152
  784. package/src/components/Header.test.tsx +0 -413
  785. package/src/components/Header.tsx +0 -400
  786. package/src/components/HeartbeatsView.tsx +0 -1003
  787. package/src/components/InventoryView.tsx +0 -393
  788. package/src/components/KnowledgeView.tsx +0 -1128
  789. package/src/components/LanguageDropdown.tsx +0 -192
  790. package/src/components/LifoMonitorPanel.tsx +0 -196
  791. package/src/components/LifoSandboxView.tsx +0 -499
  792. package/src/components/LoadingScreen.tsx +0 -112
  793. package/src/components/LogsPageView.tsx +0 -17
  794. package/src/components/LogsView.tsx +0 -239
  795. package/src/components/MediaGalleryView.tsx +0 -431
  796. package/src/components/MediaSettingsSection.tsx +0 -893
  797. package/src/components/MessageContent.tsx +0 -815
  798. package/src/components/MiladyBar.tsx +0 -103
  799. package/src/components/MiladyBarSettings.tsx +0 -872
  800. package/src/components/OnboardingWizard.test.tsx +0 -104
  801. package/src/components/OnboardingWizard.tsx +0 -249
  802. package/src/components/PairingView.tsx +0 -109
  803. package/src/components/PermissionsSection.tsx +0 -1184
  804. package/src/components/PluginsPageView.tsx +0 -9
  805. package/src/components/PluginsView.tsx +0 -3129
  806. package/src/components/ProviderSwitcher.tsx +0 -903
  807. package/src/components/RestartBanner.tsx +0 -76
  808. package/src/components/RuntimeView.tsx +0 -460
  809. package/src/components/SaveCommandModal.tsx +0 -211
  810. package/src/components/SecretsView.tsx +0 -569
  811. package/src/components/SecurityPageView.tsx +0 -242
  812. package/src/components/SettingsView.tsx +0 -825
  813. package/src/components/ShellOverlays.tsx +0 -41
  814. package/src/components/ShortcutsOverlay.tsx +0 -155
  815. package/src/components/SkillsView.tsx +0 -1435
  816. package/src/components/StartupFailureView.tsx +0 -63
  817. package/src/components/StreamView.tsx +0 -481
  818. package/src/components/StripeEmbeddedCheckout.tsx +0 -155
  819. package/src/components/SubscriptionStatus.tsx +0 -640
  820. package/src/components/SystemWarningBanner.tsx +0 -71
  821. package/src/components/ThemeToggle.tsx +0 -103
  822. package/src/components/TrajectoriesView.tsx +0 -526
  823. package/src/components/TrajectoryDetailView.tsx +0 -426
  824. package/src/components/VectorBrowserView.tsx +0 -1633
  825. package/src/components/VoiceConfigView.tsx +0 -674
  826. package/src/components/VrmStage.test.ts +0 -176
  827. package/src/components/VrmStage.tsx +0 -309
  828. package/src/components/WhatsAppQrOverlay.tsx +0 -230
  829. package/src/components/__tests__/chainConfig.test.ts +0 -220
  830. package/src/components/apps/AppDetailPane.tsx +0 -242
  831. package/src/components/apps/AppsCatalogGrid.tsx +0 -137
  832. package/src/components/apps/extensions/registry.ts +0 -13
  833. package/src/components/apps/extensions/types.ts +0 -9
  834. package/src/components/apps/helpers.ts +0 -43
  835. package/src/components/avatar/VrmAnimationLoader.test.ts +0 -164
  836. package/src/components/avatar/VrmAnimationLoader.ts +0 -151
  837. package/src/components/avatar/VrmBlinkController.ts +0 -118
  838. package/src/components/avatar/VrmCameraManager.ts +0 -407
  839. package/src/components/avatar/VrmEngine.ts +0 -2767
  840. package/src/components/avatar/VrmFootShadow.ts +0 -96
  841. package/src/components/avatar/VrmViewer.tsx +0 -421
  842. package/src/components/avatar/__tests__/VrmCameraManager.test.ts +0 -168
  843. package/src/components/avatar/__tests__/VrmEngine.test.ts +0 -1574
  844. package/src/components/avatar/mixamoVRMRigMap.ts +0 -62
  845. package/src/components/avatar/retargetMixamoFbxToVrm.ts +0 -144
  846. package/src/components/avatar/retargetMixamoGltfToVrm.ts +0 -119
  847. package/src/components/chainConfig.ts +0 -400
  848. package/src/components/companion/CompanionHeader.tsx +0 -50
  849. package/src/components/companion/CompanionSceneHost.tsx +0 -5
  850. package/src/components/companion/VrmStage.tsx +0 -2
  851. package/src/components/companion/__tests__/walletUtils.test.ts +0 -742
  852. package/src/components/companion/index.ts +0 -18
  853. package/src/components/companion/walletUtils.ts +0 -290
  854. package/src/components/companion-shell-styles.test.ts +0 -142
  855. package/src/components/companion-shell-styles.ts +0 -270
  856. package/src/components/confirm-delete-control.tsx +0 -69
  857. package/src/components/conversations/ConversationListItem.tsx +0 -185
  858. package/src/components/conversations/conversation-utils.ts +0 -151
  859. package/src/components/format.ts +0 -131
  860. package/src/components/index.ts +0 -96
  861. package/src/components/inventory/CopyableAddress.tsx +0 -41
  862. package/src/components/inventory/InventoryToolbar.tsx +0 -142
  863. package/src/components/inventory/NftGrid.tsx +0 -99
  864. package/src/components/inventory/TokenLogo.tsx +0 -71
  865. package/src/components/inventory/TokensTable.tsx +0 -216
  866. package/src/components/inventory/constants.ts +0 -170
  867. package/src/components/inventory/index.ts +0 -29
  868. package/src/components/inventory/media-url.test.ts +0 -38
  869. package/src/components/inventory/media-url.ts +0 -36
  870. package/src/components/inventory/useInventoryData.ts +0 -460
  871. package/src/components/knowledge-upload-image.ts +0 -215
  872. package/src/components/labels.ts +0 -46
  873. package/src/components/milady-bar/CloudCreditsChip.tsx +0 -61
  874. package/src/components/milady-bar/ProviderDropdown.tsx +0 -166
  875. package/src/components/milady-bar/WalletSummary.tsx +0 -61
  876. package/src/components/milady-bar/index.ts +0 -3
  877. package/src/components/onboarding/ActivateStep.tsx +0 -34
  878. package/src/components/onboarding/ConnectionStep.tsx +0 -1591
  879. package/src/components/onboarding/IdentityStep.tsx +0 -251
  880. package/src/components/onboarding/OnboardingPanel.tsx +0 -39
  881. package/src/components/onboarding/OnboardingStepNav.tsx +0 -41
  882. package/src/components/onboarding/PermissionsStep.tsx +0 -20
  883. package/src/components/onboarding/RpcStep.tsx +0 -402
  884. package/src/components/permissions/PermissionIcon.tsx +0 -25
  885. package/src/components/permissions/StreamingPermissions.tsx +0 -413
  886. package/src/components/plugins/showcase-data.ts +0 -481
  887. package/src/components/shared/ShellHeaderControls.tsx +0 -198
  888. package/src/components/shared-companion-scene-context.ts +0 -15
  889. package/src/components/skeletons.tsx +0 -88
  890. package/src/components/stream/ActivityFeed.tsx +0 -113
  891. package/src/components/stream/AvatarPip.tsx +0 -10
  892. package/src/components/stream/ChatContent.tsx +0 -126
  893. package/src/components/stream/ChatTicker.tsx +0 -55
  894. package/src/components/stream/IdleContent.tsx +0 -73
  895. package/src/components/stream/StatusBar.tsx +0 -463
  896. package/src/components/stream/StreamSettings.tsx +0 -506
  897. package/src/components/stream/StreamTerminal.tsx +0 -94
  898. package/src/components/stream/StreamVoiceConfig.tsx +0 -160
  899. package/src/components/stream/helpers.ts +0 -134
  900. package/src/components/stream/overlays/OverlayLayer.tsx +0 -75
  901. package/src/components/stream/overlays/built-in/ActionTickerWidget.tsx +0 -64
  902. package/src/components/stream/overlays/built-in/AlertPopupWidget.tsx +0 -87
  903. package/src/components/stream/overlays/built-in/BrandingWidget.tsx +0 -51
  904. package/src/components/stream/overlays/built-in/CustomHtmlWidget.tsx +0 -105
  905. package/src/components/stream/overlays/built-in/PeonGlassWidget.tsx +0 -265
  906. package/src/components/stream/overlays/built-in/PeonHudWidget.tsx +0 -247
  907. package/src/components/stream/overlays/built-in/PeonSakuraWidget.tsx +0 -278
  908. package/src/components/stream/overlays/built-in/ThoughtBubbleWidget.tsx +0 -77
  909. package/src/components/stream/overlays/built-in/ViewerCountWidget.tsx +0 -46
  910. package/src/components/stream/overlays/built-in/index.ts +0 -13
  911. package/src/components/stream/overlays/registry.ts +0 -22
  912. package/src/components/stream/overlays/types.ts +0 -90
  913. package/src/components/stream/overlays/useOverlayLayout.ts +0 -218
  914. package/src/components/trajectory-format.ts +0 -50
  915. package/src/components/ui-badges.tsx +0 -109
  916. package/src/components/ui-switch.tsx +0 -57
  917. package/src/components/vector-browser-three.ts +0 -29
  918. package/src/config/branding.ts +0 -67
  919. package/src/config/config-catalog.ts +0 -1092
  920. package/src/config/config-field.tsx +0 -1924
  921. package/src/config/config-renderer.tsx +0 -734
  922. package/src/config/index.ts +0 -12
  923. package/src/config/ui-renderer.tsx +0 -1751
  924. package/src/config/ui-spec.ts +0 -256
  925. package/src/events/index.ts +0 -96
  926. package/src/hooks/useBugReport.tsx +0 -43
  927. package/src/hooks/useCanvasWindow.ts +0 -372
  928. package/src/hooks/useChatAvatarVoice.ts +0 -111
  929. package/src/hooks/useClickOutside.ts +0 -31
  930. package/src/hooks/useContextMenu.ts +0 -127
  931. package/src/hooks/useKeyboardShortcuts.ts +0 -86
  932. package/src/hooks/useLifoSync.ts +0 -143
  933. package/src/hooks/useMemoryMonitor.ts +0 -334
  934. package/src/hooks/useMiladyBar.ts +0 -594
  935. package/src/hooks/useRenderGuard.ts +0 -43
  936. package/src/hooks/useRetakeCapture.ts +0 -68
  937. package/src/hooks/useStreamPopoutNavigation.ts +0 -27
  938. package/src/hooks/useTimeout.ts +0 -37
  939. package/src/hooks/useVoiceChat.ts +0 -1442
  940. package/src/hooks/useWhatsAppPairing.ts +0 -123
  941. package/src/i18n/index.ts +0 -76
  942. package/src/i18n/locales/en.json +0 -1195
  943. package/src/i18n/locales/es.json +0 -1195
  944. package/src/i18n/locales/ko.json +0 -1195
  945. package/src/i18n/locales/pt.json +0 -1195
  946. package/src/i18n/locales/zh-CN.json +0 -1195
  947. package/src/i18n/messages.ts +0 -21
  948. package/src/navigation/index.ts +0 -286
  949. package/src/navigation.test.ts +0 -189
  950. package/src/onboarding-config.test.ts +0 -104
  951. package/src/onboarding-config.ts +0 -122
  952. package/src/platform/browser-launch.test.ts +0 -94
  953. package/src/platform/browser-launch.ts +0 -149
  954. package/src/platform/index.ts +0 -58
  955. package/src/platform/init.ts +0 -238
  956. package/src/platform/lifo.ts +0 -225
  957. package/src/providers/index.ts +0 -108
  958. package/src/shell-params.test.ts +0 -48
  959. package/src/shell-params.ts +0 -36
  960. package/src/state/AppContext.tsx +0 -6415
  961. package/src/state/internal.ts +0 -91
  962. package/src/state/onboarding-resume.test.ts +0 -135
  963. package/src/state/onboarding-resume.ts +0 -263
  964. package/src/state/parsers.test.ts +0 -124
  965. package/src/state/parsers.ts +0 -309
  966. package/src/state/persistence.ts +0 -379
  967. package/src/state/shell-routing.ts +0 -39
  968. package/src/state/types.ts +0 -724
  969. package/src/state/ui-preferences.ts +0 -3
  970. package/src/state/useApp.ts +0 -23
  971. package/src/state/vrm.ts +0 -108
  972. package/src/styles/anime.css +0 -6324
  973. package/src/styles/onboarding-game.css +0 -976
  974. package/src/types/index.ts +0 -715
  975. package/src/types/react-test-renderer.d.ts +0 -45
  976. package/src/utils/asset-url.ts +0 -110
  977. package/src/utils/assistant-text.ts +0 -172
  978. package/src/utils/clipboard.ts +0 -41
  979. package/src/utils/desktop-dialogs.ts +0 -80
  980. package/src/utils/eliza-globals.ts +0 -44
  981. package/src/utils/number-parsing.ts +0 -125
  982. package/src/utils/openExternalUrl.ts +0 -20
  983. package/src/utils/spoken-text.ts +0 -65
  984. package/src/utils/streaming-text.ts +0 -120
  985. package/src/voice/types.ts +0 -197
  986. package/src/wallet-rpc.ts +0 -176
  987. package/test/app/AppContext.pty-sessions.test.tsx +0 -143
  988. package/test/app/MessageContent.test.tsx +0 -366
  989. package/test/app/PermissionsOnboarding.test.tsx +0 -358
  990. package/test/app/PermissionsSection.test.tsx +0 -575
  991. package/test/app/advanced-trajectory-fine-tuning.e2e.test.ts +0 -396
  992. package/test/app/agent-activity-box.test.tsx +0 -132
  993. package/test/app/agent-transfer-lock.test.ts +0 -279
  994. package/test/app/api-client-electrobun-fallback.test.ts +0 -139
  995. package/test/app/api-client-electron-fallback.test.ts +0 -139
  996. package/test/app/api-client-timeout.test.ts +0 -75
  997. package/test/app/api-client-ws.test.ts +0 -98
  998. package/test/app/api-client.ws-max-reconnect.test.ts +0 -139
  999. package/test/app/api-client.ws-reconnect.test.ts +0 -157
  1000. package/test/app/app-context-autonomy-events.test.ts +0 -559
  1001. package/test/app/apps-page-view.test.ts +0 -114
  1002. package/test/app/apps-view.test.ts +0 -768
  1003. package/test/app/autonomous-workflows.e2e.test.ts +0 -765
  1004. package/test/app/autonomy-events.test.ts +0 -150
  1005. package/test/app/avatar-selector.test.tsx +0 -52
  1006. package/test/app/bsc-trade-panel.test.tsx +0 -134
  1007. package/test/app/bug-report-modal.test.tsx +0 -353
  1008. package/test/app/character-action-bar-visibility.test.ts +0 -70
  1009. package/test/app/character-customization.e2e.test.ts +0 -1384
  1010. package/test/app/character-save-journey.test.ts +0 -1245
  1011. package/test/app/chat-advanced-features.e2e.test.ts +0 -706
  1012. package/test/app/chat-composer.test.tsx +0 -181
  1013. package/test/app/chat-journey.test.ts +0 -1075
  1014. package/test/app/chat-language-header.test.ts +0 -64
  1015. package/test/app/chat-message.test.tsx +0 -222
  1016. package/test/app/chat-modal-view.test.tsx +0 -191
  1017. package/test/app/chat-routine-filter.test.ts +0 -96
  1018. package/test/app/chat-send-lock.test.ts +0 -1465
  1019. package/test/app/chat-stream-api-client.test.tsx +0 -390
  1020. package/test/app/chat-view-game-modal.test.tsx +0 -661
  1021. package/test/app/chat-view.test.tsx +0 -877
  1022. package/test/app/cloud-api.e2e.test.ts +0 -258
  1023. package/test/app/cloud-login-flow.e2e.test.ts +0 -494
  1024. package/test/app/cloud-login-lock.test.ts +0 -416
  1025. package/test/app/command-palette.test.tsx +0 -184
  1026. package/test/app/command-registry.test.ts +0 -75
  1027. package/test/app/companion-greeting-wave.test.tsx +0 -431
  1028. package/test/app/companion-scene-host.test.tsx +0 -85
  1029. package/test/app/companion-stale-conversation.test.tsx +0 -447
  1030. package/test/app/companion-view.test.tsx +0 -690
  1031. package/test/app/confirm-delete-control.test.ts +0 -79
  1032. package/test/app/confirm-modal.test.tsx +0 -219
  1033. package/test/app/connection-mode-persistence.test.ts +0 -411
  1034. package/test/app/connectors-ui.e2e.test.ts +0 -508
  1035. package/test/app/conversations-sidebar-game-modal.test.tsx +0 -265
  1036. package/test/app/conversations-sidebar.test.tsx +0 -185
  1037. package/test/app/custom-actions-smoke.test.ts +0 -387
  1038. package/test/app/custom-avatar-api-client.test.ts +0 -207
  1039. package/test/app/desktop-utils.test.ts +0 -145
  1040. package/test/app/electrobun-rpc-bridge.test.ts +0 -83
  1041. package/test/app/events.test.ts +0 -88
  1042. package/test/app/export-import-flows.e2e.test.ts +0 -700
  1043. package/test/app/fine-tuning-view.test.ts +0 -471
  1044. package/test/app/game-view-auth-session.test.tsx +0 -187
  1045. package/test/app/game-view.test.ts +0 -444
  1046. package/test/app/global-emote-overlay.test.tsx +0 -106
  1047. package/test/app/header-status.test.tsx +0 -149
  1048. package/test/app/i18n.test.ts +0 -152
  1049. package/test/app/inventory-bsc-view.test.ts +0 -940
  1050. package/test/app/knowledge-ui.e2e.test.ts +0 -762
  1051. package/test/app/knowledge-upload-helpers.test.ts +0 -124
  1052. package/test/app/lifecycle-lock.test.ts +0 -267
  1053. package/test/app/lifo-popout-utils.test.ts +0 -208
  1054. package/test/app/lifo-safe-endpoint.test.ts +0 -34
  1055. package/test/app/loading-screen.test.tsx +0 -45
  1056. package/test/app/memory-monitor.test.ts +0 -331
  1057. package/test/app/milady-bar-regression.test.tsx +0 -519
  1058. package/test/app/milady-bar-settings.test.tsx +0 -1056
  1059. package/test/app/milady-bar.test.tsx +0 -583
  1060. package/test/app/navigation.test.tsx +0 -22
  1061. package/test/app/onboarding-e2e-journey.test.ts +0 -1409
  1062. package/test/app/onboarding-finish-lock.test.ts +0 -676
  1063. package/test/app/onboarding-language.test.tsx +0 -160
  1064. package/test/app/onboarding-steps.test.tsx +0 -375
  1065. package/test/app/open-external-url.test.ts +0 -65
  1066. package/test/app/pages-navigation-smoke.e2e.test.ts +0 -646
  1067. package/test/app/pairing-lock.test.ts +0 -260
  1068. package/test/app/pairing-view.test.tsx +0 -74
  1069. package/test/app/permissions-section.test.ts +0 -432
  1070. package/test/app/plugin-bridge.test.ts +0 -109
  1071. package/test/app/plugins-ui.e2e.test.ts +0 -605
  1072. package/test/app/plugins-view-game-modal.test.tsx +0 -686
  1073. package/test/app/plugins-view-toggle-restart.test.ts +0 -129
  1074. package/test/app/provider-dropdown-default.test.tsx +0 -300
  1075. package/test/app/restart-banner.test.tsx +0 -205
  1076. package/test/app/retake-capture.test.ts +0 -84
  1077. package/test/app/sandbox-api-client.test.ts +0 -108
  1078. package/test/app/save-command-modal.test.tsx +0 -109
  1079. package/test/app/secrets-view.test.tsx +0 -92
  1080. package/test/app/settings-control-styles.test.tsx +0 -142
  1081. package/test/app/settings-reset.e2e.test.ts +0 -726
  1082. package/test/app/settings-sections.e2e.test.ts +0 -614
  1083. package/test/app/shared-format.test.ts +0 -44
  1084. package/test/app/shared-switch.test.ts +0 -69
  1085. package/test/app/shell-mode-switching.e2e.test.ts +0 -841
  1086. package/test/app/shell-mode-tab-memory.test.tsx +0 -58
  1087. package/test/app/shell-overlays.test.tsx +0 -50
  1088. package/test/app/shortcuts-overlay.test.tsx +0 -111
  1089. package/test/app/sse-interruption.test.ts +0 -122
  1090. package/test/app/startup-asset-missing.e2e.test.ts +0 -126
  1091. package/test/app/startup-backend-missing.e2e.test.ts +0 -126
  1092. package/test/app/startup-chat.e2e.test.ts +0 -323
  1093. package/test/app/startup-conversation-restore.test.tsx +0 -381
  1094. package/test/app/startup-failure-view.test.tsx +0 -103
  1095. package/test/app/startup-onboarding.e2e.test.ts +0 -712
  1096. package/test/app/startup-timeout.test.tsx +0 -80
  1097. package/test/app/startup-token-401.e2e.test.ts +0 -103
  1098. package/test/app/stream-helpers.test.ts +0 -46
  1099. package/test/app/stream-popout-navigation.test.tsx +0 -41
  1100. package/test/app/stream-status-bar.test.tsx +0 -89
  1101. package/test/app/theme-toggle.test.tsx +0 -40
  1102. package/test/app/training-api-client.test.ts +0 -128
  1103. package/test/app/trajectories-view.test.tsx +0 -220
  1104. package/test/app/triggers-api-client.test.ts +0 -77
  1105. package/test/app/triggers-navigation.test.ts +0 -113
  1106. package/test/app/triggers-view.e2e.test.ts +0 -675
  1107. package/test/app/update-channel-lock.test.ts +0 -259
  1108. package/test/app/vector-browser.async-cleanup.test.tsx +0 -367
  1109. package/test/app/vector-browser.e2e.test.ts +0 -653
  1110. package/test/app/vrm-stage.test.tsx +0 -351
  1111. package/test/app/vrm-viewer.test.tsx +0 -298
  1112. package/test/app/wallet-api-save-lock.test.ts +0 -299
  1113. package/test/app/wallet-hooks.test.ts +0 -405
  1114. package/test/app/wallet-ui-flows.e2e.test.ts +0 -556
  1115. package/test/avatar/asset-url.test.ts +0 -90
  1116. package/test/avatar/avatar-selector.test.ts +0 -173
  1117. package/test/avatar/mixamo-vrm-rig-map.test.ts +0 -111
  1118. package/test/avatar/voice-chat-streaming-text.test.ts +0 -96
  1119. package/test/avatar/voice-chat.test.ts +0 -391
  1120. package/test/browser-extension/README.md +0 -138
  1121. package/test/browser-extension/test-harness.ts +0 -499
  1122. package/test/capacitor-plugins.e2e.test.ts +0 -168
  1123. package/test/test-types.ts +0 -5
  1124. package/test/ui/command-palette-commands.test.ts +0 -57
  1125. package/test/ui/ui-renderer.test.ts +0 -39
  1126. package/test/utils/assistant-text.test.ts +0 -68
  1127. package/test/utils/eliza-globals.test.ts +0 -59
  1128. package/test/utils/package-exports.test.ts +0 -70
  1129. package/test/utils/streaming-text.test.ts +0 -89
  1130. package/tsconfig.build.json +0 -19
  1131. package/tsconfig.json +0 -20
  1132. package/tsconfig.typecheck.json +0 -12
  1133. /package/{src/api/index.ts → api/index.js} +0 -0
  1134. /package/{src/bridge/index.ts → bridge/index.js} +0 -0
  1135. /package/{src/components/TriggersView.tsx → components/TriggersView.js} +0 -0
  1136. /package/{src/hooks/index.ts → hooks/index.js} +0 -0
  1137. /package/{src/index.ts → index.js} +0 -0
  1138. /package/{src/state/index.ts → state/index.js} +0 -0
  1139. /package/{src/styles → styles}/base.css +0 -0
  1140. /package/{src/styles → styles}/styles.css +0 -0
  1141. /package/{src/styles → styles}/xterm.css +0 -0
  1142. /package/{src/utils/index.ts → utils/index.js} +0 -0
  1143. /package/{src/voice/index.ts → voice/index.js} +0 -0
@@ -0,0 +1,2076 @@
1
+ import { resolveAppAssetUrl } from "@elizaos/app-core/utils";
2
+ import { MToonMaterialLoaderPlugin, VRMLoaderPlugin, VRMUtils, } from "@pixiv/three-vrm";
3
+ import * as THREE from "three";
4
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
5
+ import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module.js";
6
+ import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
7
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
8
+ import { loadEmoteClip, loadIdleClip, } from "./VrmAnimationLoader";
9
+ import { VrmBlinkController } from "./VrmBlinkController";
10
+ import { VrmCameraManager, } from "./VrmCameraManager";
11
+ const DEFAULT_CAMERA_ANIMATION = {
12
+ enabled: false,
13
+ swayAmplitude: 0.06,
14
+ bobAmplitude: 0.03,
15
+ rotationAmplitude: 0.01,
16
+ speed: 0.8,
17
+ };
18
+ const CAMERA_PROFILE_TRANSITION_DURATION_SECONDS = 0.8;
19
+ const AVATAR_SWITCH_CAMERA_TRANSITION_DURATION_SECONDS = 3;
20
+ const COMPANION_WORLD_SCALE = 2.5;
21
+ const COMPANION_DARK_WORLD_FLOOR_OFFSET_Y = -0.95;
22
+ const COMPANION_LIGHT_WORLD_FLOOR_OFFSET_Y = -0.35;
23
+ const COMPANION_WORLD_REVEAL_DURATION = 5.4;
24
+ const COMPANION_WORLD_REVEAL_EDGE = 0.28;
25
+ const COMPANION_WORLD_REVEAL_EASE_EXPONENT = 2;
26
+ const COMPANION_WORLD_REVEAL_START_OFFSET = 0.7;
27
+ const TELEPORT_DISSOLVE_START_Y = -1.2;
28
+ const TELEPORT_DISSOLVE_END_Y = 1.0;
29
+ const TELEPORT_SPARKLE_PARTICLE_COUNT = 28;
30
+ const TELEPORT_SPARKLE_RING_RADIUS = 0.52;
31
+ const TELEPORT_SPARKLE_MIN_SIZE = 0.055;
32
+ const TELEPORT_SPARKLE_MAX_SIZE = 0.13;
33
+ const COMPANION_DOF_APERTURE_SIZE = 0.028;
34
+ const COMPANION_DOF_NEAR_ZOOM_APERTURE_FACTOR = 0.4;
35
+ const COMPANION_ZOOM_NEAR_FACTOR = 0.25;
36
+ const COMPANION_ZOOM_MIN_RADIUS = 1.2;
37
+ const SPARK_CLIP_XY = 1.08;
38
+ const SPARK_MAX_STD_DEV = 2.35;
39
+ const SPARK_MAX_STD_DEV_NEAR = 1.9;
40
+ const SPARK_MIN_ALPHA = 0.0016;
41
+ const SPARK_MIN_ALPHA_NEAR = 0.0024;
42
+ const SPARK_SORT_DISTANCE = 0.035;
43
+ const SPARK_SORT_DISTANCE_NEAR = 0.05;
44
+ const SPARK_MAX_PIXEL_RADIUS = 96;
45
+ const SPARK_MAX_PIXEL_RADIUS_NEAR = 28;
46
+ const MAX_RENDERER_PIXEL_RATIO = 2;
47
+ const AVATAR_RENDERER_OVERRIDE_KEY = "eliza.avatarRenderer";
48
+ const KNOWN_VRM_WEBGPU_WARNING = 'TSL: "transformedNormalView" is deprecated. Use "normalView" instead.';
49
+ let knownVrmWebGpuWarningFilterRefs = 0;
50
+ let releaseKnownVrmWebGpuWarningFilterGlobal = null;
51
+ let sharedDracoLoader = null;
52
+ let teleportSparkleTexture = null;
53
+ const DRACO_DECODER_PATH = resolveAppAssetUrl("vrm-decoders/draco/");
54
+ function getRendererPixelRatio(sparkOptimized = false) {
55
+ if (typeof window === "undefined")
56
+ return 1;
57
+ if (sparkOptimized)
58
+ return 1;
59
+ return Math.min(Math.max(window.devicePixelRatio || 1, 1), MAX_RENDERER_PIXEL_RATIO);
60
+ }
61
+ function isElectrobunAvatarRuntime() {
62
+ if (typeof window === "undefined")
63
+ return false;
64
+ const runtimeWindow = window;
65
+ return (typeof runtimeWindow.__electrobunWindowId === "number" ||
66
+ typeof runtimeWindow.__electrobunWebviewId === "number");
67
+ }
68
+ function getPreferredAvatarRendererBackend() {
69
+ if (typeof window === "undefined")
70
+ return "webgl";
71
+ const override = (() => {
72
+ try {
73
+ return window.localStorage.getItem(AVATAR_RENDERER_OVERRIDE_KEY);
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ })();
79
+ const normalizedOverride = override?.trim().toLowerCase();
80
+ if (normalizedOverride === "webgpu" || normalizedOverride === "webgl") {
81
+ return normalizedOverride;
82
+ }
83
+ return isElectrobunAvatarRuntime() ? "webgpu" : "webgl";
84
+ }
85
+ function installKnownVrmWebGpuWarningFilter() {
86
+ knownVrmWebGpuWarningFilterRefs += 1;
87
+ if (!releaseKnownVrmWebGpuWarningFilterGlobal) {
88
+ const originalWarn = console.warn.bind(console);
89
+ console.warn = (...args) => {
90
+ if (typeof args[0] === "string" &&
91
+ args[0].includes(KNOWN_VRM_WEBGPU_WARNING)) {
92
+ return;
93
+ }
94
+ originalWarn(...args);
95
+ };
96
+ releaseKnownVrmWebGpuWarningFilterGlobal = () => {
97
+ knownVrmWebGpuWarningFilterRefs = Math.max(0, knownVrmWebGpuWarningFilterRefs - 1);
98
+ if (knownVrmWebGpuWarningFilterRefs === 0) {
99
+ console.warn = originalWarn;
100
+ releaseKnownVrmWebGpuWarningFilterGlobal = null;
101
+ }
102
+ };
103
+ }
104
+ return () => {
105
+ releaseKnownVrmWebGpuWarningFilterGlobal?.();
106
+ };
107
+ }
108
+ function getSharedDracoLoader() {
109
+ if (!sharedDracoLoader) {
110
+ sharedDracoLoader = new DRACOLoader();
111
+ sharedDracoLoader.setDecoderConfig({ type: "wasm" });
112
+ sharedDracoLoader.setDecoderPath(DRACO_DECODER_PATH);
113
+ sharedDracoLoader.preload();
114
+ }
115
+ return sharedDracoLoader;
116
+ }
117
+ function configureVrmGltfLoader(loader) {
118
+ loader.setMeshoptDecoder(MeshoptDecoder);
119
+ loader.setDRACOLoader(getSharedDracoLoader());
120
+ }
121
+ function getTeleportSparkleTexture() {
122
+ if (teleportSparkleTexture)
123
+ return teleportSparkleTexture;
124
+ const canvas = document.createElement("canvas");
125
+ canvas.width = 128;
126
+ canvas.height = 128;
127
+ const context = canvas.getContext("2d");
128
+ if (!context) {
129
+ teleportSparkleTexture = new THREE.CanvasTexture(canvas);
130
+ return teleportSparkleTexture;
131
+ }
132
+ const gradient = context.createRadialGradient(64, 64, 6, 64, 64, 64);
133
+ gradient.addColorStop(0.0, "rgba(255,255,255,1)");
134
+ gradient.addColorStop(0.2, "rgba(190,245,255,0.95)");
135
+ gradient.addColorStop(0.55, "rgba(112,214,255,0.48)");
136
+ gradient.addColorStop(1.0, "rgba(112,214,255,0)");
137
+ context.fillStyle = gradient;
138
+ context.fillRect(0, 0, 128, 128);
139
+ teleportSparkleTexture = new THREE.CanvasTexture(canvas);
140
+ teleportSparkleTexture.needsUpdate = true;
141
+ return teleportSparkleTexture;
142
+ }
143
+ function quantileSorted(values, percentile) {
144
+ if (values.length === 0)
145
+ return 0;
146
+ const index = Math.min(values.length - 1, Math.max(0, Math.floor((values.length - 1) * percentile)));
147
+ return values[index] ?? 0;
148
+ }
149
+ function getRobustPackedSplatAnchor(splatSource) {
150
+ const maxSamples = 4096;
151
+ const xSamples = [];
152
+ const ySamples = [];
153
+ const zSamples = [];
154
+ const splatCount = splatSource.numSplats ?? maxSamples;
155
+ const sampleStep = splatCount > maxSamples
156
+ ? Math.max(1, Math.floor(splatCount / maxSamples))
157
+ : 1;
158
+ splatSource.forEachSplat((index, center) => {
159
+ if (sampleStep > 1 && index % sampleStep !== 0)
160
+ return;
161
+ xSamples.push(center.x);
162
+ ySamples.push(center.y);
163
+ zSamples.push(center.z);
164
+ });
165
+ if (xSamples.length === 0) {
166
+ return new THREE.Vector3(0, 0, 0);
167
+ }
168
+ xSamples.sort((a, b) => a - b);
169
+ ySamples.sort((a, b) => a - b);
170
+ zSamples.sort((a, b) => a - b);
171
+ return new THREE.Vector3(quantileSorted(xSamples, 0.5), quantileSorted(ySamples, 0.05), quantileSorted(zSamples, 0.5));
172
+ }
173
+ function getRobustSplatAnchor(splat) {
174
+ return getRobustPackedSplatAnchor({
175
+ numSplats: splat.packedSplats?.numSplats,
176
+ forEachSplat: splat.forEachSplat.bind(splat),
177
+ });
178
+ }
179
+ function getRobustPackedSplatRadialExtent(splatSource, anchor) {
180
+ const maxSamples = 4096;
181
+ const radialSamples = [];
182
+ const splatCount = splatSource.numSplats ?? maxSamples;
183
+ const sampleStep = splatCount > maxSamples
184
+ ? Math.max(1, Math.floor(splatCount / maxSamples))
185
+ : 1;
186
+ splatSource.forEachSplat((index, center) => {
187
+ if (sampleStep > 1 && index % sampleStep !== 0)
188
+ return;
189
+ radialSamples.push(Math.hypot(center.x - anchor.x, center.z - anchor.z));
190
+ });
191
+ if (radialSamples.length === 0) {
192
+ return 1;
193
+ }
194
+ radialSamples.sort((a, b) => a - b);
195
+ return Math.max(1, quantileSorted(radialSamples, 0.985));
196
+ }
197
+ function getRobustSplatRadialExtent(splat, anchor) {
198
+ return getRobustPackedSplatRadialExtent({
199
+ numSplats: splat.packedSplats?.numSplats,
200
+ forEachSplat: splat.forEachSplat.bind(splat),
201
+ }, anchor);
202
+ }
203
+ function getCompanionWorldFloorOffsetY(url) {
204
+ const normalizedUrl = url.toLowerCase();
205
+ return normalizedUrl.includes("night") ||
206
+ normalizedUrl.includes("dark") ||
207
+ normalizedUrl.includes("lunarpunk")
208
+ ? COMPANION_DARK_WORLD_FLOOR_OFFSET_Y
209
+ : COMPANION_LIGHT_WORLD_FLOOR_OFFSET_Y;
210
+ }
211
+ function isGzipBuffer(buffer) {
212
+ if (buffer.byteLength < 2)
213
+ return false;
214
+ const bytes = new Uint8Array(buffer, 0, 2);
215
+ return bytes[0] === 0x1f && bytes[1] === 0x8b;
216
+ }
217
+ async function decompressGzipBuffer(buffer) {
218
+ if (typeof DecompressionStream !== "function") {
219
+ throw new Error("This runtime does not support gzip-compressed VRM assets.");
220
+ }
221
+ const stream = new Blob([buffer])
222
+ .stream()
223
+ .pipeThrough(new DecompressionStream("gzip"));
224
+ return await new Response(stream).arrayBuffer();
225
+ }
226
+ async function loadGltfAsset(loader, url, onProgress) {
227
+ const response = await fetch(url);
228
+ if (!response.ok) {
229
+ throw new Error(`Failed to fetch VRM asset: ${response.status}`);
230
+ }
231
+ const contentLength = Number(response.headers.get("content-length") || 0);
232
+ let buffer;
233
+ if (!contentLength || !response.body || !onProgress) {
234
+ buffer = await response.arrayBuffer();
235
+ onProgress?.(1);
236
+ }
237
+ else {
238
+ const reader = response.body.getReader();
239
+ let received = 0;
240
+ const chunks = [];
241
+ for (;;) {
242
+ const { done, value } = await reader.read();
243
+ if (done)
244
+ break;
245
+ if (value) {
246
+ chunks.push(value);
247
+ received += value.length;
248
+ onProgress(Math.min(received / contentLength, 1));
249
+ }
250
+ }
251
+ const combined = new Uint8Array(received);
252
+ let offset = 0;
253
+ for (const chunk of chunks) {
254
+ combined.set(chunk, offset);
255
+ offset += chunk.length;
256
+ }
257
+ buffer = combined.buffer;
258
+ }
259
+ if (!isGzipBuffer(buffer)) {
260
+ const objectUrl = URL.createObjectURL(new Blob([buffer], { type: "model/gltf-binary" }));
261
+ try {
262
+ return await loader.loadAsync(objectUrl);
263
+ }
264
+ finally {
265
+ URL.revokeObjectURL(objectUrl);
266
+ }
267
+ }
268
+ buffer = await decompressGzipBuffer(buffer);
269
+ const objectUrl = URL.createObjectURL(new Blob([buffer], { type: "model/gltf-binary" }));
270
+ try {
271
+ return await loader.loadAsync(objectUrl);
272
+ }
273
+ finally {
274
+ URL.revokeObjectURL(objectUrl);
275
+ }
276
+ }
277
+ /**
278
+ * Create the best available renderer for the current platform.
279
+ * Electrobun's CEF desktop shell expects WebGPU for the avatar stage, while the
280
+ * browser dev shell stays on WebGL by default to avoid upstream TSL noise.
281
+ * A localStorage override can force either backend for debugging.
282
+ * THREE.WebGPURenderer is async-init and requires await renderer.init().
283
+ */
284
+ async function createRenderer(canvas, preference = "auto", sparkOptimized = false) {
285
+ if (preference !== "webgl" &&
286
+ getPreferredAvatarRendererBackend() === "webgpu" &&
287
+ typeof navigator !== "undefined" &&
288
+ navigator.gpu) {
289
+ try {
290
+ const { WebGPURenderer } = await import("three/webgpu");
291
+ const renderer = new WebGPURenderer({
292
+ canvas,
293
+ alpha: true,
294
+ antialias: !sparkOptimized,
295
+ });
296
+ await renderer.init?.();
297
+ console.info("[VrmEngine] Using WebGPURenderer");
298
+ return { backend: "webgpu", renderer };
299
+ }
300
+ catch (err) {
301
+ console.warn("[VrmEngine] WebGPURenderer failed, falling back to WebGL:", err);
302
+ }
303
+ }
304
+ const renderer = new THREE.WebGLRenderer({
305
+ canvas,
306
+ alpha: true,
307
+ antialias: !sparkOptimized,
308
+ powerPreference: sparkOptimized ? "high-performance" : "default",
309
+ });
310
+ console.info("[VrmEngine] Using WebGLRenderer");
311
+ return { backend: "webgl", renderer };
312
+ }
313
+ export class VrmEngine {
314
+ static sparkModulePromise = null;
315
+ renderer = null;
316
+ rendererBackend = "webgl";
317
+ rendererPreference = "auto";
318
+ scene = null;
319
+ avatarRoot = null;
320
+ camera = null;
321
+ clock = new THREE.Clock();
322
+ vrm = null;
323
+ mixer = null;
324
+ idleAction = null;
325
+ idleLoadPromise = null;
326
+ animationFrameId = null;
327
+ onUpdate = null;
328
+ initialized = false;
329
+ loadingAborted = false;
330
+ vrmLoadRequestId = 0;
331
+ vrmReady = false;
332
+ lastLoadError = null;
333
+ teleportProgress = 1.0;
334
+ loadingProgress = 0;
335
+ teleportProgressUniform = null;
336
+ teleportDissolvedMaterials = [];
337
+ teleportFallbackShaders = [];
338
+ teleportSparkles = null;
339
+ revealStarted = false;
340
+ mouthValue = 0;
341
+ mouthSmoothed = 0;
342
+ vrmName = null;
343
+ lookAtTarget = new THREE.Vector3(0, 0.5, 0);
344
+ idleGlbUrl = resolveAppAssetUrl("animations/idle.glb.gz");
345
+ cameraAnimation = {
346
+ ...DEFAULT_CAMERA_ANIMATION,
347
+ };
348
+ baseCameraPosition = new THREE.Vector3();
349
+ elapsedTime = 0;
350
+ speaking = false;
351
+ speakingStartTime = 0;
352
+ blinkController = new VrmBlinkController();
353
+ cameraManager = new VrmCameraManager();
354
+ emoteAction = null;
355
+ emoteTimeout = null;
356
+ emoteCompletionCleanup = null;
357
+ emoteClipCache = new Map();
358
+ emoteRequestId = 0;
359
+ controls = null;
360
+ paused = false;
361
+ interactionEnabled = false;
362
+ interactionMode = "free";
363
+ cameraProfile = "chat";
364
+ worldUrl = null;
365
+ worldMesh = null;
366
+ worldReveal = null;
367
+ sparkRenderer = null;
368
+ worldLoadRequestId = 0;
369
+ pointerParallaxEnabled = false;
370
+ pointerParallaxTarget = new THREE.Vector2();
371
+ pointerParallaxCurrent = new THREE.Vector2();
372
+ pointerParallaxPosition = new THREE.Vector3();
373
+ pointerParallaxLookAt = new THREE.Vector3();
374
+ dragOrbitTarget = new THREE.Vector2();
375
+ dragOrbitCurrent = new THREE.Vector2();
376
+ companionZoomTarget = 0;
377
+ companionZoomCurrent = 0;
378
+ avatarLookTarget = null;
379
+ headLookTarget = new THREE.Vector2();
380
+ headLookCurrent = new THREE.Vector2();
381
+ clearEmoteTimeout() {
382
+ if (this.emoteTimeout !== null) {
383
+ clearTimeout(this.emoteTimeout);
384
+ this.emoteTimeout = null;
385
+ }
386
+ }
387
+ clearEmoteCompletionCleanup() {
388
+ this.emoteCompletionCleanup?.();
389
+ this.emoteCompletionCleanup = null;
390
+ }
391
+ clearPendingEmoteCompletion() {
392
+ this.clearEmoteTimeout();
393
+ this.clearEmoteCompletionCleanup();
394
+ }
395
+ watchOneShotEmoteCompletion(mixer, action, requestId, fallbackDurationSeconds) {
396
+ const handleFinished = (event) => {
397
+ if (event.action !== action)
398
+ return;
399
+ if (this.emoteRequestId !== requestId || this.emoteAction !== action) {
400
+ return;
401
+ }
402
+ this.stopEmote();
403
+ };
404
+ mixer.addEventListener("finished", handleFinished);
405
+ this.emoteCompletionCleanup = () => {
406
+ mixer.removeEventListener("finished", handleFinished);
407
+ };
408
+ const safeDuration = Number.isFinite(fallbackDurationSeconds) && fallbackDurationSeconds > 0
409
+ ? fallbackDurationSeconds
410
+ : 3;
411
+ // Keep a timer fallback in case the mixer completion event is missed.
412
+ this.emoteTimeout = setTimeout(() => {
413
+ if (this.emoteRequestId !== requestId || this.emoteAction !== action) {
414
+ return;
415
+ }
416
+ this.stopEmote();
417
+ }, Math.max(0.25, safeDuration + 0.1) * 1000);
418
+ }
419
+ activateAction(action) {
420
+ action.enabled = true;
421
+ action.paused = false;
422
+ action.setEffectiveTimeScale(1);
423
+ action.setEffectiveWeight(1);
424
+ action.play();
425
+ }
426
+ playActionWithBlend(action, fromAction, fadeDuration) {
427
+ action.reset();
428
+ this.activateAction(action);
429
+ if (fromAction && fromAction !== action) {
430
+ this.activateAction(fromAction);
431
+ action.crossFadeFrom(fromAction, fadeDuration, false);
432
+ return;
433
+ }
434
+ action.fadeIn(fadeDuration);
435
+ }
436
+ async ensureIdleAction(vrm, mixer) {
437
+ if (this.idleAction)
438
+ return this.idleAction;
439
+ if (this.idleLoadPromise)
440
+ return this.idleLoadPromise;
441
+ this.idleLoadPromise = (async () => {
442
+ const clip = await loadIdleClip(vrm, this.idleGlbUrl, this.animationLoaderContext);
443
+ if (!clip || this.loadingAborted || this.vrm !== vrm) {
444
+ return null;
445
+ }
446
+ const activeMixer = this.mixer ?? mixer;
447
+ if (!activeMixer || this.vrm !== vrm) {
448
+ return null;
449
+ }
450
+ const action = activeMixer.clipAction(clip);
451
+ action.reset();
452
+ action.setLoop(THREE.LoopRepeat, Infinity);
453
+ action.timeScale = 1.0;
454
+ this.idleAction = action;
455
+ activeMixer.update(1 / 60);
456
+ return action;
457
+ })().finally(() => {
458
+ this.idleLoadPromise = null;
459
+ });
460
+ return this.idleLoadPromise;
461
+ }
462
+ restoreIdleAfterEmote(activeEmote, fadeDuration, vrm, mixer) {
463
+ void this.ensureIdleAction(vrm, mixer).then((idleAction) => {
464
+ if (!idleAction || this.loadingAborted || this.vrm !== vrm) {
465
+ activeEmote?.fadeOut(fadeDuration);
466
+ return;
467
+ }
468
+ this.activateAction(idleAction);
469
+ if (activeEmote && activeEmote !== idleAction) {
470
+ idleAction.crossFadeFrom(activeEmote, fadeDuration, false);
471
+ }
472
+ else {
473
+ idleAction.fadeIn(fadeDuration);
474
+ }
475
+ });
476
+ }
477
+ avatarLookRig = {
478
+ headBone: null,
479
+ neckBone: null,
480
+ spineBone: null,
481
+ };
482
+ tempCameraOrbitOffset = new THREE.Vector3();
483
+ tempCameraSpherical = new THREE.Spherical();
484
+ tempAvatarLookTarget = new THREE.Vector3();
485
+ tempAvatarLocalTarget = new THREE.Vector3();
486
+ tempAvatarLocalAnchor = new THREE.Vector3();
487
+ tempAvatarHeadWorld = new THREE.Vector3();
488
+ readyPromise = Promise.resolve();
489
+ resolveReady = null;
490
+ rejectReady = null;
491
+ releaseKnownWebGpuWarningFilter = null;
492
+ // Transition state
493
+ isCameraTransitioning = false;
494
+ transitionStartFov = 0;
495
+ transitionTargetFov = 0;
496
+ transitionStartPos = new THREE.Vector3();
497
+ transitionTargetPos = new THREE.Vector3();
498
+ transitionStartLookAt = new THREE.Vector3();
499
+ transitionTargetLookAt = new THREE.Vector3();
500
+ transitionProgress = 0;
501
+ transitionDuration = CAMERA_PROFILE_TRANSITION_DURATION_SECONDS;
502
+ handleControlStart = () => {
503
+ if (!this.interactionEnabled)
504
+ return;
505
+ };
506
+ handleControlEnd = () => {
507
+ if (!this.interactionEnabled)
508
+ return;
509
+ if (this.camera) {
510
+ this.baseCameraPosition.copy(this.camera.position);
511
+ }
512
+ if (this.controls) {
513
+ this.lookAtTarget.copy(this.controls.target);
514
+ }
515
+ };
516
+ scheduleNextFrame() {
517
+ if (!this.initialized || this.paused || this.animationFrameId !== null) {
518
+ return;
519
+ }
520
+ this.animationFrameId = requestAnimationFrame(() => {
521
+ this.animationFrameId = null;
522
+ this.loop();
523
+ });
524
+ }
525
+ stopLoop() {
526
+ if (this.animationFrameId !== null) {
527
+ cancelAnimationFrame(this.animationFrameId);
528
+ this.animationFrameId = null;
529
+ }
530
+ this.clock.stop();
531
+ }
532
+ resumeLoop() {
533
+ if (!this.initialized || this.paused)
534
+ return;
535
+ this.clock.start();
536
+ this.scheduleNextFrame();
537
+ }
538
+ async loadSparkModule() {
539
+ if (!VrmEngine.sparkModulePromise) {
540
+ VrmEngine.sparkModulePromise = import("@sparkjsdev/spark");
541
+ }
542
+ return VrmEngine.sparkModulePromise;
543
+ }
544
+ async ensureSparkRenderer() {
545
+ if (this.sparkRenderer || this.rendererBackend !== "webgl")
546
+ return;
547
+ if (!this.scene || !this.renderer)
548
+ return;
549
+ const { SparkRenderer } = await this.loadSparkModule();
550
+ // Re-check after async import — the engine may have been disposed during
551
+ // the await (e.g. React StrictMode double-mount).
552
+ if (!this.scene || !this.renderer)
553
+ return;
554
+ const sparkRenderer = new SparkRenderer({
555
+ renderer: this.renderer,
556
+ apertureAngle: 0.0,
557
+ focalDistance: 5.0,
558
+ originDistance: 1,
559
+ clipXY: SPARK_CLIP_XY,
560
+ maxStdDev: SPARK_MAX_STD_DEV,
561
+ maxPixelRadius: SPARK_MAX_PIXEL_RADIUS,
562
+ minAlpha: SPARK_MIN_ALPHA,
563
+ view: {
564
+ depthBias: 1,
565
+ sortDistance: SPARK_SORT_DISTANCE,
566
+ sortRadial: true,
567
+ sort360: false,
568
+ },
569
+ });
570
+ sparkRenderer.renderOrder = 9998;
571
+ this.scene.add(sparkRenderer);
572
+ this.sparkRenderer = sparkRenderer;
573
+ }
574
+ updateSparkPerformanceProfile() {
575
+ const sparkRenderer = this.sparkRenderer;
576
+ if (!sparkRenderer)
577
+ return;
578
+ if (!this.worldMesh) {
579
+ sparkRenderer.maxPixelRadius = SPARK_MAX_PIXEL_RADIUS;
580
+ sparkRenderer.maxStdDev = SPARK_MAX_STD_DEV;
581
+ sparkRenderer.minAlpha = SPARK_MIN_ALPHA;
582
+ sparkRenderer.clipXY = SPARK_CLIP_XY;
583
+ sparkRenderer.defaultView.sortDistance = SPARK_SORT_DISTANCE;
584
+ return;
585
+ }
586
+ const isCompanionProfile = this.cameraProfile === "companion" ||
587
+ this.cameraProfile === "companion_close";
588
+ const closeZoomFactor = isCompanionProfile
589
+ ? THREE.MathUtils.smoothstep(this.companionZoomCurrent, 0.3, 1)
590
+ : 0;
591
+ sparkRenderer.maxPixelRadius = THREE.MathUtils.lerp(SPARK_MAX_PIXEL_RADIUS, SPARK_MAX_PIXEL_RADIUS_NEAR, closeZoomFactor);
592
+ sparkRenderer.maxStdDev = THREE.MathUtils.lerp(SPARK_MAX_STD_DEV, SPARK_MAX_STD_DEV_NEAR, closeZoomFactor);
593
+ sparkRenderer.minAlpha = THREE.MathUtils.lerp(SPARK_MIN_ALPHA, SPARK_MIN_ALPHA_NEAR, closeZoomFactor);
594
+ sparkRenderer.clipXY = THREE.MathUtils.lerp(SPARK_CLIP_XY, 1.03, closeZoomFactor);
595
+ sparkRenderer.defaultView.sortDistance = THREE.MathUtils.lerp(SPARK_SORT_DISTANCE, SPARK_SORT_DISTANCE_NEAR, closeZoomFactor);
596
+ }
597
+ createWorldRevealController(spark, mesh, reveal, mode) {
598
+ const dyno = ("dyno" in spark ? Reflect.get(spark, "dyno") : undefined);
599
+ if (!dyno?.Gsplat ||
600
+ !dyno.dynoBlock ||
601
+ !dyno.dynoFloat ||
602
+ !dyno.dynoVec3 ||
603
+ !dyno.dynoConst ||
604
+ !dyno.splitGsplat ||
605
+ !dyno.combineGsplat ||
606
+ !dyno.add ||
607
+ !dyno.sub ||
608
+ !dyno.mul ||
609
+ !dyno.div ||
610
+ !dyno.abs ||
611
+ !dyno.clamp ||
612
+ !dyno.max ||
613
+ !dyno.mix ||
614
+ !dyno.smoothstep ||
615
+ !dyno.pow ||
616
+ !dyno.length ||
617
+ !dyno.swizzle) {
618
+ return null;
619
+ }
620
+ const originUniform = dyno.dynoVec3(reveal.origin, "uWorldRevealOrigin");
621
+ const resolvedRadius = Math.max(reveal.radius, COMPANION_WORLD_REVEAL_EDGE * 2);
622
+ const radiusUniform = dyno.dynoFloat(resolvedRadius, "uWorldRevealRadius");
623
+ const edgeUniform = dyno.dynoFloat(COMPANION_WORLD_REVEAL_EDGE, "uWorldRevealEdge");
624
+ const progressUniform = dyno.dynoFloat(0, "uWorldRevealProgress");
625
+ const wireScaleUniform = dyno.dynoVec3(new THREE.Vector3(0.004, 0.004, 0.004), "uWorldRevealWireScale");
626
+ const wireAlphaUniform = dyno.dynoFloat(0.42, "uWorldRevealWireAlpha");
627
+ const wireBoostUniform = dyno.dynoFloat(0.3, "uWorldRevealWireBoost");
628
+ const zero = dyno.dynoConst("float", 0);
629
+ const one = dyno.dynoConst("float", 1);
630
+ const two = dyno.dynoConst("float", 2);
631
+ const startOffset = dyno.dynoConst("float", -COMPANION_WORLD_REVEAL_START_OFFSET);
632
+ const modifier = dyno.dynoBlock({ gsplat: dyno.Gsplat }, { gsplat: dyno.Gsplat }, ({ gsplat }) => {
633
+ if (!gsplat) {
634
+ throw new Error("Missing gsplat input for world reveal");
635
+ }
636
+ const { center, scales, rgb, opacity } = dyno.splitGsplat(gsplat).outputs;
637
+ const radialDistance = dyno.length(dyno.swizzle(dyno.sub(center, originUniform), "xz"));
638
+ const currentRadius = dyno.add(dyno.mul(radiusUniform, progressUniform), startOffset);
639
+ const bodyMask = dyno.sub(one, dyno.smoothstep(dyno.sub(currentRadius, edgeUniform), dyno.add(currentRadius, edgeUniform), radialDistance));
640
+ const ringDistance = dyno.abs(dyno.sub(radialDistance, currentRadius));
641
+ const ringMask = dyno.pow(dyno.sub(one, dyno.smoothstep(zero, dyno.mul(edgeUniform, two), ringDistance)), two);
642
+ const visibleMask = mode === "hide" ? dyno.sub(one, bodyMask) : bodyMask;
643
+ const wireFactor = dyno.clamp(dyno.max(visibleMask, dyno.mul(ringMask, wireAlphaUniform)), zero, one);
644
+ const brightenedRgb = dyno.mul(rgb, dyno.add(one, dyno.mul(ringMask, wireBoostUniform)));
645
+ return {
646
+ gsplat: dyno.combineGsplat({
647
+ gsplat,
648
+ scales: dyno.mix(wireScaleUniform, scales, wireFactor),
649
+ rgb: dyno.mix(brightenedRgb, rgb, visibleMask),
650
+ opacity: dyno.mul(opacity, wireFactor),
651
+ }),
652
+ };
653
+ });
654
+ mesh.objectModifier = modifier;
655
+ this.refreshSplatMesh(mesh);
656
+ return {
657
+ mesh,
658
+ progressUniform,
659
+ mode,
660
+ radius: resolvedRadius,
661
+ };
662
+ }
663
+ refreshSplatMesh(mesh) {
664
+ mesh.updateGenerator();
665
+ const refreshableMesh = mesh;
666
+ refreshableMesh.updateVersion?.();
667
+ }
668
+ setWorldRevealProgress(controller, progress) {
669
+ controller.progressUniform.value = THREE.MathUtils.clamp(progress, 0, 1);
670
+ const refreshableMesh = controller.mesh;
671
+ refreshableMesh.updateVersion?.();
672
+ }
673
+ queueWorldReveal(incoming, options = {}) {
674
+ const reveal = {
675
+ controller: incoming,
676
+ incoming,
677
+ outgoing: options.outgoing ?? null,
678
+ progress: THREE.MathUtils.clamp(options.initialProgress ?? 0, 0, 1),
679
+ duration: options.duration ?? COMPANION_WORLD_REVEAL_DURATION,
680
+ waitingForVrm: options.waitingForVrm ?? false,
681
+ syncToTeleport: options.syncToTeleport ?? false,
682
+ };
683
+ incoming.mesh.opacity = 1;
684
+ if (reveal.outgoing) {
685
+ reveal.outgoing.mesh.opacity = 1;
686
+ }
687
+ this.worldReveal = reveal;
688
+ this.setWorldRevealProgress(incoming, reveal.progress);
689
+ if (reveal.outgoing) {
690
+ this.setWorldRevealProgress(reveal.outgoing, reveal.progress);
691
+ }
692
+ }
693
+ disposeSplatMesh(mesh) {
694
+ if (!mesh)
695
+ return;
696
+ mesh.parent?.remove(mesh);
697
+ mesh.dispose();
698
+ }
699
+ completeWorldReveal(reveal) {
700
+ this.setWorldRevealProgress(reveal.incoming, 1);
701
+ reveal.incoming.mesh.opacity = 1;
702
+ reveal.incoming.mesh.objectModifier = undefined;
703
+ this.refreshSplatMesh(reveal.incoming.mesh);
704
+ if (reveal.outgoing) {
705
+ reveal.outgoing.mesh.objectModifier = undefined;
706
+ this.disposeSplatMesh(reveal.outgoing.mesh);
707
+ }
708
+ if (this.worldReveal === reveal) {
709
+ this.worldReveal = null;
710
+ }
711
+ }
712
+ cancelWorldReveal() {
713
+ if (!this.worldReveal)
714
+ return;
715
+ this.completeWorldReveal(this.worldReveal);
716
+ }
717
+ startPendingWorldReveal(syncToTeleport) {
718
+ const reveal = this.worldReveal;
719
+ if (!reveal || !reveal.waitingForVrm)
720
+ return;
721
+ reveal.waitingForVrm = false;
722
+ reveal.syncToTeleport = syncToTeleport;
723
+ reveal.progress = syncToTeleport ? this.teleportProgress : 0;
724
+ this.setWorldRevealProgress(reveal.incoming, reveal.progress);
725
+ if (reveal.outgoing) {
726
+ this.setWorldRevealProgress(reveal.outgoing, reveal.progress);
727
+ }
728
+ }
729
+ updateWorldReveal(stableDelta) {
730
+ const reveal = this.worldReveal;
731
+ if (!reveal || reveal.waitingForVrm)
732
+ return;
733
+ const avatarRevealActive = this.revealStarted && this.teleportProgress < 0.999;
734
+ const nextProgress = reveal.syncToTeleport && avatarRevealActive
735
+ ? this.teleportProgress
736
+ : Math.min(1, reveal.progress + stableDelta / reveal.duration);
737
+ const appliedProgress = reveal.syncToTeleport && avatarRevealActive
738
+ ? nextProgress
739
+ : nextProgress ** COMPANION_WORLD_REVEAL_EASE_EXPONENT;
740
+ reveal.progress = nextProgress;
741
+ this.setWorldRevealProgress(reveal.incoming, appliedProgress);
742
+ if (reveal.outgoing) {
743
+ this.setWorldRevealProgress(reveal.outgoing, appliedProgress);
744
+ }
745
+ if (nextProgress >= 1) {
746
+ this.completeWorldReveal(reveal);
747
+ }
748
+ }
749
+ updateSparkDepthOfField(camera) {
750
+ const sparkRenderer = this.sparkRenderer;
751
+ if (!sparkRenderer)
752
+ return;
753
+ if (!this.worldMesh) {
754
+ sparkRenderer.apertureAngle = 0;
755
+ return;
756
+ }
757
+ const focalDistance = Math.max(0.5, camera.position.distanceTo(this.pointerParallaxLookAt));
758
+ const isCompanionProfile = this.cameraProfile === "companion" ||
759
+ this.cameraProfile === "companion_close";
760
+ const closeZoomFactor = isCompanionProfile
761
+ ? THREE.MathUtils.smoothstep(this.companionZoomCurrent, 0.3, 1)
762
+ : 0;
763
+ const apertureSize = THREE.MathUtils.lerp(COMPANION_DOF_APERTURE_SIZE, COMPANION_DOF_APERTURE_SIZE * COMPANION_DOF_NEAR_ZOOM_APERTURE_FACTOR, closeZoomFactor);
764
+ sparkRenderer.focalDistance = focalDistance;
765
+ sparkRenderer.apertureAngle =
766
+ 2 * Math.atan((0.5 * apertureSize) / sparkRenderer.focalDistance);
767
+ }
768
+ applyCompanionZoom(camera, stableDelta) {
769
+ const isCompanionProfile = this.cameraProfile === "companion" ||
770
+ this.cameraProfile === "companion_close";
771
+ const follow = Math.min(1, stableDelta * 10);
772
+ const targetZoom = isCompanionProfile ? this.companionZoomTarget : 0;
773
+ this.companionZoomCurrent = THREE.MathUtils.lerp(this.companionZoomCurrent, targetZoom, follow);
774
+ if (this.companionZoomCurrent < 1e-4)
775
+ return;
776
+ const baseRadius = this.baseCameraPosition.distanceTo(this.lookAtTarget);
777
+ if (!Number.isFinite(baseRadius) || baseRadius < 1e-4)
778
+ return;
779
+ const orbitOffset = this.tempCameraOrbitOffset
780
+ .copy(camera.position)
781
+ .sub(this.lookAtTarget);
782
+ if (orbitOffset.lengthSq() < 1e-6)
783
+ return;
784
+ const spherical = this.tempCameraSpherical.setFromVector3(orbitOffset);
785
+ const nearRadius = Math.max(COMPANION_ZOOM_MIN_RADIUS, baseRadius * COMPANION_ZOOM_NEAR_FACTOR);
786
+ spherical.radius = THREE.MathUtils.lerp(baseRadius, nearRadius, this.companionZoomCurrent);
787
+ camera.position
788
+ .copy(this.lookAtTarget)
789
+ .add(orbitOffset.setFromSpherical(spherical));
790
+ }
791
+ configureAvatarLookTracking(vrm) {
792
+ const target = this.avatarLookTarget;
793
+ if (target) {
794
+ target.position.set(0, 1.5, 2);
795
+ target.updateMatrixWorld(true);
796
+ }
797
+ if (vrm.lookAt && target) {
798
+ vrm.lookAt.autoUpdate = true;
799
+ vrm.lookAt.target = target;
800
+ }
801
+ const headBone = vrm.humanoid?.getRawBoneNode("head") ?? null;
802
+ const neckBone = vrm.humanoid?.getRawBoneNode("neck") ?? null;
803
+ const spineBone = vrm.humanoid?.getRawBoneNode("upperChest") ??
804
+ vrm.humanoid?.getRawBoneNode("chest") ??
805
+ vrm.humanoid?.getRawBoneNode("spine") ??
806
+ null;
807
+ this.avatarLookRig = {
808
+ headBone,
809
+ neckBone,
810
+ spineBone,
811
+ };
812
+ this.headLookTarget.set(0, 0);
813
+ this.headLookCurrent.set(0, 0);
814
+ }
815
+ updateAvatarLookTarget(camera, stableDelta) {
816
+ const target = this.avatarLookTarget;
817
+ if (!target)
818
+ return;
819
+ this.tempAvatarLookTarget.copy(camera.position);
820
+ const follow = Math.min(1, stableDelta * 24);
821
+ target.position.lerp(this.tempAvatarLookTarget, follow);
822
+ target.updateMatrixWorld(true);
823
+ }
824
+ refreshAvatarEyeTracking() {
825
+ const vrm = this.vrm;
826
+ if (!vrm?.lookAt || !this.avatarLookTarget)
827
+ return;
828
+ vrm.lookAt.update(0);
829
+ vrm.expressionManager?.update();
830
+ }
831
+ applyAvatarHeadTracking(camera, stableDelta) {
832
+ const vrm = this.vrm;
833
+ const { headBone, neckBone, spineBone } = this.avatarLookRig;
834
+ if (!vrm || !headBone)
835
+ return;
836
+ const headParent = headBone.parent;
837
+ if (!headParent || typeof headParent.worldToLocal !== "function")
838
+ return;
839
+ if (typeof THREE.Euler !== "function" ||
840
+ typeof THREE.Quaternion !== "function" ||
841
+ typeof headBone.quaternion.clone !== "function") {
842
+ return;
843
+ }
844
+ const lookAtState = vrm.lookAt;
845
+ const lookAtYawDegrees = lookAtState?._yaw;
846
+ const lookAtPitchDegrees = lookAtState?._pitch;
847
+ if (Number.isFinite(lookAtYawDegrees) &&
848
+ Number.isFinite(lookAtPitchDegrees)) {
849
+ this.headLookTarget.set(THREE.MathUtils.clamp(THREE.MathUtils.degToRad(lookAtYawDegrees || 0), -0.55, 0.55), THREE.MathUtils.clamp(THREE.MathUtils.degToRad(lookAtPitchDegrees || 0), -0.3, 0.24));
850
+ }
851
+ else {
852
+ headBone.getWorldPosition(this.tempAvatarHeadWorld);
853
+ this.tempAvatarLocalTarget.copy(camera.position);
854
+ this.tempAvatarLocalTarget.y -= 0.04;
855
+ headParent.worldToLocal(this.tempAvatarLocalTarget);
856
+ headParent.worldToLocal(this.tempAvatarLocalAnchor.copy(this.tempAvatarHeadWorld));
857
+ this.tempAvatarLocalTarget.sub(this.tempAvatarLocalAnchor);
858
+ const planarDistance = Math.max(1e-4, Math.hypot(this.tempAvatarLocalTarget.x, this.tempAvatarLocalTarget.z));
859
+ this.headLookTarget.set(THREE.MathUtils.clamp(Math.atan2(-this.tempAvatarLocalTarget.x, Math.max(-this.tempAvatarLocalTarget.z, 1e-4)), -0.55, 0.55), THREE.MathUtils.clamp(Math.atan2(this.tempAvatarLocalTarget.y, planarDistance), -0.3, 0.24));
860
+ }
861
+ this.headLookCurrent.lerp(this.headLookTarget, Math.min(1, stableDelta * 4.5));
862
+ const applyTrackedBone = (bone, yawWeight, pitchWeight) => {
863
+ if (!bone ||
864
+ !bone.quaternion ||
865
+ typeof bone.quaternion.clone !== "function") {
866
+ return;
867
+ }
868
+ const offsetEuler = new THREE.Euler(this.headLookCurrent.y * pitchWeight, this.headLookCurrent.x * yawWeight, 0, "YXZ");
869
+ const offsetQuaternion = new THREE.Quaternion().setFromEuler(offsetEuler);
870
+ const animatedPose = bone.quaternion.clone();
871
+ bone.quaternion.copy(animatedPose).multiply(offsetQuaternion);
872
+ };
873
+ applyTrackedBone(spineBone, 0.12, 0.06);
874
+ applyTrackedBone(neckBone, 0.3, 0.18);
875
+ applyTrackedBone(headBone, 0.52, 0.28);
876
+ }
877
+ toDebugVector3(vector) {
878
+ if (!vector)
879
+ return null;
880
+ return {
881
+ x: Number(vector.x.toFixed(4)),
882
+ y: Number(vector.y.toFixed(4)),
883
+ z: Number(vector.z.toFixed(4)),
884
+ };
885
+ }
886
+ toDebugBounds(object) {
887
+ if (!object)
888
+ return null;
889
+ const bounds = new THREE.Box3().setFromObject(object);
890
+ if (bounds.isEmpty())
891
+ return null;
892
+ return this.toDebugBoundsFromBox(bounds);
893
+ }
894
+ toDebugBoundsFromBox(bounds) {
895
+ if (!bounds || bounds.isEmpty())
896
+ return null;
897
+ const center = bounds.getCenter(new THREE.Vector3());
898
+ const size = bounds.getSize(new THREE.Vector3());
899
+ const min = this.toDebugVector3(bounds.min.clone());
900
+ const max = this.toDebugVector3(bounds.max.clone());
901
+ const centerVector = this.toDebugVector3(center);
902
+ const sizeVector = this.toDebugVector3(size);
903
+ if (!min || !max || !centerVector || !sizeVector)
904
+ return null;
905
+ return {
906
+ min,
907
+ max,
908
+ center: centerVector,
909
+ size: sizeVector,
910
+ };
911
+ }
912
+ getDebugInfo() {
913
+ this.scene?.updateMatrixWorld(true);
914
+ this.vrm?.scene.updateMatrixWorld(true);
915
+ this.worldMesh?.updateMatrixWorld(true);
916
+ const cameraRotation = this.camera
917
+ ? new THREE.Vector3(this.camera.rotation.x, this.camera.rotation.y, this.camera.rotation.z)
918
+ : null;
919
+ const lookAtTarget = this.toDebugVector3(this.lookAtTarget) ??
920
+ { x: 0, y: 0, z: 0 };
921
+ return {
922
+ initialized: this.initialized,
923
+ rendererBackend: this.rendererBackend,
924
+ cameraProfile: this.cameraProfile,
925
+ worldUrl: this.worldUrl,
926
+ sceneChildren: this.scene?.children.map((child) => child.name || child.type) ?? [],
927
+ camera: {
928
+ parentName: this.camera?.parent?.name ?? null,
929
+ position: this.toDebugVector3(this.camera?.position ?? null),
930
+ rotation: this.toDebugVector3(cameraRotation),
931
+ fov: this.camera?.fov ?? null,
932
+ lookAtTarget,
933
+ },
934
+ avatar: {
935
+ loaded: this.vrm !== null,
936
+ ready: this.vrmReady,
937
+ parentName: this.vrm?.scene.parent?.name ?? null,
938
+ position: this.toDebugVector3(this.vrm?.scene.position ?? null),
939
+ scale: this.toDebugVector3(this.vrm?.scene.scale ?? null),
940
+ bounds: this.toDebugBounds(this.vrm?.scene ?? null),
941
+ },
942
+ world: {
943
+ loaded: this.worldMesh !== null,
944
+ parentName: this.worldMesh?.parent?.name ?? null,
945
+ position: this.toDebugVector3(this.worldMesh?.position ?? null),
946
+ scale: this.toDebugVector3(this.worldMesh?.scale ?? null),
947
+ bounds: this.toDebugBounds(this.worldMesh ?? null),
948
+ rawBounds: this.worldMesh
949
+ ? this.toDebugBoundsFromBox(this.worldMesh.getBoundingBox(true))
950
+ : null,
951
+ },
952
+ spark: {
953
+ attached: this.sparkRenderer !== null,
954
+ parentName: this.sparkRenderer?.parent?.name ?? null,
955
+ renderOrder: this.sparkRenderer?.renderOrder ?? null,
956
+ },
957
+ };
958
+ }
959
+ setDebugAvatarVisible(visible) {
960
+ if (!this.vrm)
961
+ return;
962
+ this.vrm.scene.visible = visible;
963
+ }
964
+ setDebugWorldPosition(x, y, z) {
965
+ if (!this.worldMesh)
966
+ return;
967
+ this.worldMesh.position.set(x, y, z);
968
+ }
969
+ setDebugWorldQuaternion(x, y, z, w) {
970
+ if (!this.worldMesh)
971
+ return;
972
+ this.worldMesh.quaternion.set(x, y, z, w);
973
+ }
974
+ setDebugCamera(position, target) {
975
+ if (!this.camera)
976
+ return;
977
+ this.isCameraTransitioning = false;
978
+ this.camera.position.copy(position);
979
+ this.baseCameraPosition.copy(position);
980
+ this.lookAtTarget.copy(target);
981
+ this.controls?.target.copy(target);
982
+ this.controls?.update();
983
+ this.camera.lookAt(target);
984
+ }
985
+ startCameraTransition(startPos, startLookAt, startFov, targetPos, targetLookAt, targetFov, durationSeconds) {
986
+ if (!this.camera)
987
+ return;
988
+ this.transitionStartFov = startFov;
989
+ this.transitionTargetFov = targetFov;
990
+ this.transitionStartPos.copy(startPos);
991
+ this.transitionTargetPos.copy(targetPos);
992
+ this.transitionStartLookAt.copy(startLookAt);
993
+ this.transitionTargetLookAt.copy(targetLookAt);
994
+ this.transitionDuration = Math.max(0.01, durationSeconds);
995
+ this.camera.fov = startFov;
996
+ this.camera.position.copy(startPos);
997
+ this.camera.updateProjectionMatrix();
998
+ this.baseCameraPosition.copy(startPos);
999
+ this.lookAtTarget.copy(startLookAt);
1000
+ if (this.controls) {
1001
+ this.controls.target.copy(startLookAt);
1002
+ this.controls.update();
1003
+ }
1004
+ this.camera.lookAt(startLookAt);
1005
+ this.isCameraTransitioning = true;
1006
+ this.transitionProgress = 0;
1007
+ }
1008
+ transitionCameraToFramedAvatar(vrm, durationSeconds) {
1009
+ if (!this.camera)
1010
+ return;
1011
+ const startPos = new THREE.Vector3().copy(this.camera.position);
1012
+ const startLookAt = new THREE.Vector3().copy(this.lookAtTarget);
1013
+ const startFov = this.camera.fov;
1014
+ const targetLookAt = new THREE.Vector3();
1015
+ const targetPos = new THREE.Vector3();
1016
+ this.cameraManager.centerAndFrame(vrm, this.camera, this.controls, this.cameraProfile, targetLookAt, targetPos, (c) => this.cameraManager.applyInteractionMode(c, this.interactionMode));
1017
+ this.startCameraTransition(startPos, startLookAt, startFov, targetPos, targetLookAt, this.camera.fov, durationSeconds);
1018
+ }
1019
+ whenReady() {
1020
+ return this.readyPromise;
1021
+ }
1022
+ resetReadyPromise() {
1023
+ this.readyPromise = new Promise((resolve, reject) => {
1024
+ this.resolveReady = resolve;
1025
+ this.rejectReady = reject;
1026
+ });
1027
+ }
1028
+ settleReady(error) {
1029
+ if (error) {
1030
+ this.rejectReady?.(error);
1031
+ }
1032
+ else {
1033
+ this.resolveReady?.();
1034
+ }
1035
+ this.resolveReady = null;
1036
+ this.rejectReady = null;
1037
+ }
1038
+ setup(canvas, onUpdate, options) {
1039
+ if (this.initialized && this.renderer?.domElement === canvas) {
1040
+ this.onUpdate = onUpdate;
1041
+ return;
1042
+ }
1043
+ if (this.initialized)
1044
+ this.dispose();
1045
+ this.onUpdate = onUpdate;
1046
+ this.loadingAborted = false;
1047
+ this.rendererPreference = options?.rendererPreference ?? "auto";
1048
+ this.resetReadyPromise();
1049
+ // Async renderer creation: tries WebGPU, falls back to WebGL.
1050
+ // setup() remains synchronous for callers; the loop starts after init resolves.
1051
+ void (async () => {
1052
+ try {
1053
+ const { backend, renderer } = await createRenderer(canvas, this.rendererPreference, options?.sparkOptimized ?? false);
1054
+ const releaseKnownWebGpuWarningFilter = backend === "webgpu" ? installKnownVrmWebGpuWarningFilter() : null;
1055
+ // Guard: if dispose() was called while we were awaiting, abort.
1056
+ if (this.loadingAborted) {
1057
+ releaseKnownWebGpuWarningFilter?.();
1058
+ renderer.dispose();
1059
+ this.settleReady();
1060
+ return;
1061
+ }
1062
+ this.releaseKnownWebGpuWarningFilter = releaseKnownWebGpuWarningFilter;
1063
+ renderer.setPixelRatio(getRendererPixelRatio(options?.sparkOptimized ?? false));
1064
+ renderer.setClearColor(0x000000, 0);
1065
+ if (backend === "webgl") {
1066
+ const webglRenderer = renderer;
1067
+ webglRenderer.shadowMap.enabled = true;
1068
+ webglRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
1069
+ webglRenderer.toneMapping = THREE.NoToneMapping;
1070
+ webglRenderer.toneMappingExposure = 1.0;
1071
+ webglRenderer.outputColorSpace = THREE.SRGBColorSpace;
1072
+ }
1073
+ this.renderer = renderer;
1074
+ this.rendererBackend = backend;
1075
+ const scene = new THREE.Scene();
1076
+ this.scene = scene;
1077
+ const avatarRoot = new THREE.Group();
1078
+ avatarRoot.name = "AvatarRoot";
1079
+ scene.add(avatarRoot);
1080
+ this.avatarRoot = avatarRoot;
1081
+ const avatarLookTarget = new THREE.Group();
1082
+ avatarLookTarget.name = "AvatarLookTarget";
1083
+ scene.add(avatarLookTarget);
1084
+ this.avatarLookTarget = avatarLookTarget;
1085
+ const cameraRig = new THREE.Group();
1086
+ cameraRig.name = "AvatarCameraRig";
1087
+ scene.add(cameraRig);
1088
+ const camera = new THREE.PerspectiveCamera(30, 1, 0.1, 20);
1089
+ camera.position.set(0, 1.2, 5.0);
1090
+ cameraRig.add(camera);
1091
+ this.camera = camera;
1092
+ const controls = new OrbitControls(camera, renderer.domElement);
1093
+ controls.enableDamping = false;
1094
+ controls.target.copy(this.lookAtTarget);
1095
+ controls.addEventListener("start", this.handleControlStart);
1096
+ controls.addEventListener("end", this.handleControlEnd);
1097
+ this.cameraManager.applyInteractionMode(controls, this.interactionMode);
1098
+ controls.update();
1099
+ this.controls = controls;
1100
+ this.setInteractionEnabled(this.interactionEnabled);
1101
+ const ambient = new THREE.AmbientLight(0xffffff, 0.8);
1102
+ scene.add(ambient);
1103
+ const keyLight = new THREE.DirectionalLight(0xffffff, 1.2);
1104
+ keyLight.position.set(1, 1, 1).normalize();
1105
+ keyLight.castShadow = true;
1106
+ keyLight.shadow.mapSize.setScalar(1024);
1107
+ scene.add(keyLight);
1108
+ const fillLight = new THREE.DirectionalLight(0xffffff, 0.4);
1109
+ fillLight.position.set(-1, 0.5, -1).normalize();
1110
+ scene.add(fillLight);
1111
+ this.resize(canvas.clientWidth, canvas.clientHeight);
1112
+ this.initialized = true;
1113
+ this.resumeLoop();
1114
+ this.settleReady();
1115
+ }
1116
+ catch (error) {
1117
+ this.initialized = false;
1118
+ this.releaseKnownWebGpuWarningFilter?.();
1119
+ this.releaseKnownWebGpuWarningFilter = null;
1120
+ this.renderer = null;
1121
+ this.rendererBackend = "webgl";
1122
+ this.scene = null;
1123
+ this.camera = null;
1124
+ this.controls = null;
1125
+ console.error("[VrmEngine] Failed to initialize renderer:", error);
1126
+ this.settleReady(error);
1127
+ }
1128
+ })();
1129
+ }
1130
+ isInitialized() {
1131
+ return this.initialized && this.renderer !== null;
1132
+ }
1133
+ dispose() {
1134
+ this.loadingAborted = true;
1135
+ this.initialized = false;
1136
+ this.settleReady();
1137
+ this.releaseKnownWebGpuWarningFilter?.();
1138
+ this.releaseKnownWebGpuWarningFilter = null;
1139
+ if (this.animationFrameId !== null) {
1140
+ cancelAnimationFrame(this.animationFrameId);
1141
+ this.animationFrameId = null;
1142
+ }
1143
+ if (this.vrm?.scene.parent) {
1144
+ this.vrm.scene.parent.remove(this.vrm.scene);
1145
+ VRMUtils.deepDispose(this.vrm.scene);
1146
+ }
1147
+ if (this.controls) {
1148
+ this.controls.removeEventListener("start", this.handleControlStart);
1149
+ this.controls.removeEventListener("end", this.handleControlEnd);
1150
+ this.controls.dispose();
1151
+ this.controls = null;
1152
+ }
1153
+ this.vrm = null;
1154
+ this.vrmReady = false;
1155
+ this.vrmName = null;
1156
+ this.lastLoadError = null;
1157
+ this.mixer = null;
1158
+ this.idleAction = null;
1159
+ this.idleLoadPromise = null;
1160
+ this.clearPendingEmoteCompletion();
1161
+ this.emoteAction = null;
1162
+ this.emoteClipCache.clear();
1163
+ this.teleportProgress = 1.0;
1164
+ this.cleanupTeleportDissolve();
1165
+ this.cleanupTeleportSparkles();
1166
+ this.disposeWorld();
1167
+ this.avatarLookTarget?.parent?.remove(this.avatarLookTarget);
1168
+ this.avatarLookTarget = null;
1169
+ this.avatarLookRig = {
1170
+ headBone: null,
1171
+ neckBone: null,
1172
+ spineBone: null,
1173
+ };
1174
+ this.headLookTarget.set(0, 0);
1175
+ this.headLookCurrent.set(0, 0);
1176
+ if (this.sparkRenderer) {
1177
+ this.sparkRenderer.apertureAngle = 0;
1178
+ this.sparkRenderer.removeFromParent();
1179
+ this.sparkRenderer = null;
1180
+ }
1181
+ if (this.renderer) {
1182
+ this.renderer.dispose();
1183
+ }
1184
+ this.renderer = null;
1185
+ this.rendererBackend = "webgl";
1186
+ this.scene = null;
1187
+ this.avatarRoot = null;
1188
+ this.camera = null;
1189
+ this.onUpdate = null;
1190
+ this.paused = false;
1191
+ }
1192
+ setPaused(paused) {
1193
+ if (this.paused === paused)
1194
+ return;
1195
+ this.paused = paused;
1196
+ if (paused) {
1197
+ this.stopLoop();
1198
+ return;
1199
+ }
1200
+ this.resumeLoop();
1201
+ }
1202
+ setInteractionEnabled(enabled) {
1203
+ this.interactionEnabled = enabled;
1204
+ if (this.controls) {
1205
+ this.controls.enabled = enabled;
1206
+ }
1207
+ }
1208
+ setInteractionMode(mode) {
1209
+ this.interactionMode = mode;
1210
+ if (this.controls) {
1211
+ this.cameraManager.applyInteractionMode(this.controls, mode);
1212
+ this.controls.update();
1213
+ }
1214
+ }
1215
+ setCameraProfile(profile) {
1216
+ if (this.cameraProfile === profile)
1217
+ return;
1218
+ if (this.camera) {
1219
+ const startFov = this.camera.fov;
1220
+ const startPos = new THREE.Vector3().copy(this.camera.position);
1221
+ const startLookAt = new THREE.Vector3().copy(this.lookAtTarget);
1222
+ this.cameraProfile = profile;
1223
+ const targetLookAt = new THREE.Vector3().copy(this.lookAtTarget);
1224
+ const targetPos = new THREE.Vector3().copy(this.camera.position);
1225
+ if (this.vrm) {
1226
+ this.cameraManager.centerAndFrame(this.vrm, this.camera, this.controls, this.cameraProfile, targetLookAt, targetPos, (c) => this.cameraManager.applyInteractionMode(c, this.interactionMode));
1227
+ }
1228
+ else {
1229
+ this.cameraManager.applyCameraProfileToCamera(this.camera, this.controls, this.cameraProfile);
1230
+ targetPos.copy(this.camera.position);
1231
+ if (this.controls) {
1232
+ targetLookAt.copy(this.controls.target);
1233
+ }
1234
+ }
1235
+ this.startCameraTransition(startPos, startLookAt, startFov, targetPos, targetLookAt, this.camera.fov, CAMERA_PROFILE_TRANSITION_DURATION_SECONDS);
1236
+ }
1237
+ else {
1238
+ this.cameraProfile = profile;
1239
+ }
1240
+ }
1241
+ resize(width, height) {
1242
+ if (!this.renderer || !this.camera)
1243
+ return;
1244
+ if (width <= 0 || height <= 0)
1245
+ return;
1246
+ const aspect = width / height;
1247
+ if (!Number.isFinite(aspect) || aspect <= 0)
1248
+ return;
1249
+ this.renderer.setSize(width, height, false);
1250
+ this.camera.aspect = aspect;
1251
+ this.camera.updateProjectionMatrix();
1252
+ }
1253
+ getState() {
1254
+ const idlePlaying = this.idleAction?.isRunning() ?? false;
1255
+ return {
1256
+ vrmLoaded: this.vrm !== null && this.vrmReady,
1257
+ vrmName: this.vrmName,
1258
+ loadError: this.lastLoadError,
1259
+ idlePlaying,
1260
+ idleTime: this.idleAction?.time ?? 0,
1261
+ idleTracks: this.idleAction?.getClip()?.tracks.length ?? 0,
1262
+ revealStarted: this.revealStarted,
1263
+ loadingProgress: this.loadingProgress,
1264
+ };
1265
+ }
1266
+ setMouthOpen(value) {
1267
+ this.mouthValue = Math.max(0, Math.min(1, value));
1268
+ }
1269
+ setSpeaking(speaking) {
1270
+ if (speaking && !this.speaking) {
1271
+ this.speakingStartTime = this.elapsedTime;
1272
+ }
1273
+ this.speaking = speaking;
1274
+ }
1275
+ setCameraAnimation(config) {
1276
+ this.cameraAnimation = { ...this.cameraAnimation, ...config };
1277
+ }
1278
+ setPointerParallaxEnabled(enabled) {
1279
+ this.pointerParallaxEnabled = enabled;
1280
+ if (!enabled) {
1281
+ this.pointerParallaxTarget.set(0, 0);
1282
+ }
1283
+ }
1284
+ setPointerParallaxTarget(x, y) {
1285
+ this.pointerParallaxTarget.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1));
1286
+ }
1287
+ resetPointerParallax() {
1288
+ this.pointerParallaxTarget.set(0, 0);
1289
+ }
1290
+ setDragOrbitTarget(yaw, pitch) {
1291
+ this.dragOrbitTarget.set(THREE.MathUtils.clamp(yaw, -0.6, 0.6), THREE.MathUtils.clamp(pitch, -0.35, 0.35));
1292
+ }
1293
+ resetDragOrbit() {
1294
+ this.dragOrbitTarget.set(0, 0);
1295
+ }
1296
+ setCompanionZoomNormalized(value) {
1297
+ this.companionZoomTarget = THREE.MathUtils.clamp(value, 0, 1);
1298
+ }
1299
+ async setWorldUrl(url) {
1300
+ await this.whenReady();
1301
+ if (!this.scene)
1302
+ return;
1303
+ const normalizedUrl = url?.trim() ? url : null;
1304
+ if (this.worldUrl === normalizedUrl && this.worldMesh)
1305
+ return;
1306
+ const requestId = ++this.worldLoadRequestId;
1307
+ this.worldUrl = normalizedUrl;
1308
+ this.cancelWorldReveal();
1309
+ const outgoingWorld = this.worldMesh;
1310
+ if (!normalizedUrl) {
1311
+ this.disposeWorld();
1312
+ return;
1313
+ }
1314
+ await this.ensureSparkRenderer();
1315
+ // Re-check after async — the engine may have been disposed during the
1316
+ // await (e.g. React StrictMode double-mount or rapid navigation).
1317
+ if (!this.scene || this.loadingAborted || requestId !== this.worldLoadRequestId)
1318
+ return;
1319
+ const spark = await this.loadSparkModule();
1320
+ if (!this.scene || this.loadingAborted || requestId !== this.worldLoadRequestId)
1321
+ return;
1322
+ const { SplatMesh } = spark;
1323
+ let worldAnchor = new THREE.Vector3(0, 0, 0);
1324
+ let worldRevealRadius = 1;
1325
+ const splat = new SplatMesh({
1326
+ url: normalizedUrl,
1327
+ constructSplats: (packedSplats) => {
1328
+ worldAnchor = getRobustPackedSplatAnchor(packedSplats);
1329
+ worldRevealRadius = getRobustPackedSplatRadialExtent(packedSplats, worldAnchor);
1330
+ },
1331
+ });
1332
+ splat.frustumCulled = false;
1333
+ splat.quaternion.identity();
1334
+ splat.position.set(0, 0, 0);
1335
+ splat.scale.setScalar(COMPANION_WORLD_SCALE);
1336
+ this.scene.add(splat);
1337
+ await splat.initialized;
1338
+ if (this.loadingAborted ||
1339
+ !this.scene ||
1340
+ requestId !== this.worldLoadRequestId) {
1341
+ splat.parent?.remove(splat);
1342
+ splat.dispose();
1343
+ return;
1344
+ }
1345
+ const worldCenterBottom = worldAnchor.lengthSq() > 0 ? worldAnchor : getRobustSplatAnchor(splat);
1346
+ const worldFloorOffsetY = getCompanionWorldFloorOffsetY(normalizedUrl);
1347
+ splat.position.set(-worldCenterBottom.x * COMPANION_WORLD_SCALE, -worldCenterBottom.y * COMPANION_WORLD_SCALE + worldFloorOffsetY, -worldCenterBottom.z * COMPANION_WORLD_SCALE);
1348
+ const syncToTeleport = this.revealStarted && this.teleportProgress < 0.999;
1349
+ const waitingForVrm = !outgoingWorld && !this.vrmReady;
1350
+ const incomingRevealRadius = Math.max(worldRevealRadius * COMPANION_WORLD_SCALE, getRobustSplatRadialExtent(splat, worldCenterBottom) *
1351
+ COMPANION_WORLD_SCALE);
1352
+ let outgoingAnchor = null;
1353
+ let sharedRevealRadius = incomingRevealRadius;
1354
+ if (outgoingWorld && !waitingForVrm) {
1355
+ outgoingAnchor = getRobustSplatAnchor(outgoingWorld);
1356
+ sharedRevealRadius = Math.max(sharedRevealRadius, getRobustSplatRadialExtent(outgoingWorld, outgoingAnchor) *
1357
+ COMPANION_WORLD_SCALE);
1358
+ }
1359
+ const worldReveal = this.createWorldRevealController(spark, splat, {
1360
+ origin: worldCenterBottom,
1361
+ radius: sharedRevealRadius,
1362
+ }, "reveal");
1363
+ this.worldMesh = splat;
1364
+ if (worldReveal) {
1365
+ let outgoingReveal = null;
1366
+ if (outgoingWorld && outgoingAnchor && !waitingForVrm) {
1367
+ outgoingReveal = this.createWorldRevealController(spark, outgoingWorld, {
1368
+ origin: outgoingAnchor,
1369
+ radius: sharedRevealRadius,
1370
+ }, "hide");
1371
+ if (!outgoingReveal) {
1372
+ this.disposeSplatMesh(outgoingWorld);
1373
+ }
1374
+ }
1375
+ this.queueWorldReveal(worldReveal, {
1376
+ outgoing: outgoingReveal,
1377
+ duration: COMPANION_WORLD_REVEAL_DURATION,
1378
+ waitingForVrm,
1379
+ syncToTeleport,
1380
+ initialProgress: syncToTeleport ? this.teleportProgress : 0,
1381
+ });
1382
+ }
1383
+ else {
1384
+ this.disposeSplatMesh(outgoingWorld);
1385
+ }
1386
+ }
1387
+ async playEmote(path, duration, loop) {
1388
+ const vrm = this.vrm;
1389
+ const mixer = this.mixer;
1390
+ if (!vrm || !mixer)
1391
+ return;
1392
+ this.clearPendingEmoteCompletion();
1393
+ this.emoteRequestId++;
1394
+ const requestId = this.emoteRequestId;
1395
+ const currentAction = this.emoteAction;
1396
+ const blendSource = currentAction ?? this.idleAction;
1397
+ const clip = await this.loadEmoteClipCached(path, vrm);
1398
+ if (!clip || this.vrm !== vrm || this.mixer !== mixer)
1399
+ return;
1400
+ if (this.emoteRequestId !== requestId)
1401
+ return;
1402
+ const action = mixer.clipAction(clip);
1403
+ action.setLoop(loop ? THREE.LoopRepeat : THREE.LoopOnce, loop ? Infinity : 1);
1404
+ action.clampWhenFinished = !loop;
1405
+ const fadeDuration = 0.4;
1406
+ this.playActionWithBlend(action, blendSource, fadeDuration);
1407
+ this.emoteAction = action;
1408
+ if (!loop) {
1409
+ const clipDuration = Number.isFinite(duration) && duration > 0 ? duration : clip.duration;
1410
+ this.watchOneShotEmoteCompletion(mixer, action, requestId, clipDuration);
1411
+ }
1412
+ }
1413
+ stopEmote() {
1414
+ this.clearPendingEmoteCompletion();
1415
+ const fadeDuration = 0.4;
1416
+ const activeEmote = this.emoteAction;
1417
+ this.emoteAction = null;
1418
+ if (this.idleAction) {
1419
+ this.activateAction(this.idleAction);
1420
+ if (activeEmote && activeEmote !== this.idleAction) {
1421
+ this.idleAction.crossFadeFrom(activeEmote, fadeDuration, false);
1422
+ }
1423
+ else {
1424
+ this.idleAction.fadeIn(fadeDuration);
1425
+ }
1426
+ return;
1427
+ }
1428
+ if (this.vrm && this.mixer) {
1429
+ this.restoreIdleAfterEmote(activeEmote, fadeDuration, this.vrm, this.mixer);
1430
+ return;
1431
+ }
1432
+ activeEmote?.fadeOut(fadeDuration);
1433
+ }
1434
+ /** Play a one-shot wave greeting after the VRM becomes visible. */
1435
+ playWaveGreeting() {
1436
+ this.playEmote("animations/emotes/waving-both-hands.glb.gz", 3, false);
1437
+ }
1438
+ async loadVrmFromUrl(url, name) {
1439
+ await this.whenReady();
1440
+ if (!this.scene)
1441
+ throw new Error("VrmEngine not initialized");
1442
+ if (!this.camera)
1443
+ throw new Error("VrmEngine not initialized");
1444
+ if (this.loadingAborted)
1445
+ return;
1446
+ const requestId = ++this.vrmLoadRequestId;
1447
+ const hadPreviousVrm = this.vrm !== null;
1448
+ if (this.vrm) {
1449
+ this.vrm.scene.parent?.remove(this.vrm.scene);
1450
+ VRMUtils.deepDispose(this.vrm.scene);
1451
+ this.vrm = null;
1452
+ this.vrmReady = false;
1453
+ this.vrmName = null;
1454
+ this.mixer = null;
1455
+ this.idleAction = null;
1456
+ this.idleLoadPromise = null;
1457
+ this.revealStarted = false;
1458
+ this.cleanupTeleportSparkles();
1459
+ this.stopEmote();
1460
+ this.emoteClipCache.clear();
1461
+ }
1462
+ this.lastLoadError = null;
1463
+ this.loadingProgress = 0;
1464
+ this.onUpdate?.();
1465
+ const loader = new GLTFLoader();
1466
+ configureVrmGltfLoader(loader);
1467
+ const webGpuNodes = this.rendererBackend === "webgpu"
1468
+ ? await import("@pixiv/three-vrm/nodes")
1469
+ : null;
1470
+ loader.register((parser) => {
1471
+ if (webGpuNodes) {
1472
+ const mtoonMaterialPlugin = new MToonMaterialLoaderPlugin(parser, {
1473
+ materialType: webGpuNodes.MToonNodeMaterial,
1474
+ });
1475
+ return new VRMLoaderPlugin(parser, { mtoonMaterialPlugin });
1476
+ }
1477
+ return new VRMLoaderPlugin(parser);
1478
+ });
1479
+ let gltf;
1480
+ try {
1481
+ gltf = await loadGltfAsset(loader, url, (progress) => {
1482
+ if (this.vrmLoadRequestId === requestId && !this.loadingAborted) {
1483
+ this.loadingProgress = progress;
1484
+ this.onUpdate?.();
1485
+ }
1486
+ });
1487
+ }
1488
+ catch (error) {
1489
+ if (!this.loadingAborted && requestId === this.vrmLoadRequestId) {
1490
+ this.lastLoadError =
1491
+ error instanceof Error ? error.message : String(error);
1492
+ this.onUpdate?.();
1493
+ }
1494
+ throw error;
1495
+ }
1496
+ if (this.loadingAborted ||
1497
+ !this.scene ||
1498
+ requestId !== this.vrmLoadRequestId) {
1499
+ const staleVrm = gltf.userData.vrm;
1500
+ if (staleVrm)
1501
+ VRMUtils.deepDispose(staleVrm.scene);
1502
+ return;
1503
+ }
1504
+ const vrm = gltf.userData.vrm;
1505
+ if (!vrm)
1506
+ throw new Error("Loaded asset is not a VRM");
1507
+ VRMUtils.removeUnnecessaryVertices(vrm.scene);
1508
+ if (this.camera) {
1509
+ if (hadPreviousVrm) {
1510
+ this.transitionCameraToFramedAvatar(vrm, AVATAR_SWITCH_CAMERA_TRANSITION_DURATION_SECONDS);
1511
+ }
1512
+ else {
1513
+ this.cameraManager.centerAndFrame(vrm, this.camera, this.controls, this.cameraProfile, this.lookAtTarget, this.baseCameraPosition, (c) => this.cameraManager.applyInteractionMode(c, this.interactionMode));
1514
+ }
1515
+ }
1516
+ try {
1517
+ VRMUtils.rotateVRM0(vrm);
1518
+ }
1519
+ catch {
1520
+ /* optional in some versions */
1521
+ }
1522
+ this.cameraManager.ensureFacingCamera(vrm, this.camera);
1523
+ this.configureAvatarLookTracking(vrm);
1524
+ if (this.loadingAborted ||
1525
+ !this.scene ||
1526
+ requestId !== this.vrmLoadRequestId) {
1527
+ VRMUtils.deepDispose(vrm.scene);
1528
+ return;
1529
+ }
1530
+ vrm.scene.visible = false;
1531
+ vrm.scene.traverse((obj) => {
1532
+ obj.frustumCulled = false;
1533
+ });
1534
+ const avatarParent = this.avatarRoot ?? this.scene;
1535
+ avatarParent.add(vrm.scene);
1536
+ this.vrm = vrm;
1537
+ this.vrmName = name ?? null;
1538
+ this.lastLoadError = null;
1539
+ vrm.springBoneManager?.reset?.();
1540
+ this.blinkController.reset();
1541
+ try {
1542
+ await this.loadAndPlayIdle(vrm);
1543
+ if (!this.loadingAborted && this.vrm === vrm) {
1544
+ this.vrmReady = true;
1545
+ // Let the idle animation settle into a natural pose before revealing
1546
+ await new Promise((resolve) => setTimeout(resolve, 300));
1547
+ if (this.loadingAborted || this.vrm !== vrm)
1548
+ return;
1549
+ await this.playTeleportReveal(vrm);
1550
+ vrm.scene.visible = true;
1551
+ this.startPendingWorldReveal(true);
1552
+ this.playWaveGreeting();
1553
+ }
1554
+ }
1555
+ catch {
1556
+ if (!this.loadingAborted && this.vrm === vrm) {
1557
+ this.vrmReady = true;
1558
+ vrm.scene.visible = true;
1559
+ this.startPendingWorldReveal(false);
1560
+ }
1561
+ }
1562
+ }
1563
+ async playTeleportReveal(vrm) {
1564
+ this.teleportProgress = 0.0;
1565
+ this.revealStarted = true;
1566
+ this.cleanupTeleportDissolve();
1567
+ this.startTeleportSparkles(vrm);
1568
+ let appliedNodeDissolve = false;
1569
+ try {
1570
+ const tsl = await import("three/tsl");
1571
+ const uProgress = tsl.uniform(0.0);
1572
+ this.teleportProgressUniform = uProgress;
1573
+ vrm.scene.traverse((obj) => {
1574
+ if (!(obj instanceof THREE.Mesh))
1575
+ return;
1576
+ const mats = Array.isArray(obj.material)
1577
+ ? obj.material
1578
+ : [obj.material];
1579
+ for (const mat of mats) {
1580
+ if (!mat.isNodeMaterial || mat.userData._dissolveApplied)
1581
+ continue;
1582
+ appliedNodeDissolve = true;
1583
+ mat.userData._dissolveApplied = true;
1584
+ mat.userData._origOpacityNode = mat.opacityNode ?? null;
1585
+ mat.userData._origEmissiveNode =
1586
+ mat.emissiveNode ?? null;
1587
+ mat.userData._origAlphaTest = mat.alphaTest;
1588
+ // World-space Y from TSL
1589
+ const worldY = tsl.positionWorld.y;
1590
+ // Sweep threshold starts 1m lower than before.
1591
+ const threshold = uProgress
1592
+ .mul(TELEPORT_DISSOLVE_END_Y - TELEPORT_DISSOLVE_START_Y)
1593
+ .add(TELEPORT_DISSOLVE_START_Y);
1594
+ // Distance above dissolve line
1595
+ const diff = worldY.sub(threshold);
1596
+ // Dither noise using a hash of world position
1597
+ const noiseCoord = tsl.vec2(worldY.mul(40.0), tsl.positionWorld.x.add(tsl.positionWorld.z).mul(30.0));
1598
+ const noise = tsl.fract(tsl
1599
+ .sin(tsl.dot(noiseCoord, tsl.vec2(12.9898, 78.233)))
1600
+ .mul(43758.5453));
1601
+ // Ratio: 0 = fully visible, 1 = fully hidden (wider zone = 0.3)
1602
+ const ratio = diff.div(0.3).clamp(0.0, 1.0);
1603
+ // Dithered alpha: visible when noise >= ratio
1604
+ const dissolveAlpha = tsl.step(ratio, noise);
1605
+ // --- Holographic glow at the dissolve edge ---
1606
+ // Glow is strongest right at the dissolve boundary
1607
+ const edgeDist = diff.abs();
1608
+ const glowWidth = tsl.float(0.15);
1609
+ const glowIntensity = tsl
1610
+ .float(1.0)
1611
+ .sub(edgeDist.div(glowWidth).clamp(0.0, 1.0));
1612
+ // Holographic color: cyan-magenta shift based on world position
1613
+ const hueShift = tsl.fract(worldY.mul(3.0).add(uProgress.mul(2.0)));
1614
+ const holoR = tsl
1615
+ .smoothstep(tsl.float(0.3), tsl.float(0.7), hueShift)
1616
+ .mul(0.8)
1617
+ .add(0.2);
1618
+ const holoG = tsl.float(0.9);
1619
+ const holoB = tsl
1620
+ .smoothstep(tsl.float(0.7), tsl.float(0.3), hueShift)
1621
+ .mul(0.8)
1622
+ .add(0.2);
1623
+ const holoColor = tsl.vec3(holoR, holoG, holoB);
1624
+ // Only show glow when dissolve is active and fragment is visible
1625
+ const glowActive = tsl
1626
+ .step(tsl.float(0.001), uProgress)
1627
+ .mul(tsl.float(1.0).sub(tsl.step(tsl.float(0.999), uProgress)));
1628
+ const emissiveBoost = holoColor.mul(glowIntensity.mul(3.0).mul(glowActive).mul(dissolveAlpha));
1629
+ // Compose with existing nodes
1630
+ const origOpacity = mat.opacityNode;
1631
+ mat.opacityNode = origOpacity
1632
+ ? (origOpacity.mul(dissolveAlpha) ?? dissolveAlpha)
1633
+ : dissolveAlpha;
1634
+ const matWithEmissive = mat;
1635
+ const origEmissive = matWithEmissive.emissiveNode;
1636
+ matWithEmissive.emissiveNode = origEmissive
1637
+ ? origEmissive.add(emissiveBoost)
1638
+ : emissiveBoost;
1639
+ mat.alphaTest = 0.01;
1640
+ mat.transparent = true;
1641
+ mat.needsUpdate = true;
1642
+ this.teleportDissolvedMaterials.push(mat);
1643
+ }
1644
+ });
1645
+ }
1646
+ catch (err) {
1647
+ console.warn("[VrmEngine] TSL dissolve unavailable, showing instantly:", err);
1648
+ }
1649
+ if (!appliedNodeDissolve) {
1650
+ this.applyTeleportFallbackDissolve(vrm);
1651
+ }
1652
+ }
1653
+ applyTeleportFallbackDissolve(vrm) {
1654
+ vrm.scene.traverse((obj) => {
1655
+ if (!(obj instanceof THREE.Mesh))
1656
+ return;
1657
+ const mats = Array.isArray(obj.material) ? obj.material : [obj.material];
1658
+ for (const mat of mats) {
1659
+ if (mat.userData._dissolveApplied)
1660
+ continue;
1661
+ mat.userData._dissolveApplied = true;
1662
+ mat.userData._origTransparent = mat.transparent;
1663
+ mat.userData._origAlphaTest = mat.alphaTest;
1664
+ mat.userData._origOnBeforeCompile = mat.onBeforeCompile;
1665
+ mat.userData._origCustomProgramCacheKey = mat.customProgramCacheKey;
1666
+ const shaderRef = {
1667
+ uniforms: { uTeleportProgress: { value: this.teleportProgress } },
1668
+ };
1669
+ this.teleportFallbackShaders.push(shaderRef);
1670
+ mat.transparent = true;
1671
+ mat.alphaTest = Math.max(mat.alphaTest ?? 0, 0.01);
1672
+ mat.onBeforeCompile = (shader) => {
1673
+ shader.uniforms.uTeleportProgress =
1674
+ shaderRef.uniforms.uTeleportProgress;
1675
+ shader.vertexShader = `
1676
+ varying vec3 vTeleportWorldPosition;
1677
+ ${shader.vertexShader}
1678
+ `.replace("#include <worldpos_vertex>", `#include <worldpos_vertex>
1679
+ vTeleportWorldPosition = worldPosition.xyz;`);
1680
+ shader.fragmentShader = `
1681
+ uniform float uTeleportProgress;
1682
+ varying vec3 vTeleportWorldPosition;
1683
+ float teleportNoiseHash(vec2 p) {
1684
+ return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
1685
+ }
1686
+ ${shader.fragmentShader}
1687
+ `.replace("#include <alphatest_fragment>", `float teleportThreshold = mix(${TELEPORT_DISSOLVE_START_Y.toFixed(1)}, ${TELEPORT_DISSOLVE_END_Y.toFixed(1)}, uTeleportProgress);
1688
+ float teleportDiff = vTeleportWorldPosition.y - teleportThreshold;
1689
+ float teleportRatio = clamp(teleportDiff / 0.3, 0.0, 1.0);
1690
+ float teleportNoise = teleportNoiseHash(vec2(
1691
+ vTeleportWorldPosition.y * 40.0,
1692
+ (vTeleportWorldPosition.x + vTeleportWorldPosition.z) * 30.0
1693
+ ));
1694
+ if (teleportNoise < teleportRatio) discard;
1695
+ #include <alphatest_fragment>`);
1696
+ const originalOnBeforeCompile = mat.userData._origOnBeforeCompile;
1697
+ if (typeof originalOnBeforeCompile === "function") {
1698
+ originalOnBeforeCompile(shader, this.renderer);
1699
+ }
1700
+ };
1701
+ mat.customProgramCacheKey = () => `${mat.type}:teleport-dissolve-fallback`;
1702
+ mat.needsUpdate = true;
1703
+ this.teleportDissolvedMaterials.push(mat);
1704
+ }
1705
+ });
1706
+ }
1707
+ startTeleportSparkles(vrm) {
1708
+ const parent = this.avatarRoot ?? this.scene;
1709
+ if (!parent)
1710
+ return;
1711
+ this.cleanupTeleportSparkles();
1712
+ const bounds = new THREE.Box3().setFromObject(vrm.scene);
1713
+ const center = bounds.getCenter(new THREE.Vector3());
1714
+ const size = bounds.getSize(new THREE.Vector3());
1715
+ const sparkleGroup = new THREE.Group();
1716
+ sparkleGroup.position.set(center.x, bounds.min.y + 0.06, center.z);
1717
+ parent.add(sparkleGroup);
1718
+ const texture = getTeleportSparkleTexture();
1719
+ const particleHeight = THREE.MathUtils.clamp(size.y * 0.82, 0.95, 1.75);
1720
+ const particles = [];
1721
+ for (let index = 0; index < TELEPORT_SPARKLE_PARTICLE_COUNT; index += 1) {
1722
+ const hue = 0.52 + Math.random() * 0.08;
1723
+ const material = new THREE.SpriteMaterial({
1724
+ map: texture,
1725
+ color: new THREE.Color().setHSL(hue, 0.85, 0.72),
1726
+ transparent: true,
1727
+ opacity: 0,
1728
+ depthWrite: false,
1729
+ blending: THREE.AdditiveBlending,
1730
+ });
1731
+ const sprite = new THREE.Sprite(material);
1732
+ sprite.visible = false;
1733
+ sparkleGroup.add(sprite);
1734
+ const duration = 0.3 + Math.random() * 0.32;
1735
+ const maxStart = Math.max(0.02, 0.92 - duration);
1736
+ particles.push({
1737
+ sprite,
1738
+ material,
1739
+ baseAngle: (index / TELEPORT_SPARKLE_PARTICLE_COUNT) * Math.PI * 2 +
1740
+ (Math.random() - 0.5) * 0.55,
1741
+ baseRadius: (0.18 + Math.random() * 0.82) * TELEPORT_SPARKLE_RING_RADIUS,
1742
+ height: particleHeight * (0.55 + Math.random() * 0.55),
1743
+ start: Math.random() * maxStart,
1744
+ duration,
1745
+ spin: (1.8 + Math.random() * 3.6) * (Math.random() > 0.5 ? 1 : -1),
1746
+ wobble: 0.02 + Math.random() * 0.08,
1747
+ wobbleSpeed: 8 + Math.random() * 12,
1748
+ baseSize: TELEPORT_SPARKLE_MIN_SIZE +
1749
+ Math.random() *
1750
+ (TELEPORT_SPARKLE_MAX_SIZE - TELEPORT_SPARKLE_MIN_SIZE),
1751
+ });
1752
+ }
1753
+ this.teleportSparkles = {
1754
+ group: sparkleGroup,
1755
+ particles,
1756
+ };
1757
+ this.updateTeleportSparkles();
1758
+ }
1759
+ updateTeleportSparkles() {
1760
+ const system = this.teleportSparkles;
1761
+ if (!system)
1762
+ return;
1763
+ const progress = THREE.MathUtils.clamp(this.teleportProgress, 0, 1);
1764
+ let anyVisible = false;
1765
+ for (const particle of system.particles) {
1766
+ const localProgress = THREE.MathUtils.clamp((progress - particle.start) / particle.duration, 0, 1);
1767
+ if (localProgress <= 0 || localProgress >= 1) {
1768
+ particle.material.opacity = 0;
1769
+ particle.sprite.visible = false;
1770
+ continue;
1771
+ }
1772
+ anyVisible = true;
1773
+ const rise = 1 - (1 - localProgress) ** 2;
1774
+ const angle = particle.baseAngle + progress * Math.PI * 2 * particle.spin;
1775
+ const wobblePhase = progress * particle.wobbleSpeed + particle.baseAngle;
1776
+ const wobbleOffset = Math.sin(wobblePhase) * particle.wobble;
1777
+ const radial = particle.baseRadius * (1 - 0.48 * rise);
1778
+ const x = Math.cos(angle) * radial + wobbleOffset;
1779
+ const z = Math.sin(angle) * radial + Math.cos(wobblePhase) * particle.wobble;
1780
+ const y = 0.08 +
1781
+ particle.height * rise +
1782
+ Math.sin(progress * 10 + particle.baseAngle * 3) * 0.04;
1783
+ const opacity = Math.sin(localProgress * Math.PI) *
1784
+ (0.72 + 0.28 * Math.sin(progress * 22 + particle.baseAngle * 5));
1785
+ const scale = particle.baseSize * (0.7 + (1 - localProgress) * 1.15);
1786
+ particle.sprite.visible = opacity > 0.01;
1787
+ particle.sprite.position.set(x, y, z);
1788
+ particle.sprite.scale.setScalar(scale);
1789
+ particle.material.opacity = opacity;
1790
+ }
1791
+ if (!anyVisible && progress >= 1) {
1792
+ this.cleanupTeleportSparkles();
1793
+ }
1794
+ }
1795
+ cleanupTeleportDissolve() {
1796
+ for (const mat of this.teleportDissolvedMaterials) {
1797
+ if (mat.userData._dissolveApplied) {
1798
+ if (mat.userData._origOpacityNode !== undefined) {
1799
+ mat.opacityNode =
1800
+ mat.userData._origOpacityNode ?? null;
1801
+ }
1802
+ if (mat.userData._origEmissiveNode !== undefined) {
1803
+ mat.emissiveNode =
1804
+ mat.userData._origEmissiveNode ?? null;
1805
+ }
1806
+ mat.alphaTest = mat.userData._origAlphaTest ?? 0;
1807
+ mat.transparent = mat.userData._origTransparent ?? mat.transparent;
1808
+ mat.onBeforeCompile =
1809
+ mat.userData._origOnBeforeCompile ?? mat.onBeforeCompile;
1810
+ mat.customProgramCacheKey =
1811
+ mat.userData._origCustomProgramCacheKey ?? mat.customProgramCacheKey;
1812
+ delete mat.userData._dissolveApplied;
1813
+ delete mat.userData._origOpacityNode;
1814
+ delete mat.userData._origEmissiveNode;
1815
+ delete mat.userData._origAlphaTest;
1816
+ delete mat.userData._origTransparent;
1817
+ delete mat.userData._origOnBeforeCompile;
1818
+ delete mat.userData._origCustomProgramCacheKey;
1819
+ mat.needsUpdate = true;
1820
+ }
1821
+ }
1822
+ this.teleportDissolvedMaterials = [];
1823
+ this.teleportProgressUniform = null;
1824
+ this.teleportFallbackShaders = [];
1825
+ }
1826
+ cleanupTeleportSparkles() {
1827
+ if (!this.teleportSparkles)
1828
+ return;
1829
+ for (const particle of this.teleportSparkles.particles) {
1830
+ particle.sprite.parent?.remove(particle.sprite);
1831
+ particle.material.dispose();
1832
+ }
1833
+ this.teleportSparkles.group.parent?.remove(this.teleportSparkles.group);
1834
+ this.teleportSparkles = null;
1835
+ }
1836
+ get animationLoaderContext() {
1837
+ return {
1838
+ isAborted: () => this.loadingAborted,
1839
+ isCurrentVrm: (vrm) => this.vrm === vrm,
1840
+ };
1841
+ }
1842
+ loop() {
1843
+ if (this.paused)
1844
+ return;
1845
+ this.scheduleNextFrame();
1846
+ const renderer = this.renderer;
1847
+ const scene = this.scene;
1848
+ const camera = this.camera;
1849
+ if (!renderer || !scene || !camera)
1850
+ return;
1851
+ const rawDelta = this.clock.getDelta();
1852
+ const stableDelta = Math.min(rawDelta, 1 / 30);
1853
+ this.elapsedTime += rawDelta;
1854
+ this.mixer?.update(rawDelta);
1855
+ if (this.vrm) {
1856
+ if (this.teleportProgress < 1.0) {
1857
+ this.teleportProgress += stableDelta * 2.0; // ~0.5 seconds duration
1858
+ if (this.teleportProgress > 1.0)
1859
+ this.teleportProgress = 1.0;
1860
+ if (this.teleportProgressUniform) {
1861
+ this.teleportProgressUniform.value = this.teleportProgress;
1862
+ }
1863
+ for (const shader of this.teleportFallbackShaders) {
1864
+ shader.uniforms.uTeleportProgress.value = this.teleportProgress;
1865
+ }
1866
+ if (this.teleportProgress >= 1.0) {
1867
+ this.cleanupTeleportDissolve();
1868
+ this.cleanupTeleportSparkles();
1869
+ }
1870
+ }
1871
+ this.updateTeleportSparkles();
1872
+ this.applyMouthToVrm(this.vrm);
1873
+ const blinkValue = this.blinkController.update(rawDelta);
1874
+ this.vrm.expressionManager?.setValue("blink", blinkValue);
1875
+ }
1876
+ this.updateWorldReveal(stableDelta);
1877
+ // Process camera transition
1878
+ if (this.isCameraTransitioning) {
1879
+ this.transitionProgress += stableDelta / this.transitionDuration;
1880
+ let finished = false;
1881
+ if (this.transitionProgress >= 1.0) {
1882
+ this.transitionProgress = 1.0;
1883
+ this.isCameraTransitioning = false;
1884
+ finished = true;
1885
+ }
1886
+ // Smooth step easing
1887
+ const t = this.transitionProgress;
1888
+ const ease = t * t * (3.0 - 2.0 * t);
1889
+ camera.position.lerpVectors(this.transitionStartPos, this.transitionTargetPos, ease);
1890
+ this.baseCameraPosition.copy(camera.position);
1891
+ this.lookAtTarget.lerpVectors(this.transitionStartLookAt, this.transitionTargetLookAt, ease);
1892
+ camera.fov = THREE.MathUtils.lerp(this.transitionStartFov, this.transitionTargetFov, ease);
1893
+ camera.updateProjectionMatrix();
1894
+ if (this.controls) {
1895
+ this.controls.target.copy(this.lookAtTarget);
1896
+ if (finished) {
1897
+ this.controls.update(); // Sync once at the very end when bounds match
1898
+ }
1899
+ }
1900
+ }
1901
+ const manualCameraActive = this.interactionEnabled;
1902
+ if (!manualCameraActive &&
1903
+ this.cameraAnimation.enabled &&
1904
+ this.baseCameraPosition.length() > 0 &&
1905
+ !this.isCameraTransitioning) {
1906
+ this.cameraManager.applyCameraMotion(camera, this.baseCameraPosition, this.lookAtTarget, this.cameraAnimation, this.elapsedTime);
1907
+ }
1908
+ const dragOrbitFollow = Math.min(1, stableDelta * 9);
1909
+ this.dragOrbitCurrent.lerp(this.dragOrbitTarget, dragOrbitFollow);
1910
+ if (this.dragOrbitCurrent.lengthSq() > 1e-6 &&
1911
+ this.baseCameraPosition.lengthSq() > 1e-6) {
1912
+ const orbitOffset = this.tempCameraOrbitOffset
1913
+ .copy(camera.position)
1914
+ .sub(this.lookAtTarget);
1915
+ if (orbitOffset.lengthSq() > 1e-6) {
1916
+ const spherical = this.tempCameraSpherical.setFromVector3(orbitOffset);
1917
+ spherical.theta += this.dragOrbitCurrent.x;
1918
+ spherical.phi = THREE.MathUtils.clamp(spherical.phi + this.dragOrbitCurrent.y, 0.2, Math.PI - 0.2);
1919
+ orbitOffset.setFromSpherical(spherical);
1920
+ camera.position.copy(this.lookAtTarget).add(orbitOffset);
1921
+ }
1922
+ }
1923
+ this.applyCompanionZoom(camera, stableDelta);
1924
+ this.updateSparkPerformanceProfile();
1925
+ if (this.pointerParallaxEnabled) {
1926
+ const follow = Math.min(1, stableDelta * 7.5);
1927
+ this.pointerParallaxCurrent.lerp(this.pointerParallaxTarget, follow);
1928
+ this.pointerParallaxPosition.set(this.pointerParallaxCurrent.x * 0.18, this.pointerParallaxCurrent.y * 0.12, 0);
1929
+ camera.position.add(this.pointerParallaxPosition);
1930
+ this.pointerParallaxLookAt
1931
+ .copy(this.lookAtTarget)
1932
+ .add(new THREE.Vector3(this.pointerParallaxCurrent.x * 0.08, this.pointerParallaxCurrent.y * 0.05, 0));
1933
+ }
1934
+ else {
1935
+ this.pointerParallaxCurrent.lerp(this.pointerParallaxTarget, 0.12);
1936
+ this.pointerParallaxLookAt.copy(this.lookAtTarget);
1937
+ }
1938
+ if (this.controls) {
1939
+ if (manualCameraActive && !this.isCameraTransitioning) {
1940
+ this.controls.update();
1941
+ this.lookAtTarget.copy(this.controls.target);
1942
+ }
1943
+ else if (!this.isCameraTransitioning) {
1944
+ this.controls.target.copy(this.lookAtTarget);
1945
+ }
1946
+ }
1947
+ if (!manualCameraActive || this.isCameraTransitioning) {
1948
+ camera.lookAt(this.pointerParallaxLookAt);
1949
+ }
1950
+ if (this.vrm) {
1951
+ this.updateAvatarLookTarget(camera, stableDelta);
1952
+ this.vrm.update(stableDelta);
1953
+ this.applyAvatarHeadTracking(camera, stableDelta);
1954
+ this.refreshAvatarEyeTracking();
1955
+ }
1956
+ this.updateSparkDepthOfField(camera);
1957
+ renderer.render(scene, camera);
1958
+ this.onUpdate?.();
1959
+ }
1960
+ disposeWorld() {
1961
+ if (this.sparkRenderer) {
1962
+ this.sparkRenderer.apertureAngle = 0;
1963
+ }
1964
+ this.cancelWorldReveal();
1965
+ this.disposeSplatMesh(this.worldMesh);
1966
+ this.worldMesh = null;
1967
+ }
1968
+ async loadAndPlayIdle(vrm) {
1969
+ if (this.loadingAborted)
1970
+ return;
1971
+ const mixer = this.mixer ?? new THREE.AnimationMixer(vrm.scene);
1972
+ this.mixer = mixer;
1973
+ const action = await this.ensureIdleAction(vrm, mixer);
1974
+ if (!action)
1975
+ return;
1976
+ action.fadeIn(0.25);
1977
+ action.play();
1978
+ mixer.update(1 / 60);
1979
+ }
1980
+ async loadEmoteClipCached(path, vrm) {
1981
+ const cached = this.emoteClipCache.get(path);
1982
+ if (cached)
1983
+ return cached;
1984
+ const clip = await loadEmoteClip(path, vrm, this.animationLoaderContext);
1985
+ if (clip) {
1986
+ this.emoteClipCache.set(path, clip);
1987
+ }
1988
+ return clip;
1989
+ }
1990
+ applyMouthToVrm(vrm) {
1991
+ const manager = vrm.expressionManager;
1992
+ if (!manager)
1993
+ return;
1994
+ let target;
1995
+ if (this.speaking) {
1996
+ const elapsed = this.elapsedTime - this.speakingStartTime;
1997
+ const base = Math.sin(elapsed * 12) * 0.3 + 0.4;
1998
+ const detail = Math.sin(elapsed * 18.7) * 0.15;
1999
+ const slow = Math.sin(elapsed * 4.2) * 0.1;
2000
+ target = Math.max(0, Math.min(1, base + detail + slow));
2001
+ }
2002
+ else {
2003
+ target = this.mouthValue;
2004
+ }
2005
+ const next = Math.max(0, Math.min(1, target));
2006
+ const alpha = next > this.mouthSmoothed ? 0.3 : 0.2;
2007
+ this.mouthSmoothed = this.mouthSmoothed * (1 - alpha) + next * alpha;
2008
+ manager.setValue("aa", this.mouthSmoothed);
2009
+ }
2010
+ /**
2011
+ * Capture a single-frame snapshot of the current VRM as a PNG Blob.
2012
+ *
2013
+ * When `disablePhysics` is true (the default), spring bone simulation is
2014
+ * frozen for the capture frame so hair and cloth render in their rest pose,
2015
+ * then restored afterwards. The render loop is paused during capture to
2016
+ * prevent physics from re-running between reset and canvas capture.
2017
+ */
2018
+ async snapshot(options) {
2019
+ const renderer = this.renderer;
2020
+ const scene = this.scene;
2021
+ const camera = this.camera;
2022
+ if (!renderer || !scene || !camera)
2023
+ return null;
2024
+ const canvas = renderer.domElement;
2025
+ if (!canvas)
2026
+ return null;
2027
+ const disablePhysics = options?.disablePhysics ?? true;
2028
+ const width = options?.width ?? canvas.width;
2029
+ const height = options?.height ?? canvas.height;
2030
+ // Pause the render loop so physics doesn't re-run between reset and capture
2031
+ const wasPaused = this.paused;
2032
+ this.setPaused(true);
2033
+ // Cancel any pending animation frame to ensure the loop truly stops
2034
+ if (this.animationFrameId !== null) {
2035
+ cancelAnimationFrame(this.animationFrameId);
2036
+ this.animationFrameId = null;
2037
+ }
2038
+ // Reset spring bones to rest pose (hair/cloth at initial position)
2039
+ const springBoneManager = this.vrm?.springBoneManager ?? null;
2040
+ if (disablePhysics && springBoneManager) {
2041
+ springBoneManager.reset?.();
2042
+ }
2043
+ // Resize renderer for the capture resolution
2044
+ const prevWidth = canvas.width;
2045
+ const prevHeight = canvas.height;
2046
+ renderer.setPixelRatio(1);
2047
+ renderer.setSize(width, height);
2048
+ camera.aspect = width / height;
2049
+ camera.updateProjectionMatrix();
2050
+ // Update VRM transforms without physics
2051
+ if (this.vrm) {
2052
+ if (disablePhysics && springBoneManager) {
2053
+ // Update only the humanoid/expression without spring bones
2054
+ this.vrm.humanoid?.update?.();
2055
+ this.vrm.expressionManager?.update?.();
2056
+ }
2057
+ else {
2058
+ this.vrm.update(0);
2059
+ }
2060
+ }
2061
+ // Render the frame (synchronous — captures immediately to canvas)
2062
+ renderer.render(scene, camera);
2063
+ // Capture the canvas
2064
+ const blob = await new Promise((resolve) => {
2065
+ canvas.toBlob((b) => resolve(b), "image/png");
2066
+ });
2067
+ // Restore previous renderer state
2068
+ renderer.setPixelRatio(window.devicePixelRatio ?? 1);
2069
+ renderer.setSize(prevWidth, prevHeight);
2070
+ camera.aspect = prevWidth / prevHeight;
2071
+ camera.updateProjectionMatrix();
2072
+ // Restore paused state — resume the render loop
2073
+ this.setPaused(wasPaused);
2074
+ return blob;
2075
+ }
2076
+ }