@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,39 @@
1
+ /**
2
+ * The editor's OWN connection state, as the lease guard measures it
3
+ * (`components/EditorLeaseGuard.tsx`), published for the status bar. VS
4
+ * Code shows its remote connection at the far left of the status bar and
5
+ * turns it red when the host is gone; this is that item's source. State
6
+ * lives here, events (the moment it changed) go to the notification stack.
7
+ */
8
+
9
+ export type EditorLeaseView =
10
+ | { readonly kind: 'quiet' }
11
+ | { readonly kind: 'degraded'; readonly subject: 'busy' | 'stale' }
12
+ | {
13
+ readonly kind: 'void';
14
+ readonly reason: 'taken-over' | 'server-gone';
15
+ readonly reloadOffered: boolean;
16
+ };
17
+
18
+ let _view: EditorLeaseView = { kind: 'quiet' };
19
+ let _version = 0;
20
+ const _listeners = new Set<() => void>();
21
+
22
+ export function editorLeaseView(): EditorLeaseView {
23
+ return _view;
24
+ }
25
+
26
+ export function publishEditorLeaseView(view: EditorLeaseView): void {
27
+ _view = view;
28
+ _version += 1;
29
+ for (const fn of _listeners) fn();
30
+ }
31
+
32
+ export function subscribeEditorLeaseView(listener: () => void): () => void {
33
+ _listeners.add(listener);
34
+ return () => _listeners.delete(listener);
35
+ }
36
+
37
+ export function editorLeaseViewVersion(): number {
38
+ return _version;
39
+ }
@@ -0,0 +1,415 @@
1
+ /**
2
+ * The editor tab is a SUPERVISED LEASE on its editor server.
3
+ *
4
+ * An editor tab is a client-side SPA: when its server dies UNGRACEFULLY (a
5
+ * killed process, a crash), the tab keeps rendering pixel-for-pixel as if
6
+ * nothing happened — and if a game is playing, it stays connected to the
7
+ * Colyseus room as an unowned "ghost" player that nothing ever removes. So the
8
+ * tab has to supervise its server.
9
+ *
10
+ * The graceful case (a clean `vgai close` sends a `tab-close` push) is handled
11
+ * elsewhere (tab-lifecycle-client.ts). This module is the UNGRACEFUL case that
12
+ * push never reaches.
13
+ *
14
+ * TWO independent readings, because ONE of them lies. The lease poll is a
15
+ * `fetch` on the browser's per-origin HTTP connection pool, so it reports
16
+ * "failed" for reasons that have nothing to do with the server being gone: a
17
+ * cold Vite dep-optimize floods that pool and the poll never leaves the queue
18
+ * before its own timeout; a server whose event loop is blocked answers nothing
19
+ * while its process is perfectly alive. The tab's duplex control channel
20
+ * (editor-presence.ts — a WebSocket, outside the HTTP pool) is the second
21
+ * reading, and it is the one that distinguishes them: a killed process drops
22
+ * that socket immediately, a merely BUSY one holds it open.
23
+ *
24
+ * Measured on 2026-08-09 against a live dev session: `kill -STOP` on the editor
25
+ * server produced the "Editor disconnected" scrim ~19s later while the control
26
+ * socket was still `readyState === OPEN` and duplex-granted. The tab had the
27
+ * evidence that its server was alive and never looked at it. That is the whole
28
+ * defect: missed polls alone are NOT evidence a session is gone.
29
+ *
30
+ * So a run of failed polls only VOIDS the lease when the control channel is
31
+ * ALSO down for that same run. Failed polls on a page whose channel is open
32
+ * degrade to a passive warning — never a blocking, input-eating overlay on a
33
+ * page whose server is about to answer again.
34
+ *
35
+ * ## The third reading: TIME, because a tab does not run on demand
36
+ *
37
+ * MEASURED twice on live sessions, 2026-08-19: after its server was SIGKILLed,
38
+ * the editor tab made ZERO network attempts of any kind — no lease poll, no
39
+ * control-socket reconnect, no heartbeat beat, though the last two are written
40
+ * to retry forever — and never came back, including after a replacement server
41
+ * appeared on the same port. Once from a hidden tab over four and a half
42
+ * minutes; once from a tab that was `visible` at the moment of the kill, over
43
+ * forty-five seconds.
44
+ *
45
+ * WHY the page stops is NOT established. Suspension, discard, and a lost
46
+ * renderer all fit, and the second run makes "the browser froze a background
47
+ * tab" an insufficient story on its own. What IS established is the part the
48
+ * design has to answer for: a page's own timers are not a thing this watchdog
49
+ * may assume will run, and the page carrying an overlay cannot be relied on to
50
+ * survive long enough to be read — which is why the durable note
51
+ * (`session-orphan-record.ts`) is a channel and not a nicety.
52
+ *
53
+ * So a poll COUNT never meant what it was read as. Three polls are ~12s of a
54
+ * foregrounded tab, minutes of a throttled one, and nothing at all of a stopped
55
+ * one — and now that the watchdog also polls on events (the socket dropping, the
56
+ * tab being shown again), three polls can land inside one second, which is a
57
+ * server between processes rather than a dead one. The bar that was intended
58
+ * all along is DARKNESS SUSTAINED FOR A WHILE, so the state carries the
59
+ * timestamp that says it ({@link LeaseWatchState.darkSince}).
60
+ *
61
+ * And a page may only testify about time it EXPERIENCED. A tab returning from
62
+ * a freeze knows nothing about the minutes it slept, so the shell forgets the
63
+ * run on wake ({@link forgetLeaseFailures}) and earns a fresh window rather
64
+ * than voiding on the strength of a gap it never observed.
65
+ *
66
+ * This file is the PURE half — the decision, the poll-folding reducer, and the
67
+ * recovery policy, all data-in/data-out so the whole thing is unit-testable
68
+ * with no browser, no timers, and no fetch. The watchdog
69
+ * (`EditorLeaseGuard.tsx`) is a thin shell that supplies the timers/fetch and
70
+ * renders the notice.
71
+ */
72
+
73
+ /** How a server on a port identifies itself to a polling tab. `project` is the
74
+ * canonical root it reports serving (or `null` for an idle server); `pid` is
75
+ * the server process id — the strongest signal that a port was taken over by
76
+ * a DIFFERENT session, since a replaced server on the same port has a new pid.
77
+ * `pid` is `null` for a server too old to report one (the `/__editor/project`
78
+ * `session` block is optional). */
79
+ export interface LeaseIdentity {
80
+ project: string | null;
81
+ pid: number | null;
82
+ }
83
+
84
+ /** The outcome of one poll: either the server answered with its identity, or
85
+ * the request failed (connection refused / non-OK / timeout). */
86
+ export type LeasePollResult = { ok: true; identity: LeaseIdentity } | { ok: false };
87
+
88
+ /**
89
+ * What the tab's own control channel said at the moment of a poll — the
90
+ * SECOND, independent liveness reading (see the module header).
91
+ *
92
+ * - `open` — the duplex socket to this server is connected. A dead process
93
+ * cannot hold a socket open, so this is POSITIVE evidence the session lives.
94
+ * - `closed` — the socket is down (or reconnecting). Consistent with a dead
95
+ * server; on its own it is not proof, which is why it only ever combines
96
+ * with failed polls.
97
+ * - `unknown` — no channel reading is available (a share-tunnelled tab whose
98
+ * downstream bridge exposes none). Treated exactly like `closed`: absent
99
+ * evidence must not make the watchdog MORE willing to keep a dead tab alive.
100
+ */
101
+ export type LeaseChannelState = 'open' | 'closed' | 'unknown';
102
+
103
+ /** The rolling state the watchdog folds each poll into. Pure data. */
104
+ export interface LeaseWatchState {
105
+ /** Identity this tab attached to, captured from the first successful poll.
106
+ * `null` until then. Once set it never changes — it is what a later poll is
107
+ * compared against to detect a takeover. */
108
+ bootIdentity: LeaseIdentity | null;
109
+ /** Identity from the most recent SUCCESSFUL poll, or `null` when the most
110
+ * recent poll failed. */
111
+ lastIdentity: LeaseIdentity | null;
112
+ /** Consecutive failed polls since the last success. Reset to 0 on any
113
+ * success. */
114
+ consecutiveFailures: number;
115
+ /** The subset of that run whose polls ALSO found the control channel down —
116
+ * failures with no liveness evidence behind them. Voiding reads this
117
+ * counter, never `consecutiveFailures` alone. A single poll that saw an
118
+ * open channel resets it, because that poll proved the server alive. */
119
+ unbackedFailures: number;
120
+ /** The last moment this tab had POSITIVE EVIDENCE its server was alive — a
121
+ * poll that answered, or a poll that failed while the control socket was
122
+ * up — falling back to when the watch began, which is the earliest instant
123
+ * any claim about darkness could be measured from. `now - darkSince` is
124
+ * therefore "how long since we last saw a sign of life", and it is the
125
+ * clock half of the void bar.
126
+ *
127
+ * A count alone stopped meaning "a sustained window" once polls became
128
+ * EVENT-DRIVEN (the watchdog now re-polls the instant the control socket
129
+ * drops, and again when a hidden tab is shown). Three failures can then
130
+ * land inside a second — which is a dev server mid-restart, not a dead
131
+ * one. Equally, a backgrounded tab's interval is throttled to as slow as
132
+ * once a minute, so three polls can span minutes. Neither is what the
133
+ * threshold was ever trying to measure: the bar is DARKNESS FOR A WHILE,
134
+ * and only a timestamp says that. */
135
+ darkSince: number;
136
+ }
137
+
138
+ /** Default grace before a run of EVIDENCE-BACKED failed polls voids the lease.
139
+ * At the watchdog's ~4s cadence this is ~12s — long enough that an ordinary
140
+ * dev-server restart or HMR reload does not false-trigger, short enough to
141
+ * catch a real death promptly. */
142
+ export const DEFAULT_LEASE_FAILURE_THRESHOLD = 3;
143
+
144
+ /**
145
+ * How long the evidence must stay dark before a void, ms — the bar the count
146
+ * used to stand in for.
147
+ *
148
+ * A dev server RESTARTS on its own, routinely: a source change relaunches it,
149
+ * and a cold dep re-optimize can hold it down for minutes. Every one of those
150
+ * windows opens exactly like a death — socket dropped, polls refused — and
151
+ * only its DURATION tells them apart at the start. So the watchdog must sit in
152
+ * the dark for a stretch no ordinary restart is shorter than before it says
153
+ * anything final. Ten seconds is that stretch: comfortably longer than the
154
+ * relaunch gap of a running server, short enough that a user who just clicked
155
+ * something is told inside one breath.
156
+ *
157
+ * Note the asymmetry, which is the whole point: being WRONG about "gone" costs
158
+ * the user a session, while being wrong about "busy" costs them a banner that
159
+ * clears itself. The clock buys the cheap error.
160
+ */
161
+ export const LEASE_MIN_DARK_WINDOW_MS = 10_000;
162
+
163
+ /** The watchdog's poll cadence, ms. Exported so the shell and any test share
164
+ * one number. */
165
+ export const LEASE_POLL_INTERVAL_MS = 4_000;
166
+
167
+ /** `now` is when the watch begins: a tab that has never seen its server answer
168
+ * still needs a defensible instant to measure darkness from, and the moment
169
+ * it started looking is the only honest one. */
170
+ export function initialLeaseWatchState(now: number): LeaseWatchState {
171
+ return {
172
+ bootIdentity: null,
173
+ lastIdentity: null,
174
+ consecutiveFailures: 0,
175
+ unbackedFailures: 0,
176
+ darkSince: now,
177
+ };
178
+ }
179
+
180
+ /**
181
+ * Fold one poll result into the watch state.
182
+ *
183
+ * - A FAILURE clears `lastIdentity` (we no longer have a fresh reading) and
184
+ * increments the failure counter — and increments `unbackedFailures` too
185
+ * ONLY when the control channel was not open at that moment. A failed poll
186
+ * over a live socket is a busy server, and counts toward nothing that can
187
+ * void the tab.
188
+ * - A SUCCESS records the identity, adopts it as `bootIdentity` if we did not
189
+ * have one yet, and RESETS both counters — a single good poll clears a
190
+ * transient blip so a quick restart never accumulates toward a void.
191
+ */
192
+ export function reduceLeasePoll(
193
+ state: LeaseWatchState,
194
+ result: LeasePollResult,
195
+ channel: LeaseChannelState,
196
+ now: number,
197
+ ): LeaseWatchState {
198
+ if (!result.ok) {
199
+ const backed = channel === 'open';
200
+ return {
201
+ ...state,
202
+ lastIdentity: null,
203
+ consecutiveFailures: state.consecutiveFailures + 1,
204
+ unbackedFailures: backed ? 0 : state.unbackedFailures + 1,
205
+ // An open socket is a sign of life even when the fetch missed, so it
206
+ // relights the clock exactly where it clears the counter. A dark poll
207
+ // leaves it alone: the stretch is measured from the LAST SIGN OF LIFE,
208
+ // not from the first failure — which is what makes it independent of how
209
+ // often the watchdog happens to be polling.
210
+ darkSince: backed ? now : state.darkSince,
211
+ };
212
+ }
213
+ return {
214
+ bootIdentity: state.bootIdentity ?? result.identity,
215
+ lastIdentity: result.identity,
216
+ consecutiveFailures: 0,
217
+ unbackedFailures: 0,
218
+ darkSince: now,
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Drop the current failure run, keeping the identity this tab attached to.
224
+ *
225
+ * Called when the page comes back from a state where it was not RUNNING — a
226
+ * hidden tab the browser froze, a bfcache restore. The counters and the dark
227
+ * clock are testimony about a stretch of time, and a page that was suspended
228
+ * has none to give: its last readings are from before the gap and say nothing
229
+ * about the server now. Carrying them across would let one unlucky poll on a
230
+ * just-woken page (the socket has not finished reconnecting yet, so the
231
+ * channel reads `closed`) satisfy a threshold that was banked minutes ago and
232
+ * void a perfectly live session instantly.
233
+ *
234
+ * `bootIdentity` deliberately SURVIVES: who this tab attached to is not
235
+ * testimony about elapsed time, and it is what takeover and recovery are
236
+ * judged against.
237
+ */
238
+ export function forgetLeaseFailures(state: LeaseWatchState, now: number): LeaseWatchState {
239
+ return {
240
+ bootIdentity: state.bootIdentity,
241
+ lastIdentity: null,
242
+ consecutiveFailures: 0,
243
+ unbackedFailures: 0,
244
+ darkSince: now,
245
+ };
246
+ }
247
+
248
+ /** Whether two identities describe the same live lease — i.e. NOT a takeover.
249
+ * A takeover requires POSITIVE evidence that a DIFFERENT session now holds the
250
+ * port; absence of evidence is never a takeover. There are exactly two positive
251
+ * signals, and a `null` project is neither:
252
+ *
253
+ * 1. Two KNOWN, DIFFERENT projects — the port serves a different project than
254
+ * we booted on. A server is bound to one project, so a different project is
255
+ * a different session, even if the OS happened to recycle the same pid.
256
+ * 2. Two KNOWN, DIFFERENT pids — same (or absent) project but a REPLACED
257
+ * process: a second server for our project, which the tab bijection wants
258
+ * this now-stale tab to yield to.
259
+ *
260
+ * Everything else is the same lease. In particular a reading that reports NO
261
+ * project on the SAME pid — a transiently unreadable `vgai.project.json` save
262
+ * on our own still-live server — is absence of evidence, NOT a takeover; the
263
+ * pid positively identifies it as our own process. A `null` pid on either side
264
+ * (a server too old to report one) is likewise treated conservatively. */
265
+ function sameLease(a: LeaseIdentity, b: LeaseIdentity): boolean {
266
+ if (a.project !== null && b.project !== null && a.project !== b.project) return false;
267
+ if (a.pid !== null && b.pid !== null && a.pid !== b.pid) return false;
268
+ return true;
269
+ }
270
+
271
+ export type LeaseVoidReason = 'server-gone' | 'taken-over';
272
+
273
+ /**
274
+ * - `live` — nothing to say.
275
+ * - `degraded` — the poll is failing but the control channel is up. The server
276
+ * is busy, or this page's HTTP pool is. Say so passively; change nothing.
277
+ * - `void` — the session this tab leased is gone. Tear the game down and tell
278
+ * the user.
279
+ */
280
+ export type LeaseStatus = 'live' | 'degraded' | 'void';
281
+
282
+ export interface LeaseDecision {
283
+ status: LeaseStatus;
284
+ /** Which void. `null` for every non-void status. */
285
+ reason: LeaseVoidReason | null;
286
+ }
287
+
288
+ export interface LeaseDecisionInput {
289
+ consecutiveFailures: number;
290
+ /** Of that run, how many polls also had NO channel evidence (see
291
+ * `LeaseWatchState.unbackedFailures`). */
292
+ unbackedFailures: number;
293
+ failureThreshold: number;
294
+ /** How long it has been since the last sign of life, ms — `now - darkSince`,
295
+ * computed by the caller so this decision keeps no clock of its own. */
296
+ darkForMs: number;
297
+ /** The window that run must span before it can void (see
298
+ * {@link LEASE_MIN_DARK_WINDOW_MS}). */
299
+ minDarkWindowMs: number;
300
+ /** Identity this tab attached to at boot (`null` before the first success). */
301
+ bootIdentity: LeaseIdentity | null;
302
+ /** Identity from the latest successful poll (`null` when it failed). */
303
+ lastIdentity: LeaseIdentity | null;
304
+ }
305
+
306
+ /**
307
+ * Decide this tab's lease status — the whole policy, as a pure function.
308
+ *
309
+ * - `taken-over` — a poll SUCCEEDED but the server on the port is provably a
310
+ * DIFFERENT session than the one this tab attached to (a different known
311
+ * project, or a replaced process on a new pid — see `sameLease`). This is
312
+ * IMMEDIATE: no grace, even with zero failures, because the port has
313
+ * demonstrably changed hands. A server that merely reports no/unreadable
314
+ * project on the SAME pid is NOT a takeover.
315
+ * - `server-gone` — polls have failed `failureThreshold` times in a row, the
316
+ * control channel was down for that whole run, AND the run has lasted
317
+ * `minDarkWindowMs`. Three readings, because each alone has a benign
318
+ * explanation: a queued/timed-out poll on a busy server, a socket
319
+ * mid-reconnect, and — the one the clock covers — a burst of event-driven
320
+ * polls fired inside the second a restarting server is between processes.
321
+ * - `degraded` — a failure run that has not (yet) cleared all three bars:
322
+ * the channel is still up, or the darkness is still young. The session may
323
+ * be alive and merely unreachable; that is a warning, not a void. A run
324
+ * that will eventually void passes THROUGH this state, which is what puts
325
+ * an honest "not answering" notice on screen within a poll of the trouble
326
+ * starting instead of leaving the page silent for the whole window.
327
+ *
328
+ * Takeover is checked first: a successful poll that disagrees on identity is a
329
+ * stronger, faster signal than a failure run.
330
+ */
331
+ export function decideLeaseState(input: LeaseDecisionInput): LeaseDecision {
332
+ const {
333
+ consecutiveFailures,
334
+ unbackedFailures,
335
+ failureThreshold,
336
+ darkForMs,
337
+ minDarkWindowMs,
338
+ bootIdentity,
339
+ lastIdentity,
340
+ } = input;
341
+ if (bootIdentity && lastIdentity && !sameLease(bootIdentity, lastIdentity)) {
342
+ return { status: 'void', reason: 'taken-over' };
343
+ }
344
+ if (consecutiveFailures >= failureThreshold) {
345
+ if (unbackedFailures >= failureThreshold && darkForMs >= minDarkWindowMs) {
346
+ return { status: 'void', reason: 'server-gone' };
347
+ }
348
+ return { status: 'degraded', reason: null };
349
+ }
350
+ return { status: 'live', reason: null };
351
+ }
352
+
353
+ /**
354
+ * After a `server-gone` void: whether one fresh poll proves the SAME project
355
+ * has reoccupied this port, so the tombstone page may RELOAD into the live
356
+ * editor instead of demanding a manual reopen.
357
+ *
358
+ * The revival contract (each piece decided, not defaulted):
359
+ * - AUTOMATIC, by full page reload. A reload boots a fresh SPA from the new
360
+ * server — the honest equivalent of the manual reopen the overlay used to
361
+ * demand — so "a dead tab never silently reconnects" still holds: nothing
362
+ * stale survives the reload.
363
+ * - Identity-gated: revival requires this tab's KNOWN boot project and a
364
+ * KNOWN, EQUAL reported project. A port reoccupied by a DIFFERENT project
365
+ * must never be reloaded into — that is exactly the silent retargeting the
366
+ * reserved-port rule exists to prevent. The pid is deliberately ignored:
367
+ * a revived server is a new process by definition.
368
+ */
369
+ function revives(bootIdentity: LeaseIdentity | null, identity: LeaseIdentity): boolean {
370
+ if (!bootIdentity?.project || !identity.project) return false;
371
+ return identity.project === bootIdentity.project;
372
+ }
373
+
374
+ /**
375
+ * What a `server-gone` tombstone should do when a poll starts answering again.
376
+ *
377
+ * - `resume` — the SAME PROCESS answered (equal, known pid). It never died;
378
+ * the void was drawn on a run of unreachable polls. Nothing about the page
379
+ * is stale, so it keeps its session: no reload, no lost camera/selection/
380
+ * undo stack. This is the branch that turns a hiccup back into a working
381
+ * editor instead of a restart.
382
+ * - `reload` — a DIFFERENT process now serves our SAME project: the server
383
+ * really did die and came back. The page IS stale, so the honest recovery is
384
+ * a full boot against the new server (the revival contract above).
385
+ * - `offer-reload` — something answers, but this tab never learned who it was
386
+ * (it died before its first successful poll, which is exactly what a
387
+ * mid-boot stall produces). It cannot verify the occupant, so it must not
388
+ * reload ITSELF — but leaving it a permanently dead window was the worst
389
+ * half of this defect. The notice offers the reload as a click and names it.
390
+ * - `none` — nothing answered, or a different known project holds the port.
391
+ *
392
+ * `taken-over` never recovers by any branch: that tab yielded to a live window
393
+ * the bijection chose, and reviving it would recreate the duplicate. The
394
+ * watchdog stops polling on that reason rather than encoding it here.
395
+ */
396
+ export type LeaseRecovery = 'none' | 'resume' | 'reload' | 'offer-reload';
397
+
398
+ export function decideLeaseRecovery(
399
+ bootIdentity: LeaseIdentity | null,
400
+ result: LeasePollResult,
401
+ ): LeaseRecovery {
402
+ if (!result.ok) return 'none';
403
+ const identity = result.identity;
404
+ if (
405
+ bootIdentity &&
406
+ bootIdentity.pid !== null &&
407
+ identity.pid === bootIdentity.pid &&
408
+ sameLease(bootIdentity, identity)
409
+ ) {
410
+ return 'resume';
411
+ }
412
+ if (revives(bootIdentity, identity)) return 'reload';
413
+ if (!bootIdentity?.project) return 'offer-reload';
414
+ return 'none';
415
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The project root the session injected, for the code that must spell an
3
+ * ABSOLUTE path.
4
+ *
5
+ * The editor is served by its session (`vgai edit`) and runs inside the
6
+ * Code-OSS frame (ARCHITECTURE-CORE §The target shape rule 5), so a file read
7
+ * is a request to that session and `__VGAI_PROJECT_PATH__` is the folder it
8
+ * opened.
9
+ *
10
+ * Vite replaces the define at build time; `typeof` guards the one case where
11
+ * nothing injected it (a module loaded outside the session's own bundle).
12
+ */
13
+
14
+ declare const __VGAI_PROJECT_PATH__: string;
15
+
16
+ /** Absolute project root injected by the session's dev/prod server. */
17
+ export function getProjectDefinePath(): string {
18
+ return typeof __VGAI_PROJECT_PATH__ !== 'undefined' ? __VGAI_PROJECT_PATH__ : '';
19
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * EDITOR NOTIFICATIONS — the one door for a transient, event-shaped message
3
+ * the editor has for the human: an agent presented a view, the editor server
4
+ * went away, a document reloaded from disk. Persistent STATE — "the editor is
5
+ * disconnected", "play is running" — belongs on the status bar
6
+ * (`workspace-status-registry.ts`), where a glance answers it; a notification
7
+ * is for the moment something HAPPENED.
8
+ *
9
+ * ## WHO SHOWS IT: the workbench, and only the workbench
10
+ *
11
+ * A notification is the workbench's own toast, raised through
12
+ * `INotificationService` by the fork's `vgaiNotifications.ts`. This module is
13
+ * the door every caller already uses — `notify()`, which is also what
14
+ * `EditorHost.notify` delegates to — plus the by-id replace and dismiss
15
+ * contract both sides honour. It draws nothing itself, and there is no second
16
+ * surface for it to draw into.
17
+ *
18
+ * The payload maps exactly onto VS Code's, and both halves were measured
19
+ * rather than assumed: `NotificationAction.keeps` ("the card stays after this
20
+ * action runs") IS VS Code's SECONDARY action, while a plain action is
21
+ * PRIMARY; and `detail` is joined to the title with an em dash, because
22
+ * `NotificationMessage` is `string | Error` and NOT markdown.
23
+ *
24
+ * WHAT IS SAID BEFORE ANYONE CAN HEAR IT is queued, not dropped — see
25
+ * {@link setNotificationDelegate}. A message with nowhere else to go is still
26
+ * a message; it just waits for the surface instead of getting a second one.
27
+ *
28
+ * NOT here, and measured rather than assumed: `transient-hint.ts`. A hint is
29
+ * a stage-local, three-second whisper over the viewport (45 call sites), not
30
+ * an event-shaped message for the human — the workbench has no counterpart
31
+ * and it stays ours whole.
32
+ */
33
+
34
+ export type NotificationTone = 'info' | 'warning' | 'error';
35
+
36
+ export interface NotificationAction {
37
+ readonly label: string;
38
+ readonly run: () => void;
39
+ /** The one action drawn as the primary button. */
40
+ readonly primary?: boolean;
41
+ /** Keep the card after this action runs (default: the card dismisses). */
42
+ readonly keeps?: boolean;
43
+ }
44
+
45
+ export interface EditorNotification {
46
+ readonly id: string;
47
+ readonly tone: NotificationTone;
48
+ /** One line, bold — what happened. */
49
+ readonly title: string;
50
+ /** The rest, plain — what it means, what to do. */
51
+ readonly detail?: string;
52
+ readonly actions?: readonly NotificationAction[];
53
+ /** Stay until dismissed. Default: warnings, errors and action-bearing
54
+ * cards stay; a plain info card hides after {@link INFO_NOTIFICATION_MS}. */
55
+ readonly sticky?: boolean;
56
+ /** Hide after {@link INFO_NOTIFICATION_MS} even though the tone is a
57
+ * warning — a report of a moment (a refused gesture), not a state. */
58
+ readonly fades?: boolean;
59
+ /** Called when the card leaves for any reason (dismiss, action, timeout). */
60
+ readonly onDismiss?: () => void;
61
+ }
62
+
63
+ /**
64
+ * How a notification REACHES THE PERSON: the workbench's own
65
+ * `INotificationService`, installed by the fork's contribution once it has
66
+ * one. `show` returns the dismiss, exactly as {@link notify} does.
67
+ */
68
+ export interface NotificationDelegate {
69
+ show(notification: EditorNotification): () => void;
70
+ }
71
+
72
+ let _delegate: NotificationDelegate | null = null;
73
+ /** Live notifications by id, so `dismissNotification(id)` — which several
74
+ * callers use instead of the closure `notify()` returns — reaches the toast
75
+ * too. Without it a card would be undismissable by id, silently. */
76
+ const _delegated = new Map<string, () => void>();
77
+ /**
78
+ * WHAT IS SAID BEFORE ANYONE CAN HEAR IT. The editor mounts before the
79
+ * contribution has `INotificationService` (a `ServicesAccessor` is valid only
80
+ * for the synchronous part of a command), and a `notify()` in that window is
81
+ * still a message. It waits here and is shown in order the moment the delegate
82
+ * arrives, rather than being drawn into a tray of our own that nobody looks at
83
+ * twice — there is one notification surface and it is the workbench's.
84
+ */
85
+ let _pending: EditorNotification[] = [];
86
+
87
+ /**
88
+ * Install how the frame shows one, and flush anything said before it could.
89
+ * Passing `null` stops delegation: further notifications wait again.
90
+ */
91
+ export function setNotificationDelegate(delegate: NotificationDelegate | null): void {
92
+ _delegate = delegate;
93
+ if (!delegate) return;
94
+ const waiting = _pending;
95
+ _pending = [];
96
+ for (const notification of waiting) showThroughDelegate(delegate, notification);
97
+ }
98
+
99
+ /** Show one through the delegate, keeping the by-id dismiss reachable. */
100
+ function showThroughDelegate(
101
+ delegate: NotificationDelegate,
102
+ notification: EditorNotification,
103
+ ): () => void {
104
+ // Replace-by-id is the door's contract on both sides.
105
+ _delegated.get(notification.id)?.();
106
+ const close = delegate.show(notification);
107
+ const dismiss = () => {
108
+ if (_delegated.get(notification.id) !== dismiss) return;
109
+ _delegated.delete(notification.id);
110
+ close();
111
+ notification.onDismiss?.();
112
+ };
113
+ _delegated.set(notification.id, dismiss);
114
+ return dismiss;
115
+ }
116
+
117
+ let _seq = 0;
118
+
119
+ /** Publish (or replace, by id). Returns the dismiss. */
120
+ export function notify(input: Omit<EditorNotification, 'id'> & { id?: string }): () => void {
121
+ const id = input.id ?? `notification-${++_seq}`;
122
+ const notification: EditorNotification = { ...input, id };
123
+ if (_delegate) return showThroughDelegate(_delegate, notification);
124
+ // Nothing can draw it yet. Queue, replacing any earlier message with this id
125
+ // — the same replace-by-id contract the delegate path has.
126
+ _pending = [..._pending.filter((n) => n.id !== id), notification];
127
+ return () => dismissNotification(id);
128
+ }
129
+
130
+ export function dismissNotification(id: string): void {
131
+ const delegated = _delegated.get(id);
132
+ if (delegated) {
133
+ delegated();
134
+ return;
135
+ }
136
+ const waiting = _pending.find((n) => n.id === id);
137
+ if (!waiting) return;
138
+ _pending = _pending.filter((n) => n.id !== id);
139
+ waiting.onDismiss?.();
140
+ }