@volter/editor-core 0.5.57

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 (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,420 @@
1
+ /**
2
+ * ONE React for the editor's own tree — the shell's.
3
+ *
4
+ * ## The defect this closes
5
+ *
6
+ * Under the PACKAGED runtime (`server/packaged.ts`: a `@vgai/editor` npm
7
+ * package with no monorepo checkout) the page runs two module graphs at once:
8
+ *
9
+ * - the editor shell, a PREBUILT production bundle (`dist/assets/index-*.js`)
10
+ * with its own React inlined; and
11
+ * - the opened PROJECT's source, served fresh by a second, project-rooted
12
+ * Vite instance, whose bare `react` resolves — correctly, for its root — to
13
+ * the PROJECT's own `node_modules`.
14
+ *
15
+ * Anything the project contributes that renders INSIDE the editor's React tree
16
+ * therefore called hooks from a different React than the one reconciling it.
17
+ * Measured on a fresh scaffold against the published 0.5.17 packaged editor:
18
+ * all four dev-tools inspector facets (`src/tools/game-*.inspector.tsx`)
19
+ * REGISTERED (`editor.inspect()` listed them) and then threw
20
+ * `Invalid hook call … more than one copy of React in the same app` instead of
21
+ * drawing — and so did every other project contribution that renders (the
22
+ * humanoid/bird/castle builder inspectors, the World Labs asset inspector, the
23
+ * data-tables document). None of it was visible from a checkout: `dev.ts`
24
+ * serves the editor's OWN source and the project's source through ONE Vite
25
+ * with `resolve.dedupe: ['react', …]`, so in-repo there has only ever been one
26
+ * React and every in-repo check passed.
27
+ *
28
+ * ## The mechanism: URL identity
29
+ *
30
+ * The editor build emits one extra ENTRY chunk per specifier in
31
+ * {@link SHARED_REACT_ENTRIES} — the SHELL's own React, `react-dom`,
32
+ * `react-dom/client`, `react/jsx-runtime`, `react/jsx-dev-runtime`, and the one
33
+ * third-party package that CALLS React hooks inside the editor's tree. Because
34
+ * they are entries of the SAME build, rollup hoists the actual module into a
35
+ * chunk both they and the shell import: they are not a copy of React, they are
36
+ * a doorway onto the shell's instance.
37
+ *
38
+ * At serve time {@link sharedReactPlugin} resolves those specifiers, for
39
+ * every module in the EDITOR TREE (see below), to the built chunk's URL
40
+ * (`/assets/vgai-shared-react-<hash>.js`) — the SAME absolute URL the shell's
41
+ * own bundle imports, so the browser's module map hands both sides the one
42
+ * instance.
43
+ *
44
+ * ### Why the entry bodies are GENERATED, not written
45
+ *
46
+ * The obvious spelling — a one-line `export * from 'react'` — silently emits a
47
+ * chunk with NO named exports (measured: the built chunk exported only the
48
+ * default and the raw namespace). React ships CommonJS, and rollup makes
49
+ * `import { useState } from 'react'` work by rewriting the IMPORTER's member
50
+ * access, not by synthesizing static named exports a star can forward. So each
51
+ * entry body is generated at build time from the installed package's own
52
+ * runtime key list (`Object.keys(require('react'))`), and every export is that
53
+ * package's own function read off its own module object. That is a DOORWAY,
54
+ * not a shim: there is no second implementation, nothing is faked, and the
55
+ * list cannot drift from the installed React because it is read from it. The
56
+ * chunks are emitted with `preserveSignature: 'strict'` because Vite's app
57
+ * build otherwise sets `preserveEntrySignatures: false` and mangles an entry's
58
+ * export names away.
59
+ *
60
+ * ## Where the seam is drawn (measured, not assumed)
61
+ *
62
+ * {@link sharedReactPlugin}'s own doc comment carries the full rule and the
63
+ * live failure that set it: the redirect covers the EDITOR TREE — the
64
+ * contribution lane, the widget kit, and whatever project source they reach —
65
+ * and deliberately stops at the GAME, which mounts into its own isolated
66
+ * `createRoot` tree with the project's own development React and a matching
67
+ * development reconciler. Redirecting the game too was tried first and broke
68
+ * Play mode outright.
69
+ *
70
+ * {@link sharedReactPlugin} is registered ONLY by `server/packaged.ts`.
71
+ * `dev.ts` is untouched — it has one React already.
72
+ */
73
+ import { existsSync, readFileSync } from 'node:fs';
74
+ import { createRequire } from 'node:module';
75
+ import path from 'node:path';
76
+ import { EDITOR_LANE_DIRS } from '@volter/editor-sdk/session/tool-contribution-convention';
77
+ import type { Plugin } from 'vite';
78
+
79
+ /**
80
+ * The published specifiers, and the rollup chunk NAME each appears under.
81
+ *
82
+ * The membership rule is one sentence: **a module belongs here when it CALLS
83
+ * React hooks while rendering inside the editor's tree.** React itself is the
84
+ * obvious case; a third-party component is the non-obvious one, and it fails
85
+ * exactly as loudly — its `useState`/`useId` read a different dispatcher than
86
+ * the tree reconciling it, which is "Invalid hook call" again with the
87
+ * project's name nowhere in the stack.
88
+ *
89
+ * `@fortawesome/react-fontawesome` is here because it is the ONLY such module
90
+ * `@volter/editor-sdk/widgets` reaches (measured: the kit's whole transitive bare-import
91
+ * closure is `react`, `react-dom`, `@fortawesome/free-solid-svg-icons` — pure
92
+ * path DATA, no React — and this). `SectionHeader` renders its
93
+ * `DisclosureIcon` unconditionally, so before this entry existed every project
94
+ * tool that used the kit's own section header crashed on the packaged path
95
+ * while the tool's own hooks were being redirected correctly.
96
+ *
97
+ * `react-dom/server` is deliberately absent: nothing renders to a string in an
98
+ * editor page, and an entry for it would drag React's server build into every
99
+ * shell bundle.
100
+ *
101
+ * KNOWN REMAINING HOLE, same class: any OTHER bare dependency a contribution
102
+ * renders calls its own prebundled React, and adding it here is not always the
103
+ * answer. `@pixi/react` is the worked case and the reason this paragraph
104
+ * exists — a doorway for it hands the editor's tree the SHELL's `@pixi/react`
105
+ * and therefore the shell's `pixi.js`, while the contribution's own
106
+ * `Texture`/`Assets` stay the project's: one renderer looking at another
107
+ * renderer's textures, the same renderer-instance split that broke Play mode
108
+ * when the game was redirected. The `sprite` capability's Sprite Lab took the
109
+ * other exit instead — it drives plain `pixi.js` imperatively
110
+ * (`sprite-lab/stage.ts`), because `pixi.js` calls no React hooks and so
111
+ * crosses nothing. Reach for that shape first; a new line in this map is for a
112
+ * dependency whose whole job IS rendering in the editor's tree.
113
+ */
114
+ export const SHARED_REACT_ENTRIES = {
115
+ react: 'vgai-shared-react',
116
+ 'react-dom': 'vgai-shared-react-dom',
117
+ 'react-dom/client': 'vgai-shared-react-dom-client',
118
+ 'react/jsx-runtime': 'vgai-shared-jsx-runtime',
119
+ 'react/jsx-dev-runtime': 'vgai-shared-jsx-dev-runtime',
120
+ '@fortawesome/react-fontawesome': 'vgai-shared-fontawesome',
121
+
122
+ } as const satisfies Record<string, string>;
123
+
124
+ export type SharedReactSpecifier = keyof typeof SHARED_REACT_ENTRIES;
125
+
126
+ /** The specifiers this plugin owns — the same list `packaged.ts` keeps out of
127
+ * dependency prebundling, exported so the two can never drift apart. */
128
+ export const SHARED_REACT_SPECIFIERS = Object.keys(SHARED_REACT_ENTRIES) as SharedReactSpecifier[];
129
+
130
+ /**
131
+ * The emitted map, written beside the built shell. NOT `.vite/manifest.json`:
132
+ * this file is read out of an INSTALLED tarball, and a dot-directory is one
133
+ * more thing that has to survive `npm pack`.
134
+ */
135
+ export const SHARED_REACT_MANIFEST_FILE = 'vgai-shared-react.json';
136
+
137
+ export interface SharedReactManifest {
138
+ /** Bare specifier → outDir-relative built chunk file (`assets/…js`). */
139
+ files: Record<string, string>;
140
+ }
141
+
142
+ const VIRTUAL_PREFIX = '\0vgai-shared-react:';
143
+
144
+ /**
145
+ * The body of one entry: every export the installed package actually has, read
146
+ * off that package's own module object.
147
+ *
148
+ * `__ns.default ?? __ns` covers both shapes this has to handle — a CommonJS
149
+ * package (rollup's interop puts `module.exports` on `default`) and a real ES
150
+ * module (the root Vite config aliases `react/jsx-dev-runtime` to
151
+ * `src/jsx-dev-runtime-prod-shim.ts` for builds, because production React
152
+ * stubs `jsxDEV` to `undefined`).
153
+ */
154
+ export function sharedReactEntryModule(specifier: string, exportNames: readonly string[]): string {
155
+ const named = exportNames
156
+ .filter((name) => VALID_IDENTIFIER.test(name))
157
+ .map((name) => `export const ${name} = __m.${name};`);
158
+ return [
159
+ `import * as __ns from ${JSON.stringify(specifier)};`,
160
+ // Bracketed on purpose: `__ns.default` makes rollup warn that the ES-module
161
+ // shape (the jsx-dev-runtime shim) has no `default` export, which is the
162
+ // case this line exists to handle.
163
+ "const __m = __ns['default'] ?? __ns;",
164
+ 'export default __m;',
165
+ ...named,
166
+ '',
167
+ ].join('\n');
168
+ }
169
+
170
+ const VALID_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
171
+
172
+ /** The runtime export names of an installed package, resolved from `fromDir`. */
173
+ export function installedExportNames(fromDir: string, specifier: string): string[] {
174
+ const require_ = createRequire(path.join(fromDir, 'package.json'));
175
+ // biome-ignore lint/suspicious/noExplicitAny: reading an arbitrary package's runtime shape.
176
+ const loaded = require_(specifier) as Record<string, any>;
177
+ return Object.keys(loaded).filter((name) => name !== 'default');
178
+ }
179
+
180
+ /**
181
+ * BUILD side: emit the five entry chunks and the manifest naming them.
182
+ *
183
+ * `fromDir` is the directory whose `node_modules` the React being published
184
+ * comes from — the repo root for this build, which is the same React the shell
185
+ * itself bundles.
186
+ */
187
+ export function sharedReactBuildPlugin(fromDir: string): Plugin {
188
+ const referenceIds = new Map<SharedReactSpecifier, string>();
189
+ return {
190
+ name: 'vgai-shared-react-build',
191
+ apply: 'build',
192
+ buildStart() {
193
+ referenceIds.clear();
194
+ for (const specifier of SHARED_REACT_SPECIFIERS) {
195
+ referenceIds.set(
196
+ specifier,
197
+ this.emitFile({
198
+ type: 'chunk',
199
+ id: `${VIRTUAL_PREFIX}${specifier}`,
200
+ name: SHARED_REACT_ENTRIES[specifier],
201
+ // Vite's app build sets `preserveEntrySignatures: false`, which
202
+ // mangles an entry's export names away. Per-chunk `strict` is what
203
+ // keeps `useState` spelled `useState` in the emitted file — the
204
+ // whole point of publishing it.
205
+ preserveSignature: 'strict',
206
+ }),
207
+ );
208
+ }
209
+ },
210
+ resolveId(id) {
211
+ return id.startsWith(VIRTUAL_PREFIX) ? id : undefined;
212
+ },
213
+ load(id) {
214
+ if (!id.startsWith(VIRTUAL_PREFIX)) return undefined;
215
+ const specifier = id.slice(VIRTUAL_PREFIX.length);
216
+ return sharedReactEntryModule(specifier, installedExportNames(fromDir, specifier));
217
+ },
218
+ generateBundle() {
219
+ const files: Record<string, string> = {};
220
+ for (const [specifier, referenceId] of referenceIds) {
221
+ files[specifier] = this.getFileName(referenceId);
222
+ }
223
+ this.emitFile({
224
+ type: 'asset',
225
+ fileName: SHARED_REACT_MANIFEST_FILE,
226
+ source: `${JSON.stringify({ files } satisfies SharedReactManifest, null, 2)}\n`,
227
+ });
228
+ },
229
+ };
230
+ }
231
+
232
+ /** The manifest a built `dist/` carries, or `null` when it predates this build
233
+ * step (an old tarball, or a checkout whose `dist/` was never rebuilt). */
234
+ export function readSharedReactManifest(distPath: string): SharedReactManifest | null {
235
+ const manifestPath = path.join(distPath, SHARED_REACT_MANIFEST_FILE);
236
+ if (!existsSync(manifestPath)) return null;
237
+ let manifest: SharedReactManifest;
238
+ try {
239
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as SharedReactManifest;
240
+ } catch {
241
+ return null;
242
+ }
243
+ if (SHARED_REACT_SPECIFIERS.some((specifier) => !manifest.files?.[specifier])) return null;
244
+ return manifest;
245
+ }
246
+
247
+ /**
248
+ * Specifier → URL, from a manifest. `base` is the built shell's own base (`/`
249
+ * for the packaged build), so these URLs are byte-identical to the ones the
250
+ * shell's bundle imports. That identity IS the fix: a differently-spelled URL
251
+ * for the same file is a second React.
252
+ */
253
+ export function sharedReactUrls(manifest: SharedReactManifest, base = '/'): Record<string, string> {
254
+ const prefix = base.endsWith('/') ? base : `${base}/`;
255
+ return Object.fromEntries(
256
+ SHARED_REACT_SPECIFIERS.map((specifier) => [
257
+ specifier,
258
+ `${prefix}${manifest.files[specifier]}`,
259
+ ]),
260
+ );
261
+ }
262
+
263
+ /**
264
+ * The query that marks a module as part of the EDITOR TREE — the same
265
+ * "the query IS the scope" device `vite-plugin-mount-isolation.ts` uses.
266
+ * Queries survive `cleanUrl`, so every other plugin's `.tsx` scope test still
267
+ * matches a marked module.
268
+ */
269
+ export const EDITOR_TREE_QUERY = 'vgai-editor-react';
270
+
271
+ /** A file inside a `@vgai/*` package's `contributions/` directory under any
272
+ * `node_modules` (a real install; in a checkout the package is a symlink
273
+ * whose realpath is its workspace directory, already `isOwnSource`). */
274
+ const PACKAGE_CONTRIBUTION_PATH = /[\\/]node_modules[\\/]@vgai[\\/][^\\/]+[\\/]contributions[\\/]/;
275
+
276
+ function markEditorTree(id: string): string {
277
+ return id.includes(`?${EDITOR_TREE_QUERY}`) || id.includes(`&${EDITOR_TREE_QUERY}`)
278
+ ? id
279
+ : `${id}${id.includes('?') ? '&' : '?'}${EDITOR_TREE_QUERY}`;
280
+ }
281
+
282
+ function stripQuery(id: string): string {
283
+ const cut = id.indexOf('?');
284
+ return cut === -1 ? id : id.slice(0, cut);
285
+ }
286
+
287
+ function isUnder(file: string, directory: string): boolean {
288
+ return file === directory || file.startsWith(`${directory}${path.sep}`);
289
+ }
290
+
291
+ export interface SharedReactScope {
292
+ /** Specifier → built chunk URL (see {@link sharedReactUrls}). */
293
+ urls: Record<string, string>;
294
+ /** The installed `@vgai/editor` package root — its `src/` is `@editor/*`. */
295
+ editorPackageRoot: string;
296
+ /** Every open project root, live (the same getter the sibling plugins take). */
297
+ projectRoots: () => Set<string>;
298
+ }
299
+
300
+ /**
301
+ * SERVE side: point the EDITOR TREE's React specifiers at the shell's built
302
+ * chunk URLs.
303
+ *
304
+ * ## Scope, and why it is not the whole graph
305
+ *
306
+ * The first version of this redirected React for every module this Vite
307
+ * instance served. It fixed the contributions and BROKE Play mode, loudly and
308
+ * measurably: `@react-three/fiber`'s prebundled `react-reconciler` is a
309
+ * DEVELOPMENT build (Vite prebundles a dev server's deps with
310
+ * `NODE_ENV=development`), and a dev reconciler against the shell's PRODUCTION
311
+ * React reads internals that production React does not have — `TypeError:
312
+ * Cannot read properties of undefined (reading 'push')` inside
313
+ * `updateContainer`, "The current testing environment is not configured to
314
+ * support act(...)", and finally `r3f-adapter: onCreated did not fire within
315
+ * 10s`. The DEV/PROD boundary is real: the shell ships a production React and
316
+ * the project's own graph is a development graph.
317
+ *
318
+ * So the seam is drawn where the RENDERING is: a module that renders inside
319
+ * the editor's own React tree uses the editor's React; the game — mounted by
320
+ * `createRoot` into its own isolated tree, with its own dev React and its own
321
+ * dev reconciler, internally consistent — keeps the project's. That is the
322
+ * same line `vite-plugin-module-doorways.ts` already draws for the mount
323
+ * call, and it is why Play mode works today.
324
+ *
325
+ * ## How the scope is decided
326
+ *
327
+ * An importer is in the editor tree when it is:
328
+ * - a project's `src/contributions/**` or `src/tools/**` module (the editor
329
+ * lanes shared with the contribution loader),
330
+ * - a file under the installed editor package's own `src/` (what `@editor/*`
331
+ * aliases to — the widget kit contributions build their panels from), or
332
+ * - anything already MARKED, which is how the scope propagates.
333
+ *
334
+ * Propagation is what makes this cover the real graph rather than one folder:
335
+ * `src/tools/data-tables.document.tsx` renders React components that live in
336
+ * `src/lib/data-tables/`, and a contribution may reach any project module. So
337
+ * when an editor-tree module imports another PROJECT-OWNED source file, the
338
+ * resolved id is marked and its own imports inherit the scope. Bare
339
+ * dependencies are deliberately NOT marked: they are prebundled, and a
340
+ * prebundled chunk's React is decided at prebundle time, not here.
341
+ * `@volter/editor-sdk/widgets` is the one dependency that must therefore be kept
342
+ * OUT of `optimizeDeps` (`packaged.ts` excludes it) — it renders in the editor's tree
343
+ * and has to be source-served for this scope to reach it.
344
+ *
345
+ * `enforce: 'pre'` so this runs ahead of Vite's own resolver and its alias
346
+ * plugin. The returned React id is a root-relative URL, not a filesystem path:
347
+ * Vite's import analysis leaves an id it cannot map into the project root as
348
+ * the literal import URL, and the packaged server's `express.static(dist)`
349
+ * answers it — so the browser fetches the same `/assets/…` file the shell
350
+ * already loaded.
351
+ */
352
+ export function sharedReactPlugin({
353
+ urls,
354
+ editorPackageRoot,
355
+ projectRoots,
356
+ }: SharedReactScope): Plugin {
357
+ const editorSrc = path.join(editorPackageRoot, 'src');
358
+ const layoutSdkSrc = path.resolve(editorPackageRoot, '../editor-sdk/src');
359
+ const inEditorTree = (importer: string | undefined): boolean => {
360
+ if (!importer) return false;
361
+ if (importer.includes(EDITOR_TREE_QUERY)) return true;
362
+ const file = stripQuery(importer);
363
+ if (isUnder(file, editorSrc) || isUnder(file, layoutSdkSrc)) return true;
364
+ // A skew PACKAGE's contribution (`node_modules/@vgai/<pkg>/contributions/`)
365
+ // renders in the editor's tree exactly as a project's own contribution
366
+ // does, so it takes the shell's React and SDK. Only the contributions
367
+ // directory: the same package's `src/` is also game runtime (a mesh
368
+ // component in a world), and a game keeps its own React.
369
+ if (PACKAGE_CONTRIBUTION_PATH.test(file)) return true;
370
+ for (const root of projectRoots()) {
371
+ if (file === path.join(root, 'vgai.adapter.ts')) return true;
372
+ if (EDITOR_LANE_DIRS.some((dir) => isUnder(file, path.join(root, dir)))) return true;
373
+ }
374
+ return false;
375
+ };
376
+ /** Project-owned source the scope propagates into — never a bare dep. */
377
+ const isOwnSource = (file: string): boolean => {
378
+ if (!path.isAbsolute(file)) return false;
379
+ if (isUnder(file, editorSrc) || isUnder(file, layoutSdkSrc)) return true;
380
+ if (file.includes(`${path.sep}node_modules${path.sep}`)) return false;
381
+ for (const root of projectRoots()) {
382
+ if (isUnder(file, root)) return true;
383
+ }
384
+ return false;
385
+ };
386
+
387
+ return {
388
+ name: 'vgai-shared-react',
389
+ enforce: 'pre',
390
+ async resolveId(source, importer, options) {
391
+ // Never during dependency SCANNING. The scanner records whatever an id
392
+ // resolves to as a file to prebundle, so handing it the shell's URL made
393
+ // the boot-time optimizer die on `ENOENT: open
394
+ // '/assets/vgai-shared-jsx-runtime-*.js'` — measured, on the first run
395
+ // after this scope existed. The redirect belongs to serving, where the
396
+ // browser is the thing fetching the URL.
397
+ // `scan` is Vite's own flag on the resolve options, not part of rollup's
398
+ // published type — hence the cast rather than a widened signature.
399
+ //
400
+ // The scan is not the only server-side pass that follows this redirect:
401
+ // import analysis PRE-TRANSFORMS every static import it rewrites, and a
402
+ // warmup for `/assets/vgai-shared-*.js` resolves against the project root
403
+ // and fails the same way (measured: 64 formatted `Pre-transform error`
404
+ // lines from one `*.inspector.tsx` request). Vite has no per-request
405
+ // opt-out there, so `packaged.ts` turns `server.preTransformRequests` off
406
+ // for its instance — see the comment on that option for why satisfying
407
+ // the warmup instead would pull the whole prebuilt SPA into the project's
408
+ // dev module graph.
409
+ if ((options as { scan?: boolean } | undefined)?.scan) return undefined;
410
+ if (!inEditorTree(importer)) return undefined;
411
+ const url = urls[source];
412
+ if (url) return url;
413
+ const resolved = await this.resolve(source, importer, { ...options, skipSelf: true });
414
+ if (!resolved || resolved.external) return resolved ?? undefined;
415
+ return isOwnSource(stripQuery(resolved.id))
416
+ ? { ...resolved, id: markEditorTree(resolved.id) }
417
+ : resolved;
418
+ },
419
+ };
420
+ }
@@ -0,0 +1,203 @@
1
+ /**
2
+ * ONE three.js for the whole page — the editor shell's.
3
+ *
4
+ * ## The defect this closes (WORK.md P2, "Packaged shell loads three.js twice")
5
+ *
6
+ * Under the PACKAGED runtime (`server/packaged.ts`: a `@vgai/editor` npm
7
+ * package with no monorepo checkout) the page runs two module graphs at once:
8
+ *
9
+ * - the editor shell, a PREBUILT production bundle (`dist/assets/index-*.js`)
10
+ * with its own `three` inlined — the viewport renderer, the gizmos, the
11
+ * selection outline and ~100 other shell modules import it, so it evaluates
12
+ * at boot; and
13
+ * - the opened PROJECT's source, served fresh by a second, project-rooted
14
+ * Vite instance, whose bare `three` resolves — correctly, for its root — to
15
+ * the PROJECT's own `node_modules` (prebundled into `.vite/deps/three.js`).
16
+ *
17
+ * three's own module body runs `if (window.__THREE__) console.warn('WARNING:
18
+ * Multiple instances of Three.js being imported.')` on evaluation, so the
19
+ * SECOND graph's copy trips the guard. That warning is not cosmetic: it keeps
20
+ * `vgai console` from reaching exit-0, a hard gate. `dev.ts` never sees it —
21
+ * one Vite instance, and the repo-root `vite.config.ts`'s
22
+ * `resolve.dedupe: ['three', …]` already collapses the project's copy onto the
23
+ * editor's — so nothing in a checkout ever reproduced it.
24
+ *
25
+ * ## The mechanism: URL identity (the sibling of `vite-plugin-shared-react.ts`)
26
+ *
27
+ * The editor build emits one extra ENTRY chunk for `three`
28
+ * ({@link sharedThreeBuildPlugin}) — the SHELL's own three. Because it is an
29
+ * entry of the SAME build, rollup hoists the actual module into a chunk both it
30
+ * and the shell import: it is not a copy of three, it is a doorway onto the
31
+ * shell's instance. At serve time {@link sharedThreePlugin} resolves the bare
32
+ * `three` specifier, for the whole PROJECT graph, to that built chunk's URL
33
+ * (`/assets/vgai-shared-three-<hash>.js`) — the SAME absolute URL the shell's
34
+ * own bundle imports, so the browser's module map hands both sides the one
35
+ * instance and three's body evaluates exactly once.
36
+ *
37
+ * ## Why the scope is the WHOLE project graph — unlike shared-React
38
+ *
39
+ * `sharedReactPlugin` deliberately redirects react only for the EDITOR TREE and
40
+ * leaves the GAME on the project's own (development) react, because React ships
41
+ * distinct dev/prod builds and its prebundled DEVELOPMENT reconciler must not
42
+ * run against the shell's PRODUCTION React (that broke Play mode, measured in
43
+ * that plugin's header). three has NO such split — it is one build — and
44
+ * `dev.ts`'s `resolve.dedupe` already proves the correct answer is ONE three
45
+ * for editor AND game together (the R3F entry runtime already hands Fiber's
46
+ * catalogue `host.three`, so a world's objects, Fiber's intrinsics and the
47
+ * editor viewport that adopts them must all be the SAME three or `applyProps`
48
+ * mis-types — see `r3f-entry-runtime.ts`). So this redirect is unscoped: every
49
+ * project-graph `three` import becomes the shell's one instance.
50
+ *
51
+ * ## Ingest keeps its own three — for free, by construction
52
+ *
53
+ * An INGEST root's premise is a vendored game that brought its own three. Two
54
+ * shapes, both preserved without a special case here:
55
+ *
56
+ * - a SOURCE game (its modules served by this same project-rooted Vite) has
57
+ * its bare `three` DEDUPED to the editor's instance already under `dev.ts`
58
+ * (see `ingest/resolve-three.ts`'s header, and the `cov-bundled-dedupe`
59
+ * e2e). This redirect is the packaged analogue of that dedupe — the source
60
+ * game lands on the shell's three exactly as it lands on the editor's in a
61
+ * checkout, and the three-ingest doorway's `projectThree` (which goes
62
+ * through this same resolver) lands there too, so the capture trap and the
63
+ * game agree;
64
+ * - a PRE-BUILT BUNDLE game inlines its own three into a blob/`public/` URL
65
+ * that never passes through a bare-specifier resolve, so this plugin cannot
66
+ * and does not touch it — it keeps its own copy, the case the doorway
67
+ * header calls out as inherently un-shareable.
68
+ *
69
+ * For the redirect to reach `@react-three/fiber`'s OWN `import 'three'`,
70
+ * `packaged.ts` also `optimizeDeps.exclude`s `three`: an excluded dep is
71
+ * externalized out of every prebundled chunk and resolved at serve time, where
72
+ * this plugin answers. Prebundling it instead would bake a second, un-
73
+ * redirectable three chunk into `.vite/deps` — exactly the duplicate this
74
+ * plugin removes.
75
+ *
76
+ * {@link sharedThreePlugin} is registered ONLY by `server/packaged.ts`.
77
+ * `dev.ts` is untouched — it has one three already.
78
+ */
79
+ import { existsSync, readFileSync } from 'node:fs';
80
+ import path from 'node:path';
81
+ import type { Plugin } from 'vite';
82
+ import { installedExportNames, sharedReactEntryModule } from './vite-plugin-shared-react.js';
83
+
84
+ /** The bare specifier this plugin owns. three's `window.__THREE__` guard lives
85
+ * in its main entry (`three/build/three.core.js`, re-exported by `three`), so
86
+ * collapsing the main entry collapses the duplicate-instance warning; addons
87
+ * (`three/addons/*`, `three/examples/jsm/*`) import bare `three` internally and
88
+ * ride this same redirect. */
89
+ export const SHARED_THREE_SPECIFIER = 'three';
90
+
91
+ /** The rollup chunk NAME the shell's three is emitted under. */
92
+ export const SHARED_THREE_ENTRY_NAME = 'vgai-shared-three';
93
+
94
+ /**
95
+ * The emitted map, written beside the built shell — the sibling of
96
+ * `vgai-shared-react.json`, kept a SEPARATE file so an editor build that
97
+ * predates one manifest but not the other degrades one lane at a time.
98
+ */
99
+ export const SHARED_THREE_MANIFEST_FILE = 'vgai-shared-three.json';
100
+
101
+ export interface SharedThreeManifest {
102
+ /** outDir-relative built chunk file (`assets/…js`) for `three`. */
103
+ file: string;
104
+ }
105
+
106
+ const VIRTUAL_PREFIX = '\0vgai-shared-three:';
107
+
108
+ /**
109
+ * BUILD side: emit the `three` entry chunk and the manifest naming it.
110
+ *
111
+ * `fromDir` is the directory whose `node_modules` the three being published
112
+ * comes from — the repo root for this build, which is the same three the shell
113
+ * itself bundles. The entry body is generated from the installed package's own
114
+ * runtime key list ({@link sharedReactEntryModule} / {@link installedExportNames}
115
+ * — generic over the specifier despite the React-shaped names), so it cannot
116
+ * drift from the installed three and needs no hand-maintained export list.
117
+ */
118
+ export function sharedThreeBuildPlugin(fromDir: string): Plugin {
119
+ let referenceId: string | null = null;
120
+ return {
121
+ name: 'vgai-shared-three-build',
122
+ apply: 'build',
123
+ buildStart() {
124
+ referenceId = this.emitFile({
125
+ type: 'chunk',
126
+ id: `${VIRTUAL_PREFIX}${SHARED_THREE_SPECIFIER}`,
127
+ name: SHARED_THREE_ENTRY_NAME,
128
+ // Same reason as the shared-React entries: Vite's app build sets
129
+ // `preserveEntrySignatures: false`, which would mangle the entry's
130
+ // export names away — `strict` keeps `Mesh` spelled `Mesh`.
131
+ preserveSignature: 'strict',
132
+ });
133
+ },
134
+ resolveId(id) {
135
+ return id.startsWith(VIRTUAL_PREFIX) ? id : undefined;
136
+ },
137
+ load(id) {
138
+ if (!id.startsWith(VIRTUAL_PREFIX)) return undefined;
139
+ const specifier = id.slice(VIRTUAL_PREFIX.length);
140
+ return sharedReactEntryModule(specifier, installedExportNames(fromDir, specifier));
141
+ },
142
+ generateBundle() {
143
+ if (!referenceId) return;
144
+ this.emitFile({
145
+ type: 'asset',
146
+ fileName: SHARED_THREE_MANIFEST_FILE,
147
+ source: `${JSON.stringify(
148
+ { file: this.getFileName(referenceId) } satisfies SharedThreeManifest,
149
+ null,
150
+ 2,
151
+ )}\n`,
152
+ });
153
+ },
154
+ };
155
+ }
156
+
157
+ /** The manifest a built `dist/` carries, or `null` when it predates this build
158
+ * step (an old tarball, or a checkout whose `dist/` was never rebuilt). */
159
+ export function readSharedThreeManifest(distPath: string): SharedThreeManifest | null {
160
+ const manifestPath = path.join(distPath, SHARED_THREE_MANIFEST_FILE);
161
+ if (!existsSync(manifestPath)) return null;
162
+ try {
163
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as SharedThreeManifest;
164
+ return manifest.file ? manifest : null;
165
+ } catch {
166
+ return null;
167
+ }
168
+ }
169
+
170
+ /**
171
+ * The `three` chunk URL, from a manifest. `base` is the built shell's own base
172
+ * (`/` for the packaged build), so this URL is byte-identical to the one the
173
+ * shell's bundle imports. That identity IS the fix: a differently-spelled URL
174
+ * for the same file is a second three.
175
+ */
176
+ export function sharedThreeUrl(manifest: SharedThreeManifest, base = '/'): string {
177
+ const prefix = base.endsWith('/') ? base : `${base}/`;
178
+ return `${prefix}${manifest.file}`;
179
+ }
180
+
181
+ /**
182
+ * SERVE side: point every project-graph `three` import at the shell's built
183
+ * chunk URL. Registered ONLY on the packaged runtime's project-rooted Vite.
184
+ */
185
+ export function sharedThreePlugin(url: string): Plugin {
186
+ return {
187
+ name: 'vgai-shared-three',
188
+ enforce: 'pre',
189
+ resolveId(source, _importer, options) {
190
+ if (source !== SHARED_THREE_SPECIFIER) return undefined;
191
+ // Never during dependency SCANNING — the scanner records whatever an id
192
+ // resolves to as a file to prebundle, and handing it a `/assets/*` URL
193
+ // makes the boot optimizer die on ENOENT (the exact failure
194
+ // `sharedReactPlugin` documents). Returning undefined lets the scanner
195
+ // resolve `three` normally; because `packaged.ts` `exclude`s it from
196
+ // optimizeDeps, the scanner externalizes it rather than prebundling a
197
+ // second copy. `scan` is Vite's own flag on the resolve options, not part
198
+ // of rollup's published type — hence the cast.
199
+ if ((options as { scan?: boolean } | undefined)?.scan) return undefined;
200
+ return url;
201
+ },
202
+ };
203
+ }