@alpsckr/unitycli 0.4.3 → 0.4.4
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 +5 -5
- package/contracts/command-contract.json +109 -217
- package/contracts/package-files.json +374 -294
- package/contracts/stable-session/direct-call-semantics.json +8 -2
- package/contracts/tool-completion-contract.json +148 -672
- package/dist/bridge/admission.d.ts +17 -1
- package/dist/bridge/admission.js +2 -0
- package/dist/bridge/admission.js.map +1 -1
- package/dist/bridge/domains/asset.js +3 -1
- package/dist/bridge/domains/asset.js.map +1 -1
- package/dist/bridge/domains/camera.js +39 -7
- package/dist/bridge/domains/camera.js.map +1 -1
- package/dist/bridge/domains/console.js +2 -1
- package/dist/bridge/domains/console.js.map +1 -1
- package/dist/bridge/domains/doctor.d.ts +3 -0
- package/dist/bridge/domains/doctor.js +8 -0
- package/dist/bridge/domains/doctor.js.map +1 -0
- package/dist/bridge/domains/editor.js +0 -4
- package/dist/bridge/domains/editor.js.map +1 -1
- package/dist/bridge/domains/game-object.js +4 -12
- package/dist/bridge/domains/game-object.js.map +1 -1
- package/dist/bridge/domains/graphics.js +1 -16
- package/dist/bridge/domains/graphics.js.map +1 -1
- package/dist/bridge/domains/object.js +3 -0
- package/dist/bridge/domains/object.js.map +1 -1
- package/dist/bridge/domains/physics.js +1 -2
- package/dist/bridge/domains/physics.js.map +1 -1
- package/dist/bridge/domains/profiler.js +18 -7
- package/dist/bridge/domains/profiler.js.map +1 -1
- package/dist/bridge/domains/project-tool.js +4 -0
- package/dist/bridge/domains/project-tool.js.map +1 -1
- package/dist/bridge/domains/reflection.js +10 -2
- package/dist/bridge/domains/reflection.js.map +1 -1
- package/dist/bridge/domains/runtime-tool.js +3 -0
- package/dist/bridge/domains/runtime-tool.js.map +1 -1
- package/dist/bridge/domains/scene.js +3 -8
- package/dist/bridge/domains/scene.js.map +1 -1
- package/dist/bridge/domains/screenshot.js +30 -6
- package/dist/bridge/domains/screenshot.js.map +1 -1
- package/dist/bridge/domains/ui.js +3 -1
- package/dist/bridge/domains/ui.js.map +1 -1
- package/dist/bridge/index.d.ts +5 -5
- package/dist/bridge/index.js +6 -9
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/registry.js +3 -5
- package/dist/bridge/registry.js.map +1 -1
- package/dist/bridge/session-supervisor.d.ts +6 -3
- package/dist/bridge/session-supervisor.js +122 -34
- package/dist/bridge/session-supervisor.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -5
- package/dist/bridge/types.js +16 -2
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog-protocol.d.ts +64 -0
- package/dist/catalog-protocol.js +460 -0
- package/dist/catalog-protocol.js.map +1 -0
- package/dist/cli-commands/command.js +84 -61
- package/dist/cli-commands/command.js.map +1 -1
- package/dist/cli-commands/extensions.js +70 -50
- package/dist/cli-commands/extensions.js.map +1 -1
- package/dist/cli-commands/instances.js +1 -1
- package/dist/cli-commands/instances.js.map +1 -1
- package/dist/cli-process-owners.d.ts +6 -0
- package/dist/cli-process-owners.js +27 -0
- package/dist/cli-process-owners.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +20 -5
- package/dist/cli.js.map +1 -1
- package/dist/contracts/command-contract.js +14 -4
- package/dist/contracts/command-contract.js.map +1 -1
- package/dist/doctor.d.ts +4 -6
- package/dist/doctor.js +429 -398
- package/dist/doctor.js.map +1 -1
- package/dist/editor-blocker-observer.d.ts +2 -1
- package/dist/editor-blocker-observer.js +40 -13
- package/dist/editor-blocker-observer.js.map +1 -1
- package/dist/extension-availability.d.ts +27 -9
- package/dist/extension-availability.js +96 -56
- package/dist/extension-availability.js.map +1 -1
- package/dist/extensions/descriptor-loader.d.ts +2 -2
- package/dist/extensions/descriptor-loader.js +3 -4
- package/dist/extensions/descriptor-loader.js.map +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.js +1 -1
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/installer.d.ts +24 -7
- package/dist/extensions/installer.js +142 -66
- package/dist/extensions/installer.js.map +1 -1
- package/dist/extensions/registry.js +3 -5
- package/dist/extensions/registry.js.map +1 -1
- package/dist/extensions/state-contract.d.ts +11 -0
- package/dist/extensions/state-contract.js +50 -0
- package/dist/extensions/state-contract.js.map +1 -0
- package/dist/instances.d.ts +13 -1
- package/dist/instances.js +26 -0
- package/dist/instances.js.map +1 -1
- package/dist/package-manager.d.ts +0 -24
- package/dist/package-manager.js +5 -58
- package/dist/package-manager.js.map +1 -1
- package/dist/project-tool-discovery.d.ts +5 -2
- package/dist/project-tool-discovery.js +22 -18
- package/dist/project-tool-discovery.js.map +1 -1
- package/dist/runtime-code.js +1 -1
- package/dist/runtime-code.js.map +1 -1
- package/dist/tool-name.d.ts +4 -0
- package/dist/tool-name.js +15 -0
- package/dist/tool-name.js.map +1 -0
- package/dist/tools/.generated-completion-registry.d.ts +2 -0
- package/dist/tools/.generated-completion-registry.js +763 -325
- package/dist/tools/.generated-completion-registry.js.map +1 -1
- package/dist/tools/.generated-registry.d.ts +6 -11
- package/dist/tools/.generated-registry.js +6 -11
- package/dist/tools/.generated-registry.js.map +1 -1
- package/dist/tools/.generated-schemas.js +11 -16
- package/dist/tools/.generated-schemas.js.map +1 -1
- package/dist/tools/asset/refresh-status.d.ts +3 -0
- package/dist/tools/asset/refresh-status.js +12 -0
- package/dist/tools/asset/refresh-status.js.map +1 -0
- package/dist/tools/asset/refresh.js +7 -3
- package/dist/tools/asset/refresh.js.map +1 -1
- package/dist/tools/build/player-status.d.ts +3 -0
- package/dist/tools/build/player-status.js +12 -0
- package/dist/tools/build/player-status.js.map +1 -0
- package/dist/tools/build/run.js +1 -1
- package/dist/tools/build/run.js.map +1 -1
- package/dist/tools/catalog-control.d.ts +22 -0
- package/dist/tools/catalog-control.js +335 -0
- package/dist/tools/catalog-control.js.map +1 -0
- package/dist/tools/catalog.d.ts +7 -9
- package/dist/tools/catalog.js +66 -45
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/commands.d.ts +1 -1
- package/dist/tools/commands.js +44 -11
- package/dist/tools/commands.js.map +1 -1
- package/dist/tools/define.js +3 -2
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/dispatcher.d.ts +53 -6
- package/dist/tools/dispatcher.js +277 -108
- package/dist/tools/dispatcher.js.map +1 -1
- package/dist/tools/editor/compile.js +1 -1
- package/dist/tools/editor/compile.js.map +1 -1
- package/dist/tools/editor/play-mode-status.d.ts +3 -0
- package/dist/tools/editor/play-mode-status.js +12 -0
- package/dist/tools/editor/play-mode-status.js.map +1 -0
- package/dist/tools/editor/readiness.d.ts +0 -1
- package/dist/tools/editor/readiness.js +0 -1
- package/dist/tools/editor/readiness.js.map +1 -1
- package/dist/tools/editor/refresh.d.ts +7 -3
- package/dist/tools/editor/refresh.js +20 -15
- package/dist/tools/editor/refresh.js.map +1 -1
- package/dist/tools/editor/state.d.ts +2 -2
- package/dist/tools/editor/state.js +13 -12
- package/dist/tools/editor/state.js.map +1 -1
- package/dist/tools/metadata/derived.js +1 -7
- package/dist/tools/metadata/derived.js.map +1 -1
- package/dist/tools/metadata/status.js +1 -12
- package/dist/tools/metadata/status.js.map +1 -1
- package/dist/tools/metadata/types.d.ts +0 -2
- package/dist/tools/navmesh/live.js +1 -1
- package/dist/tools/navmesh/live.js.map +1 -1
- package/dist/tools/occlusion/live.js +1 -1
- package/dist/tools/occlusion/live.js.map +1 -1
- package/dist/tools/package/deploy.js +2 -2
- package/dist/tools/package/deploy.js.map +1 -1
- package/dist/tools/package/embed.js +1 -1
- package/dist/tools/package/embed.js.map +1 -1
- package/dist/tools/package/install-status.d.ts +3 -0
- package/dist/tools/package/install-status.js +12 -0
- package/dist/tools/package/install-status.js.map +1 -0
- package/dist/tools/package/install.js +3 -3
- package/dist/tools/package/install.js.map +1 -1
- package/dist/tools/package/live-resolve.js +45 -12
- package/dist/tools/package/live-resolve.js.map +1 -1
- package/dist/tools/package/registry-clear.js.map +1 -1
- package/dist/tools/package/registry-set.js.map +1 -1
- package/dist/tools/package/remove-status.d.ts +3 -0
- package/dist/tools/package/remove-status.js +12 -0
- package/dist/tools/package/remove-status.js.map +1 -0
- package/dist/tools/package/remove.js +3 -3
- package/dist/tools/package/remove.js.map +1 -1
- package/dist/tools/package/resolve.js +3 -3
- package/dist/tools/package/resolve.js.map +1 -1
- package/dist/tools/package/restore.js +2 -2
- package/dist/tools/package/restore.js.map +1 -1
- package/dist/tools/package/scoped-registry-add.js.map +1 -1
- package/dist/tools/status/support.d.ts +13 -0
- package/dist/tools/status/support.js +28 -0
- package/dist/tools/status/support.js.map +1 -0
- package/dist/tools/test/cancel.js +2 -2
- package/dist/tools/test/cancel.js.map +1 -1
- package/dist/tools/test/run-status.d.ts +3 -0
- package/dist/tools/test/run-status.js +12 -0
- package/dist/tools/test/run-status.js.map +1 -0
- package/dist/tools/test/run.js +7 -4
- package/dist/tools/test/run.js.map +1 -1
- package/dist/tools/tools/group-summaries.js +10 -14
- package/dist/tools/tools/group-summaries.js.map +1 -1
- package/docs/architecture.md +4 -4
- package/docs/availability-differences.md +4 -4
- package/docs/command-execution.md +4 -3
- package/docs/error-codes.md +13 -5
- package/docs/extensions.md +1 -7
- package/docs/risk-and-side-effects.md +4 -3
- package/docs/safety-boundaries.md +3 -1
- package/docs/target-and-instance.md +1 -1
- package/docs/tool-discovery.md +17 -10
- package/docs/tool-execution.md +18 -7
- package/extensions/cinemachine/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/hdrp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/probuilder/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/urp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/vfx-graph/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/package.json +2 -4
- package/skills/unitycli/SKILL.md +11 -2
- package/skills/unitycli/manifest.json +1 -1
- package/skills/unitycli/references/operation-protocol.md +3 -3
- package/unitypkg/Editor/AssemblyInfo.cs +5 -0
- package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +49 -14
- package/unitypkg/Editor/Bridge/BridgeHttpServer.cs +9 -35
- package/unitypkg/Editor/Bridge/BridgeQueueState.cs +672 -0
- package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +970 -120
- package/unitypkg/Editor/BridgeStartupStateMachine.cs +59 -1
- package/unitypkg/Editor/Commands/ProjectToolCommands.cs +4 -0
- package/unitypkg/Editor/Commands/RuntimeToolCommands.cs +3 -0
- package/unitypkg/Editor/Generated/UnityCliToolCompletionRegistry.g.cs +379 -14
- package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +28 -13
- package/unitypkg/Editor/Infrastructure/RegistryOwnershipResolver.cs +132 -105
- package/unitypkg/Editor/Infrastructure/UnityCliActiveOperation.cs +138 -29
- package/unitypkg/Editor/Infrastructure/UnityCliAdmission.cs +1856 -237
- package/unitypkg/Editor/Infrastructure/UnityCliDoctorDiagnostics.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliDurableStatusCoordinator.cs +118 -0
- package/unitypkg/Editor/Infrastructure/UnityCliEditorStateSnapshot.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliHierarchyPager.cs +203 -0
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceCleanup.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +201 -63
- package/unitypkg/Editor/Infrastructure/UnityCliJson.cs +2 -3
- package/unitypkg/Editor/Infrastructure/UnityCliLiveBuildCoordinator.cs +289 -46
- package/unitypkg/Editor/Infrastructure/UnityCliLiveRefreshCoordinator.cs +87 -53
- package/unitypkg/Editor/Infrastructure/UnityCliNavMeshBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliObjectRef.cs +128 -25
- package/unitypkg/Editor/Infrastructure/UnityCliObjectSerializer.cs +435 -327
- package/unitypkg/Editor/Infrastructure/UnityCliOcclusionBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +351 -53
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveCoordinator.cs +118 -18
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveState.cs +20 -1
- package/unitypkg/Editor/Infrastructure/UnityCliReadGeneration.cs +97 -0
- package/unitypkg/Editor/Infrastructure/UnityCliReflection.cs +644 -133
- package/unitypkg/Editor/Infrastructure/UnityCliReloadOperation.cs +128 -41
- package/unitypkg/Editor/Infrastructure/UnityCliRuntimeExecutor.cs +14 -84
- package/unitypkg/Editor/Infrastructure/UnityCliSerializer.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSessionMutationLease.cs +69 -29
- package/unitypkg/Editor/Infrastructure/UnityCliTestRunCoordinator.cs +440 -54
- package/unitypkg/Editor/Infrastructure/UnityCliWaiter.cs +128 -35
- package/unitypkg/Editor/ProjectTools/IUnityCliTool.cs +9 -1
- package/unitypkg/Editor/ProjectTools/OfficialAttributeToolRegistry.cs +32 -31
- package/unitypkg/Editor/ProjectTools/ProjectToolRegistry.cs +607 -458
- package/unitypkg/Editor/ProjectTools/ProjectToolSchemaValidator.cs +35 -7
- package/unitypkg/Editor/ProjectTools/RegisteredTool.cs +501 -60
- package/unitypkg/Editor/ProjectTools/UnityCliProjectToolContext.cs +21 -0
- package/unitypkg/Editor/ProjectTools/UnityCliSchemaDeriver.cs +36 -7
- package/unitypkg/Editor/ProjectTools/UnityCliToolName.cs +30 -0
- package/unitypkg/Editor/Properties/AssemblyInfo.cs +3 -0
- package/unitypkg/Editor/Tools/asset/get-data.cs +16 -7
- package/unitypkg/Editor/Tools/build/BuildSceneStateTool.cs +23 -3
- package/unitypkg/Editor/Tools/build/BuildToolDtos.cs +2 -1
- package/unitypkg/Editor/Tools/build/scene/add.cs +6 -3
- package/unitypkg/Editor/Tools/build/scene/disable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/enable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/list.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/remove.cs +13 -3
- package/unitypkg/Editor/Tools/camera/CameraToolSupport.cs +38 -38
- package/unitypkg/Editor/Tools/camera/multiview.cs +13 -6
- package/unitypkg/Editor/Tools/camera/screenshot.cs +14 -7
- package/unitypkg/Editor/Tools/component/get.cs +16 -9
- package/unitypkg/Editor/Tools/component/modify.cs +6 -4
- package/unitypkg/Editor/Tools/console/clear.cs +7 -6
- package/unitypkg/Editor/Tools/console/get.cs +48 -16
- package/unitypkg/Editor/Tools/editor/EditorToolSupport.cs +143 -28
- package/unitypkg/Editor/Tools/editor/menu-items.cs +1 -1
- package/unitypkg/Editor/Tools/editor/play.cs +2 -11
- package/unitypkg/Editor/Tools/editor/selection.cs +1 -1
- package/unitypkg/Editor/Tools/editor/stop.cs +2 -11
- package/unitypkg/Editor/Tools/editor/windows.cs +1 -1
- package/unitypkg/Editor/Tools/go/GameObjectToolSupport.cs +54 -4
- package/unitypkg/Editor/Tools/go/delete.cs +1 -1
- package/unitypkg/Editor/Tools/go/find.cs +167 -70
- package/unitypkg/Editor/Tools/graphics/GraphicsToolSupport.cs +25 -0
- package/unitypkg/Editor/Tools/graphics/light-probe-group.cs +9 -3
- package/unitypkg/Editor/Tools/graphics/pipeline-info.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/pipeline-settings.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/quality.cs +2 -2
- package/unitypkg/Editor/Tools/graphics/reflection-probe.cs +3 -3
- package/unitypkg/Editor/Tools/graphics/stats.cs +1 -1
- package/unitypkg/Editor/Tools/object/ObjectToolSupport.cs +4 -4
- package/unitypkg/Editor/Tools/object/get-data.cs +9 -7
- package/unitypkg/Editor/Tools/object/modify.cs +7 -5
- package/unitypkg/Editor/Tools/physics/raycast.cs +24 -6
- package/unitypkg/Editor/Tools/prefab/stage.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/ProfilerFrameDebuggerSupport.cs +94 -21
- package/unitypkg/Editor/Tools/profiler/ProfilerMemorySnapshotSupport.cs +397 -10
- package/unitypkg/Editor/Tools/profiler/ProfilerToolSupport.cs +18 -4
- package/unitypkg/Editor/Tools/profiler/frame-debugger/enable.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/frame-debugger/events.cs +88 -87
- package/unitypkg/Editor/Tools/profiler/hierarchy.cs +278 -112
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/compare.cs +9 -5
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/list.cs +37 -35
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/take.cs +99 -97
- package/unitypkg/Editor/Tools/project/info.cs +1 -1
- package/unitypkg/Editor/Tools/project/layers.cs +1 -1
- package/unitypkg/Editor/Tools/project/tags.cs +1 -1
- package/unitypkg/Editor/Tools/reflection/method/call.cs +9 -7
- package/unitypkg/Editor/Tools/reflection/method/find.cs +27 -37
- package/unitypkg/Editor/Tools/reflection/type/schema.cs +24 -28
- package/unitypkg/Editor/Tools/scene/gameobject/component.cs +8 -5
- package/unitypkg/Editor/Tools/scene/gameobject/components.cs +10 -7
- package/unitypkg/Editor/Tools/scene/gameobject-support.cs +104 -8
- package/unitypkg/Editor/Tools/scene/gameobject.cs +37 -16
- package/unitypkg/Editor/Tools/scene/hierarchy.cs +146 -142
- package/unitypkg/Editor/Tools/screenshot/EditorElementCaptureToolSupport.cs +77 -25
- package/unitypkg/Editor/Tools/screenshot/ScreenshotToolSupport.cs +315 -95
- package/unitypkg/Editor/Tools/screenshot/editor-element.cs +7 -5
- package/unitypkg/Editor/Tools/screenshot/game-view.cs +35 -21
- package/unitypkg/Editor/Tools/screenshot/isolated-object.cs +29 -23
- package/unitypkg/Editor/Tools/screenshot/orbit.cs +37 -25
- package/unitypkg/Editor/Tools/screenshot/scene-view.cs +25 -18
- package/unitypkg/Editor/Tools/screenshot/screen.cs +177 -17
- package/unitypkg/Editor/Tools/screenshot/surround.cs +83 -79
- package/unitypkg/Editor/Tools/ui/render-preview.cs +16 -11
- package/unitypkg/Editor/UnityCliBridge.cs +97 -34
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeBridge.cs +753 -122
- package/unitypkg/Runtime/Properties/AssemblyInfo.cs +5 -0
- package/unitypkg/Runtime/UnityCli.Runtime.asmdef +1 -1
- package/unitypkg/Shared/AssemblyInfo.cs +4 -0
- package/unitypkg/Shared/UnityCliAdmissionPool.cs +265 -75
- package/unitypkg/Shared/UnityCliBridgeQueuePolicy.cs +410 -0
- package/unitypkg/Shared/UnityCliBridgeWorkItemState.cs +47 -0
- package/unitypkg/Shared/UnityCliExceptionProjection.cs +151 -0
- package/unitypkg/Shared/UnityCliQueuePublication.cs +30 -0
- package/unitypkg/Shared/UnityCliRequestBudget.cs +352 -0
- package/unitypkg/Shared/UnityCliRuntimeRequestPublication.cs +107 -0
- package/unitypkg/Tests/Editor/UnityCli.Editor.Tests.asmdef +2 -2
- package/unitypkg/Tests/Editor/UnityCliAdmissionCoordinatorIntegrationTests.cs +1329 -0
- package/unitypkg/Tests/Editor/UnityCliAdmissionPoolTests.cs +311 -114
- package/unitypkg/Tests/Editor/UnityCliAdmissionRepairStateTests.cs +94 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeAdmissionIntegrationTests.cs +1229 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeQueuePolicyTests.cs +412 -0
- package/unitypkg/Tests/Editor/UnityCliContinuationIntegrationTests.cs +292 -0
- package/unitypkg/Tests/Editor/UnityCliDiagnosticBoundaryTests.cs +120 -0
- package/unitypkg/Tests/Editor/UnityCliDurableStatusTests.cs +84 -0
- package/unitypkg/Tests/Editor/UnityCliExceptionProjectionTests.cs +72 -0
- package/unitypkg/Tests/Editor/UnityCliInstancePublicationRetryTests.cs +180 -97
- package/unitypkg/Tests/Editor/UnityCliMemoryReflectionIntegrationTests.cs +434 -0
- package/unitypkg/Tests/Editor/UnityCliRequestBudgetTests.cs +615 -0
- package/unitypkg/Tests/Editor/UnityCliRuntimeBridgeIntegrationTests.cs +520 -0
- package/unitypkg/Tests/Editor/UnityCliToolCatalogTests.cs +562 -0
- package/unitypkg/Tests/Runtime/UnityCli.Runtime.Tests.asmdef +23 -0
- package/unitypkg/Tests/Runtime/UnityCliRuntimeCatalogValidationTests.cs +29 -0
- package/unitypkg/package.json +1 -1
- package/contracts/static-capability-catalog.json +0 -48226
- package/dist/bridge/domains/diagnose.d.ts +0 -2
- package/dist/bridge/domains/diagnose.js +0 -11
- package/dist/bridge/domains/diagnose.js.map +0 -1
- package/dist/bridge/domains/extension.d.ts +0 -8
- package/dist/bridge/domains/extension.js +0 -20
- package/dist/bridge/domains/extension.js.map +0 -1
- package/dist/capabilities.d.ts +0 -5
- package/dist/capabilities.js +0 -84
- package/dist/capabilities.js.map +0 -1
- package/dist/static-capability-catalog.d.ts +0 -13
- package/dist/static-capability-catalog.js +0 -41
- package/dist/static-capability-catalog.js.map +0 -1
- package/dist/tools/diagnose/capabilities.d.ts +0 -13
- package/dist/tools/diagnose/capabilities.js +0 -34
- package/dist/tools/diagnose/capabilities.js.map +0 -1
- package/dist/tools/package/info.d.ts +0 -19
- package/dist/tools/package/info.js +0 -27
- package/dist/tools/package/info.js.map +0 -1
- package/dist/tools/package/list.d.ts +0 -27
- package/dist/tools/package/list.js +0 -21
- package/dist/tools/package/list.js.map +0 -1
- package/dist/tools/package/registry-get.d.ts +0 -10
- package/dist/tools/package/registry-get.js +0 -22
- package/dist/tools/package/registry-get.js.map +0 -1
- package/dist/tools/package/scoped-registry-list.d.ts +0 -14
- package/dist/tools/package/scoped-registry-list.js +0 -22
- package/dist/tools/package/scoped-registry-list.js.map +0 -1
- package/dist/tools/package/search.d.ts +0 -17
- package/dist/tools/package/search.js +0 -39
- package/dist/tools/package/search.js.map +0 -1
- package/dist/tools/package/status.d.ts +0 -21
- package/dist/tools/package/status.js +0 -37
- package/dist/tools/package/status.js.map +0 -1
- package/dist/tools/tools/describe.d.ts +0 -27
- package/dist/tools/tools/describe.js +0 -35
- package/dist/tools/tools/describe.js.map +0 -1
- package/dist/tools/tools/group-list.d.ts +0 -16
- package/dist/tools/tools/group-list.js +0 -38
- package/dist/tools/tools/group-list.js.map +0 -1
- package/dist/tools/tools/group.d.ts +0 -13
- package/dist/tools/tools/group.js +0 -34
- package/dist/tools/tools/group.js.map +0 -1
- package/dist/tools/tools/pagination.d.ts +0 -17
- package/dist/tools/tools/pagination.js +0 -28
- package/dist/tools/tools/pagination.js.map +0 -1
- package/dist/tools/tools/search.d.ts +0 -15
- package/dist/tools/tools/search.js +0 -42
- package/dist/tools/tools/search.js.map +0 -1
- package/unitypkg/Editor/Tools/diagnose/preflight.cs +0 -269
- package/unitypkg/Editor/Tools/editor/console.cs +0 -26
- package/unitypkg/Editor/Tools/extension/status.cs +0 -87
- package/unitypkg/Editor/Tools/go/inspect.cs +0 -49
- package/unitypkg/Editor/Tools/graphics/pipeline-quality.cs +0 -24
- package/unitypkg/Editor/Tools/graphics/probe-positions.cs +0 -58
- package/unitypkg/Editor/Tools/graphics/settings.cs +0 -104
- package/unitypkg/Editor/Tools/graphics/stats-counters.cs +0 -28
- package/unitypkg/Editor/Tools/graphics/stats-memory.cs +0 -21
- package/unitypkg/Editor/Tools/instances/list.cs +0 -71
- package/unitypkg/Editor/Tools/physics/raycast-all.cs +0 -67
- package/unitypkg/Editor/Tools/scene/build-settings.cs +0 -69
- package/unitypkg/Editor/Tools/scene/data.cs +0 -125
- package/unitypkg/Editor/Tools/tests/list.cs +0 -98
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
#if UNITY_EDITOR
|
|
2
|
+
using System;
|
|
3
|
+
using System.Collections.Generic;
|
|
2
4
|
using System.Globalization;
|
|
3
5
|
using System.IO;
|
|
6
|
+
using System.Text;
|
|
7
|
+
using System.Threading;
|
|
8
|
+
using UnityEditor;
|
|
4
9
|
|
|
5
10
|
namespace UnityCli
|
|
6
11
|
{
|
|
@@ -10,21 +15,403 @@ namespace UnityCli
|
|
|
10
15
|
public long SizeBytes { get; set; }
|
|
11
16
|
public string Created { get; set; }
|
|
12
17
|
|
|
13
|
-
public static MemorySnapshotEntry FromFileInfo(FileInfo
|
|
18
|
+
public static MemorySnapshotEntry FromFileInfo(FileInfo info)
|
|
14
19
|
{
|
|
15
|
-
return new MemorySnapshotEntry
|
|
16
|
-
{
|
|
17
|
-
Path = fi.FullName,
|
|
18
|
-
SizeBytes = fi.Length,
|
|
19
|
-
Created = fi.CreationTimeUtc.ToString("O", CultureInfo.InvariantCulture)
|
|
20
|
-
};
|
|
20
|
+
return new MemorySnapshotEntry { Path = info.FullName, SizeBytes = info.Length, Created = info.CreationTimeUtc.ToString("O", CultureInfo.InvariantCulture) };
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public sealed class SnapshotDelta
|
|
24
|
+
public sealed class SnapshotDelta { public long SizeDeltaBytes { get; set; } public double TimeDeltaSeconds { get; set; } }
|
|
25
|
+
|
|
26
|
+
/// <summary>Library/UnityCli/memory-snapshots 的唯一 path、retention、catalog 和 orphan owner。</summary>
|
|
27
|
+
[InitializeOnLoad]
|
|
28
|
+
internal static class ProfilerMemorySnapshotSupport
|
|
25
29
|
{
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
internal const int RetainedSnapshotCount = 100;
|
|
31
|
+
internal const long RetainedSnapshotBytes = 8L * 1024L * 1024L * 1024L;
|
|
32
|
+
internal const long AbsoluteSnapshotBytes = 4L * 1024L * 1024L * 1024L;
|
|
33
|
+
private const int MaximumObservedFiles = 1024;
|
|
34
|
+
private const int PendingSlotCount = 8;
|
|
35
|
+
private const int MaximumLegacyOrphansPerPass = 1024;
|
|
36
|
+
private static readonly object PublicationLock = new object();
|
|
37
|
+
private static readonly object PendingLock = new object();
|
|
38
|
+
private static readonly HashSet<string> ActivePendingSlots = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
39
|
+
private static readonly HashSet<string> PendingCleanup = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
40
|
+
private static int cleanupScheduled;
|
|
41
|
+
internal static string RootOverrideForTests;
|
|
42
|
+
internal static Action<string> DeleteFileOverrideForTests;
|
|
43
|
+
|
|
44
|
+
static ProfilerMemorySnapshotSupport()
|
|
45
|
+
{
|
|
46
|
+
ScheduleOrphanCleanup();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
internal static string Root
|
|
50
|
+
{
|
|
51
|
+
get
|
|
52
|
+
{
|
|
53
|
+
var root = string.IsNullOrWhiteSpace(RootOverrideForTests)
|
|
54
|
+
? Path.Combine(ProfilerToolSupport.ProjectRoot(), "Library", "UnityCli", "memory-snapshots")
|
|
55
|
+
: RootOverrideForTests;
|
|
56
|
+
return Path.GetFullPath(root);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// <summary>测试结束时清除故障注入和固定slot占用,避免跨case污染。</summary>
|
|
61
|
+
internal static void ResetTestOverrides()
|
|
62
|
+
{
|
|
63
|
+
RootOverrideForTests = null;
|
|
64
|
+
DeleteFileOverrideForTests = null;
|
|
65
|
+
ProfilerToolSupport.MemoryProfilerTypeOverrideForTests = null;
|
|
66
|
+
lock (PendingLock)
|
|
67
|
+
{
|
|
68
|
+
ActivePendingSlots.Clear();
|
|
69
|
+
PendingCleanup.Clear();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
internal static string ResolveFinalPath(string requestedName, string requestId)
|
|
74
|
+
{
|
|
75
|
+
try
|
|
76
|
+
{
|
|
77
|
+
var name = string.IsNullOrWhiteSpace(requestedName) ? "snapshot_" + SafeName(requestId) + ".snap" : requestedName.Trim();
|
|
78
|
+
if (name.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0 || !string.Equals(name, Path.GetFileName(name), StringComparison.Ordinal)
|
|
79
|
+
|| !name.EndsWith(".snap", StringComparison.OrdinalIgnoreCase) || IsReservedWindowsName(Path.GetFileNameWithoutExtension(name)))
|
|
80
|
+
throw Error("E_PROFILER_SNAPSHOT_PATH_INVALID", "Snapshot path must be one valid .snap file name without directories.", "Pass a file name such as capture.snap; artifacts always use Library/UnityCli/memory-snapshots.");
|
|
81
|
+
var fullPath = Path.GetFullPath(Path.Combine(Root, name));
|
|
82
|
+
if (!fullPath.StartsWith(Root + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
|
|
83
|
+
throw Error("E_PROFILER_SNAPSHOT_PATH_INVALID", "Snapshot path resolves outside the governed root.", "Pass a simple .snap file name.");
|
|
84
|
+
return fullPath;
|
|
85
|
+
}
|
|
86
|
+
catch (UnityCliBridge.BridgeCommandException) { throw; }
|
|
87
|
+
catch (Exception)
|
|
88
|
+
{
|
|
89
|
+
throw Error("E_PROFILER_SNAPSHOT_PATH_INVALID", "Snapshot path is not a valid governed .snap file name.", "Pass a simple file name such as capture.snap.");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private static bool IsReservedWindowsName(string value)
|
|
94
|
+
{
|
|
95
|
+
if (string.IsNullOrEmpty(value)) return true;
|
|
96
|
+
var normalized = value.TrimEnd(' ', '.').ToUpperInvariant();
|
|
97
|
+
var dot = normalized.IndexOf('.');
|
|
98
|
+
if (dot >= 0) normalized = normalized.Substring(0, dot);
|
|
99
|
+
if (normalized == "CON" || normalized == "PRN" || normalized == "AUX" || normalized == "NUL") return true;
|
|
100
|
+
if (normalized.Length == 4 && (normalized.StartsWith("COM", StringComparison.Ordinal) || normalized.StartsWith("LPT", StringComparison.Ordinal)))
|
|
101
|
+
return normalized[3] >= '1' && normalized[3] <= '9';
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// <summary>每个domain最多占用8个固定pending slot;未收到callback的slot不复用,避免迟到writer污染新请求。</summary>
|
|
106
|
+
internal static string AcquirePendingPath(string requestId)
|
|
107
|
+
{
|
|
108
|
+
PrepareRoot();
|
|
109
|
+
var fingerprint = UnityCliContinuationToken.Fingerprint(requestId ?? string.Empty);
|
|
110
|
+
var start = (int)(unchecked((uint)StringComparer.Ordinal.GetHashCode(fingerprint)) % PendingSlotCount);
|
|
111
|
+
lock (PendingLock)
|
|
112
|
+
{
|
|
113
|
+
for (var offset = 0; offset < PendingSlotCount; offset++)
|
|
114
|
+
{
|
|
115
|
+
var path = PendingSlotPath((start + offset) % PendingSlotCount);
|
|
116
|
+
if (!ActivePendingSlots.Add(path)) continue;
|
|
117
|
+
try
|
|
118
|
+
{
|
|
119
|
+
DeleteStrict(path, "E_PROFILER_SNAPSHOT_PENDING_CLEANUP_FAILED", "Failed to prepare the bounded snapshot pending slot.");
|
|
120
|
+
return path;
|
|
121
|
+
}
|
|
122
|
+
catch
|
|
123
|
+
{
|
|
124
|
+
ActivePendingSlots.Remove(path);
|
|
125
|
+
throw;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
throw Error("E_PROFILER_SNAPSHOT_PENDING_SLOTS_BUSY", "All bounded memory snapshot pending slots are awaiting callbacks.", "Wait for the outstanding Memory Profiler callbacks or reload the Editor domain before retrying.");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
internal static void ReleasePendingPath(string path)
|
|
133
|
+
{
|
|
134
|
+
lock (PendingLock) ActivePendingSlots.Remove(Path.GetFullPath(path));
|
|
135
|
+
RequestPendingCleanup(path);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
internal static void RequestPendingCleanup(string path)
|
|
139
|
+
{
|
|
140
|
+
if (string.IsNullOrWhiteSpace(path)) return;
|
|
141
|
+
try
|
|
142
|
+
{
|
|
143
|
+
DeleteStrict(path, "E_PROFILER_SNAPSHOT_PENDING_CLEANUP_FAILED", "Failed to clean the bounded snapshot pending slot.");
|
|
144
|
+
lock (PendingLock) PendingCleanup.Remove(Path.GetFullPath(path));
|
|
145
|
+
}
|
|
146
|
+
catch
|
|
147
|
+
{
|
|
148
|
+
lock (PendingLock)
|
|
149
|
+
{
|
|
150
|
+
if (PendingCleanup.Count < PendingSlotCount) PendingCleanup.Add(Path.GetFullPath(path));
|
|
151
|
+
}
|
|
152
|
+
ScheduleOrphanCleanup();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private static string PendingSlotPath(int slot)
|
|
157
|
+
{
|
|
158
|
+
return Path.Combine(Root, ".pending-" + slot.ToString("00", CultureInfo.InvariantCulture) + ".snap");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
internal static void PrepareRoot()
|
|
162
|
+
{
|
|
163
|
+
Directory.CreateDirectory(Root);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
internal static FileInfo Publish(string capturedPath, string pendingPath, string finalPath, long requestedMaxBytes, UnityCliRequestBudget budget)
|
|
167
|
+
{
|
|
168
|
+
var source = Path.GetFullPath(string.IsNullOrWhiteSpace(capturedPath) ? pendingPath : capturedPath);
|
|
169
|
+
if (!string.Equals(source, Path.GetFullPath(pendingPath), StringComparison.OrdinalIgnoreCase))
|
|
170
|
+
throw Error("E_PROFILER_SNAPSHOT_ARTIFACT_INVALID", "MemoryProfiler callback returned an unexpected artifact path.", "Inspect the Memory Profiler package and retry.");
|
|
171
|
+
lock (PublicationLock)
|
|
172
|
+
{
|
|
173
|
+
budget.CheckpointOrThrow();
|
|
174
|
+
var info = new FileInfo(source);
|
|
175
|
+
if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
176
|
+
var exists = info.Exists;
|
|
177
|
+
if (!exists) throw Error("E_PROFILER_SNAPSHOT_ARTIFACT_MISSING", "MemoryProfiler did not produce a non-empty snapshot.", "Check disk space and Unity Console before retrying.");
|
|
178
|
+
if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
179
|
+
var length = info.Length;
|
|
180
|
+
if (length <= 0L) throw Error("E_PROFILER_SNAPSHOT_ARTIFACT_MISSING", "MemoryProfiler did not produce a non-empty snapshot.", "Check disk space and Unity Console before retrying.");
|
|
181
|
+
try { ValidateSnapshotLength(length, requestedMaxBytes); }
|
|
182
|
+
catch
|
|
183
|
+
{
|
|
184
|
+
DeleteStrict(source, "E_PROFILER_SNAPSHOT_PENDING_CLEANUP_FAILED", "Failed to remove an oversized pending snapshot.");
|
|
185
|
+
throw;
|
|
186
|
+
}
|
|
187
|
+
if (File.Exists(finalPath)) throw Error("E_OUTPUT_EXISTS", "Snapshot output already exists: " + finalPath, "Choose another snapshot file name.");
|
|
188
|
+
budget.CheckpointOrThrow();
|
|
189
|
+
File.Move(source, finalPath);
|
|
190
|
+
try
|
|
191
|
+
{
|
|
192
|
+
budget.CheckpointOrThrow();
|
|
193
|
+
ApplyRetention(finalPath, budget);
|
|
194
|
+
}
|
|
195
|
+
catch
|
|
196
|
+
{
|
|
197
|
+
DeleteStrict(finalPath, "E_PROFILER_SNAPSHOT_ROLLBACK_FAILED", "Snapshot retention failed and the published artifact could not be rolled back.");
|
|
198
|
+
throw;
|
|
199
|
+
}
|
|
200
|
+
var published = new FileInfo(finalPath);
|
|
201
|
+
if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
202
|
+
var publishedLength = published.Length;
|
|
203
|
+
if (publishedLength <= 0L) throw Error("E_PROFILER_SNAPSHOT_ARTIFACT_MISSING", "Published snapshot is empty after retention verification.", "Inspect storage and retry the capture.");
|
|
204
|
+
return published;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// <summary>在任何 publication 前复用同一 4 GiB 与调用方 ceiling 判定。</summary>
|
|
209
|
+
internal static void ValidateSnapshotLength(long length, long requestedMaxBytes)
|
|
210
|
+
{
|
|
211
|
+
if (length <= 0L)
|
|
212
|
+
throw Error("E_PROFILER_SNAPSHOT_ARTIFACT_MISSING", "MemoryProfiler did not produce a non-empty snapshot.", "Check disk space and Unity Console before retrying.");
|
|
213
|
+
if (length > AbsoluteSnapshotBytes || length > requestedMaxBytes)
|
|
214
|
+
throw Error("E_PROFILER_SNAPSHOT_LIMIT_EXCEEDED", "Snapshot exceeds the requested or 4 GiB per-artifact ceiling.", "Increase maxBytes within 4 GiB or reduce captured state.");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/// <summary>每次 publication 后最多观察 108 个本产品文件,保留连续的最新 100 且总量不超过 8 GiB。</summary>
|
|
218
|
+
internal static void ApplyRetention(string newestPath, UnityCliRequestBudget budget)
|
|
219
|
+
{
|
|
220
|
+
var files = BoundedFiles(budget);
|
|
221
|
+
SortNewest(files, budget);
|
|
222
|
+
var newestIndex = -1;
|
|
223
|
+
for (var index = 0; index < files.Count; index++)
|
|
224
|
+
{
|
|
225
|
+
if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
226
|
+
if (string.Equals(files[index].FullName, newestPath, StringComparison.OrdinalIgnoreCase)) { newestIndex = index; break; }
|
|
227
|
+
}
|
|
228
|
+
if (newestIndex > 0)
|
|
229
|
+
{
|
|
230
|
+
var newest = files[newestIndex];
|
|
231
|
+
files.RemoveAt(newestIndex);
|
|
232
|
+
files.Insert(0, newest);
|
|
233
|
+
}
|
|
234
|
+
var sizes = new List<long>(files.Count);
|
|
235
|
+
foreach (var file in files)
|
|
236
|
+
{
|
|
237
|
+
if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
238
|
+
sizes.Add(file.Length);
|
|
239
|
+
}
|
|
240
|
+
var retained = UnityCliRetentionPlanner.RetainedIndices(sizes, RetainedSnapshotCount, RetainedSnapshotBytes);
|
|
241
|
+
budget.CheckpointOrThrow();
|
|
242
|
+
for (var index = 0; index < files.Count; index++)
|
|
243
|
+
{
|
|
244
|
+
if (retained.Contains(index)) continue;
|
|
245
|
+
DeleteStrict(files[index].FullName, "E_PROFILER_SNAPSHOT_RETENTION_DELETE_FAILED", "Failed to delete an artifact excluded by snapshot retention.");
|
|
246
|
+
}
|
|
247
|
+
VerifyRetentionPostcondition(newestPath, budget);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
internal static List<FileInfo> Catalog(UnityCliRequestBudget budget)
|
|
251
|
+
{
|
|
252
|
+
if (!Directory.Exists(Root)) return new List<FileInfo>();
|
|
253
|
+
var files = BoundedFiles(budget);
|
|
254
|
+
SortNewest(files, budget);
|
|
255
|
+
return files;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
internal static string CatalogGeneration(List<FileInfo> files, UnityCliRequestBudget budget)
|
|
259
|
+
{
|
|
260
|
+
var values = new List<string>(files.Count);
|
|
261
|
+
foreach (var info in files)
|
|
262
|
+
{
|
|
263
|
+
if (!budget.TryConsumeGetter() || !budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
264
|
+
var value = info.Name + "\0" + info.Length.ToString(CultureInfo.InvariantCulture) + "\0" + info.LastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture);
|
|
265
|
+
if (!budget.TryReserveSerializedUtf8(value)) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
266
|
+
values.Add(value);
|
|
267
|
+
}
|
|
268
|
+
return UnityCliContinuationToken.Fingerprint(UnityCliReadGeneration.Session("profiler.memory-snapshot.list") + "\0" + string.Join("\n", values.ToArray()));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// <summary>publication/retention/rollback删除失败必须返回稳定错误,禁止吞掉后继续宣称成功。</summary>
|
|
272
|
+
internal static void DeleteStrict(string path, string errorCode, string message)
|
|
273
|
+
{
|
|
274
|
+
try
|
|
275
|
+
{
|
|
276
|
+
var fullPath = Path.GetFullPath(path);
|
|
277
|
+
if (!fullPath.StartsWith(Root + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase))
|
|
278
|
+
throw new IOException("path is outside the governed snapshot root");
|
|
279
|
+
if (File.Exists(fullPath))
|
|
280
|
+
{
|
|
281
|
+
if (DeleteFileOverrideForTests != null) DeleteFileOverrideForTests(fullPath);
|
|
282
|
+
else File.Delete(fullPath);
|
|
283
|
+
}
|
|
284
|
+
if (File.Exists(fullPath)) throw new IOException("file still exists after deletion");
|
|
285
|
+
}
|
|
286
|
+
catch (Exception exception)
|
|
287
|
+
{
|
|
288
|
+
throw Error(errorCode, message + " " + exception.Message, "Inspect the exact governed file and storage permissions before retrying.");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/// <summary>删除后重新枚举并验证count、total bytes、single file和newest存在性。</summary>
|
|
293
|
+
private static void VerifyRetentionPostcondition(string newestPath, UnityCliRequestBudget budget)
|
|
294
|
+
{
|
|
295
|
+
var verified = BoundedFiles(budget);
|
|
296
|
+
long totalBytes = 0L;
|
|
297
|
+
var newestExists = false;
|
|
298
|
+
foreach (var file in verified)
|
|
299
|
+
{
|
|
300
|
+
if (!budget.TryConsumeGetters(2)) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
301
|
+
var length = file.Length;
|
|
302
|
+
if (length <= 0L || length > AbsoluteSnapshotBytes)
|
|
303
|
+
throw Error("E_PROFILER_SNAPSHOT_RETENTION_VERIFY_FAILED", "Snapshot retention contains an empty or oversized artifact.", "Inspect the governed snapshot directory before retrying.");
|
|
304
|
+
totalBytes = checked(totalBytes + length);
|
|
305
|
+
if (string.Equals(file.FullName, newestPath, StringComparison.OrdinalIgnoreCase)) newestExists = true;
|
|
306
|
+
}
|
|
307
|
+
if (!newestExists || verified.Count > RetainedSnapshotCount || totalBytes > RetainedSnapshotBytes)
|
|
308
|
+
throw Error("E_PROFILER_SNAPSHOT_RETENTION_VERIFY_FAILED", "Snapshot retention postcondition is not count<=100, total<=8GiB with the newest artifact present.", "Inspect the governed snapshot directory before retrying.");
|
|
309
|
+
budget.CheckpointOrThrow();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private static void SortNewest(List<FileInfo> files, UnityCliRequestBudget budget)
|
|
313
|
+
{
|
|
314
|
+
var entries = new List<SnapshotSortEntry>(files.Count);
|
|
315
|
+
foreach (var file in files)
|
|
316
|
+
{
|
|
317
|
+
if (!budget.TryConsumeGetter() || !budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
318
|
+
entries.Add(new SnapshotSortEntry { File = file, LastWriteTimeUtc = file.LastWriteTimeUtc, Name = file.Name });
|
|
319
|
+
}
|
|
320
|
+
entries.Sort((left, right) =>
|
|
321
|
+
{
|
|
322
|
+
var time = right.LastWriteTimeUtc.CompareTo(left.LastWriteTimeUtc);
|
|
323
|
+
return time != 0 ? time : string.CompareOrdinal(right.Name, left.Name);
|
|
324
|
+
});
|
|
325
|
+
files.Clear();
|
|
326
|
+
foreach (var entry in entries) files.Add(entry.File);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private sealed class SnapshotSortEntry
|
|
330
|
+
{
|
|
331
|
+
internal FileInfo File;
|
|
332
|
+
internal DateTime LastWriteTimeUtc;
|
|
333
|
+
internal string Name;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
private static List<FileInfo> BoundedFiles(UnityCliRequestBudget budget)
|
|
337
|
+
{
|
|
338
|
+
var result = new List<FileInfo>();
|
|
339
|
+
if (!Directory.Exists(Root)) return result;
|
|
340
|
+
foreach (var path in Directory.EnumerateFiles(Root, "*.snap", SearchOption.TopDirectoryOnly))
|
|
341
|
+
{
|
|
342
|
+
if (budget != null && !budget.TryConsumeScannedRecord()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
343
|
+
if (Path.GetFileName(path).StartsWith(".pending-", StringComparison.Ordinal)) continue;
|
|
344
|
+
result.Add(new FileInfo(path));
|
|
345
|
+
if (result.Count > MaximumObservedFiles)
|
|
346
|
+
throw Error("E_PROFILER_SNAPSHOT_CATALOG_UNBOUNDED", "Snapshot catalog exceeds the governed retention recovery bound.", "Move non-UnityCLI snapshots out of Library/UnityCli/memory-snapshots, then retry.");
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/// <summary>单个scheduler任务持续处理固定slot和旧candidate orphan;每tick工作有1024项硬上限。</summary>
|
|
352
|
+
private static void ScheduleOrphanCleanup()
|
|
353
|
+
{
|
|
354
|
+
if (Interlocked.CompareExchange(ref cleanupScheduled, 1, 0) != 0) return;
|
|
355
|
+
UnityCliWaitScheduler.Until(
|
|
356
|
+
"memory-snapshot-orphan-cleanup",
|
|
357
|
+
"profiler.memory-snapshot",
|
|
358
|
+
CleanupOrphanPass,
|
|
359
|
+
TimeSpan.FromDays(3650),
|
|
360
|
+
default(CancellationToken));
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
internal static bool CleanupOrphanPass()
|
|
364
|
+
{
|
|
365
|
+
var allClean = true;
|
|
366
|
+
List<string> pending;
|
|
367
|
+
lock (PendingLock) pending = new List<string>(PendingCleanup);
|
|
368
|
+
foreach (var path in pending)
|
|
369
|
+
{
|
|
370
|
+
try
|
|
371
|
+
{
|
|
372
|
+
DeleteStrict(path, "E_PROFILER_SNAPSHOT_PENDING_CLEANUP_FAILED", "Failed to clean a bounded snapshot pending slot.");
|
|
373
|
+
lock (PendingLock) PendingCleanup.Remove(path);
|
|
374
|
+
}
|
|
375
|
+
catch { allClean = false; }
|
|
376
|
+
}
|
|
377
|
+
if (!Directory.Exists(Root)) return allClean && CompleteCleanupSchedule();
|
|
378
|
+
var observed = 0;
|
|
379
|
+
foreach (var path in Directory.EnumerateFiles(Root, ".pending-*.snap", SearchOption.TopDirectoryOnly))
|
|
380
|
+
{
|
|
381
|
+
if (++observed > MaximumLegacyOrphansPerPass) { allClean = false; break; }
|
|
382
|
+
lock (PendingLock) if (ActivePendingSlots.Contains(Path.GetFullPath(path))) continue;
|
|
383
|
+
try { DeleteStrict(path, "E_PROFILER_SNAPSHOT_PENDING_CLEANUP_FAILED", "Failed to clean a snapshot orphan."); }
|
|
384
|
+
catch { allClean = false; }
|
|
385
|
+
}
|
|
386
|
+
return allClean && CompleteCleanupSchedule();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
private static bool CompleteCleanupSchedule()
|
|
390
|
+
{
|
|
391
|
+
lock (PendingLock)
|
|
392
|
+
{
|
|
393
|
+
if (PendingCleanup.Count != 0) return false;
|
|
394
|
+
Interlocked.Exchange(ref cleanupScheduled, 0);
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
private static string SafeName(string value)
|
|
400
|
+
{
|
|
401
|
+
var source = string.IsNullOrWhiteSpace(value) ? Guid.NewGuid().ToString("N") : value;
|
|
402
|
+
var result = new StringBuilder(Math.Min(96, source.Length));
|
|
403
|
+
for (var index = 0; index < source.Length && result.Length < 96; index++)
|
|
404
|
+
{
|
|
405
|
+
var character = source[index];
|
|
406
|
+
if (char.IsLetterOrDigit(character) || character == '-' || character == '_') result.Append(character);
|
|
407
|
+
}
|
|
408
|
+
return result.Length == 0 ? "capture" : result.ToString();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
internal static UnityCliBridge.BridgeCommandException Error(string code, string message, string nextAction)
|
|
412
|
+
{
|
|
413
|
+
return new UnityCliBridge.BridgeCommandException(code, message, nextAction);
|
|
414
|
+
}
|
|
28
415
|
}
|
|
29
416
|
}
|
|
30
417
|
#endif
|
|
@@ -27,8 +27,15 @@ namespace UnityCli
|
|
|
27
27
|
/// 跨程序集按全名解析类型。profiler 域各工具反射 UnityEditorInternal/UnityEditor 内部类型时复用。
|
|
28
28
|
/// </summary>
|
|
29
29
|
public static Type FindType(string fullName)
|
|
30
|
+
{
|
|
31
|
+
return FindType(fullName, null);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// <summary>请求路径在首次type/assembly lookup前消费budget;程序集快照有1024项硬上限。</summary>
|
|
35
|
+
public static Type FindType(string fullName, UnityCliRequestBudget budget)
|
|
30
36
|
{
|
|
31
37
|
if (string.IsNullOrEmpty(fullName)) return null;
|
|
38
|
+
if (budget != null && !budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
32
39
|
try
|
|
33
40
|
{
|
|
34
41
|
var direct = Type.GetType(fullName, false);
|
|
@@ -38,8 +45,12 @@ namespace UnityCli
|
|
|
38
45
|
|
|
39
46
|
var separator = fullName.IndexOf(',');
|
|
40
47
|
var typeName = separator < 0 ? fullName : fullName.Substring(0, separator).Trim();
|
|
41
|
-
|
|
48
|
+
var assemblies = budget == null ? AppDomain.CurrentDomain.GetAssemblies() : UnityCliAssemblySnapshot.Get(budget);
|
|
49
|
+
if (assemblies.Length > 1024)
|
|
50
|
+
throw new UnityCliBridge.BridgeCommandException("E_REFLECTION_LIMIT_EXCEEDED", "Loaded assembly count exceeds the hard reflection bound.");
|
|
51
|
+
foreach (var assembly in assemblies)
|
|
42
52
|
{
|
|
53
|
+
if (budget != null && !budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
43
54
|
Type type = null;
|
|
44
55
|
try { type = assembly.GetType(typeName, false); } catch { }
|
|
45
56
|
if (type != null) return type;
|
|
@@ -290,11 +301,14 @@ namespace UnityCli
|
|
|
290
301
|
return format;
|
|
291
302
|
}
|
|
292
303
|
|
|
304
|
+
internal static Func<UnityCliRequestBudget, Type> MemoryProfilerTypeOverrideForTests;
|
|
305
|
+
|
|
293
306
|
/// <summary>查找 MemoryProfiler 类型(包 com.unity.memoryprofiler)。找不到返回 null。</summary>
|
|
294
|
-
public static Type MemoryProfilerType()
|
|
307
|
+
public static Type MemoryProfilerType(UnityCliRequestBudget budget = null)
|
|
295
308
|
{
|
|
296
|
-
return
|
|
297
|
-
|
|
309
|
+
if (MemoryProfilerTypeOverrideForTests != null) return MemoryProfilerTypeOverrideForTests(budget);
|
|
310
|
+
return FindType("Unity.Profiling.Memory.MemoryProfiler", budget)
|
|
311
|
+
?? FindType("UnityEngine.Profiling.Memory.Experimental.MemoryProfiler", budget);
|
|
298
312
|
}
|
|
299
313
|
|
|
300
314
|
/// <summary>
|
|
@@ -54,7 +54,7 @@ namespace UnityCli
|
|
|
54
54
|
TimeSpan.FromMilliseconds(Math.Max(1, ctx.TimeoutMs)), ct: ct);
|
|
55
55
|
var enabled = FrameDebuggerReflection.GetEnabled();
|
|
56
56
|
if (!stable || !enabled) throw new UnityCliBridge.BridgeCommandException("E_FRAME_DEBUGGER_STATE_MISMATCH", "Frame Debugger enable write did not produce an enabled readback.", "Check Frame Debugger availability and retry.");
|
|
57
|
-
var eventCount = FrameDebuggerReflection.GetEventCount();
|
|
57
|
+
var eventCount = FrameDebuggerReflection.GetEventCount(ctx.UseReadBudget());
|
|
58
58
|
return new Result
|
|
59
59
|
{
|
|
60
60
|
Enabled = enabled,
|