@hraness/slopcamera 3.2.4
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 +21 -0
- package/NOTICE.md +60 -0
- package/PRIVACY.md +46 -0
- package/README.md +311 -0
- package/SECURITY.md +21 -0
- package/apps/desktop/README.md +966 -0
- package/apps/desktop/analysis/protocol.ts +223 -0
- package/apps/desktop/application/capability-binding.ts +594 -0
- package/apps/desktop/application/context.ts +97 -0
- package/apps/desktop/application/creative-iteration.ts +1385 -0
- package/apps/desktop/application/default-registry.ts +146 -0
- package/apps/desktop/application/directing-contract.ts +218 -0
- package/apps/desktop/application/directing-plan.ts +178 -0
- package/apps/desktop/application/errors.ts +18 -0
- package/apps/desktop/application/gateway-port.ts +867 -0
- package/apps/desktop/application/html-overlay-browser-runtime.ts +687 -0
- package/apps/desktop/application/html-overlay-integrity.ts +337 -0
- package/apps/desktop/application/html-overlay-renderer.ts +45 -0
- package/apps/desktop/application/index.ts +13 -0
- package/apps/desktop/application/operation-completion-checkpoint.ts +333 -0
- package/apps/desktop/application/operation-effects.ts +94 -0
- package/apps/desktop/application/operation.ts +224 -0
- package/apps/desktop/application/operations/analysis/faces.ts +244 -0
- package/apps/desktop/application/operations/analysis/music.ts +248 -0
- package/apps/desktop/application/operations/analysis/project-auto-zooms.ts +302 -0
- package/apps/desktop/application/operations/analysis/project-inactivity.ts +381 -0
- package/apps/desktop/application/operations/analysis/scenes.ts +272 -0
- package/apps/desktop/application/operations/analysis/shared.ts +202 -0
- package/apps/desktop/application/operations/derive/edit-batch.ts +967 -0
- package/apps/desktop/application/operations/derive/follow-faces.ts +454 -0
- package/apps/desktop/application/operations/edit/bind-candidate-revision.ts +91 -0
- package/apps/desktop/application/operations/edit/create-candidate-revision.ts +377 -0
- package/apps/desktop/application/operations/edit/create-revision.ts +255 -0
- package/apps/desktop/application/operations/edit/freeze-revision.ts +182 -0
- package/apps/desktop/application/operations/gateway/image.ts +41 -0
- package/apps/desktop/application/operations/gateway/index.ts +17 -0
- package/apps/desktop/application/operations/gateway/shared.ts +122 -0
- package/apps/desktop/application/operations/gateway/speech.ts +41 -0
- package/apps/desktop/application/operations/gateway/transcription.ts +42 -0
- package/apps/desktop/application/operations/gateway/video.ts +41 -0
- package/apps/desktop/application/operations/index.ts +31 -0
- package/apps/desktop/application/operations/iteration/create-candidate.ts +240 -0
- package/apps/desktop/application/operations/iteration/create-matrix.ts +117 -0
- package/apps/desktop/application/operations/iteration/select.ts +155 -0
- package/apps/desktop/application/operations/iteration/shared.ts +250 -0
- package/apps/desktop/application/operations/media/audio-effects.ts +376 -0
- package/apps/desktop/application/operations/media/binding.ts +79 -0
- package/apps/desktop/application/operations/media/capabilities.ts +112 -0
- package/apps/desktop/application/operations/media/color-grade.ts +343 -0
- package/apps/desktop/application/operations/media/html-overlay.ts +802 -0
- package/apps/desktop/application/operations/media/index.ts +8 -0
- package/apps/desktop/application/operations/media/ingest.ts +303 -0
- package/apps/desktop/application/operations/media/overlay.ts +729 -0
- package/apps/desktop/application/operations/media/shared.ts +845 -0
- package/apps/desktop/application/operations/media/transform-platform.ts +120 -0
- package/apps/desktop/application/operations/project/commit-edits.ts +2054 -0
- package/apps/desktop/application/operations/project/promote-selection.ts +495 -0
- package/apps/desktop/application/operations/project/snapshot.ts +95 -0
- package/apps/desktop/application/operations/recording/index.ts +5 -0
- package/apps/desktop/application/operations/recording/pause.ts +34 -0
- package/apps/desktop/application/operations/recording/resume.ts +34 -0
- package/apps/desktop/application/operations/recording/shared.ts +199 -0
- package/apps/desktop/application/operations/recording/start.ts +169 -0
- package/apps/desktop/application/operations/recording/stop.ts +34 -0
- package/apps/desktop/application/operations/render/bind-candidate-output.ts +324 -0
- package/apps/desktop/application/operations/render/materialize-selection.ts +322 -0
- package/apps/desktop/application/operations/render/project-caption-plan.ts +287 -0
- package/apps/desktop/application/operations/render/project-plan.ts +939 -0
- package/apps/desktop/application/operations/render/project-spatial-receipt.ts +70 -0
- package/apps/desktop/application/operations/render/project.ts +1922 -0
- package/apps/desktop/application/operations/shared.ts +67 -0
- package/apps/desktop/application/operations/slopcamera-portable.ts +1188 -0
- package/apps/desktop/application/operations/slopcamera-visuals.ts +784 -0
- package/apps/desktop/application/operations/spatial-project.ts +209 -0
- package/apps/desktop/application/operations/spatial-render.ts +415 -0
- package/apps/desktop/application/operations/spatial-scene.ts +97 -0
- package/apps/desktop/application/operations/studio.ts +143 -0
- package/apps/desktop/application/output-publication-lease.ts +163 -0
- package/apps/desktop/application/project-publication-lease.ts +233 -0
- package/apps/desktop/application/project-store.ts +196 -0
- package/apps/desktop/application/receipts.ts +533 -0
- package/apps/desktop/application/registry.ts +182 -0
- package/apps/desktop/application/spatial-assets.ts +675 -0
- package/apps/desktop/application/spatial-compositor-cadence.ts +23 -0
- package/apps/desktop/application/spatial-project-authority.ts +35 -0
- package/apps/desktop/application/spatial-project-lease.ts +126 -0
- package/apps/desktop/application/spatial-project-render-preparation.ts +225 -0
- package/apps/desktop/application/spatial-project-store.ts +286 -0
- package/apps/desktop/application/spatial-render-projection.ts +201 -0
- package/apps/desktop/application/spatial-render.ts +677 -0
- package/apps/desktop/application/spatial-spz.ts +44 -0
- package/apps/desktop/application/spatial-world-import.ts +135 -0
- package/apps/desktop/application/spatial-world-provenance.ts +46 -0
- package/apps/desktop/application/studio-port.ts +58 -0
- package/apps/desktop/application/verified-receipt-reconciliation.ts +1574 -0
- package/apps/desktop/capture/protocol.ts +689 -0
- package/apps/desktop/cli/analyzer.ts +406 -0
- package/apps/desktop/cli/args.ts +3181 -0
- package/apps/desktop/cli/asset-ingest.ts +747 -0
- package/apps/desktop/cli/atomic-render-effects.ts +210 -0
- package/apps/desktop/cli/atomic-render-platform.ts +205 -0
- package/apps/desktop/cli/atomic-render.ts +50 -0
- package/apps/desktop/cli/audio-analysis.ts +252 -0
- package/apps/desktop/cli/bounded-map.ts +39 -0
- package/apps/desktop/cli/bundle-service.ts +256 -0
- package/apps/desktop/cli/capabilities.ts +212 -0
- package/apps/desktop/cli/capture-bundle.ts +1117 -0
- package/apps/desktop/cli/command-host-resources.ts +251 -0
- package/apps/desktop/cli/commands.ts +6836 -0
- package/apps/desktop/cli/directing-blob.ts +291 -0
- package/apps/desktop/cli/directing-media.ts +517 -0
- package/apps/desktop/cli/directing-quote.ts +89 -0
- package/apps/desktop/cli/directing-service.ts +288 -0
- package/apps/desktop/cli/emoji-assets.ts +538 -0
- package/apps/desktop/cli/errors.ts +29 -0
- package/apps/desktop/cli/face-analysis-service.ts +940 -0
- package/apps/desktop/cli/filter-script.ts +76 -0
- package/apps/desktop/cli/gateway-application-port.ts +1142 -0
- package/apps/desktop/cli/gateway-credential.ts +81 -0
- package/apps/desktop/cli/gateway-media-artifacts.ts +723 -0
- package/apps/desktop/cli/gateway-media-catalog.ts +922 -0
- package/apps/desktop/cli/gateway-media-service.ts +3106 -0
- package/apps/desktop/cli/gateway-media-signature.ts +122 -0
- package/apps/desktop/cli/gateway-provider-options.ts +562 -0
- package/apps/desktop/cli/gateway-scene-provider.ts +391 -0
- package/apps/desktop/cli/help.ts +501 -0
- package/apps/desktop/cli/html-overlay-gpu.ts +97 -0
- package/apps/desktop/cli/html-overlay-renderer.ts +2478 -0
- package/apps/desktop/cli/io.ts +290 -0
- package/apps/desktop/cli/main.ts +123 -0
- package/apps/desktop/cli/media-effects-service.ts +885 -0
- package/apps/desktop/cli/media-ingest-model.ts +364 -0
- package/apps/desktop/cli/media-ingest-platform.ts +227 -0
- package/apps/desktop/cli/media-ingest-program.ts +200 -0
- package/apps/desktop/cli/media-ingest.ts +30 -0
- package/apps/desktop/cli/music-analysis-service.ts +434 -0
- package/apps/desktop/cli/mutation-lock.ts +530 -0
- package/apps/desktop/cli/native-assets.d.ts +12 -0
- package/apps/desktop/cli/native-media-runtime.macos.ts +7 -0
- package/apps/desktop/cli/overlay-playback.ts +177 -0
- package/apps/desktop/cli/paths.ts +265 -0
- package/apps/desktop/cli/portable-surface.ts +242 -0
- package/apps/desktop/cli/project-camera-receipt.ts +112 -0
- package/apps/desktop/cli/project-face-camera.ts +394 -0
- package/apps/desktop/cli/project-inactivity-service.ts +552 -0
- package/apps/desktop/cli/project-media-integrity.ts +121 -0
- package/apps/desktop/cli/project-renderer.ts +1526 -0
- package/apps/desktop/cli/project-service.ts +519 -0
- package/apps/desktop/cli/project-state-transaction.ts +520 -0
- package/apps/desktop/cli/query-limits.ts +1 -0
- package/apps/desktop/cli/recording-controller.ts +1567 -0
- package/apps/desktop/cli/recording-daemon.ts +931 -0
- package/apps/desktop/cli/recording-ref.ts +56 -0
- package/apps/desktop/cli/renamed-environment.ts +6 -0
- package/apps/desktop/cli/renderer.ts +1439 -0
- package/apps/desktop/cli/run-cli-test-helper.ts +60 -0
- package/apps/desktop/cli/scene-analysis-service.ts +879 -0
- package/apps/desktop/cli/spatial-compositor-verifier.ts +213 -0
- package/apps/desktop/cli/spatial-project-service.ts +90 -0
- package/apps/desktop/cli/spatial-scene-service.ts +105 -0
- package/apps/desktop/cli/spatial-world-service.ts +39 -0
- package/apps/desktop/cli/speech-analysis-service.ts +682 -0
- package/apps/desktop/cli/studio-assemble.ts +58 -0
- package/apps/desktop/cli/studio-command.ts +60 -0
- package/apps/desktop/cli/studio-custody.ts +60 -0
- package/apps/desktop/cli/studio-encode.ts +216 -0
- package/apps/desktop/cli/studio-exr.ts +52 -0
- package/apps/desktop/cli/studio-files.ts +179 -0
- package/apps/desktop/cli/studio-output-validation.ts +162 -0
- package/apps/desktop/cli/studio-process.ts +145 -0
- package/apps/desktop/cli/studio-runtime.ts +77 -0
- package/apps/desktop/cli/studio-scaffold.ts +70 -0
- package/apps/desktop/cli/studio-service.ts +301 -0
- package/apps/desktop/cli/studio-spatial-asset.ts +248 -0
- package/apps/desktop/cli/studio-template-names.ts +3 -0
- package/apps/desktop/cli/studio-workflow.ts +19 -0
- package/apps/desktop/cli/time.ts +25 -0
- package/apps/desktop/cli/workflow-code.ts +584 -0
- package/apps/desktop/cli/workflow-runs.ts +576 -0
- package/apps/desktop/code/advanced.ts +139 -0
- package/apps/desktop/code/application-node-planner.ts +1288 -0
- package/apps/desktop/code/compiler.ts +329 -0
- package/apps/desktop/code/contracts.ts +13 -0
- package/apps/desktop/code/creative-recipes.ts +94 -0
- package/apps/desktop/code/define-workflow.ts +115 -0
- package/apps/desktop/code/editing.ts +284 -0
- package/apps/desktop/code/file-candidate-provenance.ts +420 -0
- package/apps/desktop/code/file-candidate.ts +69 -0
- package/apps/desktop/code/graph-builder.ts +10 -0
- package/apps/desktop/code/host-resource-policy.ts +55 -0
- package/apps/desktop/code/plan-contracts.ts +159 -0
- package/apps/desktop/code/planning.ts +361 -0
- package/apps/desktop/code/public.ts +134 -0
- package/apps/desktop/code/reference-projection.ts +62 -0
- package/apps/desktop/code/run-contracts.ts +466 -0
- package/apps/desktop/code/run-store.ts +2478 -0
- package/apps/desktop/code/runtime-identity.ts +328 -0
- package/apps/desktop/code/scheduler.ts +3067 -0
- package/apps/desktop/code/semantic-builder.ts +1436 -0
- package/apps/desktop/code/source-bundle.ts +1641 -0
- package/apps/desktop/code/source-typecheck.ts +211 -0
- package/apps/desktop/code/testing.ts +79 -0
- package/apps/desktop/code/worker-client.ts +1675 -0
- package/apps/desktop/code/worker-effects.ts +141 -0
- package/apps/desktop/code/worker-entry.ts +435 -0
- package/apps/desktop/code/worker-lease-guardian.ts +179 -0
- package/apps/desktop/code/worker-process-identity.ts +484 -0
- package/apps/desktop/code/worker-protocol.ts +211 -0
- package/apps/desktop/code/workflow-effects.ts +132 -0
- package/apps/desktop/contracts/analysis.ts +949 -0
- package/apps/desktop/contracts/edit.ts +576 -0
- package/apps/desktop/contracts/index.ts +9 -0
- package/apps/desktop/contracts/media-effects.ts +139 -0
- package/apps/desktop/contracts/project-render.ts +644 -0
- package/apps/desktop/contracts/project.ts +740 -0
- package/apps/desktop/contracts/recording.ts +1434 -0
- package/apps/desktop/contracts/render.ts +334 -0
- package/apps/desktop/contracts/runtime.ts +155 -0
- package/apps/desktop/contracts/spatial-compositor.ts +58 -0
- package/apps/desktop/contracts/spatial-project.ts +159 -0
- package/apps/desktop/contracts/spatial-world.ts +48 -0
- package/apps/desktop/contracts/video-effects.ts +120 -0
- package/apps/desktop/core/alignment-apply.ts +400 -0
- package/apps/desktop/core/audio-alignment.ts +466 -0
- package/apps/desktop/core/auto-zoom.ts +209 -0
- package/apps/desktop/core/canonical-json.ts +14 -0
- package/apps/desktop/core/emoji.ts +210 -0
- package/apps/desktop/core/events.ts +409 -0
- package/apps/desktop/core/face-framing.ts +533 -0
- package/apps/desktop/core/face-tracks.ts +326 -0
- package/apps/desktop/core/inactivity.ts +137 -0
- package/apps/desktop/core/index.ts +30 -0
- package/apps/desktop/core/intervals.ts +123 -0
- package/apps/desktop/core/montage.ts +236 -0
- package/apps/desktop/core/music-analysis.ts +518 -0
- package/apps/desktop/core/plan.ts +244 -0
- package/apps/desktop/core/project-auto-zoom.ts +75 -0
- package/apps/desktop/core/project-camera-spatial.ts +676 -0
- package/apps/desktop/core/project-camera.ts +403 -0
- package/apps/desktop/core/project-captions.ts +888 -0
- package/apps/desktop/core/project-inactivity.ts +125 -0
- package/apps/desktop/core/project-metadata.ts +927 -0
- package/apps/desktop/core/project-plan.ts +375 -0
- package/apps/desktop/core/project-render-plan.ts +303 -0
- package/apps/desktop/core/project-time.ts +469 -0
- package/apps/desktop/core/render-plan.ts +442 -0
- package/apps/desktop/core/scene-cache.ts +174 -0
- package/apps/desktop/core/scene-sampling.ts +448 -0
- package/apps/desktop/core/spatial-compositor.ts +22 -0
- package/apps/desktop/core/spatial-durability.ts +99 -0
- package/apps/desktop/core/spatial-project.ts +169 -0
- package/apps/desktop/core/spatial-shot-clock.ts +32 -0
- package/apps/desktop/core/speech-analysis.ts +333 -0
- package/apps/desktop/core/storage.ts +970 -0
- package/apps/desktop/core/time-map.ts +91 -0
- package/apps/desktop/core/time.ts +61 -0
- package/apps/desktop/core/video-effects.ts +660 -0
- package/apps/desktop/dist/cli/NebulaSans-Bold-26se8aek.otf +0 -0
- package/apps/desktop/dist/cli/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
- package/apps/desktop/dist/cli/NebulaSans-Book-5ax05zvn.woff2 +0 -0
- package/apps/desktop/dist/cli/NebulaSans-Book-8cenzchw.otf +0 -0
- package/apps/desktop/dist/cli/main.js +5086 -0
- package/apps/desktop/html-overlay/catalog.ts +171 -0
- package/apps/desktop/html-overlay/contracts.ts +372 -0
- package/apps/desktop/html-overlay/execution-profile.ts +77 -0
- package/apps/desktop/html-overlay/index.ts +98 -0
- package/apps/desktop/html-overlay/libraries.ts +263 -0
- package/apps/desktop/html-overlay/random.ts +49 -0
- package/apps/desktop/html-overlay/runtime.ts +813 -0
- package/apps/desktop/html-overlay/scaffolds.ts +792 -0
- package/apps/desktop/html-overlay/spark-runtime.ts +88 -0
- package/apps/desktop/html-overlay/spatial-splat-runtime.ts +60 -0
- package/apps/desktop/html-overlay/spatial.ts +720 -0
- package/apps/desktop/studio/assets/README.md +39 -0
- package/apps/desktop/studio/assets/contracts.ts +129 -0
- package/apps/desktop/studio/assets/network.ts +64 -0
- package/apps/desktop/studio/assets/poly-haven.ts +148 -0
- package/apps/desktop/studio/drivers/blender_driver.py +466 -0
- package/apps/desktop/studio/drivers/cadquery_driver.py +176 -0
- package/apps/desktop/studio/education/driver.py +308 -0
- package/apps/desktop/studio/education/lesson.py +180 -0
- package/apps/desktop/studio/education/toolkit.py +249 -0
- package/apps/desktop/workflows/chaptered-demo.ts +48 -0
- package/apps/desktop/workflows/creative-iteration.ts +107 -0
- package/apps/desktop/workflows/creative-selection.ts +92 -0
- package/apps/desktop/workflows/fragments.ts +486 -0
- package/apps/desktop/workflows/index.ts +93 -0
- package/apps/desktop/workflows/polished-screen-demo.ts +128 -0
- package/apps/desktop/workflows/scene-direction.ts +12 -0
- package/apps/desktop/workflows/social-variants.ts +75 -0
- package/apps/desktop/workflows/talking-head-cleanup.ts +53 -0
- package/dist/NebulaSans-Bold-26se8aek.otf +0 -0
- package/dist/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
- package/dist/NebulaSans-Book-5ax05zvn.woff2 +0 -0
- package/dist/NebulaSans-Book-8cenzchw.otf +0 -0
- package/dist/cli.js +479 -0
- package/dist/code/advanced.js +270 -0
- package/dist/code/index.js +2240 -0
- package/dist/generate.js +24 -0
- package/dist/host-resources.js +26 -0
- package/dist/index-42zsesc1.js +2257 -0
- package/dist/index-7308egqr.js +48 -0
- package/dist/index-8txs6fkn.js +712 -0
- package/dist/index-mcy8z0br.js +192 -0
- package/dist/index-p63wavx0.js +2029 -0
- package/dist/index-r7gdhmsp.js +424 -0
- package/dist/index-sh6xbav6.js +1219 -0
- package/dist/index-z1w83f81.js +4 -0
- package/dist/index-z7239b4h.js +2363 -0
- package/dist/index-zfeg9hmw.js +2013 -0
- package/dist/index.js +241 -0
- package/dist/operations.js +29 -0
- package/dist/skill-install-dh0ntqba.js +10 -0
- package/dist/vectorize/worker.js +142 -0
- package/dist/workflow.js +16 -0
- package/docs/README.md +38 -0
- package/docs/studio.md +215 -0
- package/examples/studio/blender/README.md +26 -0
- package/examples/studio/blender/character.py +152 -0
- package/examples/studio/blender/cloth.py +101 -0
- package/examples/studio/blender/color_chart.py +29 -0
- package/examples/studio/blender/fluid.py +78 -0
- package/examples/studio/blender/import_model.py +74 -0
- package/examples/studio/blender/product.py +53 -0
- package/examples/studio/blender/shaded_street.py +481 -0
- package/examples/studio/blender/studio_scene.py +147 -0
- package/examples/studio/cadquery/README.md +13 -0
- package/examples/studio/cadquery/bracket.py +36 -0
- package/examples/studio/cadquery/import_step.py +12 -0
- package/examples/studio/education/README.md +46 -0
- package/examples/studio/education/lesson.json +99 -0
- package/examples/studio/education/scene.py +7 -0
- package/examples/studio/hybrid-scene.ts +96 -0
- package/examples/studio/native-workflow.ts +14 -0
- package/examples/studio/vgpu/README.md +64 -0
- package/examples/studio/vgpu/heat-field.mjs +290 -0
- package/package.json +304 -0
- package/packages/scene/src/index.ts +1 -0
- package/packages/scene/src/scene.ts +215 -0
- package/schema/diagram.schema.json +334 -0
- package/skills/slopcamera/SKILL.md +45 -0
- package/skills/slopcamera/agents/openai.yaml +4 -0
- package/skills/slopcamera/references/customization.md +77 -0
- package/skills/slopcamera/references/diagrams.md +153 -0
- package/skills/slopcamera/references/directed-scenes.md +42 -0
- package/skills/slopcamera/references/directing-video.md +18 -0
- package/skills/slopcamera/references/educational-video.md +26 -0
- package/skills/slopcamera/references/gateway-media.md +134 -0
- package/skills/slopcamera/references/install.md +62 -0
- package/skills/slopcamera/references/native-studio.md +31 -0
- package/skills/slopcamera/references/reference-led-3d.md +140 -0
- package/skills/slopcamera/references/rubber-stamp-examples/poster-example-1.jpg +0 -0
- package/skills/slopcamera/references/rubber-stamp-examples/poster-example-2.jpg +0 -0
- package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-1.png +0 -0
- package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-2.png +0 -0
- package/skills/slopcamera/references/rubber-stamp-field-notes.md +144 -0
- package/skills/slopcamera/references/vectorization.md +29 -0
- package/skills/slopcamera/references/video-projects.md +187 -0
- package/skills/slopcamera/references/visual-communication.md +120 -0
- package/skills/slopcamera/references/workflows-sdk.md +45 -0
- package/skills/slopcamera/scripts/compose-rubber-stamp-field-note.ts +229 -0
- package/src/artifacts.ts +106 -0
- package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
- package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
- package/src/assets/fonts/nebula-sans/PROVENANCE.md +21 -0
- package/src/assets.d.ts +9 -0
- package/src/cli.ts +601 -0
- package/src/cloud-errors.ts +26 -0
- package/src/code/advanced.ts +10 -0
- package/src/code/boundary.ts +21 -0
- package/src/code/canonical-json.ts +129 -0
- package/src/code/compiler.ts +953 -0
- package/src/code/contracts.ts +576 -0
- package/src/code/define-workflow.ts +334 -0
- package/src/code/errors.ts +41 -0
- package/src/code/graph-builder.ts +945 -0
- package/src/code/index.ts +121 -0
- package/src/code/json-snapshot.ts +899 -0
- package/src/code/json-utf8.ts +88 -0
- package/src/code/portable-builder.ts +136 -0
- package/src/code/projection.ts +378 -0
- package/src/code/public-operations.ts +450 -0
- package/src/code/runtime.ts +580 -0
- package/src/code/sha256.ts +36 -0
- package/src/config.ts +180 -0
- package/src/desktop.ts +253 -0
- package/src/fs.ts +10 -0
- package/src/generate.ts +704 -0
- package/src/host-resource-posix.ts +161 -0
- package/src/host-resources.ts +1749 -0
- package/src/icons.ts +58 -0
- package/src/index.ts +200 -0
- package/src/label-layout.ts +130 -0
- package/src/layout.ts +413 -0
- package/src/lint.ts +127 -0
- package/src/mcp/boundary.ts +354 -0
- package/src/mcp/index.ts +33 -0
- package/src/mcp/server.ts +272 -0
- package/src/mcp/tools.ts +963 -0
- package/src/mcp/types.ts +71 -0
- package/src/operations.ts +775 -0
- package/src/parse.ts +861 -0
- package/src/process-environment.ts +17 -0
- package/src/render.ts +437 -0
- package/src/skill-install.ts +49 -0
- package/src/spatial-scene/authoring.ts +27 -0
- package/src/spatial-scene/camera-track.ts +83 -0
- package/src/spatial-scene/contracts.ts +277 -0
- package/src/spatial-scene/evaluate.ts +145 -0
- package/src/spatial-scene/gltf.ts +558 -0
- package/src/spatial-scene/identity.ts +260 -0
- package/src/spatial-scene/index.ts +10 -0
- package/src/spatial-scene/inspect.ts +68 -0
- package/src/spatial-scene/math.ts +280 -0
- package/src/spatial-scene/patch.ts +131 -0
- package/src/spatial-scene/time.ts +53 -0
- package/src/studio/contracts.ts +129 -0
- package/src/studio/index.ts +2 -0
- package/src/studio/plan.ts +156 -0
- package/src/studio/shared.ts +41 -0
- package/src/theme.ts +68 -0
- package/src/tldr.ts +474 -0
- package/src/types.ts +212 -0
- package/src/vectorize/archive.ts +101 -0
- package/src/vectorize/command.ts +797 -0
- package/src/vectorize/index.ts +27 -0
- package/src/vectorize/limits.ts +61 -0
- package/src/vectorize/metrics.ts +351 -0
- package/src/vectorize/pixels.ts +323 -0
- package/src/vectorize/supervisor.ts +339 -0
- package/src/vectorize/svg.ts +188 -0
- package/src/vectorize/tool.ts +542 -0
- package/src/vectorize/types.ts +113 -0
- package/src/vectorize/vectorize.ts +634 -0
- package/src/vectorize/worker-protocol.ts +40 -0
- package/src/vectorize/worker.ts +209 -0
- package/src/version.ts +1 -0
- package/src/workflow.ts +409 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the exact UTF-8 byte length of JSON.stringify(value) without first
|
|
3
|
+
* allocating the serialized string. Undefined means the caller-provided byte
|
|
4
|
+
* ceiling was exceeded.
|
|
5
|
+
*/
|
|
6
|
+
export function jsonStringUtf8ByteLength(
|
|
7
|
+
value: string,
|
|
8
|
+
maximumBytes = Number.MAX_SAFE_INTEGER,
|
|
9
|
+
): number | undefined {
|
|
10
|
+
if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 0) return undefined
|
|
11
|
+
|
|
12
|
+
let bytes = 2 // Opening and closing quotes.
|
|
13
|
+
if (bytes > maximumBytes) return undefined
|
|
14
|
+
|
|
15
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
16
|
+
const codeUnit = value.charCodeAt(index)
|
|
17
|
+
let additional: number
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
codeUnit === 0x22
|
|
21
|
+
|| codeUnit === 0x5c
|
|
22
|
+
|| codeUnit === 0x08
|
|
23
|
+
|| codeUnit === 0x09
|
|
24
|
+
|| codeUnit === 0x0a
|
|
25
|
+
|| codeUnit === 0x0c
|
|
26
|
+
|| codeUnit === 0x0d
|
|
27
|
+
) {
|
|
28
|
+
additional = 2
|
|
29
|
+
} else if (codeUnit < 0x20) {
|
|
30
|
+
additional = 6
|
|
31
|
+
} else if (codeUnit < 0x80) {
|
|
32
|
+
additional = 1
|
|
33
|
+
} else if (codeUnit < 0x800) {
|
|
34
|
+
additional = 2
|
|
35
|
+
} else if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
|
|
36
|
+
const next = value.charCodeAt(index + 1)
|
|
37
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
38
|
+
additional = 4
|
|
39
|
+
index += 1
|
|
40
|
+
} else {
|
|
41
|
+
// Well-formed JSON.stringify escapes lone UTF-16 surrogates as \udxxx.
|
|
42
|
+
additional = 6
|
|
43
|
+
}
|
|
44
|
+
} else if (codeUnit >= 0xdc00 && codeUnit <= 0xdfff) {
|
|
45
|
+
additional = 6
|
|
46
|
+
} else {
|
|
47
|
+
additional = 3
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (additional > maximumBytes - bytes) return undefined
|
|
51
|
+
bytes += additional
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return bytes
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Exact TextEncoder byte length with an optional allocation-free cutoff. */
|
|
58
|
+
export function utf8ByteLength(
|
|
59
|
+
value: string,
|
|
60
|
+
maximumBytes = Number.MAX_SAFE_INTEGER,
|
|
61
|
+
): number | undefined {
|
|
62
|
+
if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 0) return undefined
|
|
63
|
+
|
|
64
|
+
let bytes = 0
|
|
65
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
66
|
+
const codeUnit = value.charCodeAt(index)
|
|
67
|
+
let additional: number
|
|
68
|
+
if (codeUnit < 0x80) {
|
|
69
|
+
additional = 1
|
|
70
|
+
} else if (codeUnit < 0x800) {
|
|
71
|
+
additional = 2
|
|
72
|
+
} else if (codeUnit >= 0xd800 && codeUnit <= 0xdbff) {
|
|
73
|
+
const next = value.charCodeAt(index + 1)
|
|
74
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
75
|
+
additional = 4
|
|
76
|
+
index += 1
|
|
77
|
+
} else {
|
|
78
|
+
// TextEncoder replaces malformed UTF-16 with U+FFFD.
|
|
79
|
+
additional = 3
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
additional = 3
|
|
83
|
+
}
|
|
84
|
+
if (additional > maximumBytes - bytes) return undefined
|
|
85
|
+
bytes += additional
|
|
86
|
+
}
|
|
87
|
+
return bytes
|
|
88
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AuthoredWorkflowGraphV1,
|
|
3
|
+
type OperationInputValue,
|
|
4
|
+
type Ref,
|
|
5
|
+
type WorkflowIdentity,
|
|
6
|
+
type WorkflowOutputValue,
|
|
7
|
+
} from "./contracts.js"
|
|
8
|
+
import {
|
|
9
|
+
WorkflowGraphBuilder,
|
|
10
|
+
type OperationNodeOptions,
|
|
11
|
+
} from "./graph-builder.js"
|
|
12
|
+
import {
|
|
13
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS,
|
|
14
|
+
type SlopcameraDiagramCheckInput,
|
|
15
|
+
type SlopcameraDiagramCheckOutput,
|
|
16
|
+
type SlopcameraDiagramRenderInput,
|
|
17
|
+
type SlopcameraDiagramRenderOutput,
|
|
18
|
+
type SlopcameraImageGenerateInput,
|
|
19
|
+
type SlopcameraImageGenerateOutput,
|
|
20
|
+
type SlopcameraImageVectorizeInput,
|
|
21
|
+
type SlopcameraImageVectorizeOutput,
|
|
22
|
+
} from "./public-operations.js"
|
|
23
|
+
import { PUBLIC_WORKFLOW_REGISTRY_PROJECTION } from "./projection.js"
|
|
24
|
+
|
|
25
|
+
export interface PortableWorkflowFragment<Input, Output> {
|
|
26
|
+
build(builder: PortableWorkflowBuilder, input: Input): Output
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function definePortableWorkflowFragment<Input, Output>(
|
|
30
|
+
build: (builder: PortableWorkflowBuilder, input: Input) => Output,
|
|
31
|
+
): PortableWorkflowFragment<Input, Output> {
|
|
32
|
+
return Object.freeze({ build })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class PortableWorkflowBuilder {
|
|
36
|
+
readonly #builder: WorkflowGraphBuilder
|
|
37
|
+
|
|
38
|
+
readonly diagram: Readonly<{
|
|
39
|
+
check: (
|
|
40
|
+
key: string,
|
|
41
|
+
input: OperationInputValue<SlopcameraDiagramCheckInput>,
|
|
42
|
+
options?: OperationNodeOptions,
|
|
43
|
+
) => Ref<SlopcameraDiagramCheckOutput>
|
|
44
|
+
render: (
|
|
45
|
+
key: string,
|
|
46
|
+
input: OperationInputValue<SlopcameraDiagramRenderInput>,
|
|
47
|
+
options?: OperationNodeOptions,
|
|
48
|
+
) => Ref<SlopcameraDiagramRenderOutput>
|
|
49
|
+
}>
|
|
50
|
+
|
|
51
|
+
readonly image: Readonly<{
|
|
52
|
+
generate: (
|
|
53
|
+
key: string,
|
|
54
|
+
input: OperationInputValue<SlopcameraImageGenerateInput>,
|
|
55
|
+
options?: OperationNodeOptions,
|
|
56
|
+
) => Ref<SlopcameraImageGenerateOutput>
|
|
57
|
+
vectorize: (
|
|
58
|
+
key: string,
|
|
59
|
+
input: OperationInputValue<SlopcameraImageVectorizeInput>,
|
|
60
|
+
options?: OperationNodeOptions,
|
|
61
|
+
) => Ref<SlopcameraImageVectorizeOutput>
|
|
62
|
+
}>
|
|
63
|
+
|
|
64
|
+
private constructor(builder: WorkflowGraphBuilder) {
|
|
65
|
+
this.#builder = builder
|
|
66
|
+
this.diagram = Object.freeze({
|
|
67
|
+
check: (
|
|
68
|
+
key: string,
|
|
69
|
+
input: OperationInputValue<SlopcameraDiagramCheckInput>,
|
|
70
|
+
options: OperationNodeOptions = {},
|
|
71
|
+
) => this.#builder.operation(
|
|
72
|
+
key,
|
|
73
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS["slopcamera.diagram.check"],
|
|
74
|
+
input,
|
|
75
|
+
options,
|
|
76
|
+
),
|
|
77
|
+
render: (
|
|
78
|
+
key: string,
|
|
79
|
+
input: OperationInputValue<SlopcameraDiagramRenderInput>,
|
|
80
|
+
options: OperationNodeOptions = {},
|
|
81
|
+
) => this.#builder.operation(
|
|
82
|
+
key,
|
|
83
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS["slopcamera.diagram.render"],
|
|
84
|
+
input,
|
|
85
|
+
options,
|
|
86
|
+
),
|
|
87
|
+
})
|
|
88
|
+
this.image = Object.freeze({
|
|
89
|
+
generate: (
|
|
90
|
+
key: string,
|
|
91
|
+
input: OperationInputValue<SlopcameraImageGenerateInput>,
|
|
92
|
+
options: OperationNodeOptions = {},
|
|
93
|
+
) => this.#builder.operation(
|
|
94
|
+
key,
|
|
95
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS["slopcamera.image.generate"],
|
|
96
|
+
input,
|
|
97
|
+
options,
|
|
98
|
+
),
|
|
99
|
+
vectorize: (
|
|
100
|
+
key: string,
|
|
101
|
+
input: OperationInputValue<SlopcameraImageVectorizeInput>,
|
|
102
|
+
options: OperationNodeOptions = {},
|
|
103
|
+
) => this.#builder.operation(
|
|
104
|
+
key,
|
|
105
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS["slopcamera.image.vectorize"],
|
|
106
|
+
input,
|
|
107
|
+
options,
|
|
108
|
+
),
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static create(): PortableWorkflowBuilder {
|
|
113
|
+
return new PortableWorkflowBuilder(
|
|
114
|
+
WorkflowGraphBuilder.create(PUBLIC_WORKFLOW_REGISTRY_PROJECTION),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
namespace(segment: string): PortableWorkflowBuilder {
|
|
119
|
+
return new PortableWorkflowBuilder(this.#builder.namespace(segment))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
fragment<Input, Output>(
|
|
123
|
+
namespace: string,
|
|
124
|
+
fragment: PortableWorkflowFragment<Input, Output>,
|
|
125
|
+
input: Input,
|
|
126
|
+
): Output {
|
|
127
|
+
return fragment.build(this.namespace(namespace), input)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
build(
|
|
131
|
+
workflow: WorkflowIdentity,
|
|
132
|
+
outputs: WorkflowOutputValue,
|
|
133
|
+
): AuthoredWorkflowGraphV1 {
|
|
134
|
+
return this.#builder.build(workflow, outputs)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_OPERATION_DISCOVERY_ENTRIES,
|
|
3
|
+
OPERATION_PREPARATION_KINDS,
|
|
4
|
+
OPERATION_RESOURCE_KINDS,
|
|
5
|
+
OperationDiscoverySchema,
|
|
6
|
+
SchemaIdSchema,
|
|
7
|
+
WorkflowRegistryProjectionSchema,
|
|
8
|
+
type OperationDiscovery,
|
|
9
|
+
type OperationDiscoverySource,
|
|
10
|
+
type WorkflowRegistryProjection,
|
|
11
|
+
} from "./contracts.js"
|
|
12
|
+
import {
|
|
13
|
+
canonicalJsonSha256,
|
|
14
|
+
canonicalJsonSha256Prefixed,
|
|
15
|
+
} from "./canonical-json.js"
|
|
16
|
+
import { parseCodeBoundary } from "./boundary.js"
|
|
17
|
+
import { SlopcameraCodeError } from "./errors.js"
|
|
18
|
+
import { createBoundedJsonValueSnapshot } from "./json-snapshot.js"
|
|
19
|
+
import {
|
|
20
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS,
|
|
21
|
+
PORTABLE_SLOPCAMERA_OPERATION_KINDS,
|
|
22
|
+
} from "./public-operations.js"
|
|
23
|
+
|
|
24
|
+
export const WORKFLOW_REGISTRY_PROJECTION_HASH_DOMAIN =
|
|
25
|
+
"slopcamera.workflow.registry-projection/v1" as const
|
|
26
|
+
export const PUBLIC_WORKFLOW_REGISTRY_PROJECTION_ID =
|
|
27
|
+
"slopcamera.workflow.registry.public/v1" as const
|
|
28
|
+
|
|
29
|
+
export type WorkflowRegistryProjectionSource =
|
|
30
|
+
| OperationDiscoverySource
|
|
31
|
+
| readonly OperationDiscovery[]
|
|
32
|
+
|
|
33
|
+
export interface CreateWorkflowRegistryProjectionOptions {
|
|
34
|
+
readonly trustedCompute?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const OWNED_NORMALIZED_PROJECTIONS = new WeakSet<object>()
|
|
38
|
+
const MAX_OPERATION_DISCOVERY_VALUES = 17
|
|
39
|
+
+ OPERATION_PREPARATION_KINDS.length
|
|
40
|
+
+ (3 * OPERATION_RESOURCE_KINDS.length)
|
|
41
|
+
const MAX_OPERATION_DISCOVERY_LIST_VALUES = 1
|
|
42
|
+
+ (MAX_OPERATION_DISCOVERY_ENTRIES * MAX_OPERATION_DISCOVERY_VALUES)
|
|
43
|
+
const MAX_OPERATION_DISCOVERY_LIST_BYTES = 32 * 1024 * 1024
|
|
44
|
+
const MAX_OPERATION_DISCOVERY_LIST_DEPTH = 8
|
|
45
|
+
const MAX_WORKFLOW_REGISTRY_PROJECTION_BYTES =
|
|
46
|
+
MAX_OPERATION_DISCOVERY_LIST_BYTES + 4_096
|
|
47
|
+
const MAX_WORKFLOW_REGISTRY_PROJECTION_DEPTH =
|
|
48
|
+
MAX_OPERATION_DISCOVERY_LIST_DEPTH + 1
|
|
49
|
+
const MAX_WORKFLOW_REGISTRY_PROJECTION_VALUES =
|
|
50
|
+
MAX_OPERATION_DISCOVERY_LIST_VALUES + 5
|
|
51
|
+
|
|
52
|
+
function discoveryList(
|
|
53
|
+
source: WorkflowRegistryProjectionSource,
|
|
54
|
+
): unknown {
|
|
55
|
+
return Array.isArray(source)
|
|
56
|
+
? source
|
|
57
|
+
: (source as OperationDiscoverySource).list()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function boundedOperationDiscoveryList(
|
|
61
|
+
input: unknown,
|
|
62
|
+
name = "operation discovery list",
|
|
63
|
+
): readonly unknown[] {
|
|
64
|
+
if (!Array.isArray(input)) {
|
|
65
|
+
throw new SlopcameraCodeError("invalid-data", `${name} must be an array.`)
|
|
66
|
+
}
|
|
67
|
+
const length = input.length
|
|
68
|
+
if (length > MAX_OPERATION_DISCOVERY_ENTRIES) {
|
|
69
|
+
throw new SlopcameraCodeError(
|
|
70
|
+
"invalid-data",
|
|
71
|
+
`${name} cannot exceed ${String(MAX_OPERATION_DISCOVERY_ENTRIES)} entries.`,
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
const descriptors = Object.getOwnPropertyDescriptors(input)
|
|
75
|
+
if (Object.getOwnPropertySymbols(descriptors).some(
|
|
76
|
+
symbol => (Reflect.get(descriptors, symbol) as PropertyDescriptor | undefined)
|
|
77
|
+
?.enumerable === true,
|
|
78
|
+
)) {
|
|
79
|
+
throw new SlopcameraCodeError(
|
|
80
|
+
"invalid-data",
|
|
81
|
+
`${name} cannot contain enumerable symbol properties.`,
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
const keys = Object.keys(descriptors)
|
|
85
|
+
.filter(key => descriptors[key]?.enumerable === true)
|
|
86
|
+
if (
|
|
87
|
+
keys.length !== length
|
|
88
|
+
|| keys.some((key, index) => key !== String(index))
|
|
89
|
+
) {
|
|
90
|
+
throw new SlopcameraCodeError(
|
|
91
|
+
"invalid-data",
|
|
92
|
+
`${name} must be dense and cannot have named properties.`,
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
const punctuationBytes = 2 + Math.max(0, length - 1)
|
|
96
|
+
let bytes = punctuationBytes
|
|
97
|
+
let values = 1
|
|
98
|
+
const captured: unknown[] = []
|
|
99
|
+
for (let index = 0; index < length; index += 1) {
|
|
100
|
+
const descriptor = descriptors[String(index)]
|
|
101
|
+
if (
|
|
102
|
+
descriptor === undefined
|
|
103
|
+
|| descriptor.get !== undefined
|
|
104
|
+
|| descriptor.set !== undefined
|
|
105
|
+
) {
|
|
106
|
+
throw new SlopcameraCodeError(
|
|
107
|
+
"invalid-data",
|
|
108
|
+
`${name} must contain plain data elements.`,
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
const remainingBytes = MAX_OPERATION_DISCOVERY_LIST_BYTES - bytes
|
|
112
|
+
if (remainingBytes < 1) {
|
|
113
|
+
throw new SlopcameraCodeError(
|
|
114
|
+
"invalid-data",
|
|
115
|
+
`${name} contains more than ${String(MAX_OPERATION_DISCOVERY_LIST_BYTES)} bytes.`,
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
const snapshot = createBoundedJsonValueSnapshot(
|
|
119
|
+
descriptor.value,
|
|
120
|
+
remainingBytes,
|
|
121
|
+
`${name} entry ${String(index)}`,
|
|
122
|
+
{
|
|
123
|
+
maximumDepth: MAX_OPERATION_DISCOVERY_LIST_DEPTH - 1,
|
|
124
|
+
maximumValues: MAX_OPERATION_DISCOVERY_VALUES,
|
|
125
|
+
},
|
|
126
|
+
)
|
|
127
|
+
bytes += snapshot.bytes
|
|
128
|
+
values += snapshot.values
|
|
129
|
+
if (values > MAX_OPERATION_DISCOVERY_LIST_VALUES) {
|
|
130
|
+
throw new SlopcameraCodeError(
|
|
131
|
+
"invalid-data",
|
|
132
|
+
`${name} contains more than ${String(MAX_OPERATION_DISCOVERY_LIST_VALUES)} JSON values.`,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
captured.push(snapshot.value)
|
|
136
|
+
}
|
|
137
|
+
return Object.freeze(captured)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function operationKey(kind: string, version: number): string {
|
|
141
|
+
return `${kind}@${String(version)}`
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function uniqueSorted<Value extends string>(
|
|
145
|
+
values: Iterable<Value>,
|
|
146
|
+
): readonly Value[] {
|
|
147
|
+
return [...new Set(values)].sort((left, right) => left.localeCompare(right))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function canonicalSlopcameraIdentity(value: string): string {
|
|
151
|
+
if (value === "studio") return "slopcamera"
|
|
152
|
+
return value.replace(/^studio\./u, "slopcamera.")
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function normalizeOperationDiscoveryPreservingIdentity(
|
|
156
|
+
input: unknown,
|
|
157
|
+
): readonly OperationDiscovery[] {
|
|
158
|
+
const normalized = boundedOperationDiscoveryList(input).map((item) => {
|
|
159
|
+
const parsed = parseCodeBoundary(
|
|
160
|
+
OperationDiscoverySchema,
|
|
161
|
+
item,
|
|
162
|
+
"operation discovery entry",
|
|
163
|
+
)
|
|
164
|
+
const preparation = uniqueSorted(parsed.policy.preparation)
|
|
165
|
+
if (preparation.length !== parsed.policy.preparation.length) {
|
|
166
|
+
throw new SlopcameraCodeError(
|
|
167
|
+
"invalid-data",
|
|
168
|
+
`Duplicate preparation requirement for ${operationKey(parsed.kind, parsed.version)}.`,
|
|
169
|
+
{ kind: parsed.kind, version: parsed.version },
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
const resources = [...parsed.policy.resources]
|
|
173
|
+
.sort((left, right) => (
|
|
174
|
+
left.resource.localeCompare(right.resource)
|
|
175
|
+
))
|
|
176
|
+
if (new Set(resources.map(resource => resource.resource)).size !== resources.length) {
|
|
177
|
+
throw new SlopcameraCodeError(
|
|
178
|
+
"invalid-data",
|
|
179
|
+
`Duplicate resource claim for ${operationKey(parsed.kind, parsed.version)}.`,
|
|
180
|
+
{ kind: parsed.kind, version: parsed.version },
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
return parseCodeBoundary(OperationDiscoverySchema, {
|
|
184
|
+
...parsed,
|
|
185
|
+
policy: { ...parsed.policy, preparation, resources },
|
|
186
|
+
}, "normalized operation discovery entry")
|
|
187
|
+
}).sort((left, right) => (
|
|
188
|
+
left.kind.localeCompare(right.kind) || left.version - right.version
|
|
189
|
+
))
|
|
190
|
+
const seen = new Set<string>()
|
|
191
|
+
for (const operation of normalized) {
|
|
192
|
+
const key = operationKey(operation.kind, operation.version)
|
|
193
|
+
if (seen.has(key)) {
|
|
194
|
+
throw new SlopcameraCodeError(
|
|
195
|
+
"conflict",
|
|
196
|
+
`Duplicate operation discovery entry: ${key}`,
|
|
197
|
+
{ kind: operation.kind, version: operation.version },
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
seen.add(key)
|
|
201
|
+
}
|
|
202
|
+
return normalized
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function normalizeOperationDiscovery(
|
|
206
|
+
input: unknown,
|
|
207
|
+
): readonly OperationDiscovery[] {
|
|
208
|
+
return normalizeOperationDiscoveryPreservingIdentity(input).map(operation => (
|
|
209
|
+
parseCodeBoundary(OperationDiscoverySchema, {
|
|
210
|
+
...operation,
|
|
211
|
+
inputSchemaId: canonicalSlopcameraIdentity(operation.inputSchemaId),
|
|
212
|
+
kind: canonicalSlopcameraIdentity(operation.kind),
|
|
213
|
+
outputSchemaId: canonicalSlopcameraIdentity(operation.outputSchemaId),
|
|
214
|
+
}, "canonical operation discovery entry")
|
|
215
|
+
))
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function freezeDiscovery(
|
|
219
|
+
discovery: readonly OperationDiscovery[],
|
|
220
|
+
): readonly OperationDiscovery[] {
|
|
221
|
+
return Object.freeze(discovery.map(operation => Object.freeze({
|
|
222
|
+
...operation,
|
|
223
|
+
policy: Object.freeze({
|
|
224
|
+
...operation.policy,
|
|
225
|
+
preparation: Object.freeze([...operation.policy.preparation]),
|
|
226
|
+
resources: Object.freeze(operation.policy.resources.map(
|
|
227
|
+
resource => Object.freeze({ ...resource }),
|
|
228
|
+
)),
|
|
229
|
+
}),
|
|
230
|
+
})))
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function createWorkflowRegistryProjectionHash(input: {
|
|
234
|
+
readonly discovery: readonly OperationDiscovery[]
|
|
235
|
+
readonly id: string
|
|
236
|
+
readonly trustedCompute?: boolean
|
|
237
|
+
}): string {
|
|
238
|
+
const id = canonicalSlopcameraIdentity(
|
|
239
|
+
parseCodeBoundary(SchemaIdSchema, input.id, "registry projection id"),
|
|
240
|
+
)
|
|
241
|
+
const discovery = normalizeOperationDiscovery(input.discovery)
|
|
242
|
+
const trustedCompute = input.trustedCompute ?? false
|
|
243
|
+
return workflowRegistryProjectionHashFromNormalized({
|
|
244
|
+
discovery,
|
|
245
|
+
id,
|
|
246
|
+
trustedCompute,
|
|
247
|
+
})
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function workflowRegistryProjectionHashFromNormalized(input: {
|
|
251
|
+
readonly discovery: readonly OperationDiscovery[]
|
|
252
|
+
readonly id: string
|
|
253
|
+
readonly trustedCompute: boolean
|
|
254
|
+
}, domain = WORKFLOW_REGISTRY_PROJECTION_HASH_DOMAIN): string {
|
|
255
|
+
return canonicalJsonSha256Prefixed(
|
|
256
|
+
`${domain}\0`,
|
|
257
|
+
{
|
|
258
|
+
discovery: input.discovery,
|
|
259
|
+
id: input.id,
|
|
260
|
+
trustedCompute: input.trustedCompute,
|
|
261
|
+
},
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function createWorkflowRegistryProjection(
|
|
266
|
+
idInput: string,
|
|
267
|
+
source: WorkflowRegistryProjectionSource,
|
|
268
|
+
options: CreateWorkflowRegistryProjectionOptions = {},
|
|
269
|
+
): WorkflowRegistryProjection {
|
|
270
|
+
const id = canonicalSlopcameraIdentity(
|
|
271
|
+
parseCodeBoundary(SchemaIdSchema, idInput, "registry projection id"),
|
|
272
|
+
)
|
|
273
|
+
const discovery = normalizeOperationDiscovery(discoveryList(source))
|
|
274
|
+
const trustedCompute = options.trustedCompute ?? false
|
|
275
|
+
const parsed = parseCodeBoundary(WorkflowRegistryProjectionSchema, {
|
|
276
|
+
discovery,
|
|
277
|
+
id,
|
|
278
|
+
projectionSha256: workflowRegistryProjectionHashFromNormalized({
|
|
279
|
+
discovery,
|
|
280
|
+
id,
|
|
281
|
+
trustedCompute,
|
|
282
|
+
}),
|
|
283
|
+
trustedCompute,
|
|
284
|
+
}, "workflow registry projection")
|
|
285
|
+
const projection = Object.freeze({
|
|
286
|
+
...parsed,
|
|
287
|
+
discovery: freezeDiscovery(parsed.discovery),
|
|
288
|
+
})
|
|
289
|
+
OWNED_NORMALIZED_PROJECTIONS.add(projection)
|
|
290
|
+
return projection
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function parseWorkflowRegistryProjection(
|
|
294
|
+
input: unknown,
|
|
295
|
+
): WorkflowRegistryProjection {
|
|
296
|
+
if (
|
|
297
|
+
typeof input === "object"
|
|
298
|
+
&& input !== null
|
|
299
|
+
&& OWNED_NORMALIZED_PROJECTIONS.has(input)
|
|
300
|
+
) {
|
|
301
|
+
return input as WorkflowRegistryProjection
|
|
302
|
+
}
|
|
303
|
+
const captured = createBoundedJsonValueSnapshot(
|
|
304
|
+
input,
|
|
305
|
+
MAX_WORKFLOW_REGISTRY_PROJECTION_BYTES,
|
|
306
|
+
"workflow registry projection",
|
|
307
|
+
{
|
|
308
|
+
maximumDepth: MAX_WORKFLOW_REGISTRY_PROJECTION_DEPTH,
|
|
309
|
+
maximumValues: MAX_WORKFLOW_REGISTRY_PROJECTION_VALUES,
|
|
310
|
+
},
|
|
311
|
+
).value
|
|
312
|
+
const parsed = parseCodeBoundary(
|
|
313
|
+
WorkflowRegistryProjectionSchema,
|
|
314
|
+
captured,
|
|
315
|
+
"workflow registry projection",
|
|
316
|
+
)
|
|
317
|
+
const exactDiscovery = normalizeOperationDiscoveryPreservingIdentity(
|
|
318
|
+
parsed.discovery,
|
|
319
|
+
)
|
|
320
|
+
const exactIdentity = {
|
|
321
|
+
discovery: exactDiscovery,
|
|
322
|
+
id: parsed.id,
|
|
323
|
+
trustedCompute: parsed.trustedCompute,
|
|
324
|
+
}
|
|
325
|
+
const expectedProjectionSha256 =
|
|
326
|
+
workflowRegistryProjectionHashFromNormalized(exactIdentity)
|
|
327
|
+
if (parsed.projectionSha256 !== expectedProjectionSha256) {
|
|
328
|
+
throw new SlopcameraCodeError(
|
|
329
|
+
"invalid-data",
|
|
330
|
+
"Workflow registry projection hash does not match its contents.",
|
|
331
|
+
{
|
|
332
|
+
actualProjectionSha256: parsed.projectionSha256,
|
|
333
|
+
expectedProjectionSha256,
|
|
334
|
+
projectionId: parsed.id,
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
if (canonicalJsonSha256(parsed.discovery) !== canonicalJsonSha256(exactDiscovery)) {
|
|
339
|
+
throw new SlopcameraCodeError(
|
|
340
|
+
"invalid-data",
|
|
341
|
+
"Workflow registry projection discovery is not normalized.",
|
|
342
|
+
{ projectionId: parsed.id },
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
return createWorkflowRegistryProjection(
|
|
346
|
+
parsed.id,
|
|
347
|
+
exactDiscovery,
|
|
348
|
+
{ trustedCompute: parsed.trustedCompute },
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function publicDiscovery(): readonly OperationDiscovery[] {
|
|
353
|
+
return PORTABLE_SLOPCAMERA_OPERATION_KINDS.map((kind) => {
|
|
354
|
+
const contract = PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS[kind]
|
|
355
|
+
return {
|
|
356
|
+
inputSchemaId: contract.inputSchemaId,
|
|
357
|
+
kind: contract.kind,
|
|
358
|
+
lifecycle: contract.lifecycle,
|
|
359
|
+
outputSchemaId: contract.outputSchemaId,
|
|
360
|
+
policy: contract.policy,
|
|
361
|
+
version: contract.version,
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export function createPublicWorkflowRegistryProjection(): WorkflowRegistryProjection {
|
|
367
|
+
return createWorkflowRegistryProjection(
|
|
368
|
+
PUBLIC_WORKFLOW_REGISTRY_PROJECTION_ID,
|
|
369
|
+
publicDiscovery(),
|
|
370
|
+
{ trustedCompute: false },
|
|
371
|
+
)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export const PUBLIC_WORKFLOW_REGISTRY_PROJECTION =
|
|
375
|
+
createPublicWorkflowRegistryProjection()
|
|
376
|
+
|
|
377
|
+
export const PUBLIC_SLOPCAMERA_WORKFLOW_PROJECTION =
|
|
378
|
+
PUBLIC_WORKFLOW_REGISTRY_PROJECTION
|