@alpsckr/unitycli 0.4.2 → 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 +35 -42
  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
@@ -7,103 +7,187 @@ import { PackageManagerError } from "../package-manager.js";
7
7
  import { instanceSelectionFailure, selectInstanceForFlags, selectObservationInstanceForFlags } from "../instances.js";
8
8
  import { EditorBlockerObserver, sanitizeEditorBlockers } from "../editor-blocker-observer.js";
9
9
  import { defaultDataDir } from "../platform.js";
10
+ import { trackCliProcessOwner } from "../cli-process-owners.js";
10
11
  import { validateSchema } from "../schema/validator.js";
11
- import { checkToolExtensionAvailability, extensionAvailabilityFlags } from "../extension-availability.js";
12
- import { resolveCatalogIndependentInvocationTool, resolveCatalogTool } from "./catalog.js";
12
+ import { checkToolExtensionAvailability, extensionIdForToolName, freezeExtensionAvailability } from "../extension-availability.js";
13
+ import { ExtensionInstallerError } from "../extensions/installer.js";
14
+ import { resolveCatalogIndependentInvocationTool, resolveCatalogIndependentOperabilityTool, resolveCatalogTool } from "./catalog.js";
13
15
  import { generatedToolCompletionContract } from "./.generated-completion-registry.js";
14
16
  import { findDefineTool } from "./define.js";
15
17
  import { StructuredToolError } from "./errors.js";
16
18
  import { EXTENSION_GROUPS, findToolByName, toolIsMutation } from "./metadata/index.js";
17
- const MULTI_TARGET_CATALOG_TOOLS = new Set(["tools.group", "tools.group-list", "tools.search", "tools.describe", "diagnose.capabilities"]);
19
+ /** 生产使用唯一supervisor实现;隔离测试只能替换构造边界。 */
20
+ function createSessionSupervisor(flags, runtime) {
21
+ return runtime.createSessionSupervisor?.(flags, runtime) ?? new SessionSupervisor(flags, runtime);
22
+ }
23
+ const MULTI_TARGET_CATALOG_TOOLS = new Set();
24
+ /** command 与 tools run 在第一次 live discovery 前只创建一次顶层 admission deadline。 */
25
+ export function beginToolInvocation(flags, requestId, timeoutMetadata, startedAtMs = Date.now()) {
26
+ const timeoutFailure = validateExecutionTimeoutFlags(flags, requestId);
27
+ if (timeoutFailure)
28
+ return { ok: false, result: timeoutFailure };
29
+ const timeoutMs = Math.max(1, executionFromFlags(flags).timeoutMs ?? timeoutMetadata?.timeoutMs ?? 30_000);
30
+ return { ok: true, context: { timeoutMs, admissionAbsoluteDeadlineMs: startedAtMs + timeoutMs } };
31
+ }
18
32
  /**
19
33
  * Tool 分发顺序固定为输入解析、catalog 解析、schema 校验、目标选择、执行与 envelope。
20
34
  * 调用即授权,只保留 schema、目标与 descriptor 的正确性验证。
21
35
  */
22
- export async function dispatchTool(name, positionalTarget, flags, runtime, requestId, seed = {}, resolvedTool) {
36
+ export async function dispatchTool(name, positionalTarget, flags, runtime, requestId, seed = {}, resolvedTool, invocationContext) {
23
37
  const dispatchStartedAtMs = Date.now();
24
38
  if (!name)
25
39
  return failure(requestId, "E_TOOL_NOT_FOUND_FOR_TARGET", "Tool name is required for tools run.", ["Run unitycli tools group to see tool groups.", "Run unitycli tools search <k1|k2|...> to find related tools."]);
26
- const executionFlagError = validateExecutionTimeoutFlags(flags, requestId);
27
- if (executionFlagError)
28
- return executionFlagError;
29
- const codeInputDeadlineMs = name === "code.exec"
30
- ? dispatchStartedAtMs + (typeof flags["timeout-ms"] === "string" ? Number(flags["timeout-ms"]) : 60_000)
31
- : undefined;
32
- const parsed = await parseTypedInput(flags, requestId, name === "code.exec" ? 1024 * 1024 : undefined, codeInputDeadlineMs);
40
+ if (resolvedTool && resolvedTool.name !== name)
41
+ return failure(requestId, "E_TOOL_SCHEMA_CONFLICT", `Resolved Tool name ${resolvedTool.name} does not match requested name ${name}.`, [
42
+ "Refresh the selected Unity instance catalog and retry the same command."
43
+ ], { requestedName: name, resolvedName: resolvedTool.name });
44
+ const localMetadata = findToolByName(name);
45
+ const timeoutMetadata = resolvedTool ?? localMetadata;
46
+ const defaultTimeoutMs = name === "code.exec" ? 60_000 : 30_000;
47
+ const started = invocationContext
48
+ ? { ok: true, context: invocationContext }
49
+ : beginToolInvocation(flags, requestId, { timeoutMs: timeoutMetadata?.timeoutMs ?? defaultTimeoutMs }, dispatchStartedAtMs);
50
+ if (!started.ok)
51
+ return started.result;
52
+ const admissionTimeoutMs = started.context.timeoutMs;
53
+ const admissionAbsoluteDeadlineMs = started.context.admissionAbsoluteDeadlineMs;
54
+ const parsed = await parseTypedInput(flags, requestId, name === "code.exec" ? 1024 * 1024 : undefined, admissionAbsoluteDeadlineMs);
33
55
  if (!parsed.ok)
34
56
  return parsed.error;
35
57
  const dispatchFlags = withStructuredInput(flags, parsed.input);
58
+ const dispatchResolved = (tool, input) => dispatchResolvedTool(tool, input, dispatchFlags, runtime, requestId, admissionTimeoutMs, admissionAbsoluteDeadlineMs, started.context.discoveryProvenances);
36
59
  // command入口已从同一次live catalog读取schema;直接使用该descriptor,避免二次发现改变绑定。
37
60
  if (resolvedTool) {
38
- if (resolvedTool.name !== name)
39
- return failure(requestId, "E_TOOL_SCHEMA_CONFLICT", `Resolved Tool name ${resolvedTool.name} does not match requested name ${name}.`, [
40
- "Refresh the selected Unity instance catalog and retry the same command."
41
- ], { requestedName: name, resolvedName: resolvedTool.name });
42
61
  const input = requestFromInput(resolvedTool, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
43
- return dispatchResolvedTool(resolvedTool, input, dispatchFlags, runtime, requestId, dispatchStartedAtMs);
62
+ return dispatchResolved(resolvedTool, input);
63
+ }
64
+ if (localMetadata?.handler === "offline") {
65
+ const input = requestFromInput(localMetadata, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
66
+ return dispatchResolved(localMetadata, input);
67
+ }
68
+ // 内置 hybrid Tool 的 dry-run 不需要 live descriptor,但仍保留统一 admission 与输出校验。
69
+ if (localMetadata?.handler === "hybrid" && getBoolean(dispatchFlags, "dry-run") && localMetadata.supportsDryRun) {
70
+ const input = requestFromInput(localMetadata, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
71
+ return dispatchResolved(localMetadata, input);
44
72
  }
45
- const localMetadata = findToolByName(name);
46
73
  const localProperties = localMetadata?.inputSchema.properties;
47
74
  // TS-local schema 的 project 仅约束已选实例;不得把其他业务字段写入 selector/execution flags。
48
75
  const catalogFlags = localMetadata && localProperties && "project" in localProperties
49
76
  && typeof parsed.input.project === "string" && dispatchFlags.project === undefined
50
77
  ? { ...dispatchFlags, project: parsed.input.project }
51
78
  : dispatchFlags;
52
- // exact 弹窗恢复及其 describe 学习入口不依赖被同一 modal 阻断的 Live catalog。
53
- const catalogIndependentTool = resolveCatalogIndependentInvocationTool(name, typeof seed.name === "string" ? seed.name : undefined);
79
+ // exact 弹窗观察与恢复不依赖被同一 modal 阻断的 Live catalog。
80
+ const catalogIndependentTool = resolveCatalogIndependentInvocationTool(name);
54
81
  if (catalogIndependentTool) {
55
82
  const input = requestFromInput(catalogIndependentTool, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
56
- return dispatchResolvedTool(catalogIndependentTool, input, dispatchFlags, runtime, requestId, dispatchStartedAtMs);
83
+ return dispatchResolved(catalogIndependentTool, input);
57
84
  }
58
85
  const coreSpec = bridgeCommandRegistry.specs().find((spec) => (spec.toolName === name || spec.bridgeCommand === name) && !EXTENSION_GROUPS.has(spec.group) && spec.internal !== true);
59
86
  // Runtime descriptor 的唯一 owner 在 TS catalog;执行直接进入共享 runtime wrapper,目标缺失时返回 runtime selector 错误。
60
87
  if (localMetadata?.handler === "bridge-runtime") {
61
88
  const input = requestFromInput(localMetadata, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
62
- return dispatchResolvedTool(localMetadata, input, dispatchFlags, runtime, requestId, dispatchStartedAtMs);
89
+ return dispatchResolved(localMetadata, input);
63
90
  }
64
91
  // 无 catalog fixture 的注入式 bridgeExecute 仅用于隔离测试;其余路径必须 catalog-first。
65
- if (runtime.bridgeExecute && runtime.projectTools === undefined && localMetadata) {
92
+ if (runtime.bridgeExecute && runtime.projectTools === undefined && !runtime.createSessionSupervisor && localMetadata) {
66
93
  const input = requestFromInput(localMetadata, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
67
- return dispatchResolvedTool(localMetadata, input, dispatchFlags, runtime, requestId, dispatchStartedAtMs);
94
+ return dispatchResolved(localMetadata, input);
68
95
  }
69
- if (coreSpec && runtime.bridgeExecute && runtime.projectTools === undefined) {
70
- return executeCoreBridgeSpec(name, coreSpec, parsed.input, dispatchFlags, runtime, requestId, positionalTarget);
96
+ if (coreSpec && runtime.bridgeExecute && runtime.projectTools === undefined && !runtime.createSessionSupervisor) {
97
+ return executeCoreBridgeSpec(name, coreSpec, parsed.input, dispatchFlags, runtime, requestId, admissionAbsoluteDeadlineMs, positionalTarget);
71
98
  }
72
- const resolved = await resolveCatalogTool(name, catalogFlags, runtime, requestId);
99
+ const resolved = await resolveCatalogToolForInvocation(name, catalogFlags, runtime, requestId, started.context);
73
100
  if (resolved.ok === false)
74
- return enrichTargetFailureWithDialogBlocker(resolved, catalogFlags, runtime);
101
+ return enrichTargetFailureWithDialogBlocker(resolved, catalogFlags, runtime, admissionAbsoluteDeadlineMs);
75
102
  const tool = resolved.tool;
76
103
  if (!tool)
77
104
  return failure(requestId, "E_TOOL_NOT_FOUND_FOR_TARGET", `Tool not found: ${name}.`, ["Run unitycli tools group to see tool groups.", "Run unitycli tools search <k1|k2|...> to find related tools."]);
78
105
  const input = requestFromInput(tool, { ...parsed.input, ...seed }, dispatchFlags, positionalTarget);
79
- return dispatchResolvedTool(tool, input, dispatchFlags, runtime, requestId, dispatchStartedAtMs);
106
+ return dispatchResolvedTool(tool, input, dispatchFlags, runtime, requestId, admissionTimeoutMs, admissionAbsoluteDeadlineMs, resolved.context.discoveryProvenances);
107
+ }
108
+ /**
109
+ * live exact descriptor 在真实 catalog admission 上读取,并把 exact listener provenance 带回同一顶层调用。
110
+ * fixture 仍走相同 resolver,但没有伪造 registry identity。
111
+ */
112
+ export async function resolveCatalogToolForInvocation(name, flags, runtime, requestId, context, fallbackName) {
113
+ if (runtime.projectTools) {
114
+ const resolved = await resolveCatalogTool(name, flags, runtime, requestId, context.admissionAbsoluteDeadlineMs, fallbackName);
115
+ return resolved.ok ? { ...resolved, context } : resolved;
116
+ }
117
+ const acquired = await acquireCatalogAdmissions(`catalog.resolve:${name}`, { name, ...(fallbackName ? { fallbackName } : {}) }, flags, runtime, requestId, context.timeoutMs, context.admissionAbsoluteDeadlineMs, "catalog-resolution-v1");
118
+ if ("result" in acquired)
119
+ return acquired.result;
120
+ const provenances = discoveryProvenances(acquired.admissions);
121
+ const primary = acquired.admissions.editor ?? acquired.admissions.runtime;
122
+ // descriptor discovery consumes only the original top-level admission budget.
123
+ for (const admission of Object.values(acquired.admissions)) {
124
+ if (admission)
125
+ admission.executionAbsoluteDeadlineMs = context.admissionAbsoluteDeadlineMs;
126
+ }
127
+ try {
128
+ const resolved = await resolveCatalogTool(name, flags, {
129
+ ...runtime, rootAdmission: primary, rootAdmissions: acquired.admissions,
130
+ }, requestId, context.admissionAbsoluteDeadlineMs, fallbackName);
131
+ return resolved.ok
132
+ ? { ...resolved, context: { ...context, discoveryProvenances: provenances } }
133
+ : resolved;
134
+ }
135
+ finally {
136
+ await releaseUnconsumedCatalogAdmissions(acquired);
137
+ }
138
+ }
139
+ function discoveryProvenances(admissions) {
140
+ const result = {};
141
+ for (const target of ["editor", "runtime"]) {
142
+ const admission = admissions[target];
143
+ if (!admission)
144
+ continue;
145
+ result[target] = {
146
+ target,
147
+ instanceId: admission.instanceId,
148
+ sessionId: admission.sessionId,
149
+ ...(target === "editor" ? { editorSessionId: admission.sessionId } : {}),
150
+ listenerId: admission.listenerId,
151
+ listenerGeneration: admission.listenerGeneration,
152
+ };
153
+ }
154
+ return result;
80
155
  }
81
156
  /** 公开统一catalog对每个在线target session分别占一个slot,禁止跨池旁路输出。 */
82
157
  export async function dispatchCatalogProjection(command, input, flags, runtime, requestId, execute) {
158
+ if (runtime.projectTools)
159
+ return execute(runtime);
83
160
  const startedAtMs = Date.now();
84
161
  const timeoutMs = Math.max(1, executionFromFlags(flags).timeoutMs ?? 30_000);
85
162
  const acquired = await acquireCatalogAdmissions(command, input, flags, runtime, requestId, timeoutMs, startedAtMs + timeoutMs, "catalog-projection-v1");
86
163
  if ("result" in acquired)
87
164
  return acquired.result;
88
165
  const primary = acquired.admissions.editor ?? acquired.admissions.runtime;
89
- const result = await execute({ ...runtime, rootAdmission: primary, rootAdmissions: acquired.admissions });
90
- await releaseUnconsumedCatalogAdmissions(acquired);
91
- return result;
166
+ try {
167
+ return await execute({ ...runtime, rootAdmission: primary, rootAdmissions: acquired.admissions });
168
+ }
169
+ finally {
170
+ await releaseUnconsumedCatalogAdmissions(acquired);
171
+ }
92
172
  }
93
- async function acquireCatalogAdmissions(command, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs, completionContractIdentity) {
173
+ async function acquireCatalogAdmissions(command, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs, completionContractIdentity, expectedDiscoveryProvenances) {
94
174
  const context = { admissions: {}, supervisors: {}, executionAbsoluteDeadlineMs: 0 };
95
- let lastOffline;
175
+ let firstOffline;
96
176
  for (const target of ["editor", "runtime"]) {
97
- const supervisor = new SessionSupervisor(flags, runtime);
177
+ const supervisor = createSessionSupervisor(flags, runtime);
98
178
  try {
99
- const admission = await supervisor.acquireRootAdmission({ requestId, command, input, dryRun: false, target, completionContractIdentity, timeoutMs, admissionAbsoluteDeadlineMs });
179
+ const admission = await supervisor.acquireRootAdmission({
180
+ requestId, command, input, dryRun: false, target, completionContractIdentity,
181
+ captureDiscoveryProvenance: true,
182
+ expectedDiscoveryProvenance: expectedDiscoveryProvenances?.[target], timeoutMs, admissionAbsoluteDeadlineMs,
183
+ });
100
184
  context.admissions[target] = admission;
101
185
  context.supervisors[target] = supervisor;
102
186
  }
103
187
  catch (error) {
104
188
  const projected = catalogAdmissionFailure(requestId, error);
105
189
  if (projected.error.code === "E_INSTANCE_NOT_RUNNING" || projected.error.code === "E_RUNTIME_NOT_RUNNING") {
106
- lastOffline = projected;
190
+ firstOffline ??= projected;
107
191
  continue;
108
192
  }
109
193
  await releaseUnconsumedCatalogAdmissions(context);
@@ -112,7 +196,7 @@ async function acquireCatalogAdmissions(command, input, flags, runtime, requestI
112
196
  }
113
197
  const leases = Object.values(context.admissions).filter((value) => !!value);
114
198
  if (leases.length === 0)
115
- return { result: lastOffline ?? failure(requestId, "E_INSTANCE_NOT_RUNNING", "No live Unity target is available for catalog projection.", ["Open the target Unity project or development Player."]) };
199
+ return { result: firstOffline ?? failure(requestId, "E_INSTANCE_NOT_RUNNING", "No live Unity target is available for catalog projection.", ["Open the target Unity project or development Player."]) };
116
200
  const now = Date.now();
117
201
  if (leases.some((lease) => lease.grantExpiresAtMs <= now)) {
118
202
  await releaseUnconsumedCatalogAdmissions(context);
@@ -128,9 +212,15 @@ async function releaseUnconsumedCatalogAdmissions(context) {
128
212
  const admission = context.admissions[target];
129
213
  const supervisor = context.supervisors[target];
130
214
  if (admission && supervisor)
131
- await supervisor.completeRootAdmission(admission);
215
+ await completeUnconsumedRootAdmission(admission, supervisor);
132
216
  }
133
217
  }
218
+ /** 迟到cleanup只接管仍由CLI持有的未消费lease。 */
219
+ export async function completeUnconsumedRootAdmission(admission, supervisor) {
220
+ if (admission.consumed)
221
+ return;
222
+ await supervisor.completeRootAdmission(admission);
223
+ }
134
224
  function catalogAdmissionFailure(requestId, error) {
135
225
  const selectionFailure = instanceSelectionFailure(requestId, error);
136
226
  if (selectionFailure)
@@ -139,7 +229,8 @@ function catalogAdmissionFailure(requestId, error) {
139
229
  return failure(requestId, error.code, error.message, error.nextActions, error.details, { transient: error.transient, retryAfterMs: error.retryAfterMs });
140
230
  return failure(requestId, "BRIDGE_CONNECTION_FAILED", error instanceof Error ? error.message : String(error), ["Inspect the selected Unity session."], undefined, { transient: true, retryAfterMs: 100 });
141
231
  }
142
- async function dispatchResolvedTool(tool, input, flags, runtime, requestId, dispatchStartedAtMs) {
232
+ async function dispatchResolvedTool(tool, input, flags, runtime, requestId, admissionTimeoutMs, admissionAbsoluteDeadlineMs, discoveryProvenance) {
233
+ const invocationRuntime = discoveryProvenance ? { ...runtime, discoveryProvenances: discoveryProvenance } : runtime;
143
234
  const definition = findDefineTool(tool.name);
144
235
  const executionTool = tool;
145
236
  const completion = generatedToolCompletionContract(executionTool.name) ?? executionTool.completionContract;
@@ -152,10 +243,19 @@ async function dispatchResolvedTool(tool, input, flags, runtime, requestId, disp
152
243
  return failure(requestId, "E_TOOL_COMPLETION_CONTRACT_MISMATCH", `Tool ${executionTool.name} completion contract disagrees with its descriptor mutation signals.`, [
153
244
  `Run unitycli tools describe ${executionTool.name} and fix the descriptor or completion contract before execution.`
154
245
  ], { toolName: executionTool.name, contractMutation: completion.mutation, descriptorMutation });
155
- const availabilityFlags = await extensionAvailabilityFlags(flags, runtime);
156
- const availability = await checkToolExtensionAvailability(executionTool, availabilityFlags);
157
- if (!availability.available)
158
- return failure(requestId, availability.errorCode, availability.message, availability.nextActions, { extensionId: availability.extensionId, missingPackageIds: availability.availabilityResult?.missingPackageIds ?? executionTool.requiresPackages ?? [] });
246
+ if (executionTool.source === "extension" || extensionIdForToolName(executionTool.name)) {
247
+ try {
248
+ const extensionSnapshot = await freezeExtensionAvailability(flags, invocationRuntime);
249
+ const availability = await checkToolExtensionAvailability(executionTool, extensionSnapshot, admissionAbsoluteDeadlineMs);
250
+ if (!availability.available)
251
+ return failure(requestId, availability.errorCode, availability.message, availability.nextActions, { extensionId: availability.extensionId, missingPackageIds: availability.availabilityResult?.missingPackageIds ?? executionTool.requiresPackages ?? [] });
252
+ }
253
+ catch (error) {
254
+ if (error instanceof ExtensionInstallerError)
255
+ return failure(requestId, error.code, error.message, error.nextActions);
256
+ throw error;
257
+ }
258
+ }
159
259
  if (getBoolean(flags, "dry-run") && !executionTool.supportsDryRun)
160
260
  return failure(requestId, "E_DRY_RUN_UNSUPPORTED", `Tool ${executionTool.name} does not support dry-run.`, [
161
261
  "Remove --dry-run and invoke the Tool only when its declared side effects are acceptable.",
@@ -169,24 +269,28 @@ async function dispatchResolvedTool(tool, input, flags, runtime, requestId, disp
169
269
  errors: schemaErrors
170
270
  });
171
271
  return definition && executionTool.handler !== "bridge-runtime"
172
- ? executeDefinition(executionTool, completion, definition, input, flags, runtime, requestId, dispatchStartedAtMs)
173
- : executeLiveTool(executionTool, completion, input, flags, runtime, requestId, dispatchStartedAtMs);
272
+ ? executeDefinition(executionTool, completion, definition, input, flags, invocationRuntime, requestId, admissionTimeoutMs, admissionAbsoluteDeadlineMs)
273
+ : executeLiveTool(executionTool, completion, input, flags, invocationRuntime, requestId, admissionTimeoutMs, admissionAbsoluteDeadlineMs);
174
274
  }
175
275
  /** 已有 core bridge spec 使用统一参数构造,不进入 live custom wrapper。 */
176
- async function executeCoreBridgeSpec(name, spec, input, flags, runtime, requestId, positionalTarget) {
276
+ async function executeCoreBridgeSpec(name, spec, input, flags, runtime, requestId, absoluteDeadlineMs, positionalTarget) {
177
277
  let args = await spec.buildArgs({ command: name, flags: bridgeWrapperFlags(flags, input), positionalTarget });
178
278
  if (spec.toolName)
179
279
  args = { name: spec.toolName, input: args };
180
- return enrichTargetFailureWithDialogBlocker(await executeBridgePayload(requestId, spec.bridgeCommand, args, flags, runtime, undefined, {
280
+ return enrichTargetFailureWithDialogBlocker(await executeBridgePayload(requestId, spec.bridgeCommand, args, flags, runtime, {
181
281
  mode: "execute",
182
282
  mutation: true,
183
- }), flags, runtime);
283
+ absoluteDeadlineMs,
284
+ }), flags, runtime, absoluteDeadlineMs);
184
285
  }
185
- async function executeDefinition(tool, completion, definition, input, flags, runtime, requestId, dispatchStartedAtMs) {
286
+ async function executeDefinition(tool, completion, definition, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs) {
186
287
  let projectPath = typeof input.project === "string" ? input.project : process.cwd();
187
288
  const execution = executionFromFlags(flags);
188
- const timeoutMs = Math.max(1, execution.timeoutMs ?? tool.timeoutMs ?? 30_000);
189
- const admissionAbsoluteDeadlineMs = dispatchStartedAtMs + timeoutMs;
289
+ // 仅精确观察定义及 catalog fixture 不进入业务准入;生产中的普通本地 Tool 仍是 live target root。
290
+ if (isAdmissionIndependentLocalDefinition(tool, input)
291
+ || tool.handler === "offline" && runtime.projectTools !== undefined && !runtime.createSessionSupervisor) {
292
+ return executeLocalDefinition(tool, completion, definition, input, flags, runtime, requestId, projectPath, execution, admissionAbsoluteDeadlineMs);
293
+ }
190
294
  let selected;
191
295
  // package本地Tool也是live target的一等root;先固定实例,再由同一实例原子发放准入。
192
296
  try {
@@ -216,8 +320,19 @@ async function executeDefinition(tool, completion, definition, input, flags, run
216
320
  if ("result" in admissionContext)
217
321
  return admissionContext.result;
218
322
  const { admission, admissions, supervisors, executionAbsoluteDeadlineMs } = admissionContext;
219
- const absoluteDeadlineMs = executionAbsoluteDeadlineMs;
220
323
  const rootRuntime = { ...runtime, rootAdmission: admission, rootAdmissions: admissions };
324
+ const cleanup = async () => {
325
+ await releaseUnconsumedCatalogAdmissions({ admissions, supervisors, executionAbsoluteDeadlineMs });
326
+ };
327
+ return executeLocalDefinition(tool, completion, definition, input, flags, rootRuntime, requestId, projectPath, execution, executionAbsoluteDeadlineMs, cleanup);
328
+ }
329
+ /** exact owner判定只接受固定公开观察与durable status Tool。 */
330
+ function isAdmissionIndependentLocalDefinition(tool, _input) {
331
+ return resolveCatalogIndependentOperabilityTool(tool.name)?.handler === "offline";
332
+ }
333
+ /** 本地定义统一执行输出校验、effect barrier和deadline terminal。 */
334
+ async function executeLocalDefinition(tool, completion, definition, input, flags, runtime, requestId, projectPath, execution, absoluteDeadlineMs, cleanupAfterLateSettlement) {
335
+ const barrier = new LocalEffectBarrier(tool.name, absoluteDeadlineMs);
221
336
  const run = async () => {
222
337
  try {
223
338
  const data = await definition.execute(input, {
@@ -225,16 +340,16 @@ async function executeDefinition(tool, completion, definition, input, flags, run
225
340
  projectPath,
226
341
  absoluteDeadlineMs,
227
342
  execution,
228
- dataDir: rootRuntime.dataDir,
229
- artifactDir: getString(flags, "artifact-dir") ?? rootRuntime.dataDir ?? projectPath,
343
+ dataDir: runtime.dataDir,
344
+ artifactDir: getString(flags, "artifact-dir") ?? runtime.dataDir ?? projectPath,
230
345
  logPath: typeof input.logPath === "string" ? input.logPath : undefined,
231
346
  flags,
232
- projectTools: rootRuntime.projectTools,
233
- rootAdmission: admission,
234
- rootAdmissions: admissions,
235
- bridgeExecute: rootRuntime.bridgeExecute,
236
- fetch: rootRuntime.fetch,
237
- commitEffect: async () => undefined,
347
+ projectTools: runtime.projectTools,
348
+ rootAdmission: runtime.rootAdmission,
349
+ rootAdmissions: runtime.rootAdmissions,
350
+ bridgeExecute: runtime.bridgeExecute,
351
+ fetch: runtime.fetch,
352
+ commitEffect: barrier.commitEffect,
238
353
  });
239
354
  if (!tool.outputSchema)
240
355
  throw new StructuredToolError("E_TOOL_COMPLETION_PROOF_INVALID", `Tool ${tool.name} has no output schema for terminal proof.`, [
@@ -265,42 +380,94 @@ async function executeDefinition(tool, completion, definition, input, flags, run
265
380
  return failure(requestId, "COMMAND_FAILED", error instanceof Error ? error.message : String(error), [`Run unitycli tools describe ${tool.name} for input requirements and examples.`]);
266
381
  }
267
382
  };
268
- let result;
269
383
  try {
270
- result = await settleToolExecutionAtDeadline(tool.name, requestId, completion.mutation, absoluteDeadlineMs, run);
384
+ return await settleToolExecutionAtDeadline(tool.name, requestId, completion.mutation, absoluteDeadlineMs, run, {
385
+ closeEffectBarrier: barrier.close,
386
+ cleanupAfterLateSettlement,
387
+ });
271
388
  }
272
389
  catch (error) {
273
390
  if (error instanceof PackageManagerError)
274
- result = failure(requestId, error.code, error.message, error.nextActions);
275
- else if (error instanceof StructuredToolError)
276
- result = failure(requestId, error.code, error.message, error.nextActions, error.details);
277
- else
278
- result = failure(requestId, "COMMAND_FAILED", error instanceof Error ? error.message : String(error), [
279
- `Run unitycli tools describe ${tool.name} for input requirements and examples.`
280
- ]);
391
+ return failure(requestId, error.code, error.message, error.nextActions);
392
+ if (error instanceof StructuredToolError)
393
+ return failure(requestId, error.code, error.message, error.nextActions, error.details);
394
+ return failure(requestId, "COMMAND_FAILED", error instanceof Error ? error.message : String(error), [
395
+ `Run unitycli tools describe ${tool.name} for input requirements and examples.`
396
+ ]);
281
397
  }
282
- if (rootResultHasTrustedTerminal(result))
283
- await releaseUnconsumedCatalogAdmissions({ admissions, supervisors, executionAbsoluteDeadlineMs });
284
- return result;
285
398
  }
286
- /** Tool自己的wait未按时settle时由框架结束CLI等待;已开始的Unity effect不因此停止。 */
287
- export async function settleToolExecutionAtDeadline(toolName, requestId, mutation, absoluteDeadlineMs, run) {
288
- const remainingMs = absoluteDeadlineMs - Date.now();
289
- if (remainingMs <= 0)
290
- return toolDeadlineFailure(toolName, requestId, mutation);
291
- let timer;
292
- try {
293
- return await Promise.race([
294
- run(),
295
- new Promise((resolveTimeout) => {
296
- timer = setTimeout(() => resolveTimeout(toolDeadlineFailure(toolName, requestId, mutation)), remainingMs);
297
- }),
298
- ]);
399
+ /** 首个effect barrier在公开timeout后永久关闭;此前已跨过时保持原owner。 */
400
+ export class LocalEffectBarrier {
401
+ toolName;
402
+ absoluteDeadlineMs;
403
+ now;
404
+ closed = false;
405
+ committed = false;
406
+ constructor(toolName, absoluteDeadlineMs, now = Date.now) {
407
+ this.toolName = toolName;
408
+ this.absoluteDeadlineMs = absoluteDeadlineMs;
409
+ this.now = now;
299
410
  }
300
- finally {
301
- if (timer)
302
- clearTimeout(timer);
411
+ commitEffect = async () => {
412
+ if (this.committed)
413
+ return;
414
+ if (this.closed || this.now() >= this.absoluteDeadlineMs)
415
+ throw new StructuredToolError("E_EXECUTION_TIMEOUT", `Tool ${this.toolName} cannot start its first effect after the public deadline.`, [
416
+ "Inspect editor.state and the affected business state before deciding whether to submit a new request."
417
+ ], { reason: "post-deadline-effect-barrier" });
418
+ this.committed = true;
419
+ };
420
+ close = () => { this.closed = true; };
421
+ }
422
+ /** Tool自己的wait未按时settle时只关闭公开terminal;每次settlement只执行一次精确cleanup。 */
423
+ export async function settleToolExecutionAtDeadline(toolName, requestId, mutation, absoluteDeadlineMs, run, hooks = {}) {
424
+ const now = hooks.now ?? Date.now;
425
+ let cleanupStarted = false;
426
+ const cleanup = async () => {
427
+ if (cleanupStarted || !hooks.cleanupAfterLateSettlement)
428
+ return;
429
+ cleanupStarted = true;
430
+ try {
431
+ await hooks.cleanupAfterLateSettlement();
432
+ }
433
+ catch { /* cleanup不能重写已返回的terminal。 */ }
434
+ };
435
+ const remainingMs = absoluteDeadlineMs - now();
436
+ if (remainingMs <= 0) {
437
+ hooks.closeEffectBarrier?.();
438
+ trackCliProcessOwner(cleanup());
439
+ return toolDeadlineFailure(toolName, requestId, mutation);
303
440
  }
441
+ let timer;
442
+ let resolveTimer;
443
+ const markDeadline = () => {
444
+ hooks.closeEffectBarrier?.();
445
+ return { kind: "deadline" };
446
+ };
447
+ const runPromise = Promise.resolve().then(run);
448
+ const settlement = runPromise.then((value) => now() >= absoluteDeadlineMs ? markDeadline() : { kind: "result", value }, (reason) => now() >= absoluteDeadlineMs ? markDeadline() : { kind: "rejected", reason });
449
+ const owner = settlement.then(() => cleanup());
450
+ trackCliProcessOwner(owner);
451
+ const scheduleDeadline = () => {
452
+ const remaining = absoluteDeadlineMs - now();
453
+ if (remaining > 0) {
454
+ timer = setTimeout(scheduleDeadline, Math.max(1, remaining));
455
+ return;
456
+ }
457
+ resolveTimer?.(markDeadline());
458
+ };
459
+ const timerPromise = new Promise((resolveTimeout) => {
460
+ resolveTimer = resolveTimeout;
461
+ timer = setTimeout(scheduleDeadline, Math.max(1, remainingMs));
462
+ });
463
+ const winner = await Promise.race([settlement, timerPromise]);
464
+ if (timer)
465
+ clearTimeout(timer);
466
+ if (winner.kind === "deadline")
467
+ return toolDeadlineFailure(toolName, requestId, mutation);
468
+ if (winner.kind === "result")
469
+ return winner.value;
470
+ throw winner.reason;
304
471
  }
305
472
  /** mutation超时只能读取业务状态,不能建议直接重试或声称底层执行已取消。 */
306
473
  function toolDeadlineFailure(toolName, requestId, mutation) {
@@ -539,11 +706,12 @@ function validateKnownLocalTerminal(toolName, completion, result, input) {
539
706
  }
540
707
  if (toolName === "editor.refresh") {
541
708
  const editorState = objectRecord(record.editorState);
542
- if (typeof record.changed !== "boolean" || typeof record.compilationTriggered !== "boolean"
543
- || typeof record.sourceFileCount !== "number" || !Number.isSafeInteger(record.sourceFileCount) || record.sourceFileCount < 0
544
- || !sha256(record.sourceFingerprint) || !sha256(record.dependencyVersion)
709
+ const generation = objectRecord(record.generation);
710
+ if (typeof record.changed !== "boolean" || typeof record.importObserved !== "boolean" || typeof record.compilationTriggered !== "boolean"
711
+ || !generation || !nonnegativeInteger(generation.dependencyBefore) || !nonnegativeInteger(generation.dependencyAfter)
712
+ || !nonnegativeInteger(generation.processedBefore) || !nonnegativeInteger(generation.processedAfter)
545
713
  || !editorState || editorState.status !== "ready" || editorState.compile !== false || editorState.import !== false) {
546
- throw invalidCompletionProof(toolName, completion, "did not prove a stable source and dependency refresh readback");
714
+ throw invalidCompletionProof(toolName, completion, "did not prove stable Unity-owned import generations and ready state");
547
715
  }
548
716
  return true;
549
717
  }
@@ -648,7 +816,7 @@ function findFailedCompletionStatus(value) {
648
816
  }
649
817
  async function acquireToolAdmission(tool, completion, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs, selected) {
650
818
  if (MULTI_TARGET_CATALOG_TOOLS.has(tool.name)) {
651
- const acquired = await acquireCatalogAdmissions(tool.name, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs, JSON.stringify(completion));
819
+ const acquired = await acquireCatalogAdmissions(tool.name, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs, JSON.stringify(completion), runtime.discoveryProvenances);
652
820
  if ("result" in acquired)
653
821
  return acquired;
654
822
  const admission = acquired.admissions.editor ?? acquired.admissions.runtime;
@@ -657,7 +825,7 @@ async function acquireToolAdmission(tool, completion, input, flags, runtime, req
657
825
  }
658
826
  const target = selected?.instance.activeSession?.target ?? selected?.instance.target ?? toolTarget(tool, flags);
659
827
  const admissionFlags = selected ? { ...flags, instance: selected.instance.instanceId } : flags;
660
- const supervisor = new SessionSupervisor(admissionFlags, runtime);
828
+ const supervisor = createSessionSupervisor(admissionFlags, runtime);
661
829
  try {
662
830
  const admission = await supervisor.acquireRootAdmission({
663
831
  requestId,
@@ -666,6 +834,7 @@ async function acquireToolAdmission(tool, completion, input, flags, runtime, req
666
834
  dryRun: getBoolean(flags, "dry-run") || getBoolean(flags, "preflight"),
667
835
  target,
668
836
  completionContractIdentity: JSON.stringify(completion),
837
+ expectedDiscoveryProvenance: runtime.discoveryProvenances?.[target],
669
838
  timeoutMs,
670
839
  admissionAbsoluteDeadlineMs,
671
840
  });
@@ -705,37 +874,37 @@ const UNKNOWN_ROOT_OUTCOME_CODES = new Set([
705
874
  function rootResultHasTrustedTerminal(result) {
706
875
  return result.ok || !UNKNOWN_ROOT_OUTCOME_CODES.has(result.error.code);
707
876
  }
708
- async function executeLiveTool(tool, completion, input, flags, runtime, requestId, dispatchStartedAtMs) {
709
- const timeoutMs = Math.max(1, executionFromFlags(flags).timeoutMs ?? tool.timeoutMs ?? 30_000);
710
- const admissionContext = await acquireToolAdmission(tool, completion, input, flags, runtime, requestId, timeoutMs, dispatchStartedAtMs + timeoutMs);
877
+ async function executeLiveTool(tool, completion, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs) {
878
+ const admissionContext = await acquireToolAdmission(tool, completion, input, flags, runtime, requestId, timeoutMs, admissionAbsoluteDeadlineMs);
711
879
  if ("result" in admissionContext)
712
880
  return admissionContext.result;
713
881
  const { admission, supervisor } = admissionContext;
714
882
  const runtimeTarget = admission.target === "runtime";
715
883
  const wrapper = runtimeTarget ? "runtime-tool.run" : "project-tool.run";
716
- const descriptorBinding = {
717
- ...(tool.liveDescriptorFingerprint ? { liveDescriptorFingerprint: tool.liveDescriptorFingerprint } : {})
718
- };
719
884
  const rootRuntime = { ...runtime, rootAdmission: admission };
720
885
  // live descriptor已完成schema校验,wrapper直接承载typed input并复用同一root admission。
721
886
  const mutation = toolIsMutation(tool);
722
- const result = await enrichTargetFailureWithDialogBlocker(await executeBridgeCommand(requestId, wrapper, bridgeWrapperFlags(flags, input), tool.name, rootRuntime, descriptorBinding, {
887
+ const result = await enrichTargetFailureWithDialogBlocker(await executeBridgeCommand(requestId, wrapper, bridgeWrapperFlags(flags, input), tool.name, rootRuntime, {
723
888
  mode: "execute",
724
889
  mutation,
725
890
  defaultTimeoutMs: timeoutMs,
726
891
  absoluteDeadlineMs: admission.executionAbsoluteDeadlineMs,
727
- }), flags, rootRuntime);
892
+ }), flags, rootRuntime, admission.executionAbsoluteDeadlineMs);
728
893
  if (rootResultHasTrustedTerminal(result))
729
894
  await supervisor.completeRootAdmission(admission);
730
895
  return result;
731
896
  }
732
- /** Bridge wrappers may discard supervisor details; append one independent read-only modal diagnosis to target failures. */
733
- export async function enrichTargetFailureWithDialogBlocker(result, flags, runtime, observer = new EditorBlockerObserver()) {
897
+ /** Bridge wrapper失败只在原absolute deadline内追加一次有界modal诊断。 */
898
+ export async function enrichTargetFailureWithDialogBlocker(result, flags, runtime, absoluteDeadlineMs, observer = new EditorBlockerObserver(), selectObservation = selectObservationInstanceForFlags, now = Date.now) {
734
899
  if (result.ok || (result.error.details && typeof result.error.details === "object" && Array.isArray(result.error.details.blockers)))
735
900
  return result;
901
+ const deadlineMs = Math.min(absoluteDeadlineMs, now() + 10_000);
902
+ if (deadlineMs - now() <= 0)
903
+ return result;
736
904
  try {
737
- const deadlineMs = Date.now() + 10_000;
738
- const selection = await selectObservationInstanceForFlags(flags, runtime.dataDir ?? defaultDataDir(), Math.max(0, deadlineMs - Date.now()));
905
+ const selection = await selectObservation(flags, runtime.dataDir ?? defaultDataDir(), Math.max(0, deadlineMs - now()));
906
+ if (deadlineMs - now() <= 0)
907
+ return result;
739
908
  const instance = selection.instance;
740
909
  const observation = await observer.observe({ instanceId: instance.instanceId, canonicalProjectPath: instance.canonicalProjectPath, displayProjectPath: instance.displayProjectPath }, deadlineMs, instance.activeSession);
741
910
  const blockers = observation.outcome === "observed-blocked" ? sanitizeEditorBlockers(observation.blockers) : [];
@@ -749,7 +918,7 @@ export async function enrichTargetFailureWithDialogBlocker(result, flags, runtim
749
918
  ] } };
750
919
  }
751
920
  catch {
752
- // An unproven probe must not be represented as an empty blocker list or replace the original failure.
921
+ // 未证明的诊断不能替换主错误。
753
922
  return result;
754
923
  }
755
924
  }
@@ -900,7 +1069,7 @@ function inputTooLarge(requestId, source, maxBytes) {
900
1069
  return { ok: false, error: failure(requestId, "E_CODE_INPUT_TOO_LARGE", `${source} exceeds the ${maxBytes}-byte code.exec typed-input limit.`, ["Use a smaller JSON input and keep Runtime Code source below its documented local budget."]) };
901
1070
  }
902
1071
  function inputDeadlineExceeded(requestId) {
903
- return { ok: false, error: failure(requestId, "E_EXECUTION_TIMEOUT", "code.exec typed input did not finish reading before the immutable deadline.", ["Provide bounded input from a responsive local source or submit a new request with a sufficient timeout."]) };
1072
+ return { ok: false, error: failure(requestId, "E_EXECUTION_TIMEOUT", "Tool typed input did not finish reading before the immutable admission deadline.", ["Provide bounded input from a responsive local source or submit a new request with a sufficient timeout."]) };
904
1073
  }
905
1074
  const TOOL_CONTROL_FLAGS = new Set([
906
1075
  "input", "input-file", "stdin", "pretty", "format",