@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,345 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { dirname, extname } from 'node:path';
|
|
6
|
+
import * as THREE from 'three';
|
|
7
|
+
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
|
|
8
|
+
import { ColladaLoader } from 'three/addons/loaders/ColladaLoader.js';
|
|
9
|
+
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
|
|
10
|
+
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
11
|
+
import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
|
|
12
|
+
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
|
|
13
|
+
import { PLYLoader } from 'three/addons/loaders/PLYLoader.js';
|
|
14
|
+
import { STLLoader } from 'three/addons/loaders/STLLoader.js';
|
|
15
|
+
import { TDSLoader } from 'three/addons/loaders/TDSLoader.js';
|
|
16
|
+
import { mergeVertices } from 'three/addons/utils/BufferGeometryUtils.js';
|
|
17
|
+
import {
|
|
18
|
+
type AssetImportSettings,
|
|
19
|
+
assetImportSettingsSchema,
|
|
20
|
+
} from '../src/asset-workflow/import-contract';
|
|
21
|
+
|
|
22
|
+
export const SERVER_CONVERTIBLE_MODEL_FORMATS = new Set(['fbx', 'obj', 'dae', 'stl', 'ply', '3ds']);
|
|
23
|
+
|
|
24
|
+
/** Convert a staged source model to a runtime GLB without requiring Blender. */
|
|
25
|
+
export async function convertStagedModelToGlb(
|
|
26
|
+
primaryPath: string,
|
|
27
|
+
format: string,
|
|
28
|
+
rawSettings: Partial<AssetImportSettings> | number = {},
|
|
29
|
+
): Promise<Uint8Array> {
|
|
30
|
+
const settings = assetImportSettingsSchema.parse(
|
|
31
|
+
typeof rawSettings === 'number' ? { scale: rawSettings } : rawSettings,
|
|
32
|
+
);
|
|
33
|
+
installNodeDom();
|
|
34
|
+
const bytes = new Uint8Array(await readFile(primaryPath));
|
|
35
|
+
const object = await parseSourceModel(primaryPath, format.toLowerCase(), bytes);
|
|
36
|
+
discardUnloadedTextures(object);
|
|
37
|
+
applyModelImportSettings(object, settings);
|
|
38
|
+
installNodeFileReader();
|
|
39
|
+
try {
|
|
40
|
+
const result = await new Promise<ArrayBuffer>((resolve, reject) => {
|
|
41
|
+
new GLTFExporter().parse(
|
|
42
|
+
object,
|
|
43
|
+
(output) =>
|
|
44
|
+
output instanceof ArrayBuffer
|
|
45
|
+
? resolve(output)
|
|
46
|
+
: reject(new Error('Model conversion produced JSON instead of binary GLB.')),
|
|
47
|
+
reject,
|
|
48
|
+
{ binary: true, animations: object.animations, onlyVisible: false },
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
const output = new Uint8Array(result);
|
|
52
|
+
await validateConvertedGlb(output);
|
|
53
|
+
return output;
|
|
54
|
+
} finally {
|
|
55
|
+
disposeObject(object);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const materialTextureSlots = [
|
|
60
|
+
'map',
|
|
61
|
+
'alphaMap',
|
|
62
|
+
'aoMap',
|
|
63
|
+
'bumpMap',
|
|
64
|
+
'displacementMap',
|
|
65
|
+
'emissiveMap',
|
|
66
|
+
'envMap',
|
|
67
|
+
'lightMap',
|
|
68
|
+
'metalnessMap',
|
|
69
|
+
'normalMap',
|
|
70
|
+
'roughnessMap',
|
|
71
|
+
'specularMap',
|
|
72
|
+
] as const;
|
|
73
|
+
|
|
74
|
+
/** Apply the persisted conversion settings before the runtime GLB is exported. */
|
|
75
|
+
export function applyModelImportSettings(
|
|
76
|
+
object: THREE.Object3D,
|
|
77
|
+
settings: AssetImportSettings,
|
|
78
|
+
): void {
|
|
79
|
+
object.scale.multiplyScalar(settings.scale * sourceUnitScale(settings.sourceUnits));
|
|
80
|
+
object.quaternion.premultiply(importAxisRotation(settings.upAxis, settings.forwardAxis));
|
|
81
|
+
|
|
82
|
+
const discardedTextures = new Set<THREE.Texture>();
|
|
83
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one traversal deliberately applies the persisted mesh, material, texture, normal, tangent, and optimization settings to each converted renderable.
|
|
84
|
+
object.traverse((node) => {
|
|
85
|
+
const mesh = node as THREE.Mesh;
|
|
86
|
+
if (!mesh.geometry) return;
|
|
87
|
+
let geometry = mesh.geometry;
|
|
88
|
+
if (settings.meshOptimization !== 'none') {
|
|
89
|
+
const optimized = mergeVertices(
|
|
90
|
+
geometry,
|
|
91
|
+
settings.meshOptimization === 'aggressive' ? 1e-3 : 1e-6,
|
|
92
|
+
);
|
|
93
|
+
if (optimized !== geometry) {
|
|
94
|
+
mesh.geometry = optimized;
|
|
95
|
+
geometry.dispose();
|
|
96
|
+
geometry = optimized;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (settings.normals !== 'preserve') {
|
|
100
|
+
geometry.deleteAttribute('normal');
|
|
101
|
+
geometry.computeVertexNormals();
|
|
102
|
+
}
|
|
103
|
+
if (settings.tangents === 'discard') geometry.deleteAttribute('tangent');
|
|
104
|
+
if (
|
|
105
|
+
settings.tangents === 'generate' &&
|
|
106
|
+
geometry.index &&
|
|
107
|
+
geometry.hasAttribute('position') &&
|
|
108
|
+
geometry.hasAttribute('normal') &&
|
|
109
|
+
geometry.hasAttribute('uv')
|
|
110
|
+
) {
|
|
111
|
+
geometry.computeTangents();
|
|
112
|
+
}
|
|
113
|
+
geometry.computeBoundingBox();
|
|
114
|
+
geometry.computeBoundingSphere();
|
|
115
|
+
|
|
116
|
+
const priorMaterials = Array.isArray(mesh.material)
|
|
117
|
+
? mesh.material
|
|
118
|
+
: mesh.material
|
|
119
|
+
? [mesh.material]
|
|
120
|
+
: [];
|
|
121
|
+
if (settings.materials === 'discard') {
|
|
122
|
+
mesh.material = Array.isArray(mesh.material)
|
|
123
|
+
? priorMaterials.map(() => new THREE.MeshStandardMaterial())
|
|
124
|
+
: new THREE.MeshStandardMaterial();
|
|
125
|
+
for (const material of priorMaterials) material.dispose();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (settings.textures !== 'discard') return;
|
|
129
|
+
for (const material of priorMaterials) {
|
|
130
|
+
const textured = material as THREE.Material & Record<string, unknown>;
|
|
131
|
+
for (const slot of materialTextureSlots) {
|
|
132
|
+
const texture = textured[slot];
|
|
133
|
+
if (texture instanceof THREE.Texture) discardedTextures.add(texture);
|
|
134
|
+
textured[slot] = null;
|
|
135
|
+
}
|
|
136
|
+
material.needsUpdate = true;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
for (const texture of discardedTextures) texture.dispose();
|
|
140
|
+
|
|
141
|
+
if (settings.animations.length > 0) {
|
|
142
|
+
const requested = new Set(settings.animations);
|
|
143
|
+
const selected = object.animations.filter((clip) => requested.has(clip.name));
|
|
144
|
+
const missing = settings.animations.filter(
|
|
145
|
+
(name) => !selected.some((clip) => clip.name === name),
|
|
146
|
+
);
|
|
147
|
+
if (missing.length > 0) throw new Error(`Animation clips not found: ${missing.join(', ')}.`);
|
|
148
|
+
object.animations = selected;
|
|
149
|
+
}
|
|
150
|
+
object.updateWorldMatrix(true, true);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function sourceUnitScale(units: AssetImportSettings['sourceUnits']): number {
|
|
154
|
+
return { auto: 1, mm: 0.001, cm: 0.01, m: 1, in: 0.0254, ft: 0.3048 }[units];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function importAxisRotation(
|
|
158
|
+
upAxis: AssetImportSettings['upAxis'],
|
|
159
|
+
forwardAxis: AssetImportSettings['forwardAxis'],
|
|
160
|
+
): THREE.Quaternion {
|
|
161
|
+
const up = upAxis === 'auto' ? null : axisVector(upAxis);
|
|
162
|
+
const forward = forwardAxis === 'auto' ? null : axisVector(forwardAxis);
|
|
163
|
+
if (up && forward) {
|
|
164
|
+
if (Math.abs(up.dot(forward)) > 0.001)
|
|
165
|
+
throw new Error('Import up and forward axes must be perpendicular.');
|
|
166
|
+
const right = new THREE.Vector3().crossVectors(forward, up).normalize();
|
|
167
|
+
const correctedForward = new THREE.Vector3().crossVectors(up, right).normalize();
|
|
168
|
+
const sourceBasis = new THREE.Matrix4().makeBasis(right, up, correctedForward.clone().negate());
|
|
169
|
+
return new THREE.Quaternion().setFromRotationMatrix(sourceBasis.invert());
|
|
170
|
+
}
|
|
171
|
+
if (up) return new THREE.Quaternion().setFromUnitVectors(up, new THREE.Vector3(0, 1, 0));
|
|
172
|
+
if (forward)
|
|
173
|
+
return new THREE.Quaternion().setFromUnitVectors(forward, new THREE.Vector3(0, 0, -1));
|
|
174
|
+
return new THREE.Quaternion();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function axisVector(axis: Exclude<AssetImportSettings['forwardAxis'], 'auto'> | 'x' | 'y' | 'z') {
|
|
178
|
+
const sign = axis.startsWith('-') ? -1 : 1;
|
|
179
|
+
const name = axis.replace('-', '');
|
|
180
|
+
return new THREE.Vector3(
|
|
181
|
+
name === 'x' ? sign : 0,
|
|
182
|
+
name === 'y' ? sign : 0,
|
|
183
|
+
name === 'z' ? sign : 0,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function parseSourceModel(
|
|
188
|
+
primaryPath: string,
|
|
189
|
+
format: string,
|
|
190
|
+
bytes: Uint8Array,
|
|
191
|
+
): Promise<THREE.Object3D> {
|
|
192
|
+
const resourcePath = `${dirname(primaryPath)}/`;
|
|
193
|
+
switch (format) {
|
|
194
|
+
case 'fbx':
|
|
195
|
+
return new FBXLoader().parse(bytes.buffer as ArrayBuffer, resourcePath);
|
|
196
|
+
case 'obj': {
|
|
197
|
+
const loader = new OBJLoader();
|
|
198
|
+
const materialPath = primaryPath.replace(/\.obj$/i, '.mtl');
|
|
199
|
+
try {
|
|
200
|
+
const materials = new MTLLoader().parse(await readFile(materialPath, 'utf8'), resourcePath);
|
|
201
|
+
materials.preload();
|
|
202
|
+
loader.setMaterials(materials);
|
|
203
|
+
} catch {
|
|
204
|
+
// Geometry-only OBJ conversion remains valid when no MTL is present.
|
|
205
|
+
}
|
|
206
|
+
return loader.parse(new TextDecoder().decode(bytes));
|
|
207
|
+
}
|
|
208
|
+
case 'dae': {
|
|
209
|
+
return new ColladaLoader().parse(new TextDecoder().decode(bytes), resourcePath).scene;
|
|
210
|
+
}
|
|
211
|
+
case 'stl': {
|
|
212
|
+
const geometry = new STLLoader().parse(bytes.buffer as ArrayBuffer);
|
|
213
|
+
return new THREE.Mesh(
|
|
214
|
+
geometry,
|
|
215
|
+
new THREE.MeshStandardMaterial({ color: 0x8fb5da, roughness: 0.75 }),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
case 'ply': {
|
|
219
|
+
const geometry = new PLYLoader().parse(bytes.buffer as ArrayBuffer);
|
|
220
|
+
if (!geometry.hasAttribute('normal')) geometry.computeVertexNormals();
|
|
221
|
+
return new THREE.Mesh(
|
|
222
|
+
geometry,
|
|
223
|
+
new THREE.MeshStandardMaterial({
|
|
224
|
+
color: geometry.hasAttribute('color') ? 0xffffff : 0xb8d09b,
|
|
225
|
+
vertexColors: geometry.hasAttribute('color'),
|
|
226
|
+
roughness: 0.8,
|
|
227
|
+
side: THREE.DoubleSide,
|
|
228
|
+
}),
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
case '3ds':
|
|
232
|
+
return new TDSLoader().parse(bytes.buffer as ArrayBuffer, resourcePath);
|
|
233
|
+
default:
|
|
234
|
+
throw new Error(`Built-in conversion does not support ${format || extname(primaryPath)}.`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Three's source loaders construct browser image elements even when the
|
|
239
|
+
* conversion runs in Node. JSDOM supplies that parser boundary; unresolved
|
|
240
|
+
* asynchronous images are removed below rather than passed to GLTFExporter
|
|
241
|
+
* as invalid zero-sized image objects. */
|
|
242
|
+
function installNodeDom(): void {
|
|
243
|
+
if (typeof document !== 'undefined' && typeof DOMParser !== 'undefined') return;
|
|
244
|
+
const { JSDOM } = createRequire(import.meta.url)('jsdom') as {
|
|
245
|
+
JSDOM: new () => {
|
|
246
|
+
window: {
|
|
247
|
+
document: Document;
|
|
248
|
+
DOMParser: typeof DOMParser;
|
|
249
|
+
HTMLImageElement: typeof HTMLImageElement;
|
|
250
|
+
HTMLCanvasElement: typeof HTMLCanvasElement;
|
|
251
|
+
Image: typeof Image;
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
const window = new JSDOM().window;
|
|
256
|
+
Object.assign(globalThis, {
|
|
257
|
+
document: window.document,
|
|
258
|
+
DOMParser: window.DOMParser,
|
|
259
|
+
HTMLImageElement: window.HTMLImageElement,
|
|
260
|
+
HTMLCanvasElement: window.HTMLCanvasElement,
|
|
261
|
+
Image: window.Image,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function discardUnloadedTextures(root: THREE.Object3D): void {
|
|
266
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one bounded traversal removes only unresolved image slots across every supported material shape.
|
|
267
|
+
root.traverse((object) => {
|
|
268
|
+
const mesh = object as THREE.Mesh;
|
|
269
|
+
const materials = Array.isArray(mesh.material)
|
|
270
|
+
? mesh.material
|
|
271
|
+
: mesh.material
|
|
272
|
+
? [mesh.material]
|
|
273
|
+
: [];
|
|
274
|
+
for (const material of materials) {
|
|
275
|
+
const textured = material as THREE.Material & Record<string, unknown>;
|
|
276
|
+
for (const slot of materialTextureSlots) {
|
|
277
|
+
const value = textured[slot];
|
|
278
|
+
if (!(value instanceof THREE.Texture)) continue;
|
|
279
|
+
const image = value.image as { width?: number; height?: number } | null;
|
|
280
|
+
if (image && (image.width ?? 0) > 0 && (image.height ?? 0) > 0) continue;
|
|
281
|
+
textured[slot] = null;
|
|
282
|
+
value.dispose();
|
|
283
|
+
}
|
|
284
|
+
material.needsUpdate = true;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function validateConvertedGlb(bytes: Uint8Array): Promise<void> {
|
|
290
|
+
const parsed = await new GLTFLoader().parseAsync(Uint8Array.from(bytes).buffer, '');
|
|
291
|
+
let renderable = false;
|
|
292
|
+
parsed.scene.traverse((object) => {
|
|
293
|
+
renderable ||= Boolean((object as THREE.Mesh).isMesh || (object as THREE.Points).isPoints);
|
|
294
|
+
});
|
|
295
|
+
disposeObject(parsed.scene);
|
|
296
|
+
if (!renderable && parsed.animations.length === 0) {
|
|
297
|
+
throw new Error('Converted GLB contains neither renderable geometry nor animation clips.');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function installNodeFileReader(): void {
|
|
302
|
+
if (typeof FileReader !== 'undefined') return;
|
|
303
|
+
class NodeFileReader {
|
|
304
|
+
result: string | ArrayBuffer | null = null;
|
|
305
|
+
error: Error | null = null;
|
|
306
|
+
onloadend: ((event: ProgressEvent<FileReader>) => void) | null = null;
|
|
307
|
+
onerror: ((event: ProgressEvent<FileReader>) => void) | null = null;
|
|
308
|
+
readAsArrayBuffer(blob: Blob): void {
|
|
309
|
+
void blob.arrayBuffer().then(
|
|
310
|
+
(result) => {
|
|
311
|
+
this.result = result;
|
|
312
|
+
this.onloadend?.({ target: this } as unknown as ProgressEvent<FileReader>);
|
|
313
|
+
},
|
|
314
|
+
(error) => {
|
|
315
|
+
this.error = error instanceof Error ? error : new Error(String(error));
|
|
316
|
+
this.onerror?.({ target: this } as unknown as ProgressEvent<FileReader>);
|
|
317
|
+
},
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
readAsDataURL(blob: Blob): void {
|
|
321
|
+
void blob.arrayBuffer().then((result) => {
|
|
322
|
+
this.result = `data:${blob.type || 'application/octet-stream'};base64,${Buffer.from(result).toString('base64')}`;
|
|
323
|
+
this.onloadend?.({ target: this } as unknown as ProgressEvent<FileReader>);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
Object.assign(globalThis, { FileReader: NodeFileReader });
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function disposeObject(root: THREE.Object3D): void {
|
|
331
|
+
root.traverse((object) => {
|
|
332
|
+
const renderable = object as THREE.Mesh;
|
|
333
|
+
renderable.geometry?.dispose();
|
|
334
|
+
const materials = Array.isArray(renderable.material)
|
|
335
|
+
? renderable.material
|
|
336
|
+
: renderable.material
|
|
337
|
+
? [renderable.material]
|
|
338
|
+
: [];
|
|
339
|
+
for (const material of materials) {
|
|
340
|
+
for (const value of Object.values(material))
|
|
341
|
+
if (value instanceof THREE.Texture) value.dispose();
|
|
342
|
+
material.dispose();
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
export type CredentialPersistence = 'system' | 'session';
|
|
2
|
+
|
|
3
|
+
export interface NativeCredentialStore {
|
|
4
|
+
persistence(): Promise<CredentialPersistence>;
|
|
5
|
+
read(account: string): Promise<string | null>;
|
|
6
|
+
write(account: string, value: string): Promise<void>;
|
|
7
|
+
delete(account: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Normalized per-credential handle over `@napi-rs/keyring`'s `AsyncEntry` /
|
|
12
|
+
* `Entry` classes. Restores keytar's calmer contract: a missing credential is
|
|
13
|
+
* `null` / `false`, never an error.
|
|
14
|
+
*/
|
|
15
|
+
interface KeyringEntry {
|
|
16
|
+
getPassword(): Promise<string | null>;
|
|
17
|
+
setPassword(value: string): Promise<void>;
|
|
18
|
+
deletePassword(): Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type KeyringEntryFactory = (service: string, account: string) => KeyringEntry;
|
|
22
|
+
|
|
23
|
+
type KeyringLoader = () => Promise<unknown>;
|
|
24
|
+
|
|
25
|
+
interface RawKeyringEntry {
|
|
26
|
+
getPassword(): unknown;
|
|
27
|
+
setPassword(value: string): unknown;
|
|
28
|
+
deleteCredential?(): unknown;
|
|
29
|
+
deletePassword?(): unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type RawEntryConstructor = new (service: string, account: string) => RawKeyringEntry;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* `keyring-rs` reports an absent credential as a NoEntry error. Message text
|
|
36
|
+
* varies by binding/version: keyring-rs v2/v3 says "No matching entry found
|
|
37
|
+
* in secure storage", while the actually-shipped `@napi-rs/keyring@^1.3.0`
|
|
38
|
+
* native binary says "No matching credential found" (confirmed via `strings`
|
|
39
|
+
* on the installed binary). keytar returned `null`/`false` for the same
|
|
40
|
+
* situation; treat NoEntry as "not found", not as a broken credential manager,
|
|
41
|
+
* regardless of which wording the binding uses.
|
|
42
|
+
*/
|
|
43
|
+
function isNoEntryError(error: unknown): boolean {
|
|
44
|
+
return error instanceof Error && /no matching (entry|credential)/i.test(error.message);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function keyringApi(module: unknown): KeyringEntryFactory | null {
|
|
48
|
+
if (!module || typeof module !== 'object') return null;
|
|
49
|
+
const imported = module as Record<string, unknown>;
|
|
50
|
+
const candidate =
|
|
51
|
+
imported['default'] && typeof imported['default'] === 'object'
|
|
52
|
+
? (imported['default'] as Record<string, unknown>)
|
|
53
|
+
: imported;
|
|
54
|
+
// Prefer AsyncEntry (does not block the event loop); accept sync Entry too.
|
|
55
|
+
const EntryConstructor = [candidate['AsyncEntry'], candidate['Entry']].find(
|
|
56
|
+
(value): value is RawEntryConstructor =>
|
|
57
|
+
typeof value === 'function' &&
|
|
58
|
+
typeof (value as { prototype?: Record<string, unknown> }).prototype?.['getPassword'] ===
|
|
59
|
+
'function' &&
|
|
60
|
+
typeof (value as { prototype?: Record<string, unknown> }).prototype?.['setPassword'] ===
|
|
61
|
+
'function',
|
|
62
|
+
);
|
|
63
|
+
if (!EntryConstructor) return null;
|
|
64
|
+
return (service, account) => {
|
|
65
|
+
const entry = new EntryConstructor(service, account);
|
|
66
|
+
return {
|
|
67
|
+
async getPassword() {
|
|
68
|
+
try {
|
|
69
|
+
const value = await entry.getPassword();
|
|
70
|
+
return typeof value === 'string' ? value : null;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (isNoEntryError(error)) return null;
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
async setPassword(value) {
|
|
77
|
+
await entry.setPassword(value);
|
|
78
|
+
},
|
|
79
|
+
async deletePassword() {
|
|
80
|
+
try {
|
|
81
|
+
const deleted =
|
|
82
|
+
typeof entry.deleteCredential === 'function'
|
|
83
|
+
? await entry.deleteCredential()
|
|
84
|
+
: await entry.deletePassword?.();
|
|
85
|
+
return deleted !== false;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (isNoEntryError(error)) return false;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* One editor-global secret boundary. Native builds use macOS Keychain,
|
|
97
|
+
* Windows Credential Manager, or Linux Secret Service through
|
|
98
|
+
* `@napi-rs/keyring`, the maintained native credential-store binding. A host
|
|
99
|
+
* without that optional dependency is deliberately session-only: it never
|
|
100
|
+
* turns a missing credential manager into a plaintext file.
|
|
101
|
+
*/
|
|
102
|
+
export function createNativeCredentialStore(
|
|
103
|
+
service = 'ai.vgai.editor',
|
|
104
|
+
loadKeyring: KeyringLoader = () => import('@napi-rs/keyring'),
|
|
105
|
+
): NativeCredentialStore {
|
|
106
|
+
const memory = new Map<string, string>();
|
|
107
|
+
let modulePromise: Promise<KeyringEntryFactory | null> | undefined;
|
|
108
|
+
let degraded = false;
|
|
109
|
+
const keyring = () => {
|
|
110
|
+
modulePromise ??= loadKeyring()
|
|
111
|
+
.then(keyringApi)
|
|
112
|
+
.catch(() => null);
|
|
113
|
+
return modulePromise;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
async persistence() {
|
|
118
|
+
return (await keyring()) && !degraded ? 'system' : 'session';
|
|
119
|
+
},
|
|
120
|
+
async read(account) {
|
|
121
|
+
const native = await keyring();
|
|
122
|
+
if (native && !degraded) {
|
|
123
|
+
try {
|
|
124
|
+
const value = await native(service, account).getPassword();
|
|
125
|
+
if (value === null) memory.delete(account);
|
|
126
|
+
else memory.set(account, value);
|
|
127
|
+
return value;
|
|
128
|
+
} catch {
|
|
129
|
+
degraded = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return memory.get(account) ?? null;
|
|
133
|
+
},
|
|
134
|
+
async write(account, value) {
|
|
135
|
+
const native = await keyring();
|
|
136
|
+
if (native && !degraded) {
|
|
137
|
+
try {
|
|
138
|
+
await native(service, account).setPassword(value);
|
|
139
|
+
memory.set(account, value);
|
|
140
|
+
return;
|
|
141
|
+
} catch {
|
|
142
|
+
degraded = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
memory.set(account, value);
|
|
146
|
+
},
|
|
147
|
+
async delete(account) {
|
|
148
|
+
const native = await keyring();
|
|
149
|
+
if (native) {
|
|
150
|
+
try {
|
|
151
|
+
await native(service, account).deletePassword();
|
|
152
|
+
} catch {
|
|
153
|
+
degraded = true;
|
|
154
|
+
throw new Error(
|
|
155
|
+
'The native credential manager could not confirm that the credential was deleted.',
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
memory.delete(account);
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE platform browser hand-off — the one open ladder (darwin / win32 / WSL
|
|
3
|
+
* explorer.exe→powershell.exe / xdg-open), owned here because the editor
|
|
4
|
+
* server must keep maintaining its tab (tab-bijection self-heal,
|
|
5
|
+
* ensure-driven opens) long after any launching CLI process has exited. The
|
|
6
|
+
* CLI imports this module; it does not carry its own copy — the old
|
|
7
|
+
* "no editor-package dependency" premise stopped being true when the CLI
|
|
8
|
+
* grew six editor-server imports and an `@vgai/editor` dependency, and the
|
|
9
|
+
* two ladders had already drifted (`-g` background support on one side
|
|
10
|
+
* only).
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
14
|
+
import { spawnOpener } from './spawn-opener';
|
|
15
|
+
|
|
16
|
+
function isWSL(): boolean {
|
|
17
|
+
if (process.platform !== 'linux') return false;
|
|
18
|
+
try {
|
|
19
|
+
return readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft');
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The path segment that identifies a session rooted in an AGENT's git
|
|
27
|
+
* worktree. Agents take one of these before they write code
|
|
28
|
+
* (docs/LOCAL-DEV.md), so it is the one honest, always-present signal that a
|
|
29
|
+
* tab belongs to a background builder rather than to the person at the
|
|
30
|
+
* keyboard.
|
|
31
|
+
*/
|
|
32
|
+
const AGENT_WORKTREE_MARKER = '/.claude/worktrees/';
|
|
33
|
+
|
|
34
|
+
/** Env override for the placement decision (`1` background, `0` foreground). */
|
|
35
|
+
export const TAB_BACKGROUND_ENV = 'VGAI_TAB_BACKGROUND';
|
|
36
|
+
|
|
37
|
+
export interface TabOpenPlacementInput {
|
|
38
|
+
/**
|
|
39
|
+
* The session's project root, ALREADY symlink-resolved
|
|
40
|
+
* (`canonicalProjectRoot`) — the marker check is on the real path, because
|
|
41
|
+
* a worktree reached through a symlinked parent would otherwise read as a
|
|
42
|
+
* human checkout.
|
|
43
|
+
*/
|
|
44
|
+
readonly projectRoot: string | null | undefined;
|
|
45
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Decide whether this session's ONE tab should open behind the human's
|
|
50
|
+
* current window instead of stealing focus.
|
|
51
|
+
*
|
|
52
|
+
* Measured (owner, three times in one day): every builder/reviewer `vgai edit`
|
|
53
|
+
* auto-opened a FOREGROUND tab on the one display, so the owner kept ending up
|
|
54
|
+
* looking at an agent's session instead of their own. A session rooted in an
|
|
55
|
+
* agent worktree therefore opens in the BACKGROUND; the human flow — a normal
|
|
56
|
+
* checkout, or a scaffolded game anywhere else — keeps foreground, because for
|
|
57
|
+
* a person the whole point of `vgai edit` is that the editor comes up in front
|
|
58
|
+
* of them.
|
|
59
|
+
*
|
|
60
|
+
* `VGAI_TAB_BACKGROUND` overrides in BOTH directions: `1` backgrounds a tab
|
|
61
|
+
* that would have been foreground, `0` foregrounds one inside a worktree (an
|
|
62
|
+
* agent deliberately showing the owner something).
|
|
63
|
+
*
|
|
64
|
+
* Pure: the caller supplies the resolved root and the environment.
|
|
65
|
+
*/
|
|
66
|
+
export function shouldOpenTabInBackground(input: TabOpenPlacementInput): boolean {
|
|
67
|
+
const override = input.env[TAB_BACKGROUND_ENV];
|
|
68
|
+
if (override !== undefined && override !== '') {
|
|
69
|
+
return override !== '0' && override.toLowerCase() !== 'false';
|
|
70
|
+
}
|
|
71
|
+
const root = input.projectRoot;
|
|
72
|
+
if (root === null || root === undefined || root === '') return false;
|
|
73
|
+
return root.replaceAll('\\', '/').includes(AGENT_WORKTREE_MARKER);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface OpenBrowserUrlOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Open behind the frontmost window instead of activating the browser.
|
|
79
|
+
* Honored on macOS only (`open -g`) — Windows `start` and `xdg-open` have no
|
|
80
|
+
* portable equivalent, so every other platform keeps its existing
|
|
81
|
+
* focus-stealing behavior rather than getting a half-kept promise.
|
|
82
|
+
*/
|
|
83
|
+
readonly background?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Best-effort open of `browserUrl` in the platform default browser. */
|
|
87
|
+
export function openBrowserUrl(browserUrl: string, options?: OpenBrowserUrlOptions): void {
|
|
88
|
+
if (process.platform === 'darwin') {
|
|
89
|
+
// `-g` = do not bring the opened application to the foreground. The tab
|
|
90
|
+
// still opens, still loads, and still registers with the bijection — it
|
|
91
|
+
// just does not seize the display.
|
|
92
|
+
spawnOpener('open', options?.background === true ? ['-g', browserUrl] : [browserUrl]);
|
|
93
|
+
} else if (process.platform === 'win32') {
|
|
94
|
+
// `start` is a cmd builtin, not an executable — it needs cmd itself.
|
|
95
|
+
spawnOpener('cmd', ['/c', 'start', '', browserUrl]);
|
|
96
|
+
} else if (isWSL()) {
|
|
97
|
+
// WSL has no display of its own; hand the URL to the Windows side. A dead
|
|
98
|
+
// interop socket (stale background session) means no Windows .exe can
|
|
99
|
+
// launch — name it instead of failing silently.
|
|
100
|
+
const interop = process.env['WSL_INTEROP'];
|
|
101
|
+
if (interop && !existsSync(interop)) {
|
|
102
|
+
console.error(
|
|
103
|
+
`[vgai-editor] cannot open a browser from this shell — the WSL interop socket ` +
|
|
104
|
+
`(${interop}) is gone, so Windows executables cannot launch. Open ${browserUrl} ` +
|
|
105
|
+
'from any regular terminal or browser instead.',
|
|
106
|
+
);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Explorer is the direct Windows shell-association path. Start-Process
|
|
110
|
+
// can exit zero even when a transient browser process fails to forward
|
|
111
|
+
// the URL to the existing browser, so PowerShell is the fallback.
|
|
112
|
+
spawnOpener('explorer.exe', [browserUrl], () =>
|
|
113
|
+
spawnOpener('powershell.exe', ['-NoProfile', '-Command', `Start-Process '${browserUrl}'`]),
|
|
114
|
+
);
|
|
115
|
+
} else {
|
|
116
|
+
spawnOpener('xdg-open', [browserUrl]);
|
|
117
|
+
}
|
|
118
|
+
}
|