unity-open-mcp 0.1.0 → 0.3.0
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/dist/agent-identity.d.ts +52 -0
- package/dist/agent-identity.js +115 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/batch-spawn.d.ts +7 -0
- package/dist/batch-spawn.js +155 -29
- package/dist/batch-spawn.js.map +1 -1
- package/dist/capabilities/build-capabilities.d.ts +45 -0
- package/dist/capabilities/build-capabilities.js +262 -27
- package/dist/capabilities/build-capabilities.js.map +1 -1
- package/dist/capabilities/cost-hints.d.ts +82 -0
- package/dist/capabilities/cost-hints.js +185 -0
- package/dist/capabilities/cost-hints.js.map +1 -0
- package/dist/capabilities/lifecycle.d.ts +40 -0
- package/dist/capabilities/lifecycle.js +353 -0
- package/dist/capabilities/lifecycle.js.map +1 -0
- package/dist/capabilities/rule-catalog.d.ts +13 -1
- package/dist/capabilities/rule-catalog.js +620 -75
- package/dist/capabilities/rule-catalog.js.map +1 -1
- package/dist/capabilities/tool-groups.d.ts +21 -0
- package/dist/capabilities/tool-groups.js +411 -14
- package/dist/capabilities/tool-groups.js.map +1 -1
- package/dist/cli/args.d.ts +32 -1
- package/dist/cli/args.js +201 -4
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/cli.d.ts +21 -0
- package/dist/cli/cli.js +68 -5
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/commands.d.ts +33 -0
- package/dist/cli/commands.js +400 -0
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/exit-codes.d.ts +43 -0
- package/dist/cli/exit-codes.js +78 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/compile-verify.d.ts +65 -0
- package/dist/compile-verify.js +94 -0
- package/dist/compile-verify.js.map +1 -0
- package/dist/compressible-router.js +64 -11
- package/dist/compressible-router.js.map +1 -1
- package/dist/compression/asset-model.d.ts +15 -0
- package/dist/compression/compact.d.ts +5 -4
- package/dist/compression/compact.js +13 -10
- package/dist/compression/compact.js.map +1 -1
- package/dist/dialog-dismiss.d.ts +127 -74
- package/dist/dialog-dismiss.js +427 -170
- package/dist/dialog-dismiss.js.map +1 -1
- package/dist/dialog-policy.d.ts +141 -0
- package/dist/dialog-policy.js +345 -0
- package/dist/dialog-policy.js.map +1 -0
- package/dist/gate-error.d.ts +6 -0
- package/dist/gate-error.js +13 -2
- package/dist/gate-error.js.map +1 -1
- package/dist/hub-control.d.ts +247 -0
- package/dist/hub-control.js +703 -0
- package/dist/hub-control.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -12
- package/dist/index.js.map +1 -1
- package/dist/live-client.d.ts +123 -3
- package/dist/live-client.js +526 -69
- package/dist/live-client.js.map +1 -1
- package/dist/offline.d.ts +105 -0
- package/dist/offline.js +816 -23
- package/dist/offline.js.map +1 -1
- package/dist/output-profile.d.ts +110 -0
- package/dist/output-profile.js +255 -0
- package/dist/output-profile.js.map +1 -0
- package/dist/retry-policy.d.ts +72 -0
- package/dist/retry-policy.js +146 -0
- package/dist/retry-policy.js.map +1 -0
- package/dist/routers.d.ts +4 -0
- package/dist/routers.js +2 -2
- package/dist/routers.js.map +1 -1
- package/dist/server-instructions.d.ts +18 -0
- package/dist/server-instructions.js +145 -0
- package/dist/server-instructions.js.map +1 -0
- package/dist/tool-router.d.ts +38 -1
- package/dist/tool-router.js +690 -37
- package/dist/tool-router.js.map +1 -1
- package/dist/tool-session-state.d.ts +37 -0
- package/dist/tool-session-state.js +78 -1
- package/dist/tool-session-state.js.map +1 -1
- package/dist/tools/apply-fix.js +16 -2
- package/dist/tools/apply-fix.js.map +1 -1
- package/dist/tools/asmdef-create.d.ts +2 -0
- package/dist/tools/asmdef-create.js +114 -0
- package/dist/tools/asmdef-create.js.map +1 -0
- package/dist/tools/asmdef-get.d.ts +2 -0
- package/dist/tools/asmdef-get.js +31 -0
- package/dist/tools/asmdef-get.js.map +1 -0
- package/dist/tools/asmdef-list.d.ts +2 -0
- package/dist/tools/asmdef-list.js +41 -0
- package/dist/tools/asmdef-list.js.map +1 -0
- package/dist/tools/asmdef-modify.d.ts +2 -0
- package/dist/tools/asmdef-modify.js +108 -0
- package/dist/tools/asmdef-modify.js.map +1 -0
- package/dist/tools/audio-listener-get.d.ts +2 -0
- package/dist/tools/audio-listener-get.js +16 -0
- package/dist/tools/audio-listener-get.js.map +1 -0
- package/dist/tools/audio-mixer-get-parameter.d.ts +2 -0
- package/dist/tools/audio-mixer-get-parameter.js +25 -0
- package/dist/tools/audio-mixer-get-parameter.js.map +1 -0
- package/dist/tools/audio-mixer-set-parameter.d.ts +2 -0
- package/dist/tools/audio-mixer-set-parameter.js +44 -0
- package/dist/tools/audio-mixer-set-parameter.js.map +1 -0
- package/dist/tools/audio-source-add.d.ts +2 -0
- package/dist/tools/audio-source-add.js +94 -0
- package/dist/tools/audio-source-add.js.map +1 -0
- package/dist/tools/audio-source-modify.d.ts +2 -0
- package/dist/tools/audio-source-modify.js +52 -0
- package/dist/tools/audio-source-modify.js.map +1 -0
- package/dist/tools/bridge-status.js +16 -6
- package/dist/tools/bridge-status.js.map +1 -1
- package/dist/tools/build-get-active-target.js +1 -2
- package/dist/tools/build-get-active-target.js.map +1 -1
- package/dist/tools/build-get-defines.js +1 -1
- package/dist/tools/build-get-defines.js.map +1 -1
- package/dist/tools/build-get-scenes.js +1 -2
- package/dist/tools/build-get-scenes.js.map +1 -1
- package/dist/tools/build-get-targets.js +1 -1
- package/dist/tools/build-get-targets.js.map +1 -1
- package/dist/tools/build-set-defines.js +1 -2
- package/dist/tools/build-set-defines.js.map +1 -1
- package/dist/tools/build-set-scenes.js +1 -1
- package/dist/tools/build-set-scenes.js.map +1 -1
- package/dist/tools/build-set-target.js +1 -1
- package/dist/tools/build-set-target.js.map +1 -1
- package/dist/tools/build-start.js +0 -1
- package/dist/tools/build-start.js.map +1 -1
- package/dist/tools/cinemachine-brain-ensure.d.ts +2 -0
- package/dist/tools/cinemachine-brain-ensure.js +27 -0
- package/dist/tools/cinemachine-brain-ensure.js.map +1 -0
- package/dist/tools/cinemachine-camera-list.d.ts +2 -0
- package/dist/tools/cinemachine-camera-list.js +15 -0
- package/dist/tools/cinemachine-camera-list.js.map +1 -0
- package/dist/tools/cinemachine-create-camera.d.ts +2 -0
- package/dist/tools/cinemachine-create-camera.js +55 -0
- package/dist/tools/cinemachine-create-camera.js.map +1 -0
- package/dist/tools/cinemachine-set-body.d.ts +2 -0
- package/dist/tools/cinemachine-set-body.js +33 -0
- package/dist/tools/cinemachine-set-body.js.map +1 -0
- package/dist/tools/cinemachine-set-lens.d.ts +2 -0
- package/dist/tools/cinemachine-set-lens.js +41 -0
- package/dist/tools/cinemachine-set-lens.js.map +1 -0
- package/dist/tools/cinemachine-set-noise.d.ts +2 -0
- package/dist/tools/cinemachine-set-noise.js +31 -0
- package/dist/tools/cinemachine-set-noise.js.map +1 -0
- package/dist/tools/cinemachine-set-targets.d.ts +2 -0
- package/dist/tools/cinemachine-set-targets.js +30 -0
- package/dist/tools/cinemachine-set-targets.js.map +1 -0
- package/dist/tools/console-log.js +2 -2
- package/dist/tools/console-log.js.map +1 -1
- package/dist/tools/constraint-add.d.ts +2 -0
- package/dist/tools/constraint-add.js +85 -0
- package/dist/tools/constraint-add.js.map +1 -0
- package/dist/tools/dependencies.d.ts +2 -0
- package/dist/tools/dependencies.js +76 -0
- package/dist/tools/dependencies.js.map +1 -0
- package/dist/tools/editor-add-tag.js +2 -3
- package/dist/tools/editor-add-tag.js.map +1 -1
- package/dist/tools/editor-clear-history.d.ts +2 -0
- package/dist/tools/editor-clear-history.js +25 -0
- package/dist/tools/editor-clear-history.js.map +1 -0
- package/dist/tools/editor-get-layers.js +3 -3
- package/dist/tools/editor-get-layers.js.map +1 -1
- package/dist/tools/editor-get-tags.js +2 -2
- package/dist/tools/editor-get-tags.js.map +1 -1
- package/dist/tools/editor-redo.js +2 -3
- package/dist/tools/editor-redo.js.map +1 -1
- package/dist/tools/editor-undo-history.d.ts +2 -0
- package/dist/tools/editor-undo-history.js +21 -0
- package/dist/tools/editor-undo-history.js.map +1 -0
- package/dist/tools/editor-undo.js +3 -3
- package/dist/tools/editor-undo.js.map +1 -1
- package/dist/tools/editorprefs-delete.d.ts +2 -0
- package/dist/tools/editorprefs-delete.js +23 -0
- package/dist/tools/editorprefs-delete.js.map +1 -0
- package/dist/tools/editorprefs-get.d.ts +2 -0
- package/dist/tools/editorprefs-get.js +28 -0
- package/dist/tools/editorprefs-get.js.map +1 -0
- package/dist/tools/editorprefs-set.d.ts +2 -0
- package/dist/tools/editorprefs-set.js +33 -0
- package/dist/tools/editorprefs-set.js.map +1 -0
- package/dist/tools/find-references.js +24 -4
- package/dist/tools/find-references.js.map +1 -1
- package/dist/tools/frame-debugger.d.ts +2 -0
- package/dist/tools/frame-debugger.js +48 -0
- package/dist/tools/frame-debugger.js.map +1 -0
- package/dist/tools/gameobject-modify.js +69 -2
- package/dist/tools/gameobject-modify.js.map +1 -1
- package/dist/tools/gate-budget-estimate.js +2 -1
- package/dist/tools/gate-budget-estimate.js.map +1 -1
- package/dist/tools/hub-available-releases.d.ts +2 -0
- package/dist/tools/hub-available-releases.js +23 -0
- package/dist/tools/hub-available-releases.js.map +1 -0
- package/dist/tools/hub-get-install-path.d.ts +2 -0
- package/dist/tools/hub-get-install-path.js +20 -0
- package/dist/tools/hub-get-install-path.js.map +1 -0
- package/dist/tools/hub-install-editor.d.ts +2 -0
- package/dist/tools/hub-install-editor.js +47 -0
- package/dist/tools/hub-install-editor.js.map +1 -0
- package/dist/tools/hub-install-modules.d.ts +2 -0
- package/dist/tools/hub-install-modules.js +44 -0
- package/dist/tools/hub-install-modules.js.map +1 -0
- package/dist/tools/hub-list-editors.d.ts +2 -0
- package/dist/tools/hub-list-editors.js +25 -0
- package/dist/tools/hub-list-editors.js.map +1 -0
- package/dist/tools/hub-set-install-path.d.ts +2 -0
- package/dist/tools/hub-set-install-path.js +30 -0
- package/dist/tools/hub-set-install-path.js.map +1 -0
- package/dist/tools/impact-preview.js +2 -2
- package/dist/tools/impact-preview.js.map +1 -1
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.js +534 -24
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/light-add.d.ts +2 -0
- package/dist/tools/light-add.js +73 -0
- package/dist/tools/light-add.js.map +1 -0
- package/dist/tools/light-modify.d.ts +2 -0
- package/dist/tools/light-modify.js +36 -0
- package/dist/tools/light-modify.js.map +1 -0
- package/dist/tools/light-set.d.ts +2 -0
- package/dist/tools/light-set.js +54 -0
- package/dist/tools/light-set.js.map +1 -0
- package/dist/tools/list-assets-of-type.d.ts +2 -0
- package/dist/tools/list-assets-of-type.js +54 -0
- package/dist/tools/list-assets-of-type.js.map +1 -0
- package/dist/tools/lod-add-level.d.ts +2 -0
- package/dist/tools/lod-add-level.js +66 -0
- package/dist/tools/lod-add-level.js.map +1 -0
- package/dist/tools/lod-group-configure.d.ts +2 -0
- package/dist/tools/lod-group-configure.js +64 -0
- package/dist/tools/lod-group-configure.js.map +1 -0
- package/dist/tools/manage-tools.js +7 -5
- package/dist/tools/manage-tools.js.map +1 -1
- package/dist/tools/memory-snapshot-capture.d.ts +2 -0
- package/dist/tools/memory-snapshot-capture.js +61 -0
- package/dist/tools/memory-snapshot-capture.js.map +1 -0
- package/dist/tools/mutation-explain.js +2 -2
- package/dist/tools/mutation-explain.js.map +1 -1
- package/dist/tools/playerprefs-delete.d.ts +2 -0
- package/dist/tools/playerprefs-delete.js +24 -0
- package/dist/tools/playerprefs-delete.js.map +1 -0
- package/dist/tools/playerprefs-get.d.ts +2 -0
- package/dist/tools/playerprefs-get.js +28 -0
- package/dist/tools/playerprefs-get.js.map +1 -0
- package/dist/tools/playerprefs-set.d.ts +2 -0
- package/dist/tools/playerprefs-set.js +37 -0
- package/dist/tools/playerprefs-set.js.map +1 -0
- package/dist/tools/profiler-capture-frame.d.ts +2 -0
- package/dist/tools/profiler-capture-frame.js +75 -0
- package/dist/tools/profiler-capture-frame.js.map +1 -0
- package/dist/tools/profiler-clear-data.js +1 -2
- package/dist/tools/profiler-clear-data.js.map +1 -1
- package/dist/tools/profiler-enable-module.js +4 -5
- package/dist/tools/profiler-enable-module.js.map +1 -1
- package/dist/tools/profiler-get-status.js +5 -6
- package/dist/tools/profiler-get-status.js.map +1 -1
- package/dist/tools/profiler-load-data.js +4 -5
- package/dist/tools/profiler-load-data.js.map +1 -1
- package/dist/tools/profiler-save-data.js +3 -3
- package/dist/tools/profiler-save-data.js.map +1 -1
- package/dist/tools/profiler-set-config.js +5 -5
- package/dist/tools/profiler-set-config.js.map +1 -1
- package/dist/tools/profiler-start.js +4 -4
- package/dist/tools/profiler-start.js.map +1 -1
- package/dist/tools/profiler-stop.js +2 -3
- package/dist/tools/profiler-stop.js.map +1 -1
- package/dist/tools/read-asset.js +21 -3
- package/dist/tools/read-asset.js.map +1 -1
- package/dist/tools/reflection-probe-bake.d.ts +2 -0
- package/dist/tools/reflection-probe-bake.js +47 -0
- package/dist/tools/reflection-probe-bake.js.map +1 -0
- package/dist/tools/reflection-probe-get.d.ts +2 -0
- package/dist/tools/reflection-probe-get.js +19 -0
- package/dist/tools/reflection-probe-get.js.map +1 -0
- package/dist/tools/reimport-package.d.ts +2 -0
- package/dist/tools/reimport-package.js +53 -0
- package/dist/tools/reimport-package.js.map +1 -0
- package/dist/tools/scan-paths.js +19 -0
- package/dist/tools/scan-paths.js.map +1 -1
- package/dist/tools/scene-focus.js +1 -1
- package/dist/tools/scene-focus.js.map +1 -1
- package/dist/tools/scene-get-data.js +31 -13
- package/dist/tools/scene-get-data.js.map +1 -1
- package/dist/tools/scene-get-dirty-summary.js +1 -1
- package/dist/tools/scene-get-dirty-summary.js.map +1 -1
- package/dist/tools/sceneview-get-camera.d.ts +2 -0
- package/dist/tools/sceneview-get-camera.js +16 -0
- package/dist/tools/sceneview-get-camera.js.map +1 -0
- package/dist/tools/sceneview-set-camera.d.ts +2 -0
- package/dist/tools/sceneview-set-camera.js +58 -0
- package/dist/tools/sceneview-set-camera.js.map +1 -0
- package/dist/tools/script-write.js +2 -2
- package/dist/tools/script-write.js.map +1 -1
- package/dist/tools/scriptableobject-create.d.ts +2 -0
- package/dist/tools/scriptableobject-create.js +86 -0
- package/dist/tools/scriptableobject-create.js.map +1 -0
- package/dist/tools/search-assets.js +20 -3
- package/dist/tools/search-assets.js.map +1 -1
- package/dist/tools/settings-get-lighting.js +3 -4
- package/dist/tools/settings-get-lighting.js.map +1 -1
- package/dist/tools/settings-get-player.js +2 -2
- package/dist/tools/settings-get-player.js.map +1 -1
- package/dist/tools/settings-get-quality.js +1 -2
- package/dist/tools/settings-get-quality.js.map +1 -1
- package/dist/tools/settings-get-render-pipeline.d.ts +2 -0
- package/dist/tools/settings-get-render-pipeline.js +19 -0
- package/dist/tools/settings-get-render-pipeline.js.map +1 -0
- package/dist/tools/settings-get-time.d.ts +2 -0
- package/dist/tools/settings-get-time.js +18 -0
- package/dist/tools/settings-get-time.js.map +1 -0
- package/dist/tools/settings-set-lighting.js +5 -5
- package/dist/tools/settings-set-lighting.js.map +1 -1
- package/dist/tools/settings-set-physics.js +2 -2
- package/dist/tools/settings-set-physics.js.map +1 -1
- package/dist/tools/settings-set-player.js +2 -2
- package/dist/tools/settings-set-player.js.map +1 -1
- package/dist/tools/settings-set-quality-level.d.ts +2 -0
- package/dist/tools/settings-set-quality-level.js +44 -0
- package/dist/tools/settings-set-quality-level.js.map +1 -0
- package/dist/tools/settings-set-quality.js +2 -2
- package/dist/tools/settings-set-quality.js.map +1 -1
- package/dist/tools/settings-set-time.d.ts +2 -0
- package/dist/tools/settings-set-time.js +53 -0
- package/dist/tools/settings-set-time.js.map +1 -0
- package/dist/tools/shader-get-data.js +3 -3
- package/dist/tools/shader-get-data.js.map +1 -1
- package/dist/tools/shader-graph-create.d.ts +2 -0
- package/dist/tools/shader-graph-create.js +40 -0
- package/dist/tools/shader-graph-create.js.map +1 -0
- package/dist/tools/shader-graph-node-add.d.ts +2 -0
- package/dist/tools/shader-graph-node-add.js +50 -0
- package/dist/tools/shader-graph-node-add.js.map +1 -0
- package/dist/tools/shader-graph-node-connect.d.ts +2 -0
- package/dist/tools/shader-graph-node-connect.js +60 -0
- package/dist/tools/shader-graph-node-connect.js.map +1 -0
- package/dist/tools/shader-graph-open.d.ts +2 -0
- package/dist/tools/shader-graph-open.js +29 -0
- package/dist/tools/shader-graph-open.js.map +1 -0
- package/dist/tools/skybox-get.d.ts +2 -0
- package/dist/tools/skybox-get.js +13 -0
- package/dist/tools/skybox-get.js.map +1 -0
- package/dist/tools/skybox-set.d.ts +2 -0
- package/dist/tools/skybox-set.js +34 -0
- package/dist/tools/skybox-set.js.map +1 -0
- package/dist/tools/spriteatlas-add-packable.d.ts +2 -0
- package/dist/tools/spriteatlas-add-packable.js +40 -0
- package/dist/tools/spriteatlas-add-packable.js.map +1 -0
- package/dist/tools/spriteatlas-create.d.ts +2 -0
- package/dist/tools/spriteatlas-create.js +41 -0
- package/dist/tools/spriteatlas-create.js.map +1 -0
- package/dist/tools/spriteatlas-delete.d.ts +2 -0
- package/dist/tools/spriteatlas-delete.js +32 -0
- package/dist/tools/spriteatlas-delete.js.map +1 -0
- package/dist/tools/spriteatlas-get.d.ts +2 -0
- package/dist/tools/spriteatlas-get.js +23 -0
- package/dist/tools/spriteatlas-get.js.map +1 -0
- package/dist/tools/spriteatlas-list.d.ts +2 -0
- package/dist/tools/spriteatlas-list.js +21 -0
- package/dist/tools/spriteatlas-list.js.map +1 -0
- package/dist/tools/spriteatlas-modify.d.ts +2 -0
- package/dist/tools/spriteatlas-modify.js +55 -0
- package/dist/tools/spriteatlas-modify.js.map +1 -0
- package/dist/tools/spriteatlas-remove-packable.d.ts +2 -0
- package/dist/tools/spriteatlas-remove-packable.js +39 -0
- package/dist/tools/spriteatlas-remove-packable.js.map +1 -0
- package/dist/tools/terrain-create.d.ts +2 -0
- package/dist/tools/terrain-create.js +73 -0
- package/dist/tools/terrain-create.js.map +1 -0
- package/dist/tools/terrain-paint-layer.d.ts +2 -0
- package/dist/tools/terrain-paint-layer.js +85 -0
- package/dist/tools/terrain-paint-layer.js.map +1 -0
- package/dist/tools/terrain-place-trees.d.ts +2 -0
- package/dist/tools/terrain-place-trees.js +92 -0
- package/dist/tools/terrain-place-trees.js.map +1 -0
- package/dist/tools/terrain-set-heights.d.ts +2 -0
- package/dist/tools/terrain-set-heights.js +68 -0
- package/dist/tools/terrain-set-heights.js.map +1 -0
- package/dist/tools/terrain-set-neighbors.d.ts +2 -0
- package/dist/tools/terrain-set-neighbors.js +65 -0
- package/dist/tools/terrain-set-neighbors.js.map +1 -0
- package/dist/tools/texture-get-importer.d.ts +2 -0
- package/dist/tools/texture-get-importer.js +25 -0
- package/dist/tools/texture-get-importer.js.map +1 -0
- package/dist/tools/texture-get.d.ts +2 -0
- package/dist/tools/texture-get.js +23 -0
- package/dist/tools/texture-get.js.map +1 -0
- package/dist/tools/texture-reimport.d.ts +2 -0
- package/dist/tools/texture-reimport.js +33 -0
- package/dist/tools/texture-reimport.js.map +1 -0
- package/dist/tools/texture-set-import.d.ts +2 -0
- package/dist/tools/texture-set-import.js +52 -0
- package/dist/tools/texture-set-import.js.map +1 -0
- package/dist/tools/tilemap-box-fill.d.ts +2 -0
- package/dist/tools/tilemap-box-fill.js +32 -0
- package/dist/tools/tilemap-box-fill.js.map +1 -0
- package/dist/tools/tilemap-create-rule-tile.d.ts +2 -0
- package/dist/tools/tilemap-create-rule-tile.js +39 -0
- package/dist/tools/tilemap-create-rule-tile.js.map +1 -0
- package/dist/tools/tilemap-create-tile-asset.d.ts +2 -0
- package/dist/tools/tilemap-create-tile-asset.js +35 -0
- package/dist/tools/tilemap-create-tile-asset.js.map +1 -0
- package/dist/tools/tilemap-create.d.ts +2 -0
- package/dist/tools/tilemap-create.js +32 -0
- package/dist/tools/tilemap-create.js.map +1 -0
- package/dist/tools/tilemap-set-tile.d.ts +2 -0
- package/dist/tools/tilemap-set-tile.js +33 -0
- package/dist/tools/tilemap-set-tile.js.map +1 -0
- package/dist/tools/timeline-clip-add.d.ts +2 -0
- package/dist/tools/timeline-clip-add.js +43 -0
- package/dist/tools/timeline-clip-add.js.map +1 -0
- package/dist/tools/timeline-create.d.ts +2 -0
- package/dist/tools/timeline-create.js +32 -0
- package/dist/tools/timeline-create.js.map +1 -0
- package/dist/tools/timeline-director-bind.d.ts +2 -0
- package/dist/tools/timeline-director-bind.js +34 -0
- package/dist/tools/timeline-director-bind.js.map +1 -0
- package/dist/tools/timeline-modify.d.ts +2 -0
- package/dist/tools/timeline-modify.js +44 -0
- package/dist/tools/timeline-modify.js.map +1 -0
- package/dist/tools/timeline-track-add.d.ts +2 -0
- package/dist/tools/timeline-track-add.js +37 -0
- package/dist/tools/timeline-track-add.js.map +1 -0
- package/dist/tools/ui-canvas-add.d.ts +2 -0
- package/dist/tools/ui-canvas-add.js +66 -0
- package/dist/tools/ui-canvas-add.js.map +1 -0
- package/dist/tools/ui-element-add.d.ts +2 -0
- package/dist/tools/ui-element-add.js +65 -0
- package/dist/tools/ui-element-add.js.map +1 -0
- package/dist/tools/ui-element-modify.d.ts +2 -0
- package/dist/tools/ui-element-modify.js +59 -0
- package/dist/tools/ui-element-modify.js.map +1 -0
- package/dist/tools/ui-layout-group-add.d.ts +2 -0
- package/dist/tools/ui-layout-group-add.js +80 -0
- package/dist/tools/ui-layout-group-add.js.map +1 -0
- package/dist/tools/validate-edit.js +22 -1
- package/dist/tools/validate-edit.js.map +1 -1
- package/dist/tools/vfx-block-edit.d.ts +2 -0
- package/dist/tools/vfx-block-edit.js +51 -0
- package/dist/tools/vfx-block-edit.js.map +1 -0
- package/dist/tools/vfx-list.d.ts +2 -0
- package/dist/tools/vfx-list.js +31 -0
- package/dist/tools/vfx-list.js.map +1 -0
- package/dist/tools/vfx-open.d.ts +2 -0
- package/dist/tools/vfx-open.js +29 -0
- package/dist/tools/vfx-open.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
// Unity Hub control — installed-editor discovery, available-releases feed,
|
|
2
|
+
// install deep link, and Hub CLI install-path management.
|
|
3
|
+
//
|
|
4
|
+
// This is a **self-contained** module: it uses only Node builtins
|
|
5
|
+
// (`node:fs`, `node:child_process`, `node:https`, `node:os`, `node:path`) and
|
|
6
|
+
// reuses the existing standalone TS discovery in `unity-install-discovery.ts`.
|
|
7
|
+
// It has **no** runtime dependency on anything under `/hub/` (the Tauri
|
|
8
|
+
// launcher) — the discovery roots, the Unity download-archive feed, and the
|
|
9
|
+
// `unityhub://` deep-link transport are the same *approaches* the Hub launcher
|
|
10
|
+
// uses, re-implemented independently here in TS. Provenance comments reference
|
|
11
|
+
// the Hub's Rust sources for developer context only (the same convention
|
|
12
|
+
// `unity-install-discovery.ts` already follows); no code coupling.
|
|
13
|
+
//
|
|
14
|
+
// The architecture is two layers, mirroring the pattern established in
|
|
15
|
+
// `dialog-dismiss.ts`:
|
|
16
|
+
// - **Pure functions** (`parseInstalledEditors`, `parseAvailableReleases`,
|
|
17
|
+
// `parseInstallPath`, `scanPlaybackEngines`, `resolveHubCliPath`,
|
|
18
|
+
// `listInstalledEditors`) — unit-tested with string/path fixtures.
|
|
19
|
+
// - **Side-effecting layer** (`getInstallPath`, `setInstallPath`,
|
|
20
|
+
// `openInstallDeepLink`, `fetchAvailableReleases`) — each takes an
|
|
21
|
+
// injectable runner/opener/fetcher defaulting to the real impl, so tests
|
|
22
|
+
// inject canned outputs without mocking `node:child_process`.
|
|
23
|
+
import { execFileSync } from "node:child_process";
|
|
24
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
25
|
+
import { get } from "node:https";
|
|
26
|
+
import { homedir } from "node:os";
|
|
27
|
+
import { join } from "node:path";
|
|
28
|
+
import { discoverUnityInstalls, scannedHubRoots, } from "./unity-install-discovery.js";
|
|
29
|
+
// ── Pure: playback-engine platform scan ────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Mapping from a Unity `Data/PlaybackEngines/<folder>` name to the friendly
|
|
32
|
+
* build-target label. Covers the Windows/macOS/Linux keys Unity ships on all
|
|
33
|
+
* hosts. Unknown folders fall back to the lowercased name so a new platform
|
|
34
|
+
* is never silently dropped. TS port of the Rust
|
|
35
|
+
* `friendly_playback_engine_name`.
|
|
36
|
+
*/
|
|
37
|
+
export function friendlyPlaybackEngineName(folder) {
|
|
38
|
+
switch (folder.toLowerCase()) {
|
|
39
|
+
case "androidplayer":
|
|
40
|
+
return "Android";
|
|
41
|
+
case "windowsstandalonesupport":
|
|
42
|
+
return "Win64";
|
|
43
|
+
case "linuxstandalonesupport":
|
|
44
|
+
case "linuxstandalone":
|
|
45
|
+
return "Linux64";
|
|
46
|
+
case "osxstandalonesupport":
|
|
47
|
+
case "osxstandalone":
|
|
48
|
+
return "OSX";
|
|
49
|
+
case "webglsupport":
|
|
50
|
+
case "webgl":
|
|
51
|
+
return "WebGL";
|
|
52
|
+
case "metrosupport":
|
|
53
|
+
return "UWP";
|
|
54
|
+
case "iossupport":
|
|
55
|
+
case "iphone-player":
|
|
56
|
+
return "iOS";
|
|
57
|
+
case "appletvsupport":
|
|
58
|
+
return "tvOS";
|
|
59
|
+
case "visionosplayer":
|
|
60
|
+
return "visionOS";
|
|
61
|
+
case "switchplayer":
|
|
62
|
+
case "switchsupport":
|
|
63
|
+
return "Switch";
|
|
64
|
+
case "ps4player":
|
|
65
|
+
case "ps5player":
|
|
66
|
+
return folder.toUpperCase();
|
|
67
|
+
default:
|
|
68
|
+
return folder;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the editor install's `Data/` folder. On macOS the editor lives
|
|
73
|
+
* inside `Unity.app/Contents/`; on Windows/Linux it sits in an `Editor/`
|
|
74
|
+
* subfolder (Hub layout) or as a sibling (source build). Returns null when no
|
|
75
|
+
* `Data/` directory exists. TS port of the Rust `editor_data_folder`.
|
|
76
|
+
*/
|
|
77
|
+
export function editorDataFolder(installDir) {
|
|
78
|
+
if (process.platform === "darwin") {
|
|
79
|
+
const candidate = join(installDir, "Unity.app", "Contents", "Data");
|
|
80
|
+
return existsSync(candidate) ? candidate : null;
|
|
81
|
+
}
|
|
82
|
+
const editorData = join(installDir, "Editor", "Data");
|
|
83
|
+
if (existsSync(editorData))
|
|
84
|
+
return editorData;
|
|
85
|
+
const siblingData = join(installDir, "Data");
|
|
86
|
+
return existsSync(siblingData) ? siblingData : null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Scan an editor install's `Data/PlaybackEngines/` directory and return the
|
|
90
|
+
* friendly platform names of every build target Unity shipped modules for.
|
|
91
|
+
* Returns an empty array when the install is missing the directory (a minimal
|
|
92
|
+
* / custom build). TS port of the Rust `scan_playback_engines`.
|
|
93
|
+
*/
|
|
94
|
+
export function scanPlaybackEngines(installDir) {
|
|
95
|
+
const dataFolder = editorDataFolder(installDir);
|
|
96
|
+
if (!dataFolder)
|
|
97
|
+
return [];
|
|
98
|
+
const playbackEngines = join(dataFolder, "PlaybackEngines");
|
|
99
|
+
let entries;
|
|
100
|
+
try {
|
|
101
|
+
entries = readdirSync(playbackEngines);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
const platforms = [];
|
|
107
|
+
for (const name of entries) {
|
|
108
|
+
const dirPath = join(playbackEngines, name);
|
|
109
|
+
try {
|
|
110
|
+
if (!statSync(dirPath).isDirectory())
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const friendly = friendlyPlaybackEngineName(name);
|
|
117
|
+
if (!platforms.includes(friendly))
|
|
118
|
+
platforms.push(friendly);
|
|
119
|
+
}
|
|
120
|
+
platforms.sort();
|
|
121
|
+
return platforms;
|
|
122
|
+
}
|
|
123
|
+
// ── Pure: release-stream inference ─────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Returns the Unity version's kind marker character (`a` / `b` / `f` / `p` /
|
|
126
|
+
* `c`) by scanning from the end and returning the last alphabetic character
|
|
127
|
+
* before the trailing digits. Returns `\0` for strings without a kind marker.
|
|
128
|
+
* TS port of the Rust `version_kind_marker`.
|
|
129
|
+
*/
|
|
130
|
+
function versionKindMarker(version) {
|
|
131
|
+
const chars = [...version];
|
|
132
|
+
let i = chars.length;
|
|
133
|
+
while (i > 0 && isAsciiDigit(chars[i - 1]))
|
|
134
|
+
i -= 1;
|
|
135
|
+
if (i > 0) {
|
|
136
|
+
const c = chars[i - 1];
|
|
137
|
+
if (isAsciiLetter(c))
|
|
138
|
+
return c.toLowerCase();
|
|
139
|
+
}
|
|
140
|
+
return "\0";
|
|
141
|
+
}
|
|
142
|
+
function isAsciiDigit(c) {
|
|
143
|
+
return c >= "0" && c <= "9";
|
|
144
|
+
}
|
|
145
|
+
function isAsciiLetter(c) {
|
|
146
|
+
return (c >= "a" && c <= "z") || (c >= "A" && c <= "Z");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Release stream inferred from the Unity version suffix. TS port of the Rust
|
|
150
|
+
* `release_type_for`.
|
|
151
|
+
*/
|
|
152
|
+
export function releaseTypeFor(version) {
|
|
153
|
+
const kind = versionKindMarker(version);
|
|
154
|
+
switch (kind) {
|
|
155
|
+
case "a":
|
|
156
|
+
return "Alpha";
|
|
157
|
+
case "b":
|
|
158
|
+
return "Beta";
|
|
159
|
+
case "f": {
|
|
160
|
+
const lower = version.toLowerCase();
|
|
161
|
+
// Known Unity LTS lines (min supported by the packages is 2022.3 LTS).
|
|
162
|
+
const isKnownLts = lower.startsWith("6000.0") ||
|
|
163
|
+
lower.startsWith("2022.3") ||
|
|
164
|
+
lower.startsWith("2021.3") ||
|
|
165
|
+
lower.startsWith("2020.3") ||
|
|
166
|
+
lower.startsWith("2019.4");
|
|
167
|
+
return isKnownLts ? "LTS" : "TECH";
|
|
168
|
+
}
|
|
169
|
+
default:
|
|
170
|
+
return "";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ── Pure: installed-editor discovery orchestration ─────────────────
|
|
174
|
+
/**
|
|
175
|
+
* List installed Unity editors by scanning the Hub install roots (+ `UNITY_HUB`
|
|
176
|
+
* env override), enriching each with build-target platforms and a release
|
|
177
|
+
* stream. `roots` is an optional test hook (forwarded to
|
|
178
|
+
* `discoverUnityInstalls`); when omitted the real machine roots are scanned.
|
|
179
|
+
*
|
|
180
|
+
* The primary discovery path is filesystem scanning (matches what the Hub
|
|
181
|
+
* launcher and `unity-install-discovery.ts` do). Never throws.
|
|
182
|
+
*/
|
|
183
|
+
export function listInstalledEditors(roots) {
|
|
184
|
+
const installs = discoverUnityInstalls(roots);
|
|
185
|
+
return installs.map((install) => {
|
|
186
|
+
// The version is the install folder name; the install dir is its parent.
|
|
187
|
+
// `discoverUnityInstalls` returns the executable path — derive the install
|
|
188
|
+
// folder so `scanPlaybackEngines` reads the right `Data/` dir.
|
|
189
|
+
const installDir = installDirFromExe(install.path);
|
|
190
|
+
return {
|
|
191
|
+
version: install.version,
|
|
192
|
+
path: install.path,
|
|
193
|
+
platforms: installDir ? scanPlaybackEngines(installDir) : [],
|
|
194
|
+
releaseType: releaseTypeFor(install.version),
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Derive the install root folder (the version-named dir under the Hub Editor
|
|
200
|
+
* root) from the Unity executable path returned by `discoverUnityInstalls`.
|
|
201
|
+
* Returns null when the path doesn't match the expected Hub layout.
|
|
202
|
+
*/
|
|
203
|
+
function installDirFromExe(exePath) {
|
|
204
|
+
// macOS: <install>/Unity.app/Contents/MacOS/Unity -> install is 3 up.
|
|
205
|
+
// Windows/Linux: <install>/Editor/Unity[.exe] -> install is 1 up.
|
|
206
|
+
if (process.platform === "darwin") {
|
|
207
|
+
// Walk up three levels from the executable.
|
|
208
|
+
const parts = exePath.split("/");
|
|
209
|
+
// Drop the trailing filename + MacOS + Contents + Unity.app.
|
|
210
|
+
if (parts.length >= 4)
|
|
211
|
+
return parts.slice(0, -3).join("/") || null;
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
// Windows/Linux: <install>/Editor/<binary>.
|
|
215
|
+
const parts = exePath.split(/[\\/]/);
|
|
216
|
+
if (parts.length >= 2)
|
|
217
|
+
return parts.slice(0, -2).join("/") || null;
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Parse the stdout of `Unity Hub --headless editors --installed`. Each line
|
|
222
|
+
* looks like `2022.3.0f1 , installed at C:\Program Files\Unity\...`. Lines that
|
|
223
|
+
* do not match are ignored. Pure (string in, list out) so it can be unit-tested
|
|
224
|
+
* against captured output.
|
|
225
|
+
*/
|
|
226
|
+
export function parseInstalledEditors(stdout) {
|
|
227
|
+
const editors = [];
|
|
228
|
+
const lines = stdout.split(/\r?\n/);
|
|
229
|
+
for (const line of lines) {
|
|
230
|
+
if (!line.trim())
|
|
231
|
+
continue;
|
|
232
|
+
// `version , installed at PATH` — the comma is optional in some Hub builds.
|
|
233
|
+
const match = line.match(/^([\d.]+\w*)\s*,?\s*installed at\s+(.+)$/i);
|
|
234
|
+
if (match) {
|
|
235
|
+
editors.push({ version: match[1].trim(), path: match[2].trim() });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return editors;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Parse the stdout of `Unity Hub --headless install-path`. The Hub normally
|
|
242
|
+
* prints the bare path on its own line; some builds prefix it with a label
|
|
243
|
+
* like `Default install path: /path`. Returns the trimmed path, or null when
|
|
244
|
+
* the output is empty/unparseable. Pure.
|
|
245
|
+
*
|
|
246
|
+
* Strip-rule: a `Label: <path>` prefix is removed only when the text before
|
|
247
|
+
* the colon is a plain word/phrase (alphanumerics + spaces, no path
|
|
248
|
+
* separators) — so a Windows drive path `C:\Program Files\...` (colon at
|
|
249
|
+
* index 1, left side `C`) is left intact.
|
|
250
|
+
*/
|
|
251
|
+
export function parseInstallPath(stdout) {
|
|
252
|
+
const trimmed = stdout.trim();
|
|
253
|
+
if (!trimmed)
|
|
254
|
+
return null;
|
|
255
|
+
const lines = trimmed.split(/\r?\n/).filter((l) => l.trim());
|
|
256
|
+
const last = lines[lines.length - 1];
|
|
257
|
+
let candidate = last.trim();
|
|
258
|
+
const colonIdx = candidate.indexOf(":");
|
|
259
|
+
if (colonIdx !== -1) {
|
|
260
|
+
const left = candidate.slice(0, colonIdx);
|
|
261
|
+
// A label is alphanumerics + spaces only; a Windows drive letter is a
|
|
262
|
+
// single char, and a real path always contains a separator somewhere in
|
|
263
|
+
// the left side too. Only strip when the left side is a clean label.
|
|
264
|
+
if (left.length > 1 && /^[A-Za-z0-9 ]+$/.test(left)) {
|
|
265
|
+
candidate = candidate.slice(colonIdx + 1).trim();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return candidate || null;
|
|
269
|
+
}
|
|
270
|
+
// ── Pure: Unity Hub CLI binary resolution ──────────────────────────
|
|
271
|
+
let hubCliPathCache;
|
|
272
|
+
/**
|
|
273
|
+
* Per-platform default Unity Hub binary locations. The Hub registers itself as
|
|
274
|
+
* the system handler for `unityhub://`, but the headless CLI needs the binary
|
|
275
|
+
* directly. Honors the `UNITY_HUB_PATH` env var (highest precedence). Returns
|
|
276
|
+
* null when the candidate does not exist on disk.
|
|
277
|
+
*
|
|
278
|
+
* macOS: `/Applications/Unity Hub.app/Contents/MacOS/Unity Hub`
|
|
279
|
+
* Windows: `%ProgramFiles%\Unity Hub\Unity Hub.exe`
|
|
280
|
+
* Linux: `$HOME/Unity Hub/Unity Hub` (Hub ships as an AppImage; the extracted
|
|
281
|
+
* binary path is the common install location).
|
|
282
|
+
*/
|
|
283
|
+
export function resolveHubCliPath() {
|
|
284
|
+
if (hubCliPathCache !== undefined)
|
|
285
|
+
return hubCliPathCache;
|
|
286
|
+
const envPath = process.env.UNITY_HUB_PATH;
|
|
287
|
+
const candidates = [];
|
|
288
|
+
if (envPath)
|
|
289
|
+
candidates.push(envPath);
|
|
290
|
+
if (process.platform === "darwin") {
|
|
291
|
+
candidates.push("/Applications/Unity Hub.app/Contents/MacOS/Unity Hub");
|
|
292
|
+
}
|
|
293
|
+
else if (process.platform === "win32") {
|
|
294
|
+
const programFiles = process.env.ProgramFiles || join("C:", "Program Files");
|
|
295
|
+
candidates.push(join(programFiles, "Unity Hub", "Unity Hub.exe"));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
candidates.push(join(homedir(), "Unity Hub", "Unity Hub"));
|
|
299
|
+
}
|
|
300
|
+
const found = candidates.find((p) => {
|
|
301
|
+
try {
|
|
302
|
+
return existsSync(p);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
hubCliPathCache = found ?? null;
|
|
309
|
+
return hubCliPathCache;
|
|
310
|
+
}
|
|
311
|
+
/** Test-only: reset the cached Hub CLI path. */
|
|
312
|
+
export function _resetHubCliPathCacheForTests() {
|
|
313
|
+
hubCliPathCache = undefined;
|
|
314
|
+
}
|
|
315
|
+
// ── Pure: available-releases feed parsing ──────────────────────────
|
|
316
|
+
/**
|
|
317
|
+
* Map a raw Unity archive `stream` string to our label. Unknown values fall
|
|
318
|
+
* back to "TECH" (a conservative stable-ish default) so a future Unity string
|
|
319
|
+
* is never dropped. Mirrors the Rust `ReleaseStream::from_unity_str`.
|
|
320
|
+
*/
|
|
321
|
+
export function streamFromUnityStr(raw) {
|
|
322
|
+
switch (raw) {
|
|
323
|
+
case "LTS":
|
|
324
|
+
return "LTS";
|
|
325
|
+
case "SUPPORTED":
|
|
326
|
+
return "Supported";
|
|
327
|
+
case "TECH":
|
|
328
|
+
return "TECH";
|
|
329
|
+
case "BETA":
|
|
330
|
+
return "Beta";
|
|
331
|
+
case "ALPHA":
|
|
332
|
+
return "Alpha";
|
|
333
|
+
default:
|
|
334
|
+
return "TECH";
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Extract the changeset hash from a `unityhub://<version>/<changeset>` deep
|
|
339
|
+
* link. Returns null when the link is missing or malformed. TS port of the
|
|
340
|
+
* Rust `extract_changeset`.
|
|
341
|
+
*/
|
|
342
|
+
export function extractChangeset(deepLink) {
|
|
343
|
+
if (!deepLink)
|
|
344
|
+
return null;
|
|
345
|
+
const afterScheme = deepLink.startsWith("unityhub://")
|
|
346
|
+
? deepLink.slice("unityhub://".length)
|
|
347
|
+
: null;
|
|
348
|
+
if (afterScheme === null)
|
|
349
|
+
return null;
|
|
350
|
+
// The path is `<version>/<changeset>`. Only return a changeset when there is
|
|
351
|
+
// a slash separator with a non-empty trailing segment — a bare
|
|
352
|
+
// `unityhub://<version>` carries no changeset (older Hub builds emit these).
|
|
353
|
+
const slashIdx = afterScheme.lastIndexOf("/");
|
|
354
|
+
if (slashIdx === -1)
|
|
355
|
+
return null;
|
|
356
|
+
const cs = afterScheme.slice(slashIdx + 1);
|
|
357
|
+
return cs.length > 0 ? cs : null;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Normalize the archive feed's full ISO timestamp (`2026-06-17T15:09:23.805Z`)
|
|
361
|
+
* down to the date portion (`2026-06-17`). Passes through values that don't
|
|
362
|
+
* look like an ISO date unchanged. TS port of the Rust `normalize_release_date`.
|
|
363
|
+
*/
|
|
364
|
+
export function normalizeReleaseDate(raw) {
|
|
365
|
+
if (!raw)
|
|
366
|
+
return null;
|
|
367
|
+
if (raw.length >= 10 && raw[4] === "-" && raw[7] === "-") {
|
|
368
|
+
return raw.slice(0, 10);
|
|
369
|
+
}
|
|
370
|
+
return raw;
|
|
371
|
+
}
|
|
372
|
+
function releaseNotesUrl(version) {
|
|
373
|
+
return `https://unity.com/releases/editor/whats-new/${version}`;
|
|
374
|
+
}
|
|
375
|
+
/** Find the index of the closing `"` of a JSON string literal body. Honors `\"`. */
|
|
376
|
+
function findSegmentClose(s) {
|
|
377
|
+
let i = 0;
|
|
378
|
+
while (i < s.length) {
|
|
379
|
+
if (s[i] === "\\") {
|
|
380
|
+
i += 2;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (s[i] === '"')
|
|
384
|
+
return i;
|
|
385
|
+
i += 1;
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Parse the Next.js RSC payload embedded in the Unity download-archive page
|
|
391
|
+
* HTML and return the list of releases. The page emits the GraphQL result as
|
|
392
|
+
* one `self.__next_f.push([1,"31:<json>"])` script segment; we locate that
|
|
393
|
+
* segment, JSON-decode the string literal (un-escaping the inner JSON), strip
|
|
394
|
+
* the `31:` RSC prefix, and deserialize the result. Returns null when no
|
|
395
|
+
* releases segment is found. TS port of the Rust `parse_archive_payload`.
|
|
396
|
+
*
|
|
397
|
+
* Pure (string in, list out) so it can be unit-tested against a captured
|
|
398
|
+
* fixture without touching the network.
|
|
399
|
+
*/
|
|
400
|
+
export function parseArchivePayload(html) {
|
|
401
|
+
const marker = 'self.__next_f.push([1,"';
|
|
402
|
+
let i = 0;
|
|
403
|
+
while (true) {
|
|
404
|
+
const rel = html.slice(i).indexOf(marker);
|
|
405
|
+
if (rel === -1)
|
|
406
|
+
break;
|
|
407
|
+
const abs = i + rel;
|
|
408
|
+
const start = abs + marker.length;
|
|
409
|
+
const end = findSegmentClose(html.slice(start));
|
|
410
|
+
if (end === null)
|
|
411
|
+
break;
|
|
412
|
+
const rawLiteral = html.slice(start, start + end);
|
|
413
|
+
i = start + end;
|
|
414
|
+
// Decode the JSON string literal.
|
|
415
|
+
let decoded;
|
|
416
|
+
try {
|
|
417
|
+
decoded = JSON.parse(`"${rawLiteral}"`);
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const jsonStr = decoded.startsWith("31:") ? decoded.slice(3) : null;
|
|
423
|
+
if (!jsonStr || !jsonStr.includes("getUnityReleases"))
|
|
424
|
+
continue;
|
|
425
|
+
let response;
|
|
426
|
+
try {
|
|
427
|
+
response = JSON.parse(jsonStr);
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
const edges = response.getUnityReleases?.edges;
|
|
433
|
+
if (!Array.isArray(edges))
|
|
434
|
+
continue;
|
|
435
|
+
const entries = edges.map((e) => {
|
|
436
|
+
const node = e.node;
|
|
437
|
+
return {
|
|
438
|
+
version: node.version,
|
|
439
|
+
stream: streamFromUnityStr(node.stream),
|
|
440
|
+
releaseDate: normalizeReleaseDate(node.releaseDate),
|
|
441
|
+
releaseNotesUrl: releaseNotesUrl(node.version),
|
|
442
|
+
changeset: extractChangeset(node.unityHubDeepLink),
|
|
443
|
+
};
|
|
444
|
+
});
|
|
445
|
+
// Sort newest-first by date; entries without a date sort last.
|
|
446
|
+
entries.sort((a, b) => {
|
|
447
|
+
const ad = a.releaseDate ?? "";
|
|
448
|
+
const bd = b.releaseDate ?? "";
|
|
449
|
+
return bd < ad ? -1 : bd > ad ? 1 : 0;
|
|
450
|
+
});
|
|
451
|
+
return entries;
|
|
452
|
+
}
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
// ── Bundled offline snapshot (fallback when the network is unreachable) ──
|
|
456
|
+
/**
|
|
457
|
+
* Bundled snapshot of recent Unity release streams. NOT the primary source —
|
|
458
|
+
* the offline / network-failure fallback served when the live archive fetch
|
|
459
|
+
* fails. Kept small and corrected to the right streams so we never mislabel a
|
|
460
|
+
* version. Mirrors the Rust `snapshot_entries` (newest-first).
|
|
461
|
+
*/
|
|
462
|
+
export function snapshotReleases() {
|
|
463
|
+
return [
|
|
464
|
+
{ version: "6000.4.12f1", stream: "Supported", releaseDate: "2026-06-17", releaseNotesUrl: releaseNotesUrl("6000.4.12f1"), changeset: "3ca267ce8005" },
|
|
465
|
+
{ version: "6000.3.18f1", stream: "LTS", releaseDate: "2026-06-17", releaseNotesUrl: releaseNotesUrl("6000.3.18f1"), changeset: "5ebeb53e4c07" },
|
|
466
|
+
{ version: "6000.5.0f1", stream: "Supported", releaseDate: "2026-06-15", releaseNotesUrl: releaseNotesUrl("6000.5.0f1"), changeset: "88b47c5e7076" },
|
|
467
|
+
{ version: "6000.0.32f1", stream: "TECH", releaseDate: "2026-05-14", releaseNotesUrl: releaseNotesUrl("6000.0.32f1"), changeset: null },
|
|
468
|
+
{ version: "6000.3.10f1", stream: "LTS", releaseDate: "2026-02-25", releaseNotesUrl: releaseNotesUrl("6000.3.10f1"), changeset: null },
|
|
469
|
+
{ version: "6000.3.0f1", stream: "LTS", releaseDate: "2025-12-04", releaseNotesUrl: releaseNotesUrl("6000.3.0f1"), changeset: null },
|
|
470
|
+
{ version: "2022.3.62f2", stream: "LTS", releaseDate: "2025-10-03", releaseNotesUrl: releaseNotesUrl("2022.3.62f2"), changeset: "7670c08855a9" },
|
|
471
|
+
];
|
|
472
|
+
}
|
|
473
|
+
/** Default Hub CLI runner — `execFileSync` against the resolved Hub binary. */
|
|
474
|
+
function defaultHubCliRunner(args, opts) {
|
|
475
|
+
const hubPath = resolveHubCliPath();
|
|
476
|
+
if (!hubPath) {
|
|
477
|
+
return {
|
|
478
|
+
stdout: "",
|
|
479
|
+
stderr: "",
|
|
480
|
+
exitCode: -1, // signals "not found"; caller maps to `hub_cli_not_found`.
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
// Try the modern (3.x) `--headless` form, then the legacy (2.x) `-- --headless`.
|
|
484
|
+
const strategies = [
|
|
485
|
+
{ name: "modern", args: ["--headless", ...args] },
|
|
486
|
+
{ name: "legacy", args: ["--", "--headless", ...args] },
|
|
487
|
+
];
|
|
488
|
+
for (const strategy of strategies) {
|
|
489
|
+
try {
|
|
490
|
+
const stdout = execFileSync(hubPath, strategy.args, {
|
|
491
|
+
timeout: opts?.timeoutMs ?? 30_000,
|
|
492
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
493
|
+
encoding: "utf8",
|
|
494
|
+
windowsHide: true,
|
|
495
|
+
});
|
|
496
|
+
return { stdout, stderr: "", exitCode: 0 };
|
|
497
|
+
}
|
|
498
|
+
catch (err) {
|
|
499
|
+
const e = err;
|
|
500
|
+
// ENOENT → Hub gone; surface as not-found.
|
|
501
|
+
if (e.message && /ENOENT/.test(e.message)) {
|
|
502
|
+
return { stdout: "", stderr: "", exitCode: -1 };
|
|
503
|
+
}
|
|
504
|
+
// Non-zero exit but with stdout data — some Hub builds return data despite
|
|
505
|
+
// a non-zero status. Use it if present.
|
|
506
|
+
const out = (e.stdout ?? "").toString().trim();
|
|
507
|
+
if (out) {
|
|
508
|
+
return { stdout: out, stderr: (e.stderr ?? "").toString(), exitCode: e.status ?? 0 };
|
|
509
|
+
}
|
|
510
|
+
// Otherwise try the next strategy.
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return { stdout: "", stderr: "all strategies failed", exitCode: 1 };
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Get the default Unity editor install directory. Tries the Hub CLI
|
|
517
|
+
* (`install-path`) first; falls back to inferring from the Hub install roots
|
|
518
|
+
* (`scannedHubRoots`) when the CLI is unavailable. The `roots` override is a
|
|
519
|
+
* test hook forwarded to the filesystem fallback.
|
|
520
|
+
*/
|
|
521
|
+
export function getInstallPath(opts) {
|
|
522
|
+
const runner = opts?.runHubCli ?? defaultHubCliRunner;
|
|
523
|
+
const result = runner(["install-path"]);
|
|
524
|
+
if (result.exitCode === -1) {
|
|
525
|
+
// Hub CLI not found — fall back to filesystem inference.
|
|
526
|
+
const roots = opts?.roots ?? scannedHubRoots();
|
|
527
|
+
if (roots.length > 0) {
|
|
528
|
+
return { path: roots[0], error: null, source: "filesystem" };
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
path: null,
|
|
532
|
+
error: {
|
|
533
|
+
code: "hub_cli_not_found",
|
|
534
|
+
message: "Unity Hub CLI not found. Set UNITY_HUB_PATH to the Unity Hub binary " +
|
|
535
|
+
"(e.g. '/Applications/Unity Hub.app/Contents/MacOS/Unity Hub' on macOS, " +
|
|
536
|
+
"'C:\\Program Files\\Unity Hub\\Unity Hub.exe' on Windows).",
|
|
537
|
+
},
|
|
538
|
+
source: "none",
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
const parsed = parseInstallPath(result.stdout);
|
|
542
|
+
if (!parsed) {
|
|
543
|
+
return {
|
|
544
|
+
path: null,
|
|
545
|
+
error: {
|
|
546
|
+
code: "install_path_unparseable",
|
|
547
|
+
message: `Could not parse install path from Hub CLI output: ${result.stdout || result.stderr}`,
|
|
548
|
+
},
|
|
549
|
+
source: "hub-cli",
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
return { path: parsed, error: null, source: "hub-cli" };
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Set the default Unity editor install directory via the Hub CLI
|
|
556
|
+
* (`install-path --set <path>`). This is the one Hub operation the
|
|
557
|
+
* `unityhub://` deep-link transport cannot perform, so it genuinely requires
|
|
558
|
+
* the headless CLI. Returns a structured `hub_cli_not_found` error when the Hub
|
|
559
|
+
* binary is absent.
|
|
560
|
+
*/
|
|
561
|
+
export function setInstallPath(path, opts) {
|
|
562
|
+
const runner = opts?.runHubCli ?? defaultHubCliRunner;
|
|
563
|
+
const result = runner(["install-path", "--set", path]);
|
|
564
|
+
if (result.exitCode === -1) {
|
|
565
|
+
return {
|
|
566
|
+
success: false,
|
|
567
|
+
error: {
|
|
568
|
+
code: "hub_cli_not_found",
|
|
569
|
+
message: "Unity Hub CLI not found. Set UNITY_HUB_PATH to the Unity Hub binary " +
|
|
570
|
+
"(e.g. '/Applications/Unity Hub.app/Contents/MacOS/Unity Hub' on macOS, " +
|
|
571
|
+
"'C:\\Program Files\\Unity Hub\\Unity Hub.exe' on Windows).",
|
|
572
|
+
},
|
|
573
|
+
output: "",
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
if (result.exitCode !== 0) {
|
|
577
|
+
return {
|
|
578
|
+
success: false,
|
|
579
|
+
error: {
|
|
580
|
+
code: "set_install_path_failed",
|
|
581
|
+
message: result.stderr || `Hub CLI exited with code ${result.exitCode}`,
|
|
582
|
+
},
|
|
583
|
+
output: result.stdout,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
return { success: true, error: null, output: result.stdout };
|
|
587
|
+
}
|
|
588
|
+
/** Default URL opener — dispatches to the platform handler. */
|
|
589
|
+
function defaultUrlOpener(url) {
|
|
590
|
+
let binary;
|
|
591
|
+
let args;
|
|
592
|
+
if (process.platform === "win32") {
|
|
593
|
+
binary = "cmd";
|
|
594
|
+
args = ["/c", "start", "", url];
|
|
595
|
+
}
|
|
596
|
+
else if (process.platform === "darwin") {
|
|
597
|
+
binary = "open";
|
|
598
|
+
args = [url];
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
binary = "xdg-open";
|
|
602
|
+
args = [url];
|
|
603
|
+
}
|
|
604
|
+
try {
|
|
605
|
+
execFileSync(binary, args, { encoding: "utf8", windowsHide: true });
|
|
606
|
+
return { opened: true, error: null };
|
|
607
|
+
}
|
|
608
|
+
catch (err) {
|
|
609
|
+
const e = err;
|
|
610
|
+
return { opened: false, error: e.message ?? String(err) };
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Build the `unityhub://` deep link for a release. When a changeset is
|
|
615
|
+
* available the link is `unityhub://<version>/<changeset>`, which the Hub
|
|
616
|
+
* resolves to the exact build; without one it is `unityhub://<version>`. Older
|
|
617
|
+
* Hub versions may ignore a changeset-less link, so the caller should fall back
|
|
618
|
+
* to the release-notes URL in that case.
|
|
619
|
+
*/
|
|
620
|
+
export function buildInstallDeepLink(version, changeset) {
|
|
621
|
+
const v = version.trim();
|
|
622
|
+
const cs = changeset && changeset.trim().length > 0 ? changeset.trim() : null;
|
|
623
|
+
return cs ? `unityhub://${v}/${cs}` : `unityhub://${v}`;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Open Unity Hub at its install dialog for `<version>` by firing the
|
|
627
|
+
* `unityhub://` deep link via the OS URL handler. The Hub must be installed
|
|
628
|
+
* and registered as the system handler for the scheme. Single-instance, real
|
|
629
|
+
* progress bar — the install happens inside the Hub, outside this process.
|
|
630
|
+
* There is no in-app completion detection; the caller should re-list editors
|
|
631
|
+
* after the Hub finishes.
|
|
632
|
+
*/
|
|
633
|
+
export function openInstallDeepLink(version, changeset, opts) {
|
|
634
|
+
if (!version.trim()) {
|
|
635
|
+
return {
|
|
636
|
+
deepLink: "",
|
|
637
|
+
opened: false,
|
|
638
|
+
error: { code: "missing_parameter", message: "version is required." },
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
const deepLink = buildInstallDeepLink(version, changeset);
|
|
642
|
+
const opener = opts?.openUrl ?? defaultUrlOpener;
|
|
643
|
+
const res = opener(deepLink);
|
|
644
|
+
if (res.opened) {
|
|
645
|
+
return { deepLink, opened: true, error: null };
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
deepLink,
|
|
649
|
+
opened: false,
|
|
650
|
+
error: {
|
|
651
|
+
code: "deep_link_open_failed",
|
|
652
|
+
message: `Could not open the Unity Hub install dialog via ${deepLink}. ` +
|
|
653
|
+
`Ensure Unity Hub is installed and registered as the unityhub:// handler. ` +
|
|
654
|
+
(res.error ? `OS error: ${res.error}` : ""),
|
|
655
|
+
},
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
/** Default archive fetcher — `node:https` GET against Unity's archive page. */
|
|
659
|
+
function defaultArchiveFetcher(url) {
|
|
660
|
+
return new Promise((resolve, reject) => {
|
|
661
|
+
const req = get(url, { timeout: 20_000, headers: { "User-Agent": "unity-open-mcp" } }, (res) => {
|
|
662
|
+
if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {
|
|
663
|
+
reject(new Error(`archive fetch failed: HTTP ${res.statusCode}`));
|
|
664
|
+
res.resume();
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
const chunks = [];
|
|
668
|
+
res.on("data", (c) => chunks.push(c));
|
|
669
|
+
res.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
670
|
+
});
|
|
671
|
+
req.on("error", reject);
|
|
672
|
+
req.on("timeout", () => {
|
|
673
|
+
req.destroy(new Error("archive fetch timed out"));
|
|
674
|
+
});
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
/** Public archive URL — the same source the Hub launcher fetches. */
|
|
678
|
+
export const ARCHIVE_URL = "https://unity.com/releases/editor/archive";
|
|
679
|
+
/**
|
|
680
|
+
* Fetch Unity's public download-archive page and parse the release catalog.
|
|
681
|
+
* Falls back to the bundled snapshot (with `stale: true`) on any network or
|
|
682
|
+
* parse failure, so the call never hard-errors — a network outage surfaces as
|
|
683
|
+
* stale data, not an empty result.
|
|
684
|
+
*/
|
|
685
|
+
export async function fetchAvailableReleases(opts) {
|
|
686
|
+
const fetcher = opts?.fetcher ?? defaultArchiveFetcher;
|
|
687
|
+
try {
|
|
688
|
+
const html = await fetcher(ARCHIVE_URL);
|
|
689
|
+
const entries = parseArchivePayload(html);
|
|
690
|
+
if (entries && entries.length > 0) {
|
|
691
|
+
return { entries, stale: false, fetchedAt: new Date().toISOString() };
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
catch {
|
|
695
|
+
// fall through to snapshot.
|
|
696
|
+
}
|
|
697
|
+
return {
|
|
698
|
+
entries: snapshotReleases(),
|
|
699
|
+
stale: true,
|
|
700
|
+
fetchedAt: new Date().toISOString(),
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
//# sourceMappingURL=hub-control.js.map
|