@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.
Files changed (420) hide show
  1. package/README.md +5 -5
  2. package/contracts/command-contract.json +109 -217
  3. package/contracts/package-files.json +374 -294
  4. package/contracts/stable-session/direct-call-semantics.json +8 -2
  5. package/contracts/tool-completion-contract.json +148 -672
  6. package/dist/bridge/admission.d.ts +17 -1
  7. package/dist/bridge/admission.js +2 -0
  8. package/dist/bridge/admission.js.map +1 -1
  9. package/dist/bridge/domains/asset.js +3 -1
  10. package/dist/bridge/domains/asset.js.map +1 -1
  11. package/dist/bridge/domains/camera.js +39 -7
  12. package/dist/bridge/domains/camera.js.map +1 -1
  13. package/dist/bridge/domains/console.js +2 -1
  14. package/dist/bridge/domains/console.js.map +1 -1
  15. package/dist/bridge/domains/doctor.d.ts +3 -0
  16. package/dist/bridge/domains/doctor.js +8 -0
  17. package/dist/bridge/domains/doctor.js.map +1 -0
  18. package/dist/bridge/domains/editor.js +0 -4
  19. package/dist/bridge/domains/editor.js.map +1 -1
  20. package/dist/bridge/domains/game-object.js +4 -12
  21. package/dist/bridge/domains/game-object.js.map +1 -1
  22. package/dist/bridge/domains/graphics.js +1 -16
  23. package/dist/bridge/domains/graphics.js.map +1 -1
  24. package/dist/bridge/domains/object.js +3 -0
  25. package/dist/bridge/domains/object.js.map +1 -1
  26. package/dist/bridge/domains/physics.js +1 -2
  27. package/dist/bridge/domains/physics.js.map +1 -1
  28. package/dist/bridge/domains/profiler.js +18 -7
  29. package/dist/bridge/domains/profiler.js.map +1 -1
  30. package/dist/bridge/domains/project-tool.js +4 -0
  31. package/dist/bridge/domains/project-tool.js.map +1 -1
  32. package/dist/bridge/domains/reflection.js +10 -2
  33. package/dist/bridge/domains/reflection.js.map +1 -1
  34. package/dist/bridge/domains/runtime-tool.js +3 -0
  35. package/dist/bridge/domains/runtime-tool.js.map +1 -1
  36. package/dist/bridge/domains/scene.js +3 -8
  37. package/dist/bridge/domains/scene.js.map +1 -1
  38. package/dist/bridge/domains/screenshot.js +30 -6
  39. package/dist/bridge/domains/screenshot.js.map +1 -1
  40. package/dist/bridge/domains/ui.js +3 -1
  41. package/dist/bridge/domains/ui.js.map +1 -1
  42. package/dist/bridge/index.d.ts +5 -5
  43. package/dist/bridge/index.js +6 -9
  44. package/dist/bridge/index.js.map +1 -1
  45. package/dist/bridge/registry.js +3 -5
  46. package/dist/bridge/registry.js.map +1 -1
  47. package/dist/bridge/session-supervisor.d.ts +6 -3
  48. package/dist/bridge/session-supervisor.js +122 -34
  49. package/dist/bridge/session-supervisor.js.map +1 -1
  50. package/dist/bridge/types.d.ts +6 -5
  51. package/dist/bridge/types.js +16 -2
  52. package/dist/bridge/types.js.map +1 -1
  53. package/dist/catalog-protocol.d.ts +64 -0
  54. package/dist/catalog-protocol.js +460 -0
  55. package/dist/catalog-protocol.js.map +1 -0
  56. package/dist/cli-commands/command.js +84 -61
  57. package/dist/cli-commands/command.js.map +1 -1
  58. package/dist/cli-commands/extensions.js +70 -50
  59. package/dist/cli-commands/extensions.js.map +1 -1
  60. package/dist/cli-commands/instances.js +1 -1
  61. package/dist/cli-commands/instances.js.map +1 -1
  62. package/dist/cli-process-owners.d.ts +6 -0
  63. package/dist/cli-process-owners.js +27 -0
  64. package/dist/cli-process-owners.js.map +1 -0
  65. package/dist/cli.d.ts +1 -1
  66. package/dist/cli.js +20 -5
  67. package/dist/cli.js.map +1 -1
  68. package/dist/contracts/command-contract.js +14 -4
  69. package/dist/contracts/command-contract.js.map +1 -1
  70. package/dist/doctor.d.ts +4 -6
  71. package/dist/doctor.js +429 -398
  72. package/dist/doctor.js.map +1 -1
  73. package/dist/editor-blocker-observer.d.ts +2 -1
  74. package/dist/editor-blocker-observer.js +40 -13
  75. package/dist/editor-blocker-observer.js.map +1 -1
  76. package/dist/extension-availability.d.ts +27 -9
  77. package/dist/extension-availability.js +96 -56
  78. package/dist/extension-availability.js.map +1 -1
  79. package/dist/extensions/descriptor-loader.d.ts +2 -2
  80. package/dist/extensions/descriptor-loader.js +3 -4
  81. package/dist/extensions/descriptor-loader.js.map +1 -1
  82. package/dist/extensions/index.d.ts +1 -1
  83. package/dist/extensions/index.js +1 -1
  84. package/dist/extensions/index.js.map +1 -1
  85. package/dist/extensions/installer.d.ts +24 -7
  86. package/dist/extensions/installer.js +142 -66
  87. package/dist/extensions/installer.js.map +1 -1
  88. package/dist/extensions/registry.js +3 -5
  89. package/dist/extensions/registry.js.map +1 -1
  90. package/dist/extensions/state-contract.d.ts +11 -0
  91. package/dist/extensions/state-contract.js +50 -0
  92. package/dist/extensions/state-contract.js.map +1 -0
  93. package/dist/instances.d.ts +13 -1
  94. package/dist/instances.js +26 -0
  95. package/dist/instances.js.map +1 -1
  96. package/dist/package-manager.d.ts +0 -24
  97. package/dist/package-manager.js +5 -58
  98. package/dist/package-manager.js.map +1 -1
  99. package/dist/project-tool-discovery.d.ts +5 -2
  100. package/dist/project-tool-discovery.js +22 -18
  101. package/dist/project-tool-discovery.js.map +1 -1
  102. package/dist/runtime-code.js +1 -1
  103. package/dist/runtime-code.js.map +1 -1
  104. package/dist/tool-name.d.ts +4 -0
  105. package/dist/tool-name.js +15 -0
  106. package/dist/tool-name.js.map +1 -0
  107. package/dist/tools/.generated-completion-registry.d.ts +2 -0
  108. package/dist/tools/.generated-completion-registry.js +763 -325
  109. package/dist/tools/.generated-completion-registry.js.map +1 -1
  110. package/dist/tools/.generated-registry.d.ts +6 -11
  111. package/dist/tools/.generated-registry.js +6 -11
  112. package/dist/tools/.generated-registry.js.map +1 -1
  113. package/dist/tools/.generated-schemas.js +11 -16
  114. package/dist/tools/.generated-schemas.js.map +1 -1
  115. package/dist/tools/asset/refresh-status.d.ts +3 -0
  116. package/dist/tools/asset/refresh-status.js +12 -0
  117. package/dist/tools/asset/refresh-status.js.map +1 -0
  118. package/dist/tools/asset/refresh.js +7 -3
  119. package/dist/tools/asset/refresh.js.map +1 -1
  120. package/dist/tools/build/player-status.d.ts +3 -0
  121. package/dist/tools/build/player-status.js +12 -0
  122. package/dist/tools/build/player-status.js.map +1 -0
  123. package/dist/tools/build/run.js +1 -1
  124. package/dist/tools/build/run.js.map +1 -1
  125. package/dist/tools/catalog-control.d.ts +22 -0
  126. package/dist/tools/catalog-control.js +335 -0
  127. package/dist/tools/catalog-control.js.map +1 -0
  128. package/dist/tools/catalog.d.ts +7 -9
  129. package/dist/tools/catalog.js +66 -45
  130. package/dist/tools/catalog.js.map +1 -1
  131. package/dist/tools/commands.d.ts +1 -1
  132. package/dist/tools/commands.js +44 -11
  133. package/dist/tools/commands.js.map +1 -1
  134. package/dist/tools/define.js +3 -2
  135. package/dist/tools/define.js.map +1 -1
  136. package/dist/tools/dispatcher.d.ts +53 -6
  137. package/dist/tools/dispatcher.js +277 -108
  138. package/dist/tools/dispatcher.js.map +1 -1
  139. package/dist/tools/editor/compile.js +1 -1
  140. package/dist/tools/editor/compile.js.map +1 -1
  141. package/dist/tools/editor/play-mode-status.d.ts +3 -0
  142. package/dist/tools/editor/play-mode-status.js +12 -0
  143. package/dist/tools/editor/play-mode-status.js.map +1 -0
  144. package/dist/tools/editor/readiness.d.ts +0 -1
  145. package/dist/tools/editor/readiness.js +0 -1
  146. package/dist/tools/editor/readiness.js.map +1 -1
  147. package/dist/tools/editor/refresh.d.ts +7 -3
  148. package/dist/tools/editor/refresh.js +20 -15
  149. package/dist/tools/editor/refresh.js.map +1 -1
  150. package/dist/tools/editor/state.d.ts +2 -2
  151. package/dist/tools/editor/state.js +13 -12
  152. package/dist/tools/editor/state.js.map +1 -1
  153. package/dist/tools/metadata/derived.js +1 -7
  154. package/dist/tools/metadata/derived.js.map +1 -1
  155. package/dist/tools/metadata/status.js +1 -12
  156. package/dist/tools/metadata/status.js.map +1 -1
  157. package/dist/tools/metadata/types.d.ts +0 -2
  158. package/dist/tools/navmesh/live.js +1 -1
  159. package/dist/tools/navmesh/live.js.map +1 -1
  160. package/dist/tools/occlusion/live.js +1 -1
  161. package/dist/tools/occlusion/live.js.map +1 -1
  162. package/dist/tools/package/deploy.js +2 -2
  163. package/dist/tools/package/deploy.js.map +1 -1
  164. package/dist/tools/package/embed.js +1 -1
  165. package/dist/tools/package/embed.js.map +1 -1
  166. package/dist/tools/package/install-status.d.ts +3 -0
  167. package/dist/tools/package/install-status.js +12 -0
  168. package/dist/tools/package/install-status.js.map +1 -0
  169. package/dist/tools/package/install.js +3 -3
  170. package/dist/tools/package/install.js.map +1 -1
  171. package/dist/tools/package/live-resolve.js +45 -12
  172. package/dist/tools/package/live-resolve.js.map +1 -1
  173. package/dist/tools/package/registry-clear.js.map +1 -1
  174. package/dist/tools/package/registry-set.js.map +1 -1
  175. package/dist/tools/package/remove-status.d.ts +3 -0
  176. package/dist/tools/package/remove-status.js +12 -0
  177. package/dist/tools/package/remove-status.js.map +1 -0
  178. package/dist/tools/package/remove.js +3 -3
  179. package/dist/tools/package/remove.js.map +1 -1
  180. package/dist/tools/package/resolve.js +3 -3
  181. package/dist/tools/package/resolve.js.map +1 -1
  182. package/dist/tools/package/restore.js +2 -2
  183. package/dist/tools/package/restore.js.map +1 -1
  184. package/dist/tools/package/scoped-registry-add.js.map +1 -1
  185. package/dist/tools/status/support.d.ts +13 -0
  186. package/dist/tools/status/support.js +28 -0
  187. package/dist/tools/status/support.js.map +1 -0
  188. package/dist/tools/test/cancel.js +2 -2
  189. package/dist/tools/test/cancel.js.map +1 -1
  190. package/dist/tools/test/run-status.d.ts +3 -0
  191. package/dist/tools/test/run-status.js +12 -0
  192. package/dist/tools/test/run-status.js.map +1 -0
  193. package/dist/tools/test/run.js +7 -4
  194. package/dist/tools/test/run.js.map +1 -1
  195. package/dist/tools/tools/group-summaries.js +10 -14
  196. package/dist/tools/tools/group-summaries.js.map +1 -1
  197. package/docs/architecture.md +4 -4
  198. package/docs/availability-differences.md +4 -4
  199. package/docs/command-execution.md +4 -3
  200. package/docs/error-codes.md +13 -5
  201. package/docs/extensions.md +1 -7
  202. package/docs/risk-and-side-effects.md +4 -3
  203. package/docs/safety-boundaries.md +3 -1
  204. package/docs/target-and-instance.md +1 -1
  205. package/docs/tool-discovery.md +17 -10
  206. package/docs/tool-execution.md +18 -7
  207. package/extensions/cinemachine/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
  208. package/extensions/hdrp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
  209. package/extensions/probuilder/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
  210. package/extensions/urp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
  211. package/extensions/vfx-graph/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
  212. package/package.json +2 -4
  213. package/skills/unitycli/SKILL.md +11 -2
  214. package/skills/unitycli/manifest.json +1 -1
  215. package/skills/unitycli/references/operation-protocol.md +3 -3
  216. package/unitypkg/Editor/AssemblyInfo.cs +5 -0
  217. package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +49 -14
  218. package/unitypkg/Editor/Bridge/BridgeHttpServer.cs +9 -35
  219. package/unitypkg/Editor/Bridge/BridgeQueueState.cs +672 -0
  220. package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +970 -120
  221. package/unitypkg/Editor/BridgeStartupStateMachine.cs +59 -1
  222. package/unitypkg/Editor/Commands/ProjectToolCommands.cs +4 -0
  223. package/unitypkg/Editor/Commands/RuntimeToolCommands.cs +3 -0
  224. package/unitypkg/Editor/Generated/UnityCliToolCompletionRegistry.g.cs +379 -14
  225. package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +28 -13
  226. package/unitypkg/Editor/Infrastructure/RegistryOwnershipResolver.cs +132 -105
  227. package/unitypkg/Editor/Infrastructure/UnityCliActiveOperation.cs +138 -29
  228. package/unitypkg/Editor/Infrastructure/UnityCliAdmission.cs +1856 -237
  229. package/unitypkg/Editor/Infrastructure/UnityCliDoctorDiagnostics.cs +220 -0
  230. package/unitypkg/Editor/Infrastructure/UnityCliDurableStatusCoordinator.cs +118 -0
  231. package/unitypkg/Editor/Infrastructure/UnityCliEditorStateSnapshot.cs +2 -1
  232. package/unitypkg/Editor/Infrastructure/UnityCliHierarchyPager.cs +203 -0
  233. package/unitypkg/Editor/Infrastructure/UnityCliInstanceCleanup.cs +2 -1
  234. package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +201 -63
  235. package/unitypkg/Editor/Infrastructure/UnityCliJson.cs +2 -3
  236. package/unitypkg/Editor/Infrastructure/UnityCliLiveBuildCoordinator.cs +289 -46
  237. package/unitypkg/Editor/Infrastructure/UnityCliLiveRefreshCoordinator.cs +87 -53
  238. package/unitypkg/Editor/Infrastructure/UnityCliNavMeshBakeCoordinator.cs +4 -4
  239. package/unitypkg/Editor/Infrastructure/UnityCliObjectRef.cs +128 -25
  240. package/unitypkg/Editor/Infrastructure/UnityCliObjectSerializer.cs +435 -327
  241. package/unitypkg/Editor/Infrastructure/UnityCliOcclusionBakeCoordinator.cs +4 -4
  242. package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +351 -53
  243. package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveCoordinator.cs +118 -18
  244. package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveState.cs +20 -1
  245. package/unitypkg/Editor/Infrastructure/UnityCliReadGeneration.cs +97 -0
  246. package/unitypkg/Editor/Infrastructure/UnityCliReflection.cs +644 -133
  247. package/unitypkg/Editor/Infrastructure/UnityCliReloadOperation.cs +128 -41
  248. package/unitypkg/Editor/Infrastructure/UnityCliRuntimeExecutor.cs +14 -84
  249. package/unitypkg/Editor/Infrastructure/UnityCliSerializer.cs +220 -0
  250. package/unitypkg/Editor/Infrastructure/UnityCliSessionMutationLease.cs +69 -29
  251. package/unitypkg/Editor/Infrastructure/UnityCliTestRunCoordinator.cs +440 -54
  252. package/unitypkg/Editor/Infrastructure/UnityCliWaiter.cs +128 -35
  253. package/unitypkg/Editor/ProjectTools/IUnityCliTool.cs +9 -1
  254. package/unitypkg/Editor/ProjectTools/OfficialAttributeToolRegistry.cs +32 -31
  255. package/unitypkg/Editor/ProjectTools/ProjectToolRegistry.cs +607 -458
  256. package/unitypkg/Editor/ProjectTools/ProjectToolSchemaValidator.cs +35 -7
  257. package/unitypkg/Editor/ProjectTools/RegisteredTool.cs +501 -60
  258. package/unitypkg/Editor/ProjectTools/UnityCliProjectToolContext.cs +21 -0
  259. package/unitypkg/Editor/ProjectTools/UnityCliSchemaDeriver.cs +36 -7
  260. package/unitypkg/Editor/ProjectTools/UnityCliToolName.cs +30 -0
  261. package/unitypkg/Editor/Properties/AssemblyInfo.cs +3 -0
  262. package/unitypkg/Editor/Tools/asset/get-data.cs +16 -7
  263. package/unitypkg/Editor/Tools/build/BuildSceneStateTool.cs +23 -3
  264. package/unitypkg/Editor/Tools/build/BuildToolDtos.cs +2 -1
  265. package/unitypkg/Editor/Tools/build/scene/add.cs +6 -3
  266. package/unitypkg/Editor/Tools/build/scene/disable.cs +1 -1
  267. package/unitypkg/Editor/Tools/build/scene/enable.cs +1 -1
  268. package/unitypkg/Editor/Tools/build/scene/list.cs +1 -1
  269. package/unitypkg/Editor/Tools/build/scene/remove.cs +13 -3
  270. package/unitypkg/Editor/Tools/camera/CameraToolSupport.cs +38 -38
  271. package/unitypkg/Editor/Tools/camera/multiview.cs +13 -6
  272. package/unitypkg/Editor/Tools/camera/screenshot.cs +14 -7
  273. package/unitypkg/Editor/Tools/component/get.cs +16 -9
  274. package/unitypkg/Editor/Tools/component/modify.cs +6 -4
  275. package/unitypkg/Editor/Tools/console/clear.cs +7 -6
  276. package/unitypkg/Editor/Tools/console/get.cs +48 -16
  277. package/unitypkg/Editor/Tools/editor/EditorToolSupport.cs +143 -28
  278. package/unitypkg/Editor/Tools/editor/menu-items.cs +1 -1
  279. package/unitypkg/Editor/Tools/editor/play.cs +2 -11
  280. package/unitypkg/Editor/Tools/editor/selection.cs +1 -1
  281. package/unitypkg/Editor/Tools/editor/stop.cs +2 -11
  282. package/unitypkg/Editor/Tools/editor/windows.cs +1 -1
  283. package/unitypkg/Editor/Tools/go/GameObjectToolSupport.cs +54 -4
  284. package/unitypkg/Editor/Tools/go/delete.cs +1 -1
  285. package/unitypkg/Editor/Tools/go/find.cs +167 -70
  286. package/unitypkg/Editor/Tools/graphics/GraphicsToolSupport.cs +25 -0
  287. package/unitypkg/Editor/Tools/graphics/light-probe-group.cs +9 -3
  288. package/unitypkg/Editor/Tools/graphics/pipeline-info.cs +1 -1
  289. package/unitypkg/Editor/Tools/graphics/pipeline-settings.cs +1 -1
  290. package/unitypkg/Editor/Tools/graphics/quality.cs +2 -2
  291. package/unitypkg/Editor/Tools/graphics/reflection-probe.cs +3 -3
  292. package/unitypkg/Editor/Tools/graphics/stats.cs +1 -1
  293. package/unitypkg/Editor/Tools/object/ObjectToolSupport.cs +4 -4
  294. package/unitypkg/Editor/Tools/object/get-data.cs +9 -7
  295. package/unitypkg/Editor/Tools/object/modify.cs +7 -5
  296. package/unitypkg/Editor/Tools/physics/raycast.cs +24 -6
  297. package/unitypkg/Editor/Tools/prefab/stage.cs +1 -1
  298. package/unitypkg/Editor/Tools/profiler/ProfilerFrameDebuggerSupport.cs +94 -21
  299. package/unitypkg/Editor/Tools/profiler/ProfilerMemorySnapshotSupport.cs +397 -10
  300. package/unitypkg/Editor/Tools/profiler/ProfilerToolSupport.cs +18 -4
  301. package/unitypkg/Editor/Tools/profiler/frame-debugger/enable.cs +1 -1
  302. package/unitypkg/Editor/Tools/profiler/frame-debugger/events.cs +88 -87
  303. package/unitypkg/Editor/Tools/profiler/hierarchy.cs +278 -112
  304. package/unitypkg/Editor/Tools/profiler/memory-snapshot/compare.cs +9 -5
  305. package/unitypkg/Editor/Tools/profiler/memory-snapshot/list.cs +37 -35
  306. package/unitypkg/Editor/Tools/profiler/memory-snapshot/take.cs +99 -97
  307. package/unitypkg/Editor/Tools/project/info.cs +1 -1
  308. package/unitypkg/Editor/Tools/project/layers.cs +1 -1
  309. package/unitypkg/Editor/Tools/project/tags.cs +1 -1
  310. package/unitypkg/Editor/Tools/reflection/method/call.cs +9 -7
  311. package/unitypkg/Editor/Tools/reflection/method/find.cs +27 -37
  312. package/unitypkg/Editor/Tools/reflection/type/schema.cs +24 -28
  313. package/unitypkg/Editor/Tools/scene/gameobject/component.cs +8 -5
  314. package/unitypkg/Editor/Tools/scene/gameobject/components.cs +10 -7
  315. package/unitypkg/Editor/Tools/scene/gameobject-support.cs +104 -8
  316. package/unitypkg/Editor/Tools/scene/gameobject.cs +37 -16
  317. package/unitypkg/Editor/Tools/scene/hierarchy.cs +146 -142
  318. package/unitypkg/Editor/Tools/screenshot/EditorElementCaptureToolSupport.cs +77 -25
  319. package/unitypkg/Editor/Tools/screenshot/ScreenshotToolSupport.cs +315 -95
  320. package/unitypkg/Editor/Tools/screenshot/editor-element.cs +7 -5
  321. package/unitypkg/Editor/Tools/screenshot/game-view.cs +35 -21
  322. package/unitypkg/Editor/Tools/screenshot/isolated-object.cs +29 -23
  323. package/unitypkg/Editor/Tools/screenshot/orbit.cs +37 -25
  324. package/unitypkg/Editor/Tools/screenshot/scene-view.cs +25 -18
  325. package/unitypkg/Editor/Tools/screenshot/screen.cs +177 -17
  326. package/unitypkg/Editor/Tools/screenshot/surround.cs +83 -79
  327. package/unitypkg/Editor/Tools/ui/render-preview.cs +16 -11
  328. package/unitypkg/Editor/UnityCliBridge.cs +97 -34
  329. package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeBridge.cs +753 -122
  330. package/unitypkg/Runtime/Properties/AssemblyInfo.cs +5 -0
  331. package/unitypkg/Runtime/UnityCli.Runtime.asmdef +1 -1
  332. package/unitypkg/Shared/AssemblyInfo.cs +4 -0
  333. package/unitypkg/Shared/UnityCliAdmissionPool.cs +265 -75
  334. package/unitypkg/Shared/UnityCliBridgeQueuePolicy.cs +410 -0
  335. package/unitypkg/Shared/UnityCliBridgeWorkItemState.cs +47 -0
  336. package/unitypkg/Shared/UnityCliExceptionProjection.cs +151 -0
  337. package/unitypkg/Shared/UnityCliQueuePublication.cs +30 -0
  338. package/unitypkg/Shared/UnityCliRequestBudget.cs +352 -0
  339. package/unitypkg/Shared/UnityCliRuntimeRequestPublication.cs +107 -0
  340. package/unitypkg/Tests/Editor/UnityCli.Editor.Tests.asmdef +2 -2
  341. package/unitypkg/Tests/Editor/UnityCliAdmissionCoordinatorIntegrationTests.cs +1329 -0
  342. package/unitypkg/Tests/Editor/UnityCliAdmissionPoolTests.cs +311 -114
  343. package/unitypkg/Tests/Editor/UnityCliAdmissionRepairStateTests.cs +94 -0
  344. package/unitypkg/Tests/Editor/UnityCliBridgeAdmissionIntegrationTests.cs +1229 -0
  345. package/unitypkg/Tests/Editor/UnityCliBridgeQueuePolicyTests.cs +412 -0
  346. package/unitypkg/Tests/Editor/UnityCliContinuationIntegrationTests.cs +292 -0
  347. package/unitypkg/Tests/Editor/UnityCliDiagnosticBoundaryTests.cs +120 -0
  348. package/unitypkg/Tests/Editor/UnityCliDurableStatusTests.cs +84 -0
  349. package/unitypkg/Tests/Editor/UnityCliExceptionProjectionTests.cs +72 -0
  350. package/unitypkg/Tests/Editor/UnityCliInstancePublicationRetryTests.cs +180 -97
  351. package/unitypkg/Tests/Editor/UnityCliMemoryReflectionIntegrationTests.cs +434 -0
  352. package/unitypkg/Tests/Editor/UnityCliRequestBudgetTests.cs +615 -0
  353. package/unitypkg/Tests/Editor/UnityCliRuntimeBridgeIntegrationTests.cs +520 -0
  354. package/unitypkg/Tests/Editor/UnityCliToolCatalogTests.cs +562 -0
  355. package/unitypkg/Tests/Runtime/UnityCli.Runtime.Tests.asmdef +23 -0
  356. package/unitypkg/Tests/Runtime/UnityCliRuntimeCatalogValidationTests.cs +29 -0
  357. package/unitypkg/package.json +1 -1
  358. package/contracts/static-capability-catalog.json +0 -48226
  359. package/dist/bridge/domains/diagnose.d.ts +0 -2
  360. package/dist/bridge/domains/diagnose.js +0 -11
  361. package/dist/bridge/domains/diagnose.js.map +0 -1
  362. package/dist/bridge/domains/extension.d.ts +0 -8
  363. package/dist/bridge/domains/extension.js +0 -20
  364. package/dist/bridge/domains/extension.js.map +0 -1
  365. package/dist/capabilities.d.ts +0 -5
  366. package/dist/capabilities.js +0 -84
  367. package/dist/capabilities.js.map +0 -1
  368. package/dist/static-capability-catalog.d.ts +0 -13
  369. package/dist/static-capability-catalog.js +0 -41
  370. package/dist/static-capability-catalog.js.map +0 -1
  371. package/dist/tools/diagnose/capabilities.d.ts +0 -13
  372. package/dist/tools/diagnose/capabilities.js +0 -34
  373. package/dist/tools/diagnose/capabilities.js.map +0 -1
  374. package/dist/tools/package/info.d.ts +0 -19
  375. package/dist/tools/package/info.js +0 -27
  376. package/dist/tools/package/info.js.map +0 -1
  377. package/dist/tools/package/list.d.ts +0 -27
  378. package/dist/tools/package/list.js +0 -21
  379. package/dist/tools/package/list.js.map +0 -1
  380. package/dist/tools/package/registry-get.d.ts +0 -10
  381. package/dist/tools/package/registry-get.js +0 -22
  382. package/dist/tools/package/registry-get.js.map +0 -1
  383. package/dist/tools/package/scoped-registry-list.d.ts +0 -14
  384. package/dist/tools/package/scoped-registry-list.js +0 -22
  385. package/dist/tools/package/scoped-registry-list.js.map +0 -1
  386. package/dist/tools/package/search.d.ts +0 -17
  387. package/dist/tools/package/search.js +0 -39
  388. package/dist/tools/package/search.js.map +0 -1
  389. package/dist/tools/package/status.d.ts +0 -21
  390. package/dist/tools/package/status.js +0 -37
  391. package/dist/tools/package/status.js.map +0 -1
  392. package/dist/tools/tools/describe.d.ts +0 -27
  393. package/dist/tools/tools/describe.js +0 -35
  394. package/dist/tools/tools/describe.js.map +0 -1
  395. package/dist/tools/tools/group-list.d.ts +0 -16
  396. package/dist/tools/tools/group-list.js +0 -38
  397. package/dist/tools/tools/group-list.js.map +0 -1
  398. package/dist/tools/tools/group.d.ts +0 -13
  399. package/dist/tools/tools/group.js +0 -34
  400. package/dist/tools/tools/group.js.map +0 -1
  401. package/dist/tools/tools/pagination.d.ts +0 -17
  402. package/dist/tools/tools/pagination.js +0 -28
  403. package/dist/tools/tools/pagination.js.map +0 -1
  404. package/dist/tools/tools/search.d.ts +0 -15
  405. package/dist/tools/tools/search.js +0 -42
  406. package/dist/tools/tools/search.js.map +0 -1
  407. package/unitypkg/Editor/Tools/diagnose/preflight.cs +0 -269
  408. package/unitypkg/Editor/Tools/editor/console.cs +0 -26
  409. package/unitypkg/Editor/Tools/extension/status.cs +0 -87
  410. package/unitypkg/Editor/Tools/go/inspect.cs +0 -49
  411. package/unitypkg/Editor/Tools/graphics/pipeline-quality.cs +0 -24
  412. package/unitypkg/Editor/Tools/graphics/probe-positions.cs +0 -58
  413. package/unitypkg/Editor/Tools/graphics/settings.cs +0 -104
  414. package/unitypkg/Editor/Tools/graphics/stats-counters.cs +0 -28
  415. package/unitypkg/Editor/Tools/graphics/stats-memory.cs +0 -21
  416. package/unitypkg/Editor/Tools/instances/list.cs +0 -71
  417. package/unitypkg/Editor/Tools/physics/raycast-all.cs +0 -67
  418. package/unitypkg/Editor/Tools/scene/build-settings.cs +0 -69
  419. package/unitypkg/Editor/Tools/scene/data.cs +0 -125
  420. package/unitypkg/Editor/Tools/tests/list.cs +0 -98
