@alpsckr/unitycli 0.4.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/README.md +389 -0
- package/contracts/command-contract.json +3972 -0
- package/contracts/stable-session/admission-acquire-v1.schema.json +16 -0
- package/contracts/stable-session/admission-response-v1.schema.json +30 -0
- package/contracts/stable-session/admission-revoke-v1.schema.json +15 -0
- package/contracts/stable-session/admission-transport-v1.json +36 -0
- package/contracts/stable-session/bridge-request-v2.schema.json +26 -0
- package/contracts/stable-session/canonical-path-v1-golden.json +23 -0
- package/contracts/stable-session/completion-contract.schema.json +46 -0
- package/contracts/stable-session/direct-call-semantics.json +102 -0
- package/contracts/stable-session/editor-state.schema.json +92 -0
- package/contracts/stable-session/health-v3.schema.json +47 -0
- package/contracts/stable-session/instance-registry-v3.schema.json +152 -0
- package/contracts/stable-session/removal-map.json +27 -0
- package/contracts/stable-session/request-digest-v1-golden.json +7 -0
- package/contracts/stable-session/runtime-config-v2.schema.json +27 -0
- package/contracts/static-capability-catalog.json +48226 -0
- package/contracts/tool-completion-contract.json +11322 -0
- package/dist/args.d.ts +27 -0
- package/dist/args.js +109 -0
- package/dist/args.js.map +1 -0
- package/dist/bridge/admission.d.ts +28 -0
- package/dist/bridge/admission.js +29 -0
- package/dist/bridge/admission.js.map +1 -0
- package/dist/bridge/args.d.ts +16 -0
- package/dist/bridge/args.js +123 -0
- package/dist/bridge/args.js.map +1 -0
- package/dist/bridge/domains/animation.d.ts +2 -0
- package/dist/bridge/domains/animation.js +199 -0
- package/dist/bridge/domains/animation.js.map +1 -0
- package/dist/bridge/domains/asset.d.ts +2 -0
- package/dist/bridge/domains/asset.js +85 -0
- package/dist/bridge/domains/asset.js.map +1 -0
- package/dist/bridge/domains/build.d.ts +2 -0
- package/dist/bridge/domains/build.js +35 -0
- package/dist/bridge/domains/build.js.map +1 -0
- package/dist/bridge/domains/camera.d.ts +2 -0
- package/dist/bridge/domains/camera.js +54 -0
- package/dist/bridge/domains/camera.js.map +1 -0
- package/dist/bridge/domains/code.d.ts +2 -0
- package/dist/bridge/domains/code.js +17 -0
- package/dist/bridge/domains/code.js.map +1 -0
- package/dist/bridge/domains/console.d.ts +2 -0
- package/dist/bridge/domains/console.js +34 -0
- package/dist/bridge/domains/console.js.map +1 -0
- package/dist/bridge/domains/diagnose.d.ts +2 -0
- package/dist/bridge/domains/diagnose.js +11 -0
- package/dist/bridge/domains/diagnose.js.map +1 -0
- package/dist/bridge/domains/editor.d.ts +2 -0
- package/dist/bridge/domains/editor.js +66 -0
- package/dist/bridge/domains/editor.js.map +1 -0
- package/dist/bridge/domains/extension.d.ts +8 -0
- package/dist/bridge/domains/extension.js +20 -0
- package/dist/bridge/domains/extension.js.map +1 -0
- package/dist/bridge/domains/game-object.d.ts +2 -0
- package/dist/bridge/domains/game-object.js +179 -0
- package/dist/bridge/domains/game-object.js.map +1 -0
- package/dist/bridge/domains/graphics.d.ts +2 -0
- package/dist/bridge/domains/graphics.js +185 -0
- package/dist/bridge/domains/graphics.js.map +1 -0
- package/dist/bridge/domains/material.d.ts +2 -0
- package/dist/bridge/domains/material.js +70 -0
- package/dist/bridge/domains/material.js.map +1 -0
- package/dist/bridge/domains/navmesh.d.ts +2 -0
- package/dist/bridge/domains/navmesh.js +34 -0
- package/dist/bridge/domains/navmesh.js.map +1 -0
- package/dist/bridge/domains/object.d.ts +2 -0
- package/dist/bridge/domains/object.js +43 -0
- package/dist/bridge/domains/object.js.map +1 -0
- package/dist/bridge/domains/occlusion.d.ts +2 -0
- package/dist/bridge/domains/occlusion.js +12 -0
- package/dist/bridge/domains/occlusion.js.map +1 -0
- package/dist/bridge/domains/package.d.ts +2 -0
- package/dist/bridge/domains/package.js +2 -0
- package/dist/bridge/domains/package.js.map +1 -0
- package/dist/bridge/domains/physics.d.ts +2 -0
- package/dist/bridge/domains/physics.js +139 -0
- package/dist/bridge/domains/physics.js.map +1 -0
- package/dist/bridge/domains/prefab.d.ts +2 -0
- package/dist/bridge/domains/prefab.js +104 -0
- package/dist/bridge/domains/prefab.js.map +1 -0
- package/dist/bridge/domains/profiler.d.ts +2 -0
- package/dist/bridge/domains/profiler.js +105 -0
- package/dist/bridge/domains/profiler.js.map +1 -0
- package/dist/bridge/domains/project-tool.d.ts +2 -0
- package/dist/bridge/domains/project-tool.js +46 -0
- package/dist/bridge/domains/project-tool.js.map +1 -0
- package/dist/bridge/domains/reflection.d.ts +2 -0
- package/dist/bridge/domains/reflection.js +48 -0
- package/dist/bridge/domains/reflection.js.map +1 -0
- package/dist/bridge/domains/runtime-tool.d.ts +2 -0
- package/dist/bridge/domains/runtime-tool.js +48 -0
- package/dist/bridge/domains/runtime-tool.js.map +1 -0
- package/dist/bridge/domains/scene.d.ts +2 -0
- package/dist/bridge/domains/scene.js +100 -0
- package/dist/bridge/domains/scene.js.map +1 -0
- package/dist/bridge/domains/screenshot.d.ts +2 -0
- package/dist/bridge/domains/screenshot.js +85 -0
- package/dist/bridge/domains/screenshot.js.map +1 -0
- package/dist/bridge/domains/scriptable-object.d.ts +2 -0
- package/dist/bridge/domains/scriptable-object.js +53 -0
- package/dist/bridge/domains/scriptable-object.js.map +1 -0
- package/dist/bridge/domains/shader.d.ts +2 -0
- package/dist/bridge/domains/shader.js +66 -0
- package/dist/bridge/domains/shader.js.map +1 -0
- package/dist/bridge/domains/texture.d.ts +2 -0
- package/dist/bridge/domains/texture.js +78 -0
- package/dist/bridge/domains/texture.js.map +1 -0
- package/dist/bridge/domains/timeline.d.ts +2 -0
- package/dist/bridge/domains/timeline.js +75 -0
- package/dist/bridge/domains/timeline.js.map +1 -0
- package/dist/bridge/domains/ui.d.ts +2 -0
- package/dist/bridge/domains/ui.js +193 -0
- package/dist/bridge/domains/ui.js.map +1 -0
- package/dist/bridge/index.d.ts +9 -0
- package/dist/bridge/index.js +124 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/bridge/registry.d.ts +19 -0
- package/dist/bridge/registry.js +114 -0
- package/dist/bridge/registry.js.map +1 -0
- package/dist/bridge/session-supervisor.d.ts +138 -0
- package/dist/bridge/session-supervisor.js +873 -0
- package/dist/bridge/session-supervisor.js.map +1 -0
- package/dist/bridge/types.d.ts +61 -0
- package/dist/bridge/types.js +17 -0
- package/dist/bridge/types.js.map +1 -0
- package/dist/capabilities.d.ts +5 -0
- package/dist/capabilities.js +84 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli-commands/command.d.ts +7 -0
- package/dist/cli-commands/command.js +513 -0
- package/dist/cli-commands/command.js.map +1 -0
- package/dist/cli-commands/extension-auto-detect.d.ts +62 -0
- package/dist/cli-commands/extension-auto-detect.js +119 -0
- package/dist/cli-commands/extension-auto-detect.js.map +1 -0
- package/dist/cli-commands/extensions.d.ts +24 -0
- package/dist/cli-commands/extensions.js +428 -0
- package/dist/cli-commands/extensions.js.map +1 -0
- package/dist/cli-commands/package.d.ts +4 -0
- package/dist/cli-commands/package.js +151 -0
- package/dist/cli-commands/package.js.map +1 -0
- package/dist/cli-commands/skill-installer.d.ts +83 -0
- package/dist/cli-commands/skill-installer.js +703 -0
- package/dist/cli-commands/skill-installer.js.map +1 -0
- package/dist/cli-commands/types.d.ts +17 -0
- package/dist/cli-commands/types.js +2 -0
- package/dist/cli-commands/types.js.map +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +302 -0
- package/dist/cli.js.map +1 -0
- package/dist/contracts/command-contract.d.ts +21 -0
- package/dist/contracts/command-contract.js +143 -0
- package/dist/contracts/command-contract.js.map +1 -0
- package/dist/contracts/csharp-command-extractor.d.ts +1 -0
- package/dist/contracts/csharp-command-extractor.js +89 -0
- package/dist/contracts/csharp-command-extractor.js.map +1 -0
- package/dist/contracts/validate-command-contract.d.ts +1 -0
- package/dist/contracts/validate-command-contract.js +86 -0
- package/dist/contracts/validate-command-contract.js.map +1 -0
- package/dist/doctor.d.ts +22 -0
- package/dist/doctor.js +498 -0
- package/dist/doctor.js.map +1 -0
- package/dist/editor-blocker-observer.d.ts +45 -0
- package/dist/editor-blocker-observer.js +55 -0
- package/dist/editor-blocker-observer.js.map +1 -0
- package/dist/editor-dialogs.d.ts +53 -0
- package/dist/editor-dialogs.js +79 -0
- package/dist/editor-dialogs.js.map +1 -0
- package/dist/extension-availability.d.ts +30 -0
- package/dist/extension-availability.js +83 -0
- package/dist/extension-availability.js.map +1 -0
- package/dist/extensions/.generated-bridge-domains/cinemachine.d.ts +2 -0
- package/dist/extensions/.generated-bridge-domains/cinemachine.js +104 -0
- package/dist/extensions/.generated-bridge-domains/cinemachine.js.map +1 -0
- package/dist/extensions/.generated-bridge-domains/hdrp.d.ts +2 -0
- package/dist/extensions/.generated-bridge-domains/hdrp.js +35 -0
- package/dist/extensions/.generated-bridge-domains/hdrp.js.map +1 -0
- package/dist/extensions/.generated-bridge-domains/probuilder.d.ts +13 -0
- package/dist/extensions/.generated-bridge-domains/probuilder.js +342 -0
- package/dist/extensions/.generated-bridge-domains/probuilder.js.map +1 -0
- package/dist/extensions/.generated-bridge-domains/urp.d.ts +2 -0
- package/dist/extensions/.generated-bridge-domains/urp.js +52 -0
- package/dist/extensions/.generated-bridge-domains/urp.js.map +1 -0
- package/dist/extensions/.generated-bridge-domains/vfx.d.ts +2 -0
- package/dist/extensions/.generated-bridge-domains/vfx.js +312 -0
- package/dist/extensions/.generated-bridge-domains/vfx.js.map +1 -0
- package/dist/extensions/.generated-registry-data.d.ts +7 -0
- package/dist/extensions/.generated-registry-data.js +895 -0
- package/dist/extensions/.generated-registry-data.js.map +1 -0
- package/dist/extensions/contribution-loader.d.ts +27 -0
- package/dist/extensions/contribution-loader.js +60 -0
- package/dist/extensions/contribution-loader.js.map +1 -0
- package/dist/extensions/descriptor-loader.d.ts +73 -0
- package/dist/extensions/descriptor-loader.js +126 -0
- package/dist/extensions/descriptor-loader.js.map +1 -0
- package/dist/extensions/index.d.ts +19 -0
- package/dist/extensions/index.js +23 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/installer.d.ts +80 -0
- package/dist/extensions/installer.js +594 -0
- package/dist/extensions/installer.js.map +1 -0
- package/dist/extensions/metadata/index.d.ts +15 -0
- package/dist/extensions/metadata/index.js +41 -0
- package/dist/extensions/metadata/index.js.map +1 -0
- package/dist/extensions/metadata/types.d.ts +38 -0
- package/dist/extensions/metadata/types.js +11 -0
- package/dist/extensions/metadata/types.js.map +1 -0
- package/dist/extensions/project-resolver.d.ts +35 -0
- package/dist/extensions/project-resolver.js +61 -0
- package/dist/extensions/project-resolver.js.map +1 -0
- package/dist/extensions/registry.d.ts +86 -0
- package/dist/extensions/registry.js +262 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/tool-manifest.d.ts +29 -0
- package/dist/extensions/tool-manifest.js +53 -0
- package/dist/extensions/tool-manifest.js.map +1 -0
- package/dist/extensions/types.d.ts +115 -0
- package/dist/extensions/types.js +12 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/instances.d.ts +163 -0
- package/dist/instances.js +1137 -0
- package/dist/instances.js.map +1 -0
- package/dist/output.d.ts +119 -0
- package/dist/output.js +204 -0
- package/dist/output.js.map +1 -0
- package/dist/package-manager.d.ts +280 -0
- package/dist/package-manager.js +1832 -0
- package/dist/package-manager.js.map +1 -0
- package/dist/platform.d.ts +3 -0
- package/dist/platform.js +19 -0
- package/dist/platform.js.map +1 -0
- package/dist/project-identity.d.ts +48 -0
- package/dist/project-identity.js +254 -0
- package/dist/project-identity.js.map +1 -0
- package/dist/project-tool-discovery.d.ts +23 -0
- package/dist/project-tool-discovery.js +292 -0
- package/dist/project-tool-discovery.js.map +1 -0
- package/dist/protocol/envelope.d.ts +64 -0
- package/dist/protocol/envelope.js +8 -0
- package/dist/protocol/envelope.js.map +1 -0
- package/dist/protocol/index.d.ts +7 -0
- package/dist/protocol/index.js +2 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/runtime-code.d.ts +20 -0
- package/dist/runtime-code.js +232 -0
- package/dist/runtime-code.js.map +1 -0
- package/dist/schema/any-json.d.ts +4 -0
- package/dist/schema/any-json.js +2 -0
- package/dist/schema/any-json.js.map +1 -0
- package/dist/schema/validator.d.ts +7 -0
- package/dist/schema/validator.js +135 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/services/docs-reflect-cache.d.ts +106 -0
- package/dist/services/docs-reflect-cache.js +301 -0
- package/dist/services/docs-reflect-cache.js.map +1 -0
- package/dist/services/docs-service.d.ts +16 -0
- package/dist/services/docs-service.js +208 -0
- package/dist/services/docs-service.js.map +1 -0
- package/dist/services/reflect-service.d.ts +12 -0
- package/dist/services/reflect-service.js +122 -0
- package/dist/services/reflect-service.js.map +1 -0
- package/dist/static-capability-catalog.d.ts +13 -0
- package/dist/static-capability-catalog.js +41 -0
- package/dist/static-capability-catalog.js.map +1 -0
- package/dist/test-results.d.ts +13 -0
- package/dist/test-results.js +44 -0
- package/dist/test-results.js.map +1 -0
- package/dist/tools/.generated-completion-registry.d.ts +17 -0
- package/dist/tools/.generated-completion-registry.js +5862 -0
- package/dist/tools/.generated-completion-registry.js.map +1 -0
- package/dist/tools/.generated-registry.d.ts +53 -0
- package/dist/tools/.generated-registry.js +55 -0
- package/dist/tools/.generated-registry.js.map +1 -0
- package/dist/tools/.generated-schemas.d.ts +1 -0
- package/dist/tools/.generated-schemas.js +56 -0
- package/dist/tools/.generated-schemas.js.map +1 -0
- package/dist/tools/asset/refresh.d.ts +26 -0
- package/dist/tools/asset/refresh.js +97 -0
- package/dist/tools/asset/refresh.js.map +1 -0
- package/dist/tools/build/run.d.ts +45 -0
- package/dist/tools/build/run.js +115 -0
- package/dist/tools/build/run.js.map +1 -0
- package/dist/tools/catalog.d.ts +33 -0
- package/dist/tools/catalog.js +202 -0
- package/dist/tools/catalog.js.map +1 -0
- package/dist/tools/code/exec.d.ts +53 -0
- package/dist/tools/code/exec.js +59 -0
- package/dist/tools/code/exec.js.map +1 -0
- package/dist/tools/commands.d.ts +5 -0
- package/dist/tools/commands.js +45 -0
- package/dist/tools/commands.js.map +1 -0
- package/dist/tools/completion-probe.d.ts +22 -0
- package/dist/tools/completion-probe.js +2 -0
- package/dist/tools/completion-probe.js.map +1 -0
- package/dist/tools/define.d.ts +77 -0
- package/dist/tools/define.js +58 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/diagnose/capabilities.d.ts +13 -0
- package/dist/tools/diagnose/capabilities.js +34 -0
- package/dist/tools/diagnose/capabilities.js.map +1 -0
- package/dist/tools/dispatcher.d.ts +27 -0
- package/dist/tools/dispatcher.js +971 -0
- package/dist/tools/dispatcher.js.map +1 -0
- package/dist/tools/docs/get.d.ts +22 -0
- package/dist/tools/docs/get.js +22 -0
- package/dist/tools/docs/get.js.map +1 -0
- package/dist/tools/docs/search.d.ts +31 -0
- package/dist/tools/docs/search.js +22 -0
- package/dist/tools/docs/search.js.map +1 -0
- package/dist/tools/editor/compile.d.ts +66 -0
- package/dist/tools/editor/compile.js +225 -0
- package/dist/tools/editor/compile.js.map +1 -0
- package/dist/tools/editor/dialog/click.d.ts +12 -0
- package/dist/tools/editor/dialog/click.js +71 -0
- package/dist/tools/editor/dialog/click.js.map +1 -0
- package/dist/tools/editor/dialogs.d.ts +12 -0
- package/dist/tools/editor/dialogs.js +58 -0
- package/dist/tools/editor/dialogs.js.map +1 -0
- package/dist/tools/editor/readiness.d.ts +13 -0
- package/dist/tools/editor/readiness.js +24 -0
- package/dist/tools/editor/readiness.js.map +1 -0
- package/dist/tools/editor/refresh.d.ts +25 -0
- package/dist/tools/editor/refresh.js +154 -0
- package/dist/tools/editor/refresh.js.map +1 -0
- package/dist/tools/editor/state.d.ts +63 -0
- package/dist/tools/editor/state.js +286 -0
- package/dist/tools/editor/state.js.map +1 -0
- package/dist/tools/errors.d.ts +30 -0
- package/dist/tools/errors.js +46 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/metadata/derived.d.ts +34 -0
- package/dist/tools/metadata/derived.js +136 -0
- package/dist/tools/metadata/derived.js.map +1 -0
- package/dist/tools/metadata/index.d.ts +34 -0
- package/dist/tools/metadata/index.js +130 -0
- package/dist/tools/metadata/index.js.map +1 -0
- package/dist/tools/metadata/schemas.d.ts +3 -0
- package/dist/tools/metadata/schemas.js +19 -0
- package/dist/tools/metadata/schemas.js.map +1 -0
- package/dist/tools/metadata/status.d.ts +4 -0
- package/dist/tools/metadata/status.js +61 -0
- package/dist/tools/metadata/status.js.map +1 -0
- package/dist/tools/metadata/types.d.ts +79 -0
- package/dist/tools/metadata/types.js +2 -0
- package/dist/tools/metadata/types.js.map +1 -0
- package/dist/tools/navmesh/bake-cancel.d.ts +7 -0
- package/dist/tools/navmesh/bake-cancel.js +21 -0
- package/dist/tools/navmesh/bake-cancel.js.map +1 -0
- package/dist/tools/navmesh/bake-status.d.ts +5 -0
- package/dist/tools/navmesh/bake-status.js +18 -0
- package/dist/tools/navmesh/bake-status.js.map +1 -0
- package/dist/tools/navmesh/bake.d.ts +5 -0
- package/dist/tools/navmesh/bake.js +23 -0
- package/dist/tools/navmesh/bake.js.map +1 -0
- package/dist/tools/navmesh/live.d.ts +86 -0
- package/dist/tools/navmesh/live.js +206 -0
- package/dist/tools/navmesh/live.js.map +1 -0
- package/dist/tools/navmesh/surface-bake.d.ts +5 -0
- package/dist/tools/navmesh/surface-bake.js +24 -0
- package/dist/tools/navmesh/surface-bake.js.map +1 -0
- package/dist/tools/occlusion/bake-cancel.d.ts +7 -0
- package/dist/tools/occlusion/bake-cancel.js +21 -0
- package/dist/tools/occlusion/bake-cancel.js.map +1 -0
- package/dist/tools/occlusion/bake-status.d.ts +5 -0
- package/dist/tools/occlusion/bake-status.js +18 -0
- package/dist/tools/occlusion/bake-status.js.map +1 -0
- package/dist/tools/occlusion/bake.d.ts +11 -0
- package/dist/tools/occlusion/bake.js +23 -0
- package/dist/tools/occlusion/bake.js.map +1 -0
- package/dist/tools/occlusion/live.d.ts +74 -0
- package/dist/tools/occlusion/live.js +201 -0
- package/dist/tools/occlusion/live.js.map +1 -0
- package/dist/tools/package/bridge-remove.d.ts +26 -0
- package/dist/tools/package/bridge-remove.js +32 -0
- package/dist/tools/package/bridge-remove.js.map +1 -0
- package/dist/tools/package/deploy.d.ts +49 -0
- package/dist/tools/package/deploy.js +134 -0
- package/dist/tools/package/deploy.js.map +1 -0
- package/dist/tools/package/embed.d.ts +14 -0
- package/dist/tools/package/embed.js +93 -0
- package/dist/tools/package/embed.js.map +1 -0
- package/dist/tools/package/file-mutation-worker.d.ts +6 -0
- package/dist/tools/package/file-mutation-worker.js +154 -0
- package/dist/tools/package/file-mutation-worker.js.map +1 -0
- package/dist/tools/package/info.d.ts +19 -0
- package/dist/tools/package/info.js +27 -0
- package/dist/tools/package/info.js.map +1 -0
- package/dist/tools/package/install.d.ts +24 -0
- package/dist/tools/package/install.js +65 -0
- package/dist/tools/package/install.js.map +1 -0
- package/dist/tools/package/list.d.ts +27 -0
- package/dist/tools/package/list.js +21 -0
- package/dist/tools/package/list.js.map +1 -0
- package/dist/tools/package/live-resolve.d.ts +46 -0
- package/dist/tools/package/live-resolve.js +497 -0
- package/dist/tools/package/live-resolve.js.map +1 -0
- package/dist/tools/package/public-result.d.ts +4 -0
- package/dist/tools/package/public-result.js +25 -0
- package/dist/tools/package/public-result.js.map +1 -0
- package/dist/tools/package/registry-clear.d.ts +15 -0
- package/dist/tools/package/registry-clear.js +27 -0
- package/dist/tools/package/registry-clear.js.map +1 -0
- package/dist/tools/package/registry-get.d.ts +10 -0
- package/dist/tools/package/registry-get.js +22 -0
- package/dist/tools/package/registry-get.js.map +1 -0
- package/dist/tools/package/registry-set.d.ts +17 -0
- package/dist/tools/package/registry-set.js +28 -0
- package/dist/tools/package/registry-set.js.map +1 -0
- package/dist/tools/package/remove.d.ts +47 -0
- package/dist/tools/package/remove.js +67 -0
- package/dist/tools/package/remove.js.map +1 -0
- package/dist/tools/package/resolve.d.ts +6 -0
- package/dist/tools/package/resolve.js +14 -0
- package/dist/tools/package/resolve.js.map +1 -0
- package/dist/tools/package/restore.d.ts +42 -0
- package/dist/tools/package/restore.js +122 -0
- package/dist/tools/package/restore.js.map +1 -0
- package/dist/tools/package/scoped-registry-add.d.ts +25 -0
- package/dist/tools/package/scoped-registry-add.js +30 -0
- package/dist/tools/package/scoped-registry-add.js.map +1 -0
- package/dist/tools/package/scoped-registry-list.d.ts +14 -0
- package/dist/tools/package/scoped-registry-list.js +22 -0
- package/dist/tools/package/scoped-registry-list.js.map +1 -0
- package/dist/tools/package/scoped-registry-remove.d.ts +29 -0
- package/dist/tools/package/scoped-registry-remove.js +31 -0
- package/dist/tools/package/scoped-registry-remove.js.map +1 -0
- package/dist/tools/package/search.d.ts +17 -0
- package/dist/tools/package/search.js +39 -0
- package/dist/tools/package/search.js.map +1 -0
- package/dist/tools/package/status.d.ts +21 -0
- package/dist/tools/package/status.js +37 -0
- package/dist/tools/package/status.js.map +1 -0
- package/dist/tools/reflect/member.d.ts +22 -0
- package/dist/tools/reflect/member.js +22 -0
- package/dist/tools/reflect/member.js.map +1 -0
- package/dist/tools/reflect/search.d.ts +30 -0
- package/dist/tools/reflect/search.js +22 -0
- package/dist/tools/reflect/search.js.map +1 -0
- package/dist/tools/reflect/type.d.ts +21 -0
- package/dist/tools/reflect/type.js +22 -0
- package/dist/tools/reflect/type.js.map +1 -0
- package/dist/tools/runtime/console.d.ts +24 -0
- package/dist/tools/runtime/console.js +17 -0
- package/dist/tools/runtime/console.js.map +1 -0
- package/dist/tools/runtime/input/key.d.ts +23 -0
- package/dist/tools/runtime/input/key.js +18 -0
- package/dist/tools/runtime/input/key.js.map +1 -0
- package/dist/tools/runtime/input/pointer.d.ts +34 -0
- package/dist/tools/runtime/input/pointer.js +18 -0
- package/dist/tools/runtime/input/pointer.js.map +1 -0
- package/dist/tools/runtime/log.d.ts +20 -0
- package/dist/tools/runtime/log.js +17 -0
- package/dist/tools/runtime/log.js.map +1 -0
- package/dist/tools/runtime/state.d.ts +45 -0
- package/dist/tools/runtime/state.js +17 -0
- package/dist/tools/runtime/state.js.map +1 -0
- package/dist/tools/runtime/target-framerate/set.d.ts +16 -0
- package/dist/tools/runtime/target-framerate/set.js +17 -0
- package/dist/tools/runtime/target-framerate/set.js.map +1 -0
- package/dist/tools/runtime/time-scale/set.d.ts +16 -0
- package/dist/tools/runtime/time-scale/set.js +17 -0
- package/dist/tools/runtime/time-scale/set.js.map +1 -0
- package/dist/tools/runtime/ui/capture-element.d.ts +31 -0
- package/dist/tools/runtime/ui/capture-element.js +17 -0
- package/dist/tools/runtime/ui/capture-element.js.map +1 -0
- package/dist/tools/test/cancel.d.ts +19 -0
- package/dist/tools/test/cancel.js +94 -0
- package/dist/tools/test/cancel.js.map +1 -0
- package/dist/tools/test/run.d.ts +39 -0
- package/dist/tools/test/run.js +101 -0
- package/dist/tools/test/run.js.map +1 -0
- package/dist/tools/tools/describe.d.ts +27 -0
- package/dist/tools/tools/describe.js +35 -0
- package/dist/tools/tools/describe.js.map +1 -0
- package/dist/tools/tools/group-list.d.ts +20 -0
- package/dist/tools/tools/group-list.js +39 -0
- package/dist/tools/tools/group-list.js.map +1 -0
- package/dist/tools/tools/group-summaries.d.ts +3 -0
- package/dist/tools/tools/group-summaries.js +52 -0
- package/dist/tools/tools/group-summaries.js.map +1 -0
- package/dist/tools/tools/group.d.ts +13 -0
- package/dist/tools/tools/group.js +34 -0
- package/dist/tools/tools/group.js.map +1 -0
- package/dist/tools/tools/search.d.ts +17 -0
- package/dist/tools/tools/search.js +42 -0
- package/dist/tools/tools/search.js.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/unity-project-processes.d.ts +12 -0
- package/dist/unity-project-processes.js +59 -0
- package/dist/unity-project-processes.js.map +1 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.js +22 -0
- package/dist/util.js.map +1 -0
- package/dist/windows-editor-state.d.ts +31 -0
- package/dist/windows-editor-state.js +98 -0
- package/dist/windows-editor-state.js.map +1 -0
- package/docs/README.md +43 -0
- package/docs/availability-differences.md +97 -0
- package/docs/command-execution.md +89 -0
- package/docs/error-codes.md +204 -0
- package/docs/extensions.md +132 -0
- package/docs/risk-and-side-effects.md +93 -0
- package/docs/safety-boundaries.md +103 -0
- package/docs/target-and-instance.md +83 -0
- package/docs/tool-discovery.md +104 -0
- package/docs/tool-execution.md +178 -0
- package/extensions/cinemachine/bridge/domains/cinemachine.ts +115 -0
- package/extensions/cinemachine/docs/cinemachine.md +50 -0
- package/extensions/cinemachine/extension.json +129 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/CinemachineExtensionToolSupport.cs +15 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/CinemachineToolSupport.cs +854 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/aim.cs +96 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/blend.cs +140 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/body.cs +96 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/brain-ensure.cs +16 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/brain-status.cs +12 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/create.cs +147 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/extension-add.cs +13 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/extension-list.cs +13 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/extension-remove.cs +13 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/lens.cs +142 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/noise.cs +126 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/ping.cs +43 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/priority.cs +113 -0
- package/extensions/cinemachine/unitypkg/Editor/Cinemachine/target.cs +84 -0
- package/extensions/cinemachine/unitypkg/UnityCli.Extensions.Cinemachine.Editor.asmdef +18 -0
- package/extensions/hdrp/bridge/domains/hdrp.ts +41 -0
- package/extensions/hdrp/docs/hdrp.md +15 -0
- package/extensions/hdrp/extension.json +31 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/HdrpToolSupport.cs +607 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/settings-get.cs +29 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/settings-set.cs +47 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/volume-add-effect.cs +28 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/volume-create.cs +28 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/volume-info.cs +25 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/volume-list.cs +25 -0
- package/extensions/hdrp/unitypkg/Editor/Hdrp/volume-set.cs +28 -0
- package/extensions/hdrp/unitypkg/UnityCli.Extensions.Hdrp.Editor.asmdef +19 -0
- package/extensions/probuilder/bridge/domains/probuilder.ts +386 -0
- package/extensions/probuilder/docs/probuilder.md +125 -0
- package/extensions/probuilder/extension.json +291 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderAppendCompletionProof.cs +254 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderAtomicReadback.cs +293 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderBevelCompletionProof.cs +299 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderCanonicalMeshSnapshot.cs +951 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderConnectCompletionProof.cs +407 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderEdgeCompletionProof.cs +318 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderErrors.cs +83 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderFaceCompletionProof.cs +152 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderFaceExtrudeCompletionProof.cs +283 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderFlipCompletionProof.cs +170 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderInput.cs +85 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderInsertCompletionProof.cs +674 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderOperationProof.cs +137 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderReflection.cs +1064 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderRefreshUvProof.cs +53 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderSceneTool.cs +184 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderShapeTopologyRecords.g.cs +82 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ProBuilderVertexObjectCompletionProof.cs +346 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/append-vertices-to-edge.cs +118 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/auto-smooth.cs +104 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/bevel-edges.cs +119 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/bridge-edges.cs +113 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/center-pivot.cs +43 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/combine-meshes.cs +58 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/connect-elements.cs +128 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/convert-to-probuilder.cs +40 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/create-poly-shape.cs +55 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/create-polygon.cs +28 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/create-shape.cs +168 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/delete-faces.cs +42 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/detach-faces.cs +46 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/duplicate-and-flip.cs +100 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/extrude-edges.cs +118 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/extrude-faces.cs +110 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/flip-normals.cs +102 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/freeze-transform.cs +45 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/insert-vertex.cs +132 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/merge-faces.cs +44 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/merge-objects.cs +130 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/merge-vertices.cs +109 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/mesh-info.cs +117 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/move-vertices.cs +33 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/ping.cs +51 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/repair-mesh.cs +40 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/select-faces.cs +161 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/set-face-color.cs +24 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/set-face-material.cs +23 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/set-face-uvs.cs +28 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/set-pivot.cs +42 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/set-smoothing.cs +23 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/split-vertices.cs +64 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/subdivide.cs +111 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/validate-mesh.cs +75 -0
- package/extensions/probuilder/unitypkg/Editor/ProBuilder/weld-vertices.cs +112 -0
- package/extensions/probuilder/unitypkg/UnityCli.Extensions.ProBuilder.Editor.asmdef +25 -0
- package/extensions/urp/bridge/domains/urp.ts +62 -0
- package/extensions/urp/docs/urp.md +20 -0
- package/extensions/urp/extension.json +41 -0
- package/extensions/urp/unitypkg/Editor/Urp/UrpFeatureToolSupport.cs +336 -0
- package/extensions/urp/unitypkg/Editor/Urp/UrpToolSupport.cs +801 -0
- package/extensions/urp/unitypkg/Editor/Urp/feature-add.cs +12 -0
- package/extensions/urp/unitypkg/Editor/Urp/feature-configure.cs +12 -0
- package/extensions/urp/unitypkg/Editor/Urp/feature-list.cs +12 -0
- package/extensions/urp/unitypkg/Editor/Urp/feature-remove.cs +12 -0
- package/extensions/urp/unitypkg/Editor/Urp/feature-toggle.cs +12 -0
- package/extensions/urp/unitypkg/Editor/Urp/settings-get.cs +27 -0
- package/extensions/urp/unitypkg/Editor/Urp/settings-set.cs +47 -0
- package/extensions/urp/unitypkg/Editor/Urp/volume-add-effect.cs +33 -0
- package/extensions/urp/unitypkg/Editor/Urp/volume-create.cs +33 -0
- package/extensions/urp/unitypkg/Editor/Urp/volume-info.cs +31 -0
- package/extensions/urp/unitypkg/Editor/Urp/volume-list.cs +39 -0
- package/extensions/urp/unitypkg/Editor/Urp/volume-set.cs +33 -0
- package/extensions/urp/unitypkg/UnityCli.Extensions.Urp.Editor.asmdef +19 -0
- package/extensions/vfx-graph/bridge/domains/vfx.ts +337 -0
- package/extensions/vfx-graph/docs/vfx.md +28 -0
- package/extensions/vfx-graph/extension.json +72 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/VfxActionToolSupport.cs +248 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/VfxToolSupport.cs +1325 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-pause.cs +37 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-play.cs +40 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-reinitialize.cs +37 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-set-rate.cs +36 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-set-seed.cs +42 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/control-stop.cs +37 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/effect-add.cs +55 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/effect-assign.cs +44 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/effect-info.cs +30 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/graph-create.cs +62 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/graph-info.cs +32 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/line-create.cs +75 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/line-positions.cs +100 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/parameter.cs +216 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-clear.cs +39 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-create.cs +80 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-emission.cs +126 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-info.cs +55 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-main.cs +75 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-pause.cs +38 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-play.cs +38 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-shape.cs +148 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/particle-stop.cs +41 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/template-create.cs +58 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/template-list.cs +31 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/trail-create.cs +41 -0
- package/extensions/vfx-graph/unitypkg/Editor/Vfx/trail-set.cs +44 -0
- package/extensions/vfx-graph/unitypkg/UnityCli.Extensions.VfxGraph.Editor.asmdef +18 -0
- package/package.json +46 -0
- package/schemas/error-code.schema.json +70 -0
- package/schemas/extension-descriptor.schema.json +88 -0
- package/schemas/extension-manifest.schema.json +125 -0
- package/schemas/request-envelope.schema.json +34 -0
- package/schemas/response-envelope.schema.json +42 -0
- package/schemas/tool-metadata.schema.json +111 -0
- package/skills/unitycli/SKILL.md +61 -0
- package/skills/unitycli/agents/interface.yaml +30 -0
- package/skills/unitycli/evals/history/2026-08-05-governed-baseline.json +44 -0
- package/skills/unitycli/evals/output/cases.jsonl +5 -0
- package/skills/unitycli/evals/output/fixtures/feedback-scenario.json +27 -0
- package/skills/unitycli/evals/output/schema.json +32 -0
- package/skills/unitycli/evals/semantic_config.json +46 -0
- package/skills/unitycli/evals/trigger_cases.json +39 -0
- package/skills/unitycli/examples/feedback-event.input.json +8 -0
- package/skills/unitycli/examples/feedback-record.output.json +12 -0
- package/skills/unitycli/manifest.json +112 -0
- package/skills/unitycli/references/custom-tools.md +111 -0
- package/skills/unitycli/references/feedback.md +59 -0
- package/skills/unitycli/references/operation-protocol.md +83 -0
- package/skills/unitycli/reports/output_quality_scorecard.md +56 -0
- package/skills/unitycli/reports/trust-report.md +57 -0
- package/skills/unitycli/scripts/record-feedback.ps1 +210 -0
- package/skills/unitycli/security/network_policy.json +18 -0
- package/skills/unitycli/security/permission_policy.json +40 -0
- package/unitypkg/Editor/Bridge/BridgeCommandContext.cs +64 -0
- package/unitypkg/Editor/Bridge/BridgeCommandException.cs +39 -0
- package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +172 -0
- package/unitypkg/Editor/Bridge/BridgeHttpServer.cs +534 -0
- package/unitypkg/Editor/Bridge/BridgeResponse.cs +58 -0
- package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +325 -0
- package/unitypkg/Editor/BridgeStartupStateMachine.cs +81 -0
- package/unitypkg/Editor/Commands/ProjectToolCommands.cs +43 -0
- package/unitypkg/Editor/Commands/RuntimeToolCommands.cs +43 -0
- package/unitypkg/Editor/Generated/UnityCliToolCompletionRegistry.g.cs +428 -0
- package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +664 -0
- package/unitypkg/Editor/Infrastructure/RegistryOwnershipResolver.cs +148 -0
- package/unitypkg/Editor/Infrastructure/UnityCliActiveOperation.cs +411 -0
- package/unitypkg/Editor/Infrastructure/UnityCliAdmission.cs +485 -0
- package/unitypkg/Editor/Infrastructure/UnityCliArtifacts.cs +110 -0
- package/unitypkg/Editor/Infrastructure/UnityCliAssetRefreshCoordinator.cs +106 -0
- package/unitypkg/Editor/Infrastructure/UnityCliBridgeHelpers.cs +155 -0
- package/unitypkg/Editor/Infrastructure/UnityCliCanonicalProjectPath.cs +325 -0
- package/unitypkg/Editor/Infrastructure/UnityCliCompilationEventBroker.cs +192 -0
- package/unitypkg/Editor/Infrastructure/UnityCliCompileCoordinator.cs +271 -0
- package/unitypkg/Editor/Infrastructure/UnityCliCompletionProbe.cs +515 -0
- package/unitypkg/Editor/Infrastructure/UnityCliEditorStateSnapshot.cs +84 -0
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +558 -0
- package/unitypkg/Editor/Infrastructure/UnityCliJson.cs +155 -0
- package/unitypkg/Editor/Infrastructure/UnityCliLargeOutput.cs +128 -0
- package/unitypkg/Editor/Infrastructure/UnityCliLiveBuildCoordinator.cs +230 -0
- package/unitypkg/Editor/Infrastructure/UnityCliLiveRefreshCoordinator.cs +164 -0
- package/unitypkg/Editor/Infrastructure/UnityCliLog.cs +127 -0
- package/unitypkg/Editor/Infrastructure/UnityCliNavMeshBakeCoordinator.cs +2073 -0
- package/unitypkg/Editor/Infrastructure/UnityCliObjectPatch.cs +193 -0
- package/unitypkg/Editor/Infrastructure/UnityCliObjectRef.cs +278 -0
- package/unitypkg/Editor/Infrastructure/UnityCliObjectSerializer.cs +620 -0
- package/unitypkg/Editor/Infrastructure/UnityCliOcclusionBakeCoordinator.cs +1739 -0
- package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +828 -0
- package/unitypkg/Editor/Infrastructure/UnityCliPackageEmbedCoordinator.cs +147 -0
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveCoordinator.cs +454 -0
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveState.cs +561 -0
- package/unitypkg/Editor/Infrastructure/UnityCliPipelineHandoff.cs +742 -0
- package/unitypkg/Editor/Infrastructure/UnityCliProjectSettings.cs +92 -0
- package/unitypkg/Editor/Infrastructure/UnityCliProtocolRequest.cs +116 -0
- package/unitypkg/Editor/Infrastructure/UnityCliReflection.cs +477 -0
- package/unitypkg/Editor/Infrastructure/UnityCliReloadOperation.cs +664 -0
- package/unitypkg/Editor/Infrastructure/UnityCliRequestDigest.cs +34 -0
- package/unitypkg/Editor/Infrastructure/UnityCliRuntimeBuildInjection.cs +121 -0
- package/unitypkg/Editor/Infrastructure/UnityCliRuntimeExecutor.cs +391 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSceneMutation.cs +84 -0
- package/unitypkg/Editor/Infrastructure/UnityCliScriptableObjectHelpers.cs +235 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSerializer.cs +580 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSessionMutationLease.cs +568 -0
- package/unitypkg/Editor/Infrastructure/UnityCliStateIO.cs +73 -0
- package/unitypkg/Editor/Infrastructure/UnityCliTestRunCoordinator.cs +598 -0
- package/unitypkg/Editor/Infrastructure/UnityCliTransactionLog.cs +112 -0
- package/unitypkg/Editor/Infrastructure/UnityCliValueConverter.cs +146 -0
- package/unitypkg/Editor/Infrastructure/UnityCliWaiter.cs +716 -0
- package/unitypkg/Editor/ProjectTools/IUnityCliTool.cs +152 -0
- package/unitypkg/Editor/ProjectTools/OfficialAttributeToolRegistry.cs +992 -0
- package/unitypkg/Editor/ProjectTools/ProjectToolRegistry.cs +938 -0
- package/unitypkg/Editor/ProjectTools/ProjectToolSchemaValidator.cs +258 -0
- package/unitypkg/Editor/ProjectTools/RegisteredTool.cs +75 -0
- package/unitypkg/Editor/ProjectTools/UnityCliProjectToolContext.cs +68 -0
- package/unitypkg/Editor/ProjectTools/UnityCliSchemaDeriver.cs +297 -0
- package/unitypkg/Editor/Protocol/ProtocolEnvelopeFactory.cs +92 -0
- package/unitypkg/Editor/Protocol/envelope.cs +50 -0
- package/unitypkg/Editor/Roslyn/LICENSE.txt +23 -0
- package/unitypkg/Editor/Roslyn/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/unitypkg/Editor/Roslyn/Microsoft.CodeAnalysis.dll +0 -0
- package/unitypkg/Editor/Roslyn/System.Collections.Immutable.dll +0 -0
- package/unitypkg/Editor/Roslyn/System.Reflection.Metadata.dll +0 -0
- package/unitypkg/Editor/Tools/animation/AnimationToolSupport.cs +335 -0
- package/unitypkg/Editor/Tools/animation/AnimatorRuntimeToolSupport.cs +24 -0
- package/unitypkg/Editor/Tools/animation/animator/crossfade.cs +117 -0
- package/unitypkg/Editor/Tools/animation/animator/get-info.cs +24 -0
- package/unitypkg/Editor/Tools/animation/animator/get-parameter.cs +36 -0
- package/unitypkg/Editor/Tools/animation/animator/set-enabled.cs +33 -0
- package/unitypkg/Editor/Tools/animation/animator/set-parameter.cs +71 -0
- package/unitypkg/Editor/Tools/animation/animator/set-speed.cs +33 -0
- package/unitypkg/Editor/Tools/animation/clip/create.cs +48 -0
- package/unitypkg/Editor/Tools/animation/clip/modify.cs +43 -0
- package/unitypkg/Editor/Tools/animation/clip.cs +23 -0
- package/unitypkg/Editor/Tools/animation/play.cs +41 -0
- package/unitypkg/Editor/Tools/animation/state.cs +25 -0
- package/unitypkg/Editor/Tools/animation/stop.cs +45 -0
- package/unitypkg/Editor/Tools/asset/AssetImportSettingsToolSupport.cs +633 -0
- package/unitypkg/Editor/Tools/asset/AssetToolSupport.cs +253 -0
- package/unitypkg/Editor/Tools/asset/create.cs +84 -0
- package/unitypkg/Editor/Tools/asset/delete.cs +88 -0
- package/unitypkg/Editor/Tools/asset/duplicate.cs +68 -0
- package/unitypkg/Editor/Tools/asset/get-components.cs +177 -0
- package/unitypkg/Editor/Tools/asset/get-data.cs +73 -0
- package/unitypkg/Editor/Tools/asset/import-settings/set.cs +127 -0
- package/unitypkg/Editor/Tools/asset/import-settings.cs +54 -0
- package/unitypkg/Editor/Tools/asset/import.cs +132 -0
- package/unitypkg/Editor/Tools/asset/info.cs +48 -0
- package/unitypkg/Editor/Tools/asset/modify.cs +69 -0
- package/unitypkg/Editor/Tools/asset/move.cs +70 -0
- package/unitypkg/Editor/Tools/asset/preview.cs +86 -0
- package/unitypkg/Editor/Tools/asset/rename.cs +84 -0
- package/unitypkg/Editor/Tools/asset/search-built-in.cs +90 -0
- package/unitypkg/Editor/Tools/asset/search.cs +83 -0
- package/unitypkg/Editor/Tools/build/BuildSceneStateTool.cs +37 -0
- package/unitypkg/Editor/Tools/build/BuildSettingsToolSupport.cs +4 -0
- package/unitypkg/Editor/Tools/build/BuildToolDtos.cs +15 -0
- package/unitypkg/Editor/Tools/build/BuildToolSupport.cs +111 -0
- package/unitypkg/Editor/Tools/build/platform/get.cs +12 -0
- package/unitypkg/Editor/Tools/build/platform/set.cs +45 -0
- package/unitypkg/Editor/Tools/build/profile/create.cs +44 -0
- package/unitypkg/Editor/Tools/build/profile/list.cs +12 -0
- package/unitypkg/Editor/Tools/build/profile/modify.cs +42 -0
- package/unitypkg/Editor/Tools/build/profile/switch.cs +30 -0
- package/unitypkg/Editor/Tools/build/scene/add.cs +45 -0
- package/unitypkg/Editor/Tools/build/scene/disable.cs +3 -0
- package/unitypkg/Editor/Tools/build/scene/enable.cs +4 -0
- package/unitypkg/Editor/Tools/build/scene/list.cs +4 -0
- package/unitypkg/Editor/Tools/build/scene/remove.cs +29 -0
- package/unitypkg/Editor/Tools/build/settings/get.cs +3 -0
- package/unitypkg/Editor/Tools/build/settings/set.cs +74 -0
- package/unitypkg/Editor/Tools/camera/CameraToolSupport.cs +292 -0
- package/unitypkg/Editor/Tools/camera/create.cs +114 -0
- package/unitypkg/Editor/Tools/camera/info.cs +49 -0
- package/unitypkg/Editor/Tools/camera/lens.cs +119 -0
- package/unitypkg/Editor/Tools/camera/list.cs +52 -0
- package/unitypkg/Editor/Tools/camera/multiview.cs +96 -0
- package/unitypkg/Editor/Tools/camera/screenshot.cs +65 -0
- package/unitypkg/Editor/Tools/camera/target.cs +94 -0
- package/unitypkg/Editor/Tools/component/add.cs +125 -0
- package/unitypkg/Editor/Tools/component/get.cs +73 -0
- package/unitypkg/Editor/Tools/component/list-types.cs +90 -0
- package/unitypkg/Editor/Tools/component/modify.cs +103 -0
- package/unitypkg/Editor/Tools/component/remove.cs +147 -0
- package/unitypkg/Editor/Tools/component/set.cs +93 -0
- package/unitypkg/Editor/Tools/console/clear.cs +38 -0
- package/unitypkg/Editor/Tools/console/get.cs +28 -0
- package/unitypkg/Editor/Tools/controller/add-blend-tree-child.cs +88 -0
- package/unitypkg/Editor/Tools/controller/add-layer.cs +43 -0
- package/unitypkg/Editor/Tools/controller/add-parameter.cs +51 -0
- package/unitypkg/Editor/Tools/controller/add-state.cs +44 -0
- package/unitypkg/Editor/Tools/controller/add-transition.cs +71 -0
- package/unitypkg/Editor/Tools/controller/assign.cs +38 -0
- package/unitypkg/Editor/Tools/controller/create-blend-tree-1d.cs +40 -0
- package/unitypkg/Editor/Tools/controller/create-blend-tree-2d.cs +42 -0
- package/unitypkg/Editor/Tools/controller/create.cs +31 -0
- package/unitypkg/Editor/Tools/controller/get-info.cs +27 -0
- package/unitypkg/Editor/Tools/controller/remove-layer.cs +57 -0
- package/unitypkg/Editor/Tools/controller/set-layer-weight.cs +42 -0
- package/unitypkg/Editor/Tools/diagnose/preflight.cs +269 -0
- package/unitypkg/Editor/Tools/editor/EditorActionToolSupport.cs +117 -0
- package/unitypkg/Editor/Tools/editor/EditorSearchToolSupport.cs +146 -0
- package/unitypkg/Editor/Tools/editor/EditorToolSupport.cs +132 -0
- package/unitypkg/Editor/Tools/editor/EditorWindowFocusToolSupport.cs +194 -0
- package/unitypkg/Editor/Tools/editor/active-tool/set.cs +33 -0
- package/unitypkg/Editor/Tools/editor/active-tool.cs +100 -0
- package/unitypkg/Editor/Tools/editor/autotick/set.cs +102 -0
- package/unitypkg/Editor/Tools/editor/console.cs +26 -0
- package/unitypkg/Editor/Tools/editor/focus.cs +80 -0
- package/unitypkg/Editor/Tools/editor/menu-items.cs +50 -0
- package/unitypkg/Editor/Tools/editor/menu.cs +53 -0
- package/unitypkg/Editor/Tools/editor/pause.cs +38 -0
- package/unitypkg/Editor/Tools/editor/play.cs +43 -0
- package/unitypkg/Editor/Tools/editor/redo.cs +56 -0
- package/unitypkg/Editor/Tools/editor/resolution.cs +34 -0
- package/unitypkg/Editor/Tools/editor/search.cs +55 -0
- package/unitypkg/Editor/Tools/editor/selection/set.cs +37 -0
- package/unitypkg/Editor/Tools/editor/selection.cs +153 -0
- package/unitypkg/Editor/Tools/editor/stop.cs +43 -0
- package/unitypkg/Editor/Tools/editor/tool-states.cs +140 -0
- package/unitypkg/Editor/Tools/editor/undo.cs +56 -0
- package/unitypkg/Editor/Tools/editor/windows.cs +87 -0
- package/unitypkg/Editor/Tools/extension/status.cs +87 -0
- package/unitypkg/Editor/Tools/go/GameObjectToolSupport.cs +524 -0
- package/unitypkg/Editor/Tools/go/create.cs +333 -0
- package/unitypkg/Editor/Tools/go/delete.cs +87 -0
- package/unitypkg/Editor/Tools/go/duplicate.cs +76 -0
- package/unitypkg/Editor/Tools/go/find.cs +152 -0
- package/unitypkg/Editor/Tools/go/inspect.cs +49 -0
- package/unitypkg/Editor/Tools/go/look-at.cs +76 -0
- package/unitypkg/Editor/Tools/go/modify.cs +156 -0
- package/unitypkg/Editor/Tools/go/move-relative.cs +74 -0
- package/unitypkg/Editor/Tools/go/set-parent.cs +84 -0
- package/unitypkg/Editor/Tools/graphics/GraphicsToolSupport.cs +396 -0
- package/unitypkg/Editor/Tools/graphics/bake-cancel.cs +27 -0
- package/unitypkg/Editor/Tools/graphics/bake-clear.cs +31 -0
- package/unitypkg/Editor/Tools/graphics/bake-reflection-probe.cs +35 -0
- package/unitypkg/Editor/Tools/graphics/bake-settings.cs +131 -0
- package/unitypkg/Editor/Tools/graphics/bake-start.cs +27 -0
- package/unitypkg/Editor/Tools/graphics/bake-status.cs +31 -0
- package/unitypkg/Editor/Tools/graphics/light-probe-group.cs +56 -0
- package/unitypkg/Editor/Tools/graphics/pipeline-info.cs +19 -0
- package/unitypkg/Editor/Tools/graphics/pipeline-quality.cs +24 -0
- package/unitypkg/Editor/Tools/graphics/pipeline-settings.cs +46 -0
- package/unitypkg/Editor/Tools/graphics/probe-positions.cs +58 -0
- package/unitypkg/Editor/Tools/graphics/quality.cs +85 -0
- package/unitypkg/Editor/Tools/graphics/reflection-probe.cs +73 -0
- package/unitypkg/Editor/Tools/graphics/scene-debug.cs +37 -0
- package/unitypkg/Editor/Tools/graphics/settings.cs +104 -0
- package/unitypkg/Editor/Tools/graphics/skybox-get.cs +33 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-ambient.cs +24 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-fog.cs +24 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-material.cs +33 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-properties.cs +51 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-reflection.cs +31 -0
- package/unitypkg/Editor/Tools/graphics/skybox-set-sun.cs +35 -0
- package/unitypkg/Editor/Tools/graphics/stats-counters.cs +28 -0
- package/unitypkg/Editor/Tools/graphics/stats-memory.cs +21 -0
- package/unitypkg/Editor/Tools/graphics/stats.cs +17 -0
- package/unitypkg/Editor/Tools/graphics/volume.cs +59 -0
- package/unitypkg/Editor/Tools/instances/list.cs +71 -0
- package/unitypkg/Editor/Tools/material/MaterialToolSupport.cs +401 -0
- package/unitypkg/Editor/Tools/material/assign.cs +124 -0
- package/unitypkg/Editor/Tools/material/create.cs +82 -0
- package/unitypkg/Editor/Tools/material/info.cs +55 -0
- package/unitypkg/Editor/Tools/material/set-renderer-color.cs +108 -0
- package/unitypkg/Editor/Tools/material/set.cs +114 -0
- package/unitypkg/Editor/Tools/navmesh/NavMeshToolSupport.cs +404 -0
- package/unitypkg/Editor/Tools/navmesh/bake-clear.cs +70 -0
- package/unitypkg/Editor/Tools/navmesh/settings/set.cs +73 -0
- package/unitypkg/Editor/Tools/navmesh/settings.cs +37 -0
- package/unitypkg/Editor/Tools/object/ObjectToolSupport.cs +99 -0
- package/unitypkg/Editor/Tools/object/get-data.cs +69 -0
- package/unitypkg/Editor/Tools/object/modify.cs +126 -0
- package/unitypkg/Editor/Tools/occlusion/OcclusionToolSupport.cs +422 -0
- package/unitypkg/Editor/Tools/occlusion/bake-clear.cs +67 -0
- package/unitypkg/Editor/Tools/physics/PhysicsJointToolSupport.cs +13 -0
- package/unitypkg/Editor/Tools/physics/PhysicsToolSupport.cs +389 -0
- package/unitypkg/Editor/Tools/physics/assign-material.cs +88 -0
- package/unitypkg/Editor/Tools/physics/collision-matrix.cs +90 -0
- package/unitypkg/Editor/Tools/physics/force.cs +127 -0
- package/unitypkg/Editor/Tools/physics/joint/add.cs +99 -0
- package/unitypkg/Editor/Tools/physics/joint/remove.cs +4 -0
- package/unitypkg/Editor/Tools/physics/linecast.cs +59 -0
- package/unitypkg/Editor/Tools/physics/material.cs +73 -0
- package/unitypkg/Editor/Tools/physics/overlap.cs +84 -0
- package/unitypkg/Editor/Tools/physics/raycast-all.cs +67 -0
- package/unitypkg/Editor/Tools/physics/raycast.cs +96 -0
- package/unitypkg/Editor/Tools/physics/rigidbody.cs +116 -0
- package/unitypkg/Editor/Tools/physics/settings.cs +116 -0
- package/unitypkg/Editor/Tools/physics/shapecast.cs +127 -0
- package/unitypkg/Editor/Tools/physics/simulation.cs +89 -0
- package/unitypkg/Editor/Tools/physics/validate.cs +67 -0
- package/unitypkg/Editor/Tools/prefab/PrefabOverrideToolSupport.cs +355 -0
- package/unitypkg/Editor/Tools/prefab/PrefabToolSupport.cs +446 -0
- package/unitypkg/Editor/Tools/prefab/create.cs +125 -0
- package/unitypkg/Editor/Tools/prefab/hierarchy.cs +157 -0
- package/unitypkg/Editor/Tools/prefab/info.cs +44 -0
- package/unitypkg/Editor/Tools/prefab/instantiate.cs +106 -0
- package/unitypkg/Editor/Tools/prefab/modify.cs +112 -0
- package/unitypkg/Editor/Tools/prefab/overrides/apply.cs +51 -0
- package/unitypkg/Editor/Tools/prefab/overrides/revert.cs +51 -0
- package/unitypkg/Editor/Tools/prefab/stage-close.cs +67 -0
- package/unitypkg/Editor/Tools/prefab/stage-open.cs +69 -0
- package/unitypkg/Editor/Tools/prefab/stage-save.cs +64 -0
- package/unitypkg/Editor/Tools/prefab/stage.cs +68 -0
- package/unitypkg/Editor/Tools/prefab/unpack.cs +80 -0
- package/unitypkg/Editor/Tools/prefab/variant/create.cs +53 -0
- package/unitypkg/Editor/Tools/profiler/ProfilerFrameDebuggerSupport.cs +68 -0
- package/unitypkg/Editor/Tools/profiler/ProfilerMemorySnapshotSupport.cs +30 -0
- package/unitypkg/Editor/Tools/profiler/ProfilerToolSupport.cs +515 -0
- package/unitypkg/Editor/Tools/profiler/areas.cs +36 -0
- package/unitypkg/Editor/Tools/profiler/capture.cs +188 -0
- package/unitypkg/Editor/Tools/profiler/clear.cs +57 -0
- package/unitypkg/Editor/Tools/profiler/counter.cs +34 -0
- package/unitypkg/Editor/Tools/profiler/deep.cs +48 -0
- package/unitypkg/Editor/Tools/profiler/export.cs +85 -0
- package/unitypkg/Editor/Tools/profiler/frame-debugger/disable.cs +53 -0
- package/unitypkg/Editor/Tools/profiler/frame-debugger/enable.cs +66 -0
- package/unitypkg/Editor/Tools/profiler/frame-debugger/events.cs +140 -0
- package/unitypkg/Editor/Tools/profiler/frame.cs +38 -0
- package/unitypkg/Editor/Tools/profiler/hierarchy.cs +183 -0
- package/unitypkg/Editor/Tools/profiler/load.cs +85 -0
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/compare.cs +78 -0
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/list.cs +73 -0
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/take.cs +147 -0
- package/unitypkg/Editor/Tools/profiler/memory.cs +34 -0
- package/unitypkg/Editor/Tools/profiler/module-enable.cs +52 -0
- package/unitypkg/Editor/Tools/profiler/modules.cs +33 -0
- package/unitypkg/Editor/Tools/profiler/object-memory.cs +49 -0
- package/unitypkg/Editor/Tools/profiler/pause.cs +49 -0
- package/unitypkg/Editor/Tools/profiler/rendering-stats.cs +109 -0
- package/unitypkg/Editor/Tools/profiler/script-stats.cs +35 -0
- package/unitypkg/Editor/Tools/profiler/start.cs +55 -0
- package/unitypkg/Editor/Tools/profiler/status.cs +36 -0
- package/unitypkg/Editor/Tools/profiler/stop.cs +53 -0
- package/unitypkg/Editor/Tools/project/ProjectSettingsReader.cs +31 -0
- package/unitypkg/Editor/Tools/project/ProjectSettingsToolSupport.cs +757 -0
- package/unitypkg/Editor/Tools/project/ProjectTagLayerToolSupport.cs +23 -0
- package/unitypkg/Editor/Tools/project/audio-settings/set.cs +35 -0
- package/unitypkg/Editor/Tools/project/audio-settings.cs +31 -0
- package/unitypkg/Editor/Tools/project/info.cs +52 -0
- package/unitypkg/Editor/Tools/project/input-settings/set.cs +35 -0
- package/unitypkg/Editor/Tools/project/input-settings.cs +35 -0
- package/unitypkg/Editor/Tools/project/layer/add.cs +3 -0
- package/unitypkg/Editor/Tools/project/layer/remove.cs +3 -0
- package/unitypkg/Editor/Tools/project/layers.cs +61 -0
- package/unitypkg/Editor/Tools/project/player-settings/set.cs +35 -0
- package/unitypkg/Editor/Tools/project/player-settings.cs +31 -0
- package/unitypkg/Editor/Tools/project/tag/add.cs +3 -0
- package/unitypkg/Editor/Tools/project/tag/remove.cs +3 -0
- package/unitypkg/Editor/Tools/project/tags.cs +45 -0
- package/unitypkg/Editor/Tools/project/time-settings/set.cs +35 -0
- package/unitypkg/Editor/Tools/project/time-settings.cs +31 -0
- package/unitypkg/Editor/Tools/reflection/method/call.cs +114 -0
- package/unitypkg/Editor/Tools/reflection/method/find.cs +72 -0
- package/unitypkg/Editor/Tools/reflection/type/schema.cs +56 -0
- package/unitypkg/Editor/Tools/scene/SceneToolSupport.cs +181 -0
- package/unitypkg/Editor/Tools/scene/active.cs +62 -0
- package/unitypkg/Editor/Tools/scene/build-settings.cs +69 -0
- package/unitypkg/Editor/Tools/scene/create.cs +78 -0
- package/unitypkg/Editor/Tools/scene/data.cs +125 -0
- package/unitypkg/Editor/Tools/scene/gameobject/component.cs +63 -0
- package/unitypkg/Editor/Tools/scene/gameobject/components.cs +77 -0
- package/unitypkg/Editor/Tools/scene/gameobject-support.cs +101 -0
- package/unitypkg/Editor/Tools/scene/gameobject.cs +83 -0
- package/unitypkg/Editor/Tools/scene/hierarchy.cs +250 -0
- package/unitypkg/Editor/Tools/scene/list-opened.cs +77 -0
- package/unitypkg/Editor/Tools/scene/load.cs +68 -0
- package/unitypkg/Editor/Tools/scene/move-object.cs +122 -0
- package/unitypkg/Editor/Tools/scene/save.cs +231 -0
- package/unitypkg/Editor/Tools/scene/set-active.cs +76 -0
- package/unitypkg/Editor/Tools/scene/unload.cs +109 -0
- package/unitypkg/Editor/Tools/scene/validate.cs +115 -0
- package/unitypkg/Editor/Tools/scene/view-frame.cs +218 -0
- package/unitypkg/Editor/Tools/screenshot/EditorElementCaptureToolSupport.cs +181 -0
- package/unitypkg/Editor/Tools/screenshot/ScreenshotToolSupport.cs +196 -0
- package/unitypkg/Editor/Tools/screenshot/editor-element.cs +87 -0
- package/unitypkg/Editor/Tools/screenshot/game-view.cs +116 -0
- package/unitypkg/Editor/Tools/screenshot/isolated-object.cs +93 -0
- package/unitypkg/Editor/Tools/screenshot/orbit.cs +103 -0
- package/unitypkg/Editor/Tools/screenshot/scene-view.cs +99 -0
- package/unitypkg/Editor/Tools/screenshot/screen.cs +89 -0
- package/unitypkg/Editor/Tools/screenshot/surround.cs +181 -0
- package/unitypkg/Editor/Tools/scriptable-object/ScriptableObjectToolSupport.cs +196 -0
- package/unitypkg/Editor/Tools/scriptable-object/create.cs +79 -0
- package/unitypkg/Editor/Tools/scriptable-object/info.cs +49 -0
- package/unitypkg/Editor/Tools/scriptable-object/list-types.cs +103 -0
- package/unitypkg/Editor/Tools/scriptable-object/modify.cs +208 -0
- package/unitypkg/Editor/Tools/shader/ShaderToolSupport.cs +326 -0
- package/unitypkg/Editor/Tools/shader/create.cs +82 -0
- package/unitypkg/Editor/Tools/shader/delete.cs +90 -0
- package/unitypkg/Editor/Tools/shader/get-data.cs +125 -0
- package/unitypkg/Editor/Tools/shader/info.cs +48 -0
- package/unitypkg/Editor/Tools/shader/list.cs +82 -0
- package/unitypkg/Editor/Tools/shader/read.cs +84 -0
- package/unitypkg/Editor/Tools/shader/update.cs +71 -0
- package/unitypkg/Editor/Tools/tests/list.cs +98 -0
- package/unitypkg/Editor/Tools/texture/TextureToolSupport.cs +327 -0
- package/unitypkg/Editor/Tools/texture/create.cs +182 -0
- package/unitypkg/Editor/Tools/texture/delete.cs +89 -0
- package/unitypkg/Editor/Tools/texture/generate.cs +189 -0
- package/unitypkg/Editor/Tools/texture/import-settings.cs +104 -0
- package/unitypkg/Editor/Tools/texture/info.cs +50 -0
- package/unitypkg/Editor/Tools/texture/modify.cs +154 -0
- package/unitypkg/Editor/Tools/texture/sprite.cs +132 -0
- package/unitypkg/Editor/Tools/timeline/TimelineMutationToolSupport.cs +696 -0
- package/unitypkg/Editor/Tools/timeline/TimelineReadToolSupport.cs +439 -0
- package/unitypkg/Editor/Tools/timeline/TimelineToolSupport.cs +203 -0
- package/unitypkg/Editor/Tools/timeline/clip/add.cs +93 -0
- package/unitypkg/Editor/Tools/timeline/create.cs +88 -0
- package/unitypkg/Editor/Tools/timeline/info.cs +54 -0
- package/unitypkg/Editor/Tools/timeline/track/add.cs +91 -0
- package/unitypkg/Editor/Tools/ui/UiToolSupport.cs +162 -0
- package/unitypkg/Editor/Tools/ui/UiUguiToolSupport.cs +24 -0
- package/unitypkg/Editor/Tools/ui/attach-document.cs +46 -0
- package/unitypkg/Editor/Tools/ui/button/create.cs +58 -0
- package/unitypkg/Editor/Tools/ui/canvas/create.cs +40 -0
- package/unitypkg/Editor/Tools/ui/create-panel-settings.cs +44 -0
- package/unitypkg/Editor/Tools/ui/detach-document.cs +41 -0
- package/unitypkg/Editor/Tools/ui/document/create.cs +49 -0
- package/unitypkg/Editor/Tools/ui/document/delete.cs +33 -0
- package/unitypkg/Editor/Tools/ui/document/info.cs +33 -0
- package/unitypkg/Editor/Tools/ui/document/update.cs +36 -0
- package/unitypkg/Editor/Tools/ui/get-visual-tree.cs +34 -0
- package/unitypkg/Editor/Tools/ui/hierarchy.cs +27 -0
- package/unitypkg/Editor/Tools/ui/image/create.cs +47 -0
- package/unitypkg/Editor/Tools/ui/link-stylesheet.cs +54 -0
- package/unitypkg/Editor/Tools/ui/list-documents.cs +34 -0
- package/unitypkg/Editor/Tools/ui/modify-visual-element.cs +76 -0
- package/unitypkg/Editor/Tools/ui/render-preview.cs +128 -0
- package/unitypkg/Editor/Tools/ui/text/create.cs +45 -0
- package/unitypkg/Editor/Tools/ui/update-panel-settings.cs +49 -0
- package/unitypkg/Editor/UnityCliBridge.cs +431 -0
- package/unitypkg/Editor/UnityCliBridgeBuildInfo.cs +9 -0
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeBridge.cs +580 -0
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeJson.cs +232 -0
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeRegistry.cs +297 -0
- package/unitypkg/Runtime/Tools/UnityCliRuntimeTools.cs +701 -0
- package/unitypkg/Runtime/UnityCli.Runtime.asmdef +14 -0
- package/unitypkg/Shared/UnityCli.Shared.asmdef +14 -0
- package/unitypkg/Shared/UnityCliAdmissionPool.cs +426 -0
- package/unitypkg/Tests/Editor/UnityCli.Editor.Tests.asmdef +15 -0
- package/unitypkg/Tests/Editor/UnityCliAdmissionPoolTests.cs +262 -0
- package/unitypkg/UnityCli.Editor.asmdef +26 -0
- package/unitypkg/package.json +11 -0
|
@@ -0,0 +1,1137 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
5
|
+
import { defaultDataDir } from "./platform.js";
|
|
6
|
+
import { failure, success } from "./output.js";
|
|
7
|
+
import { stripBom } from "./util.js";
|
|
8
|
+
import { getBoolean } from "./args.js";
|
|
9
|
+
import { stringFlag } from "./bridge/args.js";
|
|
10
|
+
import { findUnityProjectProcesses } from "./unity-project-processes.js";
|
|
11
|
+
import { CANONICALIZATION_VERSION, ProjectIdentityError, resolveProjectIdentity, resolveProjectIdentityAsync, resolveProjectIdentityFromCwd, resolveProjectIdentityFromCwdAsync, } from "./project-identity.js";
|
|
12
|
+
export const HEALTH_CHECK_TIMEOUT_MS = 300;
|
|
13
|
+
export const HEALTH_CACHE_TTL_MS = 1_000;
|
|
14
|
+
export const MAIN_THREAD_PULSE_FRESH_MS = 2_000;
|
|
15
|
+
const REGISTRY_READ_RETRY_DELAYS_MS = [5, 10, 20, 40];
|
|
16
|
+
const INSTANCE_ID_PATTERN = /^unity-[0-9a-f]{64}$/;
|
|
17
|
+
const SESSION_ID_PATTERN = /^session-[0-9a-f]{64}$/;
|
|
18
|
+
const LISTENER_ID_PATTERN = /^listener-[0-9a-f]{32}$/;
|
|
19
|
+
const ALIAS_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
|
|
20
|
+
const REGISTRY_LIFECYCLES = new Set(["ready", "transitioning", "blocked", "domain-reloading", "compiling", "importing", "building", "playmode-changing"]);
|
|
21
|
+
export class InstanceRegistryError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
nextActions;
|
|
24
|
+
details;
|
|
25
|
+
constructor(code, message, nextActions = [], details) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.nextActions = nextActions;
|
|
29
|
+
this.details = details;
|
|
30
|
+
this.name = "InstanceRegistryError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const healthCache = new Map();
|
|
34
|
+
const PROJECT_PROCESS_CLAIM_TIMEOUT_MS = 10_000;
|
|
35
|
+
const PROCESS_OBSERVATION_TIMEOUT_MS = 3_000;
|
|
36
|
+
/** 清空仅成功 health identity 的短缓存;失败探测从不缓存。 */
|
|
37
|
+
export function clearInstanceHealthCache() {
|
|
38
|
+
healthCache.clear();
|
|
39
|
+
}
|
|
40
|
+
/** 顶层 instances 控制面只读 registry;prune 由 C# writer 的 PID/start-time reducer 完成。 */
|
|
41
|
+
export async function handleInstancesCommand(command, flags, dataDir, requestId) {
|
|
42
|
+
const includeAll = getBoolean(flags, "all");
|
|
43
|
+
if (command === "list" || !command) {
|
|
44
|
+
const { instances, invalidRecordCount } = await readInstancesWithProjectProcessClaims(dataDir);
|
|
45
|
+
const aliasByInstanceId = new Map((await readAliasStore(dataDir)).aliases.map((binding) => [binding.instanceId, binding.alias]));
|
|
46
|
+
// 默认只展示有 session 的活跃实例;offline 历史残留用 --all 展开,避免上下文污染。
|
|
47
|
+
const visible = includeAll ? instances : instances.filter((instance) => instance.status !== "offline");
|
|
48
|
+
const hiddenOfflineCount = instances.length - visible.length;
|
|
49
|
+
return success(requestId, {
|
|
50
|
+
instances: visible.map((instance) => {
|
|
51
|
+
const summary = instanceListSummary(instance);
|
|
52
|
+
const alias = aliasByInstanceId.get(instance.instanceId);
|
|
53
|
+
return alias ? { ...summary, alias } : summary;
|
|
54
|
+
}),
|
|
55
|
+
...(includeAll || hiddenOfflineCount === 0 ? {} : { hiddenOfflineCount }),
|
|
56
|
+
...(invalidRecordCount === 0 ? {} : { invalidRecordCount }),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (command === "prune") {
|
|
60
|
+
const { instances, invalidRecordCount } = await readInstancesWithProjectProcessClaims(dataDir);
|
|
61
|
+
return success(requestId, {
|
|
62
|
+
removed: 0,
|
|
63
|
+
remaining: instances.length,
|
|
64
|
+
...(invalidRecordCount === 0 ? {} : { invalidRecordCount }),
|
|
65
|
+
writer: "unity-bridge",
|
|
66
|
+
note: "Only the C# registry writer may remove PID/start-time-invalid claims or expired offline records.",
|
|
67
|
+
instances: instances.map(instanceListSummary),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return failure(requestId, "UNKNOWN_INSTANCES_COMMAND", "Expected instances list or instances prune.", [
|
|
71
|
+
"Run unitycli instances list to inspect project identities and Editor sessions.",
|
|
72
|
+
"Run unitycli instances prune to request writer-owned cleanup.",
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
/** 顶层 target 只保留 canonical project identity alias 管理。 */
|
|
76
|
+
export async function handleTargetCommand(command, positional, flags, dataDir, requestId) {
|
|
77
|
+
if (command !== "alias") {
|
|
78
|
+
return failure(requestId, "UNKNOWN_TARGET_COMMAND", "Only target alias list|set|unset is supported.", [
|
|
79
|
+
"Run unitycli target alias list.",
|
|
80
|
+
"Pass --instance <instanceId|projectPath|alias> or run from a Unity project directory.",
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
return handleTargetAliasCommand(positional[0], positional.slice(1), flags, dataDir, requestId);
|
|
84
|
+
}
|
|
85
|
+
/** alias 永久绑定 canonical project identity,可在 Editor offline 时解析。 */
|
|
86
|
+
async function handleTargetAliasCommand(command, positional, flags, dataDir, requestId) {
|
|
87
|
+
const store = await readAliasStore(dataDir);
|
|
88
|
+
if (!command || command === "list") {
|
|
89
|
+
const instances = await readInstances(dataDir);
|
|
90
|
+
return success(requestId, {
|
|
91
|
+
aliases: store.aliases.map((binding) => ({
|
|
92
|
+
...binding,
|
|
93
|
+
status: instances.find((instance) => instance.instanceId === binding.instanceId)?.status ?? "offline",
|
|
94
|
+
})),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (command === "set") {
|
|
98
|
+
let explicitInstance;
|
|
99
|
+
try {
|
|
100
|
+
explicitInstance = explicitInstanceSelector(flags);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
return instanceSelectionFailure(requestId, error) ?? failure(requestId, "E_INSTANCE_REQUIRED", error instanceof Error ? error.message : String(error));
|
|
104
|
+
}
|
|
105
|
+
const selector = positional[0] ?? explicitInstance ?? stringFlag(flags, "project");
|
|
106
|
+
const alias = positional[1] ?? stringFlag(flags, "alias");
|
|
107
|
+
if (!selector || !alias) {
|
|
108
|
+
return failure(requestId, "E_INSTANCE_NOT_FOUND", "target alias set requires <projectPath|instanceId> <alias>.", [
|
|
109
|
+
"Pass an existing Unity project path or a full deterministic instanceId.",
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
if (!ALIAS_PATTERN.test(alias)) {
|
|
113
|
+
return failure(requestId, "E_TARGET_ALIAS_INVALID", "Alias must contain 1-64 ASCII letters, digits, dots, underscores, or hyphens.");
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const identity = await resolveAliasIdentity(selector, dataDir);
|
|
117
|
+
const existing = store.aliases.find((binding) => binding.alias === alias);
|
|
118
|
+
if (existing && existing.instanceId !== identity.instanceId && !getBoolean(flags, "force")) {
|
|
119
|
+
return failure(requestId, "E_TARGET_ALIAS_CONFLICT", `Target alias already points to another project identity: ${alias}.`, [
|
|
120
|
+
"Run unitycli target alias unset <alias> before assigning it.",
|
|
121
|
+
"Pass --force to replace the binding deliberately.",
|
|
122
|
+
], { alias, existingInstanceId: existing.instanceId, requestedInstanceId: identity.instanceId });
|
|
123
|
+
}
|
|
124
|
+
const aliases = store.aliases.filter((binding) => binding.alias !== alias);
|
|
125
|
+
aliases.push(aliasBinding(alias, identity));
|
|
126
|
+
await writeAliasStore(dataDir, { version: 2, revision: store.revision + 1, aliases: aliases.sort((left, right) => left.alias.localeCompare(right.alias)) });
|
|
127
|
+
return success(requestId, {
|
|
128
|
+
alias,
|
|
129
|
+
identity: aliasBinding(alias, identity),
|
|
130
|
+
replacedInstanceId: existing && existing.instanceId !== identity.instanceId ? existing.instanceId : null,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
return instanceSelectionFailure(requestId, error) ?? failure(requestId, "E_INSTANCE_NOT_FOUND", error instanceof Error ? error.message : String(error));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (command === "unset") {
|
|
138
|
+
const alias = positional[0] ?? stringFlag(flags, "alias");
|
|
139
|
+
const existing = alias ? store.aliases.find((binding) => binding.alias === alias) : undefined;
|
|
140
|
+
if (!alias || !existing) {
|
|
141
|
+
return failure(requestId, "E_INSTANCE_NOT_FOUND", `Target alias not found: ${alias ?? ""}.`, ["Run unitycli target alias list."]);
|
|
142
|
+
}
|
|
143
|
+
await writeAliasStore(dataDir, { version: 2, revision: store.revision + 1, aliases: store.aliases.filter((binding) => binding.alias !== alias) });
|
|
144
|
+
return success(requestId, { alias, instanceId: existing.instanceId });
|
|
145
|
+
}
|
|
146
|
+
return failure(requestId, "UNKNOWN_TARGET_ALIAS_COMMAND", "Expected target alias list, target alias set <projectPath|instanceId> <alias>, or target alias unset <alias>.");
|
|
147
|
+
}
|
|
148
|
+
/** 显式 instance flag 一旦出现就必须携带非空 selector,禁止降级到 CWD。 */
|
|
149
|
+
function explicitInstanceSelector(flags) {
|
|
150
|
+
if (!Object.prototype.hasOwnProperty.call(flags, "instance"))
|
|
151
|
+
return undefined;
|
|
152
|
+
const value = flags.instance;
|
|
153
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
154
|
+
throw new InstanceRegistryError("E_INSTANCE_REQUIRED", "--instance requires a non-empty full instance id, project path, or alias.", [
|
|
155
|
+
"Pass --instance <full-id|projectPath|alias>, or remove the flag to select from the current Unity project CWD."
|
|
156
|
+
]);
|
|
157
|
+
}
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
/** 离线 project constraint/discovery 使用 canonical identity,不依赖 active target 或单实例 fallback。 */
|
|
161
|
+
export async function currentInstanceProjectPath(flags, dataDir, cwd = process.cwd()) {
|
|
162
|
+
try {
|
|
163
|
+
const explicit = explicitInstanceSelector(flags);
|
|
164
|
+
if (explicit === undefined)
|
|
165
|
+
return resolveProjectIdentityFromCwd(cwd).displayProjectPath;
|
|
166
|
+
const identity = await resolveSelectorIdentity(explicit, dataDir);
|
|
167
|
+
return identity.displayProjectPath;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** 严格 selector:完整 ID/path/alias,或 CWD 中最近 Unity project root。 */
|
|
174
|
+
export async function selectInstanceForFlags(flags, dataDir, cwd = process.cwd(), target = "editor") {
|
|
175
|
+
const selection = await resolveInstanceSelectionIdentity(flags, dataDir, cwd);
|
|
176
|
+
const record = await readRegistryRecord(dataDir, selection.identity.instanceId);
|
|
177
|
+
if (!record)
|
|
178
|
+
throw missingSelectedInstance(selection.identity, selection.explicit, target);
|
|
179
|
+
const observations = await probeProcessObservations(record.sessions.map((session) => session.processId));
|
|
180
|
+
const instance = await reduceRegistryRecord(record, observations, Date.now(), target);
|
|
181
|
+
assertRegistryIdentity(instance, selection.identity);
|
|
182
|
+
// Editor 命令行 claim 只补充发现可正向归因的重复进程;正式启动不要求携带 -projectPath。
|
|
183
|
+
const inspected = target === "editor"
|
|
184
|
+
? applyProjectProcessClaimInspection(instance, await inspectProjectProcessClaimsWithConvergence(selection.identity))
|
|
185
|
+
: instance;
|
|
186
|
+
if (inspected.status === "offline")
|
|
187
|
+
throw targetNotRunning(inspected, target);
|
|
188
|
+
if (inspected.status === "conflict")
|
|
189
|
+
throw targetConflict(inspected, target);
|
|
190
|
+
if (inspected.status === "unverifiable")
|
|
191
|
+
throw targetUnverifiable(inspected, target);
|
|
192
|
+
return { instance: inspected, matchedBy: selection.matchedBy };
|
|
193
|
+
}
|
|
194
|
+
/** 即时观察选择器保留 offline/conflict/blocked 状态,绝不把状态归约为 selector 异常。 */
|
|
195
|
+
/** 单次 WMI/进程枚举不可验证时只重做一次纯读证明;真实 duplicate claim 不等待。 */
|
|
196
|
+
async function inspectProjectProcessClaimsWithConvergence(identity) {
|
|
197
|
+
const first = await inspectProjectProcessClaims(identity, PROJECT_PROCESS_CLAIM_TIMEOUT_MS);
|
|
198
|
+
if (first.verification !== "unverifiable")
|
|
199
|
+
return first;
|
|
200
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, 50));
|
|
201
|
+
return inspectProjectProcessClaims(identity, PROJECT_PROCESS_CLAIM_TIMEOUT_MS);
|
|
202
|
+
}
|
|
203
|
+
export async function selectObservationInstanceForFlags(flags, dataDir, remainingMs, cwd = process.cwd(), target = "editor") {
|
|
204
|
+
const observationDeadlineMs = remainingMs === undefined ? undefined : Date.now() + Math.max(0, remainingMs);
|
|
205
|
+
const selection = await resolveInstanceSelectionIdentity(flags, dataDir, cwd, observationDeadlineMs);
|
|
206
|
+
const record = await readRegistryRecord(dataDir, selection.identity.instanceId, observationDeadlineMs);
|
|
207
|
+
// observation 不要求 Bridge 已注册;canonical identity 仍可归因到启动中的 Unity process。
|
|
208
|
+
if (!record)
|
|
209
|
+
return { instance: offlineObservationInstance(selection.identity, target), matchedBy: selection.matchedBy };
|
|
210
|
+
const processBudgetMs = Math.max(0, observationDeadlineMs === undefined ? PROCESS_OBSERVATION_TIMEOUT_MS : observationDeadlineMs - Date.now());
|
|
211
|
+
const observations = await probeProcessObservations(record.sessions.map((session) => session.processId), processBudgetMs);
|
|
212
|
+
const instance = reduceObservationRegistryRecord(record, observations, target);
|
|
213
|
+
assertRegistryIdentity(instance, selection.identity);
|
|
214
|
+
return { instance, matchedBy: selection.matchedBy };
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* durable root 在 domain reload 中读取 journal 时不能依赖瞬时 /health ready。
|
|
218
|
+
* 该 selector 要求唯一 Registry claim 的 PID、process start 与 Unity.exe 成立;可正向归因的命令行 claim 不能与其冲突。
|
|
219
|
+
*/
|
|
220
|
+
export async function selectTransitionInstanceForFlags(flags, dataDir, remainingMs, cwd = process.cwd(), target = "editor") {
|
|
221
|
+
const deadlineMs = Date.now() + Math.max(0, remainingMs);
|
|
222
|
+
const selection = await selectObservationInstanceForFlags(flags, dataDir, Math.max(0, deadlineMs - Date.now()), cwd, target);
|
|
223
|
+
const instance = selection.instance;
|
|
224
|
+
const session = instance.activeSession;
|
|
225
|
+
if (!session || instance.status === "offline")
|
|
226
|
+
throw targetNotRunning(instance, target);
|
|
227
|
+
if (instance.status === "conflict")
|
|
228
|
+
throw targetConflict(instance, target);
|
|
229
|
+
if (instance.status === "unverifiable")
|
|
230
|
+
throw targetUnverifiable(instance, target);
|
|
231
|
+
const identity = {
|
|
232
|
+
instanceId: instance.instanceId,
|
|
233
|
+
canonicalProjectPath: instance.canonicalProjectPath,
|
|
234
|
+
displayProjectPath: instance.displayProjectPath,
|
|
235
|
+
};
|
|
236
|
+
const processBudgetMs = Math.max(0, deadlineMs - Date.now());
|
|
237
|
+
const [verification, claims] = await Promise.all([
|
|
238
|
+
verifyRegistrySessionProcess(identity, session, processBudgetMs),
|
|
239
|
+
target === "editor" ? inspectProjectProcessClaims(identity, processBudgetMs) : Promise.resolve(undefined),
|
|
240
|
+
]);
|
|
241
|
+
const contradictoryClaim = target === "editor"
|
|
242
|
+
&& claims?.verification === "verified"
|
|
243
|
+
&& claims.processIds.length > 0
|
|
244
|
+
&& (claims.processIds.length !== 1 || claims.processIds[0] !== session.processId);
|
|
245
|
+
if (verification === "dead")
|
|
246
|
+
throw targetNotRunning(instance, target);
|
|
247
|
+
if (verification !== "verified" || contradictoryClaim) {
|
|
248
|
+
throw targetUnverifiable({ ...instance, processClaimIds: claims?.processIds ?? [] }, target);
|
|
249
|
+
}
|
|
250
|
+
return { instance: { ...instance, ...(claims ? { processClaimIds: claims.processIds } : {}) }, matchedBy: selection.matchedBy };
|
|
251
|
+
}
|
|
252
|
+
/** registry 尚未写入时的只读 canonical identity 投影;绝不由 TS 创建 registry。 */
|
|
253
|
+
function offlineObservationInstance(identity, target) {
|
|
254
|
+
return {
|
|
255
|
+
instanceId: identity.instanceId, canonicalizationVersion: 1,
|
|
256
|
+
canonicalProjectPath: identity.canonicalProjectPath, displayProjectPath: identity.displayProjectPath,
|
|
257
|
+
projectPath: identity.displayProjectPath, projectName: projectNameFromPath(identity.displayProjectPath),
|
|
258
|
+
status: "offline", target, revision: 0, updatedAt: new Date(0).toISOString(), sessions: [], allSessions: [], progress: [], blockers: [],
|
|
259
|
+
claimVerification: "none",
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/** 两个 selector 共享 identity/flag 契约;仅 reducer 的可信度不同。 */
|
|
263
|
+
async function resolveInstanceSelectionIdentity(flags, dataDir, cwd, observationDeadlineMs) {
|
|
264
|
+
if (stringFlag(flags, "bridge-endpoint")) {
|
|
265
|
+
throw new InstanceRegistryError("E_OBSOLETE_OPTION", "--bridge-endpoint has been removed; transport binding is owned by the session supervisor.", [
|
|
266
|
+
"Pass --instance <instanceId|projectPath|alias> or run from the target Unity project directory.",
|
|
267
|
+
]);
|
|
268
|
+
}
|
|
269
|
+
const remainingSelectorBudget = () => observationDeadlineMs === undefined
|
|
270
|
+
? undefined
|
|
271
|
+
: Math.max(0, observationDeadlineMs - Date.now());
|
|
272
|
+
const explicit = explicitInstanceSelector(flags);
|
|
273
|
+
const identity = explicit !== undefined
|
|
274
|
+
? await resolveSelectorIdentity(explicit, dataDir, remainingSelectorBudget(), observationDeadlineMs)
|
|
275
|
+
: observationDeadlineMs === undefined
|
|
276
|
+
? resolveProjectIdentityFromCwd(cwd)
|
|
277
|
+
: await resolveProjectIdentityFromCwdAsync(cwd, { timeoutMs: remainingSelectorBudget() ?? 0 });
|
|
278
|
+
const matchedBy = explicit !== undefined
|
|
279
|
+
? (await readAliasStore(dataDir)).aliases.some((binding) => binding.alias === explicit)
|
|
280
|
+
? "alias"
|
|
281
|
+
: INSTANCE_ID_PATTERN.test(explicit)
|
|
282
|
+
? "instanceId"
|
|
283
|
+
: "projectPath"
|
|
284
|
+
: "cwd";
|
|
285
|
+
const projectConstraint = stringFlag(flags, "project");
|
|
286
|
+
if (projectConstraint) {
|
|
287
|
+
const constraint = observationDeadlineMs === undefined
|
|
288
|
+
? resolveProjectIdentity(projectConstraint)
|
|
289
|
+
: await resolveProjectIdentityAsync(projectConstraint, { timeoutMs: remainingSelectorBudget() ?? 0 });
|
|
290
|
+
if (constraint.instanceId !== identity.instanceId) {
|
|
291
|
+
throw new InstanceRegistryError("E_INSTANCE_PROJECT_MISMATCH", "The --project constraint does not match the selected Unity project identity.", [
|
|
292
|
+
"Pass a --project path inside the same Unity project as --instance or CWD.",
|
|
293
|
+
], { selectedInstanceId: identity.instanceId, projectInstanceId: constraint.instanceId });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return { identity, matchedBy, explicit };
|
|
297
|
+
}
|
|
298
|
+
function missingSelectedInstance(identity, explicit, target) {
|
|
299
|
+
const code = explicit && INSTANCE_ID_PATTERN.test(explicit) ? "E_INSTANCE_NOT_FOUND" : target === "runtime" ? "E_RUNTIME_NOT_RUNNING" : "E_INSTANCE_NOT_RUNNING";
|
|
300
|
+
return new InstanceRegistryError(code, `No ${target} registry record exists for the selected project identity.`, [
|
|
301
|
+
target === "runtime" ? "Launch a development Player built from this exact Unity project." : "Open this exact Unity project in Unity Editor.",
|
|
302
|
+
"Run unitycli instances list to inspect known project identities.",
|
|
303
|
+
], { instanceId: identity.instanceId, canonicalProjectPath: identity.canonicalProjectPath, target });
|
|
304
|
+
}
|
|
305
|
+
/** 为 target 离线返回稳定且可执行的选择错误。 */
|
|
306
|
+
function targetNotRunning(instance, target) {
|
|
307
|
+
return new InstanceRegistryError(target === "runtime" ? "E_RUNTIME_NOT_RUNNING" : "E_INSTANCE_NOT_RUNNING", `The selected Unity project has no active ${target} session.`, [
|
|
308
|
+
target === "runtime" ? "Launch a development Player built from this exact Unity project." : "Open this exact Unity project in Unity Editor.",
|
|
309
|
+
], { instance: instanceListSummary(instance), target });
|
|
310
|
+
}
|
|
311
|
+
/** conflict只表示已证明的同项目plural live claims。 */
|
|
312
|
+
function targetConflict(instance, target) {
|
|
313
|
+
return new InstanceRegistryError("E_INSTANCE_CONFLICT", `Multiple verified ${target} processes claim the selected canonical project identity.`, [
|
|
314
|
+
`Close every duplicate ${target} process except the intended session.`,
|
|
315
|
+
"Run unitycli instances list to inspect all verified claimants.",
|
|
316
|
+
], { instance: instanceListSummary(instance), target });
|
|
317
|
+
}
|
|
318
|
+
/** identity观察不完整时fail closed,但不得建议关闭并不存在的duplicate。 */
|
|
319
|
+
function targetUnverifiable(instance, target) {
|
|
320
|
+
return new InstanceRegistryError("E_INSTANCE_UNVERIFIABLE", `The selected ${target} process identity could not be verified safely.`, [
|
|
321
|
+
"Run unitycli instances list or tools run editor.state to observe the current identity again.",
|
|
322
|
+
"Do not retry a prior mutation whose outcome is unknown.",
|
|
323
|
+
], { instance: instanceListSummary(instance), target });
|
|
324
|
+
}
|
|
325
|
+
/** 即时观察只归约原始 registry:不得发 health 请求或扫描旧 PID。 */
|
|
326
|
+
export function reduceObservationRegistryRecord(record, observations, target = "editor") {
|
|
327
|
+
validateRegistryRecord(record);
|
|
328
|
+
const allSessions = observations
|
|
329
|
+
? record.sessions.filter((session) => claimIsAlive(session, observations.get(session.processId)))
|
|
330
|
+
: record.sessions;
|
|
331
|
+
const sessions = allSessions.filter((session) => session.target === target);
|
|
332
|
+
const verifiedSessions = observations
|
|
333
|
+
? sessions.filter((session) => observations.get(session.processId)?.state === "alive" && claimIsAlive(session, observations.get(session.processId)))
|
|
334
|
+
: [];
|
|
335
|
+
const processUnverifiable = observations === undefined || sessions.some((session) => observations.get(session.processId)?.state !== "alive");
|
|
336
|
+
const verifiedProcessIdentities = new Set(verifiedSessions.map(processIdentityKey));
|
|
337
|
+
const duplicateSessionClaim = verifiedSessions.length > 1 && verifiedProcessIdentities.size === 1;
|
|
338
|
+
const activeSession = !processUnverifiable && verifiedSessions.length === 1 ? verifiedSessions[0] : undefined;
|
|
339
|
+
const status = verifiedProcessIdentities.size > 1
|
|
340
|
+
? "conflict"
|
|
341
|
+
: (processUnverifiable || duplicateSessionClaim) && sessions.length > 0
|
|
342
|
+
? "unverifiable"
|
|
343
|
+
: verifiedSessions.length === 0
|
|
344
|
+
? "offline"
|
|
345
|
+
: activeSession.blockers.length > 0 || activeSession.lifecycle === "blocked"
|
|
346
|
+
? "blocked"
|
|
347
|
+
: "transitioning";
|
|
348
|
+
return {
|
|
349
|
+
instanceId: record.identity.instanceId,
|
|
350
|
+
canonicalizationVersion: 1,
|
|
351
|
+
canonicalProjectPath: record.identity.canonicalProjectPath,
|
|
352
|
+
displayProjectPath: record.identity.displayProjectPath,
|
|
353
|
+
projectPath: record.identity.displayProjectPath,
|
|
354
|
+
projectName: projectNameFromPath(record.identity.displayProjectPath),
|
|
355
|
+
status,
|
|
356
|
+
target,
|
|
357
|
+
revision: record.revision,
|
|
358
|
+
updatedAt: record.publishedAt,
|
|
359
|
+
sessions,
|
|
360
|
+
activeSession,
|
|
361
|
+
allSessions,
|
|
362
|
+
sessionId: activeSession?.sessionId,
|
|
363
|
+
editorSessionId: activeSession?.editorSessionId,
|
|
364
|
+
runtimeSessionId: activeSession?.runtimeSessionId,
|
|
365
|
+
processId: activeSession?.processId,
|
|
366
|
+
publishedAt: activeSession?.publishedAt,
|
|
367
|
+
lastUnitySnapshot: activeSession?.lastUnitySnapshot,
|
|
368
|
+
progress: activeSession?.progress ?? [],
|
|
369
|
+
blockers: activeSession?.blockers ?? [],
|
|
370
|
+
unityVersion: activeSession?.unityVersion,
|
|
371
|
+
buildStamp: activeSession?.buildStamp,
|
|
372
|
+
toolCatalogFingerprint: activeSession?.toolCatalogFingerprint,
|
|
373
|
+
claimVerification: sessions.length === 0 ? "none" : processUnverifiable ? "unverifiable" : "verified",
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* fallback 前重新证明 registry claim 对应原 PID/start 的 Unity.exe。
|
|
378
|
+
* 命令行存在 -projectPath 时必须匹配 canonical identity;正式 Hub/普通启动可以不携带该参数。
|
|
379
|
+
*/
|
|
380
|
+
export async function verifyRegistrySessionProcess(identity, session, timeoutMs = 900) {
|
|
381
|
+
if (process.platform !== "win32" || timeoutMs < 1)
|
|
382
|
+
return "unverifiable";
|
|
383
|
+
const startedAt = Date.now();
|
|
384
|
+
const command = [
|
|
385
|
+
"$ErrorActionPreference = 'Stop'",
|
|
386
|
+
"Add-Type -TypeDefinition @'",
|
|
387
|
+
"using System; using System.Runtime.InteropServices;",
|
|
388
|
+
"public static class UnityCliArgv { [DllImport(\"shell32.dll\", CharSet=CharSet.Unicode)] public static extern IntPtr CommandLineToArgvW(string commandLine, out int argc); [DllImport(\"kernel32.dll\")] public static extern IntPtr LocalFree(IntPtr value); public static string[] Parse(string commandLine) { int argc; var memory=CommandLineToArgvW(commandLine,out argc); if(memory==IntPtr.Zero) return null; try { var result=new string[argc]; for(var i=0;i<argc;i++) result[i]=Marshal.PtrToStringUni(Marshal.ReadIntPtr(memory,i*IntPtr.Size)); return result; } finally { LocalFree(memory); } } }",
|
|
389
|
+
"'@",
|
|
390
|
+
"$p = Get-CimInstance Win32_Process -Filter \"ProcessId=$env:UNITY_CLI_PROCESS_ID\" -ErrorAction Stop",
|
|
391
|
+
"if ($null -eq $p) { @{ state='dead' } | ConvertTo-Json -Compress; exit }",
|
|
392
|
+
"$args = [UnityCliArgv]::Parse($p.CommandLine)",
|
|
393
|
+
"@{ state='alive'; processStartedAt=([System.Diagnostics.Process]::GetProcessById([int]$p.ProcessId).StartTime.ToUniversalTime().ToString('O')); executablePath=$p.ExecutablePath; argv=@($args) } | ConvertTo-Json -Compress -Depth 4",
|
|
394
|
+
].join("\n");
|
|
395
|
+
const execution = await runPowerShellAsync(command, { UNITY_CLI_PROCESS_ID: String(session.processId) }, timeoutMs);
|
|
396
|
+
if (execution.status !== 0 || execution.error)
|
|
397
|
+
return "unverifiable";
|
|
398
|
+
try {
|
|
399
|
+
const raw = JSON.parse(execution.stdout.trim());
|
|
400
|
+
if (raw.state === "dead")
|
|
401
|
+
return "dead";
|
|
402
|
+
if (raw.state !== "alive" || typeof raw.processStartedAt !== "string" || typeof raw.executablePath !== "string" || !Array.isArray(raw.argv))
|
|
403
|
+
return "unverifiable";
|
|
404
|
+
if (Date.parse(raw.processStartedAt) !== Date.parse(session.processStartedAt))
|
|
405
|
+
return "unverifiable";
|
|
406
|
+
if (session.target === "runtime") {
|
|
407
|
+
if (!session.executablePath)
|
|
408
|
+
return "unverifiable";
|
|
409
|
+
return resolve(raw.executablePath).toLowerCase() === resolve(session.executablePath).toLowerCase() ? "verified" : "unverifiable";
|
|
410
|
+
}
|
|
411
|
+
if (basename(raw.executablePath).toLowerCase() !== "unity.exe")
|
|
412
|
+
return "unverifiable";
|
|
413
|
+
const argv = raw.argv.every((value) => typeof value === "string") ? raw.argv : undefined;
|
|
414
|
+
const index = argv?.findIndex((value) => value.toLowerCase() === "-projectpath") ?? -1;
|
|
415
|
+
if (index < 0)
|
|
416
|
+
return "verified";
|
|
417
|
+
if (!argv?.[index + 1])
|
|
418
|
+
return "unverifiable";
|
|
419
|
+
const remainingMs = Math.max(0, timeoutMs - (Date.now() - startedAt));
|
|
420
|
+
if (remainingMs <= 0)
|
|
421
|
+
return "unverifiable";
|
|
422
|
+
return (await resolveProjectIdentityAsync(argv[index + 1], { timeoutMs: remainingMs })).instanceId === identity.instanceId ? "verified" : "unverifiable";
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
return "unverifiable";
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/** 将显式 --instance 解析为已验证的 Registry v3 canonical identity,供本地 journal 绑定请求。 */
|
|
429
|
+
export async function resolveInstanceJournalIdentity(flags, dataDir) {
|
|
430
|
+
if (!Object.prototype.hasOwnProperty.call(flags, "instance"))
|
|
431
|
+
return undefined;
|
|
432
|
+
explicitInstanceSelector(flags);
|
|
433
|
+
const selected = await selectInstanceForFlags(flags, dataDir);
|
|
434
|
+
return {
|
|
435
|
+
instanceId: selected.instance.instanceId,
|
|
436
|
+
canonicalProjectPath: selected.instance.canonicalProjectPath,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
export async function hasInstanceForFlags(flags, dataDir, cwd = process.cwd()) {
|
|
440
|
+
try {
|
|
441
|
+
await selectInstanceForFlags(flags, dataDir, cwd);
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/** 将 identity/registry 失败保留为稳定 CLI envelope。 */
|
|
449
|
+
export function instanceSelectionFailure(requestId, error) {
|
|
450
|
+
if (error instanceof InstanceRegistryError || error instanceof ProjectIdentityError) {
|
|
451
|
+
const nextActions = error instanceof InstanceRegistryError ? error.nextActions : [
|
|
452
|
+
"Pass --instance <instanceId|canonicalProjectPath|alias> or run from a local Unity project directory.",
|
|
453
|
+
];
|
|
454
|
+
const details = error instanceof InstanceRegistryError ? error.details : error.details;
|
|
455
|
+
return failure(requestId, error.code, error.message, nextActions, details, { transient: false, retryAfterMs: 0 });
|
|
456
|
+
}
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
export function instancesDir(dataDir = defaultDataDir()) {
|
|
460
|
+
return resolve(dataDir, "instances");
|
|
461
|
+
}
|
|
462
|
+
export function aliasesV2Path(dataDir = defaultDataDir()) {
|
|
463
|
+
return resolve(dataDir, "aliases-v2.json");
|
|
464
|
+
}
|
|
465
|
+
/** 只读全部合法v3 identity records;单个坏文件不能污染其他canonical project。 */
|
|
466
|
+
export async function readInstances(dataDir = defaultDataDir(), now = Date.now(), target = "all") {
|
|
467
|
+
return (await readInstancesWithRegistryDiagnostics(dataDir, now, target)).instances;
|
|
468
|
+
}
|
|
469
|
+
/** 控制面可读取无效数量;具体文件名、路径和内容始终保持私有。 */
|
|
470
|
+
export async function readInstancesWithRegistryDiagnostics(dataDir = defaultDataDir(), now = Date.now(), target = "all") {
|
|
471
|
+
const { records, invalidRecordCount } = await readRegistryRecords(dataDir);
|
|
472
|
+
const processObservations = await probeProcessObservations(records.flatMap((record) => record.sessions.map((session) => session.processId)));
|
|
473
|
+
const reduced = await Promise.all(records.map((record) => reduceRegistryRecord(record, processObservations, now, target)));
|
|
474
|
+
return {
|
|
475
|
+
instances: reduced.sort((left, right) => left.canonicalProjectPath.localeCompare(right.canonicalProjectPath)),
|
|
476
|
+
invalidRecordCount,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/** CanonicalPath v1 补充进程观察;只返回可由显式 -projectPath 正向归因的 claim。 */
|
|
480
|
+
export async function inspectProjectProcessClaims(identity, timeoutMs = PROJECT_PROCESS_CLAIM_TIMEOUT_MS) {
|
|
481
|
+
if (process.platform !== "win32")
|
|
482
|
+
return { verification: "unsupported", processIds: [] };
|
|
483
|
+
try {
|
|
484
|
+
const processes = await findUnityProjectProcesses(identity.instanceId, identity.canonicalProjectPath, timeoutMs);
|
|
485
|
+
const processClaims = processes.map((item) => ({ processId: item.processId, processStartedAt: item.processStartedAt }))
|
|
486
|
+
.sort((left, right) => left.processId - right.processId);
|
|
487
|
+
return { verification: "verified", processIds: [...new Set(processClaims.map((item) => item.processId))], processClaims };
|
|
488
|
+
}
|
|
489
|
+
catch {
|
|
490
|
+
return { verification: "unverifiable", processIds: [] };
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/** 将 OS 进程 claim 与 registry session 交叉验证;冲突时清除任何可执行 session 选择。 */
|
|
494
|
+
export function applyProjectProcessClaimInspection(instance, inspection) {
|
|
495
|
+
if (inspection.verification === "unsupported")
|
|
496
|
+
return instance;
|
|
497
|
+
const registeredEditorProcessIds = instance.allSessions.filter((session) => session.target === "editor").map((session) => session.processId);
|
|
498
|
+
// 命令行扫描只提供额外正向证据;不能因正式启动缺少 -projectPath 否定 Registry/health 结论。
|
|
499
|
+
if (registeredEditorProcessIds.length === 0
|
|
500
|
+
|| inspection.verification !== "verified"
|
|
501
|
+
|| inspection.processIds.length === 0)
|
|
502
|
+
return instance;
|
|
503
|
+
if (inspection.processIds.length > 1) {
|
|
504
|
+
const blocker = {
|
|
505
|
+
kind: "duplicate-project-process",
|
|
506
|
+
title: "Multiple Unity Editor processes",
|
|
507
|
+
message: `${inspection.processIds.length} Unity.exe processes claim the selected canonical project identity.`,
|
|
508
|
+
requiresUserAction: true,
|
|
509
|
+
canAutoResolve: false,
|
|
510
|
+
source: "registry",
|
|
511
|
+
confidence: "exact",
|
|
512
|
+
};
|
|
513
|
+
return {
|
|
514
|
+
...instance,
|
|
515
|
+
status: "conflict",
|
|
516
|
+
activeSession: undefined,
|
|
517
|
+
sessionId: undefined,
|
|
518
|
+
editorSessionId: undefined,
|
|
519
|
+
runtimeSessionId: undefined,
|
|
520
|
+
processId: undefined,
|
|
521
|
+
progress: [],
|
|
522
|
+
blockers: [...instance.blockers, blocker],
|
|
523
|
+
claimVerification: "verified",
|
|
524
|
+
processClaimIds: inspection.processIds,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
const exact = inspection.processIds.length === 1
|
|
528
|
+
&& registeredEditorProcessIds.length === 1
|
|
529
|
+
&& inspection.processIds[0] === registeredEditorProcessIds[0];
|
|
530
|
+
return exact ? { ...instance, processClaimIds: inspection.processIds } : unverifiableInstance(instance, inspection.processIds);
|
|
531
|
+
}
|
|
532
|
+
/** 无法证明唯一ownership时清除任何可执行session,但绝不伪造duplicate blocker。 */
|
|
533
|
+
function unverifiableInstance(instance, processClaimIds) {
|
|
534
|
+
return {
|
|
535
|
+
...instance,
|
|
536
|
+
status: "unverifiable",
|
|
537
|
+
activeSession: undefined,
|
|
538
|
+
sessionId: undefined,
|
|
539
|
+
editorSessionId: undefined,
|
|
540
|
+
runtimeSessionId: undefined,
|
|
541
|
+
processId: undefined,
|
|
542
|
+
progress: [],
|
|
543
|
+
blockers: [],
|
|
544
|
+
claimVerification: "unverifiable",
|
|
545
|
+
processClaimIds,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
/** instances 控制面补充可正向归因的 OS process claims,使启动中的重复进程可见。 */
|
|
549
|
+
async function readInstancesWithProjectProcessClaims(dataDir) {
|
|
550
|
+
const { instances, invalidRecordCount } = await readInstancesWithRegistryDiagnostics(dataDir);
|
|
551
|
+
return {
|
|
552
|
+
instances: await Promise.all(instances.map(async (instance) => applyProjectProcessClaimInspection(instance, await inspectProjectProcessClaims({
|
|
553
|
+
instanceId: instance.instanceId,
|
|
554
|
+
canonicalProjectPath: instance.canonicalProjectPath,
|
|
555
|
+
displayProjectPath: instance.displayProjectPath,
|
|
556
|
+
})))),
|
|
557
|
+
invalidRecordCount,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
/** 纯 reducer 可由测试注入 OS observations,禁止 TS 回写观察结果。 */
|
|
561
|
+
export async function reduceRegistryRecord(record, observations, now = Date.now(), target = "editor") {
|
|
562
|
+
validateRegistryRecord(record);
|
|
563
|
+
const allClaims = record.sessions.filter((session) => claimIsAlive(session, observations.get(session.processId)));
|
|
564
|
+
const targets = target === "all" ? ["editor", "runtime"] : [target];
|
|
565
|
+
const evaluations = await Promise.all(targets.map(async (candidateTarget) => {
|
|
566
|
+
const claims = allClaims.filter((session) => session.target === candidateTarget);
|
|
567
|
+
const verifiedClaims = claims.filter((session) => observations.get(session.processId)?.state === "alive" && claimIsAlive(session, observations.get(session.processId)));
|
|
568
|
+
const verifiedProcessIdentities = new Set(verifiedClaims.map(processIdentityKey));
|
|
569
|
+
const unverifiable = claims.some((session) => observations.get(session.processId)?.state !== "alive");
|
|
570
|
+
if (verifiedProcessIdentities.size > 1)
|
|
571
|
+
return { status: "conflict", claims, active: undefined };
|
|
572
|
+
if (unverifiable || verifiedClaims.length > 1 || (claims.length > 0 && verifiedClaims.length !== 1))
|
|
573
|
+
return { status: "unverifiable", claims, active: undefined };
|
|
574
|
+
const active = verifiedClaims[0];
|
|
575
|
+
if (!active)
|
|
576
|
+
return { status: "offline", claims, active: undefined };
|
|
577
|
+
if (active.blockers.length > 0 || active.lifecycle === "blocked")
|
|
578
|
+
return { status: "blocked", claims, active };
|
|
579
|
+
if (lifecycleIsTransitioning(active.lifecycle) || active.progress.length > 0 || snapshotIsTransitioning(active.lastUnitySnapshot))
|
|
580
|
+
return { status: "transitioning", claims, active };
|
|
581
|
+
const health = await probeHealthIdentity(record.identity, active);
|
|
582
|
+
if (!health)
|
|
583
|
+
return { status: "unresponsive", claims, active };
|
|
584
|
+
if (lifecycleIsTransitioning(health.mainThread.lifecycle))
|
|
585
|
+
return { status: "transitioning", claims, active };
|
|
586
|
+
return { status: healthMainThreadIsFresh(health, now) ? "ready" : "unresponsive", claims, active };
|
|
587
|
+
}));
|
|
588
|
+
const priority = ["conflict", "unverifiable", "blocked", "ready", "transitioning", "unresponsive", "offline"];
|
|
589
|
+
const status = priority.find((candidate) => evaluations.some((evaluation) => evaluation.status === candidate)) ?? "offline";
|
|
590
|
+
const claims = target === "all" ? allClaims : evaluations[0].claims;
|
|
591
|
+
const activeCandidates = evaluations.flatMap((evaluation) => evaluation.active ? [evaluation.active] : []);
|
|
592
|
+
const selected = target === "all" ? activeCandidates.length === 1 ? activeCandidates[0] : undefined : evaluations[0].active;
|
|
593
|
+
return {
|
|
594
|
+
instanceId: record.identity.instanceId,
|
|
595
|
+
canonicalizationVersion: 1,
|
|
596
|
+
canonicalProjectPath: record.identity.canonicalProjectPath,
|
|
597
|
+
displayProjectPath: record.identity.displayProjectPath,
|
|
598
|
+
projectPath: record.identity.displayProjectPath,
|
|
599
|
+
projectName: projectNameFromPath(record.identity.displayProjectPath),
|
|
600
|
+
status,
|
|
601
|
+
...(target === "all" ? {} : { target }),
|
|
602
|
+
revision: record.revision,
|
|
603
|
+
updatedAt: record.publishedAt,
|
|
604
|
+
sessions: claims,
|
|
605
|
+
activeSession: selected,
|
|
606
|
+
allSessions: allClaims,
|
|
607
|
+
sessionId: selected?.sessionId,
|
|
608
|
+
editorSessionId: selected?.editorSessionId,
|
|
609
|
+
runtimeSessionId: selected?.runtimeSessionId,
|
|
610
|
+
processId: selected?.processId,
|
|
611
|
+
publishedAt: selected?.publishedAt,
|
|
612
|
+
lastUnitySnapshot: selected?.lastUnitySnapshot,
|
|
613
|
+
progress: selected?.progress ?? [],
|
|
614
|
+
blockers: selected?.blockers ?? [],
|
|
615
|
+
unityVersion: selected?.unityVersion,
|
|
616
|
+
buildStamp: selected?.buildStamp,
|
|
617
|
+
toolCatalogFingerprint: selected?.toolCatalogFingerprint,
|
|
618
|
+
claimVerification: claims.length === 0 ? "none" : status === "unverifiable" ? "unverifiable" : "verified",
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
/** public summary 不包含 endpoint、port 或 listener generation;null/空字段不输出以控制上下文。 */
|
|
622
|
+
export function instanceListSummary(instance) {
|
|
623
|
+
return {
|
|
624
|
+
instanceId: instance.instanceId,
|
|
625
|
+
canonicalProjectPath: instance.canonicalProjectPath,
|
|
626
|
+
displayProjectPath: instance.displayProjectPath,
|
|
627
|
+
projectName: instance.projectName,
|
|
628
|
+
status: instance.status,
|
|
629
|
+
...(instance.unityVersion ? { unityVersion: instance.unityVersion } : {}),
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/** 返回 doctor 应报告但产品不得解析的旧本地状态文件。 */
|
|
633
|
+
export async function obsoleteLocalStatePaths(dataDir) {
|
|
634
|
+
const candidates = [resolve(dataDir, "config.json"), resolve(dataDir, "aliases.json"), resolve(dataDir, "instances.json")];
|
|
635
|
+
const existing = [];
|
|
636
|
+
for (const candidate of candidates) {
|
|
637
|
+
try {
|
|
638
|
+
if ((await stat(candidate)).isFile())
|
|
639
|
+
existing.push(candidate);
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
if (error.code !== "ENOENT")
|
|
643
|
+
throw error;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return existing;
|
|
647
|
+
}
|
|
648
|
+
async function readRegistryRecords(dataDir) {
|
|
649
|
+
let names;
|
|
650
|
+
try {
|
|
651
|
+
names = await readdir(instancesDir(dataDir));
|
|
652
|
+
}
|
|
653
|
+
catch (error) {
|
|
654
|
+
if (error.code === "ENOENT")
|
|
655
|
+
return { records: [], invalidRecordCount: 0 };
|
|
656
|
+
throw error;
|
|
657
|
+
}
|
|
658
|
+
const records = [];
|
|
659
|
+
let invalidRecordCount = 0;
|
|
660
|
+
for (const name of names.filter((entry) => INSTANCE_ID_PATTERN.test(entry.replace(/\.json$/i, "")) && entry.endsWith(".json")).sort()) {
|
|
661
|
+
try {
|
|
662
|
+
const parsed = await readRegistrySnapshot(join(instancesDir(dataDir), name), true);
|
|
663
|
+
if (`${parsed.identity.instanceId}.json` !== name)
|
|
664
|
+
throw new Error("Registry filename does not match its canonical instanceId.");
|
|
665
|
+
records.push(parsed);
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
// 全量视图只隔离该文件;不读取旧格式、不修改现场,也不泄露路径或内容。
|
|
669
|
+
invalidRecordCount += 1;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return { records, invalidRecordCount };
|
|
673
|
+
}
|
|
674
|
+
/** Observation paths already know the deterministic v3 filename and must not enumerate unrelated records. */
|
|
675
|
+
async function readRegistryRecord(dataDir, instanceId, deadlineMs) {
|
|
676
|
+
const filePath = join(instancesDir(dataDir), `${instanceId}.json`);
|
|
677
|
+
try {
|
|
678
|
+
const parsed = await readRegistrySnapshot(filePath, true, deadlineMs);
|
|
679
|
+
if (parsed.identity.instanceId !== instanceId)
|
|
680
|
+
throw new Error("Registry filename does not match its canonical instanceId.");
|
|
681
|
+
return parsed;
|
|
682
|
+
}
|
|
683
|
+
catch (error) {
|
|
684
|
+
const ioCode = error.code;
|
|
685
|
+
if (ioCode === "ENOENT")
|
|
686
|
+
return undefined;
|
|
687
|
+
if (error instanceof InstanceRegistryError)
|
|
688
|
+
throw error;
|
|
689
|
+
if (ioCode === "EBUSY" || ioCode === "EPERM" || ioCode === "EACCES") {
|
|
690
|
+
throw new InstanceRegistryError("E_INSTANCE_UNVERIFIABLE", "The selected instance registry record could not be read safely.", ["Wait until the selected Unity project finishes publishing its instance record, then observe it again."], { instanceId });
|
|
691
|
+
}
|
|
692
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "The selected instance registry record does not satisfy the v3 canonical identity contract.", ["Update or restart the selected Unity project with the matching UnityCLI package before selecting it again."], { instanceId });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
function validateRegistryRecord(record) {
|
|
696
|
+
const identity = record?.identity;
|
|
697
|
+
const expectedInstanceId = identity && typeof identity.canonicalProjectPath === "string"
|
|
698
|
+
? `unity-${createHash("sha256").update(Buffer.from(identity.canonicalProjectPath, "utf8")).digest("hex")}`
|
|
699
|
+
: "";
|
|
700
|
+
if (!record || record.version !== 3 || record.canonicalizationVersion !== CANONICALIZATION_VERSION
|
|
701
|
+
|| !identity || !INSTANCE_ID_PATTERN.test(identity.instanceId) || identity.instanceId !== expectedInstanceId
|
|
702
|
+
|| typeof identity.canonicalProjectPath !== "string" || identity.canonicalProjectPath.length < 3
|
|
703
|
+
|| typeof identity.displayProjectPath !== "string" || identity.displayProjectPath.length < 3
|
|
704
|
+
|| !Array.isArray(record.sessions)
|
|
705
|
+
|| !Number.isInteger(record.revision) || record.revision < 0
|
|
706
|
+
|| !validTimestamp(record.publishedAt)) {
|
|
707
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "Instance registry does not satisfy the v3 canonical identity contract.");
|
|
708
|
+
}
|
|
709
|
+
const sessionIds = new Set();
|
|
710
|
+
const listenerIds = new Set();
|
|
711
|
+
for (const session of record.sessions) {
|
|
712
|
+
const listener = session?.listener;
|
|
713
|
+
const endpoint = listener?.endpoint;
|
|
714
|
+
const snapshot = session?.lastUnitySnapshot;
|
|
715
|
+
const expectedUrl = endpoint ? `http://127.0.0.1:${endpoint.actualPort}` : "";
|
|
716
|
+
const targetIdentityValid = session?.target === "editor"
|
|
717
|
+
? session.editorSessionId === session.sessionId && session.runtimeSessionId === undefined
|
|
718
|
+
&& validEditorRegistrySnapshot(snapshot, session.sessionId, listener?.generation)
|
|
719
|
+
: session?.target === "runtime"
|
|
720
|
+
? session.runtimeSessionId === session.sessionId && session.editorSessionId === undefined
|
|
721
|
+
&& typeof session.executablePath === "string" && isAbsolute(session.executablePath)
|
|
722
|
+
&& typeof session.buildId === "string" && /^[0-9a-f]{32}$/i.test(session.buildId)
|
|
723
|
+
&& validRuntimeRegistrySnapshot(snapshot, session.sessionId, listener?.generation)
|
|
724
|
+
: false;
|
|
725
|
+
if (!session || !SESSION_ID_PATTERN.test(session.sessionId) || sessionIds.has(session.sessionId)
|
|
726
|
+
|| !Number.isInteger(session.processId) || session.processId < 1
|
|
727
|
+
|| !validTimestamp(session.processStartedAt) || !validTimestamp(session.publishedAt)
|
|
728
|
+
|| !Number.isInteger(session.publicationSequence) || session.publicationSequence < 1
|
|
729
|
+
|| !REGISTRY_LIFECYCLES.has(session.lifecycle)
|
|
730
|
+
|| !listener || !LISTENER_ID_PATTERN.test(listener.listenerId) || listenerIds.has(listener.listenerId)
|
|
731
|
+
|| !Number.isInteger(listener.generation) || listener.generation < 1 || !validTimestamp(listener.startedAt)
|
|
732
|
+
|| !endpoint || endpoint.host !== "127.0.0.1"
|
|
733
|
+
|| !validPort(endpoint.preferredPort) || !validPort(endpoint.actualPort)
|
|
734
|
+
|| typeof endpoint.fallback !== "boolean" || endpoint.url !== expectedUrl
|
|
735
|
+
|| !targetIdentityValid
|
|
736
|
+
|| !Array.isArray(session.progress) || !Array.isArray(session.blockers)
|
|
737
|
+
|| typeof session.buildStamp !== "string" || session.buildStamp.length === 0) {
|
|
738
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "Instance registry contains an invalid v3 target session claim.", [], { instanceId: identity.instanceId });
|
|
739
|
+
}
|
|
740
|
+
sessionIds.add(session.sessionId);
|
|
741
|
+
listenerIds.add(listener.listenerId);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
/** Registry snapshot 是完整v1单包;reader不允许从两次publication拼接字段。 */
|
|
745
|
+
function validEditorRegistrySnapshot(snapshot, editorSessionId, listenerGeneration) {
|
|
746
|
+
if (!snapshot || snapshot.schemaVersion !== 1 || snapshot.sourceEditorSessionId !== editorSessionId
|
|
747
|
+
|| snapshot.sourceListenerGeneration !== listenerGeneration || !validTimestamp(String(snapshot.observedAt ?? ""))
|
|
748
|
+
|| !hasExactKeys(snapshot, ["schemaVersion", "observedAt", "sourceEditorSessionId", "sourceListenerGeneration", "fields"]))
|
|
749
|
+
return false;
|
|
750
|
+
const fields = snapshot.fields;
|
|
751
|
+
const names = ["compile", "import", "build", "playMode", "prefabStage", "activeScene", "runtime"];
|
|
752
|
+
if (!fields || typeof fields !== "object" || Array.isArray(fields) || Object.keys(fields).length !== names.length)
|
|
753
|
+
return false;
|
|
754
|
+
return names.every((name) => {
|
|
755
|
+
const field = fields[name];
|
|
756
|
+
if (!field || typeof field !== "object" || Array.isArray(field))
|
|
757
|
+
return false;
|
|
758
|
+
const raw = field;
|
|
759
|
+
return typeof raw.known === "boolean"
|
|
760
|
+
&& Object.keys(raw).every((key) => key === "known" || key === "value")
|
|
761
|
+
&& (raw.known ? Object.prototype.hasOwnProperty.call(raw, "value") : !Object.prototype.hasOwnProperty.call(raw, "value"));
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
/** Runtime snapshot 与 session/listener 同包归因;字段采用 bounded known/value 结构供后续状态能力扩展。 */
|
|
765
|
+
function validRuntimeRegistrySnapshot(snapshot, runtimeSessionId, listenerGeneration) {
|
|
766
|
+
if (!snapshot || snapshot.schemaVersion !== 1 || snapshot.sourceRuntimeSessionId !== runtimeSessionId
|
|
767
|
+
|| snapshot.sourceListenerGeneration !== listenerGeneration || !validTimestamp(String(snapshot.observedAt ?? ""))
|
|
768
|
+
|| !hasExactKeys(snapshot, ["schemaVersion", "observedAt", "sourceRuntimeSessionId", "sourceListenerGeneration", "fields"]))
|
|
769
|
+
return false;
|
|
770
|
+
const fields = snapshot.fields;
|
|
771
|
+
if (!fields || typeof fields !== "object" || Array.isArray(fields))
|
|
772
|
+
return false;
|
|
773
|
+
const entries = Object.entries(fields);
|
|
774
|
+
if (entries.length < 1 || entries.length > 16)
|
|
775
|
+
return false;
|
|
776
|
+
return entries.every(([, field]) => {
|
|
777
|
+
if (!field || typeof field !== "object" || Array.isArray(field))
|
|
778
|
+
return false;
|
|
779
|
+
const raw = field;
|
|
780
|
+
return typeof raw.known === "boolean"
|
|
781
|
+
&& Object.keys(raw).every((key) => key === "known" || key === "value")
|
|
782
|
+
&& (raw.known ? Object.prototype.hasOwnProperty.call(raw, "value") : !Object.prototype.hasOwnProperty.call(raw, "value"));
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
function hasExactKeys(value, names) {
|
|
786
|
+
const keys = Object.keys(value);
|
|
787
|
+
return keys.length === names.length && names.every((name) => Object.prototype.hasOwnProperty.call(value, name));
|
|
788
|
+
}
|
|
789
|
+
function validTimestamp(value) {
|
|
790
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
791
|
+
}
|
|
792
|
+
function validPort(value) {
|
|
793
|
+
return Number.isInteger(value) && value >= 1024 && value <= 65535;
|
|
794
|
+
}
|
|
795
|
+
/** 批量读取 PID start time;access denied 保留 unverifiable claim 并 fail closed。 */
|
|
796
|
+
export async function probeProcessObservations(processIds, timeoutMs = PROCESS_OBSERVATION_TIMEOUT_MS) {
|
|
797
|
+
const ids = [...new Set(processIds.filter((value) => Number.isInteger(value) && value > 0))];
|
|
798
|
+
if (ids.length === 0)
|
|
799
|
+
return new Map();
|
|
800
|
+
const command = [
|
|
801
|
+
"$ErrorActionPreference = 'SilentlyContinue'",
|
|
802
|
+
"$ids = $env:UNITY_CLI_PROCESS_IDS | ConvertFrom-Json",
|
|
803
|
+
"$items = foreach ($id in $ids) {",
|
|
804
|
+
" $process = Get-Process -Id ([int]$id) -ErrorAction SilentlyContinue",
|
|
805
|
+
" if ($null -eq $process) { [pscustomobject]@{ processId=[int]$id; state='dead' }; continue }",
|
|
806
|
+
" try { [pscustomobject]@{ processId=[int]$id; state='alive'; processStartedAt=$process.StartTime.ToUniversalTime().ToString('O'); executablePath=$process.Path } }",
|
|
807
|
+
" catch { [pscustomobject]@{ processId=[int]$id; state='unverifiable' } }",
|
|
808
|
+
"}",
|
|
809
|
+
"@($items) | ConvertTo-Json -Compress -Depth 3",
|
|
810
|
+
].join("\n");
|
|
811
|
+
const execution = runPowerShell(command, { UNITY_CLI_PROCESS_IDS: JSON.stringify(ids) }, Math.max(1, timeoutMs));
|
|
812
|
+
if (execution.status !== 0 || execution.error) {
|
|
813
|
+
return new Map(ids.map((processId) => [processId, { processId, state: "unverifiable" }]));
|
|
814
|
+
}
|
|
815
|
+
try {
|
|
816
|
+
const line = execution.stdout.split(/\r?\n/).map((value) => value.trim()).filter(Boolean).at(-1);
|
|
817
|
+
const raw = JSON.parse(line || "[]");
|
|
818
|
+
const items = Array.isArray(raw) ? raw : [raw];
|
|
819
|
+
return new Map(items.filter((item) => !!item && typeof item === "object").map((item) => {
|
|
820
|
+
const processId = Number(item.processId);
|
|
821
|
+
const state = item.state === "alive" || item.state === "dead" ? item.state : "unverifiable";
|
|
822
|
+
return [processId, {
|
|
823
|
+
processId,
|
|
824
|
+
state,
|
|
825
|
+
processStartedAt: typeof item.processStartedAt === "string" ? item.processStartedAt : undefined,
|
|
826
|
+
executablePath: typeof item.executablePath === "string" ? item.executablePath : undefined,
|
|
827
|
+
}];
|
|
828
|
+
}));
|
|
829
|
+
}
|
|
830
|
+
catch {
|
|
831
|
+
return new Map(ids.map((processId) => [processId, { processId, state: "unverifiable" }]));
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
/** conflict按PID/start process identity计数,不能把同一进程的重复session误报为plural claim。 */
|
|
835
|
+
function processIdentityKey(session) {
|
|
836
|
+
return `${session.processId}:${Date.parse(session.processStartedAt)}`;
|
|
837
|
+
}
|
|
838
|
+
function claimIsAlive(session, observation) {
|
|
839
|
+
if (!observation || observation.state === "unverifiable")
|
|
840
|
+
return true;
|
|
841
|
+
if (observation.state === "dead")
|
|
842
|
+
return false;
|
|
843
|
+
const expected = Date.parse(session.processStartedAt);
|
|
844
|
+
const actual = Date.parse(observation.processStartedAt ?? "");
|
|
845
|
+
return Number.isFinite(expected) && Number.isFinite(actual) && expected === actual;
|
|
846
|
+
}
|
|
847
|
+
/** strict health 必须同时匹配 project/session/listener/port/build identity。 */
|
|
848
|
+
async function probeHealthIdentity(identity, session) {
|
|
849
|
+
const listener = session.listener;
|
|
850
|
+
const cacheKey = [identity.instanceId, session.target, session.sessionId, listener.listenerId, listener.generation, listener.endpoint.actualPort, session.buildStamp ?? "", session.buildId ?? ""].join("\0");
|
|
851
|
+
const cached = healthCache.get(cacheKey);
|
|
852
|
+
if (cached && Date.now() - cached.checkedAt <= HEALTH_CACHE_TTL_MS)
|
|
853
|
+
return cached.identity;
|
|
854
|
+
const controller = new AbortController();
|
|
855
|
+
const timeout = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT_MS);
|
|
856
|
+
try {
|
|
857
|
+
const response = await fetch(new URL("/health", listener.endpoint.url), {
|
|
858
|
+
signal: controller.signal,
|
|
859
|
+
headers: {
|
|
860
|
+
"x-unity-cli-expected-target": session.target,
|
|
861
|
+
"x-unity-cli-expected-instance-id": identity.instanceId,
|
|
862
|
+
"x-unity-cli-expected-session-id": session.sessionId,
|
|
863
|
+
"x-unity-cli-expected-listener-id": listener.listenerId,
|
|
864
|
+
"x-unity-cli-expected-listener-generation": String(listener.generation),
|
|
865
|
+
},
|
|
866
|
+
});
|
|
867
|
+
if (!response.ok)
|
|
868
|
+
return undefined;
|
|
869
|
+
const envelope = await response.json();
|
|
870
|
+
if (envelope.ok !== true || !envelope.data || typeof envelope.data !== "object" || Array.isArray(envelope.data))
|
|
871
|
+
return undefined;
|
|
872
|
+
const data = envelope.data;
|
|
873
|
+
const rawMainThread = data.mainThread && typeof data.mainThread === "object" && !Array.isArray(data.mainThread) ? data.mainThread : undefined;
|
|
874
|
+
const checkedAt = Date.now();
|
|
875
|
+
const health = {
|
|
876
|
+
version: Number(data.version),
|
|
877
|
+
target: String(data.target ?? ""),
|
|
878
|
+
instanceId: String(data.instanceId ?? ""),
|
|
879
|
+
canonicalProjectPath: String(data.canonicalProjectPath ?? ""),
|
|
880
|
+
canonicalizationVersion: Number(data.canonicalizationVersion),
|
|
881
|
+
sessionId: String(data.sessionId ?? ""),
|
|
882
|
+
listenerId: String(data.listenerId ?? ""),
|
|
883
|
+
listenerGeneration: Number(data.listenerGeneration),
|
|
884
|
+
actualPort: Number(data.actualPort),
|
|
885
|
+
buildStamp: String(data.buildStamp ?? ""),
|
|
886
|
+
...(typeof data.buildId === "string" ? { buildId: data.buildId } : {}),
|
|
887
|
+
mainThread: {
|
|
888
|
+
observed: rawMainThread?.observed === true,
|
|
889
|
+
sequence: Number(rawMainThread?.sequence),
|
|
890
|
+
ageMs: rawMainThread?.ageMs === null ? null : Number(rawMainThread?.ageMs),
|
|
891
|
+
listenerGeneration: Number(rawMainThread?.listenerGeneration),
|
|
892
|
+
lifecycle: String(rawMainThread?.lifecycle ?? ""),
|
|
893
|
+
},
|
|
894
|
+
checkedAt,
|
|
895
|
+
};
|
|
896
|
+
const pulse = health.mainThread;
|
|
897
|
+
const pulseShapeValid = typeof pulse.observed === "boolean"
|
|
898
|
+
&& Number.isInteger(pulse.sequence) && pulse.sequence >= 0
|
|
899
|
+
&& (pulse.ageMs === null || Number.isInteger(pulse.ageMs) && pulse.ageMs >= 0)
|
|
900
|
+
&& Number.isInteger(pulse.listenerGeneration) && pulse.listenerGeneration >= 1
|
|
901
|
+
&& REGISTRY_LIFECYCLES.has(pulse.lifecycle)
|
|
902
|
+
&& (pulse.observed ? pulse.sequence > 0 && pulse.ageMs !== null : pulse.sequence === 0 && pulse.ageMs === null);
|
|
903
|
+
if (health.version !== 3
|
|
904
|
+
|| health.target !== session.target
|
|
905
|
+
|| health.instanceId !== identity.instanceId
|
|
906
|
+
|| health.canonicalProjectPath !== identity.canonicalProjectPath
|
|
907
|
+
|| health.canonicalizationVersion !== 1
|
|
908
|
+
|| health.sessionId !== session.sessionId
|
|
909
|
+
|| health.listenerId !== listener.listenerId
|
|
910
|
+
|| health.listenerGeneration !== listener.generation
|
|
911
|
+
|| health.actualPort !== listener.endpoint.actualPort
|
|
912
|
+
|| health.buildStamp !== session.buildStamp
|
|
913
|
+
|| health.mainThread.listenerGeneration !== listener.generation
|
|
914
|
+
|| !pulseShapeValid
|
|
915
|
+
|| (session.target === "runtime" && health.buildId !== session.buildId))
|
|
916
|
+
return undefined;
|
|
917
|
+
healthCache.set(cacheKey, { checkedAt, identity: health });
|
|
918
|
+
return health;
|
|
919
|
+
}
|
|
920
|
+
catch {
|
|
921
|
+
return undefined;
|
|
922
|
+
}
|
|
923
|
+
finally {
|
|
924
|
+
clearTimeout(timeout);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
/** cache停留时间必须计入服务端pulse age,避免旧health在TTL内伪装新鲜。 */
|
|
928
|
+
function healthMainThreadIsFresh(health, now = Date.now()) {
|
|
929
|
+
return health.mainThread.observed && health.mainThread.ageMs !== null
|
|
930
|
+
&& health.mainThread.ageMs + Math.max(0, now - health.checkedAt) <= MAIN_THREAD_PULSE_FRESH_MS;
|
|
931
|
+
}
|
|
932
|
+
function lifecycleIsTransitioning(lifecycle) {
|
|
933
|
+
return lifecycle !== "ready" && lifecycle !== "blocked";
|
|
934
|
+
}
|
|
935
|
+
async function resolveSelectorIdentity(selector, dataDir, observationBudgetMs, observationDeadlineMs) {
|
|
936
|
+
const store = await readAliasStore(dataDir);
|
|
937
|
+
const alias = store.aliases.find((binding) => binding.alias === selector);
|
|
938
|
+
if (alias)
|
|
939
|
+
return projectIdentityFromBinding(alias);
|
|
940
|
+
if (INSTANCE_ID_PATTERN.test(selector)) {
|
|
941
|
+
// instanceId 已决定固定文件名;直接读取才能对 Windows replace 窗口做有界重试。
|
|
942
|
+
const record = await readRegistryRecord(dataDir, selector, observationDeadlineMs);
|
|
943
|
+
if (!record)
|
|
944
|
+
throw new InstanceRegistryError("E_INSTANCE_NOT_FOUND", `Unity project identity not found: ${selector}.`, ["Pass an existing project path or run unitycli instances list."]);
|
|
945
|
+
return projectIdentityFromRegistry(record.identity);
|
|
946
|
+
}
|
|
947
|
+
if (!looksLikePath(selector)) {
|
|
948
|
+
throw new InstanceRegistryError("E_INSTANCE_NOT_FOUND", `Unity project alias not found: ${selector}.`, ["Run unitycli target alias list or pass a project path."]);
|
|
949
|
+
}
|
|
950
|
+
return observationBudgetMs === undefined
|
|
951
|
+
? resolveProjectIdentity(selector)
|
|
952
|
+
: resolveProjectIdentityAsync(selector, { timeoutMs: observationBudgetMs });
|
|
953
|
+
}
|
|
954
|
+
async function resolveAliasIdentity(selector, dataDir) {
|
|
955
|
+
if (!INSTANCE_ID_PATTERN.test(selector))
|
|
956
|
+
return resolveProjectIdentity(selector);
|
|
957
|
+
const record = await readRegistryRecord(dataDir, selector);
|
|
958
|
+
if (!record)
|
|
959
|
+
throw new InstanceRegistryError("E_INSTANCE_NOT_FOUND", `Unity project identity not found: ${selector}.`, ["Pass an existing Unity project path."]);
|
|
960
|
+
return projectIdentityFromRegistry(record.identity);
|
|
961
|
+
}
|
|
962
|
+
function projectIdentityFromBinding(binding) {
|
|
963
|
+
return {
|
|
964
|
+
canonicalizationVersion: 1,
|
|
965
|
+
instanceId: binding.instanceId,
|
|
966
|
+
identityHash: binding.instanceId.slice("unity-".length),
|
|
967
|
+
canonicalProjectPath: binding.canonicalProjectPath,
|
|
968
|
+
displayProjectPath: binding.displayProjectPath,
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
function projectIdentityFromRegistry(identity) {
|
|
972
|
+
return {
|
|
973
|
+
canonicalizationVersion: 1,
|
|
974
|
+
instanceId: identity.instanceId,
|
|
975
|
+
identityHash: identity.instanceId.slice("unity-".length),
|
|
976
|
+
canonicalProjectPath: identity.canonicalProjectPath,
|
|
977
|
+
displayProjectPath: identity.displayProjectPath,
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
function assertRegistryIdentity(instance, identity) {
|
|
981
|
+
if (instance.canonicalProjectPath !== identity.canonicalProjectPath || instance.canonicalizationVersion !== identity.canonicalizationVersion) {
|
|
982
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "Registry identity differs from CanonicalPath v1 for the selected project.", [], {
|
|
983
|
+
instanceId: identity.instanceId,
|
|
984
|
+
expectedCanonicalProjectPath: identity.canonicalProjectPath,
|
|
985
|
+
registryCanonicalProjectPath: instance.canonicalProjectPath,
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
async function readAliasStore(dataDir) {
|
|
990
|
+
try {
|
|
991
|
+
const parsed = JSON.parse(stripBom(await readFile(aliasesV2Path(dataDir), "utf8")));
|
|
992
|
+
if (parsed.version !== 2 || !Number.isInteger(parsed.revision) || !Array.isArray(parsed.aliases)) {
|
|
993
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "Alias store does not satisfy the v2 identity contract.");
|
|
994
|
+
}
|
|
995
|
+
const names = new Set();
|
|
996
|
+
for (const binding of parsed.aliases) {
|
|
997
|
+
if (!ALIAS_PATTERN.test(binding.alias) || names.has(binding.alias)
|
|
998
|
+
|| !INSTANCE_ID_PATTERN.test(binding.instanceId)
|
|
999
|
+
|| binding.canonicalizationVersion !== 1) {
|
|
1000
|
+
throw new InstanceRegistryError("E_INSTANCE_IDENTITY_MISMATCH", "Alias store contains an invalid or duplicate canonical identity binding.");
|
|
1001
|
+
}
|
|
1002
|
+
names.add(binding.alias);
|
|
1003
|
+
}
|
|
1004
|
+
return parsed;
|
|
1005
|
+
}
|
|
1006
|
+
catch (error) {
|
|
1007
|
+
if (error.code === "ENOENT")
|
|
1008
|
+
return { version: 2, revision: 0, aliases: [] };
|
|
1009
|
+
throw error;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
/** alias store 使用同目录临时文件原子替换;旧 aliases.json 从不读取。 */
|
|
1013
|
+
async function writeAliasStore(dataDir, store) {
|
|
1014
|
+
const filePath = aliasesV2Path(dataDir);
|
|
1015
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
1016
|
+
const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
|
|
1017
|
+
await writeFile(temporaryPath, `${JSON.stringify(store, null, 2)}\n`, "utf8");
|
|
1018
|
+
try {
|
|
1019
|
+
await rename(temporaryPath, filePath);
|
|
1020
|
+
}
|
|
1021
|
+
catch (error) {
|
|
1022
|
+
if (error.code !== "EEXIST" && error.code !== "EPERM")
|
|
1023
|
+
throw error;
|
|
1024
|
+
await rm(filePath, { force: true });
|
|
1025
|
+
await rename(temporaryPath, filePath);
|
|
1026
|
+
}
|
|
1027
|
+
finally {
|
|
1028
|
+
await rm(temporaryPath, { force: true });
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function aliasBinding(alias, identity) {
|
|
1032
|
+
return {
|
|
1033
|
+
alias,
|
|
1034
|
+
instanceId: identity.instanceId,
|
|
1035
|
+
canonicalProjectPath: identity.canonicalProjectPath,
|
|
1036
|
+
displayProjectPath: identity.displayProjectPath,
|
|
1037
|
+
canonicalizationVersion: 1,
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
/** reader只消费正式固定路径;瞬时parse failure也在同一absolute deadline内有界重读。 */
|
|
1041
|
+
async function readRegistrySnapshot(filePath, retryMissing = false, deadlineMs) {
|
|
1042
|
+
for (let attempt = 0;; attempt += 1) {
|
|
1043
|
+
try {
|
|
1044
|
+
const parsed = JSON.parse(stripBom(await readRegistryText(filePath, retryMissing, deadlineMs)));
|
|
1045
|
+
validateRegistryRecord(parsed);
|
|
1046
|
+
return parsed;
|
|
1047
|
+
}
|
|
1048
|
+
catch (error) {
|
|
1049
|
+
if (!(error instanceof SyntaxError) || attempt >= REGISTRY_READ_RETRY_DELAYS_MS.length || (deadlineMs !== undefined && Date.now() >= deadlineMs))
|
|
1050
|
+
throw error;
|
|
1051
|
+
const delayMs = Math.min(REGISTRY_READ_RETRY_DELAYS_MS[attempt], deadlineMs === undefined ? REGISTRY_READ_RETRY_DELAYS_MS[attempt] : Math.max(0, deadlineMs - Date.now()));
|
|
1052
|
+
if (delayMs <= 0)
|
|
1053
|
+
throw error;
|
|
1054
|
+
await new Promise((complete) => setTimeout(complete, delayMs));
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
/** Windows replace/open 的瞬时 sharing error 有界重读。 */
|
|
1059
|
+
async function readRegistryText(filePath, retryMissing = false, deadlineMs) {
|
|
1060
|
+
for (let attempt = 0;; attempt += 1) {
|
|
1061
|
+
try {
|
|
1062
|
+
return await readFile(filePath, "utf8");
|
|
1063
|
+
}
|
|
1064
|
+
catch (error) {
|
|
1065
|
+
const code = error.code;
|
|
1066
|
+
const retryable = (retryMissing && code === "ENOENT") || code === "EBUSY" || code === "EPERM" || code === "EACCES";
|
|
1067
|
+
if (!retryable || attempt >= REGISTRY_READ_RETRY_DELAYS_MS.length || (deadlineMs !== undefined && Date.now() >= deadlineMs))
|
|
1068
|
+
throw error;
|
|
1069
|
+
const delayMs = Math.min(REGISTRY_READ_RETRY_DELAYS_MS[attempt], deadlineMs === undefined ? REGISTRY_READ_RETRY_DELAYS_MS[attempt] : Math.max(0, deadlineMs - Date.now()));
|
|
1070
|
+
if (delayMs <= 0)
|
|
1071
|
+
throw error;
|
|
1072
|
+
await new Promise((complete) => setTimeout(complete, delayMs));
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
function looksLikePath(value) {
|
|
1077
|
+
return isAbsolute(value) || value.includes("\\") || value.includes("/") || value === "." || value.startsWith("..\\");
|
|
1078
|
+
}
|
|
1079
|
+
function projectNameFromPath(projectPath) {
|
|
1080
|
+
return projectPath.split(/[\\/]/).filter(Boolean).at(-1) ?? projectPath;
|
|
1081
|
+
}
|
|
1082
|
+
/** 原始 snapshot 的 busy 字段只用于 observation reducer,不得替代 live Bridge 证明。 */
|
|
1083
|
+
function snapshotIsTransitioning(snapshot) {
|
|
1084
|
+
const fields = snapshot?.fields;
|
|
1085
|
+
if (!fields || typeof fields !== "object" || Array.isArray(fields))
|
|
1086
|
+
return false;
|
|
1087
|
+
const field = fields;
|
|
1088
|
+
for (const name of ["compile", "import", "build"]) {
|
|
1089
|
+
const value = field[name];
|
|
1090
|
+
if (value && typeof value === "object" && !Array.isArray(value) && value.value === true)
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
const playMode = field.playMode;
|
|
1094
|
+
return !!playMode && typeof playMode === "object" && !Array.isArray(playMode)
|
|
1095
|
+
&& playMode.value === "transitioning";
|
|
1096
|
+
}
|
|
1097
|
+
function runPowerShell(command, env, timeoutMs) {
|
|
1098
|
+
const executable = process.env.SystemRoot
|
|
1099
|
+
? resolve(process.env.SystemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
1100
|
+
: "powershell.exe";
|
|
1101
|
+
return spawnSync(executable, ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(command, "utf16le").toString("base64")], {
|
|
1102
|
+
encoding: "utf8",
|
|
1103
|
+
windowsHide: true,
|
|
1104
|
+
timeout: timeoutMs,
|
|
1105
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
1106
|
+
env: { ...process.env, ...env },
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
/** fallback 校验不得阻塞 Node event loop;超时后终止子进程并 fail closed。 */
|
|
1110
|
+
function runPowerShellAsync(command, env, timeoutMs) {
|
|
1111
|
+
const executable = process.env.SystemRoot
|
|
1112
|
+
? resolve(process.env.SystemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
1113
|
+
: "powershell.exe";
|
|
1114
|
+
return new Promise((complete) => {
|
|
1115
|
+
const child = spawn(executable, ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(command, "utf16le").toString("base64")], {
|
|
1116
|
+
windowsHide: true,
|
|
1117
|
+
env: { ...process.env, ...env },
|
|
1118
|
+
});
|
|
1119
|
+
let stdout = "";
|
|
1120
|
+
let settled = false;
|
|
1121
|
+
const timeout = setTimeout(() => {
|
|
1122
|
+
child.kill();
|
|
1123
|
+
finish({ status: null, error: new Error("PowerShell probe timed out."), stdout });
|
|
1124
|
+
}, Math.max(1, timeoutMs));
|
|
1125
|
+
const finish = (result) => {
|
|
1126
|
+
if (settled)
|
|
1127
|
+
return;
|
|
1128
|
+
settled = true;
|
|
1129
|
+
clearTimeout(timeout);
|
|
1130
|
+
complete(result);
|
|
1131
|
+
};
|
|
1132
|
+
child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
|
|
1133
|
+
child.once("error", (error) => finish({ status: null, error, stdout }));
|
|
1134
|
+
child.once("close", (status) => finish({ status, stdout }));
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
//# sourceMappingURL=instances.js.map
|