@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,288 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import chokidar, { type FSWatcher } from 'chokidar';
4
+ import { resolveProjectIdentity, resolveWorkTarget, trackerConfigPath } from 'ztrack';
5
+ import { createZtrackSupercodeBridge, type ZtrackSupercodeBridge } from 'ztrack/supercode';
6
+ import type { Payload } from 'ztrack/visualizer-kit';
7
+ import {
8
+ buildVisualizerExtensionModule,
9
+ loadVisualizerPayload,
10
+ loadVisualizerTheme,
11
+ } from 'ztrack/visualizer-node';
12
+ import type { ProjectWorkAssociation, ProjectWorkSnapshot } from '../src/project-work-types';
13
+ import { unavailableProjectWorkSnapshot } from '../src/project-work-types';
14
+ import type { HarnessChatService } from './harness-chat-service';
15
+
16
+ export interface ProjectWorkCoordinatorOptions {
17
+ getProjectRoot: () => string;
18
+ harnessChat: HarnessChatService;
19
+ onChange: (snapshot: ProjectWorkSnapshot) => void;
20
+ }
21
+
22
+ function cloneSnapshot(snapshot: ProjectWorkSnapshot): ProjectWorkSnapshot {
23
+ return structuredClone(snapshot);
24
+ }
25
+
26
+ function missingTracker(error: unknown, configPath: string): boolean {
27
+ if (!existsSync(configPath)) return true;
28
+ return /tracker-config|No tracker|ENOENT/i.test(
29
+ error instanceof Error ? error.message : String(error),
30
+ );
31
+ }
32
+
33
+ export class ProjectWorkCoordinator {
34
+ private revision = 0;
35
+ private generation = 0;
36
+ private closed = false;
37
+ private watcher: FSWatcher | null = null;
38
+ private reloadTimer: ReturnType<typeof setTimeout> | null = null;
39
+ private bridge: ZtrackSupercodeBridge | null = null;
40
+ private unsubscribeBridge: (() => void) | null = null;
41
+ private payload: Payload | null = null;
42
+ private extensionCode: string | null = null;
43
+ private hydrated = new Set<string>();
44
+ private failedHydration = new Map<
45
+ string,
46
+ { attempts: number; message: string; retryAt: number }
47
+ >();
48
+ private hydrationInFlight = false;
49
+ private hydrationRetryTimer: ReturnType<typeof setTimeout> | null = null;
50
+ private snapshotValue: ProjectWorkSnapshot = unavailableProjectWorkSnapshot(
51
+ 'Project Work is loading.',
52
+ );
53
+
54
+ constructor(private readonly options: ProjectWorkCoordinatorOptions) {}
55
+
56
+ snapshot(): ProjectWorkSnapshot {
57
+ return cloneSnapshot(this.snapshotValue);
58
+ }
59
+ extension(hash: string): string | null {
60
+ return hash === this.snapshotValue.presentation.extensionHash ? this.extensionCode : null;
61
+ }
62
+
63
+ async initialize(): Promise<ProjectWorkSnapshot> {
64
+ await this.reload();
65
+ return this.snapshot();
66
+ }
67
+
68
+ async setWorkspace(): Promise<void> {
69
+ this.generation += 1;
70
+ this.hydrated.clear();
71
+ this.failedHydration.clear();
72
+ await this.reload();
73
+ }
74
+
75
+ contextForIssue(issueId: string) {
76
+ if (!this.bridge) throw new Error('Project Work is unavailable for this project.');
77
+ return this.bridge.contextForIssue(issueId);
78
+ }
79
+
80
+ private publish(next: Omit<ProjectWorkSnapshot, 'revision'>): void {
81
+ this.snapshotValue = { ...next, revision: ++this.revision };
82
+ this.options.onChange(this.snapshot());
83
+ }
84
+
85
+ private disposeLiveState(): void {
86
+ this.unsubscribeBridge?.();
87
+ this.unsubscribeBridge = null;
88
+ this.bridge?.dispose();
89
+ this.bridge = null;
90
+ void this.watcher?.close();
91
+ this.watcher = null;
92
+ if (this.reloadTimer) clearTimeout(this.reloadTimer);
93
+ this.reloadTimer = null;
94
+ if (this.hydrationRetryTimer) clearTimeout(this.hydrationRetryTimer);
95
+ this.hydrationRetryTimer = null;
96
+ }
97
+
98
+ private watch(paths: string[]): void {
99
+ this.watcher = chokidar.watch([...new Set(paths)], { ignoreInitial: true, persistent: true });
100
+ this.watcher.on('all', () => {
101
+ if (this.reloadTimer) clearTimeout(this.reloadTimer);
102
+ this.reloadTimer = setTimeout(() => void this.reload(), 150);
103
+ });
104
+ }
105
+
106
+ private async reload(): Promise<void> {
107
+ if (this.closed) return;
108
+ const generation = ++this.generation;
109
+ this.disposeLiveState();
110
+ const projectRoot = resolve(this.options.getProjectRoot());
111
+ const configPath = trackerConfigPath(projectRoot);
112
+ try {
113
+ const [board, extension, theme] = await Promise.all([
114
+ loadVisualizerPayload({ projectRoot }),
115
+ buildVisualizerExtensionModule({ projectRoot }),
116
+ loadVisualizerTheme({ projectRoot }),
117
+ ]);
118
+ if (generation !== this.generation || this.closed) return;
119
+ this.payload = board.payload;
120
+ this.extensionCode = extension.code;
121
+ const project = resolveProjectIdentity(projectRoot);
122
+ const trackerListeners = new Set<() => void>();
123
+ this.bridge = createZtrackSupercodeBridge({
124
+ projectRoot,
125
+ tracker: {
126
+ resolveProjectIdentity,
127
+ resolveWorkTarget,
128
+ payload: () => this.payload!,
129
+ subscribe: (listener) => {
130
+ trackerListeners.add(listener);
131
+ return () => trackerListeners.delete(listener);
132
+ },
133
+ },
134
+ supercode: this.options.harnessChat.bridgeAdapter(),
135
+ });
136
+ this.unsubscribeBridge = this.bridge.subscribe(() => this.rebuildFromBridge());
137
+ this.watch([...board.watchPaths, ...extension.watchPaths, ...theme.watchPaths, configPath]);
138
+ this.rebuildFromBridge({
139
+ extensionHash: extension.contentHash,
140
+ extensionError: extension.error,
141
+ theme: theme.variables,
142
+ themeError: theme.error,
143
+ projectKey: project.projectKey,
144
+ });
145
+ } catch (error) {
146
+ if (generation !== this.generation || this.closed) return;
147
+ this.payload = null;
148
+ this.extensionCode = null;
149
+ this.watch([configPath]);
150
+ const tracker = missingTracker(error, configPath)
151
+ ? { state: 'missing' as const }
152
+ : {
153
+ state: 'error' as const,
154
+ message: error instanceof Error ? error.message : String(error),
155
+ };
156
+ this.publish({
157
+ schema: 'vgai.project-work.v1',
158
+ projectKey: null,
159
+ tracker,
160
+ associations: [],
161
+ activityByIssue: {},
162
+ presentation: { extensionHash: null, extensionError: null, theme: {}, themeError: null },
163
+ });
164
+ }
165
+ }
166
+
167
+ private rebuildFromBridge(
168
+ presentation?: ProjectWorkSnapshot['presentation'] & { projectKey: string },
169
+ ): void {
170
+ if (!this.bridge || !this.payload) return;
171
+ const harness = this.options.harnessChat.snapshot();
172
+ const bridgeSnapshot = this.options.harnessChat.bridgeAdapter().getSnapshot();
173
+ const associations: ProjectWorkAssociation[] = bridgeSnapshot.sessions.map((session) => {
174
+ const result = this.bridge!.resolveSession({ session });
175
+ const hydrationFailure = this.failedHydration.get(session.identity);
176
+ const observed =
177
+ session.key === bridgeSnapshot.activeSessionKey || this.hydrated.has(session.identity);
178
+ return {
179
+ sessionIdentity: session.identity,
180
+ issueId: observed ? result.issueId : null,
181
+ state: observed ? result.state : hydrationFailure ? 'error' : 'loading',
182
+ source: observed ? result.source : null,
183
+ reason: observed
184
+ ? result.reason
185
+ : hydrationFailure
186
+ ? `Unable to inspect this session: ${hydrationFailure.message}. Retrying automatically.`
187
+ : 'persisted session has not been observed yet',
188
+ observedAt: session.updatedAt,
189
+ };
190
+ });
191
+ const activityByIssue: ProjectWorkSnapshot['activityByIssue'] = {};
192
+ for (const activity of this.bridge.activitySnapshot()) {
193
+ if (activity.freshness === 'last-observed' && !this.hydrated.has(activity.sessionIdentity))
194
+ continue;
195
+ const issueActivity = activityByIssue[activity.issueId] ?? [];
196
+ issueActivity.push(activity);
197
+ activityByIssue[activity.issueId] = issueActivity;
198
+ }
199
+ const currentPresentation = presentation ?? {
200
+ ...this.snapshotValue.presentation,
201
+ projectKey:
202
+ this.snapshotValue.projectKey ??
203
+ resolveProjectIdentity(this.options.getProjectRoot()).projectKey,
204
+ };
205
+ this.publish({
206
+ schema: 'vgai.project-work.v1',
207
+ projectKey: currentPresentation.projectKey,
208
+ tracker: { state: 'ready', payload: this.payload },
209
+ associations,
210
+ activityByIssue,
211
+ presentation: {
212
+ extensionHash: currentPresentation.extensionHash,
213
+ extensionError: currentPresentation.extensionError,
214
+ theme: currentPresentation.theme,
215
+ themeError: currentPresentation.themeError,
216
+ },
217
+ });
218
+ if (harness.operation === null && harness.turn.state === 'idle') void this.hydrateOne();
219
+ }
220
+
221
+ private async hydrateOne(): Promise<void> {
222
+ if (this.hydrationInFlight || !this.bridge || this.closed) return;
223
+ const snapshot = this.options.harnessChat.snapshot();
224
+ const now = Date.now();
225
+ const candidates = snapshot.sessions.filter(
226
+ (candidate) =>
227
+ candidate.id !== snapshot.activeSessionId && !this.hydrated.has(candidate.identity),
228
+ );
229
+ const session = candidates.find(
230
+ (candidate) => (this.failedHydration.get(candidate.identity)?.retryAt ?? 0) <= now,
231
+ );
232
+ if (!session) {
233
+ const nextRetry = candidates.reduce((earliest, candidate) => {
234
+ const retryAt = this.failedHydration.get(candidate.identity)?.retryAt;
235
+ return retryAt === undefined ? earliest : Math.min(earliest, retryAt);
236
+ }, Number.POSITIVE_INFINITY);
237
+ if (Number.isFinite(nextRetry) && !this.hydrationRetryTimer) {
238
+ const generation = this.generation;
239
+ this.hydrationRetryTimer = setTimeout(
240
+ () => {
241
+ this.hydrationRetryTimer = null;
242
+ if (generation === this.generation) void this.hydrateOne();
243
+ },
244
+ Math.max(0, nextRetry - now),
245
+ );
246
+ }
247
+ return;
248
+ }
249
+ const generation = this.generation;
250
+ this.hydrationInFlight = true;
251
+ try {
252
+ const loaded = await this.options.harnessChat.loadSessionForProjectWork(session.id);
253
+ if (generation !== this.generation || this.closed || !this.bridge) return;
254
+ this.hydrated.add(session.identity);
255
+ this.failedHydration.delete(session.identity);
256
+ this.bridge.resolveSession({
257
+ session: {
258
+ key: session.id,
259
+ identity: session.identity,
260
+ cwd: session.cwd,
261
+ title: session.title,
262
+ updatedAt: session.updatedAt,
263
+ },
264
+ loadedSession: loaded,
265
+ });
266
+ this.rebuildFromBridge();
267
+ } catch (error) {
268
+ if (generation !== this.generation || this.closed || !this.bridge) return;
269
+ const previous = this.failedHydration.get(session.identity);
270
+ const attempts = (previous?.attempts ?? 0) + 1;
271
+ this.failedHydration.set(session.identity, {
272
+ attempts,
273
+ message: error instanceof Error ? error.message : String(error),
274
+ retryAt: Date.now() + Math.min(30_000, 1_000 * 2 ** (attempts - 1)),
275
+ });
276
+ this.rebuildFromBridge();
277
+ } finally {
278
+ this.hydrationInFlight = false;
279
+ if (!this.closed) queueMicrotask(() => void this.hydrateOne());
280
+ }
281
+ }
282
+
283
+ async close(): Promise<void> {
284
+ this.closed = true;
285
+ this.generation += 1;
286
+ this.disposeLiveState();
287
+ }
288
+ }
@@ -0,0 +1,331 @@
1
+ import type {
2
+ ProviderCredentialId,
3
+ ProviderCredentialStatus,
4
+ ProviderCredentialTestResult,
5
+ } from '@volter/editor-sdk/account';
6
+ import {
7
+ type CredentialPersistence,
8
+ createNativeCredentialStore,
9
+ type NativeCredentialStore,
10
+ } from './native-credential-store';
11
+
12
+ interface ProviderCredentialDefinition {
13
+ id: ProviderCredentialId;
14
+ label: string;
15
+ environmentVariable: string;
16
+ test(key: string, signal: AbortSignal): Promise<Response>;
17
+ }
18
+
19
+ const checkedFetch = (input: string, init: RequestInit) => fetch(input, init);
20
+
21
+ export const PROVIDER_CREDENTIALS: readonly ProviderCredentialDefinition[] = [
22
+ {
23
+ id: 'fal',
24
+ label: 'Fal',
25
+ environmentVariable: 'FAL_KEY',
26
+ test: (key, signal) =>
27
+ checkedFetch('https://api.fal.ai/v1/models/pricing?endpoint_id=fal-ai/flux/dev', {
28
+ headers: { Authorization: `Key ${key}` },
29
+ signal,
30
+ }),
31
+ },
32
+ {
33
+ id: 'tripo',
34
+ label: 'Tripo',
35
+ environmentVariable: 'TRIPO_API_KEY',
36
+ test: (key, signal) =>
37
+ checkedFetch('https://api.tripo3d.ai/v2/openapi/user/balance', {
38
+ headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' },
39
+ signal,
40
+ }),
41
+ },
42
+ {
43
+ id: 'worldlabs',
44
+ label: 'World Labs',
45
+ environmentVariable: 'WORLDLABS_API_KEY',
46
+ test: (key, signal) =>
47
+ checkedFetch('https://api.worldlabs.ai/marble/v1/worlds:list', {
48
+ method: 'POST',
49
+ headers: { 'Content-Type': 'application/json', 'WLT-Api-Key': key },
50
+ body: JSON.stringify({ page_size: 1 }),
51
+ signal,
52
+ }),
53
+ },
54
+ {
55
+ id: 'openrouter',
56
+ label: 'OpenRouter',
57
+ environmentVariable: 'OPENROUTER_API_KEY',
58
+ test: (key, signal) =>
59
+ checkedFetch('https://openrouter.ai/api/v1/key', {
60
+ headers: { Authorization: `Bearer ${key}` },
61
+ signal,
62
+ }),
63
+ },
64
+ ] as const;
65
+
66
+ export interface ProviderCredentialStore {
67
+ persistence(): Promise<CredentialPersistence>;
68
+ read(provider: ProviderCredentialId): Promise<string | null>;
69
+ write(provider: ProviderCredentialId, value: string): Promise<void>;
70
+ delete(provider: ProviderCredentialId): Promise<void>;
71
+ }
72
+
73
+ export function createSystemProviderCredentialStore(
74
+ native: NativeCredentialStore = createNativeCredentialStore(),
75
+ ): ProviderCredentialStore {
76
+ return {
77
+ persistence: () => native.persistence(),
78
+ read: (provider) => native.read(`provider:${provider}`),
79
+ write: (provider, value) => native.write(`provider:${provider}`, value),
80
+ delete: (provider) => native.delete(`provider:${provider}`),
81
+ };
82
+ }
83
+
84
+ /**
85
+ * What the account panel shows for a CONNECTED provider, kept beside the
86
+ * secret rather than derived from it: the mask is the last four characters,
87
+ * which the editor already renders in the browser, so it is not itself a
88
+ * secret.
89
+ */
90
+ export interface ProviderCredentialMarker {
91
+ maskedKey: string;
92
+ connectedAt: string;
93
+ }
94
+
95
+ /**
96
+ * The non-secret record of WHICH providers have a key in the system store.
97
+ * `EditorAccountService` backs this with `~/.vgai/account.json`, the file it
98
+ * already owns; an unbacked service keeps it in memory for the process.
99
+ */
100
+ export interface ProviderCredentialMarkerStore {
101
+ read(): Promise<Partial<Record<ProviderCredentialId, ProviderCredentialMarker>>>;
102
+ write(provider: ProviderCredentialId, marker: ProviderCredentialMarker | null): Promise<void>;
103
+ }
104
+
105
+ function memoryMarkerStore(): ProviderCredentialMarkerStore {
106
+ const markers = new Map<ProviderCredentialId, ProviderCredentialMarker>();
107
+ return {
108
+ read: async () => Object.fromEntries(markers),
109
+ write: async (provider, marker) => {
110
+ if (marker) markers.set(provider, marker);
111
+ else markers.delete(provider);
112
+ },
113
+ };
114
+ }
115
+
116
+ function definition(id: string): ProviderCredentialDefinition {
117
+ const found = PROVIDER_CREDENTIALS.find((candidate) => candidate.id === id);
118
+ if (!found) throw new Error(`Unsupported provider credential ${JSON.stringify(id)}.`);
119
+ return found;
120
+ }
121
+
122
+ function normalizeKey(value: string): string {
123
+ const key = value.trim();
124
+ if (!key) throw new Error('API key is required.');
125
+ if (key.length > 16_384) throw new Error('API key is too large.');
126
+ return key;
127
+ }
128
+
129
+ function maskedKey(value: string): string {
130
+ return value.length > 4 ? `••••${value.slice(-4)}` : '••••';
131
+ }
132
+
133
+ /**
134
+ * Resolves provider-native BYOK credentials without creating a provider API
135
+ * wrapper. The provider tools continue to call their native SDK/HTTP APIs and
136
+ * read their conventional environment variables; this service owns only the
137
+ * durable-secret boundary and deterministic source precedence.
138
+ *
139
+ * A SECRET IS READ AT THE MOMENT A JOB NEEDS IT, NEVER AT BOOT, AND ONLY FOR
140
+ * THE PROVIDER THAT JOB NAMES. macOS prompts to unlock a Keychain item once
141
+ * per item per calling binary per read, and `vgai edit` is a fresh process
142
+ * every time, so a boot-time sweep of every provider is a stack of unlock
143
+ * dialogs in front of someone who asked to open a project — and a model
144
+ * project has no generation job at all. `ensure(provider)` is therefore THE
145
+ * read: one item, memoised for the process, exporting that provider's
146
+ * conventional environment variable at that moment. There is no `initialize`.
147
+ *
148
+ * "Is this provider configured?" is answered from the marker record above and
149
+ * NEVER from a credential-manager read: `@napi-rs/keyring` exposes no
150
+ * attributes-only call (`getPassword`, `getSecret` and `findCredentials` all
151
+ * return the secret, which IS the prompt), so the account panel's reading
152
+ * would otherwise be a stack of dialogs on every 30-second poll. Connecting
153
+ * and disconnecting a key rewrite both the item and the marker; a real read
154
+ * for a job refreshes the marker, so a key connected before the marker
155
+ * existed heals into the record the first time it is used.
156
+ */
157
+ export class ProviderCredentialService {
158
+ private readonly environment = new Map<ProviderCredentialId, string>();
159
+ private readonly stored = new Map<ProviderCredentialId, string>();
160
+ private readonly storageProblems = new Map<ProviderCredentialId, string>();
161
+ private readonly injected = new Set<ProviderCredentialId>();
162
+ private readonly ensured = new Map<ProviderCredentialId, Promise<string | undefined>>();
163
+
164
+ constructor(
165
+ private readonly store: ProviderCredentialStore = createSystemProviderCredentialStore(),
166
+ private readonly markers: ProviderCredentialMarkerStore = memoryMarkerStore(),
167
+ ) {
168
+ for (const provider of PROVIDER_CREDENTIALS) {
169
+ const value = process.env[provider.environmentVariable]?.trim();
170
+ if (value) {
171
+ this.environment.set(provider.id, value);
172
+ process.env[provider.environmentVariable] = value;
173
+ }
174
+ }
175
+ }
176
+
177
+ /**
178
+ * THE credential read: one provider, one credential-manager call, memoised
179
+ * for the process. Call it where a job needs the secret, never earlier.
180
+ * An unknown provider id resolves to `undefined` rather than throwing —
181
+ * `providerExecutionMode` asks about arbitrary provider names.
182
+ */
183
+ ensure(providerId: string): Promise<string | undefined> {
184
+ const provider = PROVIDER_CREDENTIALS.find((candidate) => candidate.id === providerId);
185
+ if (!provider) return Promise.resolve(undefined);
186
+ const environment = this.environment.get(provider.id);
187
+ if (environment !== undefined) return Promise.resolve(environment);
188
+ let pending = this.ensured.get(provider.id);
189
+ if (!pending) {
190
+ pending = this.readStored(provider);
191
+ this.ensured.set(provider.id, pending);
192
+ }
193
+ return pending;
194
+ }
195
+
196
+ /** `true` when the credential manager itself is holding the secrets, so a
197
+ * marker written now will still be true after a restart. */
198
+ private async systemBacked(): Promise<boolean> {
199
+ try {
200
+ return (await this.store.persistence()) === 'system';
201
+ } catch {
202
+ return false;
203
+ }
204
+ }
205
+
206
+ private async readStored(provider: ProviderCredentialDefinition): Promise<string | undefined> {
207
+ try {
208
+ const value = await this.store.read(provider.id);
209
+ if (!value) {
210
+ this.stored.delete(provider.id);
211
+ // Only a store that is really holding secrets can say "absent";
212
+ // a degraded one answers from memory and must not wipe the record.
213
+ if (await this.systemBacked()) await this.markers.write(provider.id, null);
214
+ return undefined;
215
+ }
216
+ this.stored.set(provider.id, value);
217
+ process.env[provider.environmentVariable] = value;
218
+ this.injected.add(provider.id);
219
+ await this.remember(provider.id, value);
220
+ return value;
221
+ } catch {
222
+ this.storageProblems.set(
223
+ provider.id,
224
+ 'Secure credential storage is temporarily unavailable.',
225
+ );
226
+ return undefined;
227
+ }
228
+ }
229
+
230
+ private async remember(provider: ProviderCredentialId, key: string): Promise<void> {
231
+ if (!(await this.systemBacked())) return;
232
+ await this.markers.write(provider, {
233
+ maskedKey: maskedKey(key),
234
+ connectedAt: new Date().toISOString(),
235
+ });
236
+ }
237
+
238
+ /** Trusted Node-only value for a provider process launch. Never expose this
239
+ * through an editor HTTP response or project-owned file. */
240
+ credential(providerId: ProviderCredentialId): Promise<string | undefined> {
241
+ return this.ensure(providerId);
242
+ }
243
+
244
+ async snapshot(): Promise<ProviderCredentialStatus[]> {
245
+ const markers = await this.markers.read();
246
+ let persistence: CredentialPersistence = 'session';
247
+ try {
248
+ persistence = await this.store.persistence();
249
+ } catch {
250
+ // The per-provider problem below remains visible. Session is the only
251
+ // persistence level it is safe to claim when the backend cannot answer.
252
+ }
253
+ return PROVIDER_CREDENTIALS.map((provider) => {
254
+ const environment = this.environment.get(provider.id);
255
+ const key = environment ?? this.stored.get(provider.id);
256
+ const masked = key !== undefined ? maskedKey(key) : markers[provider.id]?.maskedKey;
257
+ const configured = masked !== undefined;
258
+ return {
259
+ provider: provider.id,
260
+ label: provider.label,
261
+ environmentVariable: provider.environmentVariable,
262
+ configured,
263
+ source: environment ? 'environment' : configured ? persistence : 'none',
264
+ editable: environment === undefined,
265
+ persistence,
266
+ ...(masked ? { maskedKey: masked } : {}),
267
+ ...(this.storageProblems.get(provider.id)
268
+ ? { problem: this.storageProblems.get(provider.id) }
269
+ : {}),
270
+ } satisfies ProviderCredentialStatus;
271
+ });
272
+ }
273
+
274
+ async set(providerId: ProviderCredentialId, value: string): Promise<ProviderCredentialStatus[]> {
275
+ const provider = definition(providerId);
276
+ if (this.environment.has(provider.id)) {
277
+ throw new Error(
278
+ `${provider.label} is controlled by ${provider.environmentVariable}. Remove that environment override and restart the editor before changing it here.`,
279
+ );
280
+ }
281
+ const key = normalizeKey(value);
282
+ await this.store.write(provider.id, key);
283
+ this.storageProblems.delete(provider.id);
284
+ this.stored.set(provider.id, key);
285
+ process.env[provider.environmentVariable] = key;
286
+ this.injected.add(provider.id);
287
+ this.ensured.set(provider.id, Promise.resolve(key));
288
+ await this.remember(provider.id, key);
289
+ return this.snapshot();
290
+ }
291
+
292
+ async delete(providerId: ProviderCredentialId): Promise<ProviderCredentialStatus[]> {
293
+ const provider = definition(providerId);
294
+ if (this.environment.has(provider.id)) {
295
+ throw new Error(
296
+ `${provider.label} is controlled by ${provider.environmentVariable}. Remove that environment override and restart the editor to disable it.`,
297
+ );
298
+ }
299
+ await this.store.delete(provider.id);
300
+ this.storageProblems.delete(provider.id);
301
+ this.stored.delete(provider.id);
302
+ this.ensured.set(provider.id, Promise.resolve(undefined));
303
+ if (this.injected.delete(provider.id)) delete process.env[provider.environmentVariable];
304
+ await this.markers.write(provider.id, null);
305
+ return this.snapshot();
306
+ }
307
+
308
+ async test(providerId: ProviderCredentialId): Promise<ProviderCredentialTestResult> {
309
+ const provider = definition(providerId);
310
+ const key = await this.ensure(provider.id);
311
+ if (!key) throw new Error(`${provider.label} is not configured.`);
312
+ let response: Response;
313
+ try {
314
+ response = await provider.test(key, AbortSignal.timeout(15_000));
315
+ } catch {
316
+ throw new Error(`Could not reach ${provider.label}.`);
317
+ }
318
+ if (!response.ok) {
319
+ throw new Error(`${provider.label} rejected the credential (${response.status}).`);
320
+ }
321
+ if (provider.id === 'tripo') {
322
+ const body = (await response.json().catch(() => null)) as { code?: unknown } | null;
323
+ if (body?.code !== 0) throw new Error(`${provider.label} rejected the credential.`);
324
+ }
325
+ return {
326
+ provider: provider.id,
327
+ ok: true,
328
+ testedAt: new Date().toISOString(),
329
+ };
330
+ }
331
+ }