@@ -18,17 +18,18 @@ namespace UnityCli
18
18
  public string AssetPath { get; set; }
19
19
  public string Guid { get; set; }
20
20
  public int? ComponentInstanceId { get; set; }
21
- public int? ComponentIndex { get; set; }
21
+ [UnityCliRange(0L, int.MaxValue)] public int? ComponentIndex { get; set; }
22
22
  public string Component { get; set; }
23
23
  public string ComponentType { get; set; }
24
- public int? MaxDepth { get; set; }
25
- public int? MaxArrayItems { get; set; }
24
+ [UnityCliRange(0L, 16L)] public int? MaxDepth { get; set; }
25
+ [UnityCliRange(1L, 1000L)] public int? MaxArrayItems { get; set; }
26
26
  public bool? IncludeFields { get; set; }
27
27
  public bool? IncludeProperties { get; set; }
28
28
  public bool? DeepSerialization { get; set; }
29
- public List<string> Paths { get; set; }
29
+ [UnityCliItemsRange(0, 128)] public List<string> Paths { get; set; }
30
30
  [UnityCliAnyJson] public object ViewQuery { get; set; }
31
31
  public string NamePattern { get; set; }
32
+ public UnityCliReadBudgetInput Budget { get; set; }
32
33
  }
33
34
 
