@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,867 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
RepositoryRelativePathSchema,
|
|
5
|
+
Sha256Schema,
|
|
6
|
+
} from "../contracts";
|
|
7
|
+
import {
|
|
8
|
+
canonicalJson,
|
|
9
|
+
sha256Hex,
|
|
10
|
+
} from "../core/canonical-json";
|
|
11
|
+
import type { ApplicationContext } from "./context";
|
|
12
|
+
import { ApplicationError } from "./errors";
|
|
13
|
+
import type { OperationKind } from "./operation";
|
|
14
|
+
|
|
15
|
+
const GATEWAY_REQUEST_ID_DOMAIN = "studio.gateway-operation-request/v1";
|
|
16
|
+
const MAXIMUM_GATEWAY_OUTPUT_BYTES = 1024 * 1024 * 1024;
|
|
17
|
+
const MAXIMUM_GATEWAY_OUTPUTS = 32;
|
|
18
|
+
const MAXIMUM_GATEWAY_RECEIPT_BYTES = 256 * 1024;
|
|
19
|
+
const MAXIMUM_IMAGE_INPUT_BYTES = 50 * 1024 * 1024;
|
|
20
|
+
const MAXIMUM_IMAGE_INPUT_TOTAL_BYTES = 200 * 1024 * 1024;
|
|
21
|
+
const MAXIMUM_REFERENCE_INPUT_BYTES = 256 * 1024 * 1024;
|
|
22
|
+
const MAXIMUM_REFERENCE_INPUT_TOTAL_BYTES = 512 * 1024 * 1024;
|
|
23
|
+
|
|
24
|
+
const BoundedTextSchema = z.string().max(100_000).refine(
|
|
25
|
+
value => [...value].every((character) => {
|
|
26
|
+
const codePoint = character.codePointAt(0);
|
|
27
|
+
return codePoint !== undefined
|
|
28
|
+
&& codePoint !== 0
|
|
29
|
+
&& (
|
|
30
|
+
codePoint >= 32
|
|
31
|
+
|| codePoint === 9
|
|
32
|
+
|| codePoint === 10
|
|
33
|
+
|| codePoint === 13
|
|
34
|
+
);
|
|
35
|
+
}),
|
|
36
|
+
"Gateway text contains a disallowed control character.",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const GatewayModelIdSchema = z.string()
|
|
40
|
+
.min(3)
|
|
41
|
+
.max(256)
|
|
42
|
+
.regex(
|
|
43
|
+
/^[^\s/]+(?:\/[^\s/]+)+$/u,
|
|
44
|
+
"Gateway model IDs must be nonempty slash-separated identifiers.",
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
export const GatewayMediaTypeSchema = z.string()
|
|
48
|
+
.min(3)
|
|
49
|
+
.max(128)
|
|
50
|
+
.regex(
|
|
51
|
+
/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u,
|
|
52
|
+
"Expected a normalized media type.",
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
export const GatewayProviderOptionsReferenceSchema = z.strictObject({
|
|
56
|
+
namespaces: z.array(
|
|
57
|
+
z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/u),
|
|
58
|
+
).max(64),
|
|
59
|
+
sha256: Sha256Schema,
|
|
60
|
+
}).superRefine((reference, context) => {
|
|
61
|
+
const canonical = [...new Set(reference.namespaces)].sort((left, right) =>
|
|
62
|
+
left.localeCompare(right));
|
|
63
|
+
if (
|
|
64
|
+
canonical.length !== reference.namespaces.length
|
|
65
|
+
|| canonical.some((namespace, index) =>
|
|
66
|
+
namespace !== reference.namespaces[index])
|
|
67
|
+
) {
|
|
68
|
+
context.addIssue({
|
|
69
|
+
code: "custom",
|
|
70
|
+
message: "Provider-option namespaces must be unique and canonically sorted.",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const GatewayMediaSourceReferenceSchema = z.strictObject({
|
|
76
|
+
bytes: z.number().int().safe().positive().max(512 * 1024 * 1024),
|
|
77
|
+
facts: z.strictObject({
|
|
78
|
+
durationSeconds: z.number().finite().positive().max(1_000_000_000).optional(),
|
|
79
|
+
height: z.number().int().safe().positive().max(1_000_000).optional(),
|
|
80
|
+
width: z.number().int().safe().positive().max(1_000_000).optional(),
|
|
81
|
+
}).optional(),
|
|
82
|
+
mediaType: GatewayMediaTypeSchema,
|
|
83
|
+
path: RepositoryRelativePathSchema,
|
|
84
|
+
sha256: Sha256Schema,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const GatewayCommonRequestFields = {
|
|
88
|
+
model: GatewayModelIdSchema,
|
|
89
|
+
providerOptions: GatewayProviderOptionsReferenceSchema.optional(),
|
|
90
|
+
timeoutMs: z.number().int().safe().positive().max(30 * 60_000).optional(),
|
|
91
|
+
} as const;
|
|
92
|
+
|
|
93
|
+
export const GatewayImageOperationInputSchema = z.strictObject({
|
|
94
|
+
...GatewayCommonRequestFields,
|
|
95
|
+
aspectRatio: z.string()
|
|
96
|
+
.max(32)
|
|
97
|
+
.regex(/^[1-9]\d{0,5}:[1-9]\d{0,5}$/u)
|
|
98
|
+
.optional(),
|
|
99
|
+
images: z.array(GatewayMediaSourceReferenceSchema).max(32).optional(),
|
|
100
|
+
mask: GatewayMediaSourceReferenceSchema.optional(),
|
|
101
|
+
maxImagesPerCall: z.number().int().safe().min(1).max(32).optional(),
|
|
102
|
+
maxOutputTokens: z.number().int().safe().min(1).max(1_000_000).optional(),
|
|
103
|
+
n: z.number().int().safe().min(1).max(32).optional(),
|
|
104
|
+
prompt: BoundedTextSchema,
|
|
105
|
+
seed: z.number().int().safe().min(0).max(0xffff_ffff).optional(),
|
|
106
|
+
size: z.string()
|
|
107
|
+
.max(32)
|
|
108
|
+
.regex(/^[1-9]\d{0,5}x[1-9]\d{0,5}$/u)
|
|
109
|
+
.optional(),
|
|
110
|
+
stopSequences: z.array(z.string().min(1).max(1_024)).max(64).optional(),
|
|
111
|
+
temperature: z.number().finite().min(0).max(100).optional(),
|
|
112
|
+
}).superRefine((input, context) => {
|
|
113
|
+
const images = input.images ?? [];
|
|
114
|
+
const totalBytes = images.reduce(
|
|
115
|
+
(total, image) => total + image.bytes,
|
|
116
|
+
input.mask?.bytes ?? 0,
|
|
117
|
+
);
|
|
118
|
+
if (totalBytes > MAXIMUM_IMAGE_INPUT_TOTAL_BYTES) {
|
|
119
|
+
context.addIssue({
|
|
120
|
+
code: "custom",
|
|
121
|
+
message: "Gateway image inputs exceed the 200 MiB aggregate bound.",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (
|
|
125
|
+
images.some(image => image.bytes > MAXIMUM_IMAGE_INPUT_BYTES)
|
|
126
|
+
|| (
|
|
127
|
+
input.mask !== undefined
|
|
128
|
+
&& input.mask.bytes > MAXIMUM_IMAGE_INPUT_BYTES
|
|
129
|
+
)
|
|
130
|
+
) {
|
|
131
|
+
context.addIssue({
|
|
132
|
+
code: "custom",
|
|
133
|
+
message: "An individual Gateway image input exceeds the 50 MiB bound.",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (images.some(image => !image.mediaType.startsWith("image/"))) {
|
|
137
|
+
context.addIssue({
|
|
138
|
+
code: "custom",
|
|
139
|
+
message: "Gateway image references must use image media types.",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (
|
|
143
|
+
input.mask !== undefined
|
|
144
|
+
&& !input.mask.mediaType.startsWith("image/")
|
|
145
|
+
) {
|
|
146
|
+
context.addIssue({
|
|
147
|
+
code: "custom",
|
|
148
|
+
message: "Gateway image masks must use an image media type.",
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (input.mask !== undefined && images.length === 0) {
|
|
152
|
+
context.addIssue({
|
|
153
|
+
code: "custom",
|
|
154
|
+
message: "A Gateway image mask requires at least one source image.",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (input.size !== undefined && input.aspectRatio !== undefined) {
|
|
158
|
+
context.addIssue({
|
|
159
|
+
code: "custom",
|
|
160
|
+
message: "Gateway image size and aspect ratio are mutually exclusive.",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (
|
|
164
|
+
(input.n ?? 1) > 1
|
|
165
|
+
&& (
|
|
166
|
+
input.maxImagesPerCall === undefined
|
|
167
|
+
|| input.maxImagesPerCall < (input.n ?? 1)
|
|
168
|
+
)
|
|
169
|
+
) {
|
|
170
|
+
context.addIssue({
|
|
171
|
+
code: "custom",
|
|
172
|
+
message: "Multiple Gateway images require a matching per-call bound.",
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
if (input.prompt.trim().length === 0 && images.length === 0) {
|
|
176
|
+
context.addIssue({
|
|
177
|
+
code: "custom",
|
|
178
|
+
message: "A Gateway image request without source images requires a prompt.",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const GatewayVideoFrameSchema = z.strictObject({
|
|
184
|
+
frameType: z.enum(["first_frame", "last_frame"]),
|
|
185
|
+
source: GatewayMediaSourceReferenceSchema,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export const GatewayVideoOperationInputSchema = z.strictObject({
|
|
189
|
+
...GatewayCommonRequestFields,
|
|
190
|
+
aspectRatio: z.string()
|
|
191
|
+
.max(32)
|
|
192
|
+
.regex(/^[1-9]\d{0,5}:[1-9]\d{0,5}$/u)
|
|
193
|
+
.optional(),
|
|
194
|
+
durationSeconds: z.number().finite().min(0.01).max(3_600).optional(),
|
|
195
|
+
fps: z.number().finite().min(0.01).max(1_000).optional(),
|
|
196
|
+
frames: z.array(GatewayVideoFrameSchema).max(32).optional(),
|
|
197
|
+
generateAudio: z.boolean().optional(),
|
|
198
|
+
maxVideosPerCall: z.number().int().safe().min(1).max(32).optional(),
|
|
199
|
+
n: z.number().int().safe().min(1).max(32).optional(),
|
|
200
|
+
prompt: BoundedTextSchema,
|
|
201
|
+
promptImage: GatewayMediaSourceReferenceSchema.optional(),
|
|
202
|
+
references: z.array(GatewayMediaSourceReferenceSchema).max(32).optional(),
|
|
203
|
+
resolution: z.string()
|
|
204
|
+
.max(32)
|
|
205
|
+
.regex(/^(?:[1-9]\d{0,5}x[1-9]\d{0,5}|[1-9]\d{2,4}p|[1-9]\d{0,2}k)$/iu)
|
|
206
|
+
.optional(),
|
|
207
|
+
seed: z.number().int().safe().min(0).max(0xffff_ffff).optional(),
|
|
208
|
+
}).superRefine((input, context) => {
|
|
209
|
+
const frames = input.frames ?? [];
|
|
210
|
+
const references = input.references ?? [];
|
|
211
|
+
if (references.reduce(
|
|
212
|
+
(total, source) => total + source.bytes,
|
|
213
|
+
0,
|
|
214
|
+
) > MAXIMUM_REFERENCE_INPUT_TOTAL_BYTES) {
|
|
215
|
+
context.addIssue({
|
|
216
|
+
code: "custom",
|
|
217
|
+
message: "Gateway video inputs exceed the 512 MiB aggregate bound.",
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (
|
|
221
|
+
references.some(reference =>
|
|
222
|
+
reference.bytes > MAXIMUM_REFERENCE_INPUT_BYTES)
|
|
223
|
+
) {
|
|
224
|
+
context.addIssue({
|
|
225
|
+
code: "custom",
|
|
226
|
+
message: "A Gateway video reference exceeds the 256 MiB bound.",
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (
|
|
230
|
+
[
|
|
231
|
+
...(input.promptImage === undefined ? [] : [input.promptImage]),
|
|
232
|
+
...frames.map(frame => frame.source),
|
|
233
|
+
].some(source => source.bytes > MAXIMUM_IMAGE_INPUT_BYTES)
|
|
234
|
+
) {
|
|
235
|
+
context.addIssue({
|
|
236
|
+
code: "custom",
|
|
237
|
+
message: "A Gateway video image input exceeds the 50 MiB bound.",
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (
|
|
241
|
+
frames.reduce((total, frame) => total + frame.source.bytes, 0)
|
|
242
|
+
> MAXIMUM_IMAGE_INPUT_TOTAL_BYTES
|
|
243
|
+
) {
|
|
244
|
+
context.addIssue({
|
|
245
|
+
code: "custom",
|
|
246
|
+
message: "Gateway video frames exceed the 200 MiB aggregate bound.",
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (
|
|
250
|
+
input.promptImage !== undefined
|
|
251
|
+
&& !input.promptImage.mediaType.startsWith("image/")
|
|
252
|
+
) {
|
|
253
|
+
context.addIssue({
|
|
254
|
+
code: "custom",
|
|
255
|
+
message: "A Gateway video prompt image must use an image media type.",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if (frames.some(frame => !frame.source.mediaType.startsWith("image/"))) {
|
|
259
|
+
context.addIssue({
|
|
260
|
+
code: "custom",
|
|
261
|
+
message: "Gateway video frames must use image media types.",
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
if (new Set(frames.map(frame => frame.frameType)).size !== frames.length) {
|
|
265
|
+
context.addIssue({
|
|
266
|
+
code: "custom",
|
|
267
|
+
message: "Gateway video frame roles must be unique.",
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
if (
|
|
271
|
+
references.some(reference => ![
|
|
272
|
+
"audio/",
|
|
273
|
+
"image/",
|
|
274
|
+
"video/",
|
|
275
|
+
].some(prefix => reference.mediaType.startsWith(prefix)))
|
|
276
|
+
) {
|
|
277
|
+
context.addIssue({
|
|
278
|
+
code: "custom",
|
|
279
|
+
message: "Gateway video references must be image, video, or audio media.",
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
if (frames.length > 0 && references.length > 0) {
|
|
283
|
+
context.addIssue({
|
|
284
|
+
code: "custom",
|
|
285
|
+
message: "Gateway video frames and references are mutually exclusive.",
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
if (
|
|
289
|
+
input.promptImage !== undefined
|
|
290
|
+
&& frames.some(frame => frame.frameType === "first_frame")
|
|
291
|
+
) {
|
|
292
|
+
context.addIssue({
|
|
293
|
+
code: "custom",
|
|
294
|
+
message: "A Gateway video prompt image conflicts with a first frame.",
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (
|
|
298
|
+
frames.some(frame => frame.frameType === "last_frame")
|
|
299
|
+
&& input.promptImage === undefined
|
|
300
|
+
&& !frames.some(frame => frame.frameType === "first_frame")
|
|
301
|
+
) {
|
|
302
|
+
context.addIssue({
|
|
303
|
+
code: "custom",
|
|
304
|
+
message: "A Gateway video last frame requires a first image.",
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (
|
|
308
|
+
(input.n ?? 1) > 1
|
|
309
|
+
&& (
|
|
310
|
+
input.maxVideosPerCall === undefined
|
|
311
|
+
|| input.maxVideosPerCall < (input.n ?? 1)
|
|
312
|
+
)
|
|
313
|
+
) {
|
|
314
|
+
context.addIssue({
|
|
315
|
+
code: "custom",
|
|
316
|
+
message: "Multiple Gateway videos require a matching per-call bound.",
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (
|
|
320
|
+
input.prompt.trim().length === 0
|
|
321
|
+
&& input.promptImage === undefined
|
|
322
|
+
&& frames.length === 0
|
|
323
|
+
&& references.length === 0
|
|
324
|
+
) {
|
|
325
|
+
context.addIssue({
|
|
326
|
+
code: "custom",
|
|
327
|
+
message: "A Gateway video request without media inputs requires a prompt.",
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
export const GatewaySpeechOperationInputSchema = z.strictObject({
|
|
333
|
+
...GatewayCommonRequestFields,
|
|
334
|
+
instructions: BoundedTextSchema.optional(),
|
|
335
|
+
language: z.string().min(1).max(64).optional(),
|
|
336
|
+
outputFormat: z.string()
|
|
337
|
+
.max(64)
|
|
338
|
+
.regex(/^[a-z0-9][a-z0-9._+-]*$/iu)
|
|
339
|
+
.optional(),
|
|
340
|
+
speed: z.number().finite().min(0.01).max(100).optional(),
|
|
341
|
+
text: BoundedTextSchema.min(1),
|
|
342
|
+
voice: z.string().min(1).max(256).optional(),
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
export const GatewayTranscriptionOperationInputSchema = z.strictObject({
|
|
346
|
+
...GatewayCommonRequestFields,
|
|
347
|
+
audio: GatewayMediaSourceReferenceSchema,
|
|
348
|
+
}).superRefine((input, context) => {
|
|
349
|
+
if (!input.audio.mediaType.startsWith("audio/")) {
|
|
350
|
+
context.addIssue({
|
|
351
|
+
code: "custom",
|
|
352
|
+
message: "Gateway transcription input must use an audio media type.",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
if (input.audio.bytes > 256 * 1024 * 1024) {
|
|
356
|
+
context.addIssue({
|
|
357
|
+
code: "custom",
|
|
358
|
+
message: "Gateway transcription input exceeds the 256 MiB bound.",
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
export const GatewayOperationNameSchema = z.enum([
|
|
364
|
+
"image",
|
|
365
|
+
"video",
|
|
366
|
+
"speech",
|
|
367
|
+
"transcription",
|
|
368
|
+
]);
|
|
369
|
+
|
|
370
|
+
export const GatewayPortRequestSchema = z.union([
|
|
371
|
+
z.strictObject({
|
|
372
|
+
operation: z.literal("image"),
|
|
373
|
+
request: GatewayImageOperationInputSchema,
|
|
374
|
+
}),
|
|
375
|
+
z.strictObject({
|
|
376
|
+
operation: z.literal("video"),
|
|
377
|
+
request: GatewayVideoOperationInputSchema,
|
|
378
|
+
}),
|
|
379
|
+
z.strictObject({
|
|
380
|
+
operation: z.literal("speech"),
|
|
381
|
+
request: GatewaySpeechOperationInputSchema,
|
|
382
|
+
}),
|
|
383
|
+
z.strictObject({
|
|
384
|
+
operation: z.literal("transcription"),
|
|
385
|
+
request: GatewayTranscriptionOperationInputSchema,
|
|
386
|
+
}),
|
|
387
|
+
]);
|
|
388
|
+
|
|
389
|
+
export const GatewayRequestIdSchema = z.string()
|
|
390
|
+
.regex(/^gateway_[a-f0-9]{64}$/u);
|
|
391
|
+
|
|
392
|
+
export const GatewayOutputArtifactReferenceSchema = z.strictObject({
|
|
393
|
+
bytes: z.number().int().safe().positive().max(512 * 1024 * 1024),
|
|
394
|
+
mediaType: GatewayMediaTypeSchema,
|
|
395
|
+
path: RepositoryRelativePathSchema,
|
|
396
|
+
sha256: Sha256Schema,
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
export const GatewayReceiptReferenceSchema = z.strictObject({
|
|
400
|
+
bytes: z.number().int().safe().positive().max(MAXIMUM_GATEWAY_RECEIPT_BYTES),
|
|
401
|
+
path: RepositoryRelativePathSchema,
|
|
402
|
+
sha256: Sha256Schema,
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const GatewayOperationResultBaseFields = {
|
|
406
|
+
model: GatewayModelIdSchema,
|
|
407
|
+
outputs: z.array(GatewayOutputArtifactReferenceSchema)
|
|
408
|
+
.min(1)
|
|
409
|
+
.max(MAXIMUM_GATEWAY_OUTPUTS),
|
|
410
|
+
receipt: GatewayReceiptReferenceSchema,
|
|
411
|
+
requestId: GatewayRequestIdSchema,
|
|
412
|
+
} as const;
|
|
413
|
+
|
|
414
|
+
export const GatewayImageOperationResultSchema = z.strictObject({
|
|
415
|
+
...GatewayOperationResultBaseFields,
|
|
416
|
+
operation: z.literal("image"),
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
export const GatewayVideoOperationResultSchema = z.strictObject({
|
|
420
|
+
...GatewayOperationResultBaseFields,
|
|
421
|
+
operation: z.literal("video"),
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
export const GatewaySpeechOperationResultSchema = z.strictObject({
|
|
425
|
+
...GatewayOperationResultBaseFields,
|
|
426
|
+
operation: z.literal("speech"),
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
export const GatewayTranscriptionOperationResultSchema = z.strictObject({
|
|
430
|
+
...GatewayOperationResultBaseFields,
|
|
431
|
+
operation: z.literal("transcription"),
|
|
432
|
+
transcript: z.strictObject({
|
|
433
|
+
characters: z.number().int().safe().nonnegative().max(10_000_000),
|
|
434
|
+
durationSeconds: z.number().finite().nonnegative().max(7 * 24 * 60 * 60),
|
|
435
|
+
language: z.string().min(1).max(64).optional(),
|
|
436
|
+
segments: z.number().int().safe().nonnegative().max(100_000),
|
|
437
|
+
textSha256: Sha256Schema,
|
|
438
|
+
}),
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
export const GatewayOperationResultSchema = z.union([
|
|
442
|
+
GatewayImageOperationResultSchema,
|
|
443
|
+
GatewayVideoOperationResultSchema,
|
|
444
|
+
GatewaySpeechOperationResultSchema,
|
|
445
|
+
GatewayTranscriptionOperationResultSchema,
|
|
446
|
+
]).superRefine((result, context) => {
|
|
447
|
+
if (
|
|
448
|
+
result.outputs.reduce((total, output) => total + output.bytes, 0)
|
|
449
|
+
> MAXIMUM_GATEWAY_OUTPUT_BYTES
|
|
450
|
+
) {
|
|
451
|
+
context.addIssue({
|
|
452
|
+
code: "custom",
|
|
453
|
+
message: "Gateway outputs exceed the 1 GiB aggregate bound.",
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
const identities = result.outputs.map(output => output.sha256);
|
|
457
|
+
if (new Set(identities).size !== identities.length) {
|
|
458
|
+
context.addIssue({
|
|
459
|
+
code: "custom",
|
|
460
|
+
message: "Gateway output content identities must be unique.",
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
const wrongMediaType = result.operation === "image"
|
|
464
|
+
? result.outputs.some(output => !output.mediaType.startsWith("image/"))
|
|
465
|
+
: result.operation === "video"
|
|
466
|
+
? result.outputs.some(output => !output.mediaType.startsWith("video/"))
|
|
467
|
+
: result.operation === "speech"
|
|
468
|
+
? result.outputs.some(output => !output.mediaType.startsWith("audio/"))
|
|
469
|
+
: result.outputs.some(output => ![
|
|
470
|
+
"application/json",
|
|
471
|
+
"application/x-subrip",
|
|
472
|
+
"text/plain",
|
|
473
|
+
"text/vtt",
|
|
474
|
+
].includes(output.mediaType));
|
|
475
|
+
if (wrongMediaType) {
|
|
476
|
+
context.addIssue({
|
|
477
|
+
code: "custom",
|
|
478
|
+
message: `Gateway ${result.operation} output has the wrong media type.`,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
export type GatewayImageOperationInput =
|
|
484
|
+
z.infer<typeof GatewayImageOperationInputSchema>;
|
|
485
|
+
export type GatewayMediaSourceReference =
|
|
486
|
+
z.infer<typeof GatewayMediaSourceReferenceSchema>;
|
|
487
|
+
export type GatewayVideoOperationInput =
|
|
488
|
+
z.infer<typeof GatewayVideoOperationInputSchema>;
|
|
489
|
+
export type GatewaySpeechOperationInput =
|
|
490
|
+
z.infer<typeof GatewaySpeechOperationInputSchema>;
|
|
491
|
+
export type GatewayTranscriptionOperationInput =
|
|
492
|
+
z.infer<typeof GatewayTranscriptionOperationInputSchema>;
|
|
493
|
+
export type GatewayPortRequest = z.infer<typeof GatewayPortRequestSchema>;
|
|
494
|
+
export type GatewayOperationResult = z.infer<
|
|
495
|
+
typeof GatewayOperationResultSchema
|
|
496
|
+
>;
|
|
497
|
+
export type GatewayImageOperationResult =
|
|
498
|
+
z.infer<typeof GatewayImageOperationResultSchema>;
|
|
499
|
+
export type GatewayVideoOperationResult =
|
|
500
|
+
z.infer<typeof GatewayVideoOperationResultSchema>;
|
|
501
|
+
export type GatewaySpeechOperationResult =
|
|
502
|
+
z.infer<typeof GatewaySpeechOperationResultSchema>;
|
|
503
|
+
export type GatewayTranscriptionOperationResult =
|
|
504
|
+
z.infer<typeof GatewayTranscriptionOperationResultSchema>;
|
|
505
|
+
export type GatewayOperationName = GatewayPortRequest["operation"];
|
|
506
|
+
|
|
507
|
+
export const GatewayPortReconciliationSchema = z.union([
|
|
508
|
+
z.strictObject({
|
|
509
|
+
operation: GatewayOperationNameSchema,
|
|
510
|
+
requestId: GatewayRequestIdSchema,
|
|
511
|
+
result: GatewayOperationResultSchema,
|
|
512
|
+
status: z.literal("completed"),
|
|
513
|
+
}),
|
|
514
|
+
z.strictObject({
|
|
515
|
+
operation: GatewayOperationNameSchema,
|
|
516
|
+
requestId: GatewayRequestIdSchema,
|
|
517
|
+
status: z.literal("not-dispatched"),
|
|
518
|
+
}),
|
|
519
|
+
z.strictObject({
|
|
520
|
+
operation: GatewayOperationNameSchema,
|
|
521
|
+
requestId: GatewayRequestIdSchema,
|
|
522
|
+
status: z.literal("dispatched"),
|
|
523
|
+
}),
|
|
524
|
+
z.strictObject({
|
|
525
|
+
failureReceipt: GatewayReceiptReferenceSchema,
|
|
526
|
+
operation: GatewayOperationNameSchema,
|
|
527
|
+
requestId: GatewayRequestIdSchema,
|
|
528
|
+
status: z.literal("failed"),
|
|
529
|
+
}),
|
|
530
|
+
z.strictObject({
|
|
531
|
+
operation: GatewayOperationNameSchema,
|
|
532
|
+
reasonSha256: Sha256Schema,
|
|
533
|
+
requestId: GatewayRequestIdSchema,
|
|
534
|
+
status: z.literal("conflict"),
|
|
535
|
+
}),
|
|
536
|
+
]);
|
|
537
|
+
|
|
538
|
+
export type GatewayPortReconciliation = z.infer<
|
|
539
|
+
typeof GatewayPortReconciliationSchema
|
|
540
|
+
>;
|
|
541
|
+
|
|
542
|
+
export interface GatewayPortDispatch {
|
|
543
|
+
/**
|
|
544
|
+
* Revalidate adapter-owned custody immediately before the durable paid
|
|
545
|
+
* dispatch transition. Rejection must leave the request undispatched.
|
|
546
|
+
* This callback is ephemeral authority, outside request identity and receipts.
|
|
547
|
+
*/
|
|
548
|
+
readonly beforeDispatch?: () => Promise<void>;
|
|
549
|
+
/**
|
|
550
|
+
* Revalidates the workflow fence immediately before generated artifacts are
|
|
551
|
+
* atomically published. The host service must invoke this at its final safe
|
|
552
|
+
* publication boundary.
|
|
553
|
+
*/
|
|
554
|
+
readonly beforePublication: () => Promise<void>;
|
|
555
|
+
/**
|
|
556
|
+
* Callback-scoped machine admission held by the active operation. This is
|
|
557
|
+
* host authority, never part of the persisted or hashed Gateway request.
|
|
558
|
+
*/
|
|
559
|
+
readonly hostResourceLease?: ApplicationContext["hostResourceLease"];
|
|
560
|
+
/**
|
|
561
|
+
* Optional trusted video transport for URL-only providers. The host first
|
|
562
|
+
* verifies this exact local source, then passes an isolated copy of its bytes.
|
|
563
|
+
* The adapter owns upload consent and must expose those same bytes. Returning
|
|
564
|
+
* undefined keeps inline transport. URLs and this hook are never serialized;
|
|
565
|
+
* completed request replay must not invoke the adapter again.
|
|
566
|
+
*/
|
|
567
|
+
readonly resolveSourceUrl?: (
|
|
568
|
+
source: GatewayMediaSourceReference,
|
|
569
|
+
data: Uint8Array,
|
|
570
|
+
signal: AbortSignal,
|
|
571
|
+
) => Promise<string | undefined>;
|
|
572
|
+
/**
|
|
573
|
+
* The host must durably claim this key before crossing the paid-dispatch
|
|
574
|
+
* boundary. Repeating it may return a completed receipt but must never cause
|
|
575
|
+
* another provider call.
|
|
576
|
+
*/
|
|
577
|
+
readonly requestId: string;
|
|
578
|
+
readonly request: GatewayPortRequest;
|
|
579
|
+
readonly signal: AbortSignal;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export interface GatewayPortPrepare {
|
|
583
|
+
readonly hostResourceLease?: ApplicationContext["hostResourceLease"];
|
|
584
|
+
readonly request: GatewayPortRequest;
|
|
585
|
+
readonly signal: AbortSignal;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export interface GatewayPortReconcile {
|
|
589
|
+
/**
|
|
590
|
+
* The host compares this complete authority-free request with the durable
|
|
591
|
+
* dispatch-intent digest. A matching request ID alone is insufficient.
|
|
592
|
+
*/
|
|
593
|
+
readonly request: GatewayPortRequest;
|
|
594
|
+
readonly requestId: string;
|
|
595
|
+
readonly signal: AbortSignal;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Host-owned paid-media boundary.
|
|
600
|
+
*
|
|
601
|
+
* Credentials, cloud consent, and raw provider options remain encapsulated by
|
|
602
|
+
* this port. Only their separately prepared, secret-free integrity summary is
|
|
603
|
+
* present in a request. Implementations must durably distinguish
|
|
604
|
+
* `not-dispatched` from `dispatched`; absence of a result alone is not proof
|
|
605
|
+
* that retrying a paid call is safe.
|
|
606
|
+
*/
|
|
607
|
+
export interface ApplicationGatewayPort {
|
|
608
|
+
dispatch(input: GatewayPortDispatch): Promise<unknown>;
|
|
609
|
+
prepare(input: GatewayPortPrepare): Promise<unknown>;
|
|
610
|
+
reconcile(input: GatewayPortReconcile): Promise<unknown>;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
export interface GatewayRequestIdentity {
|
|
614
|
+
readonly nodeKey: string;
|
|
615
|
+
readonly nodePlanSha256: string;
|
|
616
|
+
readonly operation: GatewayOperationName;
|
|
617
|
+
readonly runId: string;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function gatewayRequestId(
|
|
621
|
+
identity: GatewayRequestIdentity,
|
|
622
|
+
): string {
|
|
623
|
+
if (
|
|
624
|
+
identity.runId.length < 1
|
|
625
|
+
|| identity.runId.length > 256
|
|
626
|
+
|| identity.nodeKey.length < 1
|
|
627
|
+
|| identity.nodeKey.length > 256
|
|
628
|
+
|| identity.runId.includes("\0")
|
|
629
|
+
|| identity.nodeKey.includes("\0")
|
|
630
|
+
) {
|
|
631
|
+
throw new ApplicationError(
|
|
632
|
+
"invalid-data",
|
|
633
|
+
"Gateway request identity is outside its bounded envelope.",
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
const nodePlanSha256 = Sha256Schema.parse(identity.nodePlanSha256);
|
|
637
|
+
return GatewayRequestIdSchema.parse(
|
|
638
|
+
`gateway_${sha256Hex(
|
|
639
|
+
`${GATEWAY_REQUEST_ID_DOMAIN}\0${canonicalJson({
|
|
640
|
+
nodeKey: identity.nodeKey,
|
|
641
|
+
nodePlanSha256,
|
|
642
|
+
operation: identity.operation,
|
|
643
|
+
runId: identity.runId,
|
|
644
|
+
})}`,
|
|
645
|
+
)}`,
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
type GatewayOperationKind = Extract<OperationKind, `gateway.${string}`>;
|
|
650
|
+
|
|
651
|
+
export function gatewayPortRequestForOperation(
|
|
652
|
+
kind: GatewayOperationKind,
|
|
653
|
+
input: unknown,
|
|
654
|
+
): GatewayPortRequest {
|
|
655
|
+
switch (kind) {
|
|
656
|
+
case "gateway.image":
|
|
657
|
+
return GatewayPortRequestSchema.parse({
|
|
658
|
+
operation: "image",
|
|
659
|
+
request: GatewayImageOperationInputSchema.parse(input),
|
|
660
|
+
});
|
|
661
|
+
case "gateway.video":
|
|
662
|
+
return GatewayPortRequestSchema.parse({
|
|
663
|
+
operation: "video",
|
|
664
|
+
request: GatewayVideoOperationInputSchema.parse(input),
|
|
665
|
+
});
|
|
666
|
+
case "gateway.speech":
|
|
667
|
+
return GatewayPortRequestSchema.parse({
|
|
668
|
+
operation: "speech",
|
|
669
|
+
request: GatewaySpeechOperationInputSchema.parse(input),
|
|
670
|
+
});
|
|
671
|
+
case "gateway.transcription":
|
|
672
|
+
return GatewayPortRequestSchema.parse({
|
|
673
|
+
operation: "transcription",
|
|
674
|
+
request: GatewayTranscriptionOperationInputSchema.parse(input),
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function withoutSourceFacts(
|
|
680
|
+
source: z.infer<typeof GatewayMediaSourceReferenceSchema>,
|
|
681
|
+
) {
|
|
682
|
+
return {
|
|
683
|
+
bytes: source.bytes,
|
|
684
|
+
mediaType: source.mediaType,
|
|
685
|
+
path: source.path,
|
|
686
|
+
sha256: source.sha256,
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function gatewayRequestAuthority(request: GatewayPortRequest): unknown {
|
|
691
|
+
switch (request.operation) {
|
|
692
|
+
case "image":
|
|
693
|
+
return {
|
|
694
|
+
...request,
|
|
695
|
+
request: {
|
|
696
|
+
...request.request,
|
|
697
|
+
...(request.request.images === undefined
|
|
698
|
+
? {}
|
|
699
|
+
: {
|
|
700
|
+
images: request.request.images.map(withoutSourceFacts),
|
|
701
|
+
}),
|
|
702
|
+
...(request.request.mask === undefined
|
|
703
|
+
? {}
|
|
704
|
+
: { mask: withoutSourceFacts(request.request.mask) }),
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
case "video":
|
|
708
|
+
return {
|
|
709
|
+
...request,
|
|
710
|
+
request: {
|
|
711
|
+
...request.request,
|
|
712
|
+
...(request.request.frames === undefined
|
|
713
|
+
? {}
|
|
714
|
+
: {
|
|
715
|
+
frames: request.request.frames.map(frame => ({
|
|
716
|
+
...frame,
|
|
717
|
+
source: withoutSourceFacts(frame.source),
|
|
718
|
+
})),
|
|
719
|
+
}),
|
|
720
|
+
...(request.request.promptImage === undefined
|
|
721
|
+
? {}
|
|
722
|
+
: {
|
|
723
|
+
promptImage: withoutSourceFacts(
|
|
724
|
+
request.request.promptImage,
|
|
725
|
+
),
|
|
726
|
+
}),
|
|
727
|
+
...(request.request.references === undefined
|
|
728
|
+
? {}
|
|
729
|
+
: {
|
|
730
|
+
references:
|
|
731
|
+
request.request.references.map(withoutSourceFacts),
|
|
732
|
+
}),
|
|
733
|
+
},
|
|
734
|
+
};
|
|
735
|
+
case "speech":
|
|
736
|
+
return request;
|
|
737
|
+
case "transcription":
|
|
738
|
+
return {
|
|
739
|
+
...request,
|
|
740
|
+
request: {
|
|
741
|
+
...request.request,
|
|
742
|
+
audio: withoutSourceFacts(request.request.audio),
|
|
743
|
+
},
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function requireGatewayPort(
|
|
749
|
+
application: ApplicationContext,
|
|
750
|
+
): ApplicationGatewayPort {
|
|
751
|
+
if (application.gatewayPort === undefined) {
|
|
752
|
+
throw new ApplicationError(
|
|
753
|
+
"unavailable",
|
|
754
|
+
"The host Gateway media port is unavailable.",
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
return application.gatewayPort;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
export async function prepareGatewayOperation(
|
|
761
|
+
application: ApplicationContext,
|
|
762
|
+
input: GatewayPortPrepare,
|
|
763
|
+
): Promise<GatewayPortRequest> {
|
|
764
|
+
const request = GatewayPortRequestSchema.parse(input.request);
|
|
765
|
+
const prepared = GatewayPortRequestSchema.parse(
|
|
766
|
+
await requireGatewayPort(application).prepare({
|
|
767
|
+
...(application.hostResourceLease === undefined
|
|
768
|
+
? {}
|
|
769
|
+
: { hostResourceLease: application.hostResourceLease }),
|
|
770
|
+
request,
|
|
771
|
+
signal: input.signal,
|
|
772
|
+
}),
|
|
773
|
+
);
|
|
774
|
+
if (
|
|
775
|
+
canonicalJson(gatewayRequestAuthority(prepared))
|
|
776
|
+
!== canonicalJson(gatewayRequestAuthority(request))
|
|
777
|
+
) {
|
|
778
|
+
throw new ApplicationError(
|
|
779
|
+
"conflict",
|
|
780
|
+
"Gateway preparation changed request authority instead of deriving media facts.",
|
|
781
|
+
{ operation: request.operation },
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
return prepared;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function assertReconciliationIdentity(
|
|
788
|
+
reconciliation: GatewayPortReconciliation,
|
|
789
|
+
request: GatewayPortRequest,
|
|
790
|
+
requestId: string,
|
|
791
|
+
): void {
|
|
792
|
+
if (
|
|
793
|
+
reconciliation.operation !== request.operation
|
|
794
|
+
|| reconciliation.requestId !== requestId
|
|
795
|
+
|| (
|
|
796
|
+
reconciliation.status === "completed"
|
|
797
|
+
&& (
|
|
798
|
+
reconciliation.result.operation !== request.operation
|
|
799
|
+
|| reconciliation.result.requestId !== requestId
|
|
800
|
+
|| reconciliation.result.model !== request.request.model
|
|
801
|
+
)
|
|
802
|
+
)
|
|
803
|
+
) {
|
|
804
|
+
throw new ApplicationError(
|
|
805
|
+
"conflict",
|
|
806
|
+
"Gateway reconciliation did not match the exact paid request.",
|
|
807
|
+
{ operation: request.operation, requestId },
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
export async function reconcileGatewayOperation(
|
|
813
|
+
application: ApplicationContext,
|
|
814
|
+
input: GatewayPortReconcile,
|
|
815
|
+
): Promise<GatewayPortReconciliation> {
|
|
816
|
+
const request = GatewayPortRequestSchema.parse(input.request);
|
|
817
|
+
const requestId = GatewayRequestIdSchema.parse(input.requestId);
|
|
818
|
+
const reconciliation = GatewayPortReconciliationSchema.parse(
|
|
819
|
+
await requireGatewayPort(application).reconcile({
|
|
820
|
+
request,
|
|
821
|
+
requestId,
|
|
822
|
+
signal: input.signal,
|
|
823
|
+
}),
|
|
824
|
+
);
|
|
825
|
+
assertReconciliationIdentity(reconciliation, request, requestId);
|
|
826
|
+
return reconciliation;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
export async function dispatchGatewayOperation(
|
|
830
|
+
application: ApplicationContext,
|
|
831
|
+
input: GatewayPortDispatch,
|
|
832
|
+
): Promise<GatewayOperationResult> {
|
|
833
|
+
const request = GatewayPortRequestSchema.parse(input.request);
|
|
834
|
+
const requestId = GatewayRequestIdSchema.parse(input.requestId);
|
|
835
|
+
const result = GatewayOperationResultSchema.parse(
|
|
836
|
+
await requireGatewayPort(application).dispatch({
|
|
837
|
+
...(input.beforeDispatch === undefined
|
|
838
|
+
? {}
|
|
839
|
+
: { beforeDispatch: input.beforeDispatch }),
|
|
840
|
+
beforePublication: input.beforePublication,
|
|
841
|
+
...(input.resolveSourceUrl === undefined
|
|
842
|
+
? {}
|
|
843
|
+
: { resolveSourceUrl: input.resolveSourceUrl }),
|
|
844
|
+
...(application.hostResourceLease === undefined
|
|
845
|
+
? {}
|
|
846
|
+
: { hostResourceLease: application.hostResourceLease }),
|
|
847
|
+
request,
|
|
848
|
+
requestId,
|
|
849
|
+
signal: input.signal,
|
|
850
|
+
}),
|
|
851
|
+
);
|
|
852
|
+
if (
|
|
853
|
+
result.requestId !== requestId
|
|
854
|
+
|| result.operation !== request.operation
|
|
855
|
+
|| result.model !== request.request.model
|
|
856
|
+
) {
|
|
857
|
+
throw new ApplicationError(
|
|
858
|
+
"conflict",
|
|
859
|
+
"Gateway dispatch result did not match the exact paid request.",
|
|
860
|
+
{
|
|
861
|
+
operation: request.operation,
|
|
862
|
+
requestId,
|
|
863
|
+
},
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
return result;
|
|
867
|
+
}
|