@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,410 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Collections.ObjectModel;
|
|
4
|
+
|
|
5
|
+
namespace UnityCli
|
|
6
|
+
{
|
|
7
|
+
/// <summary>Bridge主线程队列的纯分类、容量与启动选择策略。</summary>
|
|
8
|
+
public static class UnityCliBridgeQueuePolicy
|
|
9
|
+
{
|
|
10
|
+
public const int MaxBypassIdentities = 128;
|
|
11
|
+
public const int MaxFifoNodesExaminedPerTick = 128;
|
|
12
|
+
public const int MaxControlNodesExaminedPerTick = 128;
|
|
13
|
+
public const int MaxSafeStatusNodesExaminedPerTick = 4;
|
|
14
|
+
public const int MaxNodesExaminedPerTick = MaxFifoNodesExaminedPerTick
|
|
15
|
+
+ MaxControlNodesExaminedPerTick + MaxSafeStatusNodesExaminedPerTick;
|
|
16
|
+
public const int MaxStartsPerTick = 16;
|
|
17
|
+
public const int MaxSafeStatusStartsPerTick = 4;
|
|
18
|
+
|
|
19
|
+
public enum WorkClass
|
|
20
|
+
{
|
|
21
|
+
Mutation,
|
|
22
|
+
OrdinaryRead,
|
|
23
|
+
SafeStatus,
|
|
24
|
+
Control
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public enum DurableMutationBarrier
|
|
28
|
+
{
|
|
29
|
+
Clear,
|
|
30
|
+
Held,
|
|
31
|
+
Unreadable
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public enum ControlDisposition
|
|
35
|
+
{
|
|
36
|
+
Pending,
|
|
37
|
+
Authorized,
|
|
38
|
+
RejectParentUnavailable,
|
|
39
|
+
RejectIdentityMismatch,
|
|
40
|
+
ExpireDeadline
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public enum BypassAdmissionOutcome
|
|
44
|
+
{
|
|
45
|
+
Enqueue,
|
|
46
|
+
Attach,
|
|
47
|
+
RejectCapacity,
|
|
48
|
+
RejectIdentityMismatch
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public sealed class QueueNode
|
|
52
|
+
{
|
|
53
|
+
public QueueNode(string nodeId, string command, WorkClass workClass)
|
|
54
|
+
: this(nodeId, command, workClass, ControlDisposition.Pending) { }
|
|
55
|
+
|
|
56
|
+
private QueueNode(string nodeId, string command, WorkClass workClass, ControlDisposition controlDisposition)
|
|
57
|
+
{
|
|
58
|
+
ValidateNodeId(nodeId);
|
|
59
|
+
ValidateEnum(controlDisposition, "controlDisposition");
|
|
60
|
+
NodeId = nodeId;
|
|
61
|
+
Command = command;
|
|
62
|
+
Class = Classify(command, workClass);
|
|
63
|
+
if (Class != WorkClass.Control && controlDisposition != ControlDisposition.Pending)
|
|
64
|
+
throw new InvalidOperationException("Only a durable control node can receive a control disposition.");
|
|
65
|
+
ControlDecision = Class == WorkClass.Control ? controlDisposition : ControlDisposition.Pending;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public string NodeId { get; }
|
|
69
|
+
public string Command { get; }
|
|
70
|
+
public WorkClass Class { get; }
|
|
71
|
+
public ControlDisposition ControlDecision { get; }
|
|
72
|
+
public bool ControlAuthorized { get { return ControlDecision == ControlDisposition.Authorized; } }
|
|
73
|
+
|
|
74
|
+
public QueueNode WithControlAuthorization(bool authorized)
|
|
75
|
+
{
|
|
76
|
+
return WithControlDisposition(authorized ? ControlDisposition.Authorized : ControlDisposition.Pending);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public QueueNode WithControlDisposition(ControlDisposition disposition)
|
|
80
|
+
{
|
|
81
|
+
if (Class != WorkClass.Control && disposition != ControlDisposition.Pending)
|
|
82
|
+
throw new InvalidOperationException("Only a durable control node can receive a control disposition.");
|
|
83
|
+
return new QueueNode(NodeId, Command, Class, disposition);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public sealed class BypassIdentity
|
|
88
|
+
{
|
|
89
|
+
public BypassIdentity(string requestId, string requestDigest)
|
|
90
|
+
{
|
|
91
|
+
ValidateRequestId(requestId);
|
|
92
|
+
ValidateDigest(requestDigest);
|
|
93
|
+
RequestId = requestId;
|
|
94
|
+
RequestDigest = requestDigest;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public string RequestId { get; }
|
|
98
|
+
public string RequestDigest { get; }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public sealed class BypassAdmissionDecision
|
|
102
|
+
{
|
|
103
|
+
internal BypassAdmissionDecision(BypassAdmissionOutcome outcome, int existingIndex)
|
|
104
|
+
{
|
|
105
|
+
Outcome = outcome;
|
|
106
|
+
ExistingIndex = existingIndex;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public BypassAdmissionOutcome Outcome { get; }
|
|
110
|
+
public int ExistingIndex { get; }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public sealed class StartDecision
|
|
114
|
+
{
|
|
115
|
+
internal StartDecision(string nodeId, int queueIndex, WorkClass workClass)
|
|
116
|
+
{
|
|
117
|
+
NodeId = nodeId;
|
|
118
|
+
QueueIndex = queueIndex;
|
|
119
|
+
Class = workClass;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public string NodeId { get; }
|
|
123
|
+
public int QueueIndex { get; }
|
|
124
|
+
public WorkClass Class { get; }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public sealed class RejectDecision
|
|
128
|
+
{
|
|
129
|
+
internal RejectDecision(string nodeId, int queueIndex, ControlDisposition disposition)
|
|
130
|
+
{
|
|
131
|
+
NodeId = nodeId;
|
|
132
|
+
QueueIndex = queueIndex;
|
|
133
|
+
Disposition = disposition;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public string NodeId { get; }
|
|
137
|
+
public int QueueIndex { get; }
|
|
138
|
+
public ControlDisposition Disposition { get; }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public sealed class TickSelection
|
|
142
|
+
{
|
|
143
|
+
internal TickSelection(List<StartDecision> starts, List<RejectDecision> rejects, int nodesExamined)
|
|
144
|
+
{
|
|
145
|
+
Starts = new ReadOnlyCollection<StartDecision>(starts.ToArray());
|
|
146
|
+
Rejects = new ReadOnlyCollection<RejectDecision>(rejects.ToArray());
|
|
147
|
+
NodesExamined = nodesExamined;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public IReadOnlyList<StartDecision> Starts { get; }
|
|
151
|
+
public IReadOnlyList<RejectDecision> Rejects { get; }
|
|
152
|
+
public int NodesExamined { get; }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// <summary>只接受生产注册表裁决的闭集分类;SafeStatus命令不能被降级为普通读取。</summary>
|
|
156
|
+
public static WorkClass Classify(string command, WorkClass workClass)
|
|
157
|
+
{
|
|
158
|
+
ValidateCommand(command);
|
|
159
|
+
ValidateEnum(workClass, "workClass");
|
|
160
|
+
var safeStatus = IsSafeStatusCommand(command);
|
|
161
|
+
var durableControl = IsDurableControlCommand(command);
|
|
162
|
+
if (safeStatus && workClass != WorkClass.SafeStatus)
|
|
163
|
+
throw new ArgumentException("SafeStatus command must use SafeStatus classification.", "workClass");
|
|
164
|
+
if (!safeStatus && workClass == WorkClass.SafeStatus)
|
|
165
|
+
throw new ArgumentException("Only the exact SafeStatus allowlist may use SafeStatus classification.", "workClass");
|
|
166
|
+
if (durableControl && workClass != WorkClass.Control)
|
|
167
|
+
throw new ArgumentException("Durable control command must use Control classification.", "workClass");
|
|
168
|
+
if (!durableControl && workClass == WorkClass.Control)
|
|
169
|
+
throw new ArgumentException("Only the exact durable control allowlist may use Control classification.", "workClass");
|
|
170
|
+
return workClass;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/// <summary>精确白名单不接受后缀、大小写或project-tool间接名称。</summary>
|
|
174
|
+
public static bool IsSafeStatusCommand(string command)
|
|
175
|
+
{
|
|
176
|
+
switch (command)
|
|
177
|
+
{
|
|
178
|
+
case "internal.editor.compile.status":
|
|
179
|
+
case "internal.editor.refresh.status":
|
|
180
|
+
case "internal.editor.state.snapshot":
|
|
181
|
+
case "internal.asset.refresh.status":
|
|
182
|
+
case "internal.asset.refresh.public-status":
|
|
183
|
+
case "internal.build.player.public-status":
|
|
184
|
+
case "internal.editor.play-mode.public-status":
|
|
185
|
+
case "internal.package.install.public-status":
|
|
186
|
+
case "internal.package.remove.public-status":
|
|
187
|
+
case "internal.test.run.public-status":
|
|
188
|
+
case "internal.package.embed.status":
|
|
189
|
+
case "internal.package.resolve.status":
|
|
190
|
+
case "internal.test.run.status":
|
|
191
|
+
case "internal.test.run.cancel.status":
|
|
192
|
+
case "internal.navmesh.bake.status":
|
|
193
|
+
case "internal.occlusion.bake.status":
|
|
194
|
+
return true;
|
|
195
|
+
default:
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/// <summary>只有绑定当前durable parent的私有命令可进入受限control lane。</summary>
|
|
201
|
+
public static bool IsDurableControlCommand(string command)
|
|
202
|
+
{
|
|
203
|
+
switch (command)
|
|
204
|
+
{
|
|
205
|
+
case "internal.test.run.cancel.plan":
|
|
206
|
+
case "internal.test.run.cancel":
|
|
207
|
+
case "internal.package.files.claim":
|
|
208
|
+
case "internal.package.files.commit":
|
|
209
|
+
case "internal.package.files.prove":
|
|
210
|
+
case "internal.package.files.fail":
|
|
211
|
+
case "internal.navmesh.bake.cancel":
|
|
212
|
+
case "internal.occlusion.bake.cancel":
|
|
213
|
+
return true;
|
|
214
|
+
default:
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/// <summary>internal普通读取只允许不触发plan、cancel或writer控制的精确观察命令。</summary>
|
|
220
|
+
public static bool IsOrdinaryReadInternalCommand(string command)
|
|
221
|
+
{
|
|
222
|
+
return string.Equals(command, "internal.navmesh.bake.snapshot", StringComparison.Ordinal)
|
|
223
|
+
|| string.Equals(command, "internal.occlusion.bake.snapshot", StringComparison.Ordinal);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// <summary>同requestId同digest只attach;新identity达到固定上限时拒绝。</summary>
|
|
227
|
+
public static BypassAdmissionDecision DecideBypassAdmission(IReadOnlyList<BypassIdentity> activeAndQueued, BypassIdentity candidate)
|
|
228
|
+
{
|
|
229
|
+
if (activeAndQueued == null) throw new ArgumentNullException("activeAndQueued");
|
|
230
|
+
if (candidate == null) throw new ArgumentNullException("candidate");
|
|
231
|
+
if (activeAndQueued.Count > MaxBypassIdentities) throw new ArgumentException("Bypass identity snapshot exceeds its fixed bound.", "activeAndQueued");
|
|
232
|
+
|
|
233
|
+
var requestIds = new HashSet<string>(StringComparer.Ordinal);
|
|
234
|
+
var existingIndex = -1;
|
|
235
|
+
var exactMatch = false;
|
|
236
|
+
for (var index = 0; index < activeAndQueued.Count; index++)
|
|
237
|
+
{
|
|
238
|
+
var existing = activeAndQueued[index];
|
|
239
|
+
if (existing == null) throw new ArgumentException("Bypass identity snapshot contains null.", "activeAndQueued");
|
|
240
|
+
if (!requestIds.Add(existing.RequestId)) throw new ArgumentException("Bypass identity snapshot contains duplicate requestId.", "activeAndQueued");
|
|
241
|
+
if (!string.Equals(existing.RequestId, candidate.RequestId, StringComparison.Ordinal)) continue;
|
|
242
|
+
existingIndex = index;
|
|
243
|
+
exactMatch = string.Equals(existing.RequestDigest, candidate.RequestDigest, StringComparison.Ordinal);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (existingIndex >= 0)
|
|
247
|
+
return new BypassAdmissionDecision(exactMatch ? BypassAdmissionOutcome.Attach : BypassAdmissionOutcome.RejectIdentityMismatch, existingIndex);
|
|
248
|
+
return activeAndQueued.Count == MaxBypassIdentities
|
|
249
|
+
? new BypassAdmissionDecision(BypassAdmissionOutcome.RejectCapacity, -1)
|
|
250
|
+
: new BypassAdmissionDecision(BypassAdmissionOutcome.Enqueue, -1);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// <summary>lane遍历每访问一个唯一节点就完成一次policy检查,避免production再次扫描候选集合。</summary>
|
|
254
|
+
public sealed class TickSelectionAccumulator
|
|
255
|
+
{
|
|
256
|
+
private readonly int runningOrdinaryReads;
|
|
257
|
+
private readonly bool mutationRunning;
|
|
258
|
+
private readonly DurableMutationBarrier durableMutationBarrier;
|
|
259
|
+
private readonly List<QueueNode> examinedNodes = new List<QueueNode>(MaxNodesExaminedPerTick);
|
|
260
|
+
private readonly List<int> earlierOrdinaryReadIndices = new List<int>();
|
|
261
|
+
private readonly List<int> safeStatusIndices = new List<int>(MaxSafeStatusStartsPerTick);
|
|
262
|
+
private readonly List<RejectDecision> rejects = new List<RejectDecision>();
|
|
263
|
+
private readonly HashSet<string> nodeIds = new HashSet<string>(StringComparer.Ordinal);
|
|
264
|
+
private int firstMutationIndex = -1;
|
|
265
|
+
private int firstAuthorizedControlIndex = -1;
|
|
266
|
+
private bool completed;
|
|
267
|
+
|
|
268
|
+
internal TickSelectionAccumulator(int runningOrdinaryReads, bool mutationRunning, DurableMutationBarrier durableMutationBarrier)
|
|
269
|
+
{
|
|
270
|
+
if (runningOrdinaryReads < 0) throw new ArgumentOutOfRangeException("runningOrdinaryReads");
|
|
271
|
+
ValidateEnum(durableMutationBarrier, "durableMutationBarrier");
|
|
272
|
+
this.runningOrdinaryReads = runningOrdinaryReads;
|
|
273
|
+
this.mutationRunning = mutationRunning;
|
|
274
|
+
this.durableMutationBarrier = durableMutationBarrier;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private bool HasCapacity { get { return examinedNodes.Count < MaxNodesExaminedPerTick; } }
|
|
278
|
+
|
|
279
|
+
/// <summary>调用方已访问lane节点时同步记录唯一候选及其完整eligibility。</summary>
|
|
280
|
+
public void Examine(QueueNode node)
|
|
281
|
+
{
|
|
282
|
+
if (completed) throw new InvalidOperationException("Tick selection is already complete.");
|
|
283
|
+
if (!HasCapacity) throw new InvalidOperationException("Tick selection exceeded its fixed node bound.");
|
|
284
|
+
if (node == null) throw new ArgumentException("Examined queue prefix contains null.", "node");
|
|
285
|
+
if (!nodeIds.Add(node.NodeId)) throw new ArgumentException("Examined queue prefix contains duplicate nodeId.", "node");
|
|
286
|
+
var index = examinedNodes.Count;
|
|
287
|
+
examinedNodes.Add(node);
|
|
288
|
+
if (node.Class == WorkClass.Control && IsTerminalControlDisposition(node.ControlDecision))
|
|
289
|
+
{
|
|
290
|
+
rejects.Add(new RejectDecision(node.NodeId, index, node.ControlDecision));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (firstAuthorizedControlIndex < 0 && node.Class == WorkClass.Control && node.ControlAuthorized)
|
|
294
|
+
firstAuthorizedControlIndex = index;
|
|
295
|
+
if (firstMutationIndex < 0 && (node.Class == WorkClass.Mutation || node.Class == WorkClass.Control))
|
|
296
|
+
firstMutationIndex = index;
|
|
297
|
+
if (node.Class == WorkClass.SafeStatus && safeStatusIndices.Count < MaxSafeStatusStartsPerTick)
|
|
298
|
+
safeStatusIndices.Add(index);
|
|
299
|
+
if (firstMutationIndex < 0 && node.Class == WorkClass.OrdinaryRead)
|
|
300
|
+
earlierOrdinaryReadIndices.Add(index);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/// <summary>基于已检查节点完成本tick的唯一启动与拒绝裁决。</summary>
|
|
304
|
+
public TickSelection Complete()
|
|
305
|
+
{
|
|
306
|
+
if (completed) throw new InvalidOperationException("Tick selection is already complete.");
|
|
307
|
+
completed = true;
|
|
308
|
+
var selectedIndices = new List<int>(MaxStartsPerTick);
|
|
309
|
+
selectedIndices.AddRange(safeStatusIndices);
|
|
310
|
+
var remainingStarts = MaxStartsPerTick - selectedIndices.Count;
|
|
311
|
+
var regularBarrierClear = !mutationRunning && durableMutationBarrier == DurableMutationBarrier.Clear;
|
|
312
|
+
if (!mutationRunning && durableMutationBarrier == DurableMutationBarrier.Held
|
|
313
|
+
&& remainingStarts > 0 && firstAuthorizedControlIndex >= 0)
|
|
314
|
+
{
|
|
315
|
+
selectedIndices.Add(firstAuthorizedControlIndex);
|
|
316
|
+
remainingStarts -= 1;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (regularBarrierClear && remainingStarts > 0)
|
|
320
|
+
{
|
|
321
|
+
if (firstMutationIndex < 0 || earlierOrdinaryReadIndices.Count > 0)
|
|
322
|
+
{
|
|
323
|
+
foreach (var index in earlierOrdinaryReadIndices)
|
|
324
|
+
{
|
|
325
|
+
if (remainingStarts == 0) break;
|
|
326
|
+
selectedIndices.Add(index);
|
|
327
|
+
remainingStarts -= 1;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else if (runningOrdinaryReads == 0 && examinedNodes[firstMutationIndex].Class == WorkClass.Mutation)
|
|
331
|
+
{
|
|
332
|
+
selectedIndices.Add(firstMutationIndex);
|
|
333
|
+
remainingStarts -= 1;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
selectedIndices.Sort();
|
|
338
|
+
var starts = new List<StartDecision>(selectedIndices.Count);
|
|
339
|
+
foreach (var index in selectedIndices)
|
|
340
|
+
{
|
|
341
|
+
var node = examinedNodes[index];
|
|
342
|
+
starts.Add(new StartDecision(node.NodeId, index, node.Class));
|
|
343
|
+
}
|
|
344
|
+
return new TickSelection(starts, rejects, examinedNodes.Count);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/// <summary>创建与一次production lane遍历同生命周期的增量选择器。</summary>
|
|
349
|
+
public static TickSelectionAccumulator BeginSelection(
|
|
350
|
+
int runningOrdinaryReads,
|
|
351
|
+
bool mutationRunning,
|
|
352
|
+
DurableMutationBarrier durableMutationBarrier)
|
|
353
|
+
{
|
|
354
|
+
return new TickSelectionAccumulator(runningOrdinaryReads, mutationRunning, durableMutationBarrier);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// <summary>按队列顺序选择本tick唯一可移除并尝试启动的节点,不修改调用方集合。</summary>
|
|
358
|
+
public static TickSelection SelectStarts(
|
|
359
|
+
IReadOnlyList<QueueNode> queued,
|
|
360
|
+
int runningOrdinaryReads,
|
|
361
|
+
bool mutationRunning,
|
|
362
|
+
DurableMutationBarrier durableMutationBarrier)
|
|
363
|
+
{
|
|
364
|
+
if (queued == null) throw new ArgumentNullException("queued");
|
|
365
|
+
var accumulator = BeginSelection(runningOrdinaryReads, mutationRunning, durableMutationBarrier);
|
|
366
|
+
var examined = Math.Min(queued.Count, MaxNodesExaminedPerTick);
|
|
367
|
+
for (var index = 0; index < examined; index++) accumulator.Examine(queued[index]);
|
|
368
|
+
return accumulator.Complete();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private static bool IsTerminalControlDisposition(ControlDisposition disposition)
|
|
372
|
+
{
|
|
373
|
+
return disposition == ControlDisposition.RejectParentUnavailable
|
|
374
|
+
|| disposition == ControlDisposition.RejectIdentityMismatch
|
|
375
|
+
|| disposition == ControlDisposition.ExpireDeadline;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private static void ValidateCommand(string command)
|
|
379
|
+
{
|
|
380
|
+
if (string.IsNullOrWhiteSpace(command) || command.Length > 256 || !string.Equals(command, command.Trim(), StringComparison.Ordinal))
|
|
381
|
+
throw new ArgumentException("Bridge command must be a non-empty exact value of at most 256 characters.", "command");
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private static void ValidateNodeId(string nodeId)
|
|
385
|
+
{
|
|
386
|
+
if (string.IsNullOrWhiteSpace(nodeId) || nodeId.Length > 200)
|
|
387
|
+
throw new ArgumentException("Queue nodeId is required and must be at most 200 characters.", "nodeId");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private static void ValidateRequestId(string requestId)
|
|
391
|
+
{
|
|
392
|
+
if (string.IsNullOrWhiteSpace(requestId) || requestId.Length > 200)
|
|
393
|
+
throw new ArgumentException("Bypass requestId is required and must be at most 200 characters.", "requestId");
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private static void ValidateDigest(string digest)
|
|
397
|
+
{
|
|
398
|
+
if (string.IsNullOrEmpty(digest) || digest.Length != 64)
|
|
399
|
+
throw new ArgumentException("Bypass requestDigest must be a lowercase SHA-256 value.", "requestDigest");
|
|
400
|
+
foreach (var character in digest)
|
|
401
|
+
if (!((character >= '0' && character <= '9') || (character >= 'a' && character <= 'f')))
|
|
402
|
+
throw new ArgumentException("Bypass requestDigest must be a lowercase SHA-256 value.", "requestDigest");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private static void ValidateEnum<T>(T value, string parameterName) where T : struct
|
|
406
|
+
{
|
|
407
|
+
if (!Enum.IsDefined(typeof(T), value)) throw new ArgumentOutOfRangeException(parameterName);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace UnityCli
|
|
4
|
+
{
|
|
5
|
+
/// <summary>Bridge WorkItem准入、启动与HTTP取消的纯状态裁决。</summary>
|
|
6
|
+
public sealed class UnityCliBridgeWorkItemState
|
|
7
|
+
{
|
|
8
|
+
public enum StartOutcome { Started, Cancelled, ListenerChanged, DeadlineElapsed }
|
|
9
|
+
|
|
10
|
+
private bool cancelled;
|
|
11
|
+
private bool accepted;
|
|
12
|
+
private bool started;
|
|
13
|
+
|
|
14
|
+
public bool Started { get { return started; } }
|
|
15
|
+
public bool Accepted { get { return accepted; } }
|
|
16
|
+
|
|
17
|
+
public StartOutcome TryStart(bool listenerMatches, int remainingMs)
|
|
18
|
+
{
|
|
19
|
+
if (cancelled) return StartOutcome.Cancelled;
|
|
20
|
+
if (!listenerMatches) { cancelled = true; return StartOutcome.ListenerChanged; }
|
|
21
|
+
if (remainingMs <= 0) { cancelled = true; return StartOutcome.DeadlineElapsed; }
|
|
22
|
+
started = true;
|
|
23
|
+
return StartOutcome.Started;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public bool TryAccept()
|
|
27
|
+
{
|
|
28
|
+
if (cancelled || accepted) return false;
|
|
29
|
+
accepted = true;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public bool CancelBeforeAcceptance()
|
|
34
|
+
{
|
|
35
|
+
if (accepted) return false;
|
|
36
|
+
cancelled = true;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public bool CancelBeforeStart()
|
|
41
|
+
{
|
|
42
|
+
if (started) return false;
|
|
43
|
+
cancelled = true;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Runtime.CompilerServices;
|
|
4
|
+
using System.Text;
|
|
5
|
+
|
|
6
|
+
namespace UnityCli
|
|
7
|
+
{
|
|
8
|
+
/// <summary>将嵌套异常归一化为有界、可循环终止的公开 cause chain。</summary>
|
|
9
|
+
internal static class UnityCliExceptionProjection
|
|
10
|
+
{
|
|
11
|
+
internal const int MaxCauseDepth = 8;
|
|
12
|
+
internal const int MaxCauseTraversal = 256;
|
|
13
|
+
internal const int MaxCauseTextBytes = 64 * 1024;
|
|
14
|
+
private const int MaxTypeBytes = 512;
|
|
15
|
+
private const int MaxMessageBytes = 4096;
|
|
16
|
+
private const int MaxStackTraceBytes = 16384;
|
|
17
|
+
|
|
18
|
+
internal sealed class Result
|
|
19
|
+
{
|
|
20
|
+
internal string PublicMessage;
|
|
21
|
+
internal string DeepestExceptionType;
|
|
22
|
+
internal string DeepestMessage;
|
|
23
|
+
internal string DeepestStackTrace;
|
|
24
|
+
internal List<Dictionary<string, object>> Causes;
|
|
25
|
+
internal bool Truncated;
|
|
26
|
+
internal int CauseTextBytes;
|
|
27
|
+
internal int CauseTraversalCount;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
internal static Result Project(Exception exception)
|
|
31
|
+
{
|
|
32
|
+
return Project(exception, value => value == null ? null : value.InnerException);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// <summary>selector 仅供隔离测试构造循环;生产路径始终读取 Exception.InnerException。</summary>
|
|
36
|
+
internal static Result Project(Exception exception, Func<Exception, Exception> selector)
|
|
37
|
+
{
|
|
38
|
+
if (exception == null) throw new ArgumentNullException("exception");
|
|
39
|
+
if (selector == null) throw new ArgumentNullException("selector");
|
|
40
|
+
|
|
41
|
+
var retained = new List<CauseReference>(MaxCauseDepth);
|
|
42
|
+
var visited = new HashSet<Exception>(ReferenceComparer.Instance);
|
|
43
|
+
var truncated = false;
|
|
44
|
+
var current = exception;
|
|
45
|
+
Exception deepest = null;
|
|
46
|
+
var deepestDepth = -1;
|
|
47
|
+
var traversed = 0;
|
|
48
|
+
while (current != null && traversed < MaxCauseTraversal)
|
|
49
|
+
{
|
|
50
|
+
if (!visited.Add(current))
|
|
51
|
+
{
|
|
52
|
+
truncated = true;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (retained.Count < MaxCauseDepth - 1) retained.Add(new CauseReference(current, traversed));
|
|
56
|
+
deepest = current;
|
|
57
|
+
deepestDepth = traversed;
|
|
58
|
+
traversed++;
|
|
59
|
+
current = selector(current);
|
|
60
|
+
}
|
|
61
|
+
if (current != null || traversed > MaxCauseDepth) truncated = true;
|
|
62
|
+
if (deepestDepth >= MaxCauseDepth - 1) retained.Add(new CauseReference(deepest, deepestDepth));
|
|
63
|
+
|
|
64
|
+
var remaining = MaxCauseTextBytes;
|
|
65
|
+
var types = new string[retained.Count];
|
|
66
|
+
var messages = new string[retained.Count];
|
|
67
|
+
var stacks = new string[retained.Count];
|
|
68
|
+
|
|
69
|
+
// 只投影前七层与真实终端槽,并优先为终端 cause 分配 type/message bytes。
|
|
70
|
+
for (var index = retained.Count - 1; index >= 0; index--)
|
|
71
|
+
{
|
|
72
|
+
messages[index] = TakeUtf8(retained[index].Exception.Message, Math.Min(MaxMessageBytes, remaining), ref remaining, ref truncated);
|
|
73
|
+
types[index] = TakeUtf8(retained[index].Exception.GetType().FullName, Math.Min(MaxTypeBytes, remaining), ref remaining, ref truncated);
|
|
74
|
+
}
|
|
75
|
+
for (var index = retained.Count - 1; index >= 0; index--)
|
|
76
|
+
{
|
|
77
|
+
stacks[index] = TakeUtf8(retained[index].Exception.StackTrace, Math.Min(MaxStackTraceBytes, remaining), ref remaining, ref truncated);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var causes = new List<Dictionary<string, object>>(retained.Count);
|
|
81
|
+
for (var index = 0; index < retained.Count; index++)
|
|
82
|
+
{
|
|
83
|
+
causes.Add(new Dictionary<string, object>
|
|
84
|
+
{
|
|
85
|
+
{ "depth", (long)retained[index].Depth },
|
|
86
|
+
{ "exceptionType", types[index] },
|
|
87
|
+
{ "message", messages[index] },
|
|
88
|
+
{ "stackTrace", stacks[index] }
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
var deepestIndex = retained.Count - 1;
|
|
93
|
+
var deepestMessage = messages[deepestIndex];
|
|
94
|
+
if (string.IsNullOrWhiteSpace(deepestMessage)) deepestMessage = string.IsNullOrWhiteSpace(types[deepestIndex]) ? "Exception" : types[deepestIndex];
|
|
95
|
+
return new Result
|
|
96
|
+
{
|
|
97
|
+
PublicMessage = deepestMessage,
|
|
98
|
+
DeepestExceptionType = types[deepestIndex],
|
|
99
|
+
DeepestMessage = messages[deepestIndex],
|
|
100
|
+
DeepestStackTrace = stacks[deepestIndex],
|
|
101
|
+
Causes = causes,
|
|
102
|
+
Truncated = truncated,
|
|
103
|
+
CauseTextBytes = MaxCauseTextBytes - remaining,
|
|
104
|
+
CauseTraversalCount = traversed
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private sealed class CauseReference
|
|
109
|
+
{
|
|
110
|
+
internal CauseReference(Exception exception, int depth) { Exception = exception; Depth = depth; }
|
|
111
|
+
internal readonly Exception Exception;
|
|
112
|
+
internal readonly int Depth;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private static string TakeUtf8(string value, int allowedBytes, ref int remaining, ref bool truncated)
|
|
116
|
+
{
|
|
117
|
+
value = value ?? string.Empty;
|
|
118
|
+
if (allowedBytes <= 0)
|
|
119
|
+
{
|
|
120
|
+
if (value.Length > 0) truncated = true;
|
|
121
|
+
return string.Empty;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
var low = 0;
|
|
125
|
+
var high = Math.Min(value.Length, allowedBytes);
|
|
126
|
+
while (low < high)
|
|
127
|
+
{
|
|
128
|
+
var middle = low + (high - low + 1) / 2;
|
|
129
|
+
if (Encoding.UTF8.GetByteCount(value, 0, middle) <= allowedBytes) low = middle;
|
|
130
|
+
else high = middle - 1;
|
|
131
|
+
}
|
|
132
|
+
if (low > 0 && low < value.Length && char.IsHighSurrogate(value[low - 1]) && char.IsLowSurrogate(value[low])) low--;
|
|
133
|
+
if (low < value.Length) truncated = true;
|
|
134
|
+
if (low == value.Length)
|
|
135
|
+
{
|
|
136
|
+
remaining -= Encoding.UTF8.GetByteCount(value, 0, low);
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
var bounded = value.Substring(0, low);
|
|
140
|
+
remaining -= Encoding.UTF8.GetByteCount(bounded, 0, bounded.Length);
|
|
141
|
+
return bounded;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private sealed class ReferenceComparer : IEqualityComparer<Exception>
|
|
145
|
+
{
|
|
146
|
+
internal static readonly ReferenceComparer Instance = new ReferenceComparer();
|
|
147
|
+
public bool Equals(Exception left, Exception right) { return ReferenceEquals(left, right); }
|
|
148
|
+
public int GetHashCode(Exception value) { return RuntimeHelpers.GetHashCode(value); }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
|
|
3
|
+
namespace UnityCli
|
|
4
|
+
{
|
|
5
|
+
/// <summary>队列map与队列节点的原子publication骨架;任一阶段失败都回滚已发布部分。</summary>
|
|
6
|
+
public static class UnityCliQueuePublication
|
|
7
|
+
{
|
|
8
|
+
public static void Publish(Action addMap, Action addQueue, Action removeMap, Action removeQueue, Action markPublished)
|
|
9
|
+
{
|
|
10
|
+
if (addMap == null || addQueue == null || removeMap == null || removeQueue == null || markPublished == null)
|
|
11
|
+
throw new ArgumentNullException("publication action");
|
|
12
|
+
var mapAdded = false;
|
|
13
|
+
var queueAdded = false;
|
|
14
|
+
try
|
|
15
|
+
{
|
|
16
|
+
addMap();
|
|
17
|
+
mapAdded = true;
|
|
18
|
+
addQueue();
|
|
19
|
+
queueAdded = true;
|
|
20
|
+
markPublished();
|
|
21
|
+
}
|
|
22
|
+
catch
|
|
23
|
+
{
|
|
24
|
+
if (queueAdded) { try { removeQueue(); } catch { } }
|
|
25
|
+
if (mapAdded) { try { removeMap(); } catch { } }
|
|
26
|
+
throw;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|