@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,126 @@
1
+ /**
2
+ * THE ANSWER A STUCK PLAY OWES ITS CALLER.
3
+ *
4
+ * ## What this replaces
5
+ *
6
+ * Measured 2026-08-20 with `packages/editor/scripts/scale-harness`, canvas lane,
7
+ * N=20000, four consecutive runs. `vgai play` spent its full 120s budget and was
8
+ * refused with
9
+ *
10
+ * Command timed out — the tab is present (last heartbeat 0.8s ago) and
11
+ * did not respond.
12
+ *
13
+ * and then `screenshot` (15s) and `stop` (30s) were refused with that same
14
+ * sentence. Three silent timeouts in a row, and every reader — `vgai status`,
15
+ * the tab table, the journal — described a healthy session, because the
16
+ * heartbeat is a WORKER and kept beating at 0.4s while the page's main thread
17
+ * sat inside one 199.5-second synchronous block.
18
+ *
19
+ * The sentence was true and useless. It named the tab (fine), the beat (fine),
20
+ * and nothing about the eight-step boot that was actually stuck.
21
+ *
22
+ * ## The rule
23
+ *
24
+ * The page publishes each play-boot phase BEFORE that phase's work starts
25
+ * (`src/play-boot-phase.ts`), on the control channel, as its own tiny message —
26
+ * never inside the state snapshot, which is the expensive derivation a wedged
27
+ * page cannot produce. So the server always holds the phase the page was
28
+ * ENTERING when it went quiet, and this module turns that into the refusal, the
29
+ * journal row and the console entry.
30
+ *
31
+ * Pure and clock-injected: no I/O, no globals. `test/play-stall.test.ts` drives
32
+ * every branch directly.
33
+ */
34
+
35
+ /** What the page last said about its play boot, as the server holds it. */
36
+ export interface PlayPhaseRecord {
37
+ /** The phase being entered, or `null` once the boot settled either way. */
38
+ readonly phase: string | null;
39
+ /** Page clock: when it entered that phase. Never used for arithmetic — the
40
+ * two clocks are not the same clock — only carried for the record. */
41
+ readonly at: number;
42
+ /** The play attempt's ordinal on the page. */
43
+ readonly run: number;
44
+ /** SERVER clock: when this report landed. Every age below is measured from
45
+ * here, because it is the only timestamp both parties agree on. */
46
+ readonly receivedAt: number;
47
+ }
48
+
49
+ /** Commands whose timeout is about play whether or not a boot is in flight. */
50
+ const PLAY_FAMILY = new Set(['play', 'restart', 'stop', 'pause', 'resume', 'step']);
51
+
52
+ export interface PlayStallDiagnosis {
53
+ /** The full refusal the caller receives. */
54
+ readonly message: string;
55
+ /** The phase named, or `null` when no boot was in flight. */
56
+ readonly phase: string | null;
57
+ /** How long the page had been in it when the command expired, or `null`. */
58
+ readonly phaseAgeMs: number | null;
59
+ }
60
+
61
+ /**
62
+ * Compose the refusal for a relayed command that ran out of budget.
63
+ *
64
+ * `base` is the sentence the relay already produces (`Command timed out — the
65
+ * tab is present (…) and did not respond.`). It is kept VERBATIM and only
66
+ * extended: the CLI's own retry classifier matches fragments of these
67
+ * refusals (`vgai-cli/src/play-retry.ts`), and a rewritten message would
68
+ * silently change which failures it treats as retryable.
69
+ */
70
+ export function playStallDiagnosis(args: {
71
+ readonly command: unknown;
72
+ readonly base: string;
73
+ readonly phase: PlayPhaseRecord | null;
74
+ readonly now: number;
75
+ }): PlayStallDiagnosis {
76
+ const { base, phase, now } = args;
77
+ const command = typeof args.command === 'string' ? args.command : '';
78
+ const booting = phase !== null && phase.phase !== null;
79
+
80
+ if (booting) {
81
+ const ageMs = Math.max(0, now - phase.receivedAt);
82
+ return {
83
+ phase: phase.phase,
84
+ phaseAgeMs: ageMs,
85
+ message:
86
+ `${base} The page is still inside "${phase.phase}" — it entered that step ` +
87
+ `${(ageMs / 1000).toFixed(1)}s ago and has not left it. The page's own main thread is ` +
88
+ 'inside that step; the heartbeat above is a worker, which is why the tab looks healthy ' +
89
+ 'while nothing the page owns can answer. `volter-editor status` names the same phase, and the ' +
90
+ 'session journal has the row.',
91
+ };
92
+ }
93
+
94
+ if (PLAY_FAMILY.has(command)) {
95
+ const settled = phase === null ? null : Math.max(0, now - phase.receivedAt);
96
+ const when =
97
+ settled === null
98
+ ? 'this session has never reported one'
99
+ : `the last one settled ${(settled / 1000).toFixed(1)}s ago`;
100
+ return {
101
+ phase: null,
102
+ phaseAgeMs: null,
103
+ message:
104
+ `${base} No play boot is in flight (${when}), so the page went quiet somewhere other ` +
105
+ 'than play start — a heartbeat proves the tab, never the page.',
106
+ };
107
+ }
108
+
109
+ return { phase: null, phaseAgeMs: null, message: base };
110
+ }
111
+
112
+ /**
113
+ * The console-ledger condition text for a stalled command.
114
+ *
115
+ * Deliberately keyed on the PHASE and not on the elapsed time: the ledger
116
+ * fingerprints on the message, so putting a duration in it would make every
117
+ * occurrence a fresh condition and turn a repeating stall into a wall of
118
+ * one-count rows — the exact dedup failure `console-ledger.ts` exists to
119
+ * prevent, in the other direction.
120
+ */
121
+ export function playStallConsoleMessage(command: unknown, phase: string | null): string {
122
+ const verb = typeof command === 'string' && command.length > 0 ? command : 'a command';
123
+ return phase === null
124
+ ? `\`${verb}\` timed out against a beating tab whose page never answered, with no play boot in flight.`
125
+ : `\`${verb}\` timed out while the page was inside "${phase}".`;
126
+ }
@@ -0,0 +1,218 @@
1
+ import { type ChildProcess, execFileSync } from 'node:child_process';
2
+ import type { Server } from 'node:http';
3
+
4
+ /** How long a detached child gets between SIGTERM and SIGKILL when its caller
5
+ * does not say. A caller INSIDE the session's shutdown list passes a smaller
6
+ * number, because its own budget is smaller than this — see
7
+ * `createProcessShutdown`'s note on the arithmetic. */
8
+ const DEFAULT_STOP_GRACE_MS = 5_000;
9
+
10
+ /**
11
+ * Terminate a detached child and its whole process tree. Shared by the e2e
12
+ * server harness and the packaged E2E runner: keeping this under `server/`
13
+ * makes the runtime utility part of the editor package instead of forcing a
14
+ * published command to import an unshipped e2e helper.
15
+ *
16
+ * `graceMs` is the SIGTERM→SIGKILL window. It is a parameter because the
17
+ * session's shutdown list has a tighter budget than this default: a child that
18
+ * outlives its caller's own exit is an ORPHAN holding a reserved port, so the
19
+ * escalation has to complete inside the caller's window, not after it.
20
+ */
21
+ export function stopProcess(proc: ChildProcess, graceMs = DEFAULT_STOP_GRACE_MS): Promise<void> {
22
+ const signalGroup = (signal: NodeJS.Signals) => {
23
+ if (proc.pid === undefined) return;
24
+ if (process.platform === 'win32') {
25
+ try {
26
+ execFileSync('taskkill', ['/PID', String(proc.pid), '/T', '/F'], { stdio: 'ignore' });
27
+ } catch {
28
+ /* already dead, or taskkill unavailable */
29
+ }
30
+ try {
31
+ proc.kill(signal);
32
+ } catch {
33
+ /* already dead */
34
+ }
35
+ return;
36
+ }
37
+ try {
38
+ process.kill(-proc.pid, signal);
39
+ } catch {
40
+ try {
41
+ proc.kill(signal);
42
+ } catch {
43
+ /* already dead */
44
+ }
45
+ }
46
+ };
47
+
48
+ return new Promise((resolve) => {
49
+ if (proc.exitCode !== null || proc.signalCode !== null) {
50
+ signalGroup('SIGKILL');
51
+ resolve();
52
+ return;
53
+ }
54
+ const timer = setTimeout(() => {
55
+ signalGroup('SIGKILL');
56
+ resolve();
57
+ }, graceMs);
58
+ proc.on('exit', () => {
59
+ clearTimeout(timer);
60
+ signalGroup('SIGKILL');
61
+ resolve();
62
+ });
63
+ signalGroup('SIGTERM');
64
+ });
65
+ }
66
+
67
+ /**
68
+ * ONE RESOURCE THIS SESSION IS STOPPING, and the name a post-mortem will read.
69
+ *
70
+ * The name is required because the failure this list exists to survive is
71
+ * UNATTENDED: a task that never settles is only visible as the ABSENCE of
72
+ * everything after it, and "cleanup timed out" with no name leaves a reader
73
+ * guessing which resource is still alive.
74
+ */
75
+ export interface ShutdownTask {
76
+ /** What this stops, in the words a journal line should carry. */
77
+ readonly name: string;
78
+ run(): void | Promise<void>;
79
+ }
80
+
81
+ export interface ProcessShutdownOptions {
82
+ /** The WHOLE list's backstop. Bigger than `taskTimeoutMs` and nothing more:
83
+ * with every task bounded and independent, the list's own duration is the
84
+ * slowest task's, and this only catches a bug in the bounding itself. */
85
+ timeoutMs?: number;
86
+ /** Each task's OWN bound. See the note on `createProcessShutdown`. */
87
+ taskTimeoutMs?: number;
88
+ tasks: ReadonlyArray<ShutdownTask>;
89
+ exit?: (code: number) => void;
90
+ log?: (message: string) => void;
91
+ /** Where a task that did not finish, or threw, is RECORDED — the session
92
+ * journal, handed in by the host because this module owns no project. */
93
+ journal?: (record: {
94
+ readonly task: string;
95
+ readonly outcome: 'timeout' | 'failed';
96
+ readonly ms: number;
97
+ readonly detail?: string;
98
+ }) => void;
99
+ }
100
+
101
+ /** Stop accepting requests and forcibly release persistent HTTP/SSE sockets. */
102
+ export function closeHttpServer(server: Server): Promise<void> {
103
+ return new Promise((resolve, reject) => {
104
+ if (!server.listening) {
105
+ server.closeAllConnections?.();
106
+ resolve();
107
+ return;
108
+ }
109
+ server.close((error) => (error ? reject(error) : resolve()));
110
+ // `server.close()` waits for persistent SSE/keep-alive connections. They
111
+ // have no useful work after process shutdown begins, so close them after
112
+ // removing the listener and eliminate the restart race on the HTTP port.
113
+ server.closeAllConnections?.();
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Build an idempotent, bounded signal handler.
119
+ *
120
+ * Node's default signal exit is disabled as soon as an application installs
121
+ * a SIGTERM/SIGINT listener. Tooling loaders (notably tsx/esbuild) may retain
122
+ * internal handles even after every application server and watcher closes,
123
+ * so waiting for an empty event loop is not a shutdown contract. Resources
124
+ * get one bounded graceful window and then the process exits explicitly.
125
+ *
126
+ * EVERY TASK RUNS INDEPENDENTLY AND EVERY TASK IS BOUNDED BY ITSELF. Both
127
+ * halves were bought by one measurement (2026-09-21, load average ~30, one
128
+ * `vgai close`): the session's journal had no `session-shutdown` line, the
129
+ * Code-OSS server survived as PPID 1 still holding its reserved `frame` port,
130
+ * and the next `vgai edit` refused by name. A shared bound is what makes one
131
+ * slow resource spend everybody's window, and the arithmetic has to close:
132
+ * `vgai close` SIGTERMs, waits 5.5 s and SIGKILLs the session's process GROUP —
133
+ * which never reaches the Code-OSS server, because that child is spawned
134
+ * detached into a group of its own. So the last of these tasks has to have
135
+ * FINISHED by then, not merely started, or a child outlives its parent with
136
+ * nobody left to signal it.
137
+ *
138
+ * A TASK THAT DOES NOT FINISH IS NAMED (`journal`), because the only other
139
+ * evidence it leaves is the absence of everything downstream of it.
140
+ */
141
+ export function createProcessShutdown(
142
+ options: ProcessShutdownOptions,
143
+ ): (why: string) => Promise<void> {
144
+ // 4 s per task, 4.8 s for the list: the whole shutdown fits inside `vgai
145
+ // close`'s 5.5 s grace with room for the process's own exit, which the old
146
+ // 2 s tab wait plus a 5 s shared cleanup budget did not. The 4 s is sized so
147
+ // a task that must follow the tab-close notice (whose own budget is 2 s)
148
+ // still has ~2 s of its own — see dev.ts's list.
149
+ const taskTimeoutMs = options.taskTimeoutMs ?? 4_000;
150
+ const timeoutMs = options.timeoutMs ?? 4_800;
151
+ const exit = options.exit ?? ((code: number) => process.exit(code));
152
+ const log = options.log ?? ((message: string) => process.stderr.write(`${message}\n`));
153
+ const journal = options.journal ?? (() => {});
154
+ let pending: Promise<void> | null = null;
155
+
156
+ /** One task, bounded by itself. Rejects with the task's NAME in the message,
157
+ * so the aggregate line below reads as a list of resources. */
158
+ const runTask = async (task: ShutdownTask): Promise<void> => {
159
+ const startedAt = Date.now();
160
+ let timer: ReturnType<typeof setTimeout> | undefined;
161
+ try {
162
+ const outcome = await Promise.race([
163
+ Promise.resolve(task.run()).then(() => 'done' as const),
164
+ new Promise<'timeout'>((resolve) => {
165
+ timer = setTimeout(() => resolve('timeout'), taskTimeoutMs);
166
+ }),
167
+ ]);
168
+ if (outcome === 'timeout') {
169
+ journal({ task: task.name, outcome: 'timeout', ms: Date.now() - startedAt });
170
+ throw new Error(`${task.name} did not finish within ${taskTimeoutMs}ms`);
171
+ }
172
+ } catch (error) {
173
+ const detail = error instanceof Error ? error.message : String(error);
174
+ if (!detail.endsWith(`within ${taskTimeoutMs}ms`))
175
+ journal({ task: task.name, outcome: 'failed', ms: Date.now() - startedAt, detail });
176
+ throw error;
177
+ } finally {
178
+ if (timer) clearTimeout(timer);
179
+ }
180
+ };
181
+
182
+ return (why: string) => {
183
+ if (pending) return pending;
184
+ pending = (async () => {
185
+ let timeout: ReturnType<typeof setTimeout> | undefined;
186
+ const cleanup = Promise.allSettled(options.tasks.map(runTask));
187
+ const result = await Promise.race([
188
+ cleanup.then((settled) => ({ type: 'settled' as const, settled })),
189
+ new Promise<{ type: 'timeout' }>((resolve) => {
190
+ timeout = setTimeout(() => resolve({ type: 'timeout' }), timeoutMs);
191
+ }),
192
+ ]);
193
+ if (timeout) clearTimeout(timeout);
194
+
195
+ if (result.type === 'timeout') {
196
+ log(`[vgai-editor] cleanup timed out after ${timeoutMs}ms (${why}); forcing exit`);
197
+ exit(1);
198
+ return;
199
+ }
200
+ const failures = result.settled.filter(
201
+ (item): item is PromiseRejectedResult => item.status === 'rejected',
202
+ );
203
+ if (failures.length > 0) {
204
+ log(
205
+ `[vgai-editor] cleanup failed (${why}): ${failures
206
+ .map((item) =>
207
+ item.reason instanceof Error ? item.reason.message : String(item.reason),
208
+ )
209
+ .join('; ')}`,
210
+ );
211
+ exit(1);
212
+ return;
213
+ }
214
+ exit(0);
215
+ })();
216
+ return pending;
217
+ };
218
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * WHAT THIS SESSION'S PRODUCT CAN CREATE — the New Project screen's half of
3
+ * the declaration a product's `bin` reads.
4
+ *
5
+ * CREATION IS THE PRODUCT'S (ARCHITECTURE-CORE §The target shape, rule 1): the
6
+ * presets, their names and what a project declares live in
7
+ * `<product>/presets.mjs`, never in the kit. The CLI reads that file when
8
+ * a person types `<product> create`; this session reads the SAME file, of the
9
+ * SAME product it is already serving, so the wizard and the command line
10
+ * cannot offer different compositions.
11
+ *
12
+ * Plain ESM, dynamically imported: the declaration is a product's code, not a
13
+ * config, and a running session must not compile it.
14
+ */
15
+ import { existsSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ import { pathToFileURL } from 'node:url';
18
+ import { assertProductCreateDeclaration, type ProductCreateDeclaration } from '@volter/editor-sdk/session/product-create';
19
+ import { sessionProduct } from './session-product';
20
+
21
+ /**
22
+ * Where a product declares its presets, relative to its package root. Beside
23
+ * `src/`, never inside it: `src/` is the product's FRAME entry — the one module
24
+ * its workbench build compiles — and this declaration is read by Node, at the
25
+ * command line and here, and compiled by nothing.
26
+ */
27
+ export const PRODUCT_PRESETS_PATH = 'presets.mjs';
28
+
29
+ export interface ProductCreatePresets {
30
+ readonly declaration: ProductCreateDeclaration;
31
+ /** The file it came from — every refusal names it. */
32
+ readonly source: string;
33
+ }
34
+
35
+ /**
36
+ * The create declaration of the product this session serves, or `null` when
37
+ * there is no product to ask (no project open, or a project that declares
38
+ * none). A product that exists but ships no declaration THROWS: it is a broken
39
+ * product, and a wizard silently offering nothing is how that stays unnoticed.
40
+ */
41
+ export async function sessionCreatePresets(
42
+ projectPath: string | null,
43
+ ): Promise<ProductCreatePresets | null> {
44
+ const product = sessionProduct(projectPath);
45
+ if (product === null) return null;
46
+ const source = join(product.dir, PRODUCT_PRESETS_PATH);
47
+ if (!existsSync(source))
48
+ throw new Error(
49
+ `${product.name} declares no create presets (${source} is missing), so this session cannot ` +
50
+ 'create a project. A product owns its own compositions — see ' +
51
+ '@volter/editor-sdk/session/product-create for its executable declaration.',
52
+ );
53
+ const module = (await import(pathToFileURL(source).href)) as { default?: unknown };
54
+ return { declaration: assertProductCreateDeclaration(module.default, source), source };
55
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Packages the OPEN PROJECT'S native `dist/` after its own `npm run build`.
3
+ * The zip is an ordinary web artifact and the report is ephemeral editor
4
+ * telemetry — neither creates an editor-private project format.
5
+ */
6
+
7
+ import type { Dirent } from 'node:fs';
8
+ import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
9
+ import { dirname, join, relative, resolve, sep } from 'node:path';
10
+ import {
11
+ type BuildReport,
12
+ type BuildReportFile,
13
+ WEB_BUILD_ARTIFACT,
14
+ } from '@volter/editor-sdk/session/build-report';
15
+ import { zipSync } from 'fflate';
16
+ import { resolveManifestPath } from '@volter/editor-project/manifest/locate';
17
+
18
+ interface OutputFile extends BuildReportFile {
19
+ readonly absolutePath: string;
20
+ }
21
+
22
+ function portablePath(path: string): string {
23
+ return path.split(sep).join('/');
24
+ }
25
+
26
+ async function collectFiles(root: string, directory = root): Promise<OutputFile[]> {
27
+ let entries: Dirent[];
28
+ try {
29
+ entries = await readdir(directory, { withFileTypes: true });
30
+ } catch (error) {
31
+ const code = (error as NodeJS.ErrnoException).code;
32
+ if (code === 'ENOENT') {
33
+ throw new Error(
34
+ `The project's build completed without creating ${root}. ` +
35
+ 'Its native build script must emit a static dist/ directory.',
36
+ );
37
+ }
38
+ throw error;
39
+ }
40
+
41
+ const files: OutputFile[] = [];
42
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
43
+ const absolutePath = join(directory, entry.name);
44
+ if (entry.isDirectory()) {
45
+ files.push(...(await collectFiles(root, absolutePath)));
46
+ } else if (entry.isFile()) {
47
+ files.push({
48
+ absolutePath,
49
+ path: portablePath(relative(root, absolutePath)),
50
+ bytes: (await stat(absolutePath)).size,
51
+ });
52
+ }
53
+ }
54
+ return files;
55
+ }
56
+
57
+ /** The ignored, machine-local artifact used by the editor's Download action. */
58
+ export function projectBuildArtifactPath(projectRoot: string): string {
59
+ return resolve(projectRoot, '.vgai', 'tmp', 'build', WEB_BUILD_ARTIFACT);
60
+ }
61
+
62
+ export async function packageProjectWebBuild(projectRoot: string): Promise<BuildReport> {
63
+ const distRoot = resolve(projectRoot, 'dist');
64
+ const files = await collectFiles(distRoot);
65
+ if (files.length === 0) {
66
+ throw new Error(`The project's native build emitted an empty ${distRoot}.`);
67
+ }
68
+
69
+ const archive: Record<string, Uint8Array> = Object.create(null) as Record<string, Uint8Array>;
70
+ for (const file of files) archive[file.path] = await readFile(file.absolutePath);
71
+
72
+ // Keep the native manifest beside the static output, matching the existing
73
+ // deploy staging contract. If a custom build already emitted one, the source
74
+ // manifest is the authority and intentionally replaces it.
75
+ archive['vgai.project.json'] = await readFile(resolveManifestPath(projectRoot));
76
+
77
+ const bytes = zipSync(archive, { level: 6 });
78
+ const artifactPath = projectBuildArtifactPath(projectRoot);
79
+ await mkdir(dirname(artifactPath), { recursive: true });
80
+ await writeFile(artifactPath, bytes);
81
+
82
+ const outputBytes = files.reduce((sum, file) => sum + file.bytes, 0);
83
+ const largestFiles = files
84
+ .map(({ path, bytes }) => ({ path, bytes }))
85
+ .sort((a, b) => b.bytes - a.bytes || a.path.localeCompare(b.path))
86
+ .slice(0, 12);
87
+
88
+ return {
89
+ artifact: WEB_BUILD_ARTIFACT,
90
+ artifactBytes: bytes.byteLength,
91
+ outputBytes,
92
+ fileCount: files.length,
93
+ largestFiles,
94
+ };
95
+ }
@@ -0,0 +1,100 @@
1
+ import type { Dirent } from 'node:fs';
2
+ import { readdir, readFile } from 'node:fs/promises';
3
+ import { join, relative, sep } from 'node:path';
4
+ import { resolveManifestPath } from '@volter/editor-project/manifest/locate';
5
+ import type { ProjectComponentEntry } from '../src/asset-workflow/project-content';
6
+ import {
7
+ compareProjectComponents,
8
+ discoverComponentsInSource,
9
+ type IndexedProjectSource,
10
+ omitRootDocumentComponents,
11
+ projectFileSurfaces,
12
+ projectRegionEntries,
13
+ projectRootEntries,
14
+ reportUnreadableRegions,
15
+ } from '../src/asset-workflow/project-source-index';
16
+ import { ADAPTER_MODULE_FILENAME } from '../src/ui-source/adapter-region-includes';
17
+
18
+ /**
19
+ * ABSENT resolves `null`; every OTHER failure rejects — the contract
20
+ * {@link projectRegionEntries} reads, and the classification only this side
21
+ * (which knows the backend is Node's fs) can make. A blanket
22
+ * `.catch(() => '')` here would report a permissions error or a corrupt file
23
+ * as "this project declares nothing", which is a declaration it never made.
24
+ */
25
+ async function readOptionalFile(path: string): Promise<string | null> {
26
+ try {
27
+ return await readFile(path, 'utf8');
28
+ } catch (error) {
29
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;
30
+ throw error;
31
+ }
32
+ }
33
+
34
+ const SOURCE_EXTENSION = /\.(?:[cm]?[jt]sx)$/i;
35
+ const SKIPPED_DIRECTORIES = new Set(['node_modules', 'dist', 'build', '.git', '.vgai', 'tools']);
36
+
37
+ function indexSourceEntry(
38
+ directory: string,
39
+ entry: Dirent,
40
+ pending: string[],
41
+ files: string[],
42
+ ): void {
43
+ const absolute = join(directory, entry.name);
44
+ if (entry.isDirectory()) {
45
+ if (!SKIPPED_DIRECTORIES.has(entry.name) && !entry.name.startsWith('.')) {
46
+ pending.push(absolute);
47
+ }
48
+ return;
49
+ }
50
+ if (entry.isFile() && SOURCE_EXTENSION.test(entry.name)) files.push(absolute);
51
+ }
52
+
53
+ export async function discoverProjectComponents(
54
+ projectRoot: string,
55
+ ): Promise<ProjectComponentEntry[]> {
56
+ const pending = [join(projectRoot, 'src')];
57
+ const files: string[] = [];
58
+ // Same ENOENT-only rule as `readOptionalFile` above: a missing directory
59
+ // is an honest "nothing declared here"; a permissions error or I/O failure
60
+ // is NOT — swallowing it would render a short component list as a fact
61
+ // about the project.
62
+ const enoentEmpty = (error: unknown): never[] => {
63
+ if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return [];
64
+ throw error;
65
+ };
66
+ while (pending.length > 0 && files.length < 512) {
67
+ const directory = pending.shift()!;
68
+ const entries = await readdir(directory, { withFileTypes: true }).catch(enoentEmpty);
69
+ for (const entry of entries) indexSourceEntry(directory, entry, pending, files);
70
+ }
71
+ const sources = (
72
+ await Promise.all(
73
+ files.map(async (absolute): Promise<IndexedProjectSource[]> => {
74
+ const path = relative(projectRoot, absolute).split(sep).join('/');
75
+ return readFile(absolute, 'utf8')
76
+ .then((source) => [{ path, source }])
77
+ .catch(enoentEmpty);
78
+ }),
79
+ )
80
+ ).flat();
81
+ // A file's surface is its REGION, resolved by the one shared resolver from
82
+ // this project's declarations and its own import edges — never from whichever
83
+ // library a file happens to name in its text.
84
+ const { regions, unreadable } = await projectRegionEntries(
85
+ () => readOptionalFile(resolveManifestPath(projectRoot)),
86
+ () => readOptionalFile(join(projectRoot, ADAPTER_MODULE_FILENAME)),
87
+ );
88
+ // Never dropped: the real loader evaluates the module and WOULD honor an
89
+ // `include` this static read could not see, so an unreported `unreadable`
90
+ // is the two readers disagreeing with nobody told.
91
+ if (unreadable) reportUnreadableRegions(projectRoot, unreadable);
92
+ const surfaces = projectFileSurfaces(sources, regions);
93
+ const discovered = sources.flatMap((file) =>
94
+ discoverComponentsInSource(file.source, file.path, surfaces.get(file.path) ?? 'unknown'),
95
+ );
96
+ const rootEntries = await projectRootEntries(() =>
97
+ readFile(resolveManifestPath(projectRoot), 'utf8'),
98
+ );
99
+ return omitRootDocumentComponents(discovered, rootEntries).sort(compareProjectComponents);
100
+ }