@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,580 @@
|
|
|
1
|
+
import type { z } from "zod"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isComputeGraphNode,
|
|
5
|
+
isOperationGraphNode,
|
|
6
|
+
type AuthoredGraphNodeV1,
|
|
7
|
+
type CompiledWorkflowGraph,
|
|
8
|
+
type GraphCompilerLimits,
|
|
9
|
+
type GraphInputValue,
|
|
10
|
+
type JsonValue,
|
|
11
|
+
type OperationPolicy,
|
|
12
|
+
type Ref,
|
|
13
|
+
type SerializedRefV1,
|
|
14
|
+
type WorkflowOutputBinding,
|
|
15
|
+
type WorkflowOutputValue,
|
|
16
|
+
} from "./contracts.js"
|
|
17
|
+
import {
|
|
18
|
+
compileWorkflowGraph,
|
|
19
|
+
} from "./compiler.js"
|
|
20
|
+
import {
|
|
21
|
+
canonicalJsonSha256Prefixed,
|
|
22
|
+
} from "./canonical-json.js"
|
|
23
|
+
import { parseCodeBoundary } from "./boundary.js"
|
|
24
|
+
import {
|
|
25
|
+
buildWorkflow,
|
|
26
|
+
type BuiltWorkflow,
|
|
27
|
+
type WorkflowDefinition,
|
|
28
|
+
} from "./define-workflow.js"
|
|
29
|
+
import {
|
|
30
|
+
SlopcameraCodeError,
|
|
31
|
+
slopcameraCodeErrorMessage,
|
|
32
|
+
type SlopcameraCodeErrorCode,
|
|
33
|
+
} from "./errors.js"
|
|
34
|
+
import {
|
|
35
|
+
PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS,
|
|
36
|
+
isPortableSlopcameraOperationKind,
|
|
37
|
+
type PortableSlopcameraOperationInputMap,
|
|
38
|
+
type PortableSlopcameraOperationKind,
|
|
39
|
+
type PortableSlopcameraOperationResultMap,
|
|
40
|
+
} from "./public-operations.js"
|
|
41
|
+
import { PUBLIC_WORKFLOW_REGISTRY_PROJECTION } from "./projection.js"
|
|
42
|
+
import {
|
|
43
|
+
createBoundedJsonSnapshot,
|
|
44
|
+
createBoundedJsonValueSnapshot,
|
|
45
|
+
type BoundedJsonSnapshot,
|
|
46
|
+
} from "./json-snapshot.js"
|
|
47
|
+
|
|
48
|
+
export const WORKFLOW_NODE_RECEIPT_VERSION =
|
|
49
|
+
"slopcamera-workflow-node-receipt-v1" as const
|
|
50
|
+
export const WORKFLOW_NODE_RECEIPT_HASH_DOMAIN =
|
|
51
|
+
"slopcamera.workflow.node-receipt/v1" as const
|
|
52
|
+
export const MAX_WORKFLOW_RESULT_BYTES = 96 * 1024 * 1024
|
|
53
|
+
// Output bindings and one resolved node output compose at this boundary.
|
|
54
|
+
export const MAX_WORKFLOW_RESULT_DEPTH = 320
|
|
55
|
+
export const MAX_WORKFLOW_RESULT_VALUES = 1_300_000
|
|
56
|
+
|
|
57
|
+
export interface SlopcameraCodeExecutionRequest<
|
|
58
|
+
Kind extends PortableSlopcameraOperationKind = PortableSlopcameraOperationKind,
|
|
59
|
+
> {
|
|
60
|
+
readonly input: PortableSlopcameraOperationInputMap[Kind]
|
|
61
|
+
readonly kind: Kind
|
|
62
|
+
readonly nodeKey: string
|
|
63
|
+
readonly version: 2
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface SlopcameraCodeExecutionContext {
|
|
67
|
+
readonly signal: AbortSignal
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type SlopcameraCodeExecutor = <Kind extends PortableSlopcameraOperationKind>(
|
|
71
|
+
request: SlopcameraCodeExecutionRequest<Kind>,
|
|
72
|
+
context: SlopcameraCodeExecutionContext,
|
|
73
|
+
) => Promise<PortableSlopcameraOperationResultMap[Kind]>
|
|
74
|
+
|
|
75
|
+
export interface SlopcameraCodeAdmissionRequest {
|
|
76
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
77
|
+
readonly nodeKey: string
|
|
78
|
+
readonly policy: OperationPolicy
|
|
79
|
+
readonly version: 2
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export type SlopcameraCodeAdmission = <Result>(
|
|
83
|
+
request: SlopcameraCodeAdmissionRequest,
|
|
84
|
+
execute: () => Promise<Result>,
|
|
85
|
+
context: SlopcameraCodeExecutionContext,
|
|
86
|
+
) => Promise<Result>
|
|
87
|
+
|
|
88
|
+
export interface SlopcameraCodeHost {
|
|
89
|
+
readonly admit?: SlopcameraCodeAdmission
|
|
90
|
+
readonly execute: SlopcameraCodeExecutor
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface CreateSlopcameraCodeHostOptions {
|
|
94
|
+
readonly admit?: SlopcameraCodeAdmission
|
|
95
|
+
readonly execute: SlopcameraCodeExecutor
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createSlopcameraCodeHost(
|
|
99
|
+
options: CreateSlopcameraCodeHostOptions,
|
|
100
|
+
): SlopcameraCodeHost {
|
|
101
|
+
if (typeof options !== "object" || options === null) {
|
|
102
|
+
throw new SlopcameraCodeError(
|
|
103
|
+
"invalid-data",
|
|
104
|
+
"An Slopcamera Code host must be an object.",
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
if (typeof options.execute !== "function") {
|
|
108
|
+
throw new SlopcameraCodeError(
|
|
109
|
+
"invalid-data",
|
|
110
|
+
"An Slopcamera Code host requires an execute function.",
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
if (options.admit !== undefined && typeof options.admit !== "function") {
|
|
114
|
+
throw new SlopcameraCodeError(
|
|
115
|
+
"invalid-data",
|
|
116
|
+
"An Slopcamera Code host admit value must be a function when provided.",
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
return Object.freeze({
|
|
120
|
+
...(options.admit === undefined ? {} : { admit: options.admit }),
|
|
121
|
+
execute: options.execute,
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface WorkflowNodeReceipt {
|
|
126
|
+
readonly index: number
|
|
127
|
+
readonly inputSha256: string
|
|
128
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
129
|
+
readonly nodeKey: string
|
|
130
|
+
readonly outputSha256: string
|
|
131
|
+
readonly receiptSha256: string
|
|
132
|
+
readonly version: typeof WORKFLOW_NODE_RECEIPT_VERSION
|
|
133
|
+
readonly operationVersion: 2
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface FailedWorkflowNode {
|
|
137
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
138
|
+
readonly nodeKey: string
|
|
139
|
+
readonly version: 2
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export class SlopcameraWorkflowRunError extends SlopcameraCodeError {
|
|
143
|
+
readonly completedReceipts: readonly WorkflowNodeReceipt[]
|
|
144
|
+
readonly failedNode: FailedWorkflowNode | undefined
|
|
145
|
+
readonly runCause: unknown
|
|
146
|
+
|
|
147
|
+
constructor(
|
|
148
|
+
code: SlopcameraCodeErrorCode,
|
|
149
|
+
message: string,
|
|
150
|
+
options: {
|
|
151
|
+
readonly cause: unknown
|
|
152
|
+
readonly completedReceipts: readonly WorkflowNodeReceipt[]
|
|
153
|
+
readonly failedNode?: FailedWorkflowNode
|
|
154
|
+
},
|
|
155
|
+
) {
|
|
156
|
+
const failedNode = options.failedNode === undefined
|
|
157
|
+
? undefined
|
|
158
|
+
: Object.freeze({ ...options.failedNode })
|
|
159
|
+
const completedReceipts = Object.freeze([...options.completedReceipts])
|
|
160
|
+
super(code, message, {
|
|
161
|
+
completedReceiptCount: completedReceipts.length,
|
|
162
|
+
...(failedNode === undefined ? {} : { failedNode }),
|
|
163
|
+
})
|
|
164
|
+
this.name = "SlopcameraWorkflowRunError"
|
|
165
|
+
this.completedReceipts = completedReceipts
|
|
166
|
+
this.failedNode = failedNode
|
|
167
|
+
this.runCause = options.cause
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export type ResolvedWorkflowOutput<Value> =
|
|
172
|
+
Value extends Ref<infer Output>
|
|
173
|
+
? Output
|
|
174
|
+
: Value extends readonly (infer Item)[]
|
|
175
|
+
? readonly ResolvedWorkflowOutput<Item>[]
|
|
176
|
+
: Value extends Readonly<Record<string, unknown>>
|
|
177
|
+
? { readonly [Key in keyof Value]: ResolvedWorkflowOutput<Value[Key]> }
|
|
178
|
+
: never
|
|
179
|
+
|
|
180
|
+
export interface WorkflowRunResult<Output = JsonValue> {
|
|
181
|
+
readonly compilation: CompiledWorkflowGraph
|
|
182
|
+
readonly output: Output
|
|
183
|
+
readonly receipts: readonly WorkflowNodeReceipt[]
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface RunBuiltWorkflowOptions {
|
|
187
|
+
readonly host: SlopcameraCodeHost
|
|
188
|
+
readonly limits?: Partial<GraphCompilerLimits>
|
|
189
|
+
readonly signal?: AbortSignal
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function isSerializedRef(value: unknown): value is SerializedRefV1 {
|
|
193
|
+
return typeof value === "object"
|
|
194
|
+
&& value !== null
|
|
195
|
+
&& !Array.isArray(value)
|
|
196
|
+
&& Object.hasOwn(value, "$ref")
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function projectedValue(
|
|
200
|
+
reference: SerializedRefV1,
|
|
201
|
+
values: ReadonlyMap<string, JsonValue>,
|
|
202
|
+
): JsonValue {
|
|
203
|
+
let current = values.get(reference.$ref.nodeKey)
|
|
204
|
+
if (current === undefined) {
|
|
205
|
+
throw new SlopcameraCodeError(
|
|
206
|
+
"internal",
|
|
207
|
+
`Workflow reference producer ${reference.$ref.nodeKey} has not completed.`,
|
|
208
|
+
{ nodeKey: reference.$ref.nodeKey },
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
for (const segment of reference.$ref.path ?? []) {
|
|
212
|
+
if (typeof segment === "number") {
|
|
213
|
+
if (!Array.isArray(current) || segment >= current.length) {
|
|
214
|
+
throw new SlopcameraCodeError(
|
|
215
|
+
"invalid-data",
|
|
216
|
+
`Workflow reference ${reference.$ref.nodeKey} has an invalid array projection.`,
|
|
217
|
+
{ nodeKey: reference.$ref.nodeKey, segment },
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
const currentArray = current as readonly JsonValue[]
|
|
221
|
+
current = currentArray[segment]
|
|
222
|
+
} else {
|
|
223
|
+
if (
|
|
224
|
+
typeof current !== "object"
|
|
225
|
+
|| current === null
|
|
226
|
+
|| Array.isArray(current)
|
|
227
|
+
|| !Object.hasOwn(current, segment)
|
|
228
|
+
) {
|
|
229
|
+
throw new SlopcameraCodeError(
|
|
230
|
+
"invalid-data",
|
|
231
|
+
`Workflow reference ${reference.$ref.nodeKey} has an invalid object projection.`,
|
|
232
|
+
{ nodeKey: reference.$ref.nodeKey, segment },
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
current = (current as Readonly<Record<string, JsonValue>>)[segment]
|
|
236
|
+
}
|
|
237
|
+
if (current === undefined) {
|
|
238
|
+
throw new SlopcameraCodeError(
|
|
239
|
+
"invalid-data",
|
|
240
|
+
`Workflow reference ${reference.$ref.nodeKey} projected an undefined value.`,
|
|
241
|
+
{ nodeKey: reference.$ref.nodeKey, segment },
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return current
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function resolveValue(
|
|
249
|
+
value: GraphInputValue | WorkflowOutputBinding,
|
|
250
|
+
values: ReadonlyMap<string, JsonValue>,
|
|
251
|
+
): JsonValue {
|
|
252
|
+
if (isSerializedRef(value)) return projectedValue(value, values)
|
|
253
|
+
if (Array.isArray(value)) {
|
|
254
|
+
const items = value as readonly (GraphInputValue | WorkflowOutputBinding)[]
|
|
255
|
+
return items.map(item => resolveValue(item, values))
|
|
256
|
+
}
|
|
257
|
+
if (typeof value === "object" && value !== null) {
|
|
258
|
+
const record = value as Readonly<Record<string, GraphInputValue | WorkflowOutputBinding>>
|
|
259
|
+
const output: Record<string, JsonValue> = {}
|
|
260
|
+
for (const key of Object.keys(record).sort()) {
|
|
261
|
+
const item = record[key]
|
|
262
|
+
if (item === undefined) {
|
|
263
|
+
throw new SlopcameraCodeError(
|
|
264
|
+
"internal",
|
|
265
|
+
`Compiled workflow value ${key} is undefined.`,
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
output[key] = resolveValue(item, values)
|
|
269
|
+
}
|
|
270
|
+
return output
|
|
271
|
+
}
|
|
272
|
+
return value
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function createNodeReceipt(
|
|
276
|
+
index: number,
|
|
277
|
+
nodeKey: string,
|
|
278
|
+
kind: PortableSlopcameraOperationKind,
|
|
279
|
+
inputSha256: string,
|
|
280
|
+
outputSha256: string,
|
|
281
|
+
): WorkflowNodeReceipt {
|
|
282
|
+
const unsigned = {
|
|
283
|
+
index,
|
|
284
|
+
inputSha256,
|
|
285
|
+
kind,
|
|
286
|
+
nodeKey,
|
|
287
|
+
operationVersion: 2 as const,
|
|
288
|
+
outputSha256,
|
|
289
|
+
version: WORKFLOW_NODE_RECEIPT_VERSION,
|
|
290
|
+
}
|
|
291
|
+
return Object.freeze({
|
|
292
|
+
...unsigned,
|
|
293
|
+
receiptSha256: canonicalJsonSha256Prefixed(
|
|
294
|
+
`${WORKFLOW_NODE_RECEIPT_HASH_DOMAIN}\0`,
|
|
295
|
+
unsigned,
|
|
296
|
+
),
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function publicOperationNode(
|
|
301
|
+
node: AuthoredGraphNodeV1,
|
|
302
|
+
): asserts node is AuthoredGraphNodeV1 & {
|
|
303
|
+
readonly executor: {
|
|
304
|
+
readonly kind: "operation"
|
|
305
|
+
readonly operation: {
|
|
306
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
307
|
+
readonly version: 2
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} {
|
|
311
|
+
if (isComputeGraphNode(node)) {
|
|
312
|
+
throw new SlopcameraCodeError(
|
|
313
|
+
"unsupported-plan",
|
|
314
|
+
`The public projection does not support trusted compute at node ${node.key}.`,
|
|
315
|
+
{
|
|
316
|
+
executorKind: "compute",
|
|
317
|
+
nodeKey: node.key,
|
|
318
|
+
projectionId: PUBLIC_WORKFLOW_REGISTRY_PROJECTION.id,
|
|
319
|
+
},
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
if (!isOperationGraphNode(node)) {
|
|
323
|
+
throw new SlopcameraCodeError(
|
|
324
|
+
"unsupported-plan",
|
|
325
|
+
`The public projection does not support the executor at node ${node.key}.`,
|
|
326
|
+
{ nodeKey: node.key, projectionId: PUBLIC_WORKFLOW_REGISTRY_PROJECTION.id },
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
const operation = node.executor.operation
|
|
330
|
+
if (
|
|
331
|
+
operation.version !== 2
|
|
332
|
+
|| !isPortableSlopcameraOperationKind(operation.kind)
|
|
333
|
+
) {
|
|
334
|
+
throw new SlopcameraCodeError(
|
|
335
|
+
"unsupported-plan",
|
|
336
|
+
`Unsupported operation: ${operation.kind}@${String(operation.version)}`,
|
|
337
|
+
{
|
|
338
|
+
kind: operation.kind,
|
|
339
|
+
nodeKey: node.key,
|
|
340
|
+
projectionId: PUBLIC_WORKFLOW_REGISTRY_PROJECTION.id,
|
|
341
|
+
version: operation.version,
|
|
342
|
+
},
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function throwIfAborted(signal: AbortSignal): void {
|
|
348
|
+
if (signal.aborted) {
|
|
349
|
+
throw new SlopcameraCodeError("cancelled", "Workflow execution was cancelled.")
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function workflowNodeFailure(
|
|
354
|
+
error: unknown,
|
|
355
|
+
node: AuthoredGraphNodeV1 & {
|
|
356
|
+
readonly executor: {
|
|
357
|
+
readonly kind: "operation"
|
|
358
|
+
readonly operation: {
|
|
359
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
360
|
+
readonly version: 2
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
completedReceipts: readonly WorkflowNodeReceipt[],
|
|
365
|
+
): SlopcameraWorkflowRunError {
|
|
366
|
+
const code = error instanceof SlopcameraCodeError ? error.code : "subprocess"
|
|
367
|
+
return new SlopcameraWorkflowRunError(
|
|
368
|
+
code,
|
|
369
|
+
`Workflow node ${node.key} (${node.executor.operation.kind}@2) failed: `
|
|
370
|
+
+ slopcameraCodeErrorMessage(error),
|
|
371
|
+
{
|
|
372
|
+
cause: error,
|
|
373
|
+
completedReceipts,
|
|
374
|
+
failedNode: {
|
|
375
|
+
kind: node.executor.operation.kind,
|
|
376
|
+
nodeKey: node.key,
|
|
377
|
+
version: 2,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function workflowRunFailure(
|
|
384
|
+
error: unknown,
|
|
385
|
+
message: string,
|
|
386
|
+
completedReceipts: readonly WorkflowNodeReceipt[],
|
|
387
|
+
): SlopcameraWorkflowRunError {
|
|
388
|
+
const code = error instanceof SlopcameraCodeError ? error.code : "internal"
|
|
389
|
+
return new SlopcameraWorkflowRunError(code, message, {
|
|
390
|
+
cause: error,
|
|
391
|
+
completedReceipts,
|
|
392
|
+
})
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async function executePublicNode(
|
|
396
|
+
host: SlopcameraCodeHost,
|
|
397
|
+
node: AuthoredGraphNodeV1 & {
|
|
398
|
+
readonly executor: {
|
|
399
|
+
readonly kind: "operation"
|
|
400
|
+
readonly operation: {
|
|
401
|
+
readonly kind: PortableSlopcameraOperationKind
|
|
402
|
+
readonly version: 2
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
values: ReadonlyMap<string, JsonValue>,
|
|
407
|
+
context: SlopcameraCodeExecutionContext,
|
|
408
|
+
): Promise<{
|
|
409
|
+
readonly input: BoundedJsonSnapshot
|
|
410
|
+
readonly output: BoundedJsonSnapshot
|
|
411
|
+
}> {
|
|
412
|
+
const { kind } = node.executor.operation
|
|
413
|
+
const contract = PORTABLE_SLOPCAMERA_OPERATION_CONTRACTS[kind]
|
|
414
|
+
const resolvedInput = resolveValue(node.input, values)
|
|
415
|
+
const rawInput = createBoundedJsonValueSnapshot(
|
|
416
|
+
resolvedInput,
|
|
417
|
+
contract.policy.maxInputBytes,
|
|
418
|
+
`${kind} raw input at node ${node.key}`,
|
|
419
|
+
)
|
|
420
|
+
const parsedInput = parseCodeBoundary(
|
|
421
|
+
contract.inputSchema as z.ZodType<unknown>,
|
|
422
|
+
rawInput.value,
|
|
423
|
+
`${kind} input at node ${node.key}`,
|
|
424
|
+
) as PortableSlopcameraOperationInputMap[typeof kind]
|
|
425
|
+
const boundedInput = createBoundedJsonSnapshot(
|
|
426
|
+
parsedInput,
|
|
427
|
+
contract.policy.maxInputBytes,
|
|
428
|
+
`${kind} input at node ${node.key}`,
|
|
429
|
+
)
|
|
430
|
+
const request: SlopcameraCodeExecutionRequest<typeof kind> = Object.freeze({
|
|
431
|
+
input: boundedInput.value as unknown as PortableSlopcameraOperationInputMap[
|
|
432
|
+
typeof kind
|
|
433
|
+
],
|
|
434
|
+
kind,
|
|
435
|
+
nodeKey: node.key,
|
|
436
|
+
version: 2,
|
|
437
|
+
})
|
|
438
|
+
throwIfAborted(context.signal)
|
|
439
|
+
const dispatch = async () => await host.execute(request, context)
|
|
440
|
+
const rawOutput = host.admit === undefined
|
|
441
|
+
? await dispatch()
|
|
442
|
+
: await host.admit(Object.freeze({
|
|
443
|
+
kind,
|
|
444
|
+
nodeKey: node.key,
|
|
445
|
+
policy: contract.policy,
|
|
446
|
+
version: 2,
|
|
447
|
+
}), dispatch, context)
|
|
448
|
+
const boundedRawOutput = createBoundedJsonValueSnapshot(
|
|
449
|
+
rawOutput,
|
|
450
|
+
contract.policy.maxOutputBytes,
|
|
451
|
+
`${kind} raw output at node ${node.key}`,
|
|
452
|
+
)
|
|
453
|
+
const parsedOutput = parseCodeBoundary(
|
|
454
|
+
contract.outputSchema as z.ZodType<unknown>,
|
|
455
|
+
boundedRawOutput.value,
|
|
456
|
+
`${kind} output at node ${node.key}`,
|
|
457
|
+
)
|
|
458
|
+
return Object.freeze({
|
|
459
|
+
input: boundedInput,
|
|
460
|
+
output: createBoundedJsonSnapshot(
|
|
461
|
+
parsedOutput,
|
|
462
|
+
contract.policy.maxOutputBytes,
|
|
463
|
+
`${kind} output at node ${node.key}`,
|
|
464
|
+
),
|
|
465
|
+
})
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export async function runBuiltWorkflow<
|
|
469
|
+
Input extends JsonValue,
|
|
470
|
+
Output extends WorkflowOutputValue,
|
|
471
|
+
>(
|
|
472
|
+
built: BuiltWorkflow<Input, Output>,
|
|
473
|
+
options: RunBuiltWorkflowOptions,
|
|
474
|
+
): Promise<WorkflowRunResult<ResolvedWorkflowOutput<Output>>> {
|
|
475
|
+
// Compilation and the public capability check intentionally precede every
|
|
476
|
+
// host callback, including host-owned admission.
|
|
477
|
+
const compilation = compileWorkflowGraph({
|
|
478
|
+
graph: built.graph,
|
|
479
|
+
limits: options.limits,
|
|
480
|
+
projection: PUBLIC_WORKFLOW_REGISTRY_PROJECTION,
|
|
481
|
+
})
|
|
482
|
+
for (const node of compilation.graph.nodes) publicOperationNode(node)
|
|
483
|
+
const host = createSlopcameraCodeHost(options.host)
|
|
484
|
+
const context = Object.freeze({
|
|
485
|
+
signal: options.signal ?? new AbortController().signal,
|
|
486
|
+
})
|
|
487
|
+
throwIfAborted(context.signal)
|
|
488
|
+
|
|
489
|
+
const nodes = new Map(compilation.graph.nodes.map(node => [node.key, node]))
|
|
490
|
+
const values = new Map<string, JsonValue>()
|
|
491
|
+
const receipts: WorkflowNodeReceipt[] = []
|
|
492
|
+
for (const wave of compilation.topologicalWaves) {
|
|
493
|
+
const outcomes = await Promise.all(wave.map(async (nodeKey) => {
|
|
494
|
+
const node = nodes.get(nodeKey)
|
|
495
|
+
if (node === undefined) {
|
|
496
|
+
throw new SlopcameraCodeError(
|
|
497
|
+
"internal",
|
|
498
|
+
`Compiled workflow topology lost node ${nodeKey}.`,
|
|
499
|
+
{ nodeKey },
|
|
500
|
+
)
|
|
501
|
+
}
|
|
502
|
+
publicOperationNode(node)
|
|
503
|
+
try {
|
|
504
|
+
return {
|
|
505
|
+
executed: await executePublicNode(host, node, values, context),
|
|
506
|
+
kind: "executed",
|
|
507
|
+
node,
|
|
508
|
+
} as const
|
|
509
|
+
} catch (error) {
|
|
510
|
+
return { error, kind: "failed", node } as const
|
|
511
|
+
}
|
|
512
|
+
}))
|
|
513
|
+
// Each callback converts rejection to data, so Promise.all drains the
|
|
514
|
+
// complete dispatched wave before the runtime returns an error.
|
|
515
|
+
for (const outcome of outcomes) {
|
|
516
|
+
if (outcome.kind !== "executed") continue
|
|
517
|
+
values.set(outcome.node.key, outcome.executed.output.value)
|
|
518
|
+
receipts.push(createNodeReceipt(
|
|
519
|
+
receipts.length,
|
|
520
|
+
outcome.node.key,
|
|
521
|
+
outcome.node.executor.operation.kind,
|
|
522
|
+
outcome.executed.input.sha256,
|
|
523
|
+
outcome.executed.output.sha256,
|
|
524
|
+
))
|
|
525
|
+
}
|
|
526
|
+
const failure = outcomes.find(
|
|
527
|
+
(outcome): outcome is Extract<typeof outcome, { readonly kind: "failed" }> => (
|
|
528
|
+
outcome.kind === "failed"
|
|
529
|
+
),
|
|
530
|
+
)
|
|
531
|
+
if (failure !== undefined) {
|
|
532
|
+
throw workflowNodeFailure(failure.error, failure.node, receipts)
|
|
533
|
+
}
|
|
534
|
+
if (context.signal.aborted) {
|
|
535
|
+
const cause = new SlopcameraCodeError(
|
|
536
|
+
"cancelled",
|
|
537
|
+
"Workflow execution was cancelled.",
|
|
538
|
+
)
|
|
539
|
+
throw workflowRunFailure(
|
|
540
|
+
cause,
|
|
541
|
+
"Workflow execution was cancelled after the current wave settled.",
|
|
542
|
+
receipts,
|
|
543
|
+
)
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
let output: ResolvedWorkflowOutput<Output>
|
|
547
|
+
try {
|
|
548
|
+
output = createBoundedJsonValueSnapshot(
|
|
549
|
+
resolveValue(compilation.graph.outputs, values),
|
|
550
|
+
MAX_WORKFLOW_RESULT_BYTES,
|
|
551
|
+
"workflow output",
|
|
552
|
+
{
|
|
553
|
+
maximumDepth: MAX_WORKFLOW_RESULT_DEPTH,
|
|
554
|
+
maximumValues: MAX_WORKFLOW_RESULT_VALUES,
|
|
555
|
+
},
|
|
556
|
+
).value as ResolvedWorkflowOutput<Output>
|
|
557
|
+
} catch (error) {
|
|
558
|
+
throw workflowRunFailure(
|
|
559
|
+
error,
|
|
560
|
+
`Workflow output resolution failed: ${slopcameraCodeErrorMessage(error)}`,
|
|
561
|
+
receipts,
|
|
562
|
+
)
|
|
563
|
+
}
|
|
564
|
+
return Object.freeze({
|
|
565
|
+
compilation,
|
|
566
|
+
output,
|
|
567
|
+
receipts: Object.freeze(receipts),
|
|
568
|
+
})
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
export async function runWorkflow<
|
|
572
|
+
Input,
|
|
573
|
+
Output extends WorkflowOutputValue,
|
|
574
|
+
>(
|
|
575
|
+
definition: WorkflowDefinition<Input, Output>,
|
|
576
|
+
input: unknown,
|
|
577
|
+
options: RunBuiltWorkflowOptions,
|
|
578
|
+
): Promise<WorkflowRunResult<ResolvedWorkflowOutput<Output>>> {
|
|
579
|
+
return await runBuiltWorkflow(buildWorkflow(definition, input), options)
|
|
580
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha2.js"
|
|
2
|
+
import { bytesToHex } from "@noble/hashes/utils.js"
|
|
3
|
+
|
|
4
|
+
const UTF8_ENCODER = new TextEncoder()
|
|
5
|
+
|
|
6
|
+
export interface Sha256HexHasher {
|
|
7
|
+
readonly digestHex: () => string
|
|
8
|
+
readonly update: (input: string | Uint8Array) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Native on Bun, with the same synchronous audited fallback for browsers. */
|
|
12
|
+
export function createSha256HexHasher(): Sha256HexHasher {
|
|
13
|
+
if (typeof Bun !== "undefined") {
|
|
14
|
+
const hasher = new Bun.CryptoHasher("sha256")
|
|
15
|
+
return {
|
|
16
|
+
digestHex: () => hasher.digest("hex"),
|
|
17
|
+
update: (input) => {
|
|
18
|
+
hasher.update(input)
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const hasher = sha256.create()
|
|
23
|
+
return {
|
|
24
|
+
digestHex: () => bytesToHex(hasher.digest()),
|
|
25
|
+
update: (input) => {
|
|
26
|
+
hasher.update(typeof input === "string" ? UTF8_ENCODER.encode(input) : input)
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Synchronous SHA-256 over exact UTF-8 bytes in Bun, Node, and browsers. */
|
|
32
|
+
export function sha256Hex(input: string): string {
|
|
33
|
+
const hasher = createSha256HexHasher()
|
|
34
|
+
hasher.update(input)
|
|
35
|
+
return hasher.digestHex()
|
|
36
|
+
}
|