@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,35 @@
1
+ import type { ResourceKey } from './types';
2
+
3
+ /** Serializes every in-process writer that touches the same authored resource. */
4
+ export class PersistenceCoordinator {
5
+ private readonly tails = new Map<ResourceKey, Promise<void>>();
6
+
7
+ run<T>(resource: ResourceKey, operation: () => Promise<T>): Promise<T> {
8
+ return this.runMany([resource], operation);
9
+ }
10
+
11
+ async runMany<T>(resources: readonly ResourceKey[], operation: () => Promise<T>): Promise<T> {
12
+ const keys = [...new Set(resources)].sort();
13
+ if (keys.length === 0) return operation();
14
+
15
+ const previous = keys.map((key) => this.tails.get(key) ?? Promise.resolve());
16
+ const acquired = Promise.all(previous).then(() => undefined);
17
+ let release!: () => void;
18
+ const held = new Promise<void>((resolve) => {
19
+ release = resolve;
20
+ });
21
+ const reservation = acquired.then(() => held);
22
+ for (const key of keys) this.tails.set(key, reservation);
23
+
24
+ await acquired;
25
+ try {
26
+ return await operation();
27
+ } finally {
28
+ release();
29
+ for (const key of keys) {
30
+ if (this.tails.get(key) !== reservation) continue;
31
+ this.tails.delete(key);
32
+ }
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,386 @@
1
+ import { sha256Hex } from '../bytes-codec';
2
+ import { getStorageBackend } from '../storage';
3
+ import type { HistoryService } from './history-service';
4
+ import { normalizeProjectPath } from './resource-registry';
5
+ import type {
6
+ ResourceDescriptor,
7
+ ResourceDriver,
8
+ ResourceKey,
9
+ ResourceKind,
10
+ ResourceSnapshot,
11
+ } from './types';
12
+
13
+ const ABSENT = 0;
14
+ const PRESENT = 1;
15
+
16
+ function encodeFile(exists: boolean, bytes: Uint8Array = new Uint8Array()): Uint8Array {
17
+ const encoded = new Uint8Array(bytes.byteLength + 1);
18
+ encoded[0] = exists ? PRESENT : ABSENT;
19
+ if (exists) encoded.set(bytes, 1);
20
+ return encoded;
21
+ }
22
+
23
+ function decodeFile(encoded: Uint8Array): { exists: boolean; bytes: Uint8Array } {
24
+ const marker = encoded[0];
25
+ if (marker !== ABSENT && marker !== PRESENT) throw new Error('Invalid project-file snapshot.');
26
+ return { exists: marker === PRESENT, bytes: encoded.slice(1) };
27
+ }
28
+
29
+ async function captureFile(
30
+ backend: HistoryFileBackend,
31
+ path: string,
32
+ revision: number,
33
+ contentType: string,
34
+ ): Promise<ResourceSnapshot> {
35
+ const exists = await backend.exists(path);
36
+ const bytes = encodeFile(exists, exists ? await backend.readBytes(path) : undefined);
37
+ return { revision, contentType, bytes, sha256: await sha256Hex(bytes) };
38
+ }
39
+
40
+ interface ManagedFile {
41
+ descriptor: ResourceDescriptor;
42
+ revision: number;
43
+ contentType: string;
44
+ listeners: Set<() => void>;
45
+ }
46
+
47
+ export interface ProjectFileMutation {
48
+ readonly path: string;
49
+ readonly data: string | Uint8Array | null;
50
+ readonly kind?: ResourceKind;
51
+ readonly contentType?: string;
52
+ }
53
+
54
+ interface ProjectFileFingerprint {
55
+ readonly path: string;
56
+ readonly sha256: string;
57
+ }
58
+
59
+ export interface ProjectFileMutationSession {
60
+ /** Refuse before invoking a project-owned serializer when an opened file has
61
+ * already changed. The transactional check in mutate remains the final
62
+ * race-safe authority. */
63
+ assertUnchanged(): Promise<void>;
64
+ /**
65
+ * Writes only while every resource still matches the exact bytes this
66
+ * session opened. A successful write advances that baseline to the bytes
67
+ * just committed; a conflict leaves both the files and baseline untouched.
68
+ */
69
+ mutate(changes: readonly ProjectFileMutation[], options: { label: string }): Promise<boolean>;
70
+ }
71
+
72
+ export class ProjectFileContentConflictError extends Error {
73
+ constructor(readonly path: string) {
74
+ super(
75
+ `Project file "${path}" no longer matches the bytes loaded into this Asset Lab document. ` +
76
+ 'Reopen the document to review the newer file; the editor did not overwrite it.',
77
+ );
78
+ this.name = 'ProjectFileContentConflictError';
79
+ }
80
+ }
81
+
82
+ /** Exact-byte, existence-aware history for project files reached through StorageBackend. */
83
+ export class ProjectFileHistory {
84
+ private readonly files = new Map<string, ManagedFile>();
85
+ private readonly listeners = new Set<(path: string) => void>();
86
+
87
+ constructor(
88
+ private readonly history: HistoryService,
89
+ private readonly backend: HistoryFileBackend,
90
+ ) {}
91
+
92
+ write(
93
+ path: string,
94
+ data: string | Uint8Array,
95
+ options: { label: string; kind?: ResourceKind; contentType?: string },
96
+ ): Promise<boolean> {
97
+ const normalized = normalizeProjectPath(path);
98
+ const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : Uint8Array.from(data);
99
+ const file = this.file(
100
+ normalized,
101
+ options.kind ?? 'project-file',
102
+ options.contentType ?? (typeof data === 'string' ? 'text/plain' : 'application/octet-stream'),
103
+ );
104
+ return this.history.transaction(
105
+ { label: options.label, resources: [file.descriptor.key], scope: 'project' },
106
+ async (tx) => {
107
+ await tx.write(file.descriptor.key, encodeFile(true, bytes), file.contentType);
108
+ return true;
109
+ },
110
+ );
111
+ }
112
+
113
+ writeWithResources(
114
+ path: string,
115
+ data: string | Uint8Array,
116
+ options: { label: string; kind?: ResourceKind; contentType?: string },
117
+ additional: readonly {
118
+ resource: ResourceKey;
119
+ bytes: Uint8Array;
120
+ contentType: string;
121
+ }[],
122
+ ): Promise<boolean> {
123
+ const normalized = normalizeProjectPath(path);
124
+ const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : Uint8Array.from(data);
125
+ const file = this.file(
126
+ normalized,
127
+ options.kind ?? 'project-file',
128
+ options.contentType ?? (typeof data === 'string' ? 'text/plain' : 'application/octet-stream'),
129
+ );
130
+ return this.history.transaction(
131
+ {
132
+ label: options.label,
133
+ resources: [file.descriptor.key, ...additional.map((change) => change.resource)],
134
+ scope: 'project',
135
+ },
136
+ async (tx) => {
137
+ await tx.write(file.descriptor.key, encodeFile(true, bytes), file.contentType);
138
+ for (const change of additional) {
139
+ await tx.write(change.resource, change.bytes, change.contentType);
140
+ }
141
+ return true;
142
+ },
143
+ );
144
+ }
145
+
146
+ remove(
147
+ path: string,
148
+ options: { label: string; kind?: ResourceKind; contentType?: string },
149
+ ): Promise<boolean> {
150
+ const normalized = normalizeProjectPath(path);
151
+ const file = this.file(
152
+ normalized,
153
+ options.kind ?? 'project-file',
154
+ options.contentType ?? 'application/octet-stream',
155
+ );
156
+ return this.history.transaction(
157
+ { label: options.label, resources: [file.descriptor.key], scope: 'project' },
158
+ async (tx) => {
159
+ await tx.write(file.descriptor.key, encodeFile(false), file.contentType);
160
+ return true;
161
+ },
162
+ );
163
+ }
164
+
165
+ /** Apply a logical multi-file operation as one failure-atomic undo step. */
166
+ mutate(
167
+ changes: readonly ProjectFileMutation[],
168
+ options: { label: string; expected?: readonly ProjectFileFingerprint[] },
169
+ ): Promise<boolean> {
170
+ const staged = changes.map((change) => {
171
+ const path = normalizeProjectPath(change.path);
172
+ const contentType = change.contentType ?? 'application/octet-stream';
173
+ return {
174
+ change,
175
+ file: this.file(path, change.kind ?? 'project-file', contentType),
176
+ contentType,
177
+ };
178
+ });
179
+ const uniqueResources = new Set(staged.map(({ file }) => file.descriptor.key));
180
+ if (uniqueResources.size !== staged.length) {
181
+ throw new Error('A project-file mutation cannot write the same path twice.');
182
+ }
183
+ const expected = new Map(
184
+ options.expected?.map((fingerprint) => [
185
+ normalizeProjectPath(fingerprint.path),
186
+ fingerprint.sha256,
187
+ ]),
188
+ );
189
+ if (
190
+ options.expected &&
191
+ (expected.size !== staged.length ||
192
+ staged.some(({ change }) => !expected.has(normalizeProjectPath(change.path))))
193
+ ) {
194
+ throw new Error('A guarded project-file mutation must cover exactly the opened paths.');
195
+ }
196
+ return this.history.transaction(
197
+ { label: options.label, resources: [...uniqueResources], scope: 'project' },
198
+ async (tx) => {
199
+ for (const { change, file, contentType } of staged) {
200
+ const before = await tx.read(file.descriptor.key);
201
+ const path = normalizeProjectPath(change.path);
202
+ const expectedSha = expected.get(path);
203
+ if (expectedSha !== undefined && before.sha256 !== expectedSha) {
204
+ throw new ProjectFileContentConflictError(path);
205
+ }
206
+ const bytes =
207
+ change.data === null
208
+ ? encodeFile(false)
209
+ : encodeFile(
210
+ true,
211
+ typeof change.data === 'string'
212
+ ? new TextEncoder().encode(change.data)
213
+ : Uint8Array.from(change.data),
214
+ );
215
+ await tx.write(file.descriptor.key, bytes, contentType);
216
+ }
217
+ return true;
218
+ },
219
+ );
220
+ }
221
+
222
+ /**
223
+ * Opens a long-lived optimistic-concurrency boundary from the exact bytes a
224
+ * document's serializers say are currently loaded in memory.
225
+ */
226
+ async openMutationSession(
227
+ initial: readonly ProjectFileMutation[],
228
+ ): Promise<ProjectFileMutationSession> {
229
+ let expected = await this.fingerprintMutations(initial);
230
+ const contentTypes = new Map(
231
+ initial.map((change) => [
232
+ normalizeProjectPath(change.path),
233
+ change.contentType ?? 'application/octet-stream',
234
+ ]),
235
+ );
236
+ const assertUnchanged = async () => {
237
+ for (const fingerprint of expected) {
238
+ const current = await captureFile(
239
+ this.backend,
240
+ fingerprint.path,
241
+ 0,
242
+ contentTypes.get(fingerprint.path) ?? 'application/octet-stream',
243
+ );
244
+ if (current.sha256 !== fingerprint.sha256) {
245
+ throw new ProjectFileContentConflictError(fingerprint.path);
246
+ }
247
+ }
248
+ };
249
+ await assertUnchanged();
250
+ return {
251
+ assertUnchanged,
252
+ mutate: async (changes, options) => {
253
+ const next = await this.fingerprintMutations(changes);
254
+ const changed = await this.mutate(changes, { ...options, expected });
255
+ expected = next;
256
+ for (const change of changes) {
257
+ contentTypes.set(
258
+ normalizeProjectPath(change.path),
259
+ change.contentType ?? 'application/octet-stream',
260
+ );
261
+ }
262
+ return changed;
263
+ },
264
+ };
265
+ }
266
+
267
+ subscribe(path: string, listener: () => void): () => void {
268
+ const normalized = normalizeProjectPath(path);
269
+ const file = this.files.get(normalized);
270
+ if (!file) throw new Error(`Project file "${normalized}" is not registered with history.`);
271
+ file.listeners.add(listener);
272
+ return () => file.listeners.delete(listener);
273
+ }
274
+
275
+ subscribeAll(listener: (path: string) => void): () => void {
276
+ this.listeners.add(listener);
277
+ return () => this.listeners.delete(listener);
278
+ }
279
+
280
+ private file(path: string, kind: ResourceKind, contentType: string): ManagedFile {
281
+ const existing = this.files.get(path);
282
+ if (existing) {
283
+ if (existing.descriptor.kind !== kind) {
284
+ throw new Error(
285
+ `Project file "${path}" is already registered as ${existing.descriptor.kind}.`,
286
+ );
287
+ }
288
+ existing.contentType = contentType;
289
+ return existing;
290
+ }
291
+ const descriptor = this.history.registry.registerProject(kind, path);
292
+ const file: ManagedFile = {
293
+ descriptor,
294
+ revision: 0,
295
+ contentType,
296
+ listeners: new Set(),
297
+ };
298
+ const driver: ResourceDriver = {
299
+ descriptor,
300
+ capture: () => captureFile(this.backend, path, file.revision, file.contentType),
301
+ preflight: async (expected) => {
302
+ const current = await captureFile(this.backend, path, file.revision, file.contentType);
303
+ return current.sha256 === expected.sha256
304
+ ? { ok: true }
305
+ : {
306
+ ok: false,
307
+ reason: 'content-conflict',
308
+ actualRevision: file.revision,
309
+ actualSha256: current.sha256,
310
+ };
311
+ },
312
+ restore: async (snapshot) => {
313
+ const decoded = decodeFile(this.history.snapshots.read(snapshot).bytes);
314
+ if (decoded.exists) await this.backend.write(path, decoded.bytes);
315
+ else await this.backend.remove(path);
316
+ file.revision++;
317
+ for (const listener of file.listeners) listener();
318
+ for (const listener of this.listeners) listener(path);
319
+ },
320
+ estimateBytes: (snapshot) => snapshot.byteLength,
321
+ };
322
+ this.history.registerDriver(driver);
323
+ this.files.set(path, file);
324
+ return file;
325
+ }
326
+
327
+ private async fingerprintMutations(
328
+ changes: readonly ProjectFileMutation[],
329
+ ): Promise<ProjectFileFingerprint[]> {
330
+ const paths = new Set<string>();
331
+ const fingerprints: ProjectFileFingerprint[] = [];
332
+ for (const change of changes) {
333
+ const path = normalizeProjectPath(change.path);
334
+ if (paths.has(path)) {
335
+ throw new Error('A project-file mutation cannot write the same path twice.');
336
+ }
337
+ paths.add(path);
338
+ const bytes =
339
+ change.data === null
340
+ ? encodeFile(false)
341
+ : encodeFile(
342
+ true,
343
+ typeof change.data === 'string'
344
+ ? new TextEncoder().encode(change.data)
345
+ : Uint8Array.from(change.data),
346
+ );
347
+ fingerprints.push({ path, sha256: await sha256Hex(bytes) });
348
+ }
349
+ return fingerprints;
350
+ }
351
+ }
352
+
353
+ export interface HistoryFileBackend {
354
+ readonly id: string;
355
+ readBytes(path: string): Promise<Uint8Array>;
356
+ write(path: string, data: string | Uint8Array): Promise<void>;
357
+ exists(path: string): Promise<boolean>;
358
+ remove(path: string): Promise<void>;
359
+ }
360
+
361
+ const managers = new WeakMap<
362
+ HistoryService,
363
+ Map<string, { backend: HistoryFileBackend; manager: ProjectFileHistory }>
364
+ >();
365
+
366
+ export function getProjectFileHistory(
367
+ history: HistoryService,
368
+ backend: HistoryFileBackend = getStorageBackend(),
369
+ namespace = 'public',
370
+ ): ProjectFileHistory {
371
+ let byNamespace = managers.get(history);
372
+ if (!byNamespace) {
373
+ byNamespace = new Map();
374
+ managers.set(history, byNamespace);
375
+ }
376
+ const existing = byNamespace.get(namespace);
377
+ if (existing) {
378
+ if (existing.backend !== backend) {
379
+ throw new Error('The project storage backend changed without creating a new editor session.');
380
+ }
381
+ return existing.manager;
382
+ }
383
+ const manager = new ProjectFileHistory(history, backend);
384
+ byNamespace.set(namespace, { backend, manager });
385
+ return manager;
386
+ }
@@ -0,0 +1,139 @@
1
+ import { bytesToBase64 } from '../bytes-codec';
2
+ import { assertEditorServerAnswered } from '../editor-server-response';
3
+ import { sourceMutationAttribution } from '../editor-session-attribution';
4
+ import { handleProjectMutationFailure } from '../source-conflict';
5
+ import type { HistoryFileBackend } from './project-file-history';
6
+
7
+ /**
8
+ * Split by CONTENT TYPE, both classes below:
9
+ *
10
+ * - the MUTATING halves (`write`/`remove`) answer JSON — `{ ok, revision }` or
11
+ * an `{ error }` — and are read through `editor-server-response.ts`, because
12
+ * `!response.ok` alone let a page fallback report an undo/redo write that
13
+ * reached nothing as applied;
14
+ * - the READ halves (`readBytes`/`exists`) answer RAW BYTES, so that reader's
15
+ * `application/json` rule would reject their successes. They are deliberately
16
+ * left on the status code; `exists` inherits the fallback's false `true`,
17
+ * and closing that needs a body-shape discriminator this route does not have.
18
+ */
19
+ class ScopedHttpHistoryBackend implements HistoryFileBackend {
20
+ constructor(
21
+ readonly id: string,
22
+ private readonly endpoint: string,
23
+ ) {}
24
+
25
+ async readBytes(path: string): Promise<Uint8Array> {
26
+ const response = await fetch(`${this.endpoint}?${new URLSearchParams({ path })}`);
27
+ if (!response.ok) throw new Error(`${this.id}.readBytes '${path}': HTTP ${response.status}`);
28
+ return new Uint8Array(await response.arrayBuffer());
29
+ }
30
+
31
+ async write(path: string, data: string | Uint8Array): Promise<void> {
32
+ const content = typeof data === 'string' ? data : new TextDecoder().decode(data);
33
+ const response = await fetch(this.endpoint, {
34
+ method: 'POST',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ body: JSON.stringify({ path, content, ...sourceMutationAttribution() }),
37
+ });
38
+ assertEditorServerAnswered(response, `${this.id} write ${path} failed`);
39
+ if (!response.ok) {
40
+ await handleProjectMutationFailure(response, {
41
+ label: `${this.id} write ${path}`,
42
+ attempted: { [path]: content },
43
+ reapply: () => this.write(path, data),
44
+ });
45
+ }
46
+ }
47
+
48
+ async exists(path: string): Promise<boolean> {
49
+ const response = await fetch(`${this.endpoint}?${new URLSearchParams({ path })}`);
50
+ if (response.status === 404) return false;
51
+ if (!response.ok) throw new Error(`${this.id}.exists '${path}': HTTP ${response.status}`);
52
+ return true;
53
+ }
54
+
55
+ async remove(path: string): Promise<void> {
56
+ const response = await fetch(this.endpoint, {
57
+ method: 'DELETE',
58
+ headers: { 'Content-Type': 'application/json' },
59
+ body: JSON.stringify({ path, ...sourceMutationAttribution() }),
60
+ });
61
+ assertEditorServerAnswered(response, `${this.id} delete ${path} failed`);
62
+ if (!response.ok) {
63
+ await handleProjectMutationFailure(response, {
64
+ label: `${this.id} delete ${path}`,
65
+ attempted: { [path]: null },
66
+ reapply: () => this.remove(path),
67
+ });
68
+ }
69
+ }
70
+ }
71
+
72
+ const manifestHttp = new ScopedHttpHistoryBackend('project-manifest-http', '/__editor/manifest');
73
+
74
+ class ProjectResourceHttpHistoryBackend implements HistoryFileBackend {
75
+ readonly id = 'project-resource-http';
76
+ private readonly endpoint = '/__editor/project-resource';
77
+
78
+ async readBytes(path: string): Promise<Uint8Array> {
79
+ const response = await fetch(`${this.endpoint}?${new URLSearchParams({ path })}`);
80
+ if (!response.ok) throw new Error(`${this.id}.readBytes '${path}': HTTP ${response.status}`);
81
+ return new Uint8Array(await response.arrayBuffer());
82
+ }
83
+
84
+ async write(path: string, data: string | Uint8Array): Promise<void> {
85
+ const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;
86
+ const response = await fetch(this.endpoint, {
87
+ method: 'POST',
88
+ headers: { 'Content-Type': 'application/json' },
89
+ body: JSON.stringify({
90
+ path,
91
+ content: bytesToBase64(bytes),
92
+ encoding: 'base64',
93
+ ...sourceMutationAttribution(),
94
+ }),
95
+ });
96
+ assertEditorServerAnswered(response, `${this.id} write ${path} failed`);
97
+ if (!response.ok) {
98
+ await handleProjectMutationFailure(response, {
99
+ label: `${this.id} write ${path}`,
100
+ attempted: { [path]: `[${bytes.byteLength} bytes]` },
101
+ reapply: () => this.write(path, data),
102
+ });
103
+ }
104
+ }
105
+
106
+ async exists(path: string): Promise<boolean> {
107
+ const response = await fetch(`${this.endpoint}?${new URLSearchParams({ path })}`);
108
+ if (response.status === 404) return false;
109
+ if (!response.ok) throw new Error(`${this.id}.exists '${path}': HTTP ${response.status}`);
110
+ return true;
111
+ }
112
+
113
+ async remove(path: string): Promise<void> {
114
+ const response = await fetch(this.endpoint, {
115
+ method: 'DELETE',
116
+ headers: { 'Content-Type': 'application/json' },
117
+ body: JSON.stringify({ path, ...sourceMutationAttribution() }),
118
+ });
119
+ assertEditorServerAnswered(response, `${this.id} delete ${path} failed`);
120
+ if (!response.ok) {
121
+ await handleProjectMutationFailure(response, {
122
+ label: `${this.id} delete ${path}`,
123
+ attempted: { [path]: null },
124
+ reapply: () => this.remove(path),
125
+ });
126
+ }
127
+ }
128
+ }
129
+
130
+ const projectResourceHttp = new ProjectResourceHttpHistoryBackend();
131
+
132
+ export function getManifestHistoryBackend(): HistoryFileBackend {
133
+ return manifestHttp;
134
+ }
135
+
136
+ /** Exact project-root bytes for project-owned Asset Lab documents. */
137
+ export function getProjectResourceHistoryBackend(): HistoryFileBackend {
138
+ return projectResourceHttp;
139
+ }