@instruktlabs/kiln 0.0.0-stage → 1.0.0
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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +19 -0
- package/.claude-plugin/plugin.json +30 -0
- package/.codex-plugin/plugin.json +37 -0
- package/.mcp.json +10 -0
- package/CHANGELOG.md +2579 -0
- package/CONTRIBUTING.md +130 -0
- package/LICENSE +21 -0
- package/README.md +443 -2
- package/THIRD_PARTY_NOTICES.md +62 -0
- package/dist/agent-providers.mjs +310 -0
- package/dist/agent-run.mjs +40433 -0
- package/dist/build.json +215 -0
- package/dist/cli.mjs +48027 -0
- package/dist/evaluator-worker.mjs +27572 -0
- package/dist/mcp-engine.mjs +43537 -0
- package/dist/mcp-server.mjs +2388 -0
- package/dist/viewer/app.js +4281 -0
- package/dist/viewer/chat.html +4409 -0
- package/dist/viewer/index.html +51 -0
- package/dist/viewer/style.css +51 -0
- package/docs/architecture.md +77 -0
- package/docs/cameras.md +181 -0
- package/docs/chatgpt.md +48 -0
- package/docs/collections.md +195 -0
- package/docs/community-exporter.md +95 -0
- package/docs/engine-handoff.md +221 -0
- package/docs/examples.md +171 -0
- package/docs/export-profiles.md +223 -0
- package/docs/extending.md +43 -0
- package/docs/geometry.md +505 -0
- package/docs/google.md +121 -0
- package/docs/harnesses.md +372 -0
- package/docs/install.md +542 -0
- package/docs/material-library.md +133 -0
- package/docs/migration.md +809 -0
- package/docs/programs.md +123 -0
- package/docs/projects-and-live-review.md +94 -0
- package/docs/rendering.md +250 -0
- package/docs/runtime.md +223 -0
- package/docs/sdk.md +137 -0
- package/docs/tools.md +1874 -0
- package/lib/_types/render-service/src/build-identity.d.mts +24 -0
- package/lib/_types/render-service/src/instance.d.mts +47 -0
- package/lib/agent/call-budget.d.ts +55 -0
- package/lib/agent/call-budget.js +52 -0
- package/lib/agent/compaction.d.ts +83 -0
- package/lib/agent/compaction.js +124 -0
- package/lib/agent/concurrency.d.ts +8 -0
- package/lib/agent/concurrency.js +24 -0
- package/lib/agent/diff.d.ts +23 -0
- package/lib/agent/diff.js +124 -0
- package/lib/agent/generate.d.ts +192 -0
- package/lib/agent/generate.js +240 -0
- package/lib/agent/hooks.d.ts +91 -0
- package/lib/agent/hooks.js +158 -0
- package/lib/agent/index.d.ts +42 -0
- package/lib/agent/index.js +30 -0
- package/lib/agent/native-prompt.d.ts +15 -0
- package/lib/agent/native-prompt.js +29 -0
- package/lib/agent/native-workflow.d.ts +4 -0
- package/lib/agent/native-workflow.js +30 -0
- package/lib/agent/providers.d.ts +188 -0
- package/lib/agent/providers.js +392 -0
- package/lib/agent/run.d.ts +72 -0
- package/lib/agent/run.js +245 -0
- package/lib/agent/skill-resources.d.ts +9 -0
- package/lib/agent/skill-resources.js +178 -0
- package/lib/agent/split-tool-result-images.d.ts +33 -0
- package/lib/agent/split-tool-result-images.js +47 -0
- package/lib/agent/stream-start.d.ts +30 -0
- package/lib/agent/stream-start.js +32 -0
- package/lib/agent/tools.d.ts +12 -0
- package/lib/agent/tools.js +77 -0
- package/lib/agent/view-render-timeout.d.ts +40 -0
- package/lib/agent/view-render-timeout.js +71 -0
- package/lib/animation-cubic.d.ts +12 -0
- package/lib/animation-cubic.js +44 -0
- package/lib/animation-spline.d.ts +50 -0
- package/lib/animation-spline.js +168 -0
- package/lib/architecture.d.ts +146 -0
- package/lib/architecture.js +498 -0
- package/lib/arena/adaptive.d.ts +38 -0
- package/lib/arena/adaptive.js +87 -0
- package/lib/arena/bradley-terry.d.ts +63 -0
- package/lib/arena/bradley-terry.js +165 -0
- package/lib/arena/index.d.ts +15 -0
- package/lib/arena/index.js +13 -0
- package/lib/assembly-transform.d.ts +7 -0
- package/lib/assembly-transform.js +21 -0
- package/lib/assembly.d.ts +105 -0
- package/lib/assembly.js +587 -0
- package/lib/asset-catalog.d.ts +13 -0
- package/lib/asset-catalog.js +21 -0
- package/lib/asset-export.d.ts +41 -0
- package/lib/asset-export.js +106 -0
- package/lib/asset-materials-node.d.ts +5 -0
- package/lib/asset-materials-node.js +56 -0
- package/lib/asset-widget.d.ts +10 -0
- package/lib/asset-widget.js +23 -0
- package/lib/assets-node.d.ts +33 -0
- package/lib/assets-node.js +348 -0
- package/lib/assets-resources.d.ts +33 -0
- package/lib/assets-resources.js +109 -0
- package/lib/assets.d.ts +91 -0
- package/lib/assets.js +205 -0
- package/lib/atomic-directory.d.ts +9 -0
- package/lib/atomic-directory.js +31 -0
- package/lib/authoring-style.d.ts +3 -0
- package/lib/authoring-style.js +42 -0
- package/lib/build-cache-node.d.ts +12 -0
- package/lib/build-cache-node.js +87 -0
- package/lib/build-cache.d.ts +24 -0
- package/lib/build-cache.js +229 -0
- package/lib/character.d.ts +132 -0
- package/lib/character.js +612 -0
- package/lib/cli-render-mode.d.ts +31 -0
- package/lib/cli-render-mode.js +204 -0
- package/lib/community-exporter.d.ts +13 -0
- package/lib/community-exporter.js +237 -0
- package/lib/composer/agent/compaction.d.ts +72 -0
- package/lib/composer/agent/compaction.js +103 -0
- package/lib/composer/agent/index.d.ts +25 -0
- package/lib/composer/agent/index.js +19 -0
- package/lib/composer/agent/prompt.d.ts +25 -0
- package/lib/composer/agent/prompt.js +100 -0
- package/lib/composer/agent/run.d.ts +91 -0
- package/lib/composer/agent/run.js +212 -0
- package/lib/composer/agent/tools.d.ts +75 -0
- package/lib/composer/agent/tools.js +643 -0
- package/lib/composer/agent/world-run.d.ts +50 -0
- package/lib/composer/agent/world-run.js +295 -0
- package/lib/composer/agent/world-tools.d.ts +20 -0
- package/lib/composer/agent/world-tools.js +311 -0
- package/lib/composer/collision.d.ts +109 -0
- package/lib/composer/collision.js +339 -0
- package/lib/composer/contract-utils.d.ts +6 -0
- package/lib/composer/contract-utils.js +48 -0
- package/lib/composer/dsl.d.ts +52 -0
- package/lib/composer/dsl.js +147 -0
- package/lib/composer/ground.d.ts +22 -0
- package/lib/composer/ground.js +9 -0
- package/lib/composer/index.d.ts +19 -0
- package/lib/composer/index.js +19 -0
- package/lib/composer/layout.d.ts +106 -0
- package/lib/composer/layout.js +216 -0
- package/lib/composer/model.d.ts +298 -0
- package/lib/composer/model.js +441 -0
- package/lib/composer/overlap.d.ts +89 -0
- package/lib/composer/overlap.js +139 -0
- package/lib/composer/presentation.d.ts +123 -0
- package/lib/composer/presentation.js +256 -0
- package/lib/composer/reachability.d.ts +78 -0
- package/lib/composer/reachability.js +303 -0
- package/lib/composer/render-port.d.ts +293 -0
- package/lib/composer/render-port.js +172 -0
- package/lib/composer/terrain-runtime.d.ts +73 -0
- package/lib/composer/terrain-runtime.js +328 -0
- package/lib/composer/terrain.d.ts +43 -0
- package/lib/composer/terrain.js +49 -0
- package/lib/composer/world-document.d.ts +722 -0
- package/lib/composer/world-document.js +857 -0
- package/lib/composer/world-integration.d.ts +78 -0
- package/lib/composer/world-integration.js +452 -0
- package/lib/composer/world-package.d.ts +312 -0
- package/lib/composer/world-package.js +209 -0
- package/lib/contracts/asset.d.ts +270 -0
- package/lib/contracts/asset.js +1616 -0
- package/lib/contracts/breadth.d.ts +197 -0
- package/lib/contracts/breadth.js +631 -0
- package/lib/contracts/environment.d.ts +13 -0
- package/lib/contracts/environment.js +67 -0
- package/lib/contracts/index.d.ts +5 -0
- package/lib/contracts/index.js +5 -0
- package/lib/contracts/integration.d.ts +94 -0
- package/lib/contracts/integration.js +10 -0
- package/lib/contracts/requirements-migration.d.ts +61 -0
- package/lib/contracts/requirements-migration.js +401 -0
- package/lib/contracts/requirements.d.ts +815 -0
- package/lib/contracts/requirements.js +266 -0
- package/lib/contracts/semantic.d.ts +124 -0
- package/lib/contracts/semantic.js +421 -0
- package/lib/deform.d.ts +31 -0
- package/lib/deform.js +137 -0
- package/lib/deformation-normals.d.ts +3 -0
- package/lib/deformation-normals.js +72 -0
- package/lib/discovery/articulation-recipes.d.ts +6 -0
- package/lib/discovery/articulation-recipes.js +184 -0
- package/lib/discovery/catalog-schema.d.ts +175 -0
- package/lib/discovery/catalog-schema.js +118 -0
- package/lib/discovery/catalog.d.ts +25 -0
- package/lib/discovery/catalog.js +84 -0
- package/lib/discovery/construction-recipes.d.ts +7 -0
- package/lib/discovery/construction-recipes.js +236 -0
- package/lib/discovery/helper-contracts.d.ts +19 -0
- package/lib/discovery/helper-contracts.js +1940 -0
- package/lib/discovery/helper-specs.d.ts +40 -0
- package/lib/discovery/helper-specs.js +800 -0
- package/lib/discovery/index.d.ts +9 -0
- package/lib/discovery/index.js +20 -0
- package/lib/discovery/intents.d.ts +3 -0
- package/lib/discovery/intents.js +117 -0
- package/lib/discovery/lexical-index.d.ts +5 -0
- package/lib/discovery/lexical-index.js +67 -0
- package/lib/discovery/query-schema.d.ts +35 -0
- package/lib/discovery/query-schema.js +66 -0
- package/lib/discovery/recipes.d.ts +6 -0
- package/lib/discovery/recipes.js +191 -0
- package/lib/discovery/service.d.ts +57 -0
- package/lib/discovery/service.js +234 -0
- package/lib/discovery/shapes.d.ts +6 -0
- package/lib/discovery/shapes.js +65 -0
- package/lib/discovery/structural-recipes.d.ts +6 -0
- package/lib/discovery/structural-recipes.js +193 -0
- package/lib/discovery/surface-recipes.d.ts +7 -0
- package/lib/discovery/surface-recipes.js +124 -0
- package/lib/draw-diagnostics.d.ts +57 -0
- package/lib/draw-diagnostics.js +239 -0
- package/lib/edit-buffer.d.ts +86 -0
- package/lib/edit-buffer.js +99 -0
- package/lib/engine-identity.d.ts +44 -0
- package/lib/engine-identity.js +41 -0
- package/lib/evaluator/authoring-diagnostic.d.ts +38 -0
- package/lib/evaluator/authoring-diagnostic.js +128 -0
- package/lib/evaluator/handler.d.ts +14 -0
- package/lib/evaluator/handler.js +86 -0
- package/lib/evaluator/index.d.ts +4 -0
- package/lib/evaluator/index.js +4 -0
- package/lib/evaluator/isolation.d.ts +45 -0
- package/lib/evaluator/isolation.js +362 -0
- package/lib/evaluator/probe-invariants.d.ts +2 -0
- package/lib/evaluator/probe-invariants.js +7 -0
- package/lib/evaluator/probe-worker.d.ts +1 -0
- package/lib/evaluator/probe-worker.js +134 -0
- package/lib/evaluator/protocol.d.ts +105 -0
- package/lib/evaluator/protocol.js +512 -0
- package/lib/evaluator/source-check.d.ts +7 -0
- package/lib/evaluator/source-check.js +57 -0
- package/lib/evaluator/subprocess.d.ts +26 -0
- package/lib/evaluator/subprocess.js +212 -0
- package/lib/evaluator/transport-worker.d.mts +1 -0
- package/lib/evaluator/transport-worker.mjs +3 -0
- package/lib/evaluator/worker-urls.d.ts +6 -0
- package/lib/evaluator/worker-urls.js +12 -0
- package/lib/evaluator/worker.d.ts +1 -0
- package/lib/evaluator/worker.js +26 -0
- package/lib/exporter-node.d.ts +16 -0
- package/lib/exporter-node.js +58 -0
- package/lib/gears.d.ts +68 -0
- package/lib/gears.js +259 -0
- package/lib/geometry-budget.d.ts +15 -0
- package/lib/geometry-budget.js +36 -0
- package/lib/geometry-catalog.d.ts +5 -0
- package/lib/geometry-catalog.js +161 -0
- package/lib/geometry-export.d.ts +11 -0
- package/lib/geometry-export.js +160 -0
- package/lib/geometry.d.ts +46 -0
- package/lib/geometry.js +311 -0
- package/lib/gltf-io.d.ts +38 -0
- package/lib/gltf-io.js +95 -0
- package/lib/implicit.d.ts +20 -0
- package/lib/implicit.js +58 -0
- package/lib/index-policy.d.ts +13 -0
- package/lib/index-policy.js +41 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -0
- package/lib/inspect.d.ts +76 -0
- package/lib/inspect.js +206 -0
- package/lib/kit.d.ts +90 -0
- package/lib/kit.js +459 -0
- package/lib/live-review-node.d.ts +70 -0
- package/lib/live-review-node.js +961 -0
- package/lib/live-review.d.ts +65 -0
- package/lib/live-review.js +1 -0
- package/lib/local-runtime.d.ts +25 -0
- package/lib/local-runtime.js +272 -0
- package/lib/lod-export.d.ts +39 -0
- package/lib/lod-export.js +102 -0
- package/lib/lod.d.ts +56 -0
- package/lib/lod.js +138 -0
- package/lib/material-library-node.d.ts +56 -0
- package/lib/material-library-node.js +402 -0
- package/lib/material-library.d.ts +731 -0
- package/lib/material-library.js +425 -0
- package/lib/material-metrics.d.ts +72 -0
- package/lib/material-metrics.js +276 -0
- package/lib/material-presets.d.ts +29 -0
- package/lib/material-presets.js +181 -0
- package/lib/material-recipe-prompt.d.ts +23 -0
- package/lib/material-recipe-prompt.js +72 -0
- package/lib/material-recipe-runtime.d.ts +31 -0
- package/lib/material-recipe-runtime.js +91 -0
- package/lib/material-recipes.d.ts +131 -0
- package/lib/material-recipes.js +543 -0
- package/lib/material-resources.d.ts +181 -0
- package/lib/material-resources.js +416 -0
- package/lib/material-texture-library.generated.d.ts +1311 -0
- package/lib/material-texture-library.generated.js +11308 -0
- package/lib/metrics.d.ts +98 -0
- package/lib/metrics.js +210 -0
- package/lib/node-visibility.d.ts +31 -0
- package/lib/node-visibility.js +105 -0
- package/lib/open-shell.d.ts +21 -0
- package/lib/open-shell.js +83 -0
- package/lib/ops.d.ts +197 -0
- package/lib/ops.js +630 -0
- package/lib/palette-snap.d.ts +74 -0
- package/lib/palette-snap.js +151 -0
- package/lib/palette.d.ts +75 -0
- package/lib/palette.js +273 -0
- package/lib/portable-material-runtime.d.ts +14 -0
- package/lib/portable-material-runtime.js +81 -0
- package/lib/primitives.d.ts +483 -0
- package/lib/primitives.js +1553 -0
- package/lib/procedural-material-v2.d.ts +189 -0
- package/lib/procedural-material-v2.js +452 -0
- package/lib/procedural-texture.d.ts +90 -0
- package/lib/procedural-texture.js +306 -0
- package/lib/profile.d.ts +190 -0
- package/lib/profile.js +366 -0
- package/lib/program-store-node.d.ts +14 -0
- package/lib/program-store-node.js +137 -0
- package/lib/program-store.d.ts +43 -0
- package/lib/program-store.js +89 -0
- package/lib/project-bundle-node.d.ts +15 -0
- package/lib/project-bundle-node.js +175 -0
- package/lib/project-bundle.d.ts +65 -0
- package/lib/project-bundle.js +322 -0
- package/lib/projects-node.d.ts +17 -0
- package/lib/projects-node.js +227 -0
- package/lib/projects.d.ts +312 -0
- package/lib/projects.js +216 -0
- package/lib/prompt-api.d.ts +32 -0
- package/lib/prompt-api.js +223 -0
- package/lib/qa/architecture-corpus.d.ts +31 -0
- package/lib/qa/architecture-corpus.js +438 -0
- package/lib/qa/architecture-repairs.d.ts +17 -0
- package/lib/qa/architecture-repairs.js +73 -0
- package/lib/qa/architecture.d.ts +56 -0
- package/lib/qa/architecture.js +985 -0
- package/lib/qa/benchmark-fixtures.d.ts +42 -0
- package/lib/qa/benchmark-fixtures.js +191 -0
- package/lib/qa/breadth-corpus.d.ts +17 -0
- package/lib/qa/breadth-corpus.js +125 -0
- package/lib/qa/breadth-evidence.d.ts +18 -0
- package/lib/qa/breadth-evidence.js +514 -0
- package/lib/qa/breadth-final.d.ts +46 -0
- package/lib/qa/breadth-final.js +359 -0
- package/lib/qa/breadth.d.ts +66 -0
- package/lib/qa/breadth.js +539 -0
- package/lib/qa/character-advisory.d.ts +7 -0
- package/lib/qa/character-advisory.js +488 -0
- package/lib/qa/character-repairs.d.ts +11 -0
- package/lib/qa/character-repairs.js +68 -0
- package/lib/qa/character-vehicle-corpus.d.ts +32 -0
- package/lib/qa/character-vehicle-corpus.js +525 -0
- package/lib/qa/character.d.ts +66 -0
- package/lib/qa/character.js +712 -0
- package/lib/qa/corpus.d.ts +185 -0
- package/lib/qa/corpus.js +396 -0
- package/lib/qa/environment.d.ts +44 -0
- package/lib/qa/environment.js +725 -0
- package/lib/qa/geometry-relations.d.ts +94 -0
- package/lib/qa/geometry-relations.js +552 -0
- package/lib/qa/gltf.d.ts +29 -0
- package/lib/qa/gltf.js +66 -0
- package/lib/qa/index.d.ts +32 -0
- package/lib/qa/index.js +34 -0
- package/lib/qa/lod.d.ts +14 -0
- package/lib/qa/lod.js +25 -0
- package/lib/qa/material.d.ts +5 -0
- package/lib/qa/material.js +223 -0
- package/lib/qa/part-connectivity.d.ts +73 -0
- package/lib/qa/part-connectivity.js +216 -0
- package/lib/qa/prop-environment-prompt.d.ts +6 -0
- package/lib/qa/prop-environment-prompt.js +43 -0
- package/lib/qa/prop-helper-policy.d.ts +37 -0
- package/lib/qa/prop-helper-policy.js +65 -0
- package/lib/qa/prop.d.ts +44 -0
- package/lib/qa/prop.js +702 -0
- package/lib/qa/reference-comparison.d.ts +183 -0
- package/lib/qa/reference-comparison.js +420 -0
- package/lib/qa/registry.d.ts +159 -0
- package/lib/qa/registry.js +406 -0
- package/lib/qa/requirements-applicability.d.ts +33 -0
- package/lib/qa/requirements-applicability.js +189 -0
- package/lib/qa/requirements-report.d.ts +38 -0
- package/lib/qa/requirements-report.js +202 -0
- package/lib/qa/requirements-run.d.ts +20 -0
- package/lib/qa/requirements-run.js +370 -0
- package/lib/qa/run.d.ts +54 -0
- package/lib/qa/run.js +240 -0
- package/lib/qa/self-intersection.d.ts +157 -0
- package/lib/qa/self-intersection.js +633 -0
- package/lib/qa/sweep.d.ts +4 -0
- package/lib/qa/sweep.js +65 -0
- package/lib/qa/types.d.ts +90 -0
- package/lib/qa/types.js +81 -0
- package/lib/qa/universal.d.ts +14 -0
- package/lib/qa/universal.js +398 -0
- package/lib/qa/vegetation-corpus.d.ts +18 -0
- package/lib/qa/vegetation-corpus.js +304 -0
- package/lib/qa/vegetation.d.ts +133 -0
- package/lib/qa/vegetation.js +933 -0
- package/lib/qa/vehicle-advisory.d.ts +8 -0
- package/lib/qa/vehicle-advisory.js +395 -0
- package/lib/qa/vehicle.d.ts +19 -0
- package/lib/qa/vehicle.js +594 -0
- package/lib/rebuild-options.d.ts +31 -0
- package/lib/rebuild-options.js +13 -0
- package/lib/render-capabilities.d.ts +25 -0
- package/lib/render-capabilities.js +100 -0
- package/lib/render-service-client.d.ts +59 -0
- package/lib/render-service-client.js +194 -0
- package/lib/render-service-host.d.ts +44 -0
- package/lib/render-service-host.js +236 -0
- package/lib/render-service-windows.d.ts +12 -0
- package/lib/render-service-windows.js +72 -0
- package/lib/render.d.ts +565 -0
- package/lib/render.js +1978 -0
- package/lib/requirements-assets.d.ts +6 -0
- package/lib/requirements-assets.js +33 -0
- package/lib/requirements-context.d.ts +1658 -0
- package/lib/requirements-context.js +126 -0
- package/lib/requirements-identity.d.ts +3 -0
- package/lib/requirements-identity.js +38 -0
- package/lib/requirements-json.d.ts +12 -0
- package/lib/requirements-json.js +58 -0
- package/lib/requirements-store.d.ts +42 -0
- package/lib/requirements-store.js +86 -0
- package/lib/requirements.d.ts +4 -0
- package/lib/requirements.js +4 -0
- package/lib/revision-comparison.d.ts +85 -0
- package/lib/revision-comparison.js +334 -0
- package/lib/rig-export.d.ts +5 -0
- package/lib/rig-export.js +19 -0
- package/lib/rigid-merge.d.ts +90 -0
- package/lib/rigid-merge.js +585 -0
- package/lib/runtime-identity.d.ts +20 -0
- package/lib/runtime-identity.js +193 -0
- package/lib/solids.d.ts +29 -0
- package/lib/solids.js +523 -0
- package/lib/source-bindings.d.ts +6 -0
- package/lib/source-bindings.js +96 -0
- package/lib/source-runtime-checks.d.ts +14 -0
- package/lib/source-runtime-checks.js +169 -0
- package/lib/sweep-analysis.d.ts +22 -0
- package/lib/sweep-analysis.js +109 -0
- package/lib/sweep.d.ts +34 -0
- package/lib/sweep.js +347 -0
- package/lib/texture-bake.d.ts +125 -0
- package/lib/texture-bake.js +395 -0
- package/lib/texture-contract.d.ts +3 -0
- package/lib/texture-contract.js +10 -0
- package/lib/texture-resolver.d.ts +22 -0
- package/lib/texture-resolver.js +28 -0
- package/lib/textures.d.ts +90 -0
- package/lib/textures.js +240 -0
- package/lib/tools/actions.d.ts +35 -0
- package/lib/tools/actions.js +69 -0
- package/lib/tools/capture-input.d.ts +373 -0
- package/lib/tools/capture-input.js +193 -0
- package/lib/tools/discovery.d.ts +3 -0
- package/lib/tools/discovery.js +177 -0
- package/lib/tools/materials.d.ts +29 -0
- package/lib/tools/materials.js +168 -0
- package/lib/tools/preview-fidelity.d.ts +6 -0
- package/lib/tools/preview-fidelity.js +23 -0
- package/lib/tools/program-artifacts.d.ts +30 -0
- package/lib/tools/program-artifacts.js +76 -0
- package/lib/tools/programs.d.ts +9 -0
- package/lib/tools/programs.js +151 -0
- package/lib/tools/projects.d.ts +27 -0
- package/lib/tools/projects.js +98 -0
- package/lib/tools/registry.d.ts +792 -0
- package/lib/tools/registry.js +2123 -0
- package/lib/tools/review-detail.d.ts +106 -0
- package/lib/tools/review-detail.js +740 -0
- package/lib/tools/review.d.ts +40 -0
- package/lib/tools/review.js +230 -0
- package/lib/tools/skill-resource.d.ts +8 -0
- package/lib/tools/skill-resource.js +1 -0
- package/lib/tools/workspace.d.ts +8 -0
- package/lib/tools/workspace.js +87 -0
- package/lib/user-data-extras.d.ts +40 -0
- package/lib/user-data-extras.js +158 -0
- package/lib/user-data-validation.d.ts +18 -0
- package/lib/user-data-validation.js +201 -0
- package/lib/uv-project.d.ts +14 -0
- package/lib/uv-project.js +145 -0
- package/lib/uv-shapes.d.ts +11 -0
- package/lib/uv-shapes.js +48 -0
- package/lib/uv.d.ts +39 -0
- package/lib/uv.js +216 -0
- package/lib/validation.d.ts +90 -0
- package/lib/validation.js +1099 -0
- package/lib/vehicle.d.ts +128 -0
- package/lib/vehicle.js +487 -0
- package/lib/views/annotate.d.ts +41 -0
- package/lib/views/annotate.js +131 -0
- package/lib/views/architecture.d.ts +22 -0
- package/lib/views/architecture.js +55 -0
- package/lib/views/background.d.ts +54 -0
- package/lib/views/background.js +65 -0
- package/lib/views/camera-capture.d.ts +15 -0
- package/lib/views/camera-capture.js +101 -0
- package/lib/views/camera.d.ts +106 -0
- package/lib/views/camera.js +488 -0
- package/lib/views/capture-cache.d.ts +48 -0
- package/lib/views/capture-cache.js +239 -0
- package/lib/views/capture-limits.d.ts +19 -0
- package/lib/views/capture-limits.js +61 -0
- package/lib/views/capture.d.ts +124 -0
- package/lib/views/capture.js +210 -0
- package/lib/views/character-capture.d.ts +20 -0
- package/lib/views/character-capture.js +180 -0
- package/lib/views/character.d.ts +64 -0
- package/lib/views/character.js +176 -0
- package/lib/views/diagnostic.d.ts +90 -0
- package/lib/views/diagnostic.js +627 -0
- package/lib/views/evidence-history.d.ts +13 -0
- package/lib/views/evidence-history.js +131 -0
- package/lib/views/glb.d.ts +36 -0
- package/lib/views/glb.js +524 -0
- package/lib/views/grid.d.ts +46 -0
- package/lib/views/grid.js +81 -0
- package/lib/views/index.d.ts +257 -0
- package/lib/views/index.js +624 -0
- package/lib/views/inspect.d.ts +110 -0
- package/lib/views/inspect.js +195 -0
- package/lib/views/lod.d.ts +30 -0
- package/lib/views/lod.js +79 -0
- package/lib/views/measurement.d.ts +47 -0
- package/lib/views/measurement.js +60 -0
- package/lib/views/part-placement.d.ts +25 -0
- package/lib/views/part-placement.js +26 -0
- package/lib/views/png.d.ts +23 -0
- package/lib/views/png.js +162 -0
- package/lib/views/port.d.ts +74 -0
- package/lib/views/port.js +250 -0
- package/lib/views/pose.d.ts +113 -0
- package/lib/views/pose.js +433 -0
- package/lib/views/raster.d.ts +164 -0
- package/lib/views/raster.js +508 -0
- package/lib/views/renderer-id.d.ts +11 -0
- package/lib/views/renderer-id.js +29 -0
- package/lib/views/scene-raster.d.ts +41 -0
- package/lib/views/scene-raster.js +84 -0
- package/lib/views/surface-distance.d.ts +51 -0
- package/lib/views/surface-distance.js +343 -0
- package/lib/views/vehicle.d.ts +57 -0
- package/lib/views/vehicle.js +288 -0
- package/lib/wall-panels.d.ts +38 -0
- package/lib/wall-panels.js +99 -0
- package/lib/widget-transfer.d.ts +12 -0
- package/lib/widget-transfer.js +117 -0
- package/lib/workspace-location.d.ts +6 -0
- package/lib/workspace-location.js +16 -0
- package/lib/workspace-node.d.ts +15 -0
- package/lib/workspace-node.js +74 -0
- package/lib/workspace.d.ts +26 -0
- package/lib/workspace.js +22 -0
- package/lib/written-nodes.d.ts +10 -0
- package/lib/written-nodes.js +32 -0
- package/package.json +385 -4
- package/plugin.json +16 -0
- package/plugins/kiln-engine/.claude-plugin/plugin.json +18 -0
- package/plugins/kiln-engine/LICENSE +21 -0
- package/plugins/kiln-engine/README.md +25 -0
- package/plugins/kiln-engine/package-provenance.json +15 -0
- package/plugins/kiln-engine/plugin.json +38 -0
- package/plugins/kiln-engine/runtime.json +4 -0
- package/plugins/kiln-engine/scripts/setup-workspace.mjs +337 -0
- package/plugins/kiln-engine/skills/kiln-setup-workspace/SKILL.md +108 -0
- package/plugins/kiln-engine/skills/kiln-setup-workspace/references/plugin-install.md +66 -0
- package/render-service/README.md +139 -0
- package/render-service/package-lock.json +72 -0
- package/render-service/package.json +22 -0
- package/render-service/src/backdrops.mjs +26 -0
- package/render-service/src/bind-policy.mjs +80 -0
- package/render-service/src/build-identity.mjs +83 -0
- package/render-service/src/cache-identity.mjs +65 -0
- package/render-service/src/contract.mjs +494 -0
- package/render-service/src/display-output.mjs +18 -0
- package/render-service/src/display-transform.mjs +192 -0
- package/render-service/src/framing.mjs +114 -0
- package/render-service/src/glb-input.mjs +259 -0
- package/render-service/src/gpu.mjs +101 -0
- package/render-service/src/health-contract.mjs +40 -0
- package/render-service/src/instance.mjs +146 -0
- package/render-service/src/node-visibility.mjs +49 -0
- package/render-service/src/png-input.mjs +77 -0
- package/render-service/src/presentation-presets.mjs +216 -0
- package/render-service/src/readback.mjs +16 -0
- package/render-service/src/register-hooks.mjs +2 -0
- package/render-service/src/render-queue.mjs +144 -0
- package/render-service/src/renderer.mjs +473 -0
- package/render-service/src/request-limits.mjs +72 -0
- package/render-service/src/review-tone-mapping.mjs +55 -0
- package/render-service/src/server.mjs +387 -0
- package/render-service/src/three-alias-hooks.mjs +6 -0
- package/scripts/create-workspace.mjs +808 -0
- package/scripts/package-plugin.mjs +67 -0
- package/skills/kiln-author-asset/SKILL.md +104 -0
- package/skills/kiln-author-asset/references/camera-cli.md +33 -0
- package/skills/kiln-author-asset/references/camera-recipes.md +73 -0
- package/skills/kiln-author-asset/references/export-profiles.md +216 -0
- package/skills/kiln-author-asset/references/geometry-recipes.md +329 -0
- package/skills/kiln-author-asset/references/program-contract.md +44 -0
- package/skills/kiln-author-asset/references/projects-and-materials.md +158 -0
- package/skills/kiln-author-asset/references/reusable-frame.kiln.js +32 -0
- package/skills/kiln-batch-dispatch/SKILL.md +22 -0
- package/skills/kiln-batch-dispatch/references/clean-room-evaluation.md +35 -0
- package/skills/kiln-compose-scene/SKILL.md +38 -0
- package/skills/kiln-compose-scene/references/composition-api.md +29 -0
- package/skills/kiln-compose-scene/references/runtime-scenes.md +363 -0
- package/skills/kiln-qa-asset/SKILL.md +99 -0
- package/skills/kiln-qa-asset/references/engine-handoff.md +246 -0
- package/skills/kiln-qa-asset/references/integration-checks.md +96 -0
- package/skills/kiln-refine-asset/SKILL.md +136 -0
- package/skills/kiln-refine-asset/references/revision-and-views.md +205 -0
- package/skills/kiln-refine-asset/references/revision-cli.md +39 -0
- package/skills/kiln-setup-workspace/SKILL.md +108 -0
- package/skills/kiln-setup-workspace/references/plugin-install.md +66 -0
- package/src/agent/call-budget.ts +106 -0
- package/src/agent/compaction.ts +197 -0
- package/src/agent/concurrency.ts +30 -0
- package/src/agent/diff.ts +141 -0
- package/src/agent/generate.ts +448 -0
- package/src/agent/hooks.ts +204 -0
- package/src/agent/index.ts +114 -0
- package/src/agent/native-prompt.ts +51 -0
- package/src/agent/native-workflow.ts +33 -0
- package/src/agent/providers.ts +529 -0
- package/src/agent/run.ts +356 -0
- package/src/agent/skill-resources.ts +198 -0
- package/src/agent/split-tool-result-images.ts +80 -0
- package/src/agent/stream-start.ts +61 -0
- package/src/agent/tools.ts +113 -0
- package/src/agent/view-render-timeout.ts +110 -0
- package/src/animation-cli.ts +251 -0
- package/src/animation-cubic.ts +57 -0
- package/src/animation-spline.ts +183 -0
- package/src/architecture.ts +871 -0
- package/src/arena/adaptive.ts +119 -0
- package/src/arena/bradley-terry.ts +221 -0
- package/src/arena/index.ts +21 -0
- package/src/assembly-transform.ts +34 -0
- package/src/assembly.ts +762 -0
- package/src/asset-catalog.ts +30 -0
- package/src/asset-cli.ts +505 -0
- package/src/asset-export.ts +141 -0
- package/src/asset-materials-node.ts +78 -0
- package/src/asset-viewer.ts +160 -0
- package/src/asset-widget-uri.ts +9 -0
- package/src/asset-widget.ts +38 -0
- package/src/assets-node.ts +412 -0
- package/src/assets-resources.ts +137 -0
- package/src/assets.ts +252 -0
- package/src/atomic-directory.ts +45 -0
- package/src/authoring-style.ts +49 -0
- package/src/breadth-prompt.ts +79 -0
- package/src/build-cache-node.ts +99 -0
- package/src/build-cache.ts +253 -0
- package/src/character.ts +776 -0
- package/src/cli-json.ts +29 -0
- package/src/cli-output.ts +135 -0
- package/src/cli-render-mode.ts +270 -0
- package/src/cli.ts +809 -0
- package/src/community-exporter.ts +268 -0
- package/src/composer/agent/compaction.ts +146 -0
- package/src/composer/agent/index.ts +41 -0
- package/src/composer/agent/prompt.ts +126 -0
- package/src/composer/agent/run.ts +317 -0
- package/src/composer/agent/tools.ts +847 -0
- package/src/composer/agent/world-run.ts +421 -0
- package/src/composer/agent/world-tools.ts +411 -0
- package/src/composer/collision.ts +448 -0
- package/src/composer/contract-utils.ts +52 -0
- package/src/composer/dsl.ts +196 -0
- package/src/composer/ground.ts +27 -0
- package/src/composer/index.ts +19 -0
- package/src/composer/layout.ts +357 -0
- package/src/composer/model.ts +688 -0
- package/src/composer/overlap.ts +220 -0
- package/src/composer/presentation.ts +309 -0
- package/src/composer/reachability.ts +407 -0
- package/src/composer/render-port.ts +516 -0
- package/src/composer/terrain-runtime.ts +415 -0
- package/src/composer/terrain.ts +53 -0
- package/src/composer/world-document.ts +1019 -0
- package/src/composer/world-integration.ts +589 -0
- package/src/composer/world-package.ts +255 -0
- package/src/contracts/asset.ts +2030 -0
- package/src/contracts/breadth.ts +888 -0
- package/src/contracts/environment.ts +81 -0
- package/src/contracts/index.ts +5 -0
- package/src/contracts/integration.ts +100 -0
- package/src/contracts/requirements-migration.ts +536 -0
- package/src/contracts/requirements.ts +357 -0
- package/src/contracts/semantic.ts +544 -0
- package/src/deform.ts +215 -0
- package/src/deformation-normals.ts +84 -0
- package/src/direct-entry.ts +28 -0
- package/src/discovery/articulation-recipes.ts +190 -0
- package/src/discovery/catalog-schema.ts +125 -0
- package/src/discovery/catalog.ts +88 -0
- package/src/discovery/construction-recipes.ts +243 -0
- package/src/discovery/helper-contracts.ts +2388 -0
- package/src/discovery/helper-specs.ts +1046 -0
- package/src/discovery/index.ts +36 -0
- package/src/discovery/intents.ts +120 -0
- package/src/discovery/lexical-index.ts +72 -0
- package/src/discovery/query-schema.ts +71 -0
- package/src/discovery/recipes.ts +215 -0
- package/src/discovery/service.ts +329 -0
- package/src/discovery/shapes.ts +120 -0
- package/src/discovery/structural-recipes.ts +199 -0
- package/src/discovery/surface-recipes.ts +130 -0
- package/src/discovery-cli.ts +106 -0
- package/src/draw-diagnostics.ts +313 -0
- package/src/edit-buffer.ts +134 -0
- package/src/edit-cli.ts +125 -0
- package/src/engine-identity.ts +50 -0
- package/src/evaluator/authoring-diagnostic.ts +168 -0
- package/src/evaluator/handler.ts +114 -0
- package/src/evaluator/index.ts +50 -0
- package/src/evaluator/isolation.ts +454 -0
- package/src/evaluator/probe-invariants.ts +9 -0
- package/src/evaluator/probe-worker.ts +158 -0
- package/src/evaluator/protocol.ts +701 -0
- package/src/evaluator/source-check.ts +64 -0
- package/src/evaluator/subprocess.ts +294 -0
- package/src/evaluator/transport-worker.mjs +8 -0
- package/src/evaluator/worker-urls.ts +16 -0
- package/src/evaluator/worker.ts +26 -0
- package/src/experiments/geometry-acceptance.ts +278 -0
- package/src/experiments/geometry-frontier.ts +181 -0
- package/src/experiments/program-aliases.ts +96 -0
- package/src/experiments/run-w6-material-vegetation.ts +7 -0
- package/src/experiments/run-w7-vegetation-lod.ts +6 -0
- package/src/experiments/w6-material-vegetation.ts +772 -0
- package/src/experiments/w7-vegetation-lod.ts +335 -0
- package/src/exporter-node.ts +68 -0
- package/src/gears.ts +334 -0
- package/src/generated/mcp-manifest.json +2050 -0
- package/src/geometry-budget.ts +50 -0
- package/src/geometry-catalog.ts +215 -0
- package/src/geometry-export.ts +193 -0
- package/src/geometry.ts +379 -0
- package/src/gltf-io.ts +129 -0
- package/src/gltf-validator-shims.d.ts +12 -0
- package/src/implicit.ts +106 -0
- package/src/index-policy.ts +52 -0
- package/src/index.ts +5 -0
- package/src/inspect-cli.ts +198 -0
- package/src/inspect.ts +290 -0
- package/src/kit.ts +547 -0
- package/src/live-review-node.ts +1011 -0
- package/src/live-review.ts +55 -0
- package/src/local-runtime.ts +336 -0
- package/src/lod-export.ts +120 -0
- package/src/lod.ts +192 -0
- package/src/loopback.ts +6 -0
- package/src/material-library-node.ts +488 -0
- package/src/material-library.ts +481 -0
- package/src/material-metrics.ts +392 -0
- package/src/material-presets.ts +207 -0
- package/src/material-recipe-prompt.ts +99 -0
- package/src/material-recipe-runtime.ts +162 -0
- package/src/material-recipes.ts +748 -0
- package/src/material-resources.ts +640 -0
- package/src/material-texture-library.generated.ts +11408 -0
- package/src/mcp-core.ts +437 -0
- package/src/mcp-engine.ts +383 -0
- package/src/mcp-manifest.ts +104 -0
- package/src/mcp-server.ts +118 -0
- package/src/metrics.ts +277 -0
- package/src/migration-cli.ts +105 -0
- package/src/migration-rebuild.ts +265 -0
- package/src/node-visibility.ts +116 -0
- package/src/open-shell.ts +104 -0
- package/src/ops.ts +751 -0
- package/src/palette-snap.ts +209 -0
- package/src/palette.ts +307 -0
- package/src/portable-material-runtime.ts +109 -0
- package/src/primitives.ts +2299 -0
- package/src/procedural-material-v2.ts +720 -0
- package/src/procedural-texture.ts +427 -0
- package/src/profile.ts +485 -0
- package/src/program-store-node.ts +138 -0
- package/src/program-store.ts +116 -0
- package/src/project-bundle-node.ts +220 -0
- package/src/project-bundle.ts +392 -0
- package/src/project-cli.ts +248 -0
- package/src/projects-node.ts +270 -0
- package/src/projects.ts +274 -0
- package/src/prompt-api.ts +231 -0
- package/src/qa/architecture-corpus.ts +828 -0
- package/src/qa/architecture-repairs.ts +92 -0
- package/src/qa/architecture.ts +1358 -0
- package/src/qa/benchmark-fixtures.ts +441 -0
- package/src/qa/breadth-corpus.ts +168 -0
- package/src/qa/breadth-evidence.ts +595 -0
- package/src/qa/breadth-final.ts +453 -0
- package/src/qa/breadth.ts +690 -0
- package/src/qa/character-advisory.ts +596 -0
- package/src/qa/character-repairs.ts +185 -0
- package/src/qa/character-vehicle-corpus.ts +802 -0
- package/src/qa/character.ts +998 -0
- package/src/qa/corpus.ts +499 -0
- package/src/qa/environment.ts +903 -0
- package/src/qa/geometry-relations.ts +843 -0
- package/src/qa/gltf.ts +103 -0
- package/src/qa/index.ts +34 -0
- package/src/qa/lod.ts +28 -0
- package/src/qa/material.ts +302 -0
- package/src/qa/part-connectivity.ts +252 -0
- package/src/qa/prop-environment-prompt.ts +58 -0
- package/src/qa/prop-helper-policy.ts +118 -0
- package/src/qa/prop.ts +828 -0
- package/src/qa/reference-comparison.ts +495 -0
- package/src/qa/registry.ts +604 -0
- package/src/qa/requirements-applicability.ts +241 -0
- package/src/qa/requirements-report.ts +280 -0
- package/src/qa/requirements-run.ts +470 -0
- package/src/qa/run.ts +329 -0
- package/src/qa/self-intersection.ts +741 -0
- package/src/qa/sweep.ts +68 -0
- package/src/qa/types.ts +187 -0
- package/src/qa/universal.ts +506 -0
- package/src/qa/vegetation-corpus.ts +404 -0
- package/src/qa/vegetation.ts +1174 -0
- package/src/qa/vehicle-advisory.ts +468 -0
- package/src/qa/vehicle.ts +756 -0
- package/src/rebuild-options.ts +16 -0
- package/src/render-capabilities.ts +140 -0
- package/src/render-service-client.ts +297 -0
- package/src/render-service-host.ts +278 -0
- package/src/render-service-windows.ts +80 -0
- package/src/render.ts +2748 -0
- package/src/requirements-assets.ts +53 -0
- package/src/requirements-context.ts +170 -0
- package/src/requirements-file.ts +10 -0
- package/src/requirements-identity.ts +43 -0
- package/src/requirements-json.ts +65 -0
- package/src/requirements-store.ts +150 -0
- package/src/requirements.ts +4 -0
- package/src/review-cli.ts +81 -0
- package/src/revision-comparison.ts +425 -0
- package/src/rig-export.ts +29 -0
- package/src/rigid-merge.ts +691 -0
- package/src/runtime-identity.ts +207 -0
- package/src/runtime-support.mjs +20 -0
- package/src/service-cli.ts +210 -0
- package/src/solids.ts +650 -0
- package/src/source-bindings.ts +90 -0
- package/src/source-runtime-checks.ts +189 -0
- package/src/sweep-analysis.ts +168 -0
- package/src/sweep.ts +482 -0
- package/src/texture-bake.ts +526 -0
- package/src/texture-contract.ts +12 -0
- package/src/texture-resolver.ts +61 -0
- package/src/textures.ts +345 -0
- package/src/tools/actions.ts +124 -0
- package/src/tools/capture-input.ts +233 -0
- package/src/tools/discovery.ts +194 -0
- package/src/tools/materials.ts +206 -0
- package/src/tools/preview-fidelity.ts +31 -0
- package/src/tools/program-artifacts.ts +107 -0
- package/src/tools/programs.ts +190 -0
- package/src/tools/projects.ts +141 -0
- package/src/tools/registry.ts +3111 -0
- package/src/tools/review-detail.ts +788 -0
- package/src/tools/review.ts +269 -0
- package/src/tools/skill-resource.ts +9 -0
- package/src/tools/workspace.ts +112 -0
- package/src/user-data-extras.ts +181 -0
- package/src/user-data-validation.ts +211 -0
- package/src/uv-project.ts +185 -0
- package/src/uv-shapes.ts +63 -0
- package/src/uv.ts +301 -0
- package/src/validation.ts +1257 -0
- package/src/vegetation-prompt.ts +109 -0
- package/src/vehicle.ts +742 -0
- package/src/viewer/app.ts +666 -0
- package/src/viewer/attribution.ts +17 -0
- package/src/viewer/camera-state.ts +45 -0
- package/src/viewer/chat-app.ts +221 -0
- package/src/viewer/chat-download.ts +53 -0
- package/src/viewer/dashboard.ts +59 -0
- package/src/viewer/deep-link.ts +34 -0
- package/src/viewer/dom.ts +63 -0
- package/src/viewer/framing.ts +55 -0
- package/src/viewer/library-state.ts +34 -0
- package/src/viewer/live-panel.ts +742 -0
- package/src/viewer/live-state.ts +99 -0
- package/src/viewer/load-guard.ts +10 -0
- package/src/viewer/lod-control.ts +98 -0
- package/src/viewer/lod.ts +172 -0
- package/src/viewer/material-preset-form.ts +34 -0
- package/src/viewer/materials-panel.ts +335 -0
- package/src/viewer/membership-panel.ts +122 -0
- package/src/viewer/navigation.ts +9 -0
- package/src/viewer/performance-control.ts +75 -0
- package/src/viewer/performance.ts +61 -0
- package/src/viewer/project-editor.ts +37 -0
- package/src/viewer/project-membership.ts +20 -0
- package/src/viewer/projects-panel.ts +374 -0
- package/src/viewer/scene.ts +426 -0
- package/src/viewer/visibility.ts +73 -0
- package/src/views/annotate.ts +138 -0
- package/src/views/architecture.ts +77 -0
- package/src/views/background.ts +87 -0
- package/src/views/camera-capture.ts +143 -0
- package/src/views/camera.ts +622 -0
- package/src/views/capture-cache.ts +272 -0
- package/src/views/capture-limits.ts +73 -0
- package/src/views/capture.ts +300 -0
- package/src/views/character-capture.ts +279 -0
- package/src/views/character.ts +267 -0
- package/src/views/diagnostic.ts +853 -0
- package/src/views/evidence-history.ts +166 -0
- package/src/views/glb.ts +747 -0
- package/src/views/grid.ts +118 -0
- package/src/views/index.ts +1071 -0
- package/src/views/inspect.ts +296 -0
- package/src/views/lod.ts +117 -0
- package/src/views/measurement.ts +69 -0
- package/src/views/part-placement.ts +50 -0
- package/src/views/png.ts +175 -0
- package/src/views/port.ts +335 -0
- package/src/views/pose.ts +541 -0
- package/src/views/raster.ts +627 -0
- package/src/views/renderer-id.ts +31 -0
- package/src/views/scene-raster.ts +139 -0
- package/src/views/surface-distance.ts +403 -0
- package/src/views/vehicle.ts +431 -0
- package/src/wall-panels.ts +127 -0
- package/src/widget-transfer.ts +115 -0
- package/src/workspace-cli.ts +41 -0
- package/src/workspace-http.ts +219 -0
- package/src/workspace-location.ts +20 -0
- package/src/workspace-node.ts +91 -0
- package/src/workspace.ts +43 -0
- package/src/written-nodes.ts +39 -0
- package/src/xatlasjs-shims.d.ts +16 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import {
|
|
3
|
+
validatePbrRenderRequest,
|
|
4
|
+
type PbrRenderPort,
|
|
5
|
+
type PbrRenderResult,
|
|
6
|
+
type PbrRenderRequest,
|
|
7
|
+
} from '../composer/render-port';
|
|
8
|
+
import type { GlbViewCellResult } from './index';
|
|
9
|
+
import type { ResolvedAssetCameraV1 } from './camera';
|
|
10
|
+
import { decodePng } from './png';
|
|
11
|
+
import { enforcePngCaptureBudget } from './capture-limits';
|
|
12
|
+
export type CaptureCacheEntry =
|
|
13
|
+
| { kind: 'gpu'; result: PbrRenderResult }
|
|
14
|
+
| { kind: 'cpu'; result: GlbViewCellResult };
|
|
15
|
+
export interface CaptureCache {
|
|
16
|
+
get(key: string): Promise<CaptureCacheEntry | undefined>;
|
|
17
|
+
put(key: string, value: CaptureCacheEntry): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
function clone(entry: CaptureCacheEntry): CaptureCacheEntry {
|
|
20
|
+
const result = structuredClone(entry);
|
|
21
|
+
if (result.kind === 'cpu') result.result.png = Buffer.from(result.result.png);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/** One host-owned byte budget for disposable cells. Entries retain the producer and evidence. */
|
|
25
|
+
export class MemoryCaptureCache implements CaptureCache {
|
|
26
|
+
private readonly entries = new Map<string, { entry: CaptureCacheEntry; bytes: number }>();
|
|
27
|
+
private bytes = 0;
|
|
28
|
+
constructor(private readonly maxBytes = 64 * 1024 * 1024) {
|
|
29
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
30
|
+
throw new Error('Capture cache bytes must be a nonnegative integer');
|
|
31
|
+
}
|
|
32
|
+
async get(key: string) {
|
|
33
|
+
const value = this.entries.get(key);
|
|
34
|
+
if (!value) return undefined;
|
|
35
|
+
this.entries.delete(key);
|
|
36
|
+
this.entries.set(key, value);
|
|
37
|
+
return clone(value.entry);
|
|
38
|
+
}
|
|
39
|
+
async put(key: string, value: CaptureCacheEntry) {
|
|
40
|
+
const entry = clone(value);
|
|
41
|
+
let bytes: number;
|
|
42
|
+
if (entry.kind === 'gpu') {
|
|
43
|
+
const { viewsPng, beautyPng, ...metadata } = entry.result;
|
|
44
|
+
bytes =
|
|
45
|
+
(viewsPng ?? []).reduce((sum, png) => sum + png.byteLength, 0) +
|
|
46
|
+
(beautyPng?.byteLength ?? 0) +
|
|
47
|
+
Buffer.byteLength(JSON.stringify(metadata));
|
|
48
|
+
} else {
|
|
49
|
+
const { png, ...metadata } = entry.result;
|
|
50
|
+
bytes = png.byteLength + Buffer.byteLength(JSON.stringify(metadata));
|
|
51
|
+
}
|
|
52
|
+
if (bytes > this.maxBytes) return;
|
|
53
|
+
const old = this.entries.get(key);
|
|
54
|
+
if (old) {
|
|
55
|
+
this.bytes -= old.bytes;
|
|
56
|
+
this.entries.delete(key);
|
|
57
|
+
}
|
|
58
|
+
while (this.bytes + bytes > this.maxBytes) {
|
|
59
|
+
const first = this.entries.keys().next().value;
|
|
60
|
+
if (first === undefined) break;
|
|
61
|
+
this.bytes -= this.entries.get(first)!.bytes;
|
|
62
|
+
this.entries.delete(first);
|
|
63
|
+
}
|
|
64
|
+
this.entries.set(key, { entry, bytes });
|
|
65
|
+
this.bytes += bytes;
|
|
66
|
+
}
|
|
67
|
+
stats() {
|
|
68
|
+
return { entries: this.entries.size, bytes: this.bytes, maxBytes: this.maxBytes };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function canonical(value: unknown): unknown {
|
|
72
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
73
|
+
if (value && typeof value === 'object')
|
|
74
|
+
return Object.fromEntries(
|
|
75
|
+
Object.entries(value)
|
|
76
|
+
.filter(([, v]) => v !== undefined)
|
|
77
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
78
|
+
.map(([k, v]) => [k, canonical(v)]),
|
|
79
|
+
);
|
|
80
|
+
if (typeof value === 'number' && !Number.isFinite(value))
|
|
81
|
+
throw new Error('Non-finite capture identity');
|
|
82
|
+
if (
|
|
83
|
+
value === undefined ||
|
|
84
|
+
value === null ||
|
|
85
|
+
['string', 'number', 'boolean'].includes(typeof value)
|
|
86
|
+
)
|
|
87
|
+
return value;
|
|
88
|
+
throw new Error('Capture identity must be data');
|
|
89
|
+
}
|
|
90
|
+
const text = (value: unknown) => JSON.stringify(canonical(value));
|
|
91
|
+
const digest = (value: string | Uint8Array) =>
|
|
92
|
+
`sha256:${createHash('sha256').update(value).digest('hex')}` as const;
|
|
93
|
+
function usable(result: PbrRenderResult, request: PbrRenderRequest, hash: string): boolean {
|
|
94
|
+
try {
|
|
95
|
+
if (
|
|
96
|
+
!result.ok ||
|
|
97
|
+
!result.rendererId?.trim() ||
|
|
98
|
+
result.derivativeFidelity?.materialFaithful !== true ||
|
|
99
|
+
result.derivativeFidelity.inputGlbSha256 !== hash
|
|
100
|
+
)
|
|
101
|
+
return false;
|
|
102
|
+
const count = (request.cameras ?? request.viewDirs)!.length;
|
|
103
|
+
if (result.viewsPng?.length !== count) return false;
|
|
104
|
+
if (
|
|
105
|
+
request.cameras &&
|
|
106
|
+
(result.width !== request.width ||
|
|
107
|
+
result.height !== request.height ||
|
|
108
|
+
text(result.cameras) !== text(request.cameras))
|
|
109
|
+
)
|
|
110
|
+
return false;
|
|
111
|
+
enforcePngCaptureBudget(result.viewsPng);
|
|
112
|
+
for (const png of result.viewsPng) {
|
|
113
|
+
const image = decodePng(png);
|
|
114
|
+
if (
|
|
115
|
+
image.width !== image.height ||
|
|
116
|
+
(request.cameras && (image.width !== request.width || image.height !== request.height))
|
|
117
|
+
)
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
} catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Cache only acknowledged material-faithful GPU cells. Identity must include backend/version and hidden render settings. */
|
|
126
|
+
export function createCachedRenderPort(
|
|
127
|
+
port: PbrRenderPort,
|
|
128
|
+
options: { cache: CaptureCache; identity(): string | undefined | Promise<string | undefined> },
|
|
129
|
+
): PbrRenderPort {
|
|
130
|
+
return async (input, execution) => {
|
|
131
|
+
execution?.signal?.throwIfAborted();
|
|
132
|
+
const identity = await Promise.resolve()
|
|
133
|
+
.then(() => options.identity())
|
|
134
|
+
.catch(() => undefined);
|
|
135
|
+
execution?.signal?.throwIfAborted();
|
|
136
|
+
if (!identity || input.beautySize !== undefined || !(input.cameras ?? input.viewDirs)?.length)
|
|
137
|
+
return port(input, execution);
|
|
138
|
+
const validated = validatePbrRenderRequest(input);
|
|
139
|
+
const request = { ...validated, glb: Uint8Array.from(validated.glb) };
|
|
140
|
+
const hash = digest(request.glb);
|
|
141
|
+
const selectors = request.cameras ?? request.viewDirs!;
|
|
142
|
+
const keys = selectors.map((selector) =>
|
|
143
|
+
digest(
|
|
144
|
+
text({
|
|
145
|
+
version: 'kiln.capture-cache.v1',
|
|
146
|
+
kind: 'gpu',
|
|
147
|
+
identity,
|
|
148
|
+
artifact: hash,
|
|
149
|
+
selector,
|
|
150
|
+
size: request.size,
|
|
151
|
+
width: request.width,
|
|
152
|
+
height: request.height,
|
|
153
|
+
lighting: request.lightingPresetId,
|
|
154
|
+
backdrop: request.backdrop,
|
|
155
|
+
}),
|
|
156
|
+
),
|
|
157
|
+
);
|
|
158
|
+
const cells: Array<PbrRenderResult | undefined> = [];
|
|
159
|
+
const missing: number[] = [];
|
|
160
|
+
for (let i = 0; i < keys.length; i++) {
|
|
161
|
+
const cached = await options.cache.get(keys[i]!).catch(() => undefined);
|
|
162
|
+
execution?.signal?.throwIfAborted();
|
|
163
|
+
const single = {
|
|
164
|
+
...request,
|
|
165
|
+
...(request.cameras
|
|
166
|
+
? { cameras: [request.cameras[i]!] }
|
|
167
|
+
: { viewDirs: [request.viewDirs![i]!] }),
|
|
168
|
+
};
|
|
169
|
+
if (cached?.kind === 'gpu' && usable(cached.result, single, hash)) cells[i] = cached.result;
|
|
170
|
+
else missing.push(i);
|
|
171
|
+
}
|
|
172
|
+
if (missing.length) {
|
|
173
|
+
const subrequest = {
|
|
174
|
+
...request,
|
|
175
|
+
...(request.cameras
|
|
176
|
+
? { cameras: missing.map((i) => request.cameras![i]!) }
|
|
177
|
+
: { viewDirs: missing.map((i) => request.viewDirs![i]!) }),
|
|
178
|
+
};
|
|
179
|
+
const produced = await port(subrequest, execution);
|
|
180
|
+
execution?.signal?.throwIfAborted();
|
|
181
|
+
const afterIdentity = await Promise.resolve()
|
|
182
|
+
.then(() => options.identity())
|
|
183
|
+
.catch(() => undefined);
|
|
184
|
+
execution?.signal?.throwIfAborted();
|
|
185
|
+
if (afterIdentity !== identity)
|
|
186
|
+
return missing.length === selectors.length
|
|
187
|
+
? produced
|
|
188
|
+
: {
|
|
189
|
+
ok: false,
|
|
190
|
+
rendererId: produced.rendererId,
|
|
191
|
+
error: 'capture producer changed during render',
|
|
192
|
+
};
|
|
193
|
+
if (!usable(produced, subrequest, hash)) {
|
|
194
|
+
// Returning a partial batch as a successful full sheet would mislabel images.
|
|
195
|
+
return missing.length === selectors.length
|
|
196
|
+
? produced
|
|
197
|
+
: {
|
|
198
|
+
ok: false,
|
|
199
|
+
rendererId: produced.rendererId,
|
|
200
|
+
error: produced.error ?? 'uncacheable partial camera response',
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
for (let j = 0; j < missing.length; j++) {
|
|
204
|
+
const i = missing[j]!;
|
|
205
|
+
const cell = {
|
|
206
|
+
...produced,
|
|
207
|
+
viewsPng: [Uint8Array.from(produced.viewsPng![j]!)],
|
|
208
|
+
...(produced.cameras ? { cameras: [produced.cameras[j]!] } : {}),
|
|
209
|
+
};
|
|
210
|
+
cells[i] = cell;
|
|
211
|
+
await options.cache.put(keys[i]!, { kind: 'gpu', result: cell }).catch(() => {});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const first = cells[0]!;
|
|
215
|
+
if (cells.some((c) => c!.rendererId !== first.rendererId))
|
|
216
|
+
return {
|
|
217
|
+
ok: false,
|
|
218
|
+
rendererId: first.rendererId,
|
|
219
|
+
error: 'capture producer changed; refresh host cache identity',
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
...first,
|
|
223
|
+
viewsPng: cells.map((c) => Uint8Array.from(c!.viewsPng![0]!)),
|
|
224
|
+
...(request.cameras ? { cameras: structuredClone(request.cameras) } : {}),
|
|
225
|
+
captureCache: {
|
|
226
|
+
hit: missing.length === 0,
|
|
227
|
+
reused: selectors.length - missing.length,
|
|
228
|
+
total: selectors.length,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
export interface CpuCaptureIdentity {
|
|
234
|
+
artifactGlbSha256: `sha256:${string}`;
|
|
235
|
+
rendererId: string;
|
|
236
|
+
camera: ResolvedAssetCameraV1;
|
|
237
|
+
size: number;
|
|
238
|
+
backfaceCull?: boolean;
|
|
239
|
+
/** Painted backdrop; part of the key because the pixels differ per backdrop. */
|
|
240
|
+
backdrop?: import('./background').BackdropId;
|
|
241
|
+
}
|
|
242
|
+
/** CPU entries are explicitly geometry-flat and live in a different key namespace from GPU cells. */
|
|
243
|
+
export async function captureCpuCell(
|
|
244
|
+
cache: CaptureCache,
|
|
245
|
+
identity: CpuCaptureIdentity,
|
|
246
|
+
produce: () => Promise<GlbViewCellResult>,
|
|
247
|
+
): Promise<GlbViewCellResult & { captureCache?: { hit: boolean } }> {
|
|
248
|
+
const snapshot = structuredClone(identity);
|
|
249
|
+
const key = digest(text({ version: 'kiln.capture-cache.v1', kind: 'cpu', ...snapshot }));
|
|
250
|
+
const valid = (result: GlbViewCellResult) => {
|
|
251
|
+
try {
|
|
252
|
+
enforcePngCaptureBudget([result.png]);
|
|
253
|
+
const image = decodePng(result.png);
|
|
254
|
+
return (
|
|
255
|
+
result.inputGlbSha256 === snapshot.artifactGlbSha256 &&
|
|
256
|
+
image.width === snapshot.size &&
|
|
257
|
+
image.height === snapshot.size &&
|
|
258
|
+
result.width === snapshot.size &&
|
|
259
|
+
result.height === snapshot.size
|
|
260
|
+
);
|
|
261
|
+
} catch {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const cached = await cache.get(key).catch(() => undefined);
|
|
266
|
+
if (cached?.kind === 'cpu' && valid(cached.result))
|
|
267
|
+
return { ...cached.result, png: Buffer.from(cached.result.png), captureCache: { hit: true } };
|
|
268
|
+
const result = await produce();
|
|
269
|
+
if (!valid(result)) return result;
|
|
270
|
+
await cache.put(key, { kind: 'cpu', result }).catch(() => {});
|
|
271
|
+
return { ...result, png: Buffer.from(result.png), captureCache: { hit: false } };
|
|
272
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { PAD } from './grid';
|
|
2
|
+
export interface CaptureLimits {
|
|
3
|
+
maxTotalPixels?: number;
|
|
4
|
+
maxOutputBytes?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Largest square per-shot size for kiln.capture.v1. The render service accepts
|
|
8
|
+
* camera-mode images up to 4096 px a side and 16.7M pixels per request, and 2048
|
|
9
|
+
* is its top legacy rung; the capture pixel and byte budgets below bound the sheet.
|
|
10
|
+
*/
|
|
11
|
+
export const MAX_CAPTURE_SHOT_SIZE = 2048;
|
|
12
|
+
export const DEFAULT_CAPTURE_LIMITS = Object.freeze({
|
|
13
|
+
maxTotalPixels: 24_000_000,
|
|
14
|
+
maxOutputBytes: 32 * 1024 * 1024,
|
|
15
|
+
});
|
|
16
|
+
export function resolveCaptureLimits(limits: CaptureLimits = {}) {
|
|
17
|
+
const result: Required<CaptureLimits> = { ...DEFAULT_CAPTURE_LIMITS };
|
|
18
|
+
for (const key of ['maxTotalPixels', 'maxOutputBytes'] as const) {
|
|
19
|
+
const value = limits[key];
|
|
20
|
+
if (value !== undefined) {
|
|
21
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
22
|
+
throw new Error(`capture limit ${key} must be a positive integer`);
|
|
23
|
+
result[key] = Math.min(value, result[key]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
export function enforceCapturePixels(
|
|
29
|
+
cells: number,
|
|
30
|
+
size: number,
|
|
31
|
+
cols: number,
|
|
32
|
+
limits?: CaptureLimits,
|
|
33
|
+
compose = true,
|
|
34
|
+
) {
|
|
35
|
+
if (
|
|
36
|
+
!Number.isSafeInteger(cells) ||
|
|
37
|
+
cells < 1 ||
|
|
38
|
+
!Number.isSafeInteger(size) ||
|
|
39
|
+
size < 1 ||
|
|
40
|
+
!Number.isSafeInteger(cols) ||
|
|
41
|
+
cols < 1
|
|
42
|
+
)
|
|
43
|
+
throw new Error('invalid capture dimensions');
|
|
44
|
+
const pixels =
|
|
45
|
+
cells * size * size +
|
|
46
|
+
(compose
|
|
47
|
+
? (cols * size + (cols + 1) * PAD) *
|
|
48
|
+
(Math.ceil(cells / cols) * size + (Math.ceil(cells / cols) + 1) * PAD)
|
|
49
|
+
: 0);
|
|
50
|
+
if (pixels > resolveCaptureLimits(limits).maxTotalPixels)
|
|
51
|
+
throw new Error(`capture pixel budget exceeded: ${pixels}`);
|
|
52
|
+
return pixels;
|
|
53
|
+
}
|
|
54
|
+
export function enforceCaptureBytes(images: readonly Uint8Array[], limits?: CaptureLimits) {
|
|
55
|
+
const bytes = images.reduce((sum, image) => sum + image.byteLength, 0);
|
|
56
|
+
if (bytes > resolveCaptureLimits(limits).maxOutputBytes)
|
|
57
|
+
throw new Error(`capture byte budget exceeded: ${bytes}`);
|
|
58
|
+
return bytes;
|
|
59
|
+
}
|
|
60
|
+
/** Bound declared raster dimensions before a decoder allocates inflated pixel storage. */
|
|
61
|
+
export function enforcePngCaptureBudget(images: readonly Uint8Array[], limits?: CaptureLimits) {
|
|
62
|
+
enforceCaptureBytes(images, limits);
|
|
63
|
+
let pixels = 0;
|
|
64
|
+
for (const png of images) {
|
|
65
|
+
if (png.byteLength < 24) throw new Error('invalid PNG header');
|
|
66
|
+
const view = new DataView(png.buffer, png.byteOffset, png.byteLength);
|
|
67
|
+
if (view.getUint32(0) !== 0x89504e47 || view.getUint32(12) !== 0x49484452)
|
|
68
|
+
throw new Error('invalid PNG header');
|
|
69
|
+
pixels += view.getUint32(16) * view.getUint32(20);
|
|
70
|
+
}
|
|
71
|
+
if (pixels > resolveCaptureLimits(limits).maxTotalPixels)
|
|
72
|
+
throw new Error(`capture pixel budget exceeded: ${pixels}`);
|
|
73
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capture configuration for the view grid (T3.2).
|
|
3
|
+
*
|
|
4
|
+
* The contact sheet was a fixed 3x2 of six named cameras. That is the right
|
|
5
|
+
* default and stays the default, but it is wrong often enough to matter: a
|
|
6
|
+
* symmetric prop wastes four cells restating the same silhouette, and a
|
|
7
|
+
* complex asset with an occluded interior needs angles the six do not include.
|
|
8
|
+
* This module lets the model choose the grid shape and, if it wants, every
|
|
9
|
+
* cell's camera.
|
|
10
|
+
*
|
|
11
|
+
* ## The one hard rule
|
|
12
|
+
*
|
|
13
|
+
* Omitting `capture` must reproduce the existing 3x2 output **byte for byte**.
|
|
14
|
+
* Every default here is arranged around that: {@link DEFAULT_CAPTURE_PRESET} is
|
|
15
|
+
* `3x2`, its cells are `SIX_VIEWS` by identity (not a copy that could drift),
|
|
16
|
+
* and per-cell `zoom` is only applied when explicitly supplied, because passing
|
|
17
|
+
* frame bounds at all changes the framing path away from per-cell auto-framing.
|
|
18
|
+
*
|
|
19
|
+
* ## Preset naming
|
|
20
|
+
*
|
|
21
|
+
* `COLSxROWS`, matching how the existing grid is described throughout the
|
|
22
|
+
* codebase ("6 cells @ 3 cols = 3x2"). So `3x1` is a wide strip and `1x2` is a
|
|
23
|
+
* tall pair.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { SIX_VIEWS, type ViewSpec, orbitAnglesOf, orbitDir, resolveGridViews } from './raster';
|
|
27
|
+
import { BACKDROP_IDS, DEFAULT_BACKDROP_ID, isBackdropId, type BackdropId } from './background';
|
|
28
|
+
|
|
29
|
+
/** Grid shapes the model may ask for. `COLS x ROWS`. */
|
|
30
|
+
export type CapturePreset = '1x1' | '1x2' | '2x1' | '3x1' | '2x2' | '3x2' | '3x3';
|
|
31
|
+
|
|
32
|
+
export const CAPTURE_PRESETS: readonly CapturePreset[] = [
|
|
33
|
+
'1x1',
|
|
34
|
+
'1x2',
|
|
35
|
+
'2x1',
|
|
36
|
+
'3x1',
|
|
37
|
+
'2x2',
|
|
38
|
+
'3x2',
|
|
39
|
+
'3x3',
|
|
40
|
+
] as const;
|
|
41
|
+
|
|
42
|
+
/** The shipped contact sheet. Omitting `capture` resolves to exactly this. */
|
|
43
|
+
export const DEFAULT_CAPTURE_PRESET: CapturePreset = '3x2';
|
|
44
|
+
|
|
45
|
+
/** Hard cap on cells, so a runaway config cannot blow up render time or tokens. */
|
|
46
|
+
export const MAX_CAPTURE_CELLS = 9;
|
|
47
|
+
|
|
48
|
+
/** One model-specified camera. Angles are object-relative, same frame as `kiln_inspect`. */
|
|
49
|
+
export interface CaptureCell {
|
|
50
|
+
azimuthDeg: number;
|
|
51
|
+
elevationDeg: number;
|
|
52
|
+
/** Padding multiplier around the asset bounds. Omit for the default auto-framing. */
|
|
53
|
+
zoom?: number;
|
|
54
|
+
/** Optional cell label. Auto-derived from the angles when omitted. */
|
|
55
|
+
name?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CaptureConfig {
|
|
59
|
+
version?: 'kiln.capture.v1' | 'kiln.capture.v2';
|
|
60
|
+
shots?: import('./camera').CameraShotV1[];
|
|
61
|
+
cols?: number;
|
|
62
|
+
size?: number;
|
|
63
|
+
output?: 'grid' | 'separate';
|
|
64
|
+
preset?: CapturePreset;
|
|
65
|
+
cells?: CaptureCell[];
|
|
66
|
+
/**
|
|
67
|
+
* Named backdrop behind every cell. Omit for the default. One of three fixed
|
|
68
|
+
* colours rather than a free hex, so sheets stay comparable across runs and a
|
|
69
|
+
* backdrop can never be tuned to hide a seam. See `views/background.ts`.
|
|
70
|
+
*/
|
|
71
|
+
backdrop?: BackdropId;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Columns for each preset. Rows follow from the cell count. */
|
|
75
|
+
const PRESET_COLS: Record<CapturePreset, number> = {
|
|
76
|
+
'1x1': 1,
|
|
77
|
+
'1x2': 1,
|
|
78
|
+
'2x1': 2,
|
|
79
|
+
'3x1': 3,
|
|
80
|
+
'2x2': 2,
|
|
81
|
+
'3x2': 3,
|
|
82
|
+
'3x3': 3,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Cell capacity of each preset. */
|
|
86
|
+
const PRESET_CAPACITY: Record<CapturePreset, number> = {
|
|
87
|
+
'1x1': 1,
|
|
88
|
+
'1x2': 2,
|
|
89
|
+
'2x1': 2,
|
|
90
|
+
'3x1': 3,
|
|
91
|
+
'2x2': 4,
|
|
92
|
+
'3x2': 6,
|
|
93
|
+
'3x3': 9,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** Two extra cameras the six-view set has no room for. */
|
|
97
|
+
const BOTTOM: ViewSpec = { name: 'BOTTOM', dir: [0, -1, 0.0001] };
|
|
98
|
+
const THREE_QUARTER_REAR: ViewSpec = { name: 'REAR 34', dir: [-0.7, 0.5, -0.7] };
|
|
99
|
+
const THREE_QUARTER_LOW: ViewSpec = { name: 'LOW 34', dir: [0.7, -0.35, 0.7] };
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Default cameras per preset, chosen so a smaller grid drops the least
|
|
103
|
+
* informative cells rather than simply truncating the six in order.
|
|
104
|
+
*
|
|
105
|
+
* A single cell is the 3/4, not the front: one orthographic elevation reads as
|
|
106
|
+
* a flat rectangle for most assets, while the quarter view carries depth,
|
|
107
|
+
* proportion and silhouette at once. Two cells add the front for a readable
|
|
108
|
+
* measurement reference. `3x2` is `SIX_VIEWS` itself — same array identity, so
|
|
109
|
+
* a future edit to the six-view set cannot silently desynchronise the default.
|
|
110
|
+
*/
|
|
111
|
+
const PRESET_VIEWS: Record<CapturePreset, ViewSpec[]> = {
|
|
112
|
+
'1x1': [SIX_VIEWS[5]!],
|
|
113
|
+
'1x2': [SIX_VIEWS[0]!, SIX_VIEWS[5]!],
|
|
114
|
+
'2x1': [SIX_VIEWS[0]!, SIX_VIEWS[5]!],
|
|
115
|
+
'3x1': [SIX_VIEWS[0]!, SIX_VIEWS[1]!, SIX_VIEWS[5]!],
|
|
116
|
+
'2x2': [SIX_VIEWS[0]!, SIX_VIEWS[1]!, SIX_VIEWS[4]!, SIX_VIEWS[5]!],
|
|
117
|
+
'3x2': SIX_VIEWS,
|
|
118
|
+
'3x3': [...SIX_VIEWS, BOTTOM, THREE_QUARTER_REAR, THREE_QUARTER_LOW],
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Label an orbit cell using only glyphs the 3x5 bitmap font actually has
|
|
123
|
+
* (uppercase, digits, space — there is no minus sign, so elevation sign is
|
|
124
|
+
* carried by U/D rather than a `-` that would render as a blank box).
|
|
125
|
+
*/
|
|
126
|
+
export function captureCellLabel(azimuthDeg: number, elevationDeg: number): string {
|
|
127
|
+
const az = Math.round(((azimuthDeg % 360) + 360) % 360);
|
|
128
|
+
const el = Math.round(elevationDeg);
|
|
129
|
+
return `A${az} ${el < 0 ? 'D' : 'U'}${Math.abs(el)}`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface ResolvedCapture {
|
|
133
|
+
preset: CapturePreset;
|
|
134
|
+
views: ViewSpec[];
|
|
135
|
+
cols: number;
|
|
136
|
+
/** Per-cell zoom, aligned with `views`. `undefined` means auto-frame. */
|
|
137
|
+
zooms: Array<number | undefined>;
|
|
138
|
+
/** True when the result is the untouched shipped default. */
|
|
139
|
+
isDefault: boolean;
|
|
140
|
+
/** The backdrop every cell is painted on. */
|
|
141
|
+
backdrop: BackdropId;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The layout a contact sheet was actually produced in, reported alongside it.
|
|
146
|
+
*
|
|
147
|
+
* Shared by the tool result, the `views` artifact and the render port so a
|
|
148
|
+
* consumer never has to infer the grid shape by dividing image dimensions.
|
|
149
|
+
*/
|
|
150
|
+
export interface CaptureShape {
|
|
151
|
+
preset: string;
|
|
152
|
+
cols: number;
|
|
153
|
+
cells: number;
|
|
154
|
+
/** Echoed so the model never has to guess what colour it is looking at. */
|
|
155
|
+
backdrop?: BackdropId;
|
|
156
|
+
/**
|
|
157
|
+
* Delivery of a versioned capture: one sheet (`grid`, laid out as `preset`)
|
|
158
|
+
* or one image per shot (`separate`). Absent for the default six-view sheet.
|
|
159
|
+
*/
|
|
160
|
+
output?: 'grid' | 'separate';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export class CaptureConfigError extends Error {}
|
|
164
|
+
|
|
165
|
+
/** Validate an optional backdrop id, naming the choices on a miss. */
|
|
166
|
+
export function resolveCaptureBackdrop(backdrop: unknown): BackdropId {
|
|
167
|
+
if (backdrop === undefined) return DEFAULT_BACKDROP_ID;
|
|
168
|
+
if (!isBackdropId(backdrop))
|
|
169
|
+
throw new CaptureConfigError(
|
|
170
|
+
`capture.backdrop must be one of ${BACKDROP_IDS.join(', ')} (got ${JSON.stringify(backdrop)}).`,
|
|
171
|
+
);
|
|
172
|
+
return backdrop;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Resolve a capture config into the view list, column count and per-cell zooms
|
|
177
|
+
* the grid renderer needs.
|
|
178
|
+
*
|
|
179
|
+
* Throws {@link CaptureConfigError} on anything the model got wrong, with a
|
|
180
|
+
* message naming the fix — these come back through the tool result, so they are
|
|
181
|
+
* the model's only feedback channel.
|
|
182
|
+
*/
|
|
183
|
+
export function resolveCapture(config?: CaptureConfig): ResolvedCapture {
|
|
184
|
+
const backdrop = resolveCaptureBackdrop(config?.backdrop);
|
|
185
|
+
if (!config || (config.preset === undefined && config.cells === undefined)) {
|
|
186
|
+
return {
|
|
187
|
+
preset: DEFAULT_CAPTURE_PRESET,
|
|
188
|
+
views: PRESET_VIEWS[DEFAULT_CAPTURE_PRESET],
|
|
189
|
+
cols: PRESET_COLS[DEFAULT_CAPTURE_PRESET],
|
|
190
|
+
zooms: new Array(PRESET_CAPACITY[DEFAULT_CAPTURE_PRESET]).fill(undefined),
|
|
191
|
+
isDefault: true,
|
|
192
|
+
backdrop,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const cells = config.cells;
|
|
197
|
+
let preset = config.preset;
|
|
198
|
+
|
|
199
|
+
if (preset !== undefined && !CAPTURE_PRESETS.includes(preset)) {
|
|
200
|
+
throw new CaptureConfigError(
|
|
201
|
+
`capture.preset must be one of ${CAPTURE_PRESETS.join(', ')} (got ${JSON.stringify(preset)}).`,
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (cells !== undefined) {
|
|
206
|
+
if (!Array.isArray(cells) || cells.length === 0) {
|
|
207
|
+
throw new CaptureConfigError('capture.cells must be a non-empty array of camera angles.');
|
|
208
|
+
}
|
|
209
|
+
if (cells.length > MAX_CAPTURE_CELLS) {
|
|
210
|
+
throw new CaptureConfigError(
|
|
211
|
+
`capture.cells has ${cells.length} entries; the maximum is ${MAX_CAPTURE_CELLS}.`,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
for (let i = 0; i < cells.length; i++) {
|
|
215
|
+
const c = cells[i]!;
|
|
216
|
+
if (!Number.isFinite(c?.azimuthDeg) || !Number.isFinite(c?.elevationDeg)) {
|
|
217
|
+
throw new CaptureConfigError(
|
|
218
|
+
`capture.cells[${i}] needs finite azimuthDeg and elevationDeg (got ${JSON.stringify(c)}).`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
if (c.zoom !== undefined && (!Number.isFinite(c.zoom) || c.zoom <= 0)) {
|
|
222
|
+
throw new CaptureConfigError(
|
|
223
|
+
`capture.cells[${i}].zoom must be a positive number (got ${c.zoom}).`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Pick the tightest preset that fits when none was named, so `cells` alone
|
|
229
|
+
// is a complete request rather than an error about a missing preset.
|
|
230
|
+
if (preset === undefined) {
|
|
231
|
+
preset = CAPTURE_PRESETS.find((p) => PRESET_CAPACITY[p] >= cells.length)!;
|
|
232
|
+
} else if (cells.length > PRESET_CAPACITY[preset]) {
|
|
233
|
+
throw new CaptureConfigError(
|
|
234
|
+
`capture.preset ${preset} holds ${PRESET_CAPACITY[preset]} cells but ${cells.length} were given. ` +
|
|
235
|
+
`Use a larger preset or fewer cells.`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
preset,
|
|
241
|
+
views: cells.map((c) => ({
|
|
242
|
+
name: c.name?.trim().toUpperCase() || captureCellLabel(c.azimuthDeg, c.elevationDeg),
|
|
243
|
+
dir: orbitDir(c.azimuthDeg, c.elevationDeg),
|
|
244
|
+
})),
|
|
245
|
+
cols: PRESET_COLS[preset],
|
|
246
|
+
zooms: cells.map((c) => c.zoom),
|
|
247
|
+
isDefault: false,
|
|
248
|
+
backdrop,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Preset only: use its default cameras.
|
|
253
|
+
const chosen = preset!;
|
|
254
|
+
return {
|
|
255
|
+
preset: chosen,
|
|
256
|
+
views: PRESET_VIEWS[chosen],
|
|
257
|
+
cols: PRESET_COLS[chosen],
|
|
258
|
+
zooms: new Array(PRESET_VIEWS[chosen].length).fill(undefined),
|
|
259
|
+
isDefault: chosen === DEFAULT_CAPTURE_PRESET,
|
|
260
|
+
backdrop,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Resolve a capture config the way every grid producer must (T3.3).
|
|
266
|
+
*
|
|
267
|
+
* There are two producers of the same contact sheet — the CPU rasterizer and the
|
|
268
|
+
* GPU render port — and they have to agree on the layout down to the cell order,
|
|
269
|
+
* or a run's artifact silently changes shape depending on whether a GPU happened
|
|
270
|
+
* to be reachable. This is the one function both call, so the precedence rule
|
|
271
|
+
* exists once:
|
|
272
|
+
*
|
|
273
|
+
* capture supplied -> exactly what it asks for
|
|
274
|
+
* capture omitted -> the `KILN_GRID_VARIANT` view set at the shipped 3 cols
|
|
275
|
+
*
|
|
276
|
+
* The env variant only applies to the omitted case on purpose: it swaps the
|
|
277
|
+
* *default* six cameras for a bench arm, and silently rewriting a caller's
|
|
278
|
+
* explicitly-requested angles would make the request a lie.
|
|
279
|
+
*/
|
|
280
|
+
export function resolveGridCapture(config?: CaptureConfig, envVariant?: string): ResolvedCapture {
|
|
281
|
+
const resolved = resolveCapture(config);
|
|
282
|
+
if (config) return resolved;
|
|
283
|
+
const views = resolveGridViews(envVariant);
|
|
284
|
+
// Identity when the variant is unset/unknown, so the default stays the exact
|
|
285
|
+
// object the byte-identity tests pin.
|
|
286
|
+
return views === resolved.views ? resolved : { ...resolved, views };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Describe a resolved capture for the tool result, in the model's own coordinates. */
|
|
290
|
+
export function describeCapture(resolved: ResolvedCapture): string {
|
|
291
|
+
const angles = resolved.views
|
|
292
|
+
.map((v) => {
|
|
293
|
+
const { azimuthDeg, elevationDeg } = orbitAnglesOf(v.dir);
|
|
294
|
+
return `${v.name} (az ${azimuthDeg}, el ${elevationDeg})`;
|
|
295
|
+
})
|
|
296
|
+
.join('; ');
|
|
297
|
+
return `${resolved.preset} grid, ${resolved.views.length} cell${
|
|
298
|
+
resolved.views.length === 1 ? '' : 's'
|
|
299
|
+
}: ${angles}`;
|
|
300
|
+
}
|