modelrig 0.0.1 → 0.2.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/CHANGELOG.md +94 -0
- package/LICENSE +201 -0
- package/README.md +145 -8
- package/data/PROVENANCE.md +19 -0
- package/data/pricing-manual.json +22 -0
- package/data/pricing-map.json +46362 -0
- package/data/pricing-overlay.json +419 -0
- package/dist/adapters/anthropic.d.ts +90 -0
- package/dist/adapters/anthropic.d.ts.map +1 -0
- package/dist/adapters/anthropic.js +296 -0
- package/dist/adapters/build-adapters.d.ts +11 -0
- package/dist/adapters/build-adapters.d.ts.map +1 -0
- package/dist/adapters/build-adapters.js +45 -0
- package/dist/adapters/deepseek.d.ts +47 -0
- package/dist/adapters/deepseek.d.ts.map +1 -0
- package/dist/adapters/deepseek.js +216 -0
- package/dist/adapters/gemini.d.ts +44 -0
- package/dist/adapters/gemini.d.ts.map +1 -0
- package/dist/adapters/gemini.js +262 -0
- package/dist/adapters/grok.d.ts +53 -0
- package/dist/adapters/grok.d.ts.map +1 -0
- package/dist/adapters/grok.js +232 -0
- package/dist/adapters/openai-compat.d.ts +80 -0
- package/dist/adapters/openai-compat.d.ts.map +1 -0
- package/dist/adapters/openai-compat.js +244 -0
- package/dist/adapters/openai-stream.d.ts +58 -0
- package/dist/adapters/openai-stream.d.ts.map +1 -0
- package/dist/adapters/openai-stream.js +120 -0
- package/dist/adapters/openai.d.ts +55 -0
- package/dist/adapters/openai.d.ts.map +1 -0
- package/dist/adapters/openai.js +281 -0
- package/dist/adapters/sampling.d.ts +28 -0
- package/dist/adapters/sampling.d.ts.map +1 -0
- package/dist/adapters/sampling.js +34 -0
- package/dist/adapters/tool-mapping.d.ts +92 -0
- package/dist/adapters/tool-mapping.d.ts.map +1 -0
- package/dist/adapters/tool-mapping.js +143 -0
- package/dist/artifacts/artifact.d.ts +137 -0
- package/dist/artifacts/artifact.d.ts.map +1 -0
- package/dist/artifacts/artifact.js +377 -0
- package/dist/artifacts/content-uploader.d.ts +87 -0
- package/dist/artifacts/content-uploader.d.ts.map +1 -0
- package/dist/artifacts/content-uploader.js +124 -0
- package/dist/artifacts/index.d.ts +63 -0
- package/dist/artifacts/index.d.ts.map +1 -0
- package/dist/artifacts/index.js +80 -0
- package/dist/artifacts/run-context.d.ts +129 -0
- package/dist/artifacts/run-context.d.ts.map +1 -0
- package/dist/artifacts/run-context.js +208 -0
- package/dist/artifacts/scrub.d.ts +60 -0
- package/dist/artifacts/scrub.d.ts.map +1 -0
- package/dist/artifacts/scrub.js +139 -0
- package/dist/artifacts/step.d.ts +26 -0
- package/dist/artifacts/step.d.ts.map +1 -0
- package/dist/artifacts/step.js +37 -0
- package/dist/artifacts/taint.d.ts +63 -0
- package/dist/artifacts/taint.d.ts.map +1 -0
- package/dist/artifacts/taint.js +76 -0
- package/dist/bakeoff/cache-sim.d.ts +99 -0
- package/dist/bakeoff/cache-sim.d.ts.map +1 -0
- package/dist/bakeoff/cache-sim.js +126 -0
- package/dist/bakeoff/engine.d.ts +52 -0
- package/dist/bakeoff/engine.d.ts.map +1 -0
- package/dist/bakeoff/engine.js +163 -0
- package/dist/bakeoff/eval-cases.d.ts +96 -0
- package/dist/bakeoff/eval-cases.d.ts.map +1 -0
- package/dist/bakeoff/eval-cases.js +105 -0
- package/dist/bakeoff/replay.d.ts +52 -0
- package/dist/bakeoff/replay.d.ts.map +1 -0
- package/dist/bakeoff/replay.js +94 -0
- package/dist/bakeoff/report.d.ts +41 -0
- package/dist/bakeoff/report.d.ts.map +1 -0
- package/dist/bakeoff/report.js +142 -0
- package/dist/bakeoff/samples.d.ts +77 -0
- package/dist/bakeoff/samples.d.ts.map +1 -0
- package/dist/bakeoff/samples.js +148 -0
- package/dist/bakeoff/stats.d.ts +13 -0
- package/dist/bakeoff/stats.d.ts.map +1 -0
- package/dist/bakeoff/stats.js +48 -0
- package/dist/bakeoff/types.d.ts +37 -0
- package/dist/bakeoff/types.d.ts.map +1 -0
- package/dist/bakeoff/types.js +10 -0
- package/dist/cli.d.ts +25 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +590 -0
- package/dist/config.d.ts +204 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +252 -0
- package/dist/deprecations.d.ts +32 -0
- package/dist/deprecations.d.ts.map +1 -0
- package/dist/deprecations.js +59 -0
- package/dist/feedback/coverage.d.ts +32 -0
- package/dist/feedback/coverage.d.ts.map +1 -0
- package/dist/feedback/coverage.js +95 -0
- package/dist/feedback/feedback.d.ts +35 -0
- package/dist/feedback/feedback.d.ts.map +1 -0
- package/dist/feedback/feedback.js +39 -0
- package/dist/gateway/http-protocol.d.ts +175 -0
- package/dist/gateway/http-protocol.d.ts.map +1 -0
- package/dist/gateway/http-protocol.js +105 -0
- package/dist/index.d.ts +242 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +576 -0
- package/dist/init/finder.d.ts +94 -0
- package/dist/init/finder.d.ts.map +1 -0
- package/dist/init/finder.js +343 -0
- package/dist/init/init-cli.d.ts +10 -0
- package/dist/init/init-cli.d.ts.map +1 -0
- package/dist/init/init-cli.js +86 -0
- package/dist/init/observe-cli.d.ts +19 -0
- package/dist/init/observe-cli.d.ts.map +1 -0
- package/dist/init/observe-cli.js +73 -0
- package/dist/init/observe.d.ts +81 -0
- package/dist/init/observe.d.ts.map +1 -0
- package/dist/init/observe.js +245 -0
- package/dist/init/run.d.ts +99 -0
- package/dist/init/run.d.ts.map +1 -0
- package/dist/init/run.js +281 -0
- package/dist/init/signatures.d.ts +39 -0
- package/dist/init/signatures.d.ts.map +1 -0
- package/dist/init/signatures.js +116 -0
- package/dist/matrix/aggregate.d.ts +89 -0
- package/dist/matrix/aggregate.d.ts.map +1 -0
- package/dist/matrix/aggregate.js +186 -0
- package/dist/query/grammar.d.ts +35 -0
- package/dist/query/grammar.d.ts.map +1 -0
- package/dist/query/grammar.js +279 -0
- package/dist/query/run.d.ts +8 -0
- package/dist/query/run.d.ts.map +1 -0
- package/dist/query/run.js +21 -0
- package/dist/registry/build.d.ts +219 -0
- package/dist/registry/build.d.ts.map +1 -0
- package/dist/registry/build.js +313 -0
- package/dist/registry/cache-policy.d.ts +94 -0
- package/dist/registry/cache-policy.d.ts.map +1 -0
- package/dist/registry/cache-policy.js +238 -0
- package/dist/registry/call-notes.d.ts +11 -0
- package/dist/registry/call-notes.d.ts.map +1 -0
- package/dist/registry/call-notes.js +110 -0
- package/dist/registry/claims.d.ts +63 -0
- package/dist/registry/claims.d.ts.map +1 -0
- package/dist/registry/claims.js +107 -0
- package/dist/registry/effective-rate.d.ts +151 -0
- package/dist/registry/effective-rate.d.ts.map +1 -0
- package/dist/registry/effective-rate.js +156 -0
- package/dist/registry/facts.d.ts +32 -0
- package/dist/registry/facts.d.ts.map +1 -0
- package/dist/registry/facts.js +136 -0
- package/dist/registry/fingerprint.d.ts +20 -0
- package/dist/registry/fingerprint.d.ts.map +1 -0
- package/dist/registry/fingerprint.js +150 -0
- package/dist/registry/parity.d.ts +52 -0
- package/dist/registry/parity.d.ts.map +1 -0
- package/dist/registry/parity.js +82 -0
- package/dist/registry/pricing-shape.d.ts +113 -0
- package/dist/registry/pricing-shape.d.ts.map +1 -0
- package/dist/registry/pricing-shape.js +123 -0
- package/dist/registry/pricing.d.ts +43 -0
- package/dist/registry/pricing.d.ts.map +1 -0
- package/dist/registry/pricing.js +127 -0
- package/dist/registry/rows.d.ts +16 -0
- package/dist/registry/rows.d.ts.map +1 -0
- package/dist/registry/rows.js +57 -0
- package/dist/registry/seed.d.ts +43 -0
- package/dist/registry/seed.d.ts.map +1 -0
- package/dist/registry/seed.js +97 -0
- package/dist/registry/select.d.ts +68 -0
- package/dist/registry/select.d.ts.map +1 -0
- package/dist/registry/select.js +141 -0
- package/dist/registry/staleness.d.ts +18 -0
- package/dist/registry/staleness.d.ts.map +1 -0
- package/dist/registry/staleness.js +39 -0
- package/dist/rigindex/bootstrap.d.ts +36 -0
- package/dist/rigindex/bootstrap.d.ts.map +1 -0
- package/dist/rigindex/bootstrap.js +97 -0
- package/dist/rigindex/fit.d.ts +24 -0
- package/dist/rigindex/fit.d.ts.map +1 -0
- package/dist/rigindex/fit.js +76 -0
- package/dist/rigindex/gates.d.ts +52 -0
- package/dist/rigindex/gates.d.ts.map +1 -0
- package/dist/rigindex/gates.js +109 -0
- package/dist/rigindex/graph.d.ts +31 -0
- package/dist/rigindex/graph.d.ts.map +1 -0
- package/dist/rigindex/graph.js +120 -0
- package/dist/rigindex/index.d.ts +23 -0
- package/dist/rigindex/index.d.ts.map +1 -0
- package/dist/rigindex/index.js +112 -0
- package/dist/rigindex/types.d.ts +76 -0
- package/dist/rigindex/types.d.ts.map +1 -0
- package/dist/rigindex/types.js +8 -0
- package/dist/routes/cache-lint.d.ts +41 -0
- package/dist/routes/cache-lint.d.ts.map +1 -0
- package/dist/routes/cache-lint.js +81 -0
- package/dist/routes/draft.d.ts +83 -0
- package/dist/routes/draft.d.ts.map +1 -0
- package/dist/routes/draft.js +135 -0
- package/dist/routes/loader.d.ts +63 -0
- package/dist/routes/loader.d.ts.map +1 -0
- package/dist/routes/loader.js +574 -0
- package/dist/routes/manifest.d.ts +24 -0
- package/dist/routes/manifest.d.ts.map +1 -0
- package/dist/routes/manifest.js +118 -0
- package/dist/routes/resolved-bundle.d.ts +79 -0
- package/dist/routes/resolved-bundle.d.ts.map +1 -0
- package/dist/routes/resolved-bundle.js +148 -0
- package/dist/routes/sampling-config.d.ts +32 -0
- package/dist/routes/sampling-config.d.ts.map +1 -0
- package/dist/routes/sampling-config.js +91 -0
- package/dist/routes/serveability.d.ts +52 -0
- package/dist/routes/serveability.d.ts.map +1 -0
- package/dist/routes/serveability.js +73 -0
- package/dist/routes/template.d.ts +18 -0
- package/dist/routes/template.d.ts.map +1 -0
- package/dist/routes/template.js +94 -0
- package/dist/run/ajv.d.ts +22 -0
- package/dist/run/ajv.d.ts.map +1 -0
- package/dist/run/ajv.js +32 -0
- package/dist/run/cache-handle.d.ts +58 -0
- package/dist/run/cache-handle.d.ts.map +1 -0
- package/dist/run/cache-handle.js +54 -0
- package/dist/run/cache-stamp.d.ts +65 -0
- package/dist/run/cache-stamp.d.ts.map +1 -0
- package/dist/run/cache-stamp.js +0 -0
- package/dist/run/capture-write.d.ts +33 -0
- package/dist/run/capture-write.d.ts.map +1 -0
- package/dist/run/capture-write.js +55 -0
- package/dist/run/cost.d.ts +26 -0
- package/dist/run/cost.d.ts.map +1 -0
- package/dist/run/cost.js +41 -0
- package/dist/run/dispatch.d.ts +99 -0
- package/dist/run/dispatch.d.ts.map +1 -0
- package/dist/run/dispatch.js +191 -0
- package/dist/run/envelope.d.ts +21 -0
- package/dist/run/envelope.d.ts.map +1 -0
- package/dist/run/envelope.js +45 -0
- package/dist/run/grounding.d.ts +56 -0
- package/dist/run/grounding.d.ts.map +1 -0
- package/dist/run/grounding.js +89 -0
- package/dist/run/raw.d.ts +88 -0
- package/dist/run/raw.d.ts.map +1 -0
- package/dist/run/raw.js +286 -0
- package/dist/run/record-attempt.d.ts +40 -0
- package/dist/run/record-attempt.d.ts.map +1 -0
- package/dist/run/record-attempt.js +99 -0
- package/dist/run/repair.d.ts +36 -0
- package/dist/run/repair.d.ts.map +1 -0
- package/dist/run/repair.js +61 -0
- package/dist/run/resolve.d.ts +99 -0
- package/dist/run/resolve.d.ts.map +1 -0
- package/dist/run/resolve.js +203 -0
- package/dist/run/retry.d.ts +19 -0
- package/dist/run/retry.d.ts.map +1 -0
- package/dist/run/retry.js +50 -0
- package/dist/run/run.d.ts +55 -0
- package/dist/run/run.d.ts.map +1 -0
- package/dist/run/run.js +540 -0
- package/dist/run/stream.d.ts +49 -0
- package/dist/run/stream.d.ts.map +1 -0
- package/dist/run/stream.js +87 -0
- package/dist/run/validate.d.ts +15 -0
- package/dist/run/validate.d.ts.map +1 -0
- package/dist/run/validate.js +55 -0
- package/dist/savings/cache-ledger.d.ts +108 -0
- package/dist/savings/cache-ledger.d.ts.map +1 -0
- package/dist/savings/cache-ledger.js +174 -0
- package/dist/savings/cache-reconcile.d.ts +64 -0
- package/dist/savings/cache-reconcile.d.ts.map +1 -0
- package/dist/savings/cache-reconcile.js +59 -0
- package/dist/savings/cache-stats.d.ts +63 -0
- package/dist/savings/cache-stats.d.ts.map +1 -0
- package/dist/savings/cache-stats.js +108 -0
- package/dist/savings/emit.d.ts +38 -0
- package/dist/savings/emit.d.ts.map +1 -0
- package/dist/savings/emit.js +100 -0
- package/dist/savings/odometer.d.ts +32 -0
- package/dist/savings/odometer.d.ts.map +1 -0
- package/dist/savings/odometer.js +70 -0
- package/dist/savings/swap-execute.d.ts +58 -0
- package/dist/savings/swap-execute.d.ts.map +1 -0
- package/dist/savings/swap-execute.js +130 -0
- package/dist/savings/swaps-client.d.ts +55 -0
- package/dist/savings/swaps-client.d.ts.map +1 -0
- package/dist/savings/swaps-client.js +95 -0
- package/dist/settings/api-fetcher.d.ts +39 -0
- package/dist/settings/api-fetcher.d.ts.map +1 -0
- package/dist/settings/api-fetcher.js +92 -0
- package/dist/settings/index.d.ts +10 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +15 -0
- package/dist/settings/task-settings.d.ts +91 -0
- package/dist/settings/task-settings.d.ts.map +1 -0
- package/dist/settings/task-settings.js +116 -0
- package/dist/status.d.ts +77 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +113 -0
- package/dist/telemetry/artifact-store.d.ts +48 -0
- package/dist/telemetry/artifact-store.d.ts.map +1 -0
- package/dist/telemetry/artifact-store.js +189 -0
- package/dist/telemetry/cache-miss-streak.d.ts +79 -0
- package/dist/telemetry/cache-miss-streak.d.ts.map +1 -0
- package/dist/telemetry/cache-miss-streak.js +99 -0
- package/dist/telemetry/capture.d.ts +31 -0
- package/dist/telemetry/capture.d.ts.map +1 -0
- package/dist/telemetry/capture.js +81 -0
- package/dist/telemetry/exporter-setup.d.ts +28 -0
- package/dist/telemetry/exporter-setup.d.ts.map +1 -0
- package/dist/telemetry/exporter-setup.js +34 -0
- package/dist/telemetry/exporter.d.ts +137 -0
- package/dist/telemetry/exporter.d.ts.map +1 -0
- package/dist/telemetry/exporter.js +510 -0
- package/dist/telemetry/health.d.ts +76 -0
- package/dist/telemetry/health.d.ts.map +1 -0
- package/dist/telemetry/health.js +92 -0
- package/dist/telemetry/ingest-protocol.d.ts +310 -0
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -0
- package/dist/telemetry/ingest-protocol.js +363 -0
- package/dist/telemetry/load-error-report.d.ts +24 -0
- package/dist/telemetry/load-error-report.d.ts.map +1 -0
- package/dist/telemetry/load-error-report.js +50 -0
- package/dist/telemetry/otel-map.d.ts +121 -0
- package/dist/telemetry/otel-map.d.ts.map +1 -0
- package/dist/telemetry/otel-map.js +224 -0
- package/dist/telemetry/otel-normalize.d.ts +104 -0
- package/dist/telemetry/otel-normalize.d.ts.map +1 -0
- package/dist/telemetry/otel-normalize.js +530 -0
- package/dist/telemetry/otlp-emitter.d.ts +52 -0
- package/dist/telemetry/otlp-emitter.d.ts.map +1 -0
- package/dist/telemetry/otlp-emitter.js +144 -0
- package/dist/telemetry/otlp-proto.d.ts +29 -0
- package/dist/telemetry/otlp-proto.d.ts.map +1 -0
- package/dist/telemetry/otlp-proto.js +266 -0
- package/dist/telemetry/sinks.d.ts +90 -0
- package/dist/telemetry/sinks.d.ts.map +1 -0
- package/dist/telemetry/sinks.js +180 -0
- package/dist/telemetry/store.d.ts +65 -0
- package/dist/telemetry/store.d.ts.map +1 -0
- package/dist/telemetry/store.js +547 -0
- package/dist/tenancy/api-key-format.d.ts +77 -0
- package/dist/tenancy/api-key-format.d.ts.map +1 -0
- package/dist/tenancy/api-key-format.js +110 -0
- package/dist/tenancy/constants.d.ts +23 -0
- package/dist/tenancy/constants.d.ts.map +1 -0
- package/dist/tenancy/constants.js +25 -0
- package/dist/tenancy/scrub.d.ts +47 -0
- package/dist/tenancy/scrub.d.ts.map +1 -0
- package/dist/tenancy/scrub.js +85 -0
- package/dist/types/config-teaching.d.ts +62 -0
- package/dist/types/config-teaching.d.ts.map +1 -0
- package/dist/types/config-teaching.js +183 -0
- package/dist/types/failures-teaching.d.ts +56 -0
- package/dist/types/failures-teaching.d.ts.map +1 -0
- package/dist/types/failures-teaching.js +177 -0
- package/dist/types/failures.d.ts +27 -0
- package/dist/types/failures.d.ts.map +1 -0
- package/dist/types/failures.js +41 -0
- package/dist/types/provider.d.ts +200 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +40 -0
- package/dist/types/route.d.ts +205 -0
- package/dist/types/route.d.ts.map +1 -0
- package/dist/types/route.js +6 -0
- package/dist/types/telemetry.d.ts +206 -0
- package/dist/types/telemetry.d.ts.map +1 -0
- package/dist/types/telemetry.js +6 -0
- package/dist/validate-cli.d.ts +12 -0
- package/dist/validate-cli.d.ts.map +1 -0
- package/dist/validate-cli.js +57 -0
- package/dist/verify/capture.d.ts +66 -0
- package/dist/verify/capture.d.ts.map +1 -0
- package/dist/verify/capture.js +180 -0
- package/dist/verify/cli-run.d.ts +23 -0
- package/dist/verify/cli-run.d.ts.map +1 -0
- package/dist/verify/cli-run.js +57 -0
- package/dist/verify/diff.d.ts +48 -0
- package/dist/verify/diff.d.ts.map +1 -0
- package/dist/verify/diff.js +157 -0
- package/dist/verify/index.d.ts +17 -0
- package/dist/verify/index.d.ts.map +1 -0
- package/dist/verify/index.js +24 -0
- package/dist/verify/report.d.ts +14 -0
- package/dist/verify/report.d.ts.map +1 -0
- package/dist/verify/report.js +88 -0
- package/dist/verify/types.d.ts +101 -0
- package/dist/verify/types.d.ts.map +1 -0
- package/dist/verify/types.js +17 -0
- package/dist/verify/verify.d.ts +29 -0
- package/dist/verify/verify.d.ts.map +1 -0
- package/dist/verify/verify.js +148 -0
- package/dist/watch/budget.d.ts +19 -0
- package/dist/watch/budget.d.ts.map +1 -0
- package/dist/watch/budget.js +35 -0
- package/dist/watch/evaluate.d.ts +225 -0
- package/dist/watch/evaluate.d.ts.map +1 -0
- package/dist/watch/evaluate.js +155 -0
- package/dist/watch/monitor.d.ts +116 -0
- package/dist/watch/monitor.d.ts.map +1 -0
- package/dist/watch/monitor.js +199 -0
- package/dist/watch/proposals.d.ts +89 -0
- package/dist/watch/proposals.d.ts.map +1 -0
- package/dist/watch/proposals.js +197 -0
- package/dist/watch/run-record.d.ts +64 -0
- package/dist/watch/run-record.d.ts.map +1 -0
- package/dist/watch/run-record.js +86 -0
- package/dist/watch/run-reported.d.ts +20 -0
- package/dist/watch/run-reported.d.ts.map +1 -0
- package/dist/watch/run-reported.js +53 -0
- package/dist/watch/run.d.ts +73 -0
- package/dist/watch/run.d.ts.map +1 -0
- package/dist/watch/run.js +83 -0
- package/dist/watch/state-store.d.ts +48 -0
- package/dist/watch/state-store.d.ts.map +1 -0
- package/dist/watch/state-store.js +86 -0
- package/dist/watch/state.d.ts +21 -0
- package/dist/watch/state.d.ts.map +1 -0
- package/dist/watch/state.js +93 -0
- package/package.json +56 -14
- package/registry/LICENSE +20 -0
- package/registry/leaderboard.json +3639 -0
- package/registry/registry.json +7263 -0
- package/index.js +0 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The rig manifest (modelrig/rig.yaml) — cost-dimensions-design.md §2a.
|
|
4
|
+
* Project-level, optional; absence means "no declared dimensions" and
|
|
5
|
+
* everything continues to work (declaration upgrades, never gates).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.loadManifest = loadManifest;
|
|
9
|
+
exports.missingRequiredDimensions = missingRequiredDimensions;
|
|
10
|
+
exports.warnMissingRequiredDimensions = warnMissingRequiredDimensions;
|
|
11
|
+
exports.resetDimensionWarningsForTest = resetDimensionWarningsForTest;
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
13
|
+
const node_path_1 = require("node:path");
|
|
14
|
+
const yaml_1 = require("yaml");
|
|
15
|
+
const loader_1 = require("./loader");
|
|
16
|
+
const TAG_SAFE_KEY = /^[A-Za-z0-9_]{1,64}$/;
|
|
17
|
+
function isRecord(v) {
|
|
18
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
19
|
+
}
|
|
20
|
+
function parseDimensions(raw, problems) {
|
|
21
|
+
if (raw === undefined || raw === null)
|
|
22
|
+
return [];
|
|
23
|
+
if (!Array.isArray(raw)) {
|
|
24
|
+
problems.push("dimensions must be a list");
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const out = [];
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
for (const [i, d] of raw.entries()) {
|
|
30
|
+
if (!isRecord(d) || typeof d.key !== "string") {
|
|
31
|
+
problems.push(`dimensions[${i}] must be an object with a string key`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!TAG_SAFE_KEY.test(d.key)) {
|
|
35
|
+
problems.push(`dimensions[${i}].key "${d.key}" is not tag-safe (must match [A-Za-z0-9_]{1,64})`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (seen.has(d.key)) {
|
|
39
|
+
problems.push(`duplicate dimension key "${d.key}"`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
seen.add(d.key);
|
|
43
|
+
const label = d.label ?? d.key;
|
|
44
|
+
if (typeof label !== "string" || label === "") {
|
|
45
|
+
problems.push(`dimensions[${i}].label must be a non-empty string`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const required = d.required ?? false;
|
|
49
|
+
if (typeof required !== "boolean") {
|
|
50
|
+
problems.push(`dimensions[${i}].required must be a boolean`);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
out.push(Object.freeze({ key: d.key, label, required }));
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
function loadManifest(rigDir) {
|
|
58
|
+
const manifestPath = (0, node_path_1.join)(rigDir, "rig.yaml");
|
|
59
|
+
if (!(0, node_fs_1.existsSync)(manifestPath))
|
|
60
|
+
return null; // absence never gates
|
|
61
|
+
let doc;
|
|
62
|
+
try {
|
|
63
|
+
doc = (0, yaml_1.parse)((0, node_fs_1.readFileSync)(manifestPath, "utf8"));
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
throw new loader_1.RouteConfigError("invalid YAML in rig manifest", {
|
|
67
|
+
file: manifestPath,
|
|
68
|
+
problems: [err.message],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (!isRecord(doc)) {
|
|
72
|
+
throw new loader_1.RouteConfigError("rig manifest must be a YAML mapping", { file: manifestPath });
|
|
73
|
+
}
|
|
74
|
+
const problems = [];
|
|
75
|
+
if (typeof doc.name !== "string" || doc.name === "") {
|
|
76
|
+
problems.push("name must be a non-empty string");
|
|
77
|
+
}
|
|
78
|
+
const dimensions = parseDimensions(doc.dimensions, problems);
|
|
79
|
+
const contribution = doc.contribution ?? false;
|
|
80
|
+
if (typeof contribution !== "boolean") {
|
|
81
|
+
problems.push("contribution must be a boolean");
|
|
82
|
+
}
|
|
83
|
+
if (problems.length > 0) {
|
|
84
|
+
throw new loader_1.RouteConfigError("invalid rig manifest", { file: manifestPath, problems });
|
|
85
|
+
}
|
|
86
|
+
return Object.freeze({
|
|
87
|
+
name: doc.name,
|
|
88
|
+
dimensions: Object.freeze(dimensions),
|
|
89
|
+
contribution: contribution,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/** Required dimensions with no (non-empty) value in the run's tags — pure. */
|
|
93
|
+
function missingRequiredDimensions(manifest, tags) {
|
|
94
|
+
if (manifest === null)
|
|
95
|
+
return [];
|
|
96
|
+
return manifest.dimensions
|
|
97
|
+
.filter((d) => d.required)
|
|
98
|
+
.filter((d) => {
|
|
99
|
+
const value = tags[d.key];
|
|
100
|
+
return value === undefined || value === "";
|
|
101
|
+
})
|
|
102
|
+
.map((d) => d.key);
|
|
103
|
+
}
|
|
104
|
+
/** Once per process per dimension (spec WS5) — repeated untagged runs stay
|
|
105
|
+
* quiet after the first warning so pipelines aren't spammed. */
|
|
106
|
+
const warnedDimensions = new Set();
|
|
107
|
+
function warnMissingRequiredDimensions(manifest, tags, log = console.warn) {
|
|
108
|
+
for (const key of missingRequiredDimensions(manifest, tags)) {
|
|
109
|
+
if (warnedDimensions.has(key))
|
|
110
|
+
continue;
|
|
111
|
+
warnedDimensions.add(key);
|
|
112
|
+
log(`[modelrig] required dimension "${key}" missing from run tags — costs for these runs ` +
|
|
113
|
+
`will be under-attributed on /costs (declared in rig.yaml)`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function resetDimensionWarningsForTest() {
|
|
117
|
+
warnedDimensions.clear();
|
|
118
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The RESOLVED route bundle — http-gateway spec §13 (Phase D).
|
|
3
|
+
*
|
|
4
|
+
* A `RouteBundle` in memory already has its file references FOLLOWED and
|
|
5
|
+
* INLINED: `loader.ts` reads the schema file into `outputSchema` (a parsed JSON
|
|
6
|
+
* object) and the prompt file into `systemTemplate` (a string), and a MISSING
|
|
7
|
+
* file fails there with a teaching `RouteConfigError` — at deploy, where the
|
|
8
|
+
* developer is, never at request where the customer is (§13.1 rule 6). So the
|
|
9
|
+
* "resolved bundle" the exporter mirrors is a pure, serialisable PROJECTION of
|
|
10
|
+
* an already-loaded bundle; this module is the ONE definition of that shape and
|
|
11
|
+
* of the round-trip both sides use.
|
|
12
|
+
*
|
|
13
|
+
* exporter (SDK) resolveRouteBundle(bundle) → ResolvedRouteBundle + sha
|
|
14
|
+
* → mirrored onto public.routes.bundle / bundle_sha
|
|
15
|
+
* gateway (server) bundleFromResolved(mirrored) → RouteBundle
|
|
16
|
+
* → rig.runBundle(bundle, opts) → the SAME verified pipeline
|
|
17
|
+
*
|
|
18
|
+
* `bundle_sha` is the content hash of the CANONICAL serialisation (keys sorted
|
|
19
|
+
* recursively, array order preserved), so the same bundle always hashes the
|
|
20
|
+
* same and the console can flag a mirror that no longer matches git (§13.1
|
|
21
|
+
* rule 5). The hash is computed once, at sync time, from the resolved bundle.
|
|
22
|
+
*
|
|
23
|
+
* `fingerprintCell` is NOT carried on the wire: it is derived from
|
|
24
|
+
* `outputSchema` and recomputed on rebuild, so it can never drift from the
|
|
25
|
+
* schema it fingerprints.
|
|
26
|
+
*/
|
|
27
|
+
import type { LoadedRoutes } from "./loader";
|
|
28
|
+
import type { CandidateSpec, Preference, RepairPolicy, Requirement, RouteBundle, RoutePolicy, RouteVariant } from "../types/route";
|
|
29
|
+
/**
|
|
30
|
+
* The canonical, JSON-serialisable form of a resolved route bundle. Every field
|
|
31
|
+
* here defines how the route BEHAVES — the gateway needs all of them to drive
|
|
32
|
+
* the verified pipeline without the customer's filesystem. `fingerprintCell` is
|
|
33
|
+
* deliberately absent (derived from `outputSchema`, recomputed on rebuild).
|
|
34
|
+
*/
|
|
35
|
+
export interface ResolvedRouteBundle {
|
|
36
|
+
readonly route: string;
|
|
37
|
+
readonly version: number;
|
|
38
|
+
/** Resolved, parsed JSON Schema (null = unstructured route). Inlined at sync. */
|
|
39
|
+
readonly outputSchema: object | null;
|
|
40
|
+
readonly candidates: readonly CandidateSpec[];
|
|
41
|
+
readonly require: readonly Requirement[];
|
|
42
|
+
readonly prefer: readonly Preference[];
|
|
43
|
+
/** Raw template text — the prompt FILE, inlined at sync. */
|
|
44
|
+
readonly systemTemplate: string;
|
|
45
|
+
readonly variables: readonly string[];
|
|
46
|
+
readonly policy: RoutePolicy;
|
|
47
|
+
readonly repair?: RepairPolicy;
|
|
48
|
+
readonly variants: readonly RouteVariant[];
|
|
49
|
+
readonly capture: boolean;
|
|
50
|
+
readonly groundingQuery?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Project an already-loaded (resolved) bundle to its serialisable form. Pure —
|
|
53
|
+
* no filesystem; the loader already followed every file reference. */
|
|
54
|
+
export declare function resolveRouteBundle(bundle: RouteBundle): ResolvedRouteBundle;
|
|
55
|
+
/** The canonical serialisation whose hash becomes `bundle_sha`. */
|
|
56
|
+
export declare function canonicalBundleJson(bundle: ResolvedRouteBundle): string;
|
|
57
|
+
/** Content hash of the canonical bundle — `sha256:<hex>`. Self-describing so a
|
|
58
|
+
* future algorithm change is visible in the stored value rather than silent. */
|
|
59
|
+
export declare function hashResolvedBundle(bundle: ResolvedRouteBundle): string;
|
|
60
|
+
/**
|
|
61
|
+
* Rebuild a runnable `RouteBundle` from a mirrored resolved bundle. Recomputes
|
|
62
|
+
* `fingerprintCell` from `outputSchema` (never trusted from the wire) and
|
|
63
|
+
* freezes to match loader output. Throws `RouteConfigError` — the loader's own
|
|
64
|
+
* teaching class — if the mirrored payload is structurally unusable, so a
|
|
65
|
+
* corrupt mirror row surfaces as a teaching error, not a downstream crash.
|
|
66
|
+
*/
|
|
67
|
+
export declare function bundleFromResolved(raw: unknown): RouteBundle;
|
|
68
|
+
/**
|
|
69
|
+
* A `LoadedRoutes` holding exactly ONE bundle — the seam that lets the verified
|
|
70
|
+
* pipeline run over a mirrored bundle without a local routes directory.
|
|
71
|
+
*
|
|
72
|
+
* `run()`/`runStream()` resolve a route only through `deps.routes.get(name)`, so
|
|
73
|
+
* swapping in this store (and nothing else) runs the WHOLE existing pipeline —
|
|
74
|
+
* validate, repair, envelope, telemetry, ZDR (G-3), routing controls (G-2) —
|
|
75
|
+
* over the provided bundle. Asking for any other name is a teaching error, so a
|
|
76
|
+
* mismatched slug can never silently resolve to the wrong route.
|
|
77
|
+
*/
|
|
78
|
+
export declare function singleRouteStore(bundle: RouteBundle): LoadedRoutes;
|
|
79
|
+
//# sourceMappingURL=resolved-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolved-bundle.d.ts","sourceRoot":"","sources":["../../src/routes/resolved-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,gBAAgB,CAAC;AAExB;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CAgB3E;AAiBD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEvE;AAED;gFACgF;AAChF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAsC5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,YAAY,CAclE"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The RESOLVED route bundle — http-gateway spec §13 (Phase D).
|
|
4
|
+
*
|
|
5
|
+
* A `RouteBundle` in memory already has its file references FOLLOWED and
|
|
6
|
+
* INLINED: `loader.ts` reads the schema file into `outputSchema` (a parsed JSON
|
|
7
|
+
* object) and the prompt file into `systemTemplate` (a string), and a MISSING
|
|
8
|
+
* file fails there with a teaching `RouteConfigError` — at deploy, where the
|
|
9
|
+
* developer is, never at request where the customer is (§13.1 rule 6). So the
|
|
10
|
+
* "resolved bundle" the exporter mirrors is a pure, serialisable PROJECTION of
|
|
11
|
+
* an already-loaded bundle; this module is the ONE definition of that shape and
|
|
12
|
+
* of the round-trip both sides use.
|
|
13
|
+
*
|
|
14
|
+
* exporter (SDK) resolveRouteBundle(bundle) → ResolvedRouteBundle + sha
|
|
15
|
+
* → mirrored onto public.routes.bundle / bundle_sha
|
|
16
|
+
* gateway (server) bundleFromResolved(mirrored) → RouteBundle
|
|
17
|
+
* → rig.runBundle(bundle, opts) → the SAME verified pipeline
|
|
18
|
+
*
|
|
19
|
+
* `bundle_sha` is the content hash of the CANONICAL serialisation (keys sorted
|
|
20
|
+
* recursively, array order preserved), so the same bundle always hashes the
|
|
21
|
+
* same and the console can flag a mirror that no longer matches git (§13.1
|
|
22
|
+
* rule 5). The hash is computed once, at sync time, from the resolved bundle.
|
|
23
|
+
*
|
|
24
|
+
* `fingerprintCell` is NOT carried on the wire: it is derived from
|
|
25
|
+
* `outputSchema` and recomputed on rebuild, so it can never drift from the
|
|
26
|
+
* schema it fingerprints.
|
|
27
|
+
*/
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.resolveRouteBundle = resolveRouteBundle;
|
|
30
|
+
exports.canonicalBundleJson = canonicalBundleJson;
|
|
31
|
+
exports.hashResolvedBundle = hashResolvedBundle;
|
|
32
|
+
exports.bundleFromResolved = bundleFromResolved;
|
|
33
|
+
exports.singleRouteStore = singleRouteStore;
|
|
34
|
+
const node_crypto_1 = require("node:crypto");
|
|
35
|
+
const fingerprint_1 = require("../registry/fingerprint");
|
|
36
|
+
const loader_1 = require("./loader");
|
|
37
|
+
/** Project an already-loaded (resolved) bundle to its serialisable form. Pure —
|
|
38
|
+
* no filesystem; the loader already followed every file reference. */
|
|
39
|
+
function resolveRouteBundle(bundle) {
|
|
40
|
+
return {
|
|
41
|
+
route: bundle.route,
|
|
42
|
+
version: bundle.version,
|
|
43
|
+
outputSchema: bundle.outputSchema,
|
|
44
|
+
candidates: bundle.candidates,
|
|
45
|
+
require: bundle.require,
|
|
46
|
+
prefer: bundle.prefer,
|
|
47
|
+
systemTemplate: bundle.systemTemplate,
|
|
48
|
+
variables: bundle.variables,
|
|
49
|
+
policy: bundle.policy,
|
|
50
|
+
...(bundle.repair !== undefined ? { repair: bundle.repair } : {}),
|
|
51
|
+
variants: bundle.variants,
|
|
52
|
+
capture: bundle.capture,
|
|
53
|
+
...(bundle.groundingQuery !== undefined ? { groundingQuery: bundle.groundingQuery } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Deterministic JSON: object keys sorted recursively, array order preserved.
|
|
57
|
+
* The whole point is that the SAME bundle always produces the SAME bytes, so
|
|
58
|
+
* the content hash is stable across processes and machines. */
|
|
59
|
+
function canonicalize(value) {
|
|
60
|
+
if (Array.isArray(value))
|
|
61
|
+
return value.map(canonicalize);
|
|
62
|
+
if (value !== null && typeof value === "object") {
|
|
63
|
+
const out = {};
|
|
64
|
+
for (const key of Object.keys(value).sort()) {
|
|
65
|
+
out[key] = canonicalize(value[key]);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
/** The canonical serialisation whose hash becomes `bundle_sha`. */
|
|
72
|
+
function canonicalBundleJson(bundle) {
|
|
73
|
+
return JSON.stringify(canonicalize(bundle));
|
|
74
|
+
}
|
|
75
|
+
/** Content hash of the canonical bundle — `sha256:<hex>`. Self-describing so a
|
|
76
|
+
* future algorithm change is visible in the stored value rather than silent. */
|
|
77
|
+
function hashResolvedBundle(bundle) {
|
|
78
|
+
return `sha256:${(0, node_crypto_1.createHash)("sha256").update(canonicalBundleJson(bundle)).digest("hex")}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Rebuild a runnable `RouteBundle` from a mirrored resolved bundle. Recomputes
|
|
82
|
+
* `fingerprintCell` from `outputSchema` (never trusted from the wire) and
|
|
83
|
+
* freezes to match loader output. Throws `RouteConfigError` — the loader's own
|
|
84
|
+
* teaching class — if the mirrored payload is structurally unusable, so a
|
|
85
|
+
* corrupt mirror row surfaces as a teaching error, not a downstream crash.
|
|
86
|
+
*/
|
|
87
|
+
function bundleFromResolved(raw) {
|
|
88
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
89
|
+
throw new loader_1.RouteConfigError("mirrored route bundle is not an object");
|
|
90
|
+
}
|
|
91
|
+
const b = raw;
|
|
92
|
+
if (typeof b.route !== "string" || b.route === "") {
|
|
93
|
+
throw new loader_1.RouteConfigError("mirrored route bundle is missing `route`");
|
|
94
|
+
}
|
|
95
|
+
if (typeof b.version !== "number" || !Number.isInteger(b.version)) {
|
|
96
|
+
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing a valid \`version\``);
|
|
97
|
+
}
|
|
98
|
+
if (!Array.isArray(b.candidates) || b.candidates.length === 0) {
|
|
99
|
+
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" has no candidates`);
|
|
100
|
+
}
|
|
101
|
+
if (typeof b.systemTemplate !== "string") {
|
|
102
|
+
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing \`systemTemplate\``);
|
|
103
|
+
}
|
|
104
|
+
if (b.policy === undefined || b.policy === null) {
|
|
105
|
+
throw new loader_1.RouteConfigError(`mirrored route bundle "${b.route}" is missing \`policy\``);
|
|
106
|
+
}
|
|
107
|
+
const outputSchema = b.outputSchema ?? null;
|
|
108
|
+
return Object.freeze({
|
|
109
|
+
route: b.route,
|
|
110
|
+
version: b.version,
|
|
111
|
+
outputSchema: outputSchema === null ? null : Object.freeze(outputSchema),
|
|
112
|
+
candidates: Object.freeze([...b.candidates]),
|
|
113
|
+
require: Object.freeze([...(b.require ?? [])]),
|
|
114
|
+
prefer: Object.freeze([...(b.prefer ?? [])]),
|
|
115
|
+
systemTemplate: b.systemTemplate,
|
|
116
|
+
variables: Object.freeze([...(b.variables ?? [])]),
|
|
117
|
+
policy: b.policy,
|
|
118
|
+
...(b.repair !== undefined ? { repair: b.repair } : {}),
|
|
119
|
+
variants: Object.freeze([...(b.variants ?? [])]),
|
|
120
|
+
capture: b.capture === true,
|
|
121
|
+
...(b.groundingQuery !== undefined ? { groundingQuery: b.groundingQuery } : {}),
|
|
122
|
+
// Recomputed, never trusted from the wire — cannot drift from the schema.
|
|
123
|
+
fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* A `LoadedRoutes` holding exactly ONE bundle — the seam that lets the verified
|
|
128
|
+
* pipeline run over a mirrored bundle without a local routes directory.
|
|
129
|
+
*
|
|
130
|
+
* `run()`/`runStream()` resolve a route only through `deps.routes.get(name)`, so
|
|
131
|
+
* swapping in this store (and nothing else) runs the WHOLE existing pipeline —
|
|
132
|
+
* validate, repair, envelope, telemetry, ZDR (G-3), routing controls (G-2) —
|
|
133
|
+
* over the provided bundle. Asking for any other name is a teaching error, so a
|
|
134
|
+
* mismatched slug can never silently resolve to the wrong route.
|
|
135
|
+
*/
|
|
136
|
+
function singleRouteStore(bundle) {
|
|
137
|
+
return {
|
|
138
|
+
get(route) {
|
|
139
|
+
if (route !== bundle.route) {
|
|
140
|
+
throw new loader_1.RouteConfigError(`route "${route}" is not the mirrored bundle "${bundle.route}"`);
|
|
141
|
+
}
|
|
142
|
+
return bundle;
|
|
143
|
+
},
|
|
144
|
+
list() {
|
|
145
|
+
return Object.freeze([bundle]);
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-bundle sampling config (CE-6, spec §2/§3) — extracted from loader.ts to
|
|
3
|
+
* keep it under the 700-LOC cap. Pure parsing + the Gemini-3 advisory; the
|
|
4
|
+
* loader calls both and owns the fail-loud aggregation.
|
|
5
|
+
*/
|
|
6
|
+
import type { SamplingParams } from "../types/provider";
|
|
7
|
+
import type { CandidateSpec, RoutePolicy } from "../types/route";
|
|
8
|
+
/**
|
|
9
|
+
* Parse + validate `policy.sampling`. YAML is snake_case (`temperature` /
|
|
10
|
+
* `top_p` / `max_output_tokens`); the parsed block is camelCase
|
|
11
|
+
* (`SamplingParams`). Ranges are the permissive provider envelope — a value the
|
|
12
|
+
* provider then rejects surfaces through the run loop's failure ladder, never a
|
|
13
|
+
* silent clamp here (spec §3/§6). Every violation is a config error at load
|
|
14
|
+
* (fail-loud). Returns undefined when the block is absent OR empty ⇒ every
|
|
15
|
+
* adapter behaves exactly as pre-CE-6.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseSampling(raw: unknown, field: string, problems: string[]): SamplingParams | undefined;
|
|
18
|
+
/** A Gemini-3.x model id (gemini-3.0-*, gemini-3.1-*, gemini-3-*). Google
|
|
19
|
+
* recommends temperature=1.0 for the whole Gemini-3 family (CE-6 §3). */
|
|
20
|
+
export declare function isGemini3Model(model: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* CE-6 §3/§6: warn (non-fatal) when a route declares a sub-1.0 temperature on a
|
|
23
|
+
* Gemini-3 candidate. Google STRONGLY recommends temperature=1.0 for Gemini 3
|
|
24
|
+
* and warns sub-1.0 values can loop / degrade on complex reasoning tasks
|
|
25
|
+
* (classification/extraction are typically fine — which is why the source
|
|
26
|
+
* pipeline ran gemini-3.1-pro at 0.1 for classification without looping). The
|
|
27
|
+
* route still LOADS and the request is still sent AS DECLARED — the honest
|
|
28
|
+
* middle: the customer asked, we told them, the request goes as asked. Returns
|
|
29
|
+
* the warning line, or null when no advisory applies.
|
|
30
|
+
*/
|
|
31
|
+
export declare function gemini3LowTemperatureWarning(route: string, policy: RoutePolicy, candidates: readonly CandidateSpec[]): string | null;
|
|
32
|
+
//# sourceMappingURL=sampling-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampling-config.d.ts","sourceRoot":"","sources":["../../src/routes/sampling-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAMjE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,cAAc,GAAG,SAAS,CAmC5B;AAED;yEACyE;AACzE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,SAAS,aAAa,EAAE,GACnC,MAAM,GAAG,IAAI,CAaf"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Route-bundle sampling config (CE-6, spec §2/§3) — extracted from loader.ts to
|
|
4
|
+
* keep it under the 700-LOC cap. Pure parsing + the Gemini-3 advisory; the
|
|
5
|
+
* loader calls both and owns the fail-loud aggregation.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.parseSampling = parseSampling;
|
|
9
|
+
exports.isGemini3Model = isGemini3Model;
|
|
10
|
+
exports.gemini3LowTemperatureWarning = gemini3LowTemperatureWarning;
|
|
11
|
+
function isRecord(v) {
|
|
12
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse + validate `policy.sampling`. YAML is snake_case (`temperature` /
|
|
16
|
+
* `top_p` / `max_output_tokens`); the parsed block is camelCase
|
|
17
|
+
* (`SamplingParams`). Ranges are the permissive provider envelope — a value the
|
|
18
|
+
* provider then rejects surfaces through the run loop's failure ladder, never a
|
|
19
|
+
* silent clamp here (spec §3/§6). Every violation is a config error at load
|
|
20
|
+
* (fail-loud). Returns undefined when the block is absent OR empty ⇒ every
|
|
21
|
+
* adapter behaves exactly as pre-CE-6.
|
|
22
|
+
*/
|
|
23
|
+
function parseSampling(raw, field, problems) {
|
|
24
|
+
if (raw === undefined || raw === null)
|
|
25
|
+
return undefined;
|
|
26
|
+
if (!isRecord(raw)) {
|
|
27
|
+
problems.push(`${field} must be an object {temperature?, top_p?, max_output_tokens?}`);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const out = {};
|
|
31
|
+
const t = raw.temperature;
|
|
32
|
+
if (t !== undefined) {
|
|
33
|
+
if (typeof t !== "number" || !Number.isFinite(t) || t < 0 || t > 2) {
|
|
34
|
+
problems.push(`${field}.temperature must be a number in [0, 2]`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
out.temperature = t;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const p = raw.top_p;
|
|
41
|
+
if (p !== undefined) {
|
|
42
|
+
if (typeof p !== "number" || !Number.isFinite(p) || p <= 0 || p > 1) {
|
|
43
|
+
problems.push(`${field}.top_p must be a number in (0, 1]`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
out.topP = p;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const m = raw.max_output_tokens;
|
|
50
|
+
if (m !== undefined) {
|
|
51
|
+
if (typeof m !== "number" || !Number.isInteger(m) || m < 1) {
|
|
52
|
+
problems.push(`${field}.max_output_tokens must be an integer >= 1`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
out.maxOutputTokens = m;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (out.temperature === undefined && out.topP === undefined && out.maxOutputTokens === undefined) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return Object.freeze(out);
|
|
62
|
+
}
|
|
63
|
+
/** A Gemini-3.x model id (gemini-3.0-*, gemini-3.1-*, gemini-3-*). Google
|
|
64
|
+
* recommends temperature=1.0 for the whole Gemini-3 family (CE-6 §3). */
|
|
65
|
+
function isGemini3Model(model) {
|
|
66
|
+
return /^gemini-3(\.\d+)?[-.]/.test(model) || model === "gemini-3";
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* CE-6 §3/§6: warn (non-fatal) when a route declares a sub-1.0 temperature on a
|
|
70
|
+
* Gemini-3 candidate. Google STRONGLY recommends temperature=1.0 for Gemini 3
|
|
71
|
+
* and warns sub-1.0 values can loop / degrade on complex reasoning tasks
|
|
72
|
+
* (classification/extraction are typically fine — which is why the source
|
|
73
|
+
* pipeline ran gemini-3.1-pro at 0.1 for classification without looping). The
|
|
74
|
+
* route still LOADS and the request is still sent AS DECLARED — the honest
|
|
75
|
+
* middle: the customer asked, we told them, the request goes as asked. Returns
|
|
76
|
+
* the warning line, or null when no advisory applies.
|
|
77
|
+
*/
|
|
78
|
+
function gemini3LowTemperatureWarning(route, policy, candidates) {
|
|
79
|
+
const temp = policy.sampling?.temperature;
|
|
80
|
+
if (temp === undefined || temp >= 1.0)
|
|
81
|
+
return null;
|
|
82
|
+
const affected = candidates.filter((c) => c.provider === "gemini" && isGemini3Model(c.model));
|
|
83
|
+
if (affected.length === 0)
|
|
84
|
+
return null;
|
|
85
|
+
const models = affected.map((c) => c.model).join(", ");
|
|
86
|
+
return (`route "${route}" declares policy.sampling.temperature=${temp} for Gemini-3 candidate(s) ` +
|
|
87
|
+
`[${models}]. Google recommends temperature=1.0 for Gemini 3; values <1.0 can cause looping / ` +
|
|
88
|
+
`degraded output on complex reasoning tasks (classification/extraction are typically fine). ` +
|
|
89
|
+
`The route loads and the request is sent as declared. ` +
|
|
90
|
+
`Docs: https://ai.google.dev/gemini-api/docs/gemini-3`);
|
|
91
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load-time route serveability — Phase 4 resilience (architect-flagged
|
|
3
|
+
* change to the Phase-1 fail-fast guard).
|
|
4
|
+
*
|
|
5
|
+
* A declared candidate whose provider has no registered adapter (no API key
|
|
6
|
+
* in THIS environment) is INERT, not fatal: the gateway must not crash at
|
|
7
|
+
* boot because a bake-off challenger arm lacks a key here. This is the
|
|
8
|
+
* "safe but inert" behaviour the route-v3 commit assumed — true on the
|
|
9
|
+
* InferWealth cutover wrapper (it catches + falls back to legacy), but the
|
|
10
|
+
* standalone modelrig-server builds the rig eagerly at boot with no catch,
|
|
11
|
+
* so a keyless arm downed staging.
|
|
12
|
+
*
|
|
13
|
+
* Rule: warn per inert candidate and keep serving on the keyed ones; a route
|
|
14
|
+
* with ZERO serveable candidates is still a hard error (genuinely dead). The
|
|
15
|
+
* candidate-set UPPER bound is untouched — resolveCandidates still only
|
|
16
|
+
* yields declared candidates, and the run loop skips inert ones at dispatch.
|
|
17
|
+
*/
|
|
18
|
+
import type { RigFailure } from "../types/failures";
|
|
19
|
+
import type { CandidateRef } from "../types/provider";
|
|
20
|
+
import type { CandidateSpec } from "../types/route";
|
|
21
|
+
/** One route's inert candidates, structured so surfaces beyond the log —
|
|
22
|
+
* the server boot banner and console /setup (F1) — can name them and say
|
|
23
|
+
* exactly which env var fixes each. */
|
|
24
|
+
export interface ServeabilityWarning {
|
|
25
|
+
readonly route: string;
|
|
26
|
+
/** Declared candidates with no adapter in this environment. */
|
|
27
|
+
readonly inert: readonly CandidateSpec[];
|
|
28
|
+
/** Distinct providers behind `inert`, in declaration order. */
|
|
29
|
+
readonly missingProviders: readonly string[];
|
|
30
|
+
/** How many candidates CAN serve — the route is alive on these. */
|
|
31
|
+
readonly serveableCount: number;
|
|
32
|
+
/** The log/banner line (what `checkServeability` returns). */
|
|
33
|
+
readonly message: string;
|
|
34
|
+
/** The teaching half: the env vars to set, named. */
|
|
35
|
+
readonly fixHint: string;
|
|
36
|
+
}
|
|
37
|
+
/** Typed failure for an inert (keyless) candidate the run loop skips at
|
|
38
|
+
* dispatch — non-terminal config_auth so the loop advances to the next
|
|
39
|
+
* declared candidate; surfaced as the run's error only if EVERY candidate
|
|
40
|
+
* is inert. */
|
|
41
|
+
export declare function inertCandidateFailure(candidate: CandidateRef, route: string): RigFailure;
|
|
42
|
+
export declare function serveabilityWarnings(bundles: ReadonlyArray<{
|
|
43
|
+
readonly route: string;
|
|
44
|
+
readonly candidates: readonly CandidateSpec[];
|
|
45
|
+
}>, hasAdapter: (provider: string) => boolean): ServeabilityWarning[];
|
|
46
|
+
/** String façade over {@link serveabilityWarnings} — one traversal, one
|
|
47
|
+
* source of wording. Throws identically on a zero-serveable route. */
|
|
48
|
+
export declare function checkServeability(bundles: ReadonlyArray<{
|
|
49
|
+
readonly route: string;
|
|
50
|
+
readonly candidates: readonly CandidateSpec[];
|
|
51
|
+
}>, hasAdapter: (provider: string) => boolean): string[];
|
|
52
|
+
//# sourceMappingURL=serveability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serveability.d.ts","sourceRoot":"","sources":["../../src/routes/serveability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;uCAEuC;AACvC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,mEAAmE;IACnE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAMD;;;eAGe;AACf,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAUxF;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAC,EACjG,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GACxC,mBAAmB,EAAE,CA4BvB;AAED;sEACsE;AACtE,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAC,EACjG,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GACxC,MAAM,EAAE,CAEV"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Load-time route serveability — Phase 4 resilience (architect-flagged
|
|
4
|
+
* change to the Phase-1 fail-fast guard).
|
|
5
|
+
*
|
|
6
|
+
* A declared candidate whose provider has no registered adapter (no API key
|
|
7
|
+
* in THIS environment) is INERT, not fatal: the gateway must not crash at
|
|
8
|
+
* boot because a bake-off challenger arm lacks a key here. This is the
|
|
9
|
+
* "safe but inert" behaviour the route-v3 commit assumed — true on the
|
|
10
|
+
* InferWealth cutover wrapper (it catches + falls back to legacy), but the
|
|
11
|
+
* standalone modelrig-server builds the rig eagerly at boot with no catch,
|
|
12
|
+
* so a keyless arm downed staging.
|
|
13
|
+
*
|
|
14
|
+
* Rule: warn per inert candidate and keep serving on the keyed ones; a route
|
|
15
|
+
* with ZERO serveable candidates is still a hard error (genuinely dead). The
|
|
16
|
+
* candidate-set UPPER bound is untouched — resolveCandidates still only
|
|
17
|
+
* yields declared candidates, and the run loop skips inert ones at dispatch.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.inertCandidateFailure = inertCandidateFailure;
|
|
21
|
+
exports.serveabilityWarnings = serveabilityWarnings;
|
|
22
|
+
exports.checkServeability = checkServeability;
|
|
23
|
+
const config_1 = require("../config");
|
|
24
|
+
const loader_1 = require("./loader");
|
|
25
|
+
function envVarFor(provider) {
|
|
26
|
+
return config_1.PROVIDER_KEY_ENV[provider] ?? `${provider.toUpperCase()}_API_KEY`;
|
|
27
|
+
}
|
|
28
|
+
/** Typed failure for an inert (keyless) candidate the run loop skips at
|
|
29
|
+
* dispatch — non-terminal config_auth so the loop advances to the next
|
|
30
|
+
* declared candidate; surfaced as the run's error only if EVERY candidate
|
|
31
|
+
* is inert. */
|
|
32
|
+
function inertCandidateFailure(candidate, route) {
|
|
33
|
+
return {
|
|
34
|
+
class: "config_auth",
|
|
35
|
+
message: `provider "${candidate.provider}" has no adapter (declared by route "${route}") — ` +
|
|
36
|
+
`its API key is not configured; skipping this candidate`,
|
|
37
|
+
provider: candidate.provider,
|
|
38
|
+
model: candidate.model,
|
|
39
|
+
fixHint: `configure the ${candidate.provider} API key to enable this candidate`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function serveabilityWarnings(bundles, hasAdapter) {
|
|
43
|
+
const warnings = [];
|
|
44
|
+
for (const bundle of bundles) {
|
|
45
|
+
const serveable = bundle.candidates.filter((c) => hasAdapter(c.provider));
|
|
46
|
+
if (serveable.length === 0) {
|
|
47
|
+
const providers = [...new Set(bundle.candidates.map((c) => c.provider))];
|
|
48
|
+
throw new loader_1.RouteConfigError(`route "${bundle.route}" has no serveable candidate — none of its declared providers ` +
|
|
49
|
+
`[${providers.join(", ")}] has an API key configured ` +
|
|
50
|
+
`(set ${providers.map(envVarFor).join(" or ")})`);
|
|
51
|
+
}
|
|
52
|
+
const inert = bundle.candidates.filter((c) => !hasAdapter(c.provider));
|
|
53
|
+
if (inert.length === 0)
|
|
54
|
+
continue;
|
|
55
|
+
const missingProviders = [...new Set(inert.map((c) => c.provider))];
|
|
56
|
+
warnings.push({
|
|
57
|
+
route: bundle.route,
|
|
58
|
+
inert,
|
|
59
|
+
missingProviders,
|
|
60
|
+
serveableCount: serveable.length,
|
|
61
|
+
message: `route "${bundle.route}": ${inert.length} candidate(s) inert (no API key) — ` +
|
|
62
|
+
`${inert.map((c) => `${c.provider}/${c.model}`).join(", ")}; serving on ` +
|
|
63
|
+
`${serveable.length} keyed candidate(s) until their keys are configured.`,
|
|
64
|
+
fixHint: `set ${missingProviders.map(envVarFor).join(", ")} to enable these candidates`,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return warnings;
|
|
68
|
+
}
|
|
69
|
+
/** String façade over {@link serveabilityWarnings} — one traversal, one
|
|
70
|
+
* source of wording. Throws identically on a zero-serveable route. */
|
|
71
|
+
function checkServeability(bundles, hasAdapter) {
|
|
72
|
+
return serveabilityWarnings(bundles, hasAdapter).map((w) => w.message);
|
|
73
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template renderer — spec §3, plan §4.
|
|
3
|
+
* Supports {{var}} substitution and capability-conditional blocks:
|
|
4
|
+
* {{#if capability.grounded_native}}...{{/if}}
|
|
5
|
+
* {{#unless capability.structured_native}}...{{/unless}}
|
|
6
|
+
* Deliberately hand-rolled and tiny — NO external template engine (jinja-class
|
|
7
|
+
* engines are a documented CVE surface; see litellm-vendoring-strategy.md §3).
|
|
8
|
+
*/
|
|
9
|
+
import type { CapabilityFlag } from "../types/provider";
|
|
10
|
+
export interface RenderContext {
|
|
11
|
+
readonly variables: Record<string, unknown>;
|
|
12
|
+
readonly capabilities: ReadonlySet<CapabilityFlag>;
|
|
13
|
+
}
|
|
14
|
+
export declare function renderTemplate(template: string, ctx: RenderContext): string;
|
|
15
|
+
/** Distinct {{var}} names referenced anywhere in the template (loader
|
|
16
|
+
* validation: every reference must be a declared variable). */
|
|
17
|
+
export declare function scanTemplateVariables(template: string): readonly string[];
|
|
18
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/routes/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;CACpD;AAuFD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAE3E;AAED;+DAC+D;AAC/D,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAIzE"}
|