@volter/sdk 0.0.0-stage → 0.5.204
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.
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1168 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +329 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +669 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The FAILURE CHANNEL for declared-asset-pack materialization (D-AP4):
|
|
3
|
+
* *"Failure = loud degradation, not fabrication. ... the missing asset is
|
|
4
|
+
* reported in the editor console + status surface with a retry affordance, and
|
|
5
|
+
* dependent features degrade honestly."*
|
|
6
|
+
*
|
|
7
|
+
* `materializeDeclaredAssetPacks` already fails closed per entry — it never
|
|
8
|
+
* writes placeholder bytes and never blocks the other entries — but it only
|
|
9
|
+
* RETURNS a `failed` array, and an array with no reader is the hazard: a seed
|
|
10
|
+
* that lands without its clips would look like a working editor with a
|
|
11
|
+
* mysteriously dead animation, which is the worst possible outcome and
|
|
12
|
+
* precisely what the anti-shim rule forbids.
|
|
13
|
+
*
|
|
14
|
+
* This module is that reader, and it is deliberately TWO channels, because
|
|
15
|
+
* neither alone is enough — D-AP4's own words, *"reported in the editor
|
|
16
|
+
* console + status surface with a retry affordance"*:
|
|
17
|
+
*
|
|
18
|
+
* 1. `editorConsole.error` — one line per failed entry, subsystem `assets`,
|
|
19
|
+
* naming the library key, the destination path, the reason, and what
|
|
20
|
+
* degrades.
|
|
21
|
+
* 2. A module-level report slot the status bar's `asset-materialization`
|
|
22
|
+
* contribution reads (`../components/status-contributions.tsx`),
|
|
23
|
+
* carrying the RETRY affordance. Retry re-runs materialization against
|
|
24
|
+
* the active backend, which is safe and cheap by construction: the
|
|
25
|
+
* materializer skips every entry already in the ledger, so a retry only
|
|
26
|
+
* refetches what is still missing.
|
|
27
|
+
*
|
|
28
|
+
* That status item used to be a red banner across the top of the shell. The
|
|
29
|
+
* editor has ONE error home — console line, bottom-left status item, the
|
|
30
|
+
* Console utility behind it — and a second one only taught users two places
|
|
31
|
+
* to look, so the banner is gone.
|
|
32
|
+
*
|
|
33
|
+
* Same plain module-singleton + own-`subscribe` shape as
|
|
34
|
+
* `../authoring/mount-failure-report.ts`.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import { editorConsole } from '@volter/sdk/kit/editor-console';
|
|
38
|
+
import type { StorageBackend } from '@volter/sdk/kit/storage-types';
|
|
39
|
+
import type { AssetPackMaterializationResult } from './hosted-asset-materialization';
|
|
40
|
+
|
|
41
|
+
/** One declared pack entry that did not materialize — the exact fields both
|
|
42
|
+
* channels show. Flattened out of `AssetPackMaterializationFailure` so the
|
|
43
|
+
* banner never has to know the materializer's own types. */
|
|
44
|
+
export interface AssetMaterializationFailure {
|
|
45
|
+
/** Library key, `source:id` (e.g. `local:a7c5288306d9e98cb7dbdbd2`). */
|
|
46
|
+
readonly key: string;
|
|
47
|
+
/** Project-relative destination the bytes were meant to land at. */
|
|
48
|
+
readonly dest: string;
|
|
49
|
+
/** Declaring pack name from `asset-manifest.json`. */
|
|
50
|
+
readonly pack: string;
|
|
51
|
+
/** The materializer's own reason string — never fabricated, never softened. */
|
|
52
|
+
readonly reason: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let _failures: readonly AssetMaterializationFailure[] = [];
|
|
56
|
+
const _listeners = new Set<() => void>();
|
|
57
|
+
|
|
58
|
+
/** `useSyncExternalStore`-compatible subscribe for the banner. */
|
|
59
|
+
export function subscribeToAssetMaterializationFailures(callback: () => void): () => void {
|
|
60
|
+
_listeners.add(callback);
|
|
61
|
+
return () => _listeners.delete(callback);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Every declared entry that failed to materialize, in declaration order. */
|
|
65
|
+
export function getAssetMaterializationFailures(): readonly AssetMaterializationFailure[] {
|
|
66
|
+
return _failures;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Clear the slot (the banner's dismiss). Does not retry. */
|
|
70
|
+
export function clearAssetMaterializationFailures(): void {
|
|
71
|
+
_failures = [];
|
|
72
|
+
notify();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function notify(): void {
|
|
76
|
+
for (const listener of _listeners) listener();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The message BOTH channels use, so the console line and the banner row can
|
|
81
|
+
* never drift apart. Names the key, the destination and the reason, then says
|
|
82
|
+
* what degrades — a reader who sees only this line knows what is broken and
|
|
83
|
+
* what it costs them.
|
|
84
|
+
*/
|
|
85
|
+
export function formatAssetMaterializationFailure(failure: AssetMaterializationFailure): string {
|
|
86
|
+
return (
|
|
87
|
+
`Starter asset "${failure.key}" (pack "${failure.pack}") did not materialize into ` +
|
|
88
|
+
`${failure.dest}: ${failure.reason} Nothing was written for it — features that read ` +
|
|
89
|
+
'that file degrade (a missing clips GLB leaves the character standing without ' +
|
|
90
|
+
'locomotion clips). Use Retry once the cause is fixed.'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Report a materialization result through both channels. Called by every
|
|
96
|
+
* production materialization site (today: `../storage/seed.ts`'s
|
|
97
|
+
* `seedIfEmpty`) so no caller can forget to read `failed`.
|
|
98
|
+
*
|
|
99
|
+
* A result with no failures CLEARS the slot: that is what makes a successful
|
|
100
|
+
* retry dismiss its own banner.
|
|
101
|
+
*/
|
|
102
|
+
export function reportAssetMaterialization(result: AssetPackMaterializationResult): void {
|
|
103
|
+
const failures = result.failed.map((failure) => ({
|
|
104
|
+
key: failure.entry.key,
|
|
105
|
+
dest: failure.entry.dest,
|
|
106
|
+
pack: failure.entry.pack,
|
|
107
|
+
reason: failure.reason,
|
|
108
|
+
}));
|
|
109
|
+
for (const failure of failures) {
|
|
110
|
+
editorConsole.error(formatAssetMaterializationFailure(failure), 'assets');
|
|
111
|
+
}
|
|
112
|
+
_failures = failures;
|
|
113
|
+
notify();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Re-run materialization against `backend` and re-report. Retry-safe by
|
|
118
|
+
* construction (the materializer skips ledger-present entries), so this
|
|
119
|
+
* refetches only what is still missing.
|
|
120
|
+
*
|
|
121
|
+
* A THROW here is the manifest itself being unreadable/invalid — not a
|
|
122
|
+
* per-entry failure — so it degrades through the console too rather than
|
|
123
|
+
* becoming an unhandled rejection in a click handler.
|
|
124
|
+
*/
|
|
125
|
+
export async function retryAssetMaterialization(backend: StorageBackend): Promise<void> {
|
|
126
|
+
try {
|
|
127
|
+
// Lazy for the same reason the seed's call is: the materializer is the
|
|
128
|
+
// heaviest thing this report knows, and only the retry needs it.
|
|
129
|
+
const { materializeDeclaredAssetPacks } = await import('./hosted-asset-materialization');
|
|
130
|
+
const result = await materializeDeclaredAssetPacks(backend);
|
|
131
|
+
reportAssetMaterialization(result);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
editorConsole.error(
|
|
134
|
+
`Retrying asset materialization failed before any entry was attempted: ${
|
|
135
|
+
error instanceof Error ? error.message : String(error)
|
|
136
|
+
}`,
|
|
137
|
+
'assets',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset packs — `asset-manifest.json` (D-AP1) and the pure sync/check planner
|
|
3
|
+
* behind `npm run asset-packs:sync` (D-AP2)..
|
|
4
|
+
*
|
|
5
|
+
* A PACK is a named list of `{ key, dest }`: library asset keys and the
|
|
6
|
+
* project-relative paths their bytes are copied to. It is an INPUT TO
|
|
7
|
+
* MATERIALIZATION, never a runtime concept — nothing in a running game or a
|
|
8
|
+
* scaffolded project resolves a pack. It is deliberately NOT a `volter.project.json`
|
|
9
|
+
* field: the manifest says what a project IS, a pack says how its reference
|
|
10
|
+
* material was PRODUCED.
|
|
11
|
+
*
|
|
12
|
+
* The file lives beside `volter.project.json` in `packages/game-editor/template/` and each
|
|
13
|
+
* `examples/<id>/`. A scaffolded user project does not carry it; its record is
|
|
14
|
+
* the ledger (`asset-ledger.ts`, D-AP3).
|
|
15
|
+
*
|
|
16
|
+
* The binaries stay COMMITTED — creating a project must work offline and CI must stay
|
|
17
|
+
* hermetic (D-AP2/D-AP6). What the pack adds is that they are now GENERATED: the
|
|
18
|
+
* library is the origin, and `--check` re-verifies the committed bytes against
|
|
19
|
+
* the library's own `sourceHash` without touching the network.
|
|
20
|
+
*
|
|
21
|
+
* On KEYS: a key is `source:id`, the same identity as `onlineAssetKey`. For the
|
|
22
|
+
* SSD/cloud catalog the source name is `local`, and the id is a VARIANT id
|
|
23
|
+
* (`local:a7c5288306d9e98cb7dbdbd2`), not a family id — a family has several
|
|
24
|
+
* format variants, so only the variant pins bytes. `findLocalAsset` /
|
|
25
|
+
* `findCloudAsset` both resolve variant ids, so this is an ordinary library key.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
|
|
30
|
+
export const AssetPackEntrySchema = z
|
|
31
|
+
.object({
|
|
32
|
+
/** `source:id` — the library's identity for the asset (variant-precise). */
|
|
33
|
+
key: z.string().regex(/^[^:]+:.+$/, 'An asset key must be "source:id"'),
|
|
34
|
+
/** Project-relative destination for the asset's main file. */
|
|
35
|
+
dest: z.string().min(1),
|
|
36
|
+
/**
|
|
37
|
+
* The PIN: sha256 of the bytes this entry declares, bare lowercase hex.
|
|
38
|
+
*
|
|
39
|
+
* Required, and the reason is trust-on-first-use. A materializer that
|
|
40
|
+
* learns the expected digest from the same response that delivers the
|
|
41
|
+
* bytes has authenticated nothing on the first fetch — a bad or moved
|
|
42
|
+
* answer is self-consistent, gets written, and its digest becomes the
|
|
43
|
+
* project's permanent `sourceHash` in the ledger. A pin is a CHECKED-IN
|
|
44
|
+
* fact reviewed in a diff, so the first fetch is verified like every
|
|
45
|
+
* later one. `asset-packs:sync --check` cross-checks it against
|
|
46
|
+
* `catalog/cloud/manifest.json` (hermetic — both sides are repo files),
|
|
47
|
+
* and `asset-pack-manifest.test.ts` asserts no in-repo pin was invented.
|
|
48
|
+
*/
|
|
49
|
+
sha256: z
|
|
50
|
+
.string()
|
|
51
|
+
.regex(
|
|
52
|
+
/^[a-f0-9]{64}$/,
|
|
53
|
+
'A pack entry must pin the sha256 of its bytes as 64 lowercase hex digits',
|
|
54
|
+
),
|
|
55
|
+
})
|
|
56
|
+
.strict();
|
|
57
|
+
|
|
58
|
+
export const AssetPackManifestSchema = z
|
|
59
|
+
.object({
|
|
60
|
+
packs: z.record(z.string().min(1), z.array(AssetPackEntrySchema)),
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
|
|
64
|
+
export type AssetPackEntry = z.infer<typeof AssetPackEntrySchema>;
|
|
65
|
+
export type AssetPackManifest = z.infer<typeof AssetPackManifestSchema>;
|
|
66
|
+
|
|
67
|
+
/** Parse an `asset-manifest.json`. Throws loudly — a half-read pack
|
|
68
|
+
* declaration would silently stop guarding the files it dropped. */
|
|
69
|
+
export function parseAssetPackManifest(input: unknown): AssetPackManifest {
|
|
70
|
+
return AssetPackManifestSchema.parse(input);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface FlattenedPackEntry extends AssetPackEntry {
|
|
74
|
+
readonly pack: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Flatten every pack to a single entry list, rejecting two packs that claim
|
|
78
|
+
* the same destination (whichever ran last would silently win). */
|
|
79
|
+
export function flattenAssetPacks(manifest: AssetPackManifest): FlattenedPackEntry[] {
|
|
80
|
+
const flattened: FlattenedPackEntry[] = [];
|
|
81
|
+
const byDest = new Map<string, string>();
|
|
82
|
+
for (const [pack, entries] of Object.entries(manifest.packs)) {
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
const owner = byDest.get(entry.dest);
|
|
85
|
+
if (owner !== undefined) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Two packs declare the same destination "${entry.dest}": "${owner}" and "${pack}".`,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
byDest.set(entry.dest, pack);
|
|
91
|
+
flattened.push({ ...entry, pack });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return flattened;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Build the library index `planAssetPackSync` needs from a parsed
|
|
99
|
+
* `catalog/cloud/manifest.json`.
|
|
100
|
+
*
|
|
101
|
+
* That file has TWO shapes on disk and both are live. v1 is a flat `assets`
|
|
102
|
+
* array; v2 is the canonical `families` graph whose `variants` are the assets
|
|
103
|
+
* (a family holds several format variants, and only a variant pins bytes).
|
|
104
|
+
* The checked-in snapshot is still v1 while `scripts/cloud-asset-library.ts`
|
|
105
|
+
* already emits v2, so the FIRST regeneration of that file — which ingesting
|
|
106
|
+
* anything into the library requires — flips the shape under this reader.
|
|
107
|
+
* `packages/cloud-asset-library/src/worker.ts` accepts both for exactly this
|
|
108
|
+
* reason; so does this. A reader that understood only the shape it happened to
|
|
109
|
+
* be born with would turn `asset-packs:sync --check` red on a correct tree.
|
|
110
|
+
*
|
|
111
|
+
* Throws on anything else rather than returning an empty index: an index that
|
|
112
|
+
* silently came back empty would report every declared asset as an unknown key.
|
|
113
|
+
*/
|
|
114
|
+
export function libraryIndexFromCloudManifest(
|
|
115
|
+
manifest: unknown,
|
|
116
|
+
source: string,
|
|
117
|
+
): Map<string, LibraryAsset> {
|
|
118
|
+
const root = manifest as {
|
|
119
|
+
version?: unknown;
|
|
120
|
+
assets?: unknown;
|
|
121
|
+
families?: unknown;
|
|
122
|
+
} | null;
|
|
123
|
+
const flat = Array.isArray(root?.families)
|
|
124
|
+
? (root.families as ManifestFamily[]).flatMap((family) =>
|
|
125
|
+
(family.variants ?? []).map((variant) => ({ ...family, ...variant })),
|
|
126
|
+
)
|
|
127
|
+
: Array.isArray(root?.assets)
|
|
128
|
+
? (root.assets as ManifestAsset[])
|
|
129
|
+
: null;
|
|
130
|
+
if (!flat) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
'A cloud asset manifest must have a v1 "assets" array or a v2 "families" array; ' +
|
|
133
|
+
`this one has neither (version ${JSON.stringify(root?.version)}).`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const index = new Map<string, LibraryAsset>();
|
|
138
|
+
for (const asset of flat) {
|
|
139
|
+
const file = asset.files?.[0];
|
|
140
|
+
if (!file) continue;
|
|
141
|
+
const key = `${source}:${asset.id}`;
|
|
142
|
+
index.set(key, {
|
|
143
|
+
key,
|
|
144
|
+
name: asset.name,
|
|
145
|
+
license: asset.license,
|
|
146
|
+
sourceSha256: file.main.sha256,
|
|
147
|
+
sizeBytes: file.main.sizeBytes,
|
|
148
|
+
relativePath: file.main.relativePath,
|
|
149
|
+
dependencyCount: file.dependencies.length,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return index;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
interface ManifestObject {
|
|
156
|
+
sha256: string;
|
|
157
|
+
sizeBytes: number;
|
|
158
|
+
relativePath: string;
|
|
159
|
+
}
|
|
160
|
+
interface ManifestAsset {
|
|
161
|
+
id: string;
|
|
162
|
+
name: string;
|
|
163
|
+
license: string;
|
|
164
|
+
files?: { main: ManifestObject; dependencies: ManifestObject[] }[];
|
|
165
|
+
}
|
|
166
|
+
interface ManifestFamily extends Omit<ManifestAsset, 'id' | 'files'> {
|
|
167
|
+
variants?: Omit<ManifestAsset, 'name' | 'license'>[];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** One asset as the LIBRARY describes it — the only source of `sourceSha256`. */
|
|
171
|
+
export interface LibraryAsset {
|
|
172
|
+
readonly key: string;
|
|
173
|
+
readonly name: string;
|
|
174
|
+
readonly license: string;
|
|
175
|
+
readonly sourceSha256: string;
|
|
176
|
+
readonly sizeBytes: number;
|
|
177
|
+
/** The library's own filename for the main file. */
|
|
178
|
+
readonly relativePath: string;
|
|
179
|
+
/** Sibling files the main file needs. See `unsupported-dependencies` below. */
|
|
180
|
+
readonly dependencyCount: number;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export type AssetPackDecision =
|
|
184
|
+
/** Committed bytes are the library's bytes. Nothing to do. */
|
|
185
|
+
| { readonly status: 'match'; readonly entry: FlattenedPackEntry }
|
|
186
|
+
/** Declared but not committed — materialize it. */
|
|
187
|
+
| { readonly status: 'missing'; readonly entry: FlattenedPackEntry; readonly asset: LibraryAsset }
|
|
188
|
+
/** Committed but not the library's bytes — hand-edited, or the library moved. */
|
|
189
|
+
| {
|
|
190
|
+
readonly status: 'stale';
|
|
191
|
+
readonly entry: FlattenedPackEntry;
|
|
192
|
+
readonly asset: LibraryAsset;
|
|
193
|
+
readonly committedSha256: string;
|
|
194
|
+
}
|
|
195
|
+
/** The key names nothing in the library. Never guessed around. */
|
|
196
|
+
| { readonly status: 'unresolved-key'; readonly entry: FlattenedPackEntry }
|
|
197
|
+
/**
|
|
198
|
+
* The declaration's pin and the library index disagree about the asset's
|
|
199
|
+
* bytes. Two independent CHECKED-IN facts contradict each other, so neither
|
|
200
|
+
* can be assumed: copying library bytes would silently overrule a reviewed
|
|
201
|
+
* pin, and trusting the pin would hide a library that moved. A human
|
|
202
|
+
* resolves it; sync never does.
|
|
203
|
+
*/
|
|
204
|
+
| {
|
|
205
|
+
readonly status: 'pin-mismatch';
|
|
206
|
+
readonly entry: FlattenedPackEntry;
|
|
207
|
+
readonly asset: LibraryAsset;
|
|
208
|
+
}
|
|
209
|
+
/** Multi-file assets are not expressible as one `dest`; refuse rather than
|
|
210
|
+
* silently drop the siblings the main file needs. */
|
|
211
|
+
| {
|
|
212
|
+
readonly status: 'unsupported-dependencies';
|
|
213
|
+
readonly entry: FlattenedPackEntry;
|
|
214
|
+
readonly asset: LibraryAsset;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export interface AssetPackSyncInputs {
|
|
218
|
+
/** Library index by `source:id`. */
|
|
219
|
+
readonly library: ReadonlyMap<string, LibraryAsset>;
|
|
220
|
+
/** sha256 of each declared dest as committed, or null when absent. */
|
|
221
|
+
readonly committed: ReadonlyMap<string, string | null>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Decide what each declared entry needs. Pure: the caller supplies the library
|
|
226
|
+
* index and the committed hashes, so this is testable without fs or network.
|
|
227
|
+
*/
|
|
228
|
+
export function planAssetPackSync(
|
|
229
|
+
entries: readonly FlattenedPackEntry[],
|
|
230
|
+
inputs: AssetPackSyncInputs,
|
|
231
|
+
): AssetPackDecision[] {
|
|
232
|
+
return entries.map((entry) => {
|
|
233
|
+
const asset = inputs.library.get(entry.key);
|
|
234
|
+
if (!asset) return { status: 'unresolved-key', entry } as const;
|
|
235
|
+
if (asset.dependencyCount > 0) {
|
|
236
|
+
return { status: 'unsupported-dependencies', entry, asset } as const;
|
|
237
|
+
}
|
|
238
|
+
// The pin is checked BEFORE anything about the committed copy: while the
|
|
239
|
+
// two checked-in facts disagree there is no defensible expected digest to
|
|
240
|
+
// judge the copy against.
|
|
241
|
+
if (entry.sha256 !== asset.sourceSha256) {
|
|
242
|
+
return { status: 'pin-mismatch', entry, asset } as const;
|
|
243
|
+
}
|
|
244
|
+
const committedSha256 = inputs.committed.get(entry.dest) ?? null;
|
|
245
|
+
if (committedSha256 === null) return { status: 'missing', entry, asset } as const;
|
|
246
|
+
return committedSha256 === entry.sha256
|
|
247
|
+
? ({ status: 'match', entry } as const)
|
|
248
|
+
: ({ status: 'stale', entry, asset, committedSha256 } as const);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Decisions `--check` must fail on. A `missing`/`stale` copy means the
|
|
253
|
+
* committed tree no longer matches what the library says it is. */
|
|
254
|
+
export function assetPackCheckFailures(
|
|
255
|
+
decisions: readonly AssetPackDecision[],
|
|
256
|
+
): AssetPackDecision[] {
|
|
257
|
+
return decisions.filter((decision) => decision.status !== 'match');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Decisions sync can NEITHER accept nor repair — it must stop on them.
|
|
262
|
+
*
|
|
263
|
+
* Derived, not hand-listed: anything that is not already correct (`match`) and
|
|
264
|
+
* is not a work item is by definition a refusal. The hand-written version of
|
|
265
|
+
* this list silently omitted `pin-mismatch` the day that status was added, and
|
|
266
|
+
* the consequence was not a missed error but a FABRICATED one — sync would
|
|
267
|
+
* have gone on to record a `sourceHash` for bytes it never fetched or
|
|
268
|
+
* verified, which is exactly what the anti-shim rule forbids.
|
|
269
|
+
*/
|
|
270
|
+
export function assetPackBlockingDecisions(
|
|
271
|
+
decisions: readonly AssetPackDecision[],
|
|
272
|
+
): AssetPackDecision[] {
|
|
273
|
+
const repairable = new Set<AssetPackDecision>(assetPackWorkItems(decisions));
|
|
274
|
+
return decisions.filter((decision) => decision.status !== 'match' && !repairable.has(decision));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Decisions `assets:sync` can fix by copying library bytes in. */
|
|
278
|
+
export function assetPackWorkItems(
|
|
279
|
+
decisions: readonly AssetPackDecision[],
|
|
280
|
+
): Extract<AssetPackDecision, { status: 'missing' | 'stale' }>[] {
|
|
281
|
+
return decisions.flatMap((decision) =>
|
|
282
|
+
decision.status === 'missing' || decision.status === 'stale' ? [decision] : [],
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** One line explaining a decision, for both `--check` failures and sync logs. */
|
|
287
|
+
export function describeAssetPackDecision(decision: AssetPackDecision): string {
|
|
288
|
+
const where = `${decision.entry.dest} (pack "${decision.entry.pack}", key ${decision.entry.key})`;
|
|
289
|
+
switch (decision.status) {
|
|
290
|
+
case 'match':
|
|
291
|
+
return `ok ${where}`;
|
|
292
|
+
case 'missing':
|
|
293
|
+
return `MISSING ${where} — declared but not committed`;
|
|
294
|
+
case 'stale':
|
|
295
|
+
return (
|
|
296
|
+
`STALE ${where} — committed bytes are sha256:${decision.committedSha256.slice(0, 12)}…, ` +
|
|
297
|
+
`the library has sha256:${decision.asset.sourceSha256.slice(0, 12)}… ` +
|
|
298
|
+
'(either the copy was hand-edited or the library moved)'
|
|
299
|
+
);
|
|
300
|
+
case 'unresolved-key':
|
|
301
|
+
return `UNKNOWN ${where} — no such asset in the library index`;
|
|
302
|
+
case 'pin-mismatch':
|
|
303
|
+
return (
|
|
304
|
+
`PIN ${where} — the declaration pins sha256:${decision.entry.sha256.slice(0, 12)}… ` +
|
|
305
|
+
`but the library index says sha256:${decision.asset.sourceSha256.slice(0, 12)}… ` +
|
|
306
|
+
'(re-pin the declaration only after confirming the library moved deliberately; ' +
|
|
307
|
+
'nothing is fetched or copied while these disagree)'
|
|
308
|
+
);
|
|
309
|
+
case 'unsupported-dependencies':
|
|
310
|
+
return (
|
|
311
|
+
`MULTIFILE ${where} — the library asset has ${decision.asset.dependencyCount} ` +
|
|
312
|
+
'dependency file(s); a pack entry declares exactly one destination file'
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** Where a project declares its library asset packs. Lives here, beside the
|
|
318
|
+
* manifest's shape, so a reader of the PATH (the seed) does not carry the
|
|
319
|
+
* materializer (the cloud client, the ledger, its locks). */
|
|
320
|
+
export const ASSET_MANIFEST_PATH = 'asset-manifest.json';
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export type AssetHealthCode =
|
|
4
|
+
| 'healthy'
|
|
5
|
+
| 'source-only'
|
|
6
|
+
| 'missing-file'
|
|
7
|
+
| 'missing-dependency'
|
|
8
|
+
| 'missing-thumbnail'
|
|
9
|
+
| 'unsupported-format'
|
|
10
|
+
| 'invalid-metadata'
|
|
11
|
+
| 'conversion-failed'
|
|
12
|
+
| 'missing-attribution'
|
|
13
|
+
| 'broken-asset-reference';
|
|
14
|
+
|
|
15
|
+
export interface AssetHealth {
|
|
16
|
+
readonly status: 'healthy' | 'warning' | 'error';
|
|
17
|
+
readonly codes: readonly AssetHealthCode[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const AssetFileSchema = z
|
|
21
|
+
.object({
|
|
22
|
+
label: z.string().min(1),
|
|
23
|
+
path: z.string().min(1),
|
|
24
|
+
format: z.string().min(1),
|
|
25
|
+
sizeBytes: z.number().int().nonnegative(),
|
|
26
|
+
dependencies: z.array(z.string().min(1)).optional(),
|
|
27
|
+
sha256: z
|
|
28
|
+
.string()
|
|
29
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
30
|
+
.optional(),
|
|
31
|
+
})
|
|
32
|
+
.strict();
|
|
33
|
+
|
|
34
|
+
export const AssetDeliverySchema = z
|
|
35
|
+
.object({
|
|
36
|
+
id: z.string().min(1),
|
|
37
|
+
kind: z.enum(['local-ssd', 'cloud', 'remote']),
|
|
38
|
+
available: z.boolean(),
|
|
39
|
+
fileIndexes: z.array(z.number().int().nonnegative()).min(1),
|
|
40
|
+
})
|
|
41
|
+
.strict();
|
|
42
|
+
|
|
43
|
+
export const AssetThumbnailSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
path: z.string().min(1),
|
|
46
|
+
state: z.enum(['generated', 'upstream', 'fallback', 'unsupported', 'failed']),
|
|
47
|
+
profileVersion: z.string().min(1),
|
|
48
|
+
sourceHash: z
|
|
49
|
+
.string()
|
|
50
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
51
|
+
.optional(),
|
|
52
|
+
resultHash: z
|
|
53
|
+
.string()
|
|
54
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
55
|
+
.optional(),
|
|
56
|
+
issueCode: z.string().min(1).optional(),
|
|
57
|
+
})
|
|
58
|
+
.strict();
|
|
59
|
+
|
|
60
|
+
export const AssetVariantSchema = z
|
|
61
|
+
.object({
|
|
62
|
+
id: z.string().regex(/^[a-f0-9]{24}$/),
|
|
63
|
+
label: z.string().min(1),
|
|
64
|
+
type: z.enum(['model', 'animation', 'source']),
|
|
65
|
+
files: z.array(AssetFileSchema).min(1),
|
|
66
|
+
deliveries: z.array(AssetDeliverySchema).min(1),
|
|
67
|
+
thumbnail: AssetThumbnailSchema,
|
|
68
|
+
animationCount: z.number().int().nonnegative().optional(),
|
|
69
|
+
clipNames: z.array(z.string()).optional(),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
|
|
73
|
+
export const AssetFamilySchema = z
|
|
74
|
+
.object({
|
|
75
|
+
id: z.string().regex(/^[a-f0-9]{24}$/),
|
|
76
|
+
source: z.string().min(1),
|
|
77
|
+
name: z.string().min(1),
|
|
78
|
+
type: z.enum(['model', 'animation', 'source']),
|
|
79
|
+
categories: z.array(z.string()),
|
|
80
|
+
tags: z.array(z.string()),
|
|
81
|
+
license: z.string().min(1),
|
|
82
|
+
author: z.string().min(1),
|
|
83
|
+
sourceUrl: z.string().url(),
|
|
84
|
+
variants: z.array(AssetVariantSchema).min(1),
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
87
|
+
|
|
88
|
+
export const AssetCatalogEnvelopeSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
version: z.literal(2),
|
|
91
|
+
generatedAt: z.string().datetime(),
|
|
92
|
+
families: z.array(z.unknown()),
|
|
93
|
+
})
|
|
94
|
+
.strict();
|
|
95
|
+
|
|
96
|
+
export type AssetFile = z.infer<typeof AssetFileSchema>;
|
|
97
|
+
export type AssetDelivery = z.infer<typeof AssetDeliverySchema>;
|
|
98
|
+
export type AssetVariant = z.infer<typeof AssetVariantSchema>;
|
|
99
|
+
export type AssetFamily = z.infer<typeof AssetFamilySchema>;
|
|
100
|
+
|
|
101
|
+
export interface AssetCatalogIssue {
|
|
102
|
+
readonly familyIndex: number | null;
|
|
103
|
+
readonly familyId?: string;
|
|
104
|
+
readonly path: readonly (string | number)[];
|
|
105
|
+
readonly message: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface AssetCatalog {
|
|
109
|
+
readonly version: 2;
|
|
110
|
+
readonly generatedAt: string;
|
|
111
|
+
readonly families: readonly AssetFamily[];
|
|
112
|
+
readonly issues: readonly AssetCatalogIssue[];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function parseAssetCatalog(input: unknown): AssetCatalog {
|
|
116
|
+
const envelope = AssetCatalogEnvelopeSchema.parse(input);
|
|
117
|
+
const families: AssetFamily[] = [];
|
|
118
|
+
const issues: AssetCatalogIssue[] = [];
|
|
119
|
+
for (const [familyIndex, candidate] of envelope.families.entries()) {
|
|
120
|
+
const result = AssetFamilySchema.safeParse(candidate);
|
|
121
|
+
if (result.success) {
|
|
122
|
+
families.push(result.data);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const familyId =
|
|
126
|
+
candidate &&
|
|
127
|
+
typeof candidate === 'object' &&
|
|
128
|
+
'id' in candidate &&
|
|
129
|
+
typeof candidate.id === 'string'
|
|
130
|
+
? candidate.id
|
|
131
|
+
: undefined;
|
|
132
|
+
for (const issue of result.error.issues) {
|
|
133
|
+
issues.push({
|
|
134
|
+
familyIndex,
|
|
135
|
+
...(familyId ? { familyId } : {}),
|
|
136
|
+
path: issue.path.map((part) => (typeof part === 'symbol' ? String(part) : part)),
|
|
137
|
+
message: issue.message,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { version: 2, generatedAt: envelope.generatedAt, families, issues };
|
|
142
|
+
}
|