@volter/sdk 0.0.0-stage → 0.5.203

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 (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1166 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +317 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +403 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,262 @@
1
+ import type { ShareRole } from '../share';
2
+
3
+ export type CollaborationCapability =
4
+ | 'view'
5
+ | 'comment'
6
+ | 'test'
7
+ | 'edit'
8
+ | 'terminal'
9
+ | 'maintain';
10
+ /**
11
+ * A collaboration role is a {@link ShareRole} PLUS the local-only `maintainer`,
12
+ * and it is spelled that way so the relationship is CHECKED. Written as its own
13
+ * six-member union — which is what it was — the two lists drift with no
14
+ * compiler signal: a role added to the share wire is simply a role this session
15
+ * cannot hold, and the only symptom is a participant the UI refuses to promote.
16
+ */
17
+ export type CollaborationRole = ShareRole | 'maintainer';
18
+ /**
19
+ * Least authority first; `maintainer` is local-only and has no share role.
20
+ *
21
+ * Declared as a `satisfies Record<CollaborationRole, …>` rather than an array
22
+ * annotated `readonly CollaborationRole[]`, because the array form accepts an
23
+ * INCOMPLETE list: adding a role to `CollaborationRole` and forgetting it here
24
+ * compiles, and the only symptom is that `assignableCollaborationRoles` quietly
25
+ * offers a participant one fewer role than they can hold. A missing key here is
26
+ * a compile error.
27
+ */
28
+ const COLLABORATION_ROLE_RANK = {
29
+ viewer: 0,
30
+ commenter: 1,
31
+ tester: 2,
32
+ editor: 3,
33
+ terminal: 4,
34
+ maintainer: 5,
35
+ } as const satisfies Record<CollaborationRole, number>;
36
+
37
+ export const COLLABORATION_ROLE_ORDER: readonly CollaborationRole[] = (
38
+ Object.keys(COLLABORATION_ROLE_RANK) as CollaborationRole[]
39
+ ).sort((a, b) => COLLABORATION_ROLE_RANK[a] - COLLABORATION_ROLE_RANK[b]);
40
+
41
+ /**
42
+ * Which roles a UI may OFFER for one participant. Enforcement is the server's,
43
+ * always; this only keeps the editor from presenting an option the session
44
+ * would refuse. A participant that entered through the share gateway carries a
45
+ * verified `account` and can never reach `maintainer`, nor exceed the ceiling
46
+ * its invitation set.
47
+ */
48
+ export function assignableCollaborationRoles(
49
+ participant: { account: { id: string } | null },
50
+ ceiling?: CollaborationRole,
51
+ ): CollaborationRole[] {
52
+ if (!participant.account) return [...COLLABORATION_ROLE_ORDER];
53
+ const remoteLimit = COLLABORATION_ROLE_ORDER.indexOf('terminal');
54
+ const ceilingIndex = ceiling ? COLLABORATION_ROLE_ORDER.indexOf(ceiling) : remoteLimit;
55
+ const limit = Math.min(remoteLimit, ceilingIndex < 0 ? remoteLimit : ceilingIndex);
56
+ return COLLABORATION_ROLE_ORDER.slice(0, limit + 1);
57
+ }
58
+
59
+ export type ParticipantKind = 'human' | 'agent';
60
+ export type ParticipantStatus = 'active' | 'idle' | 'needs-input' | 'done';
61
+
62
+ export interface CollaborationParticipantLocation {
63
+ repositoryId: string;
64
+ worktreeId: string;
65
+ sessionId: string;
66
+ }
67
+
68
+ export interface CollaborationAgentIdentity {
69
+ harness: string;
70
+ conversationId: string;
71
+ }
72
+
73
+ export interface CollaborationCameraPose {
74
+ x: number;
75
+ y: number;
76
+ z: number;
77
+ targetX: number;
78
+ targetY: number;
79
+ targetZ: number;
80
+ fov: number;
81
+ }
82
+
83
+ export function isCollaborationCameraPose(value: unknown): value is CollaborationCameraPose {
84
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
85
+ const camera = value as Record<string, unknown>;
86
+ const keys = ['x', 'y', 'z', 'targetX', 'targetY', 'targetZ', 'fov'] as const;
87
+ return (
88
+ Object.keys(camera).length === keys.length &&
89
+ keys.every((key) => typeof camera[key] === 'number' && Number.isFinite(camera[key])) &&
90
+ (camera['fov'] as number) > 0 &&
91
+ (camera['fov'] as number) < 180
92
+ );
93
+ }
94
+
95
+ /**
96
+ * THE owner of team-message size limits, read by the HTTP route guard and by
97
+ * `CollaborationSession`'s own methods alike.
98
+ *
99
+ * The two used to carry separate numbers and disagree in both directions — the
100
+ * route accepted 20k of text the session then refused, and refused 50
101
+ * references the session would have taken — so which error a caller saw
102
+ * depended on which layer happened to see the message first. Each value here is
103
+ * the tighter of the pair that split produced.
104
+ */
105
+ export const TEAM_MESSAGE_LIMITS = {
106
+ text: 10_000,
107
+ mentions: 16,
108
+ mentionLength: 80,
109
+ references: 32,
110
+ } as const;
111
+
112
+ export const COLLABORATION_AGENT_MENTIONS = ['agent', 'claude', 'codex'] as const;
113
+
114
+ export function isCollaborationAgentMention(value: string): boolean {
115
+ return (COLLABORATION_AGENT_MENTIONS as readonly string[]).includes(value.toLowerCase());
116
+ }
117
+
118
+ export interface CollaborationPresence {
119
+ document: string | null;
120
+ file: string | null;
121
+ oid: string | null;
122
+ selection: readonly string[];
123
+ camera: Readonly<CollaborationCameraPose> | null;
124
+ gesture: Readonly<Record<string, unknown>> | null;
125
+ playtest?: {
126
+ id: string;
127
+ play: 'starting' | 'ready' | 'error';
128
+ networking: 'not-declared' | 'connecting' | 'ready' | 'error';
129
+ roomName: string | null;
130
+ problem: string | null;
131
+ } | null;
132
+ }
133
+
134
+ export interface CollaborationParticipant {
135
+ participantId: string;
136
+ /** Verified Volter account authority. Null only for local-only host/agent
137
+ * participants that did not enter through a public share gateway. */
138
+ account: { id: string; email: string; name?: string } | null;
139
+ displayName: string;
140
+ kind: ParticipantKind;
141
+ color: string;
142
+ status: ParticipantStatus;
143
+ location: CollaborationParticipantLocation | null;
144
+ agent: CollaborationAgentIdentity | null;
145
+ role: CollaborationRole;
146
+ capabilities: readonly CollaborationCapability[];
147
+ connectedAt: string;
148
+ lastSeenAt: string;
149
+ presence: CollaborationPresence;
150
+ }
151
+
152
+ export interface CollaborationAuthorProjection {
153
+ participantId: string;
154
+ account: { id: string; email: string; name?: string } | null;
155
+ displayName: string;
156
+ kind: ParticipantKind;
157
+ color: string;
158
+ location: CollaborationParticipantLocation | null;
159
+ }
160
+
161
+ const PARTICIPANT_COLORS = [
162
+ '#4f8cff',
163
+ '#e45c9d',
164
+ '#20a87a',
165
+ '#a46de8',
166
+ '#d9782d',
167
+ '#2f9eb8',
168
+ '#ca4f55',
169
+ '#6f9f32',
170
+ ] as const;
171
+
172
+ export function collaborationParticipantColor(identity: string): string {
173
+ let hash = 2_166_136_261;
174
+ for (const codePoint of identity) {
175
+ hash ^= codePoint.codePointAt(0) ?? 0;
176
+ hash = Math.imul(hash, 16_777_619);
177
+ }
178
+ return PARTICIPANT_COLORS[(hash >>> 0) % PARTICIPANT_COLORS.length]!;
179
+ }
180
+
181
+ export type TeamMessageReference =
182
+ | { type: 'worktree'; worktreeId: string }
183
+ | { type: 'revision'; revision: number }
184
+ | { type: 'file'; path: string; revision: number }
185
+ | { type: 'oid'; oid: string; revision: number }
186
+ | { type: 'asset'; path: string; revision: number }
187
+ | { type: 'screenshot'; id: string; revision: number }
188
+ | { type: 'playtest'; id: string; revision: number }
189
+ | { type: 'diff'; fromRevision: number; toRevision: number };
190
+
191
+ export interface TeamMessage {
192
+ id: string;
193
+ authorId: string;
194
+ author: CollaborationAuthorProjection;
195
+ text: string;
196
+ mentions: readonly string[];
197
+ references: readonly TeamMessageReference[];
198
+ threadId: string | null;
199
+ editedAt: string | null;
200
+ deletedAt: string | null;
201
+ reactions: Readonly<Record<string, readonly string[]>>;
202
+ revision: number;
203
+ createdAt: string;
204
+ }
205
+
206
+ export interface SourceRevision {
207
+ revision: number;
208
+ authorId: string;
209
+ author: CollaborationAuthorProjection;
210
+ source: 'editor' | 'filesystem';
211
+ resources: readonly { path: string; sha: string | null }[];
212
+ createdAt: string;
213
+ }
214
+
215
+ export interface CollaborationAuditEvent {
216
+ id: string;
217
+ type: 'join' | 'leave' | 'role' | 'revision' | 'message' | 'agent' | 'playtest' | 'git';
218
+ participantId: string;
219
+ createdAt: string;
220
+ detail: Readonly<Record<string, unknown>>;
221
+ }
222
+
223
+ export interface TeamPlaytest {
224
+ id: string;
225
+ revision: number;
226
+ seed: number;
227
+ roomKey: string;
228
+ startedBy: string;
229
+ startedAt: string;
230
+ }
231
+
232
+ export interface CollaborationSnapshot {
233
+ sequence: number;
234
+ revision: number;
235
+ activePlaytest: TeamPlaytest | null;
236
+ participants: readonly CollaborationParticipant[];
237
+ messages: readonly TeamMessage[];
238
+ revisions: readonly SourceRevision[];
239
+ audit: readonly CollaborationAuditEvent[];
240
+ }
241
+
242
+ export type CollaborationEventChannel =
243
+ | 'participants'
244
+ | 'presence'
245
+ | 'messages'
246
+ | 'revisions'
247
+ | 'audit'
248
+ | 'team-test';
249
+
250
+ export interface CollaborationEvent {
251
+ sequence: number;
252
+ channel: CollaborationEventChannel;
253
+ createdAt: string;
254
+ payload: unknown;
255
+ }
256
+
257
+ export interface CollaborationResume {
258
+ cursor: number;
259
+ reset: boolean;
260
+ events: readonly CollaborationEvent[];
261
+ snapshot?: CollaborationSnapshot;
262
+ }
@@ -0,0 +1,327 @@
1
+ import { MAX_DOCUMENT_KEY_HOLD_MS } from '../document-probe';
2
+
3
+ /**
4
+ * THE RELAY COMMAND VOCABULARY, in one typed table.
5
+ *
6
+ * A relay command's type string used to be answered by two independent
7
+ * switches that had to agree and were never checked against each other:
8
+ * `command-listener.ts`'s dispatch (what the command DOES) and
9
+ * `server/server-utils.ts`'s `relayCommandTimeoutMs` (how long the server
10
+ * waits for it). A command missing from the second one did not fail — it
11
+ * silently took the generic 5s default, which undercut a client's 60s hold, so
12
+ * the uninformative timer won every race and sent a real investigation looking
13
+ * for a dead editor.
14
+ *
15
+ * This table is the single source. Adding a command means adding a ROW here:
16
+ * the dispatch switch keys off `RelayCommandType`, so a case with no row does
17
+ * not compile, and a row with no case fails the exhaustiveness check in that
18
+ * switch's `default`. The server imports the timeout column rather than
19
+ * restating it.
20
+ *
21
+ * `timeoutMs` is the budget for the WORK. Delivery has its own, much shorter
22
+ * budget (`RELAY_DELIVERY_ACK_MS`, clamped by `RELAY_DELIVERY_MAX_WAIT_MS`) —
23
+ * see `server/server-utils.ts`, which explains why the two are separate.
24
+ */
25
+
26
+ /**
27
+ * The generic budget. Most commands are a synchronous edit against the live
28
+ * editor and answer in milliseconds; the rows that override this are the ones
29
+ * that boot a game, rasterize something, or hand control to a game's own code.
30
+ */
31
+ export const DEFAULT_RELAY_COMMAND_TIMEOUT_MS = 5_000;
32
+
33
+ interface RelayCommandSpec {
34
+ /** How long the relay waits for this command to FINISH. */
35
+ readonly timeoutMs: number;
36
+ /** Whether command completion owes a tree-scale status derivation. */
37
+ readonly derivedRefresh: RelayCommandDerivedRefresh;
38
+ }
39
+
40
+ export type RelayCommandDerivedRefresh = 'none' | 'if-content-changed' | 'always';
41
+
42
+ const noDerivedRefresh = (timeoutMs = DEFAULT_RELAY_COMMAND_TIMEOUT_MS): RelayCommandSpec => ({
43
+ timeoutMs,
44
+ derivedRefresh: 'none',
45
+ });
46
+
47
+ const refreshIfContentChanged = (
48
+ timeoutMs = DEFAULT_RELAY_COMMAND_TIMEOUT_MS,
49
+ ): RelayCommandSpec => ({ timeoutMs, derivedRefresh: 'if-content-changed' });
50
+
51
+ const alwaysRefresh = (timeoutMs = DEFAULT_RELAY_COMMAND_TIMEOUT_MS): RelayCommandSpec => ({
52
+ timeoutMs,
53
+ derivedRefresh: 'always',
54
+ });
55
+
56
+ /**
57
+ * Every command the editor's relay accepts, and how long it waits for each one
58
+ * to answer. Pure and exported so the table is testable without booting a
59
+ * server and standing through a real 5-second expiry.
60
+ *
61
+ * The rule the table encodes: the budget belongs to whoever the ack is
62
+ * actually gated on. An ordinary editor interaction ("select this entity") is
63
+ * gated on the editor and must fail fast — 5s. Everything with its own entry
64
+ * is gated on something slower and outside the editor's control:
65
+ *
66
+ * - `capture-asset-preview` loads a model, renders four views and encodes
67
+ * five PNGs before acknowledging.
68
+ * - `capture-active-document` can wait for an ingested canvas's next render,
69
+ * composite its canvas and DOM layers, sample flatness, and encode the PNG.
70
+ * It is not an ordinary editor read. Measured in Doctor on racing-game under
71
+ * SwiftShader: the 5s default expired while the page kept rasterizing; the
72
+ * walk retried, parked more captures behind it, and `stop` then 504ed behind
73
+ * work the relay had already told its caller was over.
74
+ * - `active-tab` may synchronously mount a component board before its result can
75
+ * be serialized. The Unity FPS import has 178 stories: the page RECEIVED the
76
+ * command in 0.9s but its first board activation answered after the generic
77
+ * 5s budget, while heartbeats continued throughout. This is editor work, but
78
+ * it is not a millisecond chrome toggle when the destination mounts a board.
79
+ * - `select` and `inspect` may synchronously publish the selected subject and
80
+ * compose its inspector after a cold remount. The translated Unity FPS scene
81
+ * has 4,458 authored objects: Doctor measured both commands received by a
82
+ * beating tab yet still working past 5s, which filed seven false `play-stall`
83
+ * errors and made a source value that had survived the remount look unreadable.
84
+ * - `set-inspection-field`, `remove-inspection-field`, and
85
+ * `run-inspection-action` are authored WRITES —
86
+ * the same dialect writer, the same pipe, the same budget; removing an
87
+ * attribute re-parses and rewrites the module exactly as setting one does.
88
+ * For a source-backed root
89
+ * that write is server work the tab waits on: the planner re-parses the
90
+ * game's own module, the writer rewrites the literal, and a vendored game's
91
+ * lock is re-hashed and recorded in the same gesture. Measured on the
92
+ * racing-game ingest, where the tab is also servicing a game that logs every
93
+ * frame: EVERY transform write came back 504 at the 5s default while the
94
+ * same tab answered `select`/`inspect`/`hierarchy` in the same second — so
95
+ * the caller was told "no editor answered" about a write that was merely
96
+ * slow, which is the failure mode this whole table exists to stop.
97
+ * The PLAY verbs and the whole page-bridge family carry their budgets in
98
+ * `@volter/editor-game`'s own contributed rows now, for the same reasons and with the
99
+ * same numbers: `play` waits on the project's entire async `setup()`; `stop`
100
+ * waits on a teardown chain; `bridge-recording-export` steps a paused game
101
+ * frame by frame and encodes a video; `bridge-call` runs GAME code;
102
+ * `page-script` and `game-eval` run a step the CALLER wrote; and
103
+ * `bridge-screenshot` rasterizes the whole game stack.
104
+ *
105
+ * That family is the reason this table exists as a named thing. Their
106
+ * client (`@volter/game-live`'s `RelayTransport`) already applies its own per-leg
107
+ * `AbortSignal.timeout` — 60s for invoke/page-script, 15s for screenshot —
108
+ * and the server's generic 5s was UNDERCUTTING it, so the server's timer won
109
+ * every race. That mattered for the message, not just the duration: the
110
+ * client's own expiry produces `RELAY_UNREACHABLE` plus a "split the hold into
111
+ * shorter calls" hint, while the server's produces "Command timed out —
112
+ * editor connected but did not respond", which names nothing and sent a real
113
+ * investigation looking for a dead editor. Keep each entry >= its client-side
114
+ * counterpart so the informative timer is always the one that fires.
115
+ *
116
+ * Rows without an explicit budget take {@link DEFAULT_RELAY_COMMAND_TIMEOUT_MS}.
117
+ */
118
+ export const RELAY_COMMANDS = {
119
+ 'session-prepare-close': noDerivedRefresh(120_000),
120
+ // ---- Selection ---------------------------------------------------------
121
+ select: noDerivedRefresh(30_000),
122
+ 'select-multiple': noDerivedRefresh(),
123
+ 'select-all': noDerivedRefresh(),
124
+
125
+ // ---- Editor chrome ------------------------------------------------------
126
+ 'viewport-tab': noDerivedRefresh(),
127
+ // Focusing a panel is dock work, but its ack WAITS for the dock to report
128
+ // the panel focused (`revealStaticPanel`), so keep the relay past that wait.
129
+ 'show-panel': noDerivedRefresh(15_000),
130
+ 'active-tab': alwaysRefresh(30_000),
131
+ // Opening and presenting can await the inspector and a fresh source build.
132
+ // Keep their relay budget aligned with capture-active-document below.
133
+ 'open-asset-tab': alwaysRefresh(30_000),
134
+ // The selection half: it changes what the Inspector shows, so the derived
135
+ // state a caller reads next must be refreshed like the open half's.
136
+ 'select-asset': alwaysRefresh(),
137
+ 'close-asset-tab': alwaysRefresh(),
138
+ 'toggle-command-palette': noDerivedRefresh(),
139
+ 'toggle-console': noDerivedRefresh(),
140
+ // RELOAD THE EDITOR PAGE — `@volter/game-live`'s `page.reload()`, the one page verb
141
+ // no step can express. It is the HOST's, not a package's: reloading the tab
142
+ // is what the tab is, and until walk 5 it was a `@volter/editor-game` command
143
+ // contribution, so a project without that package — every model project —
144
+ // answered `unknown command type "page-reload"` for a door `@volter/game-live`
145
+ // documents as general (measured on a `cyclotron create` scaffold,
146
+ // 2026-09-21). The handler schedules the navigation for the next task so
147
+ // this ack can travel before the channel is torn down; the client waits for
148
+ // the new page load on the server's own tab table.
149
+ 'page-reload': alwaysRefresh(),
150
+ // Acks the ARRANGEMENT, not the intent: the dock clears and rebuilds on the
151
+ // next paint, so the handler waits for that rebuild (see
152
+ // `workspace-presets.ts`'s applied signal). Still ordinary editor work.
153
+ 'set-workspace': noDerivedRefresh(),
154
+ // A style bundle is chrome appearance; the document is untouched.
155
+ 'set-style': noDerivedRefresh(),
156
+ 'set-appearance': noDerivedRefresh(),
157
+ // A view's viewport presentation (lighting, backdrop, overlays); the document is untouched.
158
+ 'viewport-presentation': noDerivedRefresh(),
159
+ 'present-view': alwaysRefresh(30_000),
160
+ 'current-view': refreshIfContentChanged(),
161
+ // A read of the resolved document table; changes nothing.
162
+ 'document-table': noDerivedRefresh(),
163
+
164
+ // ---- Inspection and authoring ------------------------------------------
165
+ // The inspection writes go through the project mutation path, which touches
166
+ // the filesystem and may wait on a collaboration revision.
167
+ inspect: refreshIfContentChanged(30_000),
168
+ hierarchy: refreshIfContentChanged(),
169
+ 'expand-hierarchy-all': refreshIfContentChanged(),
170
+ 'collapse-hierarchy-all': refreshIfContentChanged(),
171
+ 'document-probe': refreshIfContentChanged(),
172
+ // A step against the open document's session can edit it (`ctx.ops.mesh.*`).
173
+ // Project-owned document code can rebuild an entire Model, just as a
174
+ // page-script can rebuild a game. Give both the same execution budget.
175
+ 'document-script': refreshIfContentChanged(60_000),
176
+ 'set-inspection-field': alwaysRefresh(30_000),
177
+ 'remove-inspection-field': alwaysRefresh(30_000),
178
+ // `extract-component` and `fork-component` left this table with their menus
179
+ // (`@volter/editor-game/contributions/component-verbs.command.ts`), which carries
180
+ // both budgets forward row for row.
181
+ // The hierarchy context menu's structure verbs, over the control door. Every
182
+ // one of them rewrites the game's own source, so they refresh like a write.
183
+ 'structure-op': alwaysRefresh(30_000),
184
+ 'run-inspection-action': alwaysRefresh(30_000),
185
+ // `editor.command(id, args)` — ONE workbench/view command by id. What it
186
+ // does is the command's, so nothing here can know whether the document
187
+ // changed: `alwaysRefresh` is the honest budget, the same one every other
188
+ // "run something the editor does not model" verb takes.
189
+ 'run-command': alwaysRefresh(30_000),
190
+ undo: alwaysRefresh(),
191
+ redo: alwaysRefresh(),
192
+ // `open` WAITS FOR THE PROJECT ADAPTER, for the same reason `play` waits on
193
+ // the project's async `setup()`: on a cold session the adapter's scene table
194
+ // is not there yet, and the door's whole job is to put a document on screen
195
+ // once it is. MEASURED on three cold the editor's `edit` command sessions over a
196
+ // `--template models` probe — 6025 / 6831 / 6474 ms from tab-connected to
197
+ // the entry being listed, every one of them first refusing with
198
+ // `SCENE_TABLE_UNAVAILABLE`. At the 5 s default the relay's timer won that
199
+ // race and the caller was told "the tab did not respond" about a door that
200
+ // was merely waiting, which is the exact failure this table exists to stop.
201
+ // 30 s sits above `openSceneTableEntryWhenListed`'s own 15 s bound so the
202
+ // INFORMATIVE refusal (the scene table's, naming the known ids) is always
203
+ // the one that fires.
204
+ open: alwaysRefresh(30_000),
205
+
206
+ // ---- Rasterizing --------------------------------------------------------
207
+ // Everything here renders something and reads pixels back.
208
+ 'capture-active-document': refreshIfContentChanged(30_000),
209
+ // The whole editor page through the same compositor; the foreignObject leg
210
+ // over a full dock takes seconds, not milliseconds.
211
+ 'capture-editor-chrome': refreshIfContentChanged(30_000),
212
+
213
+ // The ONE door onto a view's verbs (`@volter/sdk/views`, U8 ruling 1).
214
+ // A verb either READS the view or moves its own transform; neither touches
215
+ // a document, so nothing derived refreshes.
216
+
217
+ // The THREE VIEWPORT'S verbs — framing, the camera, view presets, the open
218
+ // Object3D document's orbit/turntable/frame, the viewport photograph and the
219
+ // display and transform toggles — are its own command contribution
220
+ // (`viewport-commands.ts`), each budget on its contributed row.
221
+
222
+ // The BLENDER lane's ten verbs are `@volter/editor-blender`'s
223
+ // `contributions/blender.command.ts` (WORK.md §The workbench, item D) —
224
+ // each row's budget travelled with it, onto the contributed spec the page
225
+ // reports to the server. `capture-story-variants` made the same move, to the
226
+ // kit's own `stories/story-capture-command.ts`: it
227
+ // mounts each CSF export, waits for the DOM to settle, rasterizes it through
228
+ // the `foreignObject` leg and tiles the sheet, so its budget scales with the
229
+ // file's export count rather than with any single render — 120 s, measured
230
+ // on a real 10-story HUD file that expired the default outright, and stated
231
+ // now on the contributed row instead of here.
232
+ } as const satisfies Record<string, RelayCommandSpec>;
233
+
234
+ /** Every command type the relay accepts. The dispatch switch keys off this. */
235
+ export type RelayCommandType = keyof typeof RELAY_COMMANDS;
236
+
237
+ /** The vocabulary as data — what a guard or a tool enumerates. */
238
+ export const RELAY_COMMAND_TYPES = Object.keys(RELAY_COMMANDS) as readonly RelayCommandType[];
239
+
240
+ export function isRelayCommandType(value: unknown): value is RelayCommandType {
241
+ return typeof value === 'string' && Object.hasOwn(RELAY_COMMANDS, value);
242
+ }
243
+
244
+ /**
245
+ * How long the relay waits for a command to finish. An unrecognized type gets
246
+ * the generic budget rather than an error: the relay's job is to hand the
247
+ * string to the tab and let the TAB say it does not know it.
248
+ */
249
+ export function relayCommandTimeoutMs(type: unknown, command?: Record<string, unknown>): number {
250
+ const base = isRelayCommandType(type)
251
+ ? RELAY_COMMANDS[type].timeoutMs
252
+ : DEFAULT_RELAY_COMMAND_TIMEOUT_MS;
253
+ // A held key answers after release. Its requested duration is work, not a
254
+ // stalled tab; ordinary probes retain their short completion budget.
255
+ if (type === 'document-probe' && command?.['step'] && typeof command['step'] === 'object') {
256
+ const step = command['step'] as Record<string, unknown>;
257
+ const hold = step['holdMs'];
258
+ if (step['action'] === 'key' && typeof hold === 'number' && Number.isFinite(hold) &&
259
+ hold >= 0 && hold <= MAX_DOCUMENT_KEY_HOLD_MS) return base + Math.ceil(hold);
260
+ }
261
+ return base;
262
+ }
263
+
264
+ /** The status-derivation policy owned by the same command row as its timeout. */
265
+ export function relayCommandDerivedRefresh(type: unknown): RelayCommandDerivedRefresh {
266
+ return isRelayCommandType(type) ? RELAY_COMMANDS[type].derivedRefresh : 'always';
267
+ }
268
+
269
+ /**
270
+ * The subset an INGEST session answers itself (`ingest/ingest-play-commands.ts`).
271
+ * A captured ingest is not a host-mounted root, so first-party play would tear
272
+ * its mount down; these five are dispatched against the ingest surface instead.
273
+ *
274
+ * Plain strings, not `RelayCommandType`: the five verbs left this table for
275
+ * `@volter/editor-game`'s `play.command.ts` when Play left the host (WORK.md §The
276
+ * workbench, P3b), and the ingest latch runs in `handleCommand`'s PROLOGUE —
277
+ * before any contributed handler is looked up — so a captured ingest still
278
+ * answers them first. The latch moves with ingest in P4.
279
+ */
280
+ export const INGEST_PLAY_COMMAND_TYPES = [
281
+ 'play',
282
+ 'stop',
283
+ 'pause',
284
+ 'resume',
285
+ 'step',
286
+ ] as const satisfies readonly string[];
287
+
288
+ export type IngestPlayCommandType = (typeof INGEST_PLAY_COMMAND_TYPES)[number];
289
+
290
+ export function isIngestPlayCommandType(value: unknown): value is IngestPlayCommandType {
291
+ return (INGEST_PLAY_COMMAND_TYPES as readonly string[]).includes(value as string);
292
+ }
293
+
294
+ /**
295
+ * THE ANSWER SHAPE, the other column of the same vocabulary — what a tab posts
296
+ * back to `/__editor/command-result` for a command it just ran.
297
+ *
298
+ * Same rule as the timeout column above, for the same reason: the relay has two
299
+ * ends in two compilation units — the browser that PRODUCES this
300
+ * (`command-listener.ts`) and the server that settles and re-serves it
301
+ * (`server/server-utils.ts`, `server/routes/control-plane.ts`) — and each used
302
+ * to declare its own copy. They had already drifted on the field that matters
303
+ * most: the browser's said `ok: boolean` and the server's said `ok?: boolean`,
304
+ * so server code could read a result that never says whether it worked. Both
305
+ * files already import this module (so does `ingest/ingest-play-commands.ts`,
306
+ * which restated the shape a third time), so there is no new dependency here.
307
+ *
308
+ * `ok` is REQUIRED because the producer always writes it: every browser exit
309
+ * (`structuredErrorResult`, `commandThrewResult`, every handler's return) and
310
+ * every server-side settle (`settlePendingCommand`'s callers, all of which pair
311
+ * `timedOut: true` with `ok: false`) sets it. A payload arriving from off the
312
+ * wire is narrowed where it enters — `handleCommandResult` — not by weakening
313
+ * this type.
314
+ *
315
+ * `timedOut` is deliberately NOT here: no tab produces it. It is the SERVER's
316
+ * own verdict for a command no tab answered, so it lives on the server's
317
+ * `RelayedCommandResult` extension beside the code that sets it.
318
+ */
319
+ export interface CommandResult {
320
+ ok: boolean;
321
+ error?: string;
322
+ /** Payload for commands that answer with data (`capture-viewport`'s base64
323
+ * PNG, the debug-seam reads). On the failure path it carries structured
324
+ * markers (`{ code: 'UNKNOWN_COMMAND_TYPE' }`, registered-name lists) the
325
+ * SDK matches on — never message prose. */
326
+ data?: Record<string, unknown>;
327
+ }
@@ -0,0 +1,100 @@
1
+ /** Registered-session discovery; never selects another project's session. */
2
+ import { readLiveRegisteredSessions, servedProjectAnswer } from './registry-format.js';
3
+ export { servedProjectAnswer } from './registry-format.js';
4
+
5
+ export const EDITOR_SESSION_DISCOVERY_TIMEOUT_MS = 2000;
6
+
7
+ export const EDITOR_PROBE_TIMEOUT_MS = 1500;
8
+
9
+ export class EditorTimeoutError extends Error {
10
+ constructor(label: string, ms: number) {
11
+ super(`${label} timed out after ${ms}ms`);
12
+ this.name = 'EditorTimeoutError';
13
+ }
14
+ }
15
+
16
+ export function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {
17
+ return new Promise<T>((resolvePromise, reject) => {
18
+ const timer = setTimeout(() => reject(new EditorTimeoutError(label, ms)), ms);
19
+ promise.then(
20
+ (v) => {
21
+ clearTimeout(timer);
22
+ resolvePromise(v);
23
+ },
24
+ (err) => {
25
+ clearTimeout(timer);
26
+ reject(err instanceof Error ? err : new Error(String(err)));
27
+ },
28
+ );
29
+ });
30
+ }
31
+
32
+ export interface EditorSessionInfo {
33
+ /** The port this session's dev server is bound to. */
34
+ port: number;
35
+ /** Canonical project root path currently open, or null when none. */
36
+ project: string | null;
37
+ /** Dev-server process id, when known from the local session registry (null for an unregistered/legacy server the caller only probed by port). */
38
+ pid: number | null;
39
+ /** Exact explicitly targeted editor origin/base URL, including protocol and host. */
40
+ url?: string;
41
+ /**
42
+ * Why this server cannot DESCRIBE the `project` it is serving — its
43
+ * manifest's own parse/validation failure, naming the failing key. `null`
44
+ * when the project reads fine, and `undefined` from a probe that did not ask
45
+ * (or a server too old to say). See {@link servedProjectAnswer}: a session in
46
+ * this state is still THIS project's session, and callers must report the
47
+ * reason rather than treat it as no session at all.
48
+ */
49
+ manifestError?: string | null;
50
+ }
51
+
52
+ async function fetchJson(url: string, timeoutMs: number): Promise<unknown> {
53
+ const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
54
+ if (!res.ok) throw new Error(`GET /__editor/project returned HTTP ${res.status}`);
55
+ return await res.json();
56
+ }
57
+
58
+ function baseUrl(session: EditorSessionInfo): string {
59
+ return session.url ?? `http://127.0.0.1:${session.port}`;
60
+ }
61
+
62
+ export interface SessionListingTransport { listSessions(timeoutMs: number): Promise<EditorSessionInfo[]>; }
63
+ export class HttpSessionDiscovery implements SessionListingTransport {
64
+ async listSessions(timeoutMs: number): Promise<EditorSessionInfo[]> {
65
+ const registered = readLiveRegisteredSessions();
66
+ const perProbeTimeout = Math.min(EDITOR_PROBE_TIMEOUT_MS, Math.max(200, timeoutMs));
67
+ const failures: string[] = [];
68
+ const probes = await Promise.all(
69
+ registered.map(async (s) => {
70
+ try {
71
+ const body = await fetchJson(
72
+ `${baseUrl({ port: s.port, project: null, pid: s.pid })}/__editor/project`,
73
+ perProbeTimeout,
74
+ );
75
+ const served = servedProjectAnswer(body);
76
+ const info: EditorSessionInfo = {
77
+ port: s.port,
78
+ project: served.path,
79
+ pid: s.pid,
80
+ manifestError: served.manifestError,
81
+ };
82
+ return info;
83
+ } catch (error) {
84
+ const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
85
+ failures.push(`port ${s.port}: ${detail}`);
86
+ return undefined;
87
+ }
88
+ }),
89
+ );
90
+ const sessions = probes.filter((p): p is EditorSessionInfo => p !== undefined);
91
+ // A readable registry with registered live processes is not an empty
92
+ // registry just because every HTTP discovery request failed. Keep any
93
+ // verified sessions usable, but refuse an entirely unanswered inventory
94
+ // rather than telling the caller to launch a second editor.
95
+ if (registered.length > 0 && sessions.length === 0) {
96
+ throw new Error(`Registered editor sessions could not be inspected: ${failures.join('; ')}`);
97
+ }
98
+ return sessions;
99
+ }
100
+ }