@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,272 @@
1
+ /**
2
+ * `/__editor/log-session`, `/__editor/log-entries`, `/__editor/server-log` —
3
+ * play-mode console log persistence: the per-run JSONL file under the
4
+ * project's `logs/`, the reader behind the Console panel, and the server-side
5
+ * `console.*` sink a page can post into.
6
+ *
7
+ * The log-session route is also where the build-discipline tripwires get their
8
+ * SECOND firing moment: the save event alone goes quiet exactly during
9
+ * end-of-build verification, which is when an uncommitted batch is oldest.
10
+ */
11
+
12
+ import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises';
13
+ import { basename, join } from 'node:path';
14
+ import type { NextFunction, Request, Response } from 'express';
15
+ import { asPlayLogHeader, playLogHeaderLine } from '../support/play/log-format';
16
+ import { type EditorServerRouter, playLogFilename, playRunSlug } from '../editor-server';
17
+ import { broadcast } from '../editor-sse';
18
+ import { pruneGameplaySessionLogs } from '../gameplay-session-retention';
19
+ import {
20
+ gameplaySessionRecordingPath,
21
+ getGameplaySession,
22
+ listGameplaySessionCatalog,
23
+ } from '../gameplay-sessions';
24
+ import { processSessionId } from '../session-registry';
25
+ import type { RouteContext } from './context';
26
+
27
+ export function registerLogRoutes(router: EditorServerRouter, ctx: RouteContext): void {
28
+ const { announceBuildDisciplineTripwires, journalEvent } = ctx;
29
+
30
+ // ---- Play-mode console log persistence ----
31
+ let logSessionSequence = 0;
32
+ let activeLogStartedAt: number | null = null;
33
+ let recentlyEndedLog: { file: string; startedAt: number; endedAt: number } | null = null;
34
+
35
+ // Play start/stop is the SECOND event the build-discipline tripwires ride
36
+ // (`announceBuildDisciplineTripwires`, above). The save event alone covers
37
+ // the authoring stretch and goes quiet exactly where the measured failure
38
+ // lives: the end-of-build verification phase is play, playtest and eval —
39
+ // minutes of activity with no file written, which is also the stretch where
40
+ // an uncommitted batch is at its oldest. Same guarded call, so the read cap
41
+ // and the announce gate are unchanged; this only adds a moment at which
42
+ // they can fire.
43
+ router.post('/__editor/log-session', async (req: Request, res: Response) => {
44
+ const body = req.body as { action: 'start' | 'end'; name?: string | null };
45
+
46
+ if (body.action === 'start') {
47
+ const logsDir = join(ctx.projectRoot, 'logs');
48
+ await mkdir(logsDir, { recursive: true });
49
+
50
+ // Lexicographic order remains chronological for pruning/tail tooling —
51
+ // see `playLogFilename` for why an optional run name goes on the END.
52
+ const slug = playRunSlug(body.name);
53
+ const startedAt = new Date();
54
+ const filename = playLogFilename(startedAt, ++logSessionSequence, slug);
55
+ ctx.activeLogFile = join(logsDir, filename);
56
+ activeLogStartedAt = startedAt.getTime();
57
+ // The run's IDENTITY, recorded ONCE (see `play/log-format.ts`): who wrote
58
+ // this file, for which project, under which run name, when. These four
59
+ // facts are fixed for the file's whole lifetime, so they are a header
60
+ // line and not a per-entry stamp — what varies per entry (tick/simT,
61
+ // simSpeed, world) is stamped by the entry writer instead.
62
+ await writeFile(
63
+ ctx.activeLogFile,
64
+ playLogHeaderLine({
65
+ session: processSessionId(),
66
+ project: ctx.projectRoot,
67
+ run: slug,
68
+ startedAt: startedAt.getTime(),
69
+ }),
70
+ 'utf-8',
71
+ );
72
+ await pruneGameplaySessionLogs(ctx.projectRoot);
73
+ journalEvent({ kind: 'play', action: 'start', name: slug, logFile: filename });
74
+ announceBuildDisciplineTripwires();
75
+ res.json({ ok: true, file: filename });
76
+ } else {
77
+ const ended = ctx.activeLogFile;
78
+ if (ended !== null) {
79
+ const endedAt = Date.now();
80
+ await appendFile(
81
+ ended,
82
+ `${JSON.stringify({
83
+ t: endedAt,
84
+ level: 'info',
85
+ source: 'gameplay-session',
86
+ msg: 'ended',
87
+ meta: { endedAt },
88
+ })}\n`,
89
+ 'utf-8',
90
+ ).catch(() => undefined);
91
+ if (activeLogStartedAt !== null) {
92
+ recentlyEndedLog = { file: ended, startedAt: activeLogStartedAt, endedAt };
93
+ }
94
+ }
95
+ ctx.activeLogFile = null;
96
+ activeLogStartedAt = null;
97
+ journalEvent({
98
+ kind: 'play',
99
+ action: 'stop',
100
+ name: null,
101
+ logFile: ended === null ? null : basename(ended),
102
+ });
103
+ announceBuildDisciplineTripwires();
104
+ res.json({ ok: true });
105
+ }
106
+ });
107
+
108
+ router.get('/__editor/gameplay-sessions', async (_req: Request, res: Response) => {
109
+ res.json({ sessions: await listGameplaySessionCatalog(ctx.projectRoot, ctx.activeLogFile) });
110
+ });
111
+
112
+ router.get(
113
+ '/__editor/gameplay-sessions/:id/recording',
114
+ async (req: Request, res: Response, next: NextFunction) => {
115
+ const session = await getGameplaySession(
116
+ ctx.projectRoot,
117
+ Array.isArray(req.params['id']) ? (req.params['id'][0] ?? '') : (req.params['id'] ?? ''),
118
+ ctx.activeLogFile,
119
+ );
120
+ const path = session ? gameplaySessionRecordingPath(ctx.projectRoot, session) : null;
121
+ if (!path) {
122
+ res.status(404).json({ error: 'This Gameplay Session has no recording.' });
123
+ return;
124
+ }
125
+ res.sendFile(path, { dotfiles: 'allow' }, (error) => {
126
+ if (!error) return;
127
+ if (!res.headersSent) res.status(404).json({ error: 'Recording file not found.' });
128
+ else next(error);
129
+ });
130
+ },
131
+ );
132
+
133
+ router.get('/__editor/gameplay-sessions/:id', async (req: Request, res: Response) => {
134
+ const session = await getGameplaySession(
135
+ ctx.projectRoot,
136
+ Array.isArray(req.params['id']) ? (req.params['id'][0] ?? '') : (req.params['id'] ?? ''),
137
+ ctx.activeLogFile,
138
+ );
139
+ if (!session) {
140
+ res.status(404).json({ error: 'Gameplay Session not found.' });
141
+ return;
142
+ }
143
+ res.json({ session });
144
+ });
145
+
146
+ // `entries` is ENTRIES ONLY — the file's first line is the run's identity
147
+ // header (`play/log-format.ts`), and a reader counting or rendering log
148
+ // lines must never see it as one. It is reported beside them instead, so a
149
+ // follower learns which session/project/run it is tailing without a second
150
+ // request.
151
+ router.get('/__editor/log-entries', async (_req: Request, res: Response) => {
152
+ if (!ctx.activeLogFile) {
153
+ res.json({ entries: [], header: null });
154
+ return;
155
+ }
156
+ // The whole read used to sit in one try/catch whose catch answered the
157
+ // EMPTY NO-LOG SHAPE — the same bytes as "no session is running". So a log
158
+ // being APPENDED TO while this route read it (the normal case: the writer
159
+ // is a live play session, and a read landing mid-append sees a torn last
160
+ // line) reported the entire run as having produced nothing. A follower
161
+ // cannot tell that from a quiet session, so it stops asking.
162
+ let raw: string;
163
+ try {
164
+ raw = await readFile(ctx.activeLogFile, 'utf-8');
165
+ } catch (error) {
166
+ res.json({
167
+ entries: [],
168
+ header: null,
169
+ file: basename(ctx.activeLogFile),
170
+ unreadable: error instanceof Error ? error.message : String(error),
171
+ });
172
+ return;
173
+ }
174
+ const lines = raw.split('\n').filter(Boolean);
175
+ const records: unknown[] = [];
176
+ let truncatedTail = false;
177
+ let unparsableLines = 0;
178
+ for (const [index, line] of lines.entries()) {
179
+ try {
180
+ records.push(JSON.parse(line) as unknown);
181
+ } catch {
182
+ // The writer appends WHOLE lines, so the last one is the only one a
183
+ // concurrent read can catch half-written — that is a torn tail, and
184
+ // every line before it is real data. An unparsable line anywhere else
185
+ // is corruption, counted separately; neither discards what did parse.
186
+ if (index === lines.length - 1) truncatedTail = true;
187
+ else unparsableLines += 1;
188
+ }
189
+ }
190
+ const header = records.length > 0 ? asPlayLogHeader(records[0]) : null;
191
+ const entries = header === null ? records : records.slice(1);
192
+ res.json({
193
+ entries,
194
+ header,
195
+ file: basename(ctx.activeLogFile),
196
+ ...(truncatedTail ? { truncatedTail: true } : {}),
197
+ ...(unparsableLines > 0 ? { unparsableLines } : {}),
198
+ });
199
+ });
200
+
201
+ router.post('/__editor/log-entries', async (req: Request, res: Response) => {
202
+ const body = req.body as
203
+ | {
204
+ entries: Array<{
205
+ t: number;
206
+ level: string;
207
+ source?: string;
208
+ sub?: string;
209
+ msg: string;
210
+ meta?: Record<string, unknown>;
211
+ }>;
212
+ }
213
+ | null
214
+ | undefined;
215
+ if (!body || !Array.isArray(body.entries) || body.entries.length === 0) {
216
+ res.status(400).json({ error: 'Expected a non-empty entries array.' });
217
+ return;
218
+ }
219
+ const batches = new Map<string, typeof body.entries>();
220
+ for (const entry of body.entries) {
221
+ const target =
222
+ recentlyEndedLog &&
223
+ Number.isFinite(entry.t) &&
224
+ entry.t >= recentlyEndedLog.startedAt &&
225
+ entry.t <= recentlyEndedLog.endedAt
226
+ ? recentlyEndedLog.file
227
+ : ctx.activeLogFile;
228
+ if (!target) {
229
+ res.status(409).json({ error: 'No matching Gameplay Session for these entries.' });
230
+ return;
231
+ }
232
+ const batch = batches.get(target) ?? [];
233
+ batch.push(entry);
234
+ batches.set(target, batch);
235
+ }
236
+ await Promise.all(
237
+ [...batches].map(([target, entries]) =>
238
+ appendFile(
239
+ target,
240
+ `${entries.map((entry) => JSON.stringify(entry)).join('\n')}\n`,
241
+ 'utf-8',
242
+ ),
243
+ ),
244
+ );
245
+ res.json({ ok: true });
246
+ });
247
+
248
+ // ---- External-tool narration relay ----
249
+ // A tool driving this session (a `@vgai/live` client, say) fires
250
+ // best-effort lifecycle lines at this route so they land in the
251
+ // SAME live editor console the `server-log` SSE event feeds
252
+ // (see `runFileValidation`'s `broadcast('server-log', …)` calls above) — a
253
+ // human watching the editor sees the script's progress without tailing a
254
+ // separate terminal. Deliberately dumb: this is a narration RELAY, not an
255
+ // API — it validates shape, broadcasts, and gets out of the way; no state is
256
+ // kept here, and a caller with nothing to say just never POSTs.
257
+ router.post('/__editor/server-log', (req: Request, res: Response) => {
258
+ const body = req.body as { level?: unknown; message?: unknown };
259
+ const level = body.level;
260
+ if (
261
+ (level !== 'info' && level !== 'warn' && level !== 'error') ||
262
+ typeof body.message !== 'string'
263
+ ) {
264
+ res
265
+ .status(400)
266
+ .json({ error: "Expected { level: 'info'|'warn'|'error', message: string }." });
267
+ return;
268
+ }
269
+ broadcast('server-log', { level, message: body.message });
270
+ res.status(204).end();
271
+ });
272
+ }
@@ -0,0 +1,302 @@
1
+ /**
2
+ * WHAT PROJECT IS THIS, and what does the editor know about it:
3
+ * `/__editor/compatibility`, `/__editor/project`, `/__editor/project-verbs`,
4
+ * `/__editor/project-attribution`, and the three `/__editor/manifest` verbs.
5
+ *
6
+ * `/__editor/project` is BOOT ROUTING — every caller of it is on the critical
7
+ * path — which is why `/__editor/project-verbs` is a separate route despite
8
+ * reading the same two files: it is a periodic vitals read, and its failures
9
+ * must never be able to make a session look projectless.
10
+ *
11
+ * The manifest write is the one route in the whole server that HARD-CODES its
12
+ * destination rather than deriving it from the request. `validateManifestWrite`
13
+ * rejects a different filename, a traversal path, or a non-JSON body before
14
+ * the handler touches the filesystem.
15
+ */
16
+
17
+ import { readFile, stat } from 'node:fs/promises';
18
+ import { join, resolve } from 'node:path';
19
+ import type { Request, Response } from 'express';
20
+ import { MANIFEST_FILENAME } from '@volter/editor-project/manifest/filename';
21
+ import { resolveManifestPath } from '@volter/editor-project/manifest/locate';
22
+ import {
23
+ deriveProjectAttributionReport,
24
+ emptyProjectProvenanceDocument,
25
+ formatProjectAttributionMarkdown,
26
+ PROJECT_PROVENANCE_PATH,
27
+ ProjectProvenanceDocumentSchema,
28
+ } from '../support/project/provenance';
29
+ import type { EditorServerRouter } from '../editor-server';
30
+ import type { EngineProvenance } from '../engine-provenance';
31
+ import { projectEnginePackageOrigin } from '../project-package-origin';
32
+ import { readProjectVerbFacts } from '../project-verbs';
33
+ import { readProjectViewResult } from '../project-view';
34
+ import {
35
+ isCanonicalPathInside,
36
+ isMonorepoScaffoldRoot,
37
+ isPathInside,
38
+ validateManifestWrite,
39
+ } from '../server-utils';
40
+ import { isEphemeralSession, processSessionId } from '../session-registry';
41
+ import type { RouteContext } from './context';
42
+
43
+ /**
44
+ * Registered SEPARATELY, and before the project-file-serving middleware,
45
+ * because that is where it sat: this is a read of the project's own
46
+ * provenance document, not a file the middleware should get a chance at.
47
+ */
48
+ export function registerProjectAttributionRoute(
49
+ router: EditorServerRouter,
50
+ ctx: RouteContext,
51
+ ): void {
52
+ const { engineRoot } = ctx;
53
+
54
+ // Derived credits view. The sole durable source is central project provenance.
55
+ router.get('/__editor/project-attribution', async (req: Request, res: Response) => {
56
+ if (ctx.projectRoot === engineRoot) {
57
+ res.status(400).json({ error: 'No project is open.' });
58
+ return;
59
+ }
60
+ try {
61
+ const raw = await readFile(join(ctx.projectRoot, PROJECT_PROVENANCE_PATH), 'utf8').catch(
62
+ (error: NodeJS.ErrnoException) => {
63
+ if (error.code === 'ENOENT') return null;
64
+ throw error;
65
+ },
66
+ );
67
+ const provenance = raw
68
+ ? ProjectProvenanceDocumentSchema.parse(JSON.parse(raw))
69
+ : emptyProjectProvenanceDocument();
70
+ const activeOperations = Object.fromEntries(
71
+ (
72
+ await Promise.all(
73
+ Object.entries(provenance.operations).map(async ([operationId, operation]) => {
74
+ const present = await Promise.all(
75
+ operation.outputs.map(async (output) => {
76
+ const absolute = resolve(ctx.projectRoot, output.path);
77
+ if (!isPathInside(ctx.projectRoot, absolute)) return false;
78
+ return stat(absolute).then(
79
+ (info) => info.isFile(),
80
+ () => false,
81
+ );
82
+ }),
83
+ );
84
+ return present.some(Boolean) ? ([operationId, operation] as const) : null;
85
+ }),
86
+ )
87
+ ).filter((entry): entry is readonly [string, (typeof provenance.operations)[string]] =>
88
+ Boolean(entry),
89
+ ),
90
+ );
91
+ const report = deriveProjectAttributionReport({ version: 1, operations: activeOperations });
92
+ const format = typeof req.query['format'] === 'string' ? req.query['format'] : 'json';
93
+ if (format === 'markdown' || req.accepts(['json', 'text/markdown']) === 'text/markdown') {
94
+ res.type('text/markdown').send(formatProjectAttributionMarkdown(report));
95
+ return;
96
+ }
97
+ res.json(report);
98
+ } catch (error) {
99
+ res.status(500).json({ error: `Project attribution failed: ${error}` });
100
+ }
101
+ });
102
+ }
103
+
104
+ export function registerProjectIdentityRoutes(router: EditorServerRouter, ctx: RouteContext): void {
105
+ const {
106
+ commitProjectMutation,
107
+ compatibilityIdentity,
108
+ currentSessionIdentity,
109
+ engineRoot,
110
+ enginePromise,
111
+ options,
112
+ projectMutationError,
113
+ trustedShareIdentity,
114
+ } = ctx;
115
+
116
+ // ---- Browser/server compatibility identity ----
117
+ router.get('/__editor/compatibility', (_req: Request, res: Response) => {
118
+ res.set('Cache-Control', 'no-store');
119
+ res.json(compatibilityIdentity());
120
+ });
121
+
122
+ // ---- Current project info ----
123
+ /**
124
+ * Who is answering — the server's own pid, and whether it is a throwaway
125
+ * probe (`VGAI_EPHEMERAL_SESSION`, today `vgai doctor`) rather than a
126
+ * session anyone owns.
127
+ *
128
+ * FX-1: `vgai edit` decided "this project's editor is already open" from the
129
+ * `project.path` above alone, and a probe server answers with exactly that
130
+ * path for the few seconds it lives — so an attach could succeed, exit 0,
131
+ * and leave every control command with nothing to talk to. The CLI now ASKS
132
+ * the session what it is instead of inferring it from the port; the
133
+ * registry's pid is the same `process.pid` reported here
134
+ * (`session-registry.ts`), which is what makes the two views comparable.
135
+ */
136
+ const serverSessionIdentity = (shared = false) => {
137
+ const identity = currentSessionIdentity();
138
+ const value = {
139
+ pid: process.pid,
140
+ ephemeral: isEphemeralSession(),
141
+ sessionId: processSessionId(),
142
+ repositoryId: identity?.repositoryId ?? null,
143
+ worktreeId: identity?.worktreeId ?? null,
144
+ worktreeRoot: identity?.worktreeRoot ?? null,
145
+ projectRelativePath: identity?.projectRelativePath ?? null,
146
+ branch: identity?.branch ?? null,
147
+ headCommit: identity?.headCommit ?? null,
148
+ baseCommit: identity?.baseCommit ?? null,
149
+ };
150
+ if (!shared) return value;
151
+ return {
152
+ ephemeral: value.ephemeral,
153
+ sessionId: value.sessionId,
154
+ repositoryId: value.repositoryId,
155
+ worktreeId: value.worktreeId,
156
+ projectRelativePath: value.projectRelativePath,
157
+ branch: value.branch,
158
+ };
159
+ };
160
+
161
+ router.get('/__editor/project', async (req: Request, res: Response) => {
162
+ const session = serverSessionIdentity(trustedShareIdentity(req) !== null);
163
+ // On EVERY branch, including "no project open": the question "what code is
164
+ // this port serving?" is the one a caller asks precisely when nothing else
165
+ // about the session makes sense (engine-provenance.ts).
166
+ const engine: EngineProvenance = await enginePromise;
167
+ // A SERVER fact, not a project one, so it rides at the top level and is
168
+ // answered on every branch: whether this host serves the `/__ui-source/*`
169
+ // recorder decides whether an authoring edit is written to the game's own
170
+ // source or is honestly live-only, and the client asks that question
171
+ // (`src/ui-source/tier-source-write-backend.ts`) about the PORT, not about
172
+ // whatever project happens to be open on it.
173
+ const sourceWrite = options.sourceWriteRoutes === true;
174
+ // The ingest lane's own route, stated beside it and on every branch for the
175
+ // same reason: `/__ingest-source/*` comes from a DIFFERENT plugin, so a host
176
+ // can serve one and not the other, and the client must not infer either
177
+ // from the other.
178
+ const ingestSourceWrite = options.ingestSourceWriteRoutes === true;
179
+ if (ctx.projectRoot === engineRoot) {
180
+ // No project open
181
+ res.json({ project: null, session, engine, sourceWrite, ingestSourceWrite });
182
+ return;
183
+ }
184
+ const configResult = await readProjectViewResult(ctx.projectRoot);
185
+ if (!configResult.ok) {
186
+ // Boot routing: this server IS serving a project — it just cannot
187
+ // describe it. Answering a bare `{ project: null }` here is
188
+ // indistinguishable from "no project open", which is how a page for a
189
+ // live, project-serving session ended up rendering the launcher.
190
+ // `serving` names the path and the reason so the client fails loudly
191
+ // instead (boot-routing.ts, `decideServerProjectBoot`).
192
+ res.json({
193
+ project: null,
194
+ serving: { path: ctx.projectRoot, error: configResult.error },
195
+ session,
196
+ engine,
197
+ sourceWrite,
198
+ ingestSourceWrite,
199
+ });
200
+ return;
201
+ }
202
+ const config = configResult.view;
203
+ // hasUiRegistry: whether the project ships an OPTIONAL src/ui/registry.ts
204
+ // (scene-UI project mode, D9). The client must not
205
+ // probe /@fs for it — a dev server answers 200 (SPA fallback) for missing
206
+ // files, and a dynamic import of a missing module logs an unsuppressible
207
+ // browser network error on every registry-less project.
208
+ const hasUiRegistry = await stat(join(ctx.projectRoot, 'src', 'ui', 'registry.ts')).then(
209
+ (s) => s.isFile(),
210
+ () => false,
211
+ );
212
+ // `packaged`: true iff this server is the no-monorepo-checkout runtime
213
+ // (`packages/editor/server/packaged.ts`) — same `isMonorepoScaffoldRoot`
214
+ // check the "New Project" packaged-mode guard already uses server-side
215
+ // (server-utils.ts). Client-side, `binding-resolver.ts`'s react-world
216
+ // mount reads this to decide whether it must resolve its
217
+ // `react`/`react-dom/client`/`WorldProvider` wrapper from the PROJECT's
218
+ // own module graph (packaged: the editor's prebuilt SPA bundles its OWN
219
+ // separate react copy, so a react world would dual-instance otherwise)
220
+ // or keep the existing static-import path (dev: one shared Vite
221
+ // instance + root `vite.config.ts`'s `resolve.dedupe` — including
222
+ // `@vgai/game-runtime` itself, so `WorldProvider`/`useGame` are one context
223
+ // object — already collapses them, so this flag is `false` there and
224
+ // that path stays unchanged).
225
+ const packaged = !isMonorepoScaffoldRoot(engineRoot);
226
+ const enginePackage = projectEnginePackageOrigin(ctx.projectRoot);
227
+ res.json({
228
+ project: { path: ctx.projectRoot, config, hasUiRegistry, packaged, enginePackage },
229
+ session,
230
+ engine,
231
+ sourceWrite,
232
+ ingestSourceWrite,
233
+ });
234
+ });
235
+
236
+ // The two project files behind the `project.*` coverage family, as raw facts
237
+ // (`server/project-verbs.ts`). A separate route from `/__editor/project`
238
+ // deliberately: that one is BOOT routing and every caller of it is on the
239
+ // critical path, while this is a periodic vitals read whose failures must
240
+ // never be able to make a session look projectless.
241
+ router.get('/__editor/project-verbs', async (_req: Request, res: Response) => {
242
+ res.json(await readProjectVerbFacts(ctx.projectRoot === engineRoot ? null : ctx.projectRoot));
243
+ });
244
+ // ---- Manifest write (A4, D8 — the ONE manifest-write verb) ----
245
+ // Unlike every other write route above, this one HARD-CODES its
246
+ // destination: `join(ctx.projectRoot, 'vgai.project.json')`, NEVER derived from
247
+ // `req.body`. `validateManifestWrite` (server-utils.ts, unit-tested there)
248
+ // rejects anything else (a different filename, a traversal path, a
249
+ // non-string/non-JSON body) before this handler ever touches the
250
+ // filesystem — see `server-security.test.ts` for the rejection matrix.
251
+ router.post('/__editor/manifest', async (req: Request, res: Response) => {
252
+ const body = req.body as { path?: unknown; content?: unknown };
253
+ const result = validateManifestWrite(ctx.projectRoot, engineRoot, body);
254
+ if (!result.ok) {
255
+ res.status(result.status).json({ error: result.error });
256
+ return;
257
+ }
258
+ try {
259
+ const revision = await commitProjectMutation(req, [
260
+ { path: MANIFEST_FILENAME, content: result.content },
261
+ ]);
262
+ res.json({ ok: true, revision: revision?.revision ?? null });
263
+ } catch (error) {
264
+ projectMutationError(res, error);
265
+ }
266
+ });
267
+
268
+ router.get('/__editor/manifest', async (req: Request, res: Response) => {
269
+ if (ctx.projectRoot === engineRoot) {
270
+ res.status(404).json({ error: 'No project open.' });
271
+ return;
272
+ }
273
+ try {
274
+ const manifestPath = resolveManifestPath(ctx.projectRoot);
275
+ if (
276
+ trustedShareIdentity(req) &&
277
+ !(await isCanonicalPathInside(ctx.projectRoot, manifestPath))
278
+ ) {
279
+ res.status(403).json({ error: 'Shared manifest path leaves the project root.' });
280
+ return;
281
+ }
282
+ res.type('application/json').send(await readFile(manifestPath));
283
+ } catch {
284
+ res.status(404).json({ error: 'Not found.' });
285
+ }
286
+ });
287
+
288
+ router.delete('/__editor/manifest', async (req: Request, res: Response) => {
289
+ if (ctx.projectRoot === engineRoot) {
290
+ res.status(400).json({ error: 'No project open.' });
291
+ return;
292
+ }
293
+ try {
294
+ const revision = await commitProjectMutation(req, [
295
+ { path: MANIFEST_FILENAME, content: null },
296
+ ]);
297
+ res.json({ ok: true, revision: revision?.revision ?? null });
298
+ } catch (error) {
299
+ projectMutationError(res, error);
300
+ }
301
+ });
302
+ }