@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,628 @@
1
+ /* THE TAB BOOTSTRAP — what makes a page one of this session's TABS.
2
+ *
3
+ * It mints the tab identity, opens the duplex control channel, starts the
4
+ * heartbeat WORKER that proves the tab to `tab-presence.ts`, answers the
5
+ * main-thread echo, and sends the `pagehide` goodbye. Everything the tab
6
+ * bijection decides — bless, yield, depart, re-mint — is decided from what
7
+ * this sends.
8
+ *
9
+ * IT IS PLAIN JS, AND IT IS SERVED VERBATIM (`tab-bootstrap.ts`, at
10
+ * `/__editor/tab-bootstrap.js`). The page that runs it is the Code-OSS
11
+ * workbench's, authored by VS Code, so it cannot be a module of the editor's
12
+ * graph and cannot be transformed: it is a classic script the contribution
13
+ * loads BEFORE the React Refresh preamble and before the editor itself. It
14
+ * takes its base from its own `src` (`document.currentScript`), so every url
15
+ * it builds points at the session rather than at the page hosting it.
16
+ *
17
+ * It lived inline in the editor's own `index.html` until PART B, and was read
18
+ * back out of that file to be served here; the page is gone and this is its
19
+ * own file now, with one author and nothing to drift against.
20
+ */
21
+
22
+ /* Connect the tab before any editor module loads. `editor-presence.ts` adopts
23
+ this exact client id/socket and replays any lifecycle event that arrived
24
+ while its typed handlers were loading. */
25
+ (() => {
26
+ /* ONCE PER DOCUMENT. The mount path that loads this can be reached twice,
27
+ and a second bootstrap would mint a second tab identity for one document:
28
+ two tabs, to a table that exists to count one. */
29
+ if (globalThis.__VGAI_EDITOR_PRESENCE_BOOTSTRAP__) return;
30
+
31
+ /* WHERE THE SESSION IS — the base every url below is built on, and the
32
+ reason none of them reads `location`.
33
+
34
+ Inline in the editor's own page the two are the same thing: an inline
35
+ script's `currentScript` has no `src`, so this falls through to
36
+ `location.href` and nothing changes. But this same bootstrap is also
37
+ SERVED, as `/__editor/tab-bootstrap.js`, to a page vgai does not
38
+ author — the Code-OSS workbench, which on desktop is
39
+ `vscode-file://vscode-app` and can never be this session's origin
40
+ (docs/CODE-OSS.md §Boot, DESKTOP; server/tab-bootstrap.ts). On that
41
+ page `location` is the WORKBENCH: a heartbeat socket built from it
42
+ goes nowhere, and a tab that cannot beat is a tab the bijection
43
+ believes is dead. The script's own `src` is the one reading that
44
+ cannot be wrong, because the frame fetched it from the session.
45
+
46
+ The frame also declares WHAT KIND of page it is in the same url
47
+ (`?surface=vscode-desktop`), and that is what the tab table reports
48
+ back — so a page that beats is never described as an anomaly. */
49
+ const bootstrapSrc = document.currentScript?.src || '';
50
+ const sessionBase = bootstrapSrc ? `${new URL(bootstrapSrc).origin}/` : location.href;
51
+ const pageSurface = bootstrapSrc ? new URL(bootstrapSrc).searchParams.get('surface') || '' : '';
52
+ const sessionUrl = (path) => new URL(path, sessionBase).href;
53
+ const sessionSocketUrl = (path) => {
54
+ const url = new URL(path, sessionBase);
55
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
56
+ return url;
57
+ };
58
+ const clientId = globalThis.crypto?.randomUUID?.() || `editor-${Date.now()}`;
59
+ const uuid = () => globalThis.crypto?.randomUUID?.() || `id-${Date.now()}-${Math.random()}`;
60
+
61
+ /* PAGE ERRORS, CAPTURED FIRST — before this bootstrap's own next line,
62
+ and long before the module graph.
63
+
64
+ The doctrine: the product answers its own state. Every other door onto
65
+ a tab's errors lives INSIDE the module graph (editor-console.ts's
66
+ capture, read back by command-listener.ts's `collectPageErrors`), so
67
+ the one boot failure that most needs explaining — the one that kills
68
+ the page before the command listener attaches — was the only one the
69
+ product could not describe. It could report `commandListener: not
70
+ attached` and never why, and the way you learned the cause was to open
71
+ devtools, which is the workaround this whole seam exists to delete.
72
+
73
+ These go out on the control connection the bootstrap already holds,
74
+ falling back to a POST exactly like editor-presence.ts's `sendControl`
75
+ does for a tunnelled tab. The server journals them and serves them
76
+ back on `/__editor/state` — a plain GET — so `vgai status` answers with
77
+ no listener, no module graph, and no cooperation from the page beyond
78
+ this handler. */
79
+ const pendingPageErrors = [];
80
+ let pageErrorChannel = null;
81
+ const PAGE_ERROR_LIMIT = 8;
82
+ const deliverPageError = (message) => {
83
+ if (pageErrorChannel && pageErrorChannel.send('page-error', { message })) return;
84
+ try {
85
+ const lifecycle = pageErrorChannel?.lifecycle ?? null;
86
+ void fetch(sessionUrl('/__editor/page-error'), {
87
+ method: 'POST',
88
+ headers: { 'Content-Type': 'application/json' },
89
+ body: JSON.stringify({
90
+ message,
91
+ _clientId: clientId,
92
+ ...(lifecycle === null ? {} : { _controlLifecycle: lifecycle }),
93
+ }),
94
+ keepalive: true,
95
+ }).catch(() => {});
96
+ } catch {
97
+ /* A page that cannot even fetch has nothing left to report with;
98
+ the tab table still says the document never came up. */
99
+ }
100
+ };
101
+ const flushPageErrors = () => {
102
+ while (pendingPageErrors.length > 0) deliverPageError(pendingPageErrors.shift());
103
+ };
104
+ const capturePageError = (message) => {
105
+ if (typeof message !== 'string' || message === '') return;
106
+ if (pageErrorChannel === null) {
107
+ if (pendingPageErrors.length < PAGE_ERROR_LIMIT) pendingPageErrors.push(message);
108
+ return;
109
+ }
110
+ deliverPageError(message);
111
+ };
112
+ const describeError = (value) => {
113
+ if (value instanceof Error) return `${value.name}: ${value.message}\n${value.stack ?? ''}`;
114
+ try {
115
+ return String(value);
116
+ } catch {
117
+ return 'unstringifiable error value';
118
+ }
119
+ };
120
+ window.addEventListener(
121
+ 'error',
122
+ (event) => {
123
+ /* A failed <script>/<link> load raises `error` on the ELEMENT with no
124
+ `error` property — the module graph failing to arrive at all, which
125
+ is precisely the case that leaves no listener. */
126
+ if (event.error) capturePageError(describeError(event.error));
127
+ else if (event.message)
128
+ capturePageError(`${event.message} (${event.filename ?? '?'}:${event.lineno ?? 0})`);
129
+ else if (event.target && event.target !== window) {
130
+ const src = event.target.src || event.target.href;
131
+ if (src) capturePageError(`failed to load ${src}`);
132
+ }
133
+ },
134
+ true,
135
+ );
136
+ window.addEventListener('unhandledrejection', (event) => {
137
+ capturePageError(`unhandled rejection: ${describeError(event.reason)}`);
138
+ });
139
+ /* TAB IDENTITY. sessionStorage is scoped to exactly one tab and
140
+ survives its reloads, which is the definition the server needs: a
141
+ reload is the SAME tab with a new `epoch`, not a departure. The one
142
+ thing it gets wrong is "Duplicate Tab", which COPIES it — the server
143
+ sees two epochs beating under one tabId and tells the younger to
144
+ re-mint, which is what `remint()` below does. */
145
+ const TAB_KEY = 'vgai.tab.v1';
146
+ let tabId;
147
+ try {
148
+ tabId = sessionStorage.getItem(TAB_KEY) || '';
149
+ if (!tabId) {
150
+ tabId = uuid();
151
+ sessionStorage.setItem(TAB_KEY, tabId);
152
+ }
153
+ } catch {
154
+ /* No sessionStorage (rare, but a private-mode quirk is not a reason
155
+ to be invisible): a per-load id still makes this tab countable. */
156
+ tabId = uuid();
157
+ }
158
+ const epoch = uuid();
159
+ let participantId;
160
+ let displayName = 'Local editor';
161
+ try {
162
+ participantId = document.cookie
163
+ .split('; ')
164
+ .find((entry) => entry.startsWith('vgai_share_participant='))
165
+ ?.slice('vgai_share_participant='.length);
166
+ participantId ||= localStorage.getItem('vgai.collaboration.participant.v1');
167
+ if (!participantId) {
168
+ participantId = globalThis.crypto?.randomUUID?.() || `participant-${Date.now()}`;
169
+ localStorage.setItem('vgai.collaboration.participant.v1', participantId);
170
+ }
171
+ displayName = localStorage.getItem('vgai.collaboration.display-name.v1') || displayName;
172
+ } catch {
173
+ participantId = globalThis.crypto?.randomUUID?.() || `participant-${Date.now()}`;
174
+ }
175
+ const query = new URLSearchParams({
176
+ clientId,
177
+ participantId,
178
+ displayName,
179
+ tabId,
180
+ pageGeneration: epoch,
181
+ });
182
+ /* Only a page that is not the editor's own sends this; the tab table
183
+ keeps it so `vgai status` can name the page instead of guessing. */
184
+ if (pageSurface) query.set('surface', pageSurface);
185
+ /* The tab's control channel. Downstream it looks exactly like an
186
+ EventSource (same named events, same `data` strings). Upstream it
187
+ also carries this page's control replies — receipts, results, state,
188
+ route — so they never queue behind a module flood in the browser's
189
+ per-origin HTTP connection pool. That queueing is what made a cold
190
+ boot's blocked main thread indistinguishable from a dead tab on
191
+ 2026-08-09: five `vgai play` commands were refused as "not picked
192
+ up" and every one of them ran later.
193
+
194
+ `duplex` is granted by the SERVER, never assumed: the share tunnel's
195
+ gateway answers this same URL with a one-way bridge of the SSE
196
+ stream, and a control frame sent into that would vanish. Only a
197
+ native socket emits `control-duplex`, so a tunnelled tab keeps
198
+ POSTing (see editor-presence.ts's `sendControl`). */
199
+ class WebSocketEventSource extends EventTarget {
200
+ constructor(path) {
201
+ super();
202
+ this.path = path;
203
+ this.closed = false;
204
+ this.duplex = false;
205
+ this.lifecycle = null;
206
+ this.lastEventId = '';
207
+ this.retryMs = 500;
208
+ this.connectionAttempt = 0;
209
+ this.reidentifyAfterClose = null;
210
+ this.identityReady = null;
211
+ this.connect();
212
+ }
213
+ connect() {
214
+ const attempt = ++this.connectionAttempt;
215
+ const url = new URL(this.path, sessionBase);
216
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
217
+ if (this.lastEventId) url.searchParams.set('lastEventId', this.lastEventId);
218
+ const socket = new WebSocket(url);
219
+ this.socket = socket;
220
+ socket.addEventListener('open', () => {
221
+ if (attempt !== this.connectionAttempt) return;
222
+ this.retryMs = 500;
223
+ this.dispatchEvent(new Event('open'));
224
+ });
225
+ socket.addEventListener('message', (message) => {
226
+ if (attempt !== this.connectionAttempt || this.reidentifyAfterClose !== null) return;
227
+ try {
228
+ const frame = JSON.parse(String(message.data));
229
+ if (!frame || typeof frame.event !== 'string' || typeof frame.data !== 'string') {
230
+ return;
231
+ }
232
+ if (frame.event === 'control-duplex') {
233
+ this.duplex = true;
234
+ this.finishIdentityChange();
235
+ return;
236
+ }
237
+ if (frame.event === 'control-lifecycle') {
238
+ const lifecycle = JSON.parse(frame.data);
239
+ if (
240
+ lifecycle?.version === 1 &&
241
+ typeof lifecycle.serverGeneration === 'string' &&
242
+ typeof lifecycle.connectionGeneration === 'string' &&
243
+ typeof lifecycle.clientId === 'string' &&
244
+ typeof lifecycle.tabId === 'string' &&
245
+ typeof lifecycle.pageGeneration === 'string'
246
+ ) {
247
+ this.lifecycle = lifecycle;
248
+ this.dispatchEvent(new MessageEvent('control-lifecycle', { data: frame.data }));
249
+ this.finishIdentityChange();
250
+ }
251
+ return;
252
+ }
253
+ /* The main-thread liveness echo. Answered HERE, in the inline
254
+ bootstrap, because that is what makes an unanswered echo
255
+ mean something: this responder exists before the first
256
+ module loads, so silence can only be a blocked main thread —
257
+ never a listener that had not been wired up yet. */
258
+ if (frame.event === 'control-echo') {
259
+ this.send('echo-reply', { id: frame.data });
260
+ return;
261
+ }
262
+ if (typeof frame.id === 'string') this.lastEventId = frame.id;
263
+ this.dispatchEvent(
264
+ new MessageEvent(frame.event, {
265
+ data: frame.data,
266
+ lastEventId: typeof frame.id === 'string' ? frame.id : '',
267
+ }),
268
+ );
269
+ } catch {
270
+ this.dispatchEvent(new Event('error'));
271
+ }
272
+ });
273
+ socket.addEventListener('error', () => this.dispatchEvent(new Event('error')));
274
+ socket.addEventListener('close', () => {
275
+ if (attempt !== this.connectionAttempt) return;
276
+ this.duplex = false;
277
+ this.lifecycle = null;
278
+ if (this.closed) return;
279
+ if (this.reidentifyAfterClose !== null) {
280
+ this.path = this.reidentifyAfterClose;
281
+ this.reidentifyAfterClose = null;
282
+ this.retryMs = 500;
283
+ this.connect();
284
+ return;
285
+ }
286
+ const retryMs = this.retryMs;
287
+ this.retryMs = Math.min(5_000, retryMs * 2);
288
+ /* Same clientId across reconnects — the server treats the
289
+ reconnected tab as the same tab, not a second one. */
290
+ setTimeout(() => this.connect(), retryMs);
291
+ });
292
+ }
293
+ /* Is this page's control connection to the server UP right now?
294
+ Read by the supervised lease (src/editor-lease.ts) as the second,
295
+ independent liveness reading: a killed server drops this socket
296
+ immediately, while a merely BUSY one — a blocked event loop, a cold
297
+ dep-optimize — holds it open while HTTP polls time out. Without it
298
+ the watchdog cannot tell "gone" from "slow", and on 2026-08-09 a
299
+ `kill -STOP`ped (perfectly alive) server produced the blocking
300
+ "Editor disconnected" scrim while this socket read OPEN. */
301
+ get connected() {
302
+ return this.socket?.readyState === WebSocket.OPEN;
303
+ }
304
+ /* Upstream control frame; false when this socket cannot carry it.
305
+ The envelope is built HERE and only here, with the discriminator
306
+ and the payload in separate keys — a caller cannot flatten them.
307
+ A payload is an open-ended object (a state snapshot is literally
308
+ whatever the editor reports), so a shared namespace would let a
309
+ key named `type` overwrite the frame type on the way out and drop
310
+ the whole report, and would leak the frame type into stored state
311
+ on the way in. */
312
+ send(type, payload) {
313
+ const socket = this.socket;
314
+ if (!this.duplex || !this.lifecycle || !socket || socket.readyState !== WebSocket.OPEN)
315
+ return false;
316
+ try {
317
+ socket.send(JSON.stringify({ type, payload, lifecycle: this.lifecycle }));
318
+ return true;
319
+ } catch {
320
+ return false;
321
+ }
322
+ }
323
+ finishIdentityChange() {
324
+ if (!this.duplex || !this.lifecycle || this.identityReady === null) return;
325
+ const ready = this.identityReady;
326
+ this.identityReady = null;
327
+ ready();
328
+ }
329
+ /* Replace ALL channels which name a tab, as one transition. The old
330
+ connection closes before the new one opens, and the new heartbeat
331
+ starts only after the server accepts the replacement control
332
+ identity. A duplicate can therefore never beat as B while taking
333
+ commands as copied tab A. */
334
+ reidentifyTab(nextTabId, ready) {
335
+ const next = new URL(this.path, sessionBase);
336
+ next.searchParams.set('tabId', nextTabId);
337
+ this.duplex = false;
338
+ this.lifecycle = null;
339
+ this.identityReady = ready;
340
+ this.reidentifyAfterClose = `${next.pathname}${next.search}${next.hash}`;
341
+ const socket = this.socket;
342
+ if (socket && socket.readyState !== WebSocket.CLOSED) {
343
+ try {
344
+ socket.close(1000, 'tab identity replaced');
345
+ return;
346
+ } catch {
347
+ /* Fall through to a fresh attempt. */
348
+ }
349
+ }
350
+ this.path = this.reidentifyAfterClose;
351
+ this.reidentifyAfterClose = null;
352
+ this.connect();
353
+ }
354
+ close() {
355
+ this.closed = true;
356
+ this.socket?.close();
357
+ }
358
+ }
359
+ /* Every tab, not just tunnelled ones. TryCloudflare Quick Tunnels
360
+ cannot do SSE at all; local tabs use the socket for the reason
361
+ above. The plain GET/SSE form of this URL still works — it is what
362
+ the tunnel gateway bridges through, and what curl reads. */
363
+ let bootstrap = null;
364
+ const source = new WebSocketEventSource(`/__editor/events?${query}`);
365
+ /* From here the capture above has a channel. Anything it buffered while
366
+ this class was being defined goes now, and on every reconnect — the
367
+ duplex grant arrives after `open`, and `send` answers false until it
368
+ does, which is exactly when the POST fallback takes over. */
369
+ pageErrorChannel = source;
370
+ source.addEventListener('open', () => flushPageErrors());
371
+ flushPageErrors();
372
+
373
+ /* THE HEARTBEAT. A dedicated Worker, started here — before the module
374
+ graph exists — because the failure it covers is the module graph
375
+ blocking the main thread for a minute on a cold boot. It keeps
376
+ beating through that, it dies exactly when this tab dies, and its
377
+ socket is not this page's socket, so nothing that happens to the
378
+ control channel can make the server believe the tab went away.
379
+
380
+ Presence is a UNION of a fresh beat and a live control channel
381
+ (server/tab-presence.ts), so a tab that cannot run a worker at all —
382
+ a tunnelled one, which is refused the script by the share gateway —
383
+ is still SEEN. What the beat adds is the case the union needs it
384
+ for: a tab whose page socket is down or whose main thread is
385
+ blocked. */
386
+ let heartbeatWorker = null;
387
+ let heartbeatVisibilityListener = null;
388
+ const startHeartbeat = (activeTabId) => {
389
+ try {
390
+ heartbeatWorker?.terminate();
391
+ if (heartbeatVisibilityListener !== null) {
392
+ document.removeEventListener('visibilitychange', heartbeatVisibilityListener);
393
+ }
394
+ const worker = new Worker(sessionUrl('/__editor/tab-heartbeat.js'));
395
+ heartbeatWorker = worker;
396
+ worker.addEventListener('message', (event) => {
397
+ if (event.data?.type === 're-mint') remint();
398
+ });
399
+ /* A worker that cannot start (no script — the share gateway
400
+ refuses it to a tunnelled tab — or a CSP that forbids one) is
401
+ not an error to report: presence falls back to this page's own
402
+ control channel. */
403
+ worker.addEventListener('error', (event) => event.preventDefault());
404
+ const socketUrl = sessionSocketUrl('/__editor/heartbeat');
405
+ socketUrl.searchParams.set('tabId', activeTabId);
406
+ worker.postMessage({
407
+ type: 'start',
408
+ tabId: activeTabId,
409
+ epoch,
410
+ socketUrl: socketUrl.href,
411
+ postUrl: sessionUrl('/__editor/heartbeat'),
412
+ });
413
+ const reportVisibility = () =>
414
+ worker.postMessage({
415
+ type: 'visibility',
416
+ visibility: document.visibilityState === 'hidden' ? 'hidden' : 'visible',
417
+ });
418
+ heartbeatVisibilityListener = reportVisibility;
419
+ document.addEventListener('visibilitychange', heartbeatVisibilityListener);
420
+ reportVisibility();
421
+ } catch {
422
+ /* A tab that cannot run a Worker is still SEEN — the server counts
423
+ a live control channel as presence too (tab-presence.ts's union
424
+ rule). It just loses the reload/blocked-thread coverage. */
425
+ }
426
+ };
427
+ /* "Duplicate Tab" copied this tab's sessionStorage, so two pages are
428
+ beating under one identity. The younger takes a fresh one. */
429
+ const remint = () => {
430
+ heartbeatWorker?.terminate();
431
+ heartbeatWorker = null;
432
+ tabId = uuid();
433
+ try {
434
+ sessionStorage.setItem(TAB_KEY, tabId);
435
+ } catch {
436
+ /* the in-memory id is enough for this page load */
437
+ }
438
+ if (bootstrap !== null) bootstrap.tabId = tabId;
439
+ source.reidentifyTab(tabId, () => startHeartbeat(tabId));
440
+ };
441
+ startHeartbeat(tabId);
442
+
443
+ /* The module graph's one door to the beat. The census rides the
444
+ HEARTBEAT rather than the control channel deliberately: the profile
445
+ that explains a death has to leave the tab on the thread that is
446
+ still alive when the page's is not.
447
+
448
+ Each call hands over ONE fresh sample and the worker carries it on one
449
+ beat, so the server's stamp means "the page sampled this" — never
450
+ "the worker echoed it again". Nothing is replayed into a re-minted
451
+ worker for the same reason: a duplicate-tab re-mint is a new tabId
452
+ with an empty record, and it gets its first honest sample within 5s. */
453
+ const reportCensus = (census) => {
454
+ try {
455
+ heartbeatWorker?.postMessage({ type: 'census', census });
456
+ } catch {
457
+ /* the next sample tries again; a missed profile is not a missed beat */
458
+ }
459
+ };
460
+ /* What the page's main thread is about to do — a model's build() — or
461
+ null when it is done. Same road as the census, for the same reason:
462
+ the phase that explains a stall has to leave on the thread that is
463
+ still alive while the page's is inside the work. */
464
+ const reportPhase = (phase) => {
465
+ try {
466
+ heartbeatWorker?.postMessage({ type: 'phase', phase });
467
+ } catch {
468
+ /* the control channel carries it too, once the page can speak */
469
+ }
470
+ };
471
+
472
+ /* LEAVING THE TAB TABLE, for a page whose session is over for good.
473
+
474
+ The beat is what PROVES a tab to the server (server/tab-presence.ts),
475
+ so a page that keeps beating after its session ended stays present,
476
+ stays blessed, and `vgai edit` answers "focused" instead of opening a
477
+ real tab — a corpse holding the session's one tab slot. Measured on
478
+ this box, 2026-08-15: a page that had painted the "session ended"
479
+ notice went on beating under the same tabId across a `vgai close` and
480
+ a fresh `vgai edit`, so the new server blessed it and every command
481
+ had nowhere to go.
482
+
483
+ Stopping the beat is the whole withdrawal: the table departs the tab
484
+ on the evidence it already uses, and the bijection opens a new one by
485
+ its own existing rule. Only the TERMINAL deaths call this
486
+ (src/session-tombstone.ts) — a `server-gone` page may still resume. */
487
+ const stopHeartbeat = () => {
488
+ try {
489
+ heartbeatWorker?.postMessage({ type: 'stop' });
490
+ if (heartbeatVisibilityListener !== null) {
491
+ document.removeEventListener('visibilitychange', heartbeatVisibilityListener);
492
+ heartbeatVisibilityListener = null;
493
+ }
494
+ } catch {
495
+ /* the worker dies with the document regardless */
496
+ }
497
+ };
498
+
499
+ /* THE GOODBYE. One `sendBeacon` on `pagehide`, and the only page signal
500
+ this bootstrap sends about its own end.
501
+
502
+ WHY (measured 2026-09-17): four different failures — a renderer killed
503
+ by a dev-server reload, a worker that never finished booting, a main
504
+ thread wedged inside a 46 MB encode, and a twin call genuinely running
505
+ for sixteen minutes — all reached the server as the SAME observation,
506
+ beats that stopped or a page that did not answer. `pagehide` fires for
507
+ a close, a navigation and a reload; it does NOT fire for a renderer
508
+ kill or a wedged thread. So its presence is exactly the discriminator
509
+ the table was missing (server/tab-presence.ts's `tabState`): a silence
510
+ WITH a goodbye is closed/reloading, a silence without one is crashed.
511
+
512
+ `sendBeacon` and not `fetch`: it is the one transport the browser
513
+ promises to deliver for a document that is already gone. The reply is
514
+ unreadable by definition, and nothing waits on it — a beacon that does
515
+ not arrive degrades to `crashed`, which is what the server believed
516
+ before this line existed.
517
+
518
+ `persisted` is the back/forward cache: the page may yet come back, so
519
+ it is reported rather than collapsed into "this page is over". */
520
+ const sendCloseBeacon = (persisted, reason) => {
521
+ try {
522
+ navigator.sendBeacon?.(
523
+ sessionUrl('/__editor/tab/close'),
524
+ new Blob(
525
+ [
526
+ JSON.stringify({
527
+ tabId,
528
+ epoch,
529
+ persisted: persisted === true,
530
+ ...(reason === undefined ? {} : { reason }),
531
+ }),
532
+ ],
533
+ { type: 'application/json' },
534
+ ),
535
+ );
536
+ } catch {
537
+ /* a goodbye that cannot be sent is the crash case, truthfully */
538
+ }
539
+ };
540
+ addEventListener('pagehide', (event) => sendCloseBeacon(event.persisted));
541
+
542
+ bootstrap = {
543
+ clientId,
544
+ participantId,
545
+ displayName,
546
+ tabId,
547
+ epoch,
548
+ controlLifecycle: source.lifecycle,
549
+ reportCensus,
550
+ reportPhase,
551
+ stopHeartbeat,
552
+ source,
553
+ pageOwned: true,
554
+ pending: [],
555
+ queueListeners: [],
556
+ };
557
+ source.addEventListener('control-lifecycle', (event) => {
558
+ try {
559
+ bootstrap.controlLifecycle = JSON.parse(event.data);
560
+ } catch {
561
+ bootstrap.controlLifecycle = null;
562
+ }
563
+ });
564
+ globalThis.__VGAI_EDITOR_PRESENCE_BOOTSTRAP__ = bootstrap;
565
+ /* This EventSource connects before the module graph loads, so from here
566
+ on the server counts this tab and will route to it. Anything it sends
567
+ in that window reaches a page with no listener for it yet — buffered
568
+ here, replayed by editor-presence.ts once a real consumer subscribes.
569
+ `editor-command` belongs on this list for the same reason the tab-*
570
+ events do, and its absence was a silent command loss: the event
571
+ dispatched to zero listeners and left no trace, so `vgai play` was
572
+ refused for a tab that never saw the command. Capped because a tab
573
+ whose consumer never arrives must not grow this without bound. */
574
+ /* `tab-reload` is the ONE instruction that is not buffered, because it is
575
+ the one that matters precisely when the module graph never evaluated.
576
+ Everything else here waits for a consumer that, in that case, is never
577
+ coming: a page whose app failed to boot keeps beating from its worker,
578
+ keeps this EventSource open, and answers `tab-refocus` and `tab-adopt`
579
+ by appending them to a queue nobody drains. The session then adopts it
580
+ forever and no command can complete. Acting here — in the inline
581
+ bootstrap, before any module — is what makes "a lost tab self-heals"
582
+ true for a lost DOCUMENT and not just a lost socket. */
583
+ source.addEventListener('tab-reload', () => {
584
+ location.reload();
585
+ });
586
+ /* `tab-close` is the SECOND instruction this bootstrap acts on itself, and
587
+ for the same reason as the first: it matters precisely when no editor
588
+ module is there to act on it.
589
+
590
+ Measured 2026-09-21 on a first open of an untrusted folder: the page is a
591
+ tab from the moment it loads (the frame's activation bootstrap) while the
592
+ workbench is still asking whether the person trusts it, so `vgai close`
593
+ reached a tab whose consumer was never coming — the instruction went onto
594
+ a queue nobody drains, the session waited out its two seconds and exited
595
+ with "tab … did not acknowledge", and the browser was left showing a
596
+ workbench whose session is gone. The bijection's own promise is that
597
+ shutdown CLOSES the tab; a window that only draws the editor could not
598
+ keep it.
599
+
600
+ ONLY WHILE NOBODY ELSE OWNS IT. `editor-presence.ts` removes this type's
601
+ queue listener the moment its own consumer attaches (`drainBootstrap`), so
602
+ a still-queued `tab-close` is exactly "the editor has not taken this
603
+ over" — and after it has, this stays out of the way and the editor's
604
+ handler does the whole job (tombstone latch, ack, close-or-card). */
605
+ source.addEventListener('tab-close', () => {
606
+ if (!bootstrap.queueListeners.some((entry) => entry.type === 'tab-close')) return;
607
+ sendCloseBeacon(false, 'session-ended');
608
+ /* Best effort: a browser refuses `close()` for a tab a person opened. The
609
+ page then keeps standing with a dead session behind it — the same
610
+ outcome as before this listener, minus the unacknowledged close.
611
+ `globalThis.close`, spelled out: this file declares a `close()` METHOD a
612
+ few hundred lines up (the control socket's), and a bare call here costs
613
+ the next reader the proof that it is not that one. */
614
+ try {
615
+ globalThis.close?.();
616
+ } catch {
617
+ /* refused is the ordinary case, and it is not an error */
618
+ }
619
+ });
620
+ for (const type of ['tab-refocus', 'tab-yield', 'tab-close', 'tab-adopt', 'editor-command']) {
621
+ const listener = (event) => {
622
+ if (bootstrap.pending.length >= 64) return;
623
+ bootstrap.pending.push({ type, data: event.data });
624
+ };
625
+ source.addEventListener(type, listener);
626
+ bootstrap.queueListeners.push({ type, listener });
627
+ }
628
+ })();