@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.
- package/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The headless Blender build, served to the editor tab — and the door that
|
|
3
|
+
* says WHICH BUILD it is.
|
|
4
|
+
*
|
|
5
|
+
* THE BLENDER IN THE TAB IS BLENDER (ARCHITECTURE-CORE, owner ruling
|
|
6
|
+
* 2026-09-17), and since the 2026-09-18 amendment there are two builds of it:
|
|
7
|
+
*
|
|
8
|
+
* emscripten — the STANDALONE skew, and the one `@volter/blender-engine` SHIPS under
|
|
9
|
+
* `wasm/`: the glue as text plus the two large files pre-compressed
|
|
10
|
+
* (`blender_browser.wasm.br`, `blender_browser.data.br`, ~38 MB together
|
|
11
|
+
* against ~156 MB raw). They are served as-is with `Content-Encoding: br`;
|
|
12
|
+
* the browser decompresses before the runtime sees a byte, so the glue's
|
|
13
|
+
* own `instantiateStreaming` and `.data` preload run unchanged.
|
|
14
|
+
*
|
|
15
|
+
* wali — the SUBSTRATE skew: one `blender.wasm` linked for
|
|
16
|
+
* `wasm32-wali-linux-musl` beside the `runtime/` tree it reads through
|
|
17
|
+
* `BLENDER_SYSTEM_*` (browser-substrate `programs/blender/5.2.0`, whose
|
|
18
|
+
* `gate.sh` stages exactly that pair).
|
|
19
|
+
*
|
|
20
|
+
* THE SKEW IS NOT CONFIGURED, IT IS READ. One editor serves one Blender, and
|
|
21
|
+
* the served directory holds either `blender_browser.js` or `blender.wasm`;
|
|
22
|
+
* that IS the answer, and `status` carries it. There is no manifest field, no
|
|
23
|
+
* setting and no flag, because nothing a user does may depend on the skew —
|
|
24
|
+
* the ruling's "a skew may refuse a capability by name, never answer the same
|
|
25
|
+
* question differently" leaves nothing for a chooser to choose.
|
|
26
|
+
* `VGAI_BLENDER_WASM_DIR` is the existing door for pointing the editor at a
|
|
27
|
+
* different build, and pointing it at a WALI pack is how the substrate skew is
|
|
28
|
+
* reached in development.
|
|
29
|
+
*
|
|
30
|
+
* ONE PATCH IS APPLIED TO THE EMSCRIPTEN GLUE, and it is applied HERE rather
|
|
31
|
+
* than in the worker so that the pthread workers — which the runtime spawns by
|
|
32
|
+
* loading this same URL as a classic worker (`Module.mainScriptUrlOrBlob`) —
|
|
33
|
+
* get the identical text. The build is `-sPROXY_TO_PTHREAD`, and its
|
|
34
|
+
* `pthread_create` glue transfers a `#canvas` to the spawned thread by default.
|
|
35
|
+
* There is no canvas in a worker, and the transfer aborts the spawn, so the
|
|
36
|
+
* transfer list is emptied. The upstream release already does exactly this for
|
|
37
|
+
* node (`if(ENVIRONMENT_IS_NODE){transferredCanvasNames=0}`); a worker needs
|
|
38
|
+
* the same, and for the same reason.
|
|
39
|
+
*
|
|
40
|
+
* THE SAME PATCHING IS WHAT CARRIES THE SUBSTRATE, and it is the precedent
|
|
41
|
+
* being transcribed rather than a new mechanism: `@volter/browser-wali` and
|
|
42
|
+
* `@volter/browser-runtime` are served out of this door too
|
|
43
|
+
* (`/__editor/blender-wasm/wali/<package>/<file>.js`), with their bare
|
|
44
|
+
* `@volter/...` specifiers rewritten to those URLs on the way out. That is
|
|
45
|
+
* what keeps `@volter/blender-engine` free of any dependency on browser-substrate: the
|
|
46
|
+
* standalone skew installs nothing, bundles nothing and fetches nothing, and
|
|
47
|
+
* the WALI engine imports the substrate from URLs instead of specifiers. The
|
|
48
|
+
* nested workers `BrowserWaliWorkerProgram` spawns load from these same URLs,
|
|
49
|
+
* so they get the identical rewritten text — exactly the reason the glue patch
|
|
50
|
+
* lives here.
|
|
51
|
+
*
|
|
52
|
+
* A missing directory is a LOUD 404 naming the variable, never a silent
|
|
53
|
+
* fall-through: the engine either is Blender or says why it is not.
|
|
54
|
+
*/
|
|
55
|
+
import { createHash } from 'node:crypto';
|
|
56
|
+
import { createReadStream, existsSync } from 'node:fs';
|
|
57
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
58
|
+
import { dirname, isAbsolute, join, posix, relative } from 'node:path';
|
|
59
|
+
import { fileURLToPath } from 'node:url';
|
|
60
|
+
import { brotliDecompressSync } from 'node:zlib';
|
|
61
|
+
|
|
62
|
+
export type BlenderSkew = 'emscripten' | 'wali';
|
|
63
|
+
|
|
64
|
+
/** The three files the Emscripten runtime asks for, by the names the glue uses. */
|
|
65
|
+
export const BLENDER_WASM_FILES = [
|
|
66
|
+
'blender_browser.js',
|
|
67
|
+
'blender_browser.wasm',
|
|
68
|
+
'blender_browser.data',
|
|
69
|
+
] as const;
|
|
70
|
+
|
|
71
|
+
export type BlenderWasmFile = (typeof BLENDER_WASM_FILES)[number];
|
|
72
|
+
|
|
73
|
+
/** What the WALI skew's directory must hold: the artifact, and the runtime
|
|
74
|
+
* tree Blender reads through `BLENDER_SYSTEM_*`. */
|
|
75
|
+
export const BLENDER_WALI_ARTIFACT = 'blender.wasm';
|
|
76
|
+
export const BLENDER_WALI_RUNTIME = 'runtime';
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* THE THREAD BUDGET, stated once, here, because it is a property of this RUN
|
|
80
|
+
* SURFACE and not of the program.
|
|
81
|
+
*
|
|
82
|
+
* Blender is SERIAL unless it is told `-t N` and says so on stderr
|
|
83
|
+
* (browser-substrate `programs/blender/5.2.0/README.md` §(a): `-t N` sets
|
|
84
|
+
* oneTBB's global control and blenlib's explicitly sized arena). The POOL is a
|
|
85
|
+
* different number and must be comfortably above it: measured 2026-09-18 in
|
|
86
|
+
* the pack's own emulator, `blender -t 4` TRAPS with a host pool of 4, because
|
|
87
|
+
* the stated count buys four oneTBB workers and Blender starts threads of its
|
|
88
|
+
* own besides. 4 in a pool of 16 is the pair this lane measured end to end
|
|
89
|
+
* (`blender-n-gate`, 2026-09-19: boot 12.0 s, first request 0.9 s, later calls
|
|
90
|
+
* ~1.5 s), and a pool of 8 under `-t 4` trapped during boot on this box.
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* FOUR, MEASURED, NOT THE MACHINE'S CORES. The Emscripten skew runs Blender at 6
|
|
94
|
+
* on this 12-core box; measured 2026-09-20 on the same operations, WALI at 12
|
|
95
|
+
* threads was SLOWER than at 4 everywhere (subsurf level 6: 40 ms against 17;
|
|
96
|
+
* an ico sphere: 30 against 15; the courtyard 31.1 s against 28.6) -- the
|
|
97
|
+
* pool's scheduling costs more than the cores return, so more `-t` is not more
|
|
98
|
+
* speed here. The pool stays four times the count, the ratio that measured
|
|
99
|
+
* clean (16 under 4; 8 under 4 trapped at boot), because Blender starts threads
|
|
100
|
+
* of its own beyond the oneTBB workers `-t` buys.
|
|
101
|
+
*/
|
|
102
|
+
export const BLENDER_WALI_WORKERS = { pool: 16, blender: 4 } as const;
|
|
103
|
+
|
|
104
|
+
/** The substrate packages the WALI engine imports, by the URL segment each is
|
|
105
|
+
* served under and the specifier prefix rewritten to it. */
|
|
106
|
+
export const BLENDER_WALI_SUBSTRATE = [
|
|
107
|
+
{ segment: 'browser-wali', specifier: '@volter/browser-wali' },
|
|
108
|
+
{ segment: 'browser-runtime', specifier: '@volter/browser-runtime' },
|
|
109
|
+
] as const;
|
|
110
|
+
|
|
111
|
+
export const BLENDER_WASM_DIR_VARIABLE = 'VGAI_BLENDER_WASM_DIR';
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The bundle `@volter/blender-engine` ships — Blender itself, so its own GPL
|
|
115
|
+
* package (ARCHITECTURE-CORE §Licensing, "Blender's licence stops at the
|
|
116
|
+
* wire"). This resolution is a PATH, not an import: the editor serves those
|
|
117
|
+
* bytes and never imports the engine. `import.meta.url` is THIS FILE in a
|
|
118
|
+
* checkout (`packages/editor/server/`) and the esbuild bundle
|
|
119
|
+
* (`<pkg>/dist-server/packaged.mjs`) in a registry install; from either, two
|
|
120
|
+
* directories up and across is the sibling package -- `packages/blender-engine/wasm`
|
|
121
|
+
* in a checkout, `node_modules/@volter/blender-engine/wasm` installed. Existence is
|
|
122
|
+
* checked once so a realm that lacks it gets a named absence, not a path.
|
|
123
|
+
*/
|
|
124
|
+
export const SHIPPED_BLENDER_WASM_DIR: string | null = (() => {
|
|
125
|
+
const candidate = fileURLToPath(new URL('../../blender-engine/wasm/', import.meta.url));
|
|
126
|
+
return existsSync(candidate) ? candidate.replace(/\/$/, '') : null;
|
|
127
|
+
})();
|
|
128
|
+
|
|
129
|
+
/** Where the build is: the named directory, else the shipped one, else null. */
|
|
130
|
+
export function blenderWasmDir(env: NodeJS.ProcessEnv = process.env): string | null {
|
|
131
|
+
const named = env[BLENDER_WASM_DIR_VARIABLE];
|
|
132
|
+
if (typeof named === 'string' && named.trim() !== '') {
|
|
133
|
+
const dir = named.trim();
|
|
134
|
+
return isAbsolute(dir) ? dir : null;
|
|
135
|
+
}
|
|
136
|
+
return SHIPPED_BLENDER_WASM_DIR;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** A file on disk as the build stores it: raw, or pre-compressed as `.br`. */
|
|
140
|
+
export interface BlenderWasmOnDisk {
|
|
141
|
+
path: string;
|
|
142
|
+
size: number;
|
|
143
|
+
encoding: 'br' | null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function blenderWasmOnDisk(
|
|
147
|
+
dir: string,
|
|
148
|
+
file: string,
|
|
149
|
+
): Promise<BlenderWasmOnDisk | null> {
|
|
150
|
+
for (const [suffix, encoding] of [
|
|
151
|
+
['.br', 'br'],
|
|
152
|
+
['', null],
|
|
153
|
+
] as const) {
|
|
154
|
+
const path = join(dir, `${file}${suffix}`);
|
|
155
|
+
try {
|
|
156
|
+
const info = await stat(path);
|
|
157
|
+
if (info.isFile()) return { path, size: info.size, encoding };
|
|
158
|
+
} catch {
|
|
159
|
+
/* try the other spelling */
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface BlenderWasmStatus {
|
|
166
|
+
available: boolean;
|
|
167
|
+
/** Which build the served directory holds; null when nothing is served. */
|
|
168
|
+
skew: BlenderSkew | null;
|
|
169
|
+
/** The directory that was looked in, or null when the variable is unset. */
|
|
170
|
+
dir: string | null;
|
|
171
|
+
/** On-disk byte sizes of the files, for the ones that are there
|
|
172
|
+
* (the `.br` size when a file is stored pre-compressed). */
|
|
173
|
+
sizes: Record<string, number>;
|
|
174
|
+
/** Which files are stored pre-compressed, by name. */
|
|
175
|
+
encoded: Record<string, 'br'>;
|
|
176
|
+
/** Why it is unavailable, named. Empty when it is available. */
|
|
177
|
+
missing: string[];
|
|
178
|
+
/** WALI only: the `sha256-` SRI of `blender.wasm`. The program loader
|
|
179
|
+
* refuses any non-blob URL without one, so the session names the exact
|
|
180
|
+
* bytes it ran. */
|
|
181
|
+
integrity?: string;
|
|
182
|
+
/** WALI only: {@link BLENDER_WALI_WORKERS}. */
|
|
183
|
+
workers?: { pool: number; blender: number };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Which skew a directory holds, by what is in it. Null when it holds neither,
|
|
187
|
+
* which is what `missing` then has to explain. */
|
|
188
|
+
async function skewOf(dir: string): Promise<BlenderSkew | null> {
|
|
189
|
+
if (await blenderWasmOnDisk(dir, 'blender_browser.js')) return 'emscripten';
|
|
190
|
+
if (existsSync(join(dir, BLENDER_WALI_ARTIFACT))) return 'wali';
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export async function blenderWasmStatus(
|
|
195
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
196
|
+
): Promise<BlenderWasmStatus> {
|
|
197
|
+
const dir = blenderWasmDir(env);
|
|
198
|
+
if (dir === null)
|
|
199
|
+
return {
|
|
200
|
+
available: false,
|
|
201
|
+
skew: null,
|
|
202
|
+
dir: null,
|
|
203
|
+
sizes: {},
|
|
204
|
+
encoded: {},
|
|
205
|
+
missing: [
|
|
206
|
+
`no packages/blender-engine/wasm beside this editor, and ${BLENDER_WASM_DIR_VARIABLE} ` +
|
|
207
|
+
`is not set to an absolute directory holding either ${BLENDER_WASM_FILES.join(', ')} ` +
|
|
208
|
+
`or ${BLENDER_WALI_ARTIFACT} beside its ${BLENDER_WALI_RUNTIME}/ tree`,
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
const skew = await skewOf(dir);
|
|
212
|
+
if (skew === null)
|
|
213
|
+
return {
|
|
214
|
+
available: false,
|
|
215
|
+
skew: null,
|
|
216
|
+
dir,
|
|
217
|
+
sizes: {},
|
|
218
|
+
encoded: {},
|
|
219
|
+
missing: [
|
|
220
|
+
`${dir} holds neither ${BLENDER_WASM_FILES.join(', ')} (the standalone skew) nor ` +
|
|
221
|
+
`${BLENDER_WALI_ARTIFACT} (the substrate skew)`,
|
|
222
|
+
],
|
|
223
|
+
};
|
|
224
|
+
return skew === 'wali' ? waliStatus(dir) : emscriptenStatus(dir);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function emscriptenStatus(dir: string): Promise<BlenderWasmStatus> {
|
|
228
|
+
const sizes: Record<string, number> = {};
|
|
229
|
+
const encoded: Record<string, 'br'> = {};
|
|
230
|
+
const missing: string[] = [];
|
|
231
|
+
for (const file of BLENDER_WASM_FILES) {
|
|
232
|
+
const found = await blenderWasmOnDisk(dir, file);
|
|
233
|
+
if (!found) {
|
|
234
|
+
missing.push(`${join(dir, file)} (or .br)`);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
sizes[file] = found.size;
|
|
238
|
+
if (found.encoding) encoded[file] = found.encoding;
|
|
239
|
+
}
|
|
240
|
+
return { available: missing.length === 0, skew: 'emscripten', dir, sizes, encoded, missing };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function waliStatus(dir: string): Promise<BlenderWasmStatus> {
|
|
244
|
+
const sizes: Record<string, number> = {};
|
|
245
|
+
const missing: string[] = [];
|
|
246
|
+
const artifact = join(dir, BLENDER_WALI_ARTIFACT);
|
|
247
|
+
try {
|
|
248
|
+
sizes[BLENDER_WALI_ARTIFACT] = (await stat(artifact)).size;
|
|
249
|
+
} catch {
|
|
250
|
+
missing.push(artifact);
|
|
251
|
+
}
|
|
252
|
+
let index: RuntimeIndex | null = null;
|
|
253
|
+
try {
|
|
254
|
+
index = await runtimeIndex(dir);
|
|
255
|
+
sizes[`${BLENDER_WALI_RUNTIME}/`] = index.files.reduce((total, file) => total + file.size, 0);
|
|
256
|
+
} catch (error) {
|
|
257
|
+
missing.push(
|
|
258
|
+
`${join(dir, BLENDER_WALI_RUNTIME)} (Blender's scripts, datafiles and python; ` +
|
|
259
|
+
`${error instanceof Error ? error.message : String(error)})`,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
for (const { segment, specifier } of BLENDER_WALI_SUBSTRATE)
|
|
263
|
+
if (substrateDir(specifier) === null)
|
|
264
|
+
missing.push(
|
|
265
|
+
`${specifier} (served at wali/${segment}/; the substrate skew runs Blender through it, ` +
|
|
266
|
+
`so a project that opts into this skew declares it)`,
|
|
267
|
+
);
|
|
268
|
+
const integrity =
|
|
269
|
+
missing.length === 0
|
|
270
|
+
? `sha256-${createHash('sha256')
|
|
271
|
+
.update(await readFile(artifact))
|
|
272
|
+
.digest('base64')}`
|
|
273
|
+
: undefined;
|
|
274
|
+
return {
|
|
275
|
+
available: missing.length === 0,
|
|
276
|
+
skew: 'wali',
|
|
277
|
+
dir,
|
|
278
|
+
sizes,
|
|
279
|
+
encoded: {},
|
|
280
|
+
missing,
|
|
281
|
+
...(integrity ? { integrity } : {}),
|
|
282
|
+
workers: { ...BLENDER_WALI_WORKERS },
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The glue, patched. Read once and held: it is 700 KB of text and every
|
|
288
|
+
* pthread the runtime spawns asks for it again.
|
|
289
|
+
*/
|
|
290
|
+
let patchedGlue: { dir: string; text: string } | null = null;
|
|
291
|
+
|
|
292
|
+
const CANVAS_TRANSFER =
|
|
293
|
+
'var transferredCanvasNames=attr?(growMemViews(),HEAPU32)[attr+40>>2]:0;if(';
|
|
294
|
+
|
|
295
|
+
export function patchBlenderGlue(source: string): string {
|
|
296
|
+
// A headless build spawns no window and its glue carries no canvas transfer:
|
|
297
|
+
// then there is nothing to patch and the glue is served as-is. Only a build
|
|
298
|
+
// that DOES transfer a `#canvas` (the port's UI-derived release) needs the
|
|
299
|
+
// list emptied, because a worker has no canvas and `#canvas` asks
|
|
300
|
+
// `Module.canvas` for one that is not there.
|
|
301
|
+
if (!source.includes(CANVAS_TRANSFER)) return source;
|
|
302
|
+
return source.replace(
|
|
303
|
+
CANVAS_TRANSFER,
|
|
304
|
+
`${CANVAS_TRANSFER}true){transferredCanvasNames=0}else if(`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export async function blenderGlueText(dir: string): Promise<string> {
|
|
309
|
+
if (patchedGlue?.dir === dir) return patchedGlue.text;
|
|
310
|
+
const found = await blenderWasmOnDisk(dir, 'blender_browser.js');
|
|
311
|
+
if (!found) throw new Error(`${join(dir, 'blender_browser.js')} is not there`);
|
|
312
|
+
const raw = await readFile(found.path);
|
|
313
|
+
// The glue is patched as TEXT, so a pre-compressed glue is inflated here.
|
|
314
|
+
const source =
|
|
315
|
+
found.encoding === 'br' ? brotliDecompressSync(raw).toString('utf8') : raw.toString('utf8');
|
|
316
|
+
const text = patchBlenderGlue(source);
|
|
317
|
+
patchedGlue = { dir, text };
|
|
318
|
+
return text;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function blenderWasmReadStream(found: BlenderWasmOnDisk): NodeJS.ReadableStream {
|
|
322
|
+
return createReadStream(found.path);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ---- The WALI skew: the runtime tree, and the substrate that runs the program.
|
|
326
|
+
|
|
327
|
+
export interface RuntimeIndex {
|
|
328
|
+
files: { path: string; size: number; mode: number }[];
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
let cachedRuntimeIndex: { dir: string; index: RuntimeIndex } | null = null;
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Blender's runtime tree, as ONE index plus ONE blob.
|
|
335
|
+
*
|
|
336
|
+
* ~2,300 files and 78 MB, every one of which has to exist before Blender's
|
|
337
|
+
* first act. The tab fetches this index and then `runtime.bin`, whose bytes
|
|
338
|
+
* are the same files concatenated IN THIS ORDER, and slices
|
|
339
|
+
* (`blender-wali-engine.mts`'s `stageRuntime`). A request per file would be
|
|
340
|
+
* 2,300 round trips; a tar would be a dependency and a decoder. The order is
|
|
341
|
+
* the index's and nothing else may assume it.
|
|
342
|
+
*/
|
|
343
|
+
export async function runtimeIndex(dir: string): Promise<RuntimeIndex> {
|
|
344
|
+
if (cachedRuntimeIndex?.dir === dir) return cachedRuntimeIndex.index;
|
|
345
|
+
const root = join(dir, BLENDER_WALI_RUNTIME);
|
|
346
|
+
const files: RuntimeIndex['files'] = [];
|
|
347
|
+
const walk = async (where: string): Promise<void> => {
|
|
348
|
+
for (const entry of (await readdir(where, { withFileTypes: true })).sort((left, right) =>
|
|
349
|
+
left.name < right.name ? -1 : left.name > right.name ? 1 : 0,
|
|
350
|
+
)) {
|
|
351
|
+
const path = join(where, entry.name);
|
|
352
|
+
if (entry.isDirectory()) {
|
|
353
|
+
await walk(path);
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
if (!entry.isFile()) continue;
|
|
357
|
+
const info = await stat(path);
|
|
358
|
+
files.push({
|
|
359
|
+
path: relative(root, path).split(/[\\/]/).join(posix.sep),
|
|
360
|
+
size: info.size,
|
|
361
|
+
mode: info.mode & 0o7777,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
await walk(root);
|
|
366
|
+
if (files.length === 0) throw new Error(`${root} is empty`);
|
|
367
|
+
const index = { files };
|
|
368
|
+
cachedRuntimeIndex = { dir, index };
|
|
369
|
+
return index;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Stream the runtime blob: every indexed file's bytes, in index order. */
|
|
373
|
+
export async function writeRuntimeBlob(dir: string, write: (chunk: Buffer) => void): Promise<void> {
|
|
374
|
+
const root = join(dir, BLENDER_WALI_RUNTIME);
|
|
375
|
+
for (const file of (await runtimeIndex(dir)).files) write(await readFile(join(root, file.path)));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Where a substrate package's browser ESM is, or null when it is not
|
|
380
|
+
* installed. Resolved through Node's own resolution from THIS file, so it
|
|
381
|
+
* finds whatever the project that opted into this skew declared.
|
|
382
|
+
*
|
|
383
|
+
* `import.meta.resolve` and not `createRequire().resolve`: these packages
|
|
384
|
+
* export `"."` and `"./*.js"` under the `import` condition ONLY, so a CJS
|
|
385
|
+
* resolve raises ERR_PACKAGE_PATH_NOT_EXPORTED on a package that is plainly
|
|
386
|
+
* installed. The package's OWN ENTRY is resolved rather than its
|
|
387
|
+
* `package.json`, which is not exported at all; the entry's directory IS the
|
|
388
|
+
* published `dist`, which is where every served module comes from.
|
|
389
|
+
*/
|
|
390
|
+
export function substrateDir(specifier: string): string | null {
|
|
391
|
+
try {
|
|
392
|
+
return dirname(fileURLToPath(import.meta.resolve(specifier)));
|
|
393
|
+
} catch {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const SUBSTRATE_SEGMENTS = new Map<string, string>(
|
|
399
|
+
BLENDER_WALI_SUBSTRATE.map(({ segment, specifier }) => [segment, specifier] as const),
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* One substrate module, with its bare specifiers rewritten to this door's URLs.
|
|
404
|
+
*
|
|
405
|
+
* `@volter/browser-wali/dist/worker-program.js` imports
|
|
406
|
+
* `@volter/browser-runtime/browser-filesystem.js`, which a browser cannot
|
|
407
|
+
* resolve; and `BrowserWaliWorkerProgram` spawns its own workers with
|
|
408
|
+
* `new Worker(new URL("./worker-program-worker.js", import.meta.url))`, so
|
|
409
|
+
* those land back on this same route and must get the identically rewritten
|
|
410
|
+
* text. That is the glue patch's rule applied to a second artifact, for the
|
|
411
|
+
* same reason.
|
|
412
|
+
*/
|
|
413
|
+
export async function substrateModule(
|
|
414
|
+
segment: string,
|
|
415
|
+
file: string,
|
|
416
|
+
): Promise<{ text: string } | null> {
|
|
417
|
+
const specifier = SUBSTRATE_SEGMENTS.get(segment);
|
|
418
|
+
if (!specifier || !/^[\w.-]+\.(?:js|mjs|map)$/.test(file)) return null;
|
|
419
|
+
const root = substrateDir(specifier);
|
|
420
|
+
if (root === null) return null;
|
|
421
|
+
const path = join(root, file);
|
|
422
|
+
if (!existsSync(path)) return null;
|
|
423
|
+
let text = (await readFile(path)).toString('utf8');
|
|
424
|
+
for (const other of BLENDER_WALI_SUBSTRATE)
|
|
425
|
+
text = text.replaceAll(
|
|
426
|
+
`"${other.specifier}/`,
|
|
427
|
+
`"/__editor/blender-wasm/wali/${other.segment}/`,
|
|
428
|
+
);
|
|
429
|
+
return { text };
|
|
430
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "WHERE DID EDITOR BOOT TIME GO" — the one journal row the server writes about
|
|
3
|
+
* its own start-up, emitted when the first browser tab's control channel
|
|
4
|
+
* arrives (`editor-server.ts`, beside `client-connected`).
|
|
5
|
+
*
|
|
6
|
+
* WHY IT EXISTS. `vgai edit` prints two lines — `Editor ready at …` and
|
|
7
|
+
* `Editor page connected …` — and the gap between them is the largest stage of
|
|
8
|
+
* opening a project, with nothing recording it anywhere. Measured 2026-08-20 on
|
|
9
|
+
* an imported Unity FPS port (528 source files): dev-server readiness was 8s and
|
|
10
|
+
* the SAME stage was 83–139s, and answering "why" needed a hand-built request
|
|
11
|
+
* trace plus a V8 CPU profile of the dev server. The cause turned out to be the
|
|
12
|
+
* server's own event loop blocked ~85% of two minutes inside the TypeScript
|
|
13
|
+
* parser (`ui-source/r3f-project-contracts.ts`) — which is exactly the shape a
|
|
14
|
+
* loop-delay number reports for free. A product whose slow stage can only be
|
|
15
|
+
* diagnosed by attaching a profiler is missing a door; this is that door.
|
|
16
|
+
*
|
|
17
|
+
* WHAT IT COSTS. One `monitorEventLoopDelay` histogram — a libuv-side C++
|
|
18
|
+
* sampler, not a JS timer — plus five `Date.now()` marks. `disable()` runs at
|
|
19
|
+
* the first bind, so nothing here outlives boot.
|
|
20
|
+
*
|
|
21
|
+
* `loopDelayP99Ms` IS THE DISCRIMINATING FIELD, and the reason the row is not
|
|
22
|
+
* just a list of stage durations: a slow bind with a quiet loop is the browser
|
|
23
|
+
* (or the network, or a hidden tab); a slow bind with a p99 in the hundreds of
|
|
24
|
+
* ms is THIS process refusing to answer, and every per-request duration in that
|
|
25
|
+
* window is queueing rather than work. Reading them the other way around is the
|
|
26
|
+
* mistake this row prevents — a 38s response for a static `.svg` measured
|
|
27
|
+
* nothing about the svg.
|
|
28
|
+
*/
|
|
29
|
+
import { type IntervalHistogram, monitorEventLoopDelay } from 'node:perf_hooks';
|
|
30
|
+
|
|
31
|
+
/** Every span in the boot, in the order a reader should think about them. */
|
|
32
|
+
export interface EditorBootTimings {
|
|
33
|
+
/** Process start → Vite's `createServer` resolved. */
|
|
34
|
+
readonly viteMs: number;
|
|
35
|
+
/** …→ the dependency scan settled (the barrier `dev.ts` awaits before listen). */
|
|
36
|
+
readonly depScanMs: number;
|
|
37
|
+
/** …→ the HTTP server was listening (what `Editor ready at` announces). */
|
|
38
|
+
readonly listenMs: number;
|
|
39
|
+
/**
|
|
40
|
+
* Listening → the first page that PROVED it is running the editor document
|
|
41
|
+
* (its command listener attached). Deliberately not the control channel:
|
|
42
|
+
* `index.html`'s inline bootstrap opens that before any module loads, so it
|
|
43
|
+
* dates the HTML, not the app.
|
|
44
|
+
*/
|
|
45
|
+
readonly boundMs: number;
|
|
46
|
+
/**
|
|
47
|
+
* Process start → the project's declared world warmup finished; `null` when
|
|
48
|
+
* no project was open to warm. On the same clock as the marks above on
|
|
49
|
+
* purpose: the warmup is kicked off right after `depScanMs` and deliberately
|
|
50
|
+
* NOT awaited, so what a reader needs is where it LANDS relative to the
|
|
51
|
+
* bind — before it (free) or across it (competing with the browser).
|
|
52
|
+
*/
|
|
53
|
+
readonly worldWarmupDoneMs: number | null;
|
|
54
|
+
/** Event-loop delay across the whole boot. A high p99 means the SERVER was the wait. */
|
|
55
|
+
readonly loopDelayP99Ms: number;
|
|
56
|
+
readonly loopDelayMaxMs: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type EditorBootMark = 'vite-created' | 'dep-scan-settled' | 'listening' | 'world-warmup';
|
|
60
|
+
|
|
61
|
+
export interface EditorBootTimer {
|
|
62
|
+
mark(name: EditorBootMark): void;
|
|
63
|
+
/**
|
|
64
|
+
* The row, ONCE — the first page to prove it is running the document ends
|
|
65
|
+
* the boot, and a later reload is not a second boot. `null` on every call
|
|
66
|
+
* after that, and on a call that arrives before `listening` was ever marked.
|
|
67
|
+
*/
|
|
68
|
+
takeBoundTimings(): EditorBootTimings | null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createEditorBootTimer(startedAt: number = Date.now()): EditorBootTimer {
|
|
72
|
+
const marks = new Map<EditorBootMark, number>();
|
|
73
|
+
let loop: IntervalHistogram | null = null;
|
|
74
|
+
try {
|
|
75
|
+
loop = monitorEventLoopDelay({ resolution: 20 });
|
|
76
|
+
loop.enable();
|
|
77
|
+
} catch {
|
|
78
|
+
// A runtime without the histogram still gets every other field.
|
|
79
|
+
loop = null;
|
|
80
|
+
}
|
|
81
|
+
let taken = false;
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
mark(name) {
|
|
85
|
+
if (!marks.has(name)) marks.set(name, Date.now());
|
|
86
|
+
},
|
|
87
|
+
takeBoundTimings() {
|
|
88
|
+
const listening = marks.get('listening');
|
|
89
|
+
if (taken || listening === undefined) return null;
|
|
90
|
+
taken = true;
|
|
91
|
+
const now = Date.now();
|
|
92
|
+
loop?.disable();
|
|
93
|
+
const warmup = marks.get('world-warmup');
|
|
94
|
+
return {
|
|
95
|
+
viteMs: (marks.get('vite-created') ?? startedAt) - startedAt,
|
|
96
|
+
depScanMs: (marks.get('dep-scan-settled') ?? startedAt) - startedAt,
|
|
97
|
+
listenMs: listening - startedAt,
|
|
98
|
+
boundMs: now - listening,
|
|
99
|
+
worldWarmupDoneMs: warmup === undefined ? null : warmup - startedAt,
|
|
100
|
+
// The histogram reports NANOSECONDS.
|
|
101
|
+
loopDelayP99Ms: loop === null ? 0 : Math.round(loop.percentile(99) / 1e6),
|
|
102
|
+
loopDelayMaxMs: loop === null ? 0 : Math.round(loop.max / 1e6),
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonicalize a project root path (T6.2 slice 3 finding; reported in the
|
|
3
|
+
* slice-3 "Report back").
|
|
4
|
+
*
|
|
5
|
+
* Vite's own module resolver calls `fs.realpathSync` when resolving a
|
|
6
|
+
* STATIC relative import — e.g. a react world's entry module's own
|
|
7
|
+
* `import { useWorldState } from '@vgai/game-runtime/react/world-state'` — which
|
|
8
|
+
* collapses a symlinked path segment (macOS's `/var` -> `/private/var`,
|
|
9
|
+
* hit by every project scaffolded under `os.tmpdir()`, as every e2e spec
|
|
10
|
+
* that calls `scaffoldProject()` does) to its real form.
|
|
11
|
+
* `binding-resolver.ts`'s hand-built `/@fs/${projectRoot}/...` dynamic-import
|
|
12
|
+
* strings (which must bypass Vite's static analysis via `@vite-ignore` — the
|
|
13
|
+
* path is only known at runtime) do NOT go through that same resolution. So
|
|
14
|
+
* if `projectRoot` itself isn't already canonical, two DIFFERENT `/@fs/`
|
|
15
|
+
* URLs get produced for the exact same file: Vite's realpath'd rewrite of
|
|
16
|
+
* the entry module's own relative import vs. our raw, non-realpath'd string
|
|
17
|
+
* used to import `WorldProvider` for the `<WorldProvider>` wrap. Browser ES
|
|
18
|
+
* module identity is per-URL, so the SAME `game-state.tsx` loads as TWO
|
|
19
|
+
* separate module instances with TWO separate top-level `createContext()`
|
|
20
|
+
* calls — `useWorldState`'s `useGame()` then throws "no Game in context"
|
|
21
|
+
* even though `<WorldProvider>` genuinely wraps the entry (this is exactly
|
|
22
|
+
* what the T6.2 slice-3 AC e2e's first real-browser run of a react world
|
|
23
|
+
* caught).
|
|
24
|
+
*
|
|
25
|
+
* The fix is upstream of any one `/@fs/` string: canonicalize the project
|
|
26
|
+
* root ONCE, at the points a project path enters server state (dev/prod
|
|
27
|
+
* boot from `VGAI_PROJECT`, and the `/__editor/open-project` route) — every
|
|
28
|
+
* `/@fs/${projectRoot}` string built anywhere afterwards (browser-side,
|
|
29
|
+
* repo-wide, not just the react-world resolver) then already matches
|
|
30
|
+
* whatever Vite's own resolver would independently arrive at for that same
|
|
31
|
+
* project.
|
|
32
|
+
*/
|
|
33
|
+
import { realpathSync } from 'node:fs';
|
|
34
|
+
import { resolve } from 'node:path';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolve `rawPath` to an absolute, symlink-canonicalized path. Falls back to
|
|
38
|
+
* a plain `path.resolve` if the path doesn't exist yet or `realpathSync`
|
|
39
|
+
* otherwise fails (e.g. a permissions error) — never throws, so a bad/odd
|
|
40
|
+
* path degrades to today's pre-canonicalization behavior rather than
|
|
41
|
+
* blocking project open.
|
|
42
|
+
*/
|
|
43
|
+
export function canonicalProjectRoot(rawPath: string): string {
|
|
44
|
+
const absolute = resolve(rawPath);
|
|
45
|
+
try {
|
|
46
|
+
return realpathSync(absolute);
|
|
47
|
+
} catch {
|
|
48
|
+
return absolute;
|
|
49
|
+
}
|
|
50
|
+
}
|