34
35
  public sealed class Result
@@ -42,7 +43,7 @@ namespace UnityCli
42
43
  {
43
44
  Name = "component.get",
44
45
  Summary = "Deep-read one Component by GameObject and component selector; use paths/viewQuery for token-safe fields.",
45
- Description = "Deep-read one Component after selecting a GameObject with go.find/go.inspect or tools run scene.gameobject.components. For token safety, pass exact paths or one viewQuery; they are mutually exclusive and skip full fields/props expansion. Use componentIndex/componentInstanceId when duplicate components exist. Keep maxDepth low before expanding MonoBehaviours.",
46
+ Description = "Deep-read one Component after selecting a GameObject with go.find, scene.hierarchy, scene.gameobject, or scene.gameobject.components. For token safety, pass exact paths or one viewQuery; they are mutually exclusive and skip full fields/props expansion. Use componentIndex/componentInstanceId when duplicate components exist. maxDepth is 0..16, maxArrayItems is 1..1000, and paths accepts at most 128 ordered exact reads. All reads share budget scan/node/getter/reflection/time/UTF-8 ceilings; truncated nodes return nextPath. Defaults are 10000 scans, 4096 nodes, 2048 getters, 4096 reflection calls, 250 main-thread ms, and 1 MiB; maxima are 100000/20000/10000/20000/2000 ms/8 MiB. Read-only in Edit and Play Mode.",
46
47
  Group = "component",
47
48
  DestructiveHint = false,
48
49
  Target = "editor",
@@ -58,13 +59,19 @@ namespace UnityCli
58
59
 
59
60
  public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request request, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
60
61
  {
61
- var component = UnityCliBridge.ObjectRefResolver.ResolveComponent(request);
62
+ var budget = ctx.UseReadBudget(request.Budget);
63
+ var component = UnityCliBridge.ObjectRefResolver.ResolveComponent(request, budget);
62
64
  var options = GameObjectToolSupport.BuildSerializerOptions(request);
63
- var data = UnityCliBridge.ObjectSerializer.Serialize(component, options);
65
+ var data = UnityCliBridge.ObjectSerializer.Serialize(component, options, budget);
66
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
67
+ var typeName = component.GetType().FullName;
68
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
69
+ var gameObject = component.gameObject;
70
+ var gameObjectRef = GameObjectToolSupport.BuildGameObjectRef(gameObject, budget);
64
71
  return new System.Threading.Tasks.ValueTask<Result>(new Result
65
72
  {
66
- TypeName = component.GetType().FullName,
67
- GameObject = GameObjectToolSupport.BuildGameObjectRef(component.gameObject),
73
+ TypeName = typeName,
74
+ GameObject = gameObjectRef,
68
75
  Data = data
69
76
  });
70
77
  }
@@ -21,11 +21,12 @@ namespace UnityCli
21
21
  public string AssetPath { get; set; }
22
22
  public string Guid { get; set; }
23
23
  public int? ComponentInstanceId { get; set; }
24
- public int? ComponentIndex { get; set; }
24
+ [UnityCliRange(0L, int.MaxValue)] public int? ComponentIndex { get; set; }
25
25
  public string Component { get; set; }
26
26
  public string ComponentType { get; set; }
27
- public int? MaxDepth { get; set; }
27
+ [UnityCliRange(0L, 16L)] public int? MaxDepth { get; set; }
28
28
  [UnityCliAnyJson] public List<object> PathPatches { get; set; }
29
+ public UnityCliReadBudgetInput Budget { get; set; }
29
30
  }
30
31
 
31
32
  public sealed class Result
@@ -59,7 +60,8 @@ namespace UnityCli
59
60
  public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request request, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
60
61
  {
61
62
  GameObjectToolSupport.EnsureEditorNotBusy("component.modify");
62
- var component = UnityCliBridge.ObjectRefResolver.ResolveComponent(request);
63
+ var readBudget = ctx.UseReadBudget(request.Budget);
64
+ var component = UnityCliBridge.ObjectRefResolver.ResolveComponent(request, readBudget);
63
65
  if (request.PathPatches == null || request.PathPatches.Count == 0)
64
66
  throw new UnityCliBridge.BridgeCommandException("E_COMPONENT_PATCH_REQUIRED", "component.modify requires non-empty pathPatches.", "Pass direct replace pathPatches for writable serialized properties.");
65
67
  UnityCliBridge.ObjectPatch.ValidateOnly(component, request.PathPatches, null);
@@ -90,7 +92,7 @@ namespace UnityCli
90
92
  observedSerializedObject.Update();
91
93
  UnityCliBridge.ObjectPatch.VerifyFreshSerializedProperties(observedComponent, request.PathPatches);
92
94
  var maxDepth = request.MaxDepth ?? 2;
93
- var updatedData = UnityCliBridge.ObjectSerializer.Serialize(observedComponent, new UnityCliBridge.ObjectSerializer.Options { MaxDepth = maxDepth, IncludeFields = true, IncludeProperties = true, DeepSerialization = false });
95
+ var updatedData = UnityCliBridge.ObjectSerializer.Serialize(observedComponent, new UnityCliBridge.ObjectSerializer.Options { MaxDepth = maxDepth, IncludeFields = true, IncludeProperties = true, DeepSerialization = false }, readBudget);
94
96
  return new System.Threading.Tasks.ValueTask<Result>(new Result
95
97
  {
96
98
  TypeName = component.GetType().FullName,
@@ -13,8 +13,8 @@ namespace UnityCli
13
13
  public class ConsoleClearTool : IUnityCliTool<ConsoleClearTool.Request, ConsoleClearTool.Result>
14
14
  {
15
15
  public sealed class Request { }
16
- public sealed class Result { public bool DryRun { get; set; } public bool Cleared { get; set; } public List<EditorPlannedEffect> PlannedEffects { get; set; } }
17
- public ToolDescriptor Describe() => new() { Name = "console.clear", Summary = "Clear the Unity Console log.", Description = "Clear all Console entries via LogEntries.Clear(). dryRun=true previews without clearing.", Group = "console",DestructiveHint = false, SupportsDryRun = true, SideEffects = new[] { "editor-console-state" }, Target = "editor", PlayModeSupport = "supported", DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000, Examples = new[] { new ToolExample { Description = "Clear console", Input = new Request { } } } };
16
+ public sealed class Result { public bool DryRun { get; set; } public bool Cleared { get; set; } public long PreviousCount { get; set; } public long RemainingCount { get; set; } public List<EditorPlannedEffect> PlannedEffects { get; set; } }
17
+ public ToolDescriptor Describe() => new() { Name = "console.clear", Summary = "Clear every Unity Console entry and return count readback.", Description = "Clear all Console entries in Edit or Play mode. dryRun previews without clearing. A real call reads the count before the effect, invokes LogEntries.Clear once, and succeeds only after fresh GetCount readback reaches zero.", Group = "console",DestructiveHint = false, SupportsDryRun = true, SideEffects = new[] { "editor-console-state" }, Target = "editor", PlayModeSupport = "supported", DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000, Examples = new[] { new ToolExample { Description = "Preview clearing the Console", Input = new Request { }, Execution = new ToolExampleExecution { DryRun = true } } } };
18
18
  public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request r, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
19
19
  {
20
20
  var dryRun = ctx.DryRun;
@@ -26,12 +26,13 @@ namespace UnityCli
26
26
  var getCountMethod = logEntriesType.GetMethod("GetCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
27
27
  if (clearMethod == null || getCountMethod == null)
28
28
  throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_CLEAR_UNSUPPORTED", "UnityEditor.LogEntries.Clear or GetCount is unavailable.", "Use a Unity Editor version that exposes Console log entry controls.");
29
+ var previousCount = Convert.ToInt32(getCountMethod.Invoke(null, null));
29
30
  ctx.CommitEffect();
30
31
  clearMethod.Invoke(null, null);
31
- var count = Convert.ToInt32(getCountMethod.Invoke(null, null));
32
- if (count != 0)
33
- throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_CLEAR_STATE_MISMATCH", "Unity Console still contains " + count + " entries after clearing.", "Inspect the Unity Console and retry.");
34
- return new System.Threading.Tasks.ValueTask<Result>(new Result { DryRun = false, Cleared = true, PlannedEffects = new List<EditorPlannedEffect> { new EditorPlannedEffect { Type = "console.clear" } } });
32
+ var remainingCount = Convert.ToInt32(getCountMethod.Invoke(null, null));
33
+ if (remainingCount != 0)
34
+ throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_CLEAR_STATE_MISMATCH", "Unity Console still contains " + remainingCount + " entries after clearing.", "Inspect the Unity Console and retry.");
35
+ return new System.Threading.Tasks.ValueTask<Result>(new Result { DryRun = false, Cleared = true, PreviousCount = previousCount, RemainingCount = remainingCount, PlannedEffects = new List<EditorPlannedEffect> { new EditorPlannedEffect { Type = "console.clear" } } });
35
36
  }
36
37
  }
37
38
  }
@@ -1,27 +1,59 @@
1
1
  #if UNITY_EDITOR
2
- using System;
3
2
  using System.Collections.Generic;
4
- using System.Linq;
5
- using System.Reflection;
6
- using UnityEditor;
7
- using UnityEditor.Compilation;
8
- using UnityEngine;
9
3
 
10
4
  namespace UnityCli
11
5
  {
12
- /// <summary>console.get — 读取 Console 日志(支持过滤和分页)。</summary>
6
+ /// <summary>console.get — 按稳定 raw Console 位置执行有界过滤与续页。</summary>
13
7
  public class ConsoleGetTool : IUnityCliTool<ConsoleGetTool.Request, ConsoleGetTool.Result>
14
8
  {
15
- public sealed class Request { public string Type { get; set; } public string Filter { get; set; } public int? Count { get; set; } public int? Cursor { get; set; } }
16
- public sealed class Result { public List<ConsoleEntry> Items { get; set; } public PageInfo PageInfo { get; set; } }
17
- public ToolDescriptor Describe() => new() { Name = "console.get", Summary = "Read Unity Console entries with type filter, text search, and cursor paging.", Description = "Read Console entries newest-first. type filters by error/warning/log. filter does case-insensitive text search. cursor for pagination.", Group = "console",DestructiveHint = false, Target = "editor", PlayModeSupport = "supported", DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000, Examples = new[] { new ToolExample { Description = "Read errors", Input = new Request { Type = "error", Count = 10 } } } };
18
- public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request r, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
9
+ public sealed class Request
19
10
  {
20
- var count = Math.Max(1, Math.Min(r.Count ?? 50, 500));
21
- var cursor = Math.Max(0, r.Cursor ?? 0);
22
- var items = EditorToolSupport.ReadConsoleEntries(r.Type, r.Filter, count + cursor);
23
- var paged = items.Skip(cursor).Take(count).ToList();
24
- return new System.Threading.Tasks.ValueTask<Result>(new Result { Items = paged, PageInfo = new PageInfo { PageSize = count, Cursor = cursor, Total = items.Count, NextCursor = cursor + paged.Count < items.Count ? (long?)(cursor + paged.Count) : null } });
11
+ [UnityCliStringEnum("all", "error", "warning", "assert", "log")]
12
+ public string Type { get; set; }
13
+ public string Filter { get; set; }
14
+ [UnityCliRange(1L, 500L)] public int? Count { get; set; }
15
+ public UnityCliReadBudgetInput Budget { get; set; }
16
+ }
17
+
18
+ public sealed class Result
19
+ {
20
+ [UnityCliItemsRange(0, 500)] public List<ConsoleEntry> Items { get; set; }
21
+ public long RawEntryCount { get; set; }
22
+ public bool Truncated { get; set; }
23
+ public string Note { get; set; }
24
+ public UnityCliRequestBudgetUsage Budget { get; set; }
25
+ }
26
+
27
+ public ToolDescriptor Describe() => new()
28
+ {
29
+ Name = "console.get",
30
+ Summary = "Read one bounded, non-resumable Unity Console snapshot under request-wide limits.",
31
+ Description = "Read Console entries newest-first from one Unity snapshot window without materializing the Console. count defaults to 50 and is limited to 1..500. Filtering advances over raw positions and every entry uses the shared scan/reflection/getter/main-thread/UTF-8 budget. Unity exposes no reliable generation covering external Console clear/rebuild, so this tool intentionally has no cursor; truncated=true means start a fresh snapshot with a larger count or budget. rawEntryCount is Unity's raw count, not a filtered total. Read-only in Edit and Play Mode.",
32
+ Group = "console",
33
+ DestructiveHint = false,
34
+ Target = "editor",
35
+ PlayModeSupport = "supported",
36
+ DefaultTimeoutMs = 30000,
37
+ MaxTimeoutMs = 600000,
38
+ Examples = new[]
39
+ {
40
+ new ToolExample { Description = "Read a bounded error page", Input = new Request { Type = "error", Count = 50 } }
41
+ }
42
+ };
43
+
44
+ public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request request, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
45
+ {
46
+ request = request ?? new Request();
47
+ var pageSize = request.Count ?? 50;
48
+ var page = EditorToolSupport.ReadConsolePage(request.Type, request.Filter, pageSize, ctx.UseReadBudget(request.Budget));
49
+ return new System.Threading.Tasks.ValueTask<Result>(new Result
50
+ {
51
+ Items = page.Items,
52
+ RawEntryCount = page.RawEntryCount,
53
+ Truncated = page.Truncated,
54
+ Note = page.Note,
55
+ Budget = page.Budget
56
+ });
25
57
  }
26
58
  }
27
59
  }
@@ -45,48 +45,129 @@ namespace UnityCli
45
45
  };
46
46
  }
47
47
 
48
- /// <summary>读取 Console 日志条目;Unity 2022 通过内部 LogEntries 反射读取。</summary>
49
- public static List<ConsoleEntry> ReadConsoleEntries(string typeFilter, string textFilter, int count)
48
+ /// <summary>在 Unity 固定读取窗口中按 raw index 扫描;外部 clear 无可靠 generation,因此截断明确不可续页。</summary>
49
+ public static ConsoleReadPage ReadConsolePage(string typeFilter, string textFilter, int pageSize, UnityCliRequestBudget budget)
50
50
  {
51
- var entries = new List<ConsoleEntry>();
52
- var entryType = FindType("UnityEditor.LogEntry");
53
- var logEntries = FindType("UnityEditor.LogEntries");
54
- var getEntry = logEntries == null ? null : logEntries.GetMethod("GetEntryInternal", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
55
- if (entryType == null || getEntry == null)
51
+ if (budget == null) throw new ArgumentNullException("budget");
52
+ budget.CheckpointOrThrow();
53
+ var entryType = FindConsoleType("UnityEditor.LogEntry", budget);
54
+ var logEntries = FindConsoleType("UnityEditor.LogEntries", budget);
55
+ if (entryType == null || logEntries == null)
56
56
  {
57
- return entries;
57
+ if (budget.IsExhausted) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
58
+ return ConsoleReadPage.Empty(budget.Usage());
58
59
  }
59
-
60
+ const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
61
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
62
+ var getEntry = logEntries.GetMethod("GetEntryInternal", flags);
63
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
64
+ var start = logEntries.GetMethod("StartGettingEntries", flags);
65
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
66
+ var end = logEntries.GetMethod("EndGettingEntries", flags);
67
+ if (getEntry == null || start == null || end == null)
68
+ throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_API_UNAVAILABLE", "Unity Console snapshot methods are unavailable in this Editor generation.", "Use a supported Unity Editor version.");
69
+ var fields = ConsoleFields.Create(entryType, budget);
60
70
  var entry = Activator.CreateInstance(entryType);
61
- var total = ConsoleEntryCount(logEntries);
62
- var max = Math.Max(1, Math.Min(count > 0 ? count : 50, 1000));
71
+ if (!budget.TryConsumeGetter() || !budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
72
+ var rawCount = Convert.ToInt32(start.Invoke(null, null), CultureInfo.InvariantCulture);
73
+ try
74
+ {
75
+ return ReadConsolePage(typeFilter, textFilter, pageSize, budget,
76
+ new ReflectionConsoleSnapshotAdapter(rawCount, getEntry, entry, fields));
77
+ }
78
+ finally
79
+ {
80
+ try { end.Invoke(null, null); }
81
+ catch (Exception exception)
82
+ {
83
+ throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_SNAPSHOT_CLOSE_FAILED", "Unity Console snapshot could not be closed: " + exception.GetType().Name + ".", "Retry after the Editor Console becomes available.");
84
+ }
85
+ }
86
+ }
87
+
88
+ /// <summary>生产分页核心只按raw index读取当前项,不复制完整Console集合。</summary>
89
+ internal static ConsoleReadPage ReadConsolePage(
90
+ string typeFilter,
91
+ string textFilter,
92
+ int pageSize,
93
+ UnityCliRequestBudget budget,
94
+ IConsoleSnapshotAdapter snapshot)
95
+ {
96
+ if (budget == null) throw new ArgumentNullException("budget");
97
+ if (snapshot == null) throw new ArgumentNullException("snapshot");
98
+ if (pageSize <= 0) throw new ArgumentOutOfRangeException("pageSize");
99
+ var rawCount = snapshot.Count;
100
+ var scanIndex = rawCount - 1;
101
+ var items = new List<ConsoleEntry>(Math.Min(pageSize, rawCount));
63
102
  var includeAllTypes = string.IsNullOrEmpty(typeFilter) || string.Equals(typeFilter, "all", StringComparison.OrdinalIgnoreCase);
64
- for (var i = total - 1; i >= 0 && entries.Count < max; i--)
103
+ while (scanIndex >= 0 && items.Count < pageSize)
65
104
  {
66
- getEntry.Invoke(null, new object[] { i, entry });
67
- var mode = Convert.ToInt32(entryType.GetField("mode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(entry), CultureInfo.InvariantCulture);
68
- var logType = ConsoleLevel(mode);
69
- if (!includeAllTypes && !string.Equals(logType, typeFilter, StringComparison.OrdinalIgnoreCase)) continue;
70
- var message = Convert.ToString(entryType.GetField("message", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(entry), CultureInfo.InvariantCulture) ?? "";
71
- var file = Convert.ToString(entryType.GetField("file", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(entry), CultureInfo.InvariantCulture) ?? "";
105
+ ConsoleEntry item;
106
+ if (!snapshot.TryRead(scanIndex, budget, out item)) break;
107
+ scanIndex--;
108
+ if (!includeAllTypes && !string.Equals(item.Type, typeFilter, StringComparison.OrdinalIgnoreCase)) continue;
72
109
  if (!string.IsNullOrEmpty(textFilter)
73
- && message.IndexOf(textFilter, StringComparison.OrdinalIgnoreCase) < 0
74
- && file.IndexOf(textFilter, StringComparison.OrdinalIgnoreCase) < 0) continue;
75
- entries.Add(new ConsoleEntry { Type = logType, Message = message, Count = 1 });
110
+ && item.Message.IndexOf(textFilter, StringComparison.OrdinalIgnoreCase) < 0
111
+ && item.File.IndexOf(textFilter, StringComparison.OrdinalIgnoreCase) < 0) continue;
112
+ if (!budget.TryReserveSerializedUtf8(item.Message) || !budget.TryReserveSerializedUtf8(item.File)) break;
113
+ items.Add(item);
76
114
  }
77
- return entries;
115
+ if (items.Count == 0 && rawCount > 0 && budget.IsExhausted)
116
+ throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension ?? "scannedRecords");
117
+ var truncated = scanIndex >= 0;
118
+ return new ConsoleReadPage
119
+ {
120
+ Items = items,
121
+ RawEntryCount = rawCount,
122
+ Truncated = truncated,
123
+ Note = truncated ? "Snapshot truncated; Console entries are intentionally non-resumable because Unity exposes no observable external clear generation." : null,
124
+ Budget = budget.Usage()
125
+ };
126
+ }
127
+
128
+ internal interface IConsoleSnapshotAdapter
129
+ {
130
+ int Count { get; }
131
+ bool TryRead(int rawIndex, UnityCliRequestBudget budget, out ConsoleEntry result);
78
132
  }
79
133
 
80
- private static int ConsoleEntryCount(Type logEntries)
134
+ private sealed class ReflectionConsoleSnapshotAdapter : IConsoleSnapshotAdapter
81
135
  {
82
- var method = logEntries == null ? null : logEntries.GetMethod("GetCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
83
- return method == null ? 0 : Convert.ToInt32(method.Invoke(null, null), CultureInfo.InvariantCulture);
136
+ private readonly MethodInfo getEntry;
137
+ private readonly object target;
138
+ private readonly ConsoleFields fields;
139
+
140
+ internal ReflectionConsoleSnapshotAdapter(int count, MethodInfo getEntry, object target, ConsoleFields fields)
141
+ {
142
+ Count = count;
143
+ this.getEntry = getEntry;
144
+ this.target = target;
145
+ this.fields = fields;
146
+ }
147
+
148
+ public int Count { get; private set; }
149
+
150
+ public bool TryRead(int rawIndex, UnityCliRequestBudget budget, out ConsoleEntry result)
151
+ {
152
+ result = null;
153
+ if (!budget.TryConsumeScannedRecord() || !budget.TryConsumeReflectionCall()) return false;
154
+ getEntry.Invoke(null, new object[] { rawIndex, target });
155
+ if (!budget.TryConsumeGetter() || !budget.TryConsumeReflectionCall()) return false;
156
+ var mode = Convert.ToInt32(fields.Mode.GetValue(target), CultureInfo.InvariantCulture);
157
+ if (!budget.TryConsumeGetter() || !budget.TryConsumeReflectionCall()) return false;
158
+ var message = Convert.ToString(fields.Message.GetValue(target), CultureInfo.InvariantCulture) ?? string.Empty;
159
+ if (!budget.TryConsumeGetter() || !budget.TryConsumeReflectionCall()) return false;
160
+ var file = Convert.ToString(fields.File.GetValue(target), CultureInfo.InvariantCulture) ?? string.Empty;
161
+ result = new ConsoleEntry { RawIndex = rawIndex, Type = ConsoleLevel(mode), Message = message, File = file, Count = 1L };
162
+ return true;
163
+ }
84
164
  }
85
165
 
86
- private static Type FindType(string fullName)
166
+ private static Type FindConsoleType(string fullName, UnityCliRequestBudget budget)
87
167
  {
88
- foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
168
+ foreach (var assembly in UnityCliAssemblySnapshot.Get(budget))
89
169
  {
170
+ if (!budget.TryConsumeReflectionCall()) return null;
90
171
  Type type = null;
91
172
  try { type = assembly.GetType(fullName, false); } catch { }
92
173
  if (type != null) return type;
@@ -94,6 +175,27 @@ namespace UnityCli
94
175
  return null;
95
176
  }
96
177
 
178
+ private sealed class ConsoleFields
179
+ {
180
+ internal FieldInfo Mode;
181
+ internal FieldInfo Message;
182
+ internal FieldInfo File;
183
+
184
+ internal static ConsoleFields Create(Type entryType, UnityCliRequestBudget budget)
185
+ {
186
+ const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
187
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
188
+ var mode = entryType.GetField("mode", flags);
189
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
190
+ var message = entryType.GetField("message", flags);
191
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
192
+ var file = entryType.GetField("file", flags);
193
+ if (mode == null || message == null || file == null) throw new UnityCliBridge.BridgeCommandException("E_CONSOLE_API_UNAVAILABLE", "Unity Console entry fields are unavailable in this Editor generation.", "Use a supported Unity Editor version.");
194
+ return new ConsoleFields { Mode = mode, Message = message, File = file };
195
+ }
196
+ }
197
+
198
+
97
199
  // Unity 2022 LogEntry.mode 位布局:kError=1, kAssert=2, kLog=4, kFatal=16, kAssetImportError=64,
98
200
  // kAssetImportWarning=128, kScriptingError=256, kScriptingWarning=512, kScriptingException=2048, kScriptingAssertion=4096。
99
201
  // 错误/警告/断言来自多个位(脚本与资源导入各有独立位),只查低 3 位会把全部条目误归为 log。
@@ -123,7 +225,20 @@ namespace UnityCli
123
225
  public sealed class PlayModeInfo { public bool IsPlaying { get; set; } public bool IsPaused { get; set; } public bool IsPlayingOrWillChangePlaymode { get; set; } }
124
226
  public sealed class BusyInfo { public bool IsBusy { get; set; } public bool Compiling { get; set; } public bool Updating { get; set; } public bool Building { get; set; } public bool PlayModeChanging { get; set; } }
125
227
  public sealed class ActiveSceneInfo { public string Name { get; set; } public string Path { get; set; } public bool IsLoaded { get; set; } public bool IsDirty { get; set; } }
126
- public sealed class ConsoleEntry { public string Type { get; set; } public string Message { get; set; } public long Count { get; set; } }
228
+ public sealed class ConsoleEntry { public long RawIndex { get; set; } public string Type { get; set; } public string Message { get; set; } public string File { get; set; } public long Count { get; set; } }
229
+ public sealed class ConsoleReadPage
230
+ {
231
+ public List<ConsoleEntry> Items { get; set; }
232
+ public long RawEntryCount { get; set; }
233
+ public bool Truncated { get; set; }
234
+ public string Note { get; set; }
235
+ public UnityCliRequestBudgetUsage Budget { get; set; }
236
+
237
+ internal static ConsoleReadPage Empty(UnityCliRequestBudgetUsage usage)
238
+ {
239
+ return new ConsoleReadPage { Items = new List<ConsoleEntry>(), RawEntryCount = 0L, Truncated = false, Budget = usage };
240
+ }
241
+ }
127
242
  public sealed class EditorPlannedEffect { public string Type { get; set; } public string Path { get; set; } public string Action { get; set; } public string Name { get; set; } }
128
243
  public sealed class PlayModeResult { public bool Changed { get; set; } public bool IsPlaying { get; set; } public bool IsPaused { get; set; } }
129
244
  public sealed class MenuResult { public string Path { get; set; } public bool Executed { get; set; } public long ElapsedMs { get; set; } }
@@ -26,7 +26,7 @@ namespace UnityCli.Tools.Editor
26
26
  Name = "editor.menu-items",
27
27
  Summary = "Report Editor menu enumeration availability without executing menus.",
28
28
  Description = "Attempt to enumerate Unity Editor menu items as read-only discovery. Unity has no stable public API for full menu enumeration, so this context may return an empty items array with diagnostics; executing a menu path remains the destructive Tool editor.menu.",
29
- DestructiveHint = false,
29
+ DestructiveHint = false,
30
30
  Group = "editor",
31
31
  Target = "editor",
32
32
  PlayModeSupport = "supported",
@@ -15,17 +15,8 @@ namespace UnityCli
15
15
  public ToolDescriptor Describe() => new() { Name = "editor.play", Summary = "Enter Unity Play Mode and return only after the Editor reaches a stable playing state.", Description = "Set EditorApplication.isPlaying=true, absorb the PlayMode transition or same-session reload, and return the stable Editor state. Success proves isPlaying=true and the central PlayMode transition flag is false.", Group = "editor",DestructiveHint = false, SideEffects = new[] { "session-affecting" }, Target = "editor", PlayModeSupport = "supported", DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000, Examples = new[] { new ToolExample { Description = "Enter play mode", Input = new Request { } } } };
16
16
  public async System.Threading.Tasks.ValueTask<Response> ExecuteAsync(Request r, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
17
17
  {
18
- // before 采集一次后按 requestId 存 SessionState:PlayMode 过渡触发 domain reload,
19
- // 同一请求重跑时 before 必须仍是第一次 effect 前的值,Changed 语义才跨 reload 成立。
20
- var beforeKey = "unity-cli.play.before." + ctx.RequestId;
21
- var rawBefore = SessionState.GetString(beforeKey, null);
22
- bool before;
23
- if (string.IsNullOrEmpty(rawBefore))
24
- {
25
- before = EditorApplication.isPlaying;
26
- SessionState.SetString(beforeKey, before ? "1" : "0");
27
- }
28
- else before = rawBefore == "1";
18
+ // 首次effect前状态由固定direct root持久化;Tool重入不再创建逐请求SessionState键。
19
+ var before = EditorApplication.isPlaying;
29
20
  EditorToolSupport.EnsureEditorNotBusy("editor.play");
30
21
  ctx.CommitEffect();
31
22
  EditorApplication.isPaused = false;
@@ -54,7 +54,7 @@ namespace UnityCli
54
54
  {
55
55
  Name = "editor.selection", Summary = "Read current Editor selection names and reusable object references without changing selection.",
56
56
  Description = "Read the current Unity Editor selection in Hierarchy or Project Browser. Returns name arrays plus reusable object details: instanceId, type, asset path/GUID, hierarchy path, GameObject reference, transform, and component summaries. It does not select, focus, ping, or modify anything.",
57
- DestructiveHint = false,
57
+ DestructiveHint = false,
58
58
  Group = "editor", Target = "editor", PlayModeSupport = "supported",
59
59
  Examples = new[] { new ToolExample { Description = "Read the current selection", Input = new Request { } } }
60
60
  };
@@ -15,17 +15,8 @@ namespace UnityCli
15
15
  public ToolDescriptor Describe() => new() { Name = "editor.stop", Summary = "Exit Unity Play Mode and return only after the Editor reaches stable Edit Mode.", Description = "Set EditorApplication.isPlaying=false, absorb the PlayMode transition or same-session reload, and return the stable Editor state. Success proves isPlaying=false and the central PlayMode transition flag is false.", Group = "editor",DestructiveHint = false, SideEffects = new[] { "session-affecting" }, Target = "editor", PlayModeSupport = "supported", DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000, Examples = new[] { new ToolExample { Description = "Exit play mode", Input = new Request { } } } };
16
16
  public async System.Threading.Tasks.ValueTask<Response> ExecuteAsync(Request r, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
17
17
  {
18
- // before 采集一次后按 requestId 存 SessionState:PlayMode 过渡触发 domain reload,
19
- // 同一请求重跑时 before 必须仍是第一次 effect 前的值,Changed 语义才跨 reload 成立。
20
- var beforeKey = "unity-cli.stop.before." + ctx.RequestId;
21
- var rawBefore = SessionState.GetString(beforeKey, null);
22
- bool before;
23
- if (string.IsNullOrEmpty(rawBefore))
24
- {
25
- before = EditorApplication.isPlaying;
26
- SessionState.SetString(beforeKey, before ? "1" : "0");
27
- }
28
- else before = rawBefore == "1";
18
+ // 首次effect前状态由固定direct root持久化;Tool重入不再创建逐请求SessionState键。
19
+ var before = EditorApplication.isPlaying;
29
20
  EditorToolSupport.EnsureEditorNotBusy("editor.stop");
30
21
  ctx.CommitEffect();
31
22
  EditorApplication.isPaused = false;
@@ -41,7 +41,7 @@ namespace UnityCli.Tools.Editor
41
41
  {
42
42
  Name = "editor.windows", Summary = "Read currently open Unity EditorWindow instances with title, type names, focused state, and instance IDs.",
43
43
  Description = "Read currently open Unity EditorWindow instances with title, type names, focused state, and instance IDs. This observes editor UI state without opening, closing, focusing, or moving windows.",
44
- DestructiveHint = false,
44
+ DestructiveHint = false,
45
45
  Group = "editor",
46
46
  Target = "editor",
47
47
  PlayModeSupport = "supported",
@@ -34,8 +34,8 @@ namespace UnityCli
34
34
  {
35
35
  var options = new UnityCliBridge.ObjectSerializer.Options
36
36
  {
37
- MaxDepth = request.MaxDepth ?? 4,
38
- MaxArrayItems = Math.Max(0, Math.Min(request.MaxArrayItems ?? 50, 1000)),
37
+ MaxDepth = request.MaxDepth ?? UnityCliBridge.ObjectSerializer.DefaultMaxDepth,
38
+ MaxArrayItems = request.MaxArrayItems ?? UnityCliBridge.ObjectSerializer.DefaultMaxArrayItems,
39
39
  IncludeFields = request.IncludeFields ?? true,
40
40
  IncludeProperties = request.IncludeProperties ?? true,
41
41
  DeepSerialization = request.DeepSerialization ?? true
@@ -46,7 +46,7 @@ namespace UnityCli
46
46
  }
47
47
  if (request.Paths != null)
48
48
  {
49
- options.Paths = new HashSet<string>(request.Paths.Where(path => !string.IsNullOrWhiteSpace(path)).Select(path => path.Trim()));
49
+ options.Paths = request.Paths.Where(path => !string.IsNullOrWhiteSpace(path)).Select(path => path.Trim()).ToList();
50
50
  }
51
51
  var query = request.ViewQuery as Dictionary<string, object>;
52
52
  if (query != null)
@@ -55,7 +55,7 @@ namespace UnityCli
55
55
  if (query.TryGetValue("path", out value)) options.ViewPath = value as string;
56
56
  if (query.TryGetValue("namePattern", out value)) options.NamePattern = value as string;
57
57
  if (query.TryGetValue("typeFilter", out value)) options.TypeFilter = value as string;
58
- if (query.TryGetValue("maxDepth", out value) && value != null) options.MaxDepth = Math.Max(0, Convert.ToInt32(value, CultureInfo.InvariantCulture));
58
+ if (query.TryGetValue("maxDepth", out value) && value != null) options.MaxDepth = UnityCliBridge.ObjectSerializer.ParseMaxDepth(value);
59
59
  }
60
60
  if (!string.IsNullOrEmpty(request.NamePattern))
61
61
  {
@@ -117,6 +117,17 @@ namespace UnityCli
117
117
  return new GameObjectRef { Id = gameObject.GetInstanceID(), Name = gameObject.name, Path = HierarchyPath(gameObject) };
118
118
  }
119
119
 
120
+ /// <summary>在同一请求预算内构造 GameObject 引用,祖先每一步都在读取前计费。</summary>
121
+ public static GameObjectRef BuildGameObjectRef(GameObject gameObject, UnityCliRequestBudget budget)
122
+ {
123
+ if (budget == null) throw new ArgumentNullException("budget");
124
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
125
+ var id = gameObject.GetInstanceID();
126
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
127
+ var name = gameObject.name;
128
+ return new GameObjectRef { Id = id, Name = name, Path = HierarchyPath(gameObject, budget) };
129
+ }
130
+
120
131
  /// <summary>构造 Transform 摘要(position/rotation/scale)。</summary>
121
132
  public static TransformInfo BuildTransformInfo(Transform transform)
122
133
  {
@@ -145,6 +156,16 @@ namespace UnityCli
145
156
  return property == null || (bool)property.GetValue(component, null);
146
157
  }
147
158
 
159
+ /// <summary>在反射和 getter 前计费后读取 enabled;没有该属性的组件视为启用。</summary>
160
+ public static bool ComponentEnabled(Component component, UnityCliRequestBudget budget)
161
+ {
162
+ if (!budget.TryConsumeReflectionCall()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
163
+ var property = component.GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public);
164
+ if (property == null) return true;
165
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
166
+ return (bool)property.GetValue(component, null);
167
+ }
168
+
148
169
  /// <summary>构造 GameObject 详情(id/name/path/active/tag/layer/transform/components/children)。</summary>
149
170
  public static GameObjectDetail BuildGameObjectDetail(GameObject gameObject)
150
171
  {
@@ -222,6 +243,24 @@ namespace UnityCli
222
243
  return string.Join("/", names.ToArray());
223
244
  }
224
245
 
246
+ /// <summary>祖先链逐步读取并收取 scan/getter/UTF-8 预算。</summary>
247
+ public static string HierarchyPath(GameObject gameObject, UnityCliRequestBudget budget)
248
+ {
249
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
250
+ var names = new Stack<string>();
251
+ var current = gameObject.transform;
252
+ while (current != null)
253
+ {
254
+ if (!budget.TryConsumeScannedRecord() || !budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
255
+ var name = current.name;
256
+ if (!budget.TryReserveSerializedUtf8(name)) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
257
+ names.Push(name);
258
+ if (!budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
259
+ current = current.parent;
260
+ }
261
+ return string.Join("/", names.ToArray());
262
+ }
263
+
225
264
  // ─── 向量解析 ──────────────────────────────────────────────────────
226
265
 
227
266
  public static Vector3 ParseVector3(string value)
@@ -299,6 +338,17 @@ namespace UnityCli
299
338
  return null;
300
339
  }
301
340
 
341
+ /// <summary>读取型搜索只尝试 exact/full Unity namespaces,避免为短名调用 Assembly.GetTypes 全量扫描。</summary>
342
+ public static Type ResolveComponentType(string componentName, UnityCliRequestBudget budget)
343
+ {
344
+ var type = UnityCliBridge.TypeSchemaGenerator.ResolveType(componentName, budget)
345
+ ?? UnityCliBridge.TypeSchemaGenerator.ResolveType("UnityEngine." + componentName, budget)
346
+ ?? UnityCliBridge.TypeSchemaGenerator.ResolveType("UnityEngine.UI." + componentName, budget);
347
+ if (type == null || !typeof(Component).IsAssignableFrom(type))
348
+ throw new UnityCliBridge.BridgeCommandException("E_COMPONENT_TYPE_NOT_FOUND", "Component type not found within the bounded exact namespaces: " + componentName, "Pass a full component type name.");
349
+ return type;
350
+ }
351
+
302
352
  /// <summary>按短名、FullName 或 UnityEngine namespace 名解析 Component Type。</summary>
303
353
  public static Type ResolveComponentType(string componentName)
304
354
  {
@@ -72,7 +72,7 @@ namespace UnityCli
72
72
  { "target", targetRef.Path },
73
73
  { "instanceId", targetRef.Id }
74
74
  },
75
- new[] { "Run tools run go.inspect for the target and inspect the Unity Console before retrying." });
75
+ new[] { "Run tools run scene.gameobject for the target and inspect console.get before retrying." });
76
76
  }
77
77
  UnityCliSceneMutation.MarkSceneDirty(scene);
78
78
  return new System.Threading.Tasks.ValueTask<Result>(new Result