@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,563 @@
1
+ import type { EditorControlLifecycle } from '@volter/editor-sdk/session/editor-control-lifecycle';
2
+ import { COMMAND_RESULT_RECEIPT_EVENT } from '@volter/editor-sdk/session/editor-control-protocol';
3
+ import { isCancellationReason } from './cancellation-reason';
4
+ // Type-only: erased at compile, so the pre-React bootstrap module stays
5
+ // dependency-light while the channel vocabulary keeps ONE owner.
6
+ import type { LeaseChannelState } from './editor-lease';
7
+ import {
8
+ COLLABORATION_PARTICIPANT_ID,
9
+ COLLABORATION_PARTICIPANT_NAME,
10
+ } from './editor-session-attribution';
11
+ import { onSessionEndedChange } from './session-tombstone';
12
+ import type { TabCensus } from './tab-census';
13
+ import { type EditorTabRoute, installTabLifecycleListeners } from './tab-lifecycle-client';
14
+
15
+ const BASE = '/__editor';
16
+
17
+ interface EditorPresenceBootstrap {
18
+ clientId: string;
19
+ participantId: string;
20
+ displayName: string;
21
+ /**
22
+ * This TAB's identity (sessionStorage, survives reloads) and this
23
+ * page-load's `epoch`. Minted by the inline bootstrap, which also starts
24
+ * the heartbeat worker that proves the tab to the server — see
25
+ * `server/tab-presence.ts`. Absent only where there is no inline bootstrap
26
+ * at all (browser-mode builds, jsdom tests).
27
+ */
28
+ tabId?: string;
29
+ epoch?: string;
30
+ /** The generation record most recently accepted by the server. */
31
+ controlLifecycle?: EditorControlLifecycle | null;
32
+ /**
33
+ * Hand this tab's resource census to the heartbeat worker, which carries it
34
+ * out on the next beat and then drops it (`server/tab-presence.ts`'s
35
+ * `TabCensus`) — one call, one sample the server files. Absent wherever the
36
+ * inline bootstrap is — browser-mode builds, jsdom tests, a tunnelled tab
37
+ * that was refused the worker script.
38
+ */
39
+ reportCensus?: (census: TabCensus) => void;
40
+ /** Hand the heartbeat worker what the page's main thread is about to do
41
+ * (`building src/models/x.ts`) or that it is done (`null`): the beat
42
+ * carries it while the page itself cannot speak. */
43
+ reportPhase?: (phase: string | null) => void;
44
+ /**
45
+ * Stop the heartbeat worker, withdrawing this tab from the server's tab
46
+ * table. The one caller is a TERMINAL session tombstone
47
+ * (`session-tombstone.ts`) — see the bootstrap's own comment in index.html
48
+ * for why a beating corpse is what this closes. Absent wherever the inline
49
+ * bootstrap is.
50
+ */
51
+ stopHeartbeat?: () => void;
52
+ source: PresenceEventSource | null;
53
+ pageOwned: boolean;
54
+ pending: Array<{ type: string; data: string }>;
55
+ queueListeners: Array<{ type: string; listener: EventListener }>;
56
+ }
57
+
58
+ type PresenceEventSource = Pick<
59
+ EventSource,
60
+ 'addEventListener' | 'removeEventListener' | 'dispatchEvent' | 'close'
61
+ > & {
62
+ /**
63
+ * Upstream control frame, present only on the duplex control socket the
64
+ * inline bootstrap builds (index.html). Returns false when this transport
65
+ * cannot carry it — an `EventSource`, or a socket the server has not
66
+ * granted duplex to (the share tunnel bridges the SSE stream one way).
67
+ *
68
+ * Type and payload are separate ARGUMENTS, never one merged object: the
69
+ * payload is open-ended (a state snapshot is whatever the editor reports),
70
+ * so sharing a namespace with the discriminator would both leak `type`
71
+ * into the state the server stores and let a payload key named `type`
72
+ * silently redirect the frame.
73
+ */
74
+ send?(type: string, payload: Record<string, unknown>): boolean;
75
+
76
+ /**
77
+ * Whether this transport's connection to the server is UP right now.
78
+ * Present only on the duplex control socket the inline bootstrap builds
79
+ * (index.html). A real `EventSource` exposes the equivalent as its numeric
80
+ * `readyState`, which `readControlChannelState` reads instead.
81
+ */
82
+ readonly connected?: boolean;
83
+ };
84
+
85
+ const bootstrapGlobal = globalThis as typeof globalThis & {
86
+ __VGAI_EDITOR_PRESENCE_BOOTSTRAP__?: EditorPresenceBootstrap;
87
+ };
88
+ const bootstrap = bootstrapGlobal.__VGAI_EDITOR_PRESENCE_BOOTSTRAP__;
89
+
90
+ export const EDITOR_CLIENT_ID =
91
+ bootstrap?.clientId ?? globalThis.crypto?.randomUUID?.() ?? `editor-${Date.now()}`;
92
+ export const EDITOR_PARTICIPANT_ID = COLLABORATION_PARTICIPANT_ID;
93
+ export const EDITOR_PARTICIPANT_NAME = COLLABORATION_PARTICIPANT_NAME;
94
+
95
+ /**
96
+ * Push this tab's resource census onto the heartbeat.
97
+ *
98
+ * A no-op wherever there is no inline bootstrap (browser-mode builds, jsdom):
99
+ * the census is diagnostics, and diagnostics that break their host are worse
100
+ * than none.
101
+ */
102
+ export function reportTabPhase(phase: string | null): void {
103
+ bootstrap?.reportPhase?.(phase);
104
+ }
105
+
106
+ export function reportTabCensus(census: TabCensus): void {
107
+ bootstrap?.reportCensus?.(census);
108
+ }
109
+
110
+ /**
111
+ * WITHDRAW THIS TAB from the server's tab table. Terminal tombstones only
112
+ * (`session-tombstone.ts`).
113
+ *
114
+ * Presence is a UNION (`server/tab-presence.ts`): a fresh BEAT **or** a live
115
+ * control channel. Both halves therefore have to go, and measured live on
116
+ * 2026-08-15, stopping only the beat was not enough — the inert page's control
117
+ * socket reconnected to the successor server on the same port, which kept the
118
+ * corpse present, blessed, and reported as `commandListener not attached`
119
+ * while `vgai edit` answered "focused" instead of opening a real tab.
120
+ *
121
+ * The channel is closed unconditionally, not by releasing a reference: this
122
+ * page is over, so there is no consumer whose refcount could legitimately hold
123
+ * it open. Both calls are no-ops where the inline bootstrap never ran (browser
124
+ * mode, jsdom), which is also where the tab was never in the table.
125
+ */
126
+ export function withdrawTabFromSession(): void {
127
+ bootstrap?.stopHeartbeat?.();
128
+ const real = sharedSource;
129
+ if (real === null) return;
130
+ sharedSource = null;
131
+ sharedRefCount = 0;
132
+ if (bootstrap?.source === real) bootstrap.source = null;
133
+ if (lifecycleSource === real) lifecycleSource = null;
134
+ try {
135
+ real.close();
136
+ } catch {
137
+ /* the socket is going away with the page regardless */
138
+ }
139
+ }
140
+
141
+ function eventsUrl(): string {
142
+ const query = new URLSearchParams({
143
+ clientId: EDITOR_CLIENT_ID,
144
+ participantId: EDITOR_PARTICIPANT_ID,
145
+ displayName: EDITOR_PARTICIPANT_NAME,
146
+ });
147
+ if (bootstrap?.tabId) query.set('tabId', bootstrap.tabId);
148
+ return `${BASE}/events?${query}`;
149
+ }
150
+
151
+ /**
152
+ * The subset of `EventSource` used by editor event consumers. `close()` only
153
+ * releases the calling consumer; one real socket is shared by the whole page.
154
+ */
155
+ export interface EditorEventSource {
156
+ addEventListener(type: string, listener: (event: MessageEvent) => void): void;
157
+ removeEventListener(type: string, listener: (event: MessageEvent) => void): void;
158
+ close(): void;
159
+ }
160
+
161
+ let sharedSource: PresenceEventSource | null = bootstrap?.source ?? null;
162
+ let sharedRefCount = bootstrap?.source && bootstrap.pageOwned ? 1 : 0;
163
+ let lifecycleSource: PresenceEventSource | null = null;
164
+
165
+ /**
166
+ * Buffered types whose replay must wait for their own consumer.
167
+ *
168
+ * The tab-* events are replayed by `installLifecycle` because
169
+ * `installTabLifecycleListeners` has just attached their listeners — the
170
+ * consumer is in place before the drain. `editor-command` is different: its
171
+ * listener is attached by `connectCommandListener`, once the whole React
172
+ * graph has loaded, long after boot. Replaying it at boot would dispatch it
173
+ * to zero listeners and lose it exactly as not buffering it did.
174
+ */
175
+ const DEFERRED_REPLAY_TYPES = new Set(['editor-command']);
176
+
177
+ /**
178
+ * Hand back the buffered events whose type `accept`s, and stop buffering
179
+ * that type — its consumer is now attached, so later events reach it
180
+ * directly. Everything else stays queued for its own consumer.
181
+ */
182
+ function drainBootstrap(source: PresenceEventSource, accept: (type: string) => boolean): void {
183
+ if (!bootstrap || bootstrap.source !== source) return;
184
+ bootstrap.queueListeners = bootstrap.queueListeners.filter(({ type, listener }) => {
185
+ if (!accept(type)) return true;
186
+ source.removeEventListener(type, listener);
187
+ return false;
188
+ });
189
+ const replay = bootstrap.pending.filter((event) => accept(event.type));
190
+ bootstrap.pending = bootstrap.pending.filter((event) => !accept(event.type));
191
+ for (const { type, data } of replay) {
192
+ source.dispatchEvent(new MessageEvent(type, { data }));
193
+ }
194
+ }
195
+
196
+ function installLifecycle(source: PresenceEventSource): void {
197
+ if (lifecycleSource === source) return;
198
+ lifecycleSource = source;
199
+ // This tab's identity rides along so `tab-close` can be ACKNOWLEDGED: the
200
+ // bootstrap global is read here and nowhere else.
201
+ installTabLifecycleListeners(source, BASE, { tabId: bootstrap?.tabId, epoch: bootstrap?.epoch });
202
+ drainBootstrap(source, (type) => !DEFERRED_REPLAY_TYPES.has(type));
203
+ }
204
+
205
+ /**
206
+ * Connect to the editor's shared SSE stream.
207
+ *
208
+ * Keeping this implementation in a dependency-light module is intentional:
209
+ * index.html imports it before the React entry so the server sees the tab even
210
+ * while Vite is still loading or optimizing the much larger editor graph.
211
+ */
212
+ export function connectEvents(): EditorEventSource {
213
+ if (!sharedSource) {
214
+ if (bootstrap?.source) {
215
+ sharedSource = bootstrap.source;
216
+ if (bootstrap.pageOwned) sharedRefCount++;
217
+ } else {
218
+ sharedSource = new EventSource(eventsUrl());
219
+ if (bootstrap) bootstrap.source = sharedSource;
220
+ }
221
+ }
222
+ const real = sharedSource;
223
+ installLifecycle(real);
224
+ sharedRefCount++;
225
+
226
+ const ownListeners: Array<{ type: string; listener: EventListener }> = [];
227
+ let released = false;
228
+
229
+ return {
230
+ addEventListener(type, listener) {
231
+ const wrapped = listener as EventListener;
232
+ real.addEventListener(type, wrapped);
233
+ ownListeners.push({ type, listener: wrapped });
234
+ // The consumer this type was buffered FOR has just arrived. Replaying
235
+ // here — rather than at boot — is the whole point of the deferral.
236
+ if (DEFERRED_REPLAY_TYPES.has(type)) drainBootstrap(real, (queued) => queued === type);
237
+ },
238
+ removeEventListener(type, listener) {
239
+ const wrapped = listener as EventListener;
240
+ real.removeEventListener(type, wrapped);
241
+ const idx = ownListeners.findIndex((item) => item.type === type && item.listener === wrapped);
242
+ if (idx >= 0) ownListeners.splice(idx, 1);
243
+ },
244
+ close() {
245
+ if (released) return;
246
+ released = true;
247
+ for (const { type, listener } of ownListeners) real.removeEventListener(type, listener);
248
+ ownListeners.length = 0;
249
+ sharedRefCount--;
250
+ if (sharedRefCount <= 0) {
251
+ real.close();
252
+ if (sharedSource === real) sharedSource = null;
253
+ // The bootstrap holds its own reference, and `connectEvents` adopts
254
+ // it before minting a socket. Leaving it pointing at the one we just
255
+ // closed would hand the next caller a dead EventSource that never
256
+ // reconnects and never errors — it would simply go quiet.
257
+ if (bootstrap?.source === real) bootstrap.source = null;
258
+ if (lifecycleSource === real) lifecycleSource = null;
259
+ sharedRefCount = 0;
260
+ }
261
+ },
262
+ };
263
+ }
264
+
265
+ /**
266
+ * Is this page's control connection to its editor server up?
267
+ *
268
+ * The supervised lease (editor-lease.ts) reads this as its SECOND liveness
269
+ * signal, independent of the HTTP poll: a fetch can fail because the browser's
270
+ * per-origin pool is saturated by a cold module flood or because the server's
271
+ * event loop is blocked, neither of which means the session is gone — but a
272
+ * dead PROCESS cannot hold this socket open. Both readings together are what
273
+ * separates "gone" from "busy".
274
+ *
275
+ * `unknown` is deliberate rather than an optimistic `open`: a transport that
276
+ * exposes no connection state (the share tunnel's one-way SSE bridge) gives no
277
+ * evidence, and absent evidence must not make the watchdog keener to keep a
278
+ * dead tab alive. The lease treats it exactly like `closed`.
279
+ */
280
+ export function readControlChannelState(): LeaseChannelState {
281
+ const source = sharedSource ?? bootstrap?.source ?? null;
282
+ if (!source) return 'unknown';
283
+ if (typeof source.connected === 'boolean') return source.connected ? 'open' : 'closed';
284
+ // A real `EventSource`: 0 CONNECTING, 1 OPEN, 2 CLOSED. Only OPEN is
285
+ // evidence — a socket mid-reconnect proves nothing about the server.
286
+ const readyState = (source as { readyState?: unknown }).readyState;
287
+ if (typeof readyState === 'number') return readyState === 1 ? 'open' : 'closed';
288
+ return 'unknown';
289
+ }
290
+
291
+ /** Hold this page's editor-session connection until its caller releases it. */
292
+ export function connectTabPresence(): () => void {
293
+ if (typeof EventSource === 'undefined') return () => {};
294
+ const events = connectEvents();
295
+ // A TERMINAL tombstone withdraws this tab from the server's table — both
296
+ // halves of the presence union. Subscribed HERE rather than inside
297
+ // `session-tombstone.ts` so that module keeps no dependencies at all (and so
298
+ // this file, which owns both doors, stays the only thing that touches them).
299
+ // `server-gone` deliberately stays present: that page may still resume onto
300
+ // the same process, and a tab that withdrew could not.
301
+ const unsubscribeTombstone = onSessionEndedChange((state) => {
302
+ if (state !== null && state.reason !== 'server-gone') withdrawTabFromSession();
303
+ });
304
+ const stopBootErrors = reportBootErrors();
305
+ return () => {
306
+ stopBootErrors();
307
+ unsubscribeTombstone();
308
+ events.close();
309
+ };
310
+ }
311
+
312
+ /** How many boot failures one page-load reports. A module that throws inside a
313
+ * retry loop must not become a firehose; the first few say what broke. */
314
+ const BOOT_ERROR_CAP = 5;
315
+
316
+ /**
317
+ * THE APP'S FIRST ERROR, reported by the layer that is already up.
318
+ *
319
+ * `installEditorConsoleCapture` hooks `error`/`unhandledrejection`, but it is
320
+ * part of the editor app -- so when the app dies during init, that hook never
321
+ * exists and the page reports NOTHING. The reporter sat downstream of the
322
+ * failure it needed to describe.
323
+ *
324
+ * MEASURED 2026-09-15: a tab beat for the better part of an hour, answered
325
+ * liveness echoes, and reported `commandListener not attached` with no page
326
+ * error and an empty `vgai console` -- so `vgai status` could say only that
327
+ * the app "never finished loading", which is the symptom, never the cause.
328
+ * Every door the CLI offers was blind to a crash before the app came up.
329
+ *
330
+ * Presence is connected by this point, so this reports through the SAME
331
+ * `console-entries` door the app uses later and lands in the same ledger
332
+ * `vgai console` reads. A duplicate once the app's own capture starts is
333
+ * deduplicated there by fingerprint.
334
+ */
335
+ function reportBootErrors(): () => void {
336
+ if (typeof window === 'undefined') return () => {};
337
+ let sent = 0;
338
+ const report = (message: string): void => {
339
+ if (message === '' || sent >= BOOT_ERROR_CAP) return;
340
+ sent += 1;
341
+ void postControl('console-entries', {
342
+ entries: [
343
+ {
344
+ id: `boot-error:${sent}`,
345
+ severity: 'error',
346
+ // Named as a BOOT failure, so a reader knows the app never came up
347
+ // rather than hunting for a console that was never going to fill.
348
+ message: `editor app failed to start: ${message}`,
349
+ source: 'runtime',
350
+ occurrences: 1,
351
+ },
352
+ ],
353
+ _clientId: bootstrap?.clientId ?? 'boot',
354
+ });
355
+ };
356
+ const onError = (event: ErrorEvent): void => {
357
+ const error = event.error as Error | undefined;
358
+ report(error?.stack ?? `${event.message} (${event.filename ?? '?'}:${event.lineno ?? 0})`);
359
+ };
360
+ const onRejection = (event: PromiseRejectionEvent): void => {
361
+ const reason: unknown = event.reason;
362
+ // A CANCELLATION IS NOT A FAILURE TO START. See `isCancellationReason`'s
363
+ // own note in `editor-console.ts`: this listener is the page's, the page
364
+ // under the Code-OSS frame is a WORKBENCH, and a workbench throws
365
+ // `CancellationError` (`name === 'Canceled'`) whenever a quick input is
366
+ // dismissed or a search is superseded. MEASURED 2026-09-19, the frame
367
+ // walk's beat 9: `[runtime] editor app failed to start: Canceled: Canceled`
368
+ // on a game scaffold whose editor had started perfectly. The claim in that
369
+ // sentence was false in BOTH halves — nothing failed, and nothing was
370
+ // starting.
371
+ if (isCancellationReason(reason)) return;
372
+ report(
373
+ reason instanceof Error
374
+ ? (reason.stack ?? reason.message)
375
+ : `unhandled rejection: ${String(reason)}`,
376
+ );
377
+ };
378
+ window.addEventListener('error', onError);
379
+ window.addEventListener('unhandledrejection', onRejection);
380
+ return () => {
381
+ window.removeEventListener('error', onError);
382
+ window.removeEventListener('unhandledrejection', onRejection);
383
+ };
384
+ }
385
+
386
+ /**
387
+ * The five things this tab reports UPSTREAM, and the one door they go
388
+ * through.
389
+ *
390
+ * Each has an equivalent POST route, and the POST is still the fallback —
391
+ * the share tunnel's gateway bridges the SSE stream one way, so a tunnelled
392
+ * tab has no upstream socket. But when the page holds a duplex control
393
+ * socket (every local tab), these ride it instead. That is the entire point
394
+ * of the socket: a blocked main thread cannot issue a `fetch`, and even an
395
+ * unblocked one queues control POSTs behind a cold module flood in the
396
+ * browser's per-origin HTTP connection pool.
397
+ *
398
+ * `play-phase` is the second of those standing facts, and it exists for the
399
+ * same reason: it says which of play's eight boot steps the page is INSIDE,
400
+ * published before the step runs, so a step that never returns is still named.
401
+ * It rides its own message rather than the state snapshot on purpose — the
402
+ * snapshot is the expensive derivation, and a page wedged inside a boot step is
403
+ * exactly the page that cannot produce one. Measured at N=20000: `play`,
404
+ * `screenshot` and `stop` all timed out and every reader called the session
405
+ * healthy (`server/play-stall.ts`).
406
+ *
407
+ * `command-listener` is the odd one out: it reports nothing
408
+ * about a command, only whether this page is in a position to run one. THIS
409
+ * module opens the control channel before any other module loads, so a page
410
+ * that dies during boot still connects, still beats, and still counts as
411
+ * present — and every one of those facts is about the TAB, not the document.
412
+ * The listener says so about the document, which is the only thing that
413
+ * separates a healthy session from an eight-minute lie.
414
+ */
415
+ export type EditorControlMessage =
416
+ | 'command-received'
417
+ | 'command-result'
418
+ | 'command-listener'
419
+ | 'console-entries'
420
+ | 'console-resolved'
421
+ | 'play-phase'
422
+ | 'state'
423
+ | 'tab-route';
424
+
425
+ /** A missing receipt must never strand deferred editor presentation forever. */
426
+ const CONTROL_RECEIPT_TIMEOUT_MS = 2_000;
427
+
428
+ const CONTROL_POST_PATHS: Record<EditorControlMessage, string> = {
429
+ 'command-received': `${BASE}/command-received`,
430
+ 'command-result': `${BASE}/command-result`,
431
+ 'command-listener': `${BASE}/command-listener`,
432
+ 'console-entries': `${BASE}/console-entries`,
433
+ 'console-resolved': `${BASE}/console-resolved`,
434
+ 'play-phase': `${BASE}/play-phase`,
435
+ state: `${BASE}/state`,
436
+ 'tab-route': `${BASE}/tab/route`,
437
+ };
438
+
439
+ /** Send one control message on the socket, else POST it. Never throws — a
440
+ * failed report costs a named refusal, never a broken page.
441
+ *
442
+ * Deliberately NOT read through `editor-server-response.ts`: never-throwing is
443
+ * this function's contract and there is no caller to report to, so asserting
444
+ * could only turn a dropped report into a swallowed one. The absence is
445
+ * detected at the READING end instead — `/__editor/state` goes stale and the
446
+ * CLI says so — which is where a missing report is actually visible. */
447
+ async function postControl(
448
+ type: EditorControlMessage,
449
+ payload: Record<string, unknown>,
450
+ ): Promise<void> {
451
+ if (typeof fetch === 'undefined') return;
452
+ try {
453
+ await fetch(CONTROL_POST_PATHS[type], {
454
+ method: 'POST',
455
+ headers: { 'Content-Type': 'application/json' },
456
+ body: JSON.stringify({
457
+ ...payload,
458
+ ...(bootstrap?.controlLifecycle ? { _controlLifecycle: bootstrap.controlLifecycle } : {}),
459
+ }),
460
+ });
461
+ } catch {
462
+ // Relative URLs outside a real document (jsdom/tests) can throw
463
+ // synchronously, and a dropped report must never take down the page.
464
+ }
465
+ }
466
+
467
+ export async function sendControl(
468
+ type: EditorControlMessage,
469
+ payload: Record<string, unknown>,
470
+ ): Promise<void> {
471
+ const source = sharedSource ?? bootstrap?.source ?? null;
472
+ if (source?.send?.(type, payload)) return;
473
+ await postControl(type, payload);
474
+ }
475
+
476
+ /**
477
+ * Report one command result and wait until its original caller is answered.
478
+ *
479
+ * `WebSocket.send()` only queues bytes; its return says nothing about whether
480
+ * the relay accepted the result. Selection presentation depends on that
481
+ * distinction: the server must release the waiting control caller before a
482
+ * large hierarchy/inspector render can monopolize the editor page again.
483
+ *
484
+ * The server answers with {@link COMMAND_RESULT_RECEIPT_EVENT} only after the
485
+ * original command caller's response has finished. That works for both a
486
+ * native duplex result and a tunnelled/SSE result posted upstream. The timeout
487
+ * preserves the standing control-channel rule that a vanished server may drop
488
+ * a report but must never leave the editor page wedged.
489
+ */
490
+ export async function sendCommandResultControl(
491
+ requestId: string,
492
+ payload: Record<string, unknown>,
493
+ ): Promise<void> {
494
+ const source = sharedSource ?? bootstrap?.source ?? null;
495
+ if (!source) {
496
+ await postControl('command-result', payload);
497
+ return;
498
+ }
499
+
500
+ let settle!: () => void;
501
+ const receipt = new Promise<void>((resolve) => {
502
+ settle = resolve;
503
+ });
504
+ const onReceipt: EventListener = (event) => {
505
+ const wireData = (event as MessageEvent).data;
506
+ let received = wireData;
507
+ if (typeof wireData === 'string') {
508
+ try {
509
+ received = JSON.parse(wireData);
510
+ } catch {
511
+ // Direct/fake event sources may already carry the unencoded id.
512
+ }
513
+ }
514
+ if (received === requestId) settle();
515
+ };
516
+ source.addEventListener(COMMAND_RESULT_RECEIPT_EVENT, onReceipt);
517
+
518
+ const resultPayload = { ...payload, _awaitCallerReceipt: true };
519
+ if (!source.send?.('command-result', resultPayload)) {
520
+ await postControl('command-result', resultPayload);
521
+ }
522
+
523
+ let timer: ReturnType<typeof setTimeout> | undefined;
524
+ let acknowledged = false;
525
+ await Promise.race([
526
+ receipt.then(() => {
527
+ acknowledged = true;
528
+ }),
529
+ new Promise<void>((resolve) => {
530
+ timer = setTimeout(resolve, CONTROL_RECEIPT_TIMEOUT_MS);
531
+ }),
532
+ ]);
533
+ if (timer !== undefined) clearTimeout(timer);
534
+
535
+ // NO RECEIPT MEANS THE RESULT DID NOT LAND — SO SEND IT AGAIN, OVER HTTP.
536
+ //
537
+ // This is the whole reason the receipt exists (see the docblock: `send()`
538
+ // only queues bytes), and until now nothing acted on its absence: the race
539
+ // simply expired and the page dropped an answer it was still holding. The
540
+ // caller then burned its entire command budget waiting for a result that had
541
+ // already been computed.
542
+ //
543
+ // MEASURED 2026-09-15 on `02-hinged-vise`: a `blender-read-file` was relayed
544
+ // 2.1 s before the socket closed 1006, the page reconnected, and the command
545
+ // failed at exactly 60.0 s — its budget — with the tab's last heartbeat
546
+ // 0.9 s old. The bytes went into a socket that died before the server read
547
+ // them, and `send()` had already returned true.
548
+ //
549
+ // Re-posting is safe to do blind: `settlePendingCommand` returns early when
550
+ // the request is no longer pending, so a duplicate result is a no-op, and
551
+ // the HTTP path does not depend on the socket that just died.
552
+ if (!acknowledged) await postControl('command-result', payload);
553
+ source.removeEventListener(COMMAND_RESULT_RECEIPT_EVENT, onReceipt);
554
+ }
555
+
556
+ /** Tell the local editor session which surface this tab is showing. */
557
+ export function reportTabRoute(route: EditorTabRoute): void {
558
+ void sendControl('tab-route', {
559
+ clientId: EDITOR_CLIENT_ID,
560
+ participantId: EDITOR_PARTICIPANT_ID,
561
+ route,
562
+ });
563
+ }
@@ -0,0 +1,50 @@
1
+ /** Host visibility controls presentation work, never document ownership. */
2
+ interface PresentationActivity {
3
+ hostActive: boolean;
4
+ readonly listeners: Set<() => void>;
5
+ }
6
+
7
+ // Existing renderer sessions can survive a replacement of this module. Keep
8
+ // their subscriptions and the host's last answer on the same shared object.
9
+ const hotData = import.meta.hot?.data;
10
+ const activity: PresentationActivity = hotData?.presentationActivity ?? {
11
+ hostActive: true,
12
+ listeners: new Set<() => void>(),
13
+ };
14
+ if (hotData) hotData.presentationActivity = activity;
15
+
16
+ export function isEditorPresentationActive(): boolean {
17
+ return activity.hostActive && (typeof document === 'undefined' || !document.hidden);
18
+ }
19
+ function changed(): void {
20
+ for (const listener of activity.listeners) listener();
21
+ }
22
+
23
+ const parentOrigin =
24
+ typeof document !== 'undefined' && document.referrer ? new URL(document.referrer).origin : null;
25
+
26
+ function receive(event: MessageEvent): void {
27
+ if (window.parent === window || event.source !== window.parent) return;
28
+ if (!parentOrigin || event.origin !== parentOrigin) return;
29
+ if (event.data?.type !== 'vgai:embed-activity' || typeof event.data.active !== 'boolean') return;
30
+ if (activity.hostActive === event.data.active) return;
31
+ activity.hostActive = event.data.active;
32
+ changed();
33
+ }
34
+ export function subscribeEditorPresentationActivity(listener: () => void): () => void {
35
+ activity.listeners.add(listener);
36
+ return () => {
37
+ activity.listeners.delete(listener);
38
+ };
39
+ }
40
+ if (typeof window !== 'undefined') {
41
+ window.addEventListener('message', receive);
42
+ document.addEventListener('visibilitychange', changed);
43
+ if (window.parent !== window && parentOrigin) {
44
+ window.parent.postMessage({ type: 'vgai:request-embed-activity' }, parentOrigin);
45
+ }
46
+ import.meta.hot?.dispose(() => {
47
+ window.removeEventListener('message', receive);
48
+ document.removeEventListener('visibilitychange', changed);
49
+ });
50
+ }
@@ -0,0 +1,42 @@
1
+ import type { EditorView, PresentedEditorView } from '@volter/editor-sdk';
2
+
3
+ export interface EditorPresentationNotice {
4
+ readonly presented: PresentedEditorView;
5
+ readonly previousView: EditorView;
6
+ }
7
+
8
+ let notice: EditorPresentationNotice | null = null;
9
+ let version = 0;
10
+ const listeners = new Set<() => void>();
11
+
12
+ function publish(next: EditorPresentationNotice | null): void {
13
+ if (notice === next) return;
14
+ notice = next;
15
+ version++;
16
+ for (const listener of listeners) listener();
17
+ }
18
+
19
+ export function editorPresentationNotice(): EditorPresentationNotice | null {
20
+ return notice;
21
+ }
22
+
23
+ export function showEditorPresentationNotice(next: EditorPresentationNotice): void {
24
+ publish(next);
25
+ }
26
+
27
+ export function clearEditorPresentationNotice(): void {
28
+ publish(null);
29
+ }
30
+
31
+ export function subscribeEditorPresentationNotice(listener: () => void): () => void {
32
+ listeners.add(listener);
33
+ return () => listeners.delete(listener);
34
+ }
35
+
36
+ export function editorPresentationNoticeVersion(): number {
37
+ return version;
38
+ }
39
+
40
+ export function __resetEditorPresentationNoticeForTest(): void {
41
+ publish(null);
42
+ }