@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
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Globalization;
|
|
4
|
+
using System.Security.Cryptography;
|
|
5
|
+
using System.Text;
|
|
6
|
+
using System.Threading;
|
|
7
|
+
|
|
8
|
+
namespace UnityCli
|
|
9
|
+
{
|
|
10
|
+
/// <summary>为数值协议字段声明公开最小值与最大值,并由 schema 与执行前校验共同强制。</summary>
|
|
11
|
+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
|
12
|
+
public sealed class UnityCliRangeAttribute : Attribute
|
|
13
|
+
{
|
|
14
|
+
public UnityCliRangeAttribute(long minimum, long maximum) { Minimum = minimum; Maximum = maximum; }
|
|
15
|
+
public long Minimum { get; private set; }
|
|
16
|
+
public long Maximum { get; private set; }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// <summary>为集合协议字段声明公开元素数量范围,并由 schema 与执行前校验共同强制。</summary>
|
|
20
|
+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
|
21
|
+
public sealed class UnityCliItemsRangeAttribute : Attribute
|
|
22
|
+
{
|
|
23
|
+
public UnityCliItemsRangeAttribute(int minimum, int maximum) { Minimum = minimum; Maximum = maximum; }
|
|
24
|
+
public int Minimum { get; private set; }
|
|
25
|
+
public int Maximum { get; private set; }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// <summary>公开读取预算输入;调用方可以收紧预算,但不能超过产品冻结上限。</summary>
|
|
29
|
+
public sealed class UnityCliReadBudgetInput
|
|
30
|
+
{
|
|
31
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxScannedRecords)] public long? MaxScannedRecords { get; set; }
|
|
32
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxNodes)] public long? MaxNodes { get; set; }
|
|
33
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxGetters)] public long? MaxGetters { get; set; }
|
|
34
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxReflectionCalls)] public long? MaxReflectionCalls { get; set; }
|
|
35
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxMainThreadMilliseconds)] public long? MaxMainThreadMilliseconds { get; set; }
|
|
36
|
+
[UnityCliRange(1L, UnityCliRequestBudget.AbsoluteMaxSerializedUtf8Bytes)] public long? MaxSerializedUtf8Bytes { get; set; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// <summary>请求预算实际消耗;估算输出与最终 envelope 的实际 UTF-8 字节分别报告。</summary>
|
|
40
|
+
public sealed class UnityCliRequestBudgetUsage
|
|
41
|
+
{
|
|
42
|
+
private readonly UnityCliRequestBudget liveBudget;
|
|
43
|
+
private long scannedRecords;
|
|
44
|
+
private long nodes;
|
|
45
|
+
private long getters;
|
|
46
|
+
private long reflectionCalls;
|
|
47
|
+
private long mainThreadMilliseconds;
|
|
48
|
+
private long estimatedSerializedUtf8Bytes;
|
|
49
|
+
private long actualSerializedUtf8Bytes;
|
|
50
|
+
private string exhaustedDimension;
|
|
51
|
+
|
|
52
|
+
public UnityCliRequestBudgetUsage() { }
|
|
53
|
+
|
|
54
|
+
internal UnityCliRequestBudgetUsage(UnityCliRequestBudget liveBudget)
|
|
55
|
+
{
|
|
56
|
+
this.liveBudget = liveBudget;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public long ScannedRecords { get { return liveBudget == null ? scannedRecords : liveBudget.ScannedRecords; } set { scannedRecords = value; } }
|
|
60
|
+
public long Nodes { get { return liveBudget == null ? nodes : liveBudget.Nodes; } set { nodes = value; } }
|
|
61
|
+
public long Getters { get { return liveBudget == null ? getters : liveBudget.Getters; } set { getters = value; } }
|
|
62
|
+
public long ReflectionCalls { get { return liveBudget == null ? reflectionCalls : liveBudget.ReflectionCalls; } set { reflectionCalls = value; } }
|
|
63
|
+
public long MainThreadMilliseconds { get { return liveBudget == null ? mainThreadMilliseconds : liveBudget.MainThreadMilliseconds; } set { mainThreadMilliseconds = value; } }
|
|
64
|
+
public long EstimatedSerializedUtf8Bytes { get { return liveBudget == null ? estimatedSerializedUtf8Bytes : liveBudget.EstimatedSerializedUtf8Bytes; } set { estimatedSerializedUtf8Bytes = value; } }
|
|
65
|
+
public long ActualSerializedUtf8Bytes { get { return liveBudget == null ? actualSerializedUtf8Bytes : liveBudget.ActualSerializedUtf8Bytes; } set { actualSerializedUtf8Bytes = value; } }
|
|
66
|
+
public string ExhaustedDimension { get { return liveBudget == null ? exhaustedDimension : liveBudget.ExhaustedDimension; } set { exhaustedDimension = value; } }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// <summary>可注入的单调时钟,生产使用 Stopwatch,测试使用手工时钟。</summary>
|
|
70
|
+
public interface IUnityCliMonotonicClock
|
|
71
|
+
{
|
|
72
|
+
long ElapsedMilliseconds { get; }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public sealed class UnityCliStopwatchClock : IUnityCliMonotonicClock
|
|
76
|
+
{
|
|
77
|
+
private readonly System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
78
|
+
public long ElapsedMilliseconds { get { return stopwatch.ElapsedMilliseconds; } }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// <summary>遍历预算耗尽;上层将其归约为稳定 E_REQUEST_BUDGET_EXCEEDED。</summary>
|
|
82
|
+
public sealed class UnityCliRequestBudgetExceededException : Exception
|
|
83
|
+
{
|
|
84
|
+
public UnityCliRequestBudgetExceededException(string dimension)
|
|
85
|
+
: base("Request-wide Unity main-thread budget exhausted: " + dimension + ".")
|
|
86
|
+
{
|
|
87
|
+
Dimension = dimension;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public string Dimension { get; private set; }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// <summary>
|
|
94
|
+
/// 一次 Tool 请求共用的预算账本。每次原始读取前先消费对应维度;elapsed 使用单调时钟,
|
|
95
|
+
/// cancellation 与所有维度共享同一终止点,禁止子路径或递归重新创建预算。
|
|
96
|
+
/// </summary>
|
|
97
|
+
public sealed class UnityCliRequestBudget
|
|
98
|
+
{
|
|
99
|
+
public const long DefaultMaxScannedRecords = 10000L;
|
|
100
|
+
public const long AbsoluteMaxScannedRecords = 100000L;
|
|
101
|
+
public const long DefaultMaxNodes = 4096L;
|
|
102
|
+
public const long AbsoluteMaxNodes = 20000L;
|
|
103
|
+
public const long DefaultMaxGetters = 2048L;
|
|
104
|
+
public const long AbsoluteMaxGetters = 10000L;
|
|
105
|
+
public const long DefaultMaxReflectionCalls = 4096L;
|
|
106
|
+
public const long AbsoluteMaxReflectionCalls = 20000L;
|
|
107
|
+
public const long DefaultMaxMainThreadMilliseconds = 250L;
|
|
108
|
+
public const long AbsoluteMaxMainThreadMilliseconds = 2000L;
|
|
109
|
+
public const long DefaultMaxSerializedUtf8Bytes = 1024L * 1024L;
|
|
110
|
+
public const long AbsoluteMaxSerializedUtf8Bytes = 8L * 1024L * 1024L;
|
|
111
|
+
|
|
112
|
+
private readonly IUnityCliMonotonicClock clock;
|
|
113
|
+
private readonly CancellationToken cancellationToken;
|
|
114
|
+
private readonly long maxScannedRecords;
|
|
115
|
+
private readonly long maxNodes;
|
|
116
|
+
private readonly long maxGetters;
|
|
117
|
+
private readonly long maxReflectionCalls;
|
|
118
|
+
private readonly long maxMainThreadMilliseconds;
|
|
119
|
+
private readonly long maxSerializedUtf8Bytes;
|
|
120
|
+
private long scannedRecords;
|
|
121
|
+
private long nodes;
|
|
122
|
+
private long getters;
|
|
123
|
+
private long reflectionCalls;
|
|
124
|
+
private long serializedUtf8Bytes;
|
|
125
|
+
private long mainThreadMilliseconds;
|
|
126
|
+
private long lastClockMilliseconds;
|
|
127
|
+
private string exhaustedDimension;
|
|
128
|
+
|
|
129
|
+
public UnityCliRequestBudget(UnityCliReadBudgetInput input, long executionTimeoutMilliseconds, CancellationToken cancellationToken, IUnityCliMonotonicClock clock = null)
|
|
130
|
+
{
|
|
131
|
+
input = input ?? new UnityCliReadBudgetInput();
|
|
132
|
+
maxScannedRecords = Limit(input.MaxScannedRecords, DefaultMaxScannedRecords, AbsoluteMaxScannedRecords, "maxScannedRecords");
|
|
133
|
+
maxNodes = Limit(input.MaxNodes, DefaultMaxNodes, AbsoluteMaxNodes, "maxNodes");
|
|
134
|
+
maxGetters = Limit(input.MaxGetters, DefaultMaxGetters, AbsoluteMaxGetters, "maxGetters");
|
|
135
|
+
maxReflectionCalls = Limit(input.MaxReflectionCalls, DefaultMaxReflectionCalls, AbsoluteMaxReflectionCalls, "maxReflectionCalls");
|
|
136
|
+
var requestedElapsed = Limit(input.MaxMainThreadMilliseconds, DefaultMaxMainThreadMilliseconds, AbsoluteMaxMainThreadMilliseconds, "maxMainThreadMilliseconds");
|
|
137
|
+
maxMainThreadMilliseconds = executionTimeoutMilliseconds > 0L ? Math.Min(requestedElapsed, executionTimeoutMilliseconds) : requestedElapsed;
|
|
138
|
+
maxSerializedUtf8Bytes = Limit(input.MaxSerializedUtf8Bytes, DefaultMaxSerializedUtf8Bytes, AbsoluteMaxSerializedUtf8Bytes, "maxSerializedUtf8Bytes");
|
|
139
|
+
this.cancellationToken = cancellationToken;
|
|
140
|
+
this.clock = clock ?? new UnityCliStopwatchClock();
|
|
141
|
+
lastClockMilliseconds = this.clock.ElapsedMilliseconds;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private long actualSerializedUtf8Bytes;
|
|
145
|
+
|
|
146
|
+
public long MaxSerializedUtf8Bytes { get { return maxSerializedUtf8Bytes; } }
|
|
147
|
+
public long RemainingScannedRecords { get { return Math.Max(0L, maxScannedRecords - scannedRecords); } }
|
|
148
|
+
public long RemainingNodes { get { return Math.Max(0L, maxNodes - nodes); } }
|
|
149
|
+
public long RemainingGetters { get { return Math.Max(0L, maxGetters - getters); } }
|
|
150
|
+
public long RemainingReflectionCalls { get { return Math.Max(0L, maxReflectionCalls - reflectionCalls); } }
|
|
151
|
+
public bool IsExhausted { get { return exhaustedDimension != null; } }
|
|
152
|
+
public string ExhaustedDimension { get { return exhaustedDimension; } }
|
|
153
|
+
internal long ScannedRecords { get { return scannedRecords; } }
|
|
154
|
+
internal long Nodes { get { return nodes; } }
|
|
155
|
+
internal long Getters { get { return getters; } }
|
|
156
|
+
internal long ReflectionCalls { get { return reflectionCalls; } }
|
|
157
|
+
internal long MainThreadMilliseconds { get { return Math.Max(0L, mainThreadMilliseconds); } }
|
|
158
|
+
internal long EstimatedSerializedUtf8Bytes { get { return serializedUtf8Bytes; } }
|
|
159
|
+
internal long ActualSerializedUtf8Bytes { get { return actualSerializedUtf8Bytes; } }
|
|
160
|
+
|
|
161
|
+
public bool TryConsumeScannedRecord() { return TryConsume(ref scannedRecords, maxScannedRecords, "scannedRecords"); }
|
|
162
|
+
public bool TryConsumeNode() { return TryConsume(ref nodes, maxNodes, "nodes"); }
|
|
163
|
+
public bool TryConsumeGetter() { return TryConsume(ref getters, maxGetters, "getters"); }
|
|
164
|
+
public bool TryConsumeReflectionCall() { return TryConsume(ref reflectionCalls, maxReflectionCalls, "reflectionCalls"); }
|
|
165
|
+
|
|
166
|
+
/// <summary>在批量 API 调用前一次性保留可验证 cardinality,避免先物化后超限。</summary>
|
|
167
|
+
public bool TryConsumeScannedRecords(long count) { return TryConsumeMany(ref scannedRecords, maxScannedRecords, count, "scannedRecords"); }
|
|
168
|
+
public bool TryConsumeNodes(long count) { return TryConsumeMany(ref nodes, maxNodes, count, "nodes"); }
|
|
169
|
+
public bool TryConsumeGetters(long count) { return TryConsumeMany(ref getters, maxGetters, count, "getters"); }
|
|
170
|
+
public bool TryConsumeReflectionCalls(long count) { return TryConsumeMany(ref reflectionCalls, maxReflectionCalls, count, "reflectionCalls"); }
|
|
171
|
+
|
|
172
|
+
/// <summary>在原始读取前检查取消与单调 elapsed;false 表示调用方必须返回 continuation。</summary>
|
|
173
|
+
public bool TryCheckpoint()
|
|
174
|
+
{
|
|
175
|
+
cancellationToken.ThrowIfCancellationRequested();
|
|
176
|
+
var now = clock.ElapsedMilliseconds;
|
|
177
|
+
if (now > lastClockMilliseconds) mainThreadMilliseconds += now - lastClockMilliseconds;
|
|
178
|
+
lastClockMilliseconds = now;
|
|
179
|
+
if (mainThreadMilliseconds < maxMainThreadMilliseconds) return exhaustedDimension == null;
|
|
180
|
+
Exhaust("mainThreadMilliseconds");
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// <summary>异步框架 wait 返回后重置采样基线;等待时间不属于 Unity 主线程工作。</summary>
|
|
185
|
+
public void ResumeAfterWait()
|
|
186
|
+
{
|
|
187
|
+
cancellationToken.ThrowIfCancellationRequested();
|
|
188
|
+
lastClockMilliseconds = clock.ElapsedMilliseconds;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public void CheckpointOrThrow()
|
|
192
|
+
{
|
|
193
|
+
if (!TryCheckpoint()) throw new UnityCliRequestBudgetExceededException(exhaustedDimension);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// <summary>构造动态输出时预留确定的 UTF-8 文本字节;最终 JSON 仍由框架做精确检查。</summary>
|
|
197
|
+
public bool TryReserveSerializedUtf8(string value)
|
|
198
|
+
{
|
|
199
|
+
return TryReserveSerializedUtf8Bytes(value == null ? 4L : Encoding.UTF8.GetByteCount(value));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/// <summary>为 JSON 结构或已知编码结果预留确定字节,避免先分配完整字符串。</summary>
|
|
203
|
+
public bool TryReserveSerializedUtf8Bytes(long bytes)
|
|
204
|
+
{
|
|
205
|
+
cancellationToken.ThrowIfCancellationRequested();
|
|
206
|
+
if (!TryCheckpoint()) return false;
|
|
207
|
+
if (bytes < 0L || bytes > maxSerializedUtf8Bytes - serializedUtf8Bytes)
|
|
208
|
+
{
|
|
209
|
+
Exhaust("serializedUtf8Bytes");
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
serializedUtf8Bytes += bytes;
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// <summary>序列化器增量检查最终 JSON 的实际 UTF-8 长度,不覆盖 Tool 侧估算。</summary>
|
|
217
|
+
public void ValidateSerializedUtf8Bytes(long bytes)
|
|
218
|
+
{
|
|
219
|
+
cancellationToken.ThrowIfCancellationRequested();
|
|
220
|
+
if (bytes < 0L || bytes > maxSerializedUtf8Bytes)
|
|
221
|
+
{
|
|
222
|
+
Exhaust("serializedUtf8Bytes");
|
|
223
|
+
throw new UnityCliRequestBudgetExceededException("serializedUtf8Bytes");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// <summary>记录最终成功 envelope 的实际 UTF-8 长度;调用方负责在返回前使自描述长度收敛。</summary>
|
|
228
|
+
internal void ObserveActualSerializedUtf8Bytes(long bytes)
|
|
229
|
+
{
|
|
230
|
+
ValidateSerializedUtf8Bytes(bytes);
|
|
231
|
+
actualSerializedUtf8Bytes = bytes;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public UnityCliRequestBudgetUsage Usage()
|
|
235
|
+
{
|
|
236
|
+
return new UnityCliRequestBudgetUsage(this);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private bool TryConsume(ref long current, long maximum, string dimension)
|
|
240
|
+
{
|
|
241
|
+
return TryConsumeMany(ref current, maximum, 1L, dimension);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private bool TryConsumeMany(ref long current, long maximum, long count, string dimension)
|
|
245
|
+
{
|
|
246
|
+
cancellationToken.ThrowIfCancellationRequested();
|
|
247
|
+
if (!TryCheckpoint()) return false;
|
|
248
|
+
if (count < 0L || count > maximum - current)
|
|
249
|
+
{
|
|
250
|
+
Exhaust(dimension);
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
current += count;
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private void Exhaust(string dimension)
|
|
258
|
+
{
|
|
259
|
+
if (exhaustedDimension == null) exhaustedDimension = dimension;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private static long Limit(long? requested, long fallback, long maximum, string field)
|
|
263
|
+
{
|
|
264
|
+
var value = requested ?? fallback;
|
|
265
|
+
if (value < 1L || value > maximum)
|
|
266
|
+
throw new ArgumentOutOfRangeException(field, value, field + " must be between 1 and " + maximum.ToString(CultureInfo.InvariantCulture) + ".");
|
|
267
|
+
return value;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// <summary>输入按 newest-first 排序,返回同时满足 count/bytes 的稳定保留索引。</summary>
|
|
272
|
+
public static class UnityCliRetentionPlanner
|
|
273
|
+
{
|
|
274
|
+
public static HashSet<int> RetainedIndices(IReadOnlyList<long> sizes, int maximumCount, long maximumBytes)
|
|
275
|
+
{
|
|
276
|
+
if (sizes == null) throw new ArgumentNullException("sizes");
|
|
277
|
+
if (maximumCount < 1) throw new ArgumentOutOfRangeException("maximumCount");
|
|
278
|
+
if (maximumBytes < 1L) throw new ArgumentOutOfRangeException("maximumBytes");
|
|
279
|
+
var result = new HashSet<int>();
|
|
280
|
+
long bytes = 0L;
|
|
281
|
+
for (var index = 0; index < sizes.Count && result.Count < maximumCount; index++)
|
|
282
|
+
{
|
|
283
|
+
var size = sizes[index];
|
|
284
|
+
if (size < 0L) throw new ArgumentOutOfRangeException("sizes");
|
|
285
|
+
if (size > maximumBytes - bytes) break;
|
|
286
|
+
bytes += size;
|
|
287
|
+
result.Add(index);
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/// <summary>稳定 continuation 的无状态编码;generation/scope 不匹配时调用方必须拒绝。</summary>
|
|
294
|
+
public static class UnityCliContinuationToken
|
|
295
|
+
{
|
|
296
|
+
public static string Create(string scope, string generation, string position)
|
|
297
|
+
{
|
|
298
|
+
return "ucli1." + Encode(scope) + "." + Encode(generation) + "." + Encode(position ?? string.Empty);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public static bool TryParse(string token, string expectedScope, string expectedGeneration, out string position)
|
|
302
|
+
{
|
|
303
|
+
position = null;
|
|
304
|
+
if (string.IsNullOrEmpty(token) || token.Length > 4096) return false;
|
|
305
|
+
var parts = token.Split('.');
|
|
306
|
+
if (parts.Length != 4 || parts[0] != "ucli1") return false;
|
|
307
|
+
string scope;
|
|
308
|
+
string generation;
|
|
309
|
+
try
|
|
310
|
+
{
|
|
311
|
+
scope = Decode(parts[1]);
|
|
312
|
+
generation = Decode(parts[2]);
|
|
313
|
+
position = Decode(parts[3]);
|
|
314
|
+
}
|
|
315
|
+
catch
|
|
316
|
+
{
|
|
317
|
+
position = null;
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
return string.Equals(scope, expectedScope, StringComparison.Ordinal)
|
|
321
|
+
&& string.Equals(generation, expectedGeneration, StringComparison.Ordinal);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
public static string Fingerprint(string value)
|
|
325
|
+
{
|
|
326
|
+
using (var sha = SHA256.Create())
|
|
327
|
+
{
|
|
328
|
+
var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(value ?? string.Empty));
|
|
329
|
+
var builder = new StringBuilder(bytes.Length * 2);
|
|
330
|
+
foreach (var item in bytes) builder.Append(item.ToString("x2", CultureInfo.InvariantCulture));
|
|
331
|
+
return builder.ToString();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private static string Encode(string value)
|
|
336
|
+
{
|
|
337
|
+
return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? string.Empty)).TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private static string Decode(string value)
|
|
341
|
+
{
|
|
342
|
+
var padded = value.Replace('-', '+').Replace('_', '/');
|
|
343
|
+
switch (padded.Length % 4)
|
|
344
|
+
{
|
|
345
|
+
case 2: padded += "=="; break;
|
|
346
|
+
case 3: padded += "="; break;
|
|
347
|
+
case 1: throw new FormatException("Invalid base64url continuation component.");
|
|
348
|
+
}
|
|
349
|
+
return Encoding.UTF8.GetString(Convert.FromBase64String(padded));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
|
|
5
|
+
namespace UnityCli
|
|
6
|
+
{
|
|
7
|
+
/// <summary>Runtime request cache的纯事务reservation;只在enqueue成功后提交淘汰。</summary>
|
|
8
|
+
public sealed class UnityCliRuntimeRequestPublication<T>
|
|
9
|
+
{
|
|
10
|
+
public sealed class Reservation
|
|
11
|
+
{
|
|
12
|
+
internal Reservation(string requestId, string requestDigest, string evictionRequestId, T evictionCandidate)
|
|
13
|
+
{
|
|
14
|
+
RequestId = requestId;
|
|
15
|
+
RequestDigest = requestDigest;
|
|
16
|
+
EvictionRequestId = evictionRequestId;
|
|
17
|
+
EvictionCandidate = evictionCandidate;
|
|
18
|
+
}
|
|
19
|
+
public string RequestId { get; private set; }
|
|
20
|
+
public string RequestDigest { get; private set; }
|
|
21
|
+
public string EvictionRequestId { get; private set; }
|
|
22
|
+
internal T EvictionCandidate { get; private set; }
|
|
23
|
+
public bool HasEviction { get { return EvictionRequestId != null; } }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private readonly int capacity;
|
|
27
|
+
private readonly Dictionary<string, T> entries = new Dictionary<string, T>(StringComparer.Ordinal);
|
|
28
|
+
private readonly Dictionary<string, string> digests = new Dictionary<string, string>(StringComparer.Ordinal);
|
|
29
|
+
|
|
30
|
+
public UnityCliRuntimeRequestPublication(int capacity)
|
|
31
|
+
{
|
|
32
|
+
if (capacity < 1) throw new ArgumentOutOfRangeException("capacity");
|
|
33
|
+
this.capacity = capacity;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public int Count { get { return entries.Count; } }
|
|
37
|
+
public IEnumerable<T> Values { get { return entries.Values.ToArray(); } }
|
|
38
|
+
|
|
39
|
+
public bool TryGet(string requestId, out T value)
|
|
40
|
+
{
|
|
41
|
+
return entries.TryGetValue(requestId, out value);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public bool IsIdentityMatch(string requestId, string requestDigest)
|
|
45
|
+
{
|
|
46
|
+
string digest;
|
|
47
|
+
return digests.TryGetValue(requestId, out digest) && string.Equals(digest, requestDigest, StringComparison.Ordinal);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// <summary>规划只读且可重复;无可淘汰terminal时不修改当前cache。</summary>
|
|
51
|
+
public Reservation Plan(string requestId, string requestDigest, Func<T, bool> isCompleted, Func<T, long> order)
|
|
52
|
+
{
|
|
53
|
+
if (string.IsNullOrWhiteSpace(requestId)) throw new ArgumentException("requestId is required.", "requestId");
|
|
54
|
+
if (string.IsNullOrWhiteSpace(requestDigest)) throw new ArgumentException("requestDigest is required.", "requestDigest");
|
|
55
|
+
if (isCompleted == null) throw new ArgumentNullException("isCompleted");
|
|
56
|
+
if (order == null) throw new ArgumentNullException("order");
|
|
57
|
+
T existing;
|
|
58
|
+
if (entries.TryGetValue(requestId, out existing))
|
|
59
|
+
{
|
|
60
|
+
if (!IsIdentityMatch(requestId, requestDigest)) throw new InvalidOperationException("Request identity does not match the existing cache entry.");
|
|
61
|
+
return new Reservation(requestId, requestDigest, null, existing);
|
|
62
|
+
}
|
|
63
|
+
if (entries.Count < capacity) return new Reservation(requestId, requestDigest, null, default(T));
|
|
64
|
+
var completed = entries.Where(pair => isCompleted(pair.Value)).OrderBy(pair => order(pair.Value)).ToArray();
|
|
65
|
+
return completed.Length == 0 ? null : new Reservation(requestId, requestDigest, completed[0].Key, completed[0].Value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// <summary>先加入新entry并提交enqueue;enqueue失败时旧entry保持不变,新entry回滚。</summary>
|
|
69
|
+
public bool Publish(Reservation reservation, T value, Func<T, bool> enqueue)
|
|
70
|
+
{
|
|
71
|
+
if (reservation == null) throw new ArgumentNullException("reservation");
|
|
72
|
+
if (enqueue == null) throw new ArgumentNullException("enqueue");
|
|
73
|
+
if (entries.ContainsKey(reservation.RequestId)) return IsIdentityMatch(reservation.RequestId, reservation.RequestDigest);
|
|
74
|
+
if (entries.Count >= capacity && !reservation.HasEviction) return false;
|
|
75
|
+
if (reservation.HasEviction)
|
|
76
|
+
{
|
|
77
|
+
T current;
|
|
78
|
+
if (!entries.TryGetValue(reservation.EvictionRequestId, out current) || !object.ReferenceEquals(current, reservation.EvictionCandidate)) return false;
|
|
79
|
+
}
|
|
80
|
+
entries.Add(reservation.RequestId, value);
|
|
81
|
+
digests.Add(reservation.RequestId, reservation.RequestDigest);
|
|
82
|
+
try
|
|
83
|
+
{
|
|
84
|
+
if (!enqueue(value))
|
|
85
|
+
{
|
|
86
|
+
entries.Remove(reservation.RequestId);
|
|
87
|
+
digests.Remove(reservation.RequestId);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (reservation.HasEviction)
|
|
91
|
+
{
|
|
92
|
+
entries.Remove(reservation.EvictionRequestId);
|
|
93
|
+
digests.Remove(reservation.EvictionRequestId);
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch
|
|
98
|
+
{
|
|
99
|
+
entries.Remove(reservation.RequestId);
|
|
100
|
+
digests.Remove(reservation.RequestId);
|
|
101
|
+
throw;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public void Clear() { entries.Clear(); digests.Clear(); }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "UnityCli.Editor.Tests",
|
|
3
3
|
"rootNamespace": "UnityCli.Tests",
|
|
4
|
-
"references": ["UnityCli.Shared"],
|
|
4
|
+
"references": ["UnityCli.Shared", "UnityCli.Editor", "UnityCli.Runtime"],
|
|
5
5
|
"includePlatforms": ["Editor"],
|
|
6
6
|
"excludePlatforms": [],
|
|
7
7
|
"allowUnsafeCode": false,
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"autoReferenced": false,
|
|
11
11
|
"defineConstraints": [],
|
|
12
12
|
"versionDefines": [],
|
|
13
|
-
"noEngineReferences":
|
|
13
|
+
"noEngineReferences": false,
|
|
14
14
|
"optionalUnityReferences": ["TestAssemblies"]
|
|
15
15
|
}
|