@volter/editor-core 0.5.57

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 (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,810 @@
1
+ import {
2
+ type ActiveDocumentCapture,
3
+ type CaptureDimensions,
4
+ EDITOR_VIEW_DOCUMENT_KINDS,
5
+ EDITOR_VIEW_KEYS,
6
+ EDITOR_VIEW_TOOL_UTILITY_PREFIX,
7
+ type EditorView,
8
+ editorViewUrl,
9
+ isEditorViewDocumentKind,
10
+ type PresentedEditorView,
11
+ type ShadingMode,
12
+ } from '@volter/editor-sdk';
13
+ import type { StoryRef } from '@volter/editor-project/adapter';
14
+ import { getActiveAuthoring } from './authoring/active-adapter';
15
+ import {
16
+ object3DDocumentSession,
17
+ prepareObject3DDocument,
18
+ } from './authoring/object3d-document-session-registry';
19
+ import { openRegisteredDocumentAsync, registeredDocumentOpenerIds } from './document-open-registry';
20
+ import { currentEditorView } from './editor-current-view';
21
+ import { activeDocumentContainer } from './editor-document-probe';
22
+ import type { EditorShellStore } from './editor-shell-store';
23
+ import { activeEditorKeymap } from './keymap-presets';
24
+ import { liveFrameCanvas, liveInstanceContainer } from './live-session-registry';
25
+ import { projectDocumentKinds } from './project-shape';
26
+ import { DOCUMENT_REGISTRATION_TIMEOUT_MS, waitUntil } from './wait-until';
27
+ import { GAME_DOCUMENT_ID } from './workspace-document-ids';
28
+ import {
29
+ activateWorkspaceDocument,
30
+ activeWorkspaceDocument,
31
+ activeWorkspaceDocumentId,
32
+ workspaceDocumentSelection,
33
+ } from './workspace-document-registry';
34
+ import {
35
+ activeWorkspaceStaticPanel,
36
+ showWorkspaceStaticPanel,
37
+ showWorkspaceUtility,
38
+ } from './workspace-host-commands';
39
+ import {
40
+ activeEditorWorkspace,
41
+ editorWorkspaceIds,
42
+ isEditorWorkspaceId,
43
+ setEditorWorkspace,
44
+ whenEditorWorkspaceApplied,
45
+ } from './workspace-presets';
46
+ import { WORKSPACE_STATIC_PANELS, type WorkspaceStaticPanelKind } from './workspace-static-panels';
47
+ import { applyWorkspaceStyle, workspaceStyles } from './workspace-style';
48
+ import {
49
+ availableWorkspaceUtilities,
50
+ subscribeWorkspaceUtilities,
51
+ } from './workspace-utility-registry';
52
+ import {
53
+ activateRootDocument,
54
+ rootDocumentGap,
55
+ workspaceDocumentGap,
56
+ } from './world-document-routing';
57
+
58
+ async function captureLiveCanvasFrame(
59
+ canvas: HTMLCanvasElement,
60
+ ): Promise<CanvasImageSource | null> {
61
+ const { liveCanvasFrame } = await import('./live-canvas-frame');
62
+ return liveCanvasFrame(canvas);
63
+ }
64
+
65
+ /**
66
+ * THE TWO LAZY DOORS, and the reason they are lazy rather than plain imports:
67
+ * THIS FILE IS A DOOR EVERY PACKAGE CALLS (`packages/blender/host/
68
+ * blender-runtime-host.ts:32` imports `presentEditorView`), so whatever it
69
+ * reaches statically, a package that merely wants to present a view PAYS FOR.
70
+ * Measured 2026-09-18 (phase 1 unit 14): after the five document families left
71
+ * for the registry, these two edges were the WHOLE remainder of the game realm
72
+ * shim in this closure — `composite-screenshot` → the two game-CSS scopers,
73
+ * and `tool-loader` → `browser-project-scripts` → `browser-transpile` →
74
+ * `gated-globals` and the six realm modules behind it, plus
75
+ * `creation-site-registry` and (via `account.ts`) `editor-session-attribution`.
76
+ * Neither belongs to PRESENTING anything: one is the capture path for the Game
77
+ * document, the other is the project-tool discovery a LATE utility address
78
+ * drives. Both call sites are already async, and both modules are eagerly
79
+ * loaded by the shell itself long before either runs, so the import resolves
80
+ * from cache. `captureLiveCanvasFrame` above is the precedent this transcribes.
81
+ */
82
+ async function captureComposite(
83
+ ...args: Parameters<typeof import('./composite-screenshot').capturePlayComposite>
84
+ ) {
85
+ const { capturePlayComposite } = await import('./composite-screenshot');
86
+ return capturePlayComposite(...args);
87
+ }
88
+
89
+ async function projectToolContributions() {
90
+ return import('./tool-loader');
91
+ }
92
+
93
+ /**
94
+ * THE THIRD LAZY DOOR, for the same reason and by the same precedent as the
95
+ * two above — and it is the one the unit's own measurement missed. After the
96
+ * families left and those two edges went lazy, this file still reached TWO
97
+ * files of the four buckets phase 1 item 13 named, not one: the notice module
98
+ * is `collaboration and presence` by the inventory's own bucket, imported here
99
+ * statically since long before the cut. The other,
100
+ * `editor-session-attribution`, arrives `keymap-presets -> settings-store ->
101
+ * api/settings -> storage/index -> http-storage` — the storage backend's own
102
+ * edge, a 'keep' chain, and the collaboration package's question.
103
+ *
104
+ * The precondition the precedent requires holds: `AppRoot ->
105
+ * DefaultEditorLayout -> AgentPresentationNotice` loads this module at boot,
106
+ * so in a real editor the import resolves from cache, and the call site is
107
+ * already async. Notifying is not PRESENTING: a package that calls this door
108
+ * must not carry the shell's notice surface to do it.
109
+ */
110
+ async function presentationNotice() {
111
+ return import('./editor-presentation-notice');
112
+ }
113
+
114
+ const SCENE_MODES = new Set<ShadingMode>([
115
+ 'solid',
116
+ 'clay',
117
+ 'unlit',
118
+ 'wireframe',
119
+ 'normals',
120
+ 'overdraw',
121
+ ]);
122
+
123
+ /**
124
+ * Reveal the bottom-drawer utility a view names — the ONE door onto the
125
+ * drawer, routing to the same `showWorkspaceUtility` reveal a menu click uses.
126
+ *
127
+ * Every id names a utility id, and a `tool:` one names a tab a PACKAGE or the
128
+ * OPEN PROJECT contributes (`tool-loader.ts` registers each
129
+ * `workspace.utility` contribution as `tool:<contribution-id>` in the
130
+ * registry's `project` cluster). Which of those exist depends entirely on
131
+ * what is installed, so existence is checked HERE, against the live registry:
132
+ * `showWorkspaceUtility` silently ignores an id it cannot find, which is
133
+ * precisely the "the door did nothing and said nothing" failure this door
134
+ * exists to prevent.
135
+ */
136
+ function waitForWorkspaceUtility(id: string, timeoutMs = 5_000): Promise<void> {
137
+ if (availableWorkspaceUtilities().some((item) => item.id === id)) return Promise.resolve();
138
+ return new Promise((resolve) => {
139
+ let timeout = 0;
140
+ let unsubscribe = () => {};
141
+ const finish = () => {
142
+ clearTimeout(timeout);
143
+ unsubscribe();
144
+ resolve();
145
+ };
146
+ unsubscribe = subscribeWorkspaceUtilities(() => {
147
+ if (availableWorkspaceUtilities().some((item) => item.id === id)) finish();
148
+ });
149
+ if (availableWorkspaceUtilities().some((item) => item.id === id)) finish();
150
+ else timeout = window.setTimeout(finish, timeoutMs);
151
+ });
152
+ }
153
+
154
+ async function revealUtility(utility: EditorView['utility']): Promise<void> {
155
+ if (!utility) return;
156
+ if (!availableWorkspaceUtilities().some((item) => item.id === utility)) {
157
+ // A cold Vite graph can register the project catalog before its
158
+ // contribution modules finish loading — the same race the `tool` ADDRESS
159
+ // resolves in its own `settle`, by driving the owning discovery pass
160
+ // rather than racing it.
161
+ const contributed = utility.startsWith(EDITOR_VIEW_TOOL_UTILITY_PREFIX);
162
+ if (contributed) {
163
+ await (await projectToolContributions()).refreshProjectToolContributions();
164
+ // Discovery can already have started another refresh. The pass above
165
+ // then yields to that newer epoch rather than publishing stale results;
166
+ // wait for its registry publication before deciding the deep link is
167
+ // broken. This is event-driven and bounded so a genuinely absent tool
168
+ // still gets the teaching error below.
169
+ await waitForWorkspaceUtility(utility);
170
+ }
171
+ if (!availableWorkspaceUtilities().some((item) => item.id === utility)) {
172
+ const registered = availableWorkspaceUtilities().map((item) => item.id);
173
+ const hint = contributed
174
+ ? (await projectToolContributions()).contributionFailureHint(
175
+ utility.slice(EDITOR_VIEW_TOOL_UTILITY_PREFIX.length),
176
+ )
177
+ : '';
178
+ throw new Error(
179
+ `Utility is not registered: ${utility}.` +
180
+ hint +
181
+ ` Registered utilities: ${registered.length > 0 ? registered.join(', ') : '(none)'}.` +
182
+ ' A project contributes one by exporting a `workspace.utility` tool contribution;' +
183
+ ' its view id is `tool:<contribution-id>`.',
184
+ );
185
+ }
186
+ }
187
+ showWorkspaceUtility(utility);
188
+ }
189
+
190
+ /**
191
+ * Focus a static workspace panel by key — the ONE resolution behind the
192
+ * session verb (`show-panel`) and a view's `panel`, routing to the same
193
+ * `showWorkspaceStaticPanel` reveal the Window menu's own items use.
194
+ *
195
+ * The vocabulary is read from the static-panel REGISTRY at call time, never
196
+ * kept by hand here: a door with its own list is how `showPanel` came to know
197
+ * five names and none of the seven panels a human can click. An unknown key
198
+ * refuses naming the keys the registry holds; a key the registry holds but
199
+ * this layout does not show (the Inspector under its compact presentation,
200
+ * the Conversations panel with the harness collapsed) refuses saying so,
201
+ * because a silent no-op is the same failure one layer in.
202
+ */
203
+ export async function revealStaticPanel(panel: string): Promise<WorkspaceStaticPanelKind> {
204
+ const kinds = WORKSPACE_STATIC_PANELS.map((entry) => entry.kind);
205
+ const kind = kinds.find(
206
+ (candidate): candidate is WorkspaceStaticPanelKind => candidate === panel,
207
+ );
208
+ if (!kind) {
209
+ throw new Error(`"${panel}" is not a panel of this editor. Panels: ${kinds.join(', ')}.`);
210
+ }
211
+ showWorkspaceStaticPanel(kind);
212
+ if (!(await waitUntil(() => activeWorkspaceStaticPanel() === kind))) {
213
+ throw new Error(
214
+ `The ${kind} panel is not in this workspace's layout, so it could not be focused. ` +
215
+ `Panels: ${kinds.join(', ')}.`,
216
+ );
217
+ }
218
+ return kind;
219
+ }
220
+
221
+ type ViewDocument<K extends NonNullable<EditorView['document']>['kind']> = Extract<
222
+ NonNullable<EditorView['document']>,
223
+ { kind: K }
224
+ >;
225
+
226
+ /**
227
+ * Reveal the workspace scene document.
228
+ *
229
+ * `path` is purely PROVENANCE here — the active adapter's persistence
230
+ * destination, whatever its format — so restoring this view activates the
231
+ * scene surface and lets its adapter own what is on it. Nothing fetches or
232
+ * parses the path.
233
+ */
234
+ function openSceneView(_store: EditorShellStore, _document: ViewDocument<'scene'>) {
235
+ activateWorkspaceDocument('workspace:scene');
236
+ return 'workspace:scene';
237
+ }
238
+
239
+ /**
240
+ * Reveal the edit-time document that owns a manifest root.
241
+ *
242
+ * The wait is for the BOOT RACE — a root's document is installed
243
+ * asynchronously, and an explicit view is durable intent, so a document that is
244
+ * merely late must still land. It is NOT a way to discover that a root has no
245
+ * document at all: `rootDocumentGap` is that answer, registered by whoever owns
246
+ * the decision, and it ends the wait the moment it exists.
247
+ *
248
+ * MEASURED, and the reason this branch exists: a `dom` root in a project with
249
+ * no UI board sat here for the full registration window and then threw the
250
+ * generic "not registered" — by which time the asking side (the eval relay
251
+ * gives up at ~5 s) had already reported a timeout against an unresponsive
252
+ * page. The truth was decided within the first second and nobody ever heard it.
253
+ */
254
+ async function openRootView(document: ViewDocument<'world'>) {
255
+ let activated = false;
256
+ await waitUntil(() => {
257
+ activated = activateRootDocument(document.id);
258
+ return activated || rootDocumentGap(document.id) !== null;
259
+ }, DOCUMENT_REGISTRATION_TIMEOUT_MS);
260
+ if (activated) return activeWorkspaceDocumentId();
261
+ const gap = rootDocumentGap(document.id);
262
+ if (gap) throw new Error(gap);
263
+ throw new Error(`World document is not registered: ${document.id}`);
264
+ }
265
+
266
+ /**
267
+ * The board story selector (design ledger item 4): resolve the address's
268
+ * `story` against THE BOARD'S OWN provider and apply it through the same seam
269
+ * a board click uses. Unknown or ambiguous refuses loudly WITH the candidates:
270
+ * a view that silently opened the default frame would hand back a confident
271
+ * capture of the wrong story.
272
+ *
273
+ * MEASURED, AND CHANGED, 2026-09-18 (unit 11, edge 8). This used to resolve
274
+ * against the project story REGISTRY (id / export name / label) and then check
275
+ * that the board's provider would accept the id anyway — so the provider's own
276
+ * list was always the real answer and the registry read was a detour. It is
277
+ * the only story edge in this file that is not a registry question at heart:
278
+ * `StoriesProvider` is the CONTRACT and stays host. `StoryRef` carries
279
+ * `{ id, label }`, so an address may name a story by either; the one spelling
280
+ * that no longer resolves is the CSF EXPORT name where an author gave the
281
+ * story a different display name, and the refusal now lists exactly what this
282
+ * board will accept.
283
+ */
284
+ async function applyBoardStory(documentId: string, requested: string): Promise<void> {
285
+ const matching = (stories: readonly StoryRef[]) =>
286
+ stories.filter((candidate) => candidate.id === requested || candidate.label === requested);
287
+ let known: readonly StoryRef[] = [];
288
+ const reached = await waitUntil(() => {
289
+ // The BOARD's own adapter, through its registered per-document selection
290
+ // (the same seam waitForAssetDocumentInspector reads) — the store's
291
+ // active-authoring pointer may still be the previous document's, and
292
+ // applying an unknown story id there is a measured warn-and-ignore.
293
+ const provider = workspaceDocumentSelection(documentId)?.adapter?.stories;
294
+ if (!provider) return false;
295
+ known = provider.storiesFor('');
296
+ const matches = matching(known);
297
+ if (matches.length === 1) {
298
+ provider.apply(matches[0]!.id, matches[0]!.id);
299
+ return true;
300
+ }
301
+ // A provider that has listed SOMETHING has answered; waiting longer will
302
+ // not turn an unknown name into a known one.
303
+ return known.length > 0;
304
+ }, DOCUMENT_REGISTRATION_TIMEOUT_MS);
305
+ if (!reached) {
306
+ throw new Error(
307
+ `The board mounted no stories provider within the wait window; story ` +
308
+ `${JSON.stringify(requested)} was not applied.`,
309
+ );
310
+ }
311
+ const matches = matching(known);
312
+ if (matches.length === 1) return;
313
+ throw new Error(
314
+ matches.length === 0
315
+ ? `No story matches ${JSON.stringify(requested)}. This board's stories: ` +
316
+ `${known.map((candidate) => candidate.label).join(', ') || '(none)'}.`
317
+ : `${JSON.stringify(requested)} is ambiguous (${matches.length} stories match) — ` +
318
+ `use the story id: ${matches.map((candidate) => candidate.id).join(' | ')}`,
319
+ );
320
+ }
321
+
322
+ /**
323
+ * A workspace id is the ONE address with two answers, and the order is the
324
+ * point: a module that CONSTRUCTS a workspace document under that id (the
325
+ * account document, the project-tools catalog) claims it through the registry
326
+ * first; everything else is a document some other part of the session has
327
+ * already opened, which the host activates by id out of its own registry. The
328
+ * host used to spell the two constructed ids here by hand.
329
+ */
330
+ async function openWorkspaceView(store: EditorShellStore, document: ViewDocument<'workspace'>) {
331
+ const claimed = await openRegisteredDocumentAsync(document.kind, store, document);
332
+ if (claimed !== null) return claimed;
333
+ // Pinned component boards are registered from asynchronous story-media
334
+ // discovery. A URL is durable intent, so wait for the same bounded project
335
+ // bootstrap window as a manifest-world route instead of treating the first
336
+ // pre-registration read as proof that the document does not exist — and end
337
+ // that wait the instant the session can SAY the document is never coming
338
+ // (`workspaceDocumentGap`, the same seam and the same reasoning as
339
+ // `openRootView` above). MEASURED before this branch existed: a workspace id
340
+ // this project has no document for burned the whole 10 s window and then
341
+ // reported the generic "not available", by which time the eval relay had
342
+ // already given up at ~5 s and filed a `play-stall` error against a tab that
343
+ // was answering fine.
344
+ let activated = false;
345
+ await waitUntil(() => {
346
+ activated = activateWorkspaceDocument(document.id);
347
+ return activated || workspaceDocumentGap(document.id) !== null;
348
+ }, DOCUMENT_REGISTRATION_TIMEOUT_MS);
349
+ if (activated) {
350
+ if (document.story !== undefined) await applyBoardStory(document.id, document.story);
351
+ return document.id;
352
+ }
353
+ const gap = workspaceDocumentGap(document.id);
354
+ if (gap) throw new Error(gap);
355
+ throw new Error(`Workspace document is not available: ${document.id}`);
356
+ }
357
+
358
+ /**
359
+ * A VIEW ADDRESS IS AN OPENER ID. Every document kind the host does not
360
+ * construct itself is asked of `document-open-registry.ts` under its OWN kind:
361
+ * a package that can open that kind registers an opener there, and the host
362
+ * addresses the document without importing one (WORKBENCH.md §host versus
363
+ * package). A build whose package list carries no opener for the kind refuses
364
+ * by name rather than pretending — the same honest `null` an undeclared story
365
+ * medium has always given.
366
+ */
367
+ async function openDelegatedView(
368
+ store: EditorShellStore,
369
+ document: NonNullable<EditorView['document']>,
370
+ ): Promise<string> {
371
+ const opened = await openRegisteredDocumentAsync(document.kind, store, document);
372
+ if (opened === null) {
373
+ // The SUBJECT as the address spelled it — an id where the kind has one, the
374
+ // rest of the address where it does not (a story names a module and an
375
+ // export). The host does not know which fields a kind carries, so it prints
376
+ // what it was given rather than reaching for one field's name.
377
+ const { kind, ...subject } = document as { kind: string } & Record<string, unknown>;
378
+ const registered = registeredDocumentOpenerIds();
379
+ throw new Error(
380
+ `Nothing in this editor can open a '${kind}' document (${JSON.stringify(subject)}). ` +
381
+ `Either no package registered an opener for that view address, or the subject ` +
382
+ `does not exist. Registered view addresses: ` +
383
+ `${registered.length > 0 ? registered.join(', ') : '(none)'}.`,
384
+ );
385
+ }
386
+ return opened;
387
+ }
388
+
389
+ /**
390
+ * The second sentence of the refusal above, read from the PROJECT'S OWN
391
+ * document table rather than from a list written here — `project-shape`'s
392
+ * supplier is the resolved table's kinds, which is what makes "model" an
393
+ * answerable mistake instead of an unknown word.
394
+ */
395
+ function documentKindAdvice(kind: string): string {
396
+ const kinds = projectDocumentKinds();
397
+ if (kinds === null) return '';
398
+ if (kinds.includes(kind)) {
399
+ return (
400
+ `"${kind}" is a kind in this project's document table, not an address — a document opens ` +
401
+ `in the editor registered for its KIND, so address it as ` +
402
+ `{ kind: "document", id: "<that table entry's id>" }.`
403
+ );
404
+ }
405
+ if (kinds.length === 0) return '';
406
+ return (
407
+ `This project's document table holds ${kinds.map((one) => `"${one}"`).join(', ')}; ` +
408
+ 'each opens as { kind: "document", id: "<the table entry\'s id>" }.'
409
+ );
410
+ }
411
+
412
+ async function openRequestedDocument(
413
+ store: EditorShellStore,
414
+ document: EditorView['document'],
415
+ ): Promise<string | null> {
416
+ if (!document) return activeWorkspaceDocumentId();
417
+ // AN UNRECOGNIZED KIND IS A REFUSAL, exactly as an unrecognized KEY is
418
+ // (`presentEditorView`'s own note). The switch below is exhaustive over the
419
+ // published union, so TypeScript is satisfied — and at RUNTIME a kind outside
420
+ // it fell off the end, returned `undefined`, and presented `ok` having moved
421
+ // nothing, with `view.doc=undefined` in the url it handed back as
422
+ // confirmation. Measured on `{kind: 'model', path: …}`, which is the most
423
+ // likely mistake there is: `model` IS a real kind, of a row in the project's
424
+ // document table, and a table row's address is `{kind: 'document', id}`.
425
+ if (!isEditorViewDocumentKind(document.kind)) {
426
+ throw new Error(
427
+ `present-view does not know the document kind "${String(document.kind)}". ` +
428
+ `An EditorView addresses a document by one of: ${EDITOR_VIEW_DOCUMENT_KINDS.join(', ')}. ` +
429
+ documentKindAdvice(String(document.kind)),
430
+ );
431
+ }
432
+ switch (document.kind) {
433
+ // THE HOST'S OWN TWO, and they construct nothing: the scene surface is a
434
+ // fixed workspace id, and a manifest root's document is routed by
435
+ // `world-document-routing.ts`, the seam whoever owns a root registers into.
436
+ case 'scene':
437
+ return openSceneView(store, document);
438
+ case 'world':
439
+ return openRootView(document);
440
+ // EVERY OTHER KIND IS AN ADDRESS. Resolving a story's module and export,
441
+ // what an asset extension means and when its Inspector is ready, which
442
+ // editor a table entry's KIND opens in and what that document's id turns
443
+ // out to be, which contribution a tool id names — all of it is the kind's
444
+ // own job, answered through `document-open-registry.ts` by whichever
445
+ // module (host family or package) registered that address. The switch
446
+ // stays exhaustive because the ADDRESS SPACE is `@volter/editor-sdk`'s
447
+ // `EditorView`, published and finite; the implementations are not the
448
+ // host's.
449
+ case 'asset':
450
+ case 'tool':
451
+ case 'document':
452
+ case 'story':
453
+ case 'project-tool':
454
+ case 'generation':
455
+ return openDelegatedView(store, document);
456
+ case 'workspace':
457
+ return openWorkspaceView(store, document);
458
+ }
459
+ }
460
+
461
+ function captureDataUrl(dataUrl: string): Pick<ActiveDocumentCapture, 'base64' | 'mimeType'> {
462
+ const comma = dataUrl.indexOf(',');
463
+ return { base64: comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl, mimeType: 'image/png' };
464
+ }
465
+
466
+ /** The capture and the scoped probe (`editor-document-probe.ts`) must never
467
+ * disagree about which element IS the active document, so they share one
468
+ * lookup rather than two copies of the same query. */
469
+ const activeDocumentContent = activeDocumentContainer;
470
+
471
+ /**
472
+ * A BLACK FRAME IS NOT AN ANSWER — the refusal text when a document holding a
473
+ * live three ingest's own canvas photographs blank, or `null` when it did not.
474
+ *
475
+ * MEASURED (`vgai doctor public/ingest/three-clipping-intersection`): the Game
476
+ * document came back "~100% one flat surface (#000000)" and the walk filed it
477
+ * as that ingestion's play evidence until the flatness measure caught it.
478
+ *
479
+ * The mechanism is NOT that the document is empty — an ingested three game's
480
+ * own canvas IS mounted in it. It is that the canvas is the GAME'S, created
481
+ * without `preserveDrawingBuffer`, so its pixels are readable only from inside
482
+ * the game's own render pass (`ingest/ingest-frame-snapshot.ts` arms exactly
483
+ * that bracket). When the game does not draw inside the snapshot window — a
484
+ * render-on-demand world sitting idle, or a loop the Edit-tab input gate has
485
+ * frozen — the read falls back to a late `drawImage` and the browser hands
486
+ * back the discarded buffer: black, silently, in a PNG that looks like a real
487
+ * photograph.
488
+ *
489
+ * Gated on the composite's OWN degeneracy rather than on the route alone: a
490
+ * three ingest that IS drawing photographs correctly through this door and
491
+ * must keep doing so.
492
+ */
493
+ function ingestBlankFrameRefusal(
494
+ documentId: string,
495
+ content: Element,
496
+ flatness: { degenerate: boolean; warning?: string } | undefined,
497
+ ): string | null {
498
+ if (!flatness?.degenerate) return null;
499
+ const gameCanvas = liveFrameCanvas();
500
+ if (!gameCanvas || !content.contains(gameCanvas)) return null;
501
+ return (
502
+ `This door photographs the "${documentId}" document, which for a live three ingest holds the ` +
503
+ "GAME'S own canvas — created without `preserveDrawingBuffer`, so its pixels can only be read " +
504
+ "from inside the game's own render pass. This game did not draw inside that window (a " +
505
+ 'render-on-demand world sitting idle, or a loop the Edit-tab input gate has frozen), so the ' +
506
+ `frame came back BLANK (${flatness.warning ?? 'essentially one flat colour'}) — a PNG that reads ` +
507
+ "as a real image. The editor's own renderer is drawing this same world in the Scene viewport " +
508
+ '(the mount adopts the captured scene), so capture `workspace:scene` instead — or drive the ' +
509
+ 'game until it renders and ask again.'
510
+ );
511
+ }
512
+
513
+ /**
514
+ * Capture the active center subject through its native session when one
515
+ * exists, otherwise through the common mounted-document surface.
516
+ *
517
+ * `size` is a square by default and `{width, height}` when a caller wants a
518
+ * shaped frame ({@link CaptureDimensions}). The Object3D document session
519
+ * renders its buffer and camera at that aspect. Composite captures (Scene,
520
+ * Game and DOM documents) photograph the mounted panel at its own size,
521
+ * including its visible overlays, and do not use `size`.
522
+ */
523
+ export async function captureActiveEditorDocument(
524
+ store: EditorShellStore,
525
+ size?: CaptureDimensions,
526
+ ): Promise<ActiveDocumentCapture> {
527
+ const active = activeWorkspaceDocument();
528
+ if (!active) throw new Error('No active editor document to capture.');
529
+ const { descriptor, title } = active;
530
+ const view = currentEditorView(store);
531
+ const documentInfo = {
532
+ id: descriptor.id,
533
+ title,
534
+ kind: descriptor.kind,
535
+ ...(descriptor.provenance?.sourcePath ? { sourcePath: descriptor.provenance.sourcePath } : {}),
536
+ ...(descriptor.provenance?.rootId ? { rootId: descriptor.provenance.rootId } : {}),
537
+ };
538
+ const session = object3DDocumentSession(descriptor.id);
539
+ if (session) {
540
+ const dataUrl = session.captureImage(size);
541
+ if (!dataUrl) throw new Error(`Object3D document could not be captured: ${descriptor.id}`);
542
+ return {
543
+ ...captureDataUrl(dataUrl),
544
+ document: documentInfo,
545
+ view,
546
+ source: 'object3d-document',
547
+ };
548
+ }
549
+ // THE GAME DOCUMENT'S SUBJECT IS THE GAME STACK, not the dock panel holding
550
+ // it — `getInstanceContainer()`, exactly what `bridge-screenshot` photographs.
551
+ //
552
+ // MEASURED (canvas ingest, `flappy`): capturing the PANEL put 64% of the
553
+ // frame at alpha 0. `composite-screenshot.ts`'s overlay leg clones the
554
+ // container's CHILDREN into a neutral wrapper, so from the panel those
555
+ // children are editor-CSS-classed layout divs whose styling a detached
556
+ // serialization drops — the game's own surface then lays out against the
557
+ // wrong containing block and contributes nothing, leaving a hole wherever
558
+ // the canvas leg did not draw. From the runtime container the game's surface
559
+ // IS the child, its inline box survives the clone, and the frame is opaque.
560
+ //
561
+ // It also removes a whole class of defect on its own: two doors onto the same
562
+ // pixels that photograph two different elements will disagree, and a reader
563
+ // has no way to tell which one is the game.
564
+ const content =
565
+ descriptor.id === GAME_DOCUMENT_ID
566
+ ? (liveInstanceContainer() ?? activeDocumentContent(descriptor.id))
567
+ : activeDocumentContent(descriptor.id);
568
+ if (!content) throw new Error(`Active document surface is not mounted: ${descriptor.id}`);
569
+ // `liveCanvasFrame` answers only for a canvas some live surface owns — a
570
+ // registered Pixi `Application` (the `2D` board's exhibits, the first-party
571
+ // canvas root, a canvas ingest) or the three ingest mount's own canvas;
572
+ // every other canvas takes the seam's documented "read it directly" path, so
573
+ // this is inert for every document that presents neither. Without it those
574
+ // canvases photograph blank — a game's own canvas has no
575
+ // `preserveDrawingBuffer`, and this read happens well after its frame. It is
576
+ // the SAME seam `bridge-screenshot` passes, deliberately: two doors onto the
577
+ // same pixels that disagree about which lane they can see is exactly the
578
+ // defect (`live-canvas-frame.ts`).
579
+ const composite = await captureComposite(content, {
580
+ canvasFrame: captureLiveCanvasFrame,
581
+ // The Game document's subject is the game stack and must never inherit
582
+ // editor CSS. Every other composite subject is an editor-owned document;
583
+ // its design-system classes are part of what the user is looking at.
584
+ includeDocumentStyles: descriptor.id !== GAME_DOCUMENT_ID,
585
+ });
586
+ // A blank frame over a live three ingest is REFUSED with its mechanism named
587
+ // rather than handed back as a photograph — see `ingestBlankFrameRefusal`.
588
+ const blank = ingestBlankFrameRefusal(descriptor.id, content, composite.flatness);
589
+ if (blank) throw new Error(blank);
590
+ return {
591
+ base64: composite.base64,
592
+ mimeType: composite.mimeType,
593
+ document: documentInfo,
594
+ view,
595
+ source:
596
+ descriptor.id === GAME_DOCUMENT_ID
597
+ ? 'game-composite'
598
+ : descriptor.id === 'workspace:scene'
599
+ ? 'scene-viewport'
600
+ : 'document-composite',
601
+ layers: composite.layers,
602
+ // The composite already MEASURES whether what it grabbed is a flat,
603
+ // contentless frame (`sampleFlatness`), and `ActiveDocumentCapture`
604
+ // declares the field — this door simply dropped it, so a blank-white
605
+ // headless play frame came back through it looking exactly like a good
606
+ // one. `vgai doctor` files that frame as an ingestion's evidence, so a
607
+ // degenerate capture that cannot say so is a capture that lies.
608
+ ...(composite.flatness ? { flatness: composite.flatness } : {}),
609
+ };
610
+ }
611
+
612
+ type ObjectSession = NonNullable<ReturnType<typeof object3DDocumentSession>>;
613
+
614
+ /**
615
+ * WHICH STAGE THIS VIEW DRIVES — a plain lookup, and deliberately nothing else.
616
+ *
617
+ * A kind declares when its document is ready to be DRIVEN in its own opener's
618
+ * `ready` (`document-open-registry.ts`), and the registry awaits it inside the
619
+ * open `openRequestedDocument` has already performed above. So by the moment
620
+ * this reads, a document that mounts a stage has one, and a document that
621
+ * mounts none never will: there is nothing left here to wait for and no way
622
+ * for this file to know what a wait would even be waiting on. A view asking
623
+ * for a selection or a viewport on a session-less document takes the
624
+ * store-level path `applyGrid` and `applyDiagnostic` already take for it.
625
+ */
626
+ function resolveObjectSession(documentId: string | null): ObjectSession | null {
627
+ return documentId ? object3DDocumentSession(documentId) : null;
628
+ }
629
+
630
+ function applyGrid(store: EditorShellStore, session: ObjectSession | null, grid?: boolean): void {
631
+ if (grid === undefined) return;
632
+ if (session) session.setGrid(grid);
633
+ else if (store.showGrid !== grid) store.toggleGrid();
634
+ }
635
+
636
+ function applyDiagnostic(
637
+ store: EditorShellStore,
638
+ session: ObjectSession | null,
639
+ diagnostic: NonNullable<EditorView['viewport']>['diagnostic'],
640
+ warnings: string[],
641
+ ): void {
642
+ if (!diagnostic) return;
643
+ if (session) {
644
+ session.setSkeleton(diagnostic === 'skeleton');
645
+ session.setBounds(diagnostic === 'bounds');
646
+ if (diagnostic === 'skeleton' || diagnostic === 'bounds') {
647
+ session.setMode('solid');
648
+ } else {
649
+ session.setMode(diagnostic);
650
+ }
651
+ } else if (SCENE_MODES.has(diagnostic as ShadingMode))
652
+ store.setShadingMode(diagnostic as ShadingMode);
653
+ else warnings.push(`Diagnostic ${diagnostic} is unavailable for this document.`);
654
+ }
655
+
656
+ function applyCamera(
657
+ store: EditorShellStore,
658
+ session: ObjectSession | null,
659
+ camera: NonNullable<EditorView['viewport']>['camera'],
660
+ warnings: string[],
661
+ ): void {
662
+ if (!camera) return;
663
+ if (typeof camera !== 'string') {
664
+ if (session) session.setCameraPose(camera.position, camera.target, camera.fov);
665
+ else store.setCameraPose(camera.position, camera.target, camera.fov);
666
+ return;
667
+ }
668
+ if (session && camera === 'perspective') {
669
+ session.setProjection('perspective');
670
+ session.frame();
671
+ } else if (session && camera !== 'perspective') session.setViewPreset(camera);
672
+ else if (camera !== 'isometric') store.setViewPreset(camera);
673
+ else warnings.push('Isometric camera is unavailable for this document.');
674
+ }
675
+
676
+ function applyFraming(
677
+ store: EditorShellStore,
678
+ session: ObjectSession | null,
679
+ view: EditorView,
680
+ warnings: string[],
681
+ ): void {
682
+ if (view.selection?.focus || view.viewport?.frame === 'selection') {
683
+ if (session && !session.frameSelection()) {
684
+ warnings.push('The requested selection could not be framed.');
685
+ } else if (!session) store.focusOnSelection();
686
+ } else if (view.viewport?.frame === 'document') {
687
+ if (session) session.frame();
688
+ else warnings.push('Document framing is unavailable for this document.');
689
+ }
690
+ }
691
+
692
+ function applyPresentation(
693
+ store: EditorShellStore,
694
+ session: ObjectSession | null,
695
+ view: EditorView,
696
+ warnings: string[],
697
+ ): void {
698
+ if (view.selection) {
699
+ if (session) session.select(view.selection.ids);
700
+ else store.selectMultiple(view.selection.ids);
701
+ }
702
+ applyGrid(store, session, view.viewport?.grid);
703
+ applyDiagnostic(store, session, view.viewport?.diagnostic, warnings);
704
+ applyCamera(store, session, view.viewport?.camera, warnings);
705
+ applyFraming(store, session, view, warnings);
706
+ }
707
+
708
+ /**
709
+ * The one imperative presenter behind both the agent wire command and URL
710
+ * restoration. It applies semantic intent to the current workspace layout;
711
+ * it never encodes physical coordinates.
712
+ */
713
+ export async function presentEditorView(
714
+ store: EditorShellStore,
715
+ view: EditorView,
716
+ options: { updateUrl?: boolean; origin?: 'agent' | 'link' | 'return' } = {},
717
+ ): Promise<PresentedEditorView> {
718
+ if (view?.version !== 1) throw new Error('present-view requires EditorView version 1.');
719
+ // AN UNRECOGNIZED KEY IS A REFUSAL, not a silent pass-through. Every named
720
+ // field below refuses by name; an unnamed one used to be ignored AND echoed
721
+ // back in the answer, so `{version: 1, kind: 'story', …}` — the document's
722
+ // address spelled one level too high — presented `ok`, moved nothing, and
723
+ // handed the caller its own mistake as confirmation (found live, unit 17).
724
+ // The vocabulary is `@volter/editor-sdk`'s `EDITOR_VIEW_KEYS`, published and
725
+ // finite, so the refusal can be complete.
726
+ const unknown = Object.keys(view).filter(
727
+ (key) => !(EDITOR_VIEW_KEYS as readonly string[]).includes(key),
728
+ );
729
+ if (unknown.length > 0) {
730
+ throw new Error(
731
+ `present-view does not know ${unknown.map((key) => `"${key}"`).join(', ')}. ` +
732
+ `An EditorView carries: ${EDITOR_VIEW_KEYS.join(', ')}. ` +
733
+ `A document's own address (kind, and the fields that kind reads) goes under "document".`,
734
+ );
735
+ }
736
+ const previousView = currentEditorView(store);
737
+ // The style bundle, if named: chrome appearance only, refused by name the
738
+ // way `set-style` refuses — never a silent no-op.
739
+ if (view.style !== undefined) {
740
+ const ids = workspaceStyles().map((bundle) => bundle.id);
741
+ if (!ids.includes(view.style)) {
742
+ throw new Error(
743
+ `present-view requires a style of ${ids.join(', ')}, got ${String(view.style)}.`,
744
+ );
745
+ }
746
+ applyWorkspaceStyle(view.style);
747
+ }
748
+ // The workspace first: a layout decides which documents and utilities the
749
+ // rest of the view can reach. An id the open project does not offer refuses
750
+ // by name, the same sentence as `set-workspace` — never a silent no-op.
751
+ if (view.workspace !== undefined) {
752
+ if (!isEditorWorkspaceId(view.workspace)) {
753
+ throw new Error(
754
+ `present-view requires a workspace of ${editorWorkspaceIds().join(', ')}, got ${String(view.workspace)}.`,
755
+ );
756
+ }
757
+ if (activeEditorWorkspace() !== view.workspace) {
758
+ const rebuilt = whenEditorWorkspaceApplied();
759
+ setEditorWorkspace(view.workspace);
760
+ await Promise.race([rebuilt, new Promise<void>((resolve) => setTimeout(resolve, 3000))]);
761
+ }
762
+ }
763
+ const warnings: string[] = [];
764
+ // The keymap is REPORTED, not presented (see `EditorView.keymap`): a link
765
+ // carrying one says so out loud instead of silently rewriting the bindings
766
+ // of whoever opens it.
767
+ if (view.keymap !== undefined && view.keymap !== activeEditorKeymap()) {
768
+ warnings.push(
769
+ `Keymap "${view.keymap}" was not applied — a view reports the keymap, it does not set it. ` +
770
+ `This project is on "${activeEditorKeymap()}" (its adapter's declaration, or its own settings).`,
771
+ );
772
+ }
773
+ const documentId = await openRequestedDocument(store, view.document);
774
+ await revealUtility(view.utility);
775
+ const session = resolveObjectSession(documentId);
776
+ if (session && documentId) await prepareObject3DDocument(documentId);
777
+ // A shared scene/world link can arrive before the source-backed hierarchy
778
+ // mounts. Applying selection to that empty shell loses it when the world is
779
+ // adopted. Wait for the owning adapter to expose the requested identities.
780
+ if (
781
+ !session &&
782
+ view.selection?.ids.length &&
783
+ (view.document?.kind === 'scene' || view.document?.kind === 'world')
784
+ ) {
785
+ const ids = view.selection.ids;
786
+ const ready = await waitUntil(
787
+ () => ids.every((id) => getActiveAuthoring(store).hierarchy.node(id) !== null),
788
+ DOCUMENT_REGISTRATION_TIMEOUT_MS,
789
+ );
790
+ if (!ready) throw new Error(`Shared view selection is not available: ${ids.join(', ')}`);
791
+ }
792
+ // Utility layout reconciliation may restore focus to the previous center
793
+ // tab while an async Object3D document is mounting. Presentation is atomic:
794
+ // after that mount settles, the requested document must be the active one.
795
+ if (documentId && activeWorkspaceDocumentId() !== documentId) {
796
+ activateWorkspaceDocument(documentId);
797
+ }
798
+ applyPresentation(store, session, view, warnings);
799
+ // The panel LAST: opening a document and reconciling the utility drawer both
800
+ // take the dock's focus, so a view naming a panel must END on it.
801
+ if (view.panel !== undefined) await revealStaticPanel(view.panel);
802
+
803
+ const url = editorViewUrl(view, window.location.href);
804
+ if (options.updateUrl !== false) window.history.replaceState(window.history.state, '', url);
805
+ const presented = { view, url, warnings };
806
+ if ((options.origin ?? 'agent') === 'agent') {
807
+ (await presentationNotice()).showEditorPresentationNotice({ presented, previousView });
808
+ }
809
+ return presented;
810
+ }