@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,158 @@
1
+ /**
2
+ * The `.data.json` DIFF CONTRACT, server-side and unforkable.
3
+ *
4
+ * A data asset's editor UI ships as a COPIED capability (`data-tables`), and a
5
+ * copy can be edited — which is the point, and also the reason none of this
6
+ * may live there. Key order and `$schema`-first serialization are the property
7
+ * that keeps a one-cell edit a one-line git diff; a project that reorganized
8
+ * its own table UI must not be able to reorganize the file's bytes with it. So
9
+ * the client posts PARSED VALUES for a path (`POST /__editor/data-file` with
10
+ * `values`) and this module owns the fold from those values to the exact text
11
+ * written to disk.
12
+ *
13
+ * Ported verbatim (behavior, not shape) from the editor-side data panel that
14
+ * used to own it. Two facts drive every line here:
15
+ *
16
+ * 1. `JSON.parse` REINDEXES integer-like keys. A JS object enumerates "1",
17
+ * "2", "10" numerically-ascending no matter what order the file had, so
18
+ * "the order this file has on disk" can only be recovered from the raw
19
+ * TEXT, before parsing — {@link extractTopLevelKeyOrder}.
20
+ * 2. `JSON.stringify` of a spread-reordered object reindexes them again on the
21
+ * way out, so the writer emits keys one at a time in the caller's order —
22
+ * {@link serializeDataFile}.
23
+ */
24
+
25
+ /** Scan a (valid-JSON) string literal starting at the opening quote; returns the index just past the closing quote. */
26
+ function skipJsonString(text: string, i: number): number {
27
+ let j = i + 1;
28
+ while (j < text.length) {
29
+ const ch = text[j];
30
+ if (ch === '\\') {
31
+ j += 2;
32
+ continue;
33
+ }
34
+ if (ch === '"') return j + 1;
35
+ j++;
36
+ }
37
+ return j;
38
+ }
39
+
40
+ /** Scan one JSON value (string/object/array/number/bool/null) starting at `i`; returns the index just past it. Assumes well-formed JSON (only ever called on text `JSON.parse` already accepted). */
41
+ function skipJsonValue(text: string, i: number): number {
42
+ const ch = text[i];
43
+ if (ch === '"') return skipJsonString(text, i);
44
+ if (ch === '{' || ch === '[') {
45
+ const close = ch === '{' ? '}' : ']';
46
+ let depth = 1;
47
+ let j = i + 1;
48
+ while (j < text.length && depth > 0) {
49
+ const c = text[j];
50
+ if (c === '"') {
51
+ j = skipJsonString(text, j);
52
+ continue;
53
+ }
54
+ if (c === '{' || c === '[') depth++;
55
+ else if (c === close || c === '}' || c === ']') depth--;
56
+ j++;
57
+ }
58
+ return j;
59
+ }
60
+ // number / true / false / null — run until a structural character.
61
+ let j = i;
62
+ while (j < text.length && !/[,}\]\s]/.test(text[j]!)) j++;
63
+ return j;
64
+ }
65
+
66
+ /**
67
+ * Read a top-level JSON object's key order straight off the SOURCE TEXT — see
68
+ * fact #1 in the module header. Only ever called with text `JSON.parse`
69
+ * already accepted, so this can assume well-formed JSON throughout.
70
+ */
71
+ export function extractTopLevelKeyOrder(text: string): string[] {
72
+ const keys: string[] = [];
73
+ let i = 0;
74
+ const n = text.length;
75
+ const skipWs = () => {
76
+ while (i < n && /\s/.test(text[i]!)) i++;
77
+ };
78
+ skipWs();
79
+ if (text[i] !== '{') return keys;
80
+ i++;
81
+ skipWs();
82
+ while (i < n && text[i] !== '}') {
83
+ if (text[i] !== '"') break;
84
+ const keyEnd = skipJsonString(text, i);
85
+ const key = JSON.parse(text.slice(i, keyEnd)) as string;
86
+ if (!keys.includes(key)) keys.push(key);
87
+ i = keyEnd;
88
+ skipWs();
89
+ if (text[i] !== ':') break;
90
+ i++;
91
+ skipWs();
92
+ i = skipJsonValue(text, i);
93
+ skipWs();
94
+ if (text[i] === ',') {
95
+ i++;
96
+ skipWs();
97
+ continue;
98
+ }
99
+ break;
100
+ }
101
+ return keys;
102
+ }
103
+
104
+ /**
105
+ * Fold a commit's resulting keys into a stable order: `prevOrder` (the order
106
+ * the file currently has on disk) survives for every key still present, and
107
+ * any BRAND NEW key (add-row, a freshly-set nested field) is appended at the
108
+ * end in `Object.keys` order.
109
+ */
110
+ export function nextKeyOrder(
111
+ prevOrder: string[] | undefined,
112
+ obj: Record<string, unknown>,
113
+ ): string[] {
114
+ const existing = prevOrder ?? Object.keys(obj);
115
+ const kept = [...new Set(existing)].filter((k) => k in obj);
116
+ const added = Object.keys(obj).filter((k) => !existing.includes(k));
117
+ return [...kept, ...added];
118
+ }
119
+
120
+ /**
121
+ * Serialize per the diff-minimal contract: `"$schema"` first, then every other
122
+ * key in `keyOrder` (falling back to `Object.keys(obj)` when the caller has
123
+ * none — a brand-new file), 2-space indent, trailing newline. Emitting the
124
+ * object key by key is deliberate; see fact #2 in the module header.
125
+ */
126
+ export function serializeDataFile(obj: Record<string, unknown>, keyOrder?: string[]): string {
127
+ const hasSchema = '$schema' in obj;
128
+ const rest = (keyOrder ?? Object.keys(obj)).filter((k) => k !== '$schema' && k in obj);
129
+ const order = hasSchema ? ['$schema', ...rest] : rest;
130
+ if (order.length === 0) return '{}\n';
131
+ const lines = order.map((k) => {
132
+ const valueJson = JSON.stringify(obj[k], null, 2);
133
+ return ` ${JSON.stringify(k)}: ${valueJson.split('\n').join('\n ')}`;
134
+ });
135
+ return `{\n${lines.join(',\n')}\n}\n`;
136
+ }
137
+
138
+ /**
139
+ * The whole server-side fold in one call: the file's CURRENT text (absent for
140
+ * a file that does not exist yet) plus the values the client posted, giving
141
+ * the exact bytes to write.
142
+ */
143
+ export function foldDataFileText(
144
+ currentText: string | null,
145
+ values: Record<string, unknown>,
146
+ ): string {
147
+ let prevOrder: string[] | undefined;
148
+ if (currentText !== null) {
149
+ try {
150
+ JSON.parse(currentText);
151
+ prevOrder = extractTopLevelKeyOrder(currentText);
152
+ } catch {
153
+ // Unparseable file on disk — nothing to carry, so the posted values
154
+ // define the order. Never a reason to refuse the write.
155
+ }
156
+ }
157
+ return serializeDataFile(values, nextKeyOrder(prevOrder, values));
158
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ EDITOR_BRAND,
3
+ editorAppIconSvg,
4
+ editorDocumentTitle,
5
+ } from '@volter/editor-sdk/session/editor-brand';
6
+
7
+ function escapeHtml(value: string): string {
8
+ return value.replace(
9
+ /[&<>"']/g,
10
+ (character) =>
11
+ ({
12
+ '&': '&amp;',
13
+ '<': '&lt;',
14
+ '>': '&gt;',
15
+ '"': '&quot;',
16
+ "'": '&#39;',
17
+ })[character] ?? character,
18
+ );
19
+ }
20
+
21
+ export interface EditorBrandPageOptions {
22
+ readonly subject?: string;
23
+ readonly description: string;
24
+ /** Trusted, server-owned markup rendered inside the brand card. */
25
+ readonly contentHtml: string;
26
+ /** Trusted, server-owned script body. */
27
+ readonly scriptHtml?: string;
28
+ readonly socialPreview?: boolean;
29
+ }
30
+
31
+ /**
32
+ * Render the editor's small server-owned HTML surfaces (auth, share, yield).
33
+ * These pages intentionally stay dependency-free because they also appear
34
+ * while the main editor bundle is unavailable.
35
+ */
36
+ export function renderEditorBrandPage(options: EditorBrandPageOptions): string {
37
+ const title = editorDocumentTitle(options.subject);
38
+ const favicon = `data:image/svg+xml,${encodeURIComponent(editorAppIconSvg())}`;
39
+ const social = options.socialPreview
40
+ ? `<meta property="og:type" content="website">
41
+ <meta property="og:site_name" content="${escapeHtml(EDITOR_BRAND.name)}">
42
+ <meta property="og:title" content="${escapeHtml(title)}">
43
+ <meta property="og:description" content="${escapeHtml(options.description)}">
44
+
45
+ <meta name="twitter:card" content="summary">
46
+ <meta name="twitter:title" content="${escapeHtml(title)}">
47
+ <meta name="twitter:description" content="${escapeHtml(options.description)}">
48
+ `
49
+ : '';
50
+ const script = options.scriptHtml ? `<script>${options.scriptHtml}</script>` : '';
51
+ return `<!doctype html>
52
+ <html lang="en">
53
+ <head>
54
+ <meta charset="utf-8">
55
+ <meta name="viewport" content="width=device-width,initial-scale=1">
56
+ <meta name="theme-color" content="${EDITOR_BRAND.themeColor}">
57
+ <meta name="robots" content="noindex,nofollow">
58
+ <meta name="description" content="${escapeHtml(options.description)}">
59
+ <link rel="icon" href="${favicon}" type="image/svg+xml">
60
+ <title>${escapeHtml(title)}</title>
61
+ ${social}
62
+ <style>
63
+ :root{color-scheme:dark;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;background:${EDITOR_BRAND.themeColor};color:#e8edf3}
64
+ *{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;padding:24px;background:radial-gradient(circle at 50% 30%,#1c2a3a 0,${EDITOR_BRAND.themeColor} 52%,#0b0e13 100%)}
65
+ .brand-card{width:min(440px,100%);padding:34px;text-align:center;border:1px solid rgba(255,255,255,.1);border-radius:20px;background:rgba(23,28,35,.92);box-shadow:0 22px 60px rgba(0,0,0,.38)}
66
+ .brand-mark{width:68px;height:68px;margin:0 auto 20px}.brand-mark svg{display:block;width:100%;height:100%}h1{margin:0 0 10px;font-size:22px;line-height:1.25;color:#f4f6f8}p{margin:0;color:#aeb9c6;font-size:14px;line-height:1.6}
67
+ button,a.brand-action{display:inline-block;margin-top:20px;padding:9px 17px;border:1px solid #3a526c;border-radius:8px;background:#20354c;color:#eaf3ff;font:600 14px inherit;text-decoration:none;cursor:pointer}button:hover,a.brand-action:hover{background:#294561;border-color:${EDITOR_BRAND.accentColor}}
68
+ </style>
69
+ </head>
70
+ <body><main class="brand-card"><div class="brand-mark">${editorAppIconSvg()}</div>${options.contentHtml}</main>${script}</body>
71
+ </html>`;
72
+ }
@@ -0,0 +1,366 @@
1
+ /**
2
+ * The editor tab's duplex control socket — a WebSocket upgrade on the SAME
3
+ * path as the SSE stream (`/__editor/events`), carrying the SAME named events
4
+ * downstream and the tab's control replies upstream.
5
+ *
6
+ * Why it exists (measured 2026-08-09): a cold editor boot blocked a real
7
+ * tab's main thread for 60-100s. A blocked main thread can neither issue nor
8
+ * answer a `fetch`, so every receipt/result/state POST stopped — and the
9
+ * relay, which could only see silence, refused five plays that all executed
10
+ * later. Two things fix that here:
11
+ *
12
+ * - Upstream control traffic rides the ALREADY-OPEN socket instead of
13
+ * opening new HTTP requests, so it never queues behind a module flood in
14
+ * the browser's per-origin connection pool.
15
+ * - Liveness stops being a guess. The browser's NETWORK stack answers
16
+ * protocol pings while the main thread is blocked, and the page's INLINE
17
+ * bootstrap (index.html, attached before any module loads) answers a
18
+ * `control-echo`. Pong-fresh + echo-silent is "alive but busy" as a
19
+ * measured fact; an unanswered echo can never mean "the listener was not
20
+ * wired up yet", because the responder exists before the module graph does.
21
+ *
22
+ * Deliberately no frame-rate or rendering signal: games legitimately run
23
+ * `frameloop: 'never'` and the engine hidden-pauses loops in a background
24
+ * tab, so anything rAF-shaped would read a healthy tab as dead.
25
+ */
26
+
27
+ import type { Server as HttpServer, IncomingMessage } from 'node:http';
28
+ import type { Duplex } from 'node:stream';
29
+ import {
30
+ type EditorControlLifecycle,
31
+ parseEditorControlLifecycle,
32
+ } from '@volter/editor-sdk/session/editor-control-lifecycle';
33
+ import { type WebSocket, WebSocketServer } from 'ws';
34
+ import type { EditorSocketClient } from './editor-sse';
35
+
36
+ /** The one path both transports answer on. */
37
+ export const EDITOR_EVENTS_PATH = '/__editor/events';
38
+
39
+ /**
40
+ * Protocol-ping cadence. Short enough that a pong age reported in a refusal
41
+ * is meaningful evidence ("answered 3s ago" = the socket is genuinely live),
42
+ * long enough to be invisible next to the keepalive it replaces.
43
+ */
44
+ export const CONTROL_PING_INTERVAL_MS = 10_000;
45
+
46
+ /** How long the main-thread echo gets before it counts as unanswered. */
47
+ export const CONTROL_ECHO_TIMEOUT_MS = 1_000;
48
+
49
+ /**
50
+ * The socket ENDED WITH NO CLOSE FRAME — RFC 6455's 1006, which no endpoint is
51
+ * allowed to send and only an observer can synthesize. It is the shape a
52
+ * KILLED browser renderer process leaves behind (a tab that closes normally
53
+ * sends a frame), so it is also the discriminator the tab-death profile keys
54
+ * off. One owner of the literal: this file synthesizes it below,
55
+ * `editor-server.ts` reads it.
56
+ */
57
+ export const ABNORMAL_SOCKET_CLOSE = 1006;
58
+
59
+ /**
60
+ * The capability frame. Sent ONLY over a native socket, never on the SSE
61
+ * stream — the share tunnel's gateway bridges the SSE stream into its own
62
+ * WebSocket, and that socket does NOT accept upstream control frames. A tab
63
+ * behind the tunnel therefore never sees this and keeps POSTing, which is
64
+ * exactly right.
65
+ */
66
+ const DUPLEX_READY_EVENT = 'control-duplex';
67
+
68
+ export interface EditorControlConnection {
69
+ /** The pool handle for this socket. */
70
+ readonly client: EditorSocketClient;
71
+ /** The upgrade request's URL, for query parameters. */
72
+ readonly url: URL;
73
+ /** The raw upgrade request, for header-derived identity. */
74
+ readonly request: IncomingMessage;
75
+ /** Deliver one framed event before the client is pooled. */
76
+ send(event: string, data: string, id?: string): void;
77
+ /** Close the socket with a reason (rejected identity, session end). */
78
+ close(code: number, reason: string): void;
79
+ }
80
+
81
+ /**
82
+ * Another WebSocket path this session owns (the tab heartbeat).
83
+ *
84
+ * It rides the control socket's ONE `upgrade` listener rather than adding a
85
+ * second, because the fallthrough branch below has to know whether ANY editor
86
+ * path claimed the socket before it destroys it — and `listenerCount` cannot
87
+ * answer that once two of our own listeners are competing to say "not mine".
88
+ */
89
+ export interface RawSocketRoute {
90
+ readonly path: string;
91
+ /** Same shape as the control socket's own gate; a string refuses with 403. */
92
+ authorize(request: IncomingMessage, url: URL): string | null;
93
+ open(socket: WebSocket, url: URL, request: IncomingMessage): void;
94
+ }
95
+
96
+ export interface EditorControlSocketOptions {
97
+ /**
98
+ * Reject the upgrade BEFORE the handshake. Return an error string to
99
+ * refuse (sent as a plain 403 body, the same shape the SSE route answers
100
+ * with), or null to accept.
101
+ */
102
+ authorize(request: IncomingMessage, url: URL): string | null;
103
+ /**
104
+ * Register the open socket; the returned function runs once on close, and
105
+ * is handed the WebSocket close code/reason. Those two are the only honest
106
+ * answer to "why did this tab's channel go away" — the journal quotes them
107
+ * verbatim rather than inferring a story from the silence.
108
+ */
109
+ open(connection: EditorControlConnection): (close?: { code: number; reason: string }) => void;
110
+ /** The duplex capability was granted to this socket (journalling hook). */
111
+ duplexGranted?(connection: EditorControlConnection): void;
112
+ /** One upstream control frame from the tab. */
113
+ message(
114
+ type: string,
115
+ payload: Record<string, unknown>,
116
+ connection: EditorControlConnection,
117
+ lifecycle: EditorControlLifecycle | null,
118
+ lifecycleMalformed: boolean,
119
+ ): void;
120
+ /** Other WebSocket paths this one upgrade listener also routes. */
121
+ extraRoutes?: readonly RawSocketRoute[] | undefined;
122
+ }
123
+
124
+ export interface EditorControlSocketServer {
125
+ /**
126
+ * Handle `upgrade` on this HTTP server.
127
+ *
128
+ * Routes by PATHNAME and passes every other upgrade through untouched —
129
+ * Vite's HMR socket may share this server. When this is the only `upgrade`
130
+ * listener there is nobody to pass to, so the socket is destroyed, which is
131
+ * exactly what Node does by default with no listener at all.
132
+ */
133
+ attach(server: HttpServer): void;
134
+ /** Close every live control socket (server shutdown). */
135
+ close(): void;
136
+ }
137
+
138
+ /**
139
+ * One upstream `{ type, payload }` frame, or null if it is not one. A
140
+ * malformed frame is dropped, never partially read.
141
+ *
142
+ * The discriminator and the payload live in SEPARATE keys, and that
143
+ * separation is load-bearing in both directions. Flattened
144
+ * (`{ type, ...payload }`) the envelope leaked its own `type` into the state
145
+ * the server stored, so `vgai status` printed a field the tab never
146
+ * reported — on the exact seam this transport promises the POST route
147
+ * cannot drift from. And a payload key named `type` (a state snapshot is an
148
+ * open-ended object) would have overwritten the discriminator on the way
149
+ * out, turning a routine state report into an unknown control frame:
150
+ * dropped silently, health left stale, and the next refusal quoting a
151
+ * silence the tab never chose.
152
+ */
153
+ function parseControlFrame(raw: unknown): {
154
+ type: string;
155
+ payload: Record<string, unknown>;
156
+ lifecycle: EditorControlLifecycle | null;
157
+ lifecycleMalformed: boolean;
158
+ } | null {
159
+ let frame: unknown;
160
+ try {
161
+ frame = JSON.parse(String(raw));
162
+ } catch {
163
+ return null;
164
+ }
165
+ if (!frame || typeof frame !== 'object') return null;
166
+ const type = (frame as Record<string, unknown>)['type'];
167
+ if (typeof type !== 'string') return null;
168
+ const body = (frame as Record<string, unknown>)['payload'];
169
+ const rawLifecycle = (frame as Record<string, unknown>)['lifecycle'];
170
+ const lifecycle = parseEditorControlLifecycle(rawLifecycle);
171
+ return {
172
+ type,
173
+ payload: body && typeof body === 'object' ? (body as Record<string, unknown>) : {},
174
+ lifecycle,
175
+ lifecycleMalformed: rawLifecycle !== undefined && lifecycle === null,
176
+ };
177
+ }
178
+
179
+ export function createEditorControlSocket(
180
+ options: EditorControlSocketOptions,
181
+ ): EditorControlSocketServer {
182
+ const sockets = new WebSocketServer({ noServer: true });
183
+
184
+ const onUpgrade = (
185
+ server: HttpServer,
186
+ request: IncomingMessage,
187
+ socket: Duplex,
188
+ head: Buffer,
189
+ ): void => {
190
+ let url: URL;
191
+ try {
192
+ url = new URL(request.url ?? '/', 'http://editor.local');
193
+ } catch {
194
+ return;
195
+ }
196
+ const extra = (options.extraRoutes ?? []).find((route) => route.path === url.pathname);
197
+ if (extra) {
198
+ const extraRefusal = extra.authorize(request, url);
199
+ if (extraRefusal !== null) {
200
+ socket.end(
201
+ `HTTP/1.1 403 Forbidden\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n${extraRefusal}`,
202
+ );
203
+ return;
204
+ }
205
+ sockets.handleUpgrade(request, socket, head, (ws) => extra.open(ws, url, request));
206
+ return;
207
+ }
208
+ if (url.pathname !== EDITOR_EVENTS_PATH) {
209
+ // Not ours. Another listener (Vite HMR, the share gateway) owns it — or
210
+ // nobody does, in which case leaving the socket open would leak it.
211
+ if (server.listenerCount('upgrade') <= 1) socket.destroy();
212
+ return;
213
+ }
214
+ const refusal = options.authorize(request, url);
215
+ if (refusal !== null) {
216
+ socket.end(
217
+ `HTTP/1.1 403 Forbidden\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n${refusal}`,
218
+ );
219
+ return;
220
+ }
221
+ sockets.handleUpgrade(request, socket, head, (ws) => {
222
+ let closed = false;
223
+ let lastPongAt: number | null = null;
224
+ let echoSequence = 0;
225
+ const pendingEchoes = new Map<string, (answered: boolean) => void>();
226
+
227
+ const sendFrame = (event: string, data: string, id?: string): boolean => {
228
+ if (closed || ws.readyState !== ws.OPEN) return false;
229
+ try {
230
+ ws.send(JSON.stringify(id === undefined ? { event, data } : { event, data, id }));
231
+ return true;
232
+ } catch {
233
+ return false;
234
+ }
235
+ };
236
+
237
+ const client: EditorSocketClient = {
238
+ kind: 'socket',
239
+ sendFrame,
240
+ isClosed: () => closed || ws.readyState !== ws.OPEN,
241
+ lastPongAgeMs: () => (lastPongAt === null ? null : Date.now() - lastPongAt),
242
+ echo: (timeoutMs) =>
243
+ new Promise<boolean>((resolve) => {
244
+ if (closed || ws.readyState !== ws.OPEN) {
245
+ resolve(false);
246
+ return;
247
+ }
248
+ const id = `echo-${++echoSequence}`;
249
+ const timer = setTimeout(() => {
250
+ pendingEchoes.delete(id);
251
+ resolve(false);
252
+ }, timeoutMs);
253
+ timer.unref?.();
254
+ pendingEchoes.set(id, (answered) => {
255
+ clearTimeout(timer);
256
+ resolve(answered);
257
+ });
258
+ if (!sendFrame('control-echo', id)) {
259
+ pendingEchoes.delete(id);
260
+ clearTimeout(timer);
261
+ resolve(false);
262
+ }
263
+ }),
264
+ close: (code, reason) => {
265
+ try {
266
+ ws.close(code, reason);
267
+ } catch {
268
+ /* The close event owns teardown if the socket is still alive. */
269
+ }
270
+ },
271
+ };
272
+
273
+ const connection: EditorControlConnection = {
274
+ client,
275
+ url,
276
+ request,
277
+ send: (event, data, id) => {
278
+ sendFrame(event, data, id);
279
+ },
280
+ close: (code, reason) => {
281
+ try {
282
+ ws.close(code, reason);
283
+ } catch {
284
+ /* already gone */
285
+ }
286
+ },
287
+ };
288
+
289
+ const dispose = options.open(connection);
290
+
291
+ // Tell the page this socket takes upstream control frames. Only the
292
+ // native transport ever emits this (see DUPLEX_READY_EVENT).
293
+ if (sendFrame(DUPLEX_READY_EVENT, JSON.stringify({ ok: true }))) {
294
+ options.duplexGranted?.(connection);
295
+ }
296
+
297
+ // Ping immediately so the first refusal in this connection's life can
298
+ // still quote a real pong age, then on the standing cadence.
299
+ ws.on('pong', () => {
300
+ lastPongAt = Date.now();
301
+ });
302
+ const ping = () => {
303
+ if (closed || ws.readyState !== ws.OPEN) return;
304
+ try {
305
+ ws.ping();
306
+ } catch {
307
+ /* the close handler owns teardown */
308
+ }
309
+ };
310
+ ping();
311
+ const pingTimer = setInterval(ping, CONTROL_PING_INTERVAL_MS);
312
+ pingTimer.unref?.();
313
+
314
+ ws.on('message', (raw) => {
315
+ const frame = parseControlFrame(raw);
316
+ if (!frame) return;
317
+ if (frame.type === 'echo-reply') {
318
+ const id = frame.payload['id'];
319
+ if (typeof id !== 'string') return;
320
+ pendingEchoes.get(id)?.(true);
321
+ pendingEchoes.delete(id);
322
+ return;
323
+ }
324
+ options.message(
325
+ frame.type,
326
+ frame.payload,
327
+ connection,
328
+ frame.lifecycle,
329
+ frame.lifecycleMalformed,
330
+ );
331
+ });
332
+
333
+ const onClosed = (code?: number, reason?: Buffer | string) => {
334
+ if (closed) return;
335
+ closed = true;
336
+ clearInterval(pingTimer);
337
+ for (const settle of [...pendingEchoes.values()]) settle(false);
338
+ pendingEchoes.clear();
339
+ dispose({
340
+ code: typeof code === 'number' ? code : ABNORMAL_SOCKET_CLOSE,
341
+ reason: reason === undefined ? '' : String(reason),
342
+ });
343
+ };
344
+ ws.on('close', onClosed);
345
+ ws.on('error', () => onClosed());
346
+ });
347
+ };
348
+
349
+ return {
350
+ attach(server) {
351
+ server.on('upgrade', (request, socket, head) =>
352
+ onUpgrade(server, request, socket as Duplex, head),
353
+ );
354
+ },
355
+ close() {
356
+ for (const ws of sockets.clients) {
357
+ try {
358
+ ws.close(1001, 'editor session ended');
359
+ } catch {
360
+ /* best effort */
361
+ }
362
+ }
363
+ sockets.close();
364
+ },
365
+ };
366
+ }