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,547 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SQLite telemetry store — spec §5, plan §2. Package-owned storage; zero
|
|
4
|
+
* InferWealth Supabase involvement. Schema created idempotently on open;
|
|
5
|
+
* PRAGMA user_version tracks migrations (v2: fingerprint_cell, Phase 2;
|
|
6
|
+
* v3: captures table + served_variant/repaired_by, Phase 3).
|
|
7
|
+
*
|
|
8
|
+
* PRIVACY (Phase 3 WS4): the `captures` table is created here but NEVER read
|
|
9
|
+
* here — capture access lives exclusively behind telemetry/capture.ts's
|
|
10
|
+
* separate handle. ExportableTelemetryStore MUST NOT gain capture accessors;
|
|
11
|
+
* the export-isolation tests are the tripwire.
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.openTelemetryStore = openTelemetryStore;
|
|
18
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
19
|
+
const node_fs_1 = require("node:fs");
|
|
20
|
+
const node_path_1 = require("node:path");
|
|
21
|
+
const health_1 = require("./health");
|
|
22
|
+
const SCHEMA_SQL = `
|
|
23
|
+
CREATE TABLE IF NOT EXISTS inferences (
|
|
24
|
+
id TEXT PRIMARY KEY,
|
|
25
|
+
ts TEXT NOT NULL,
|
|
26
|
+
route TEXT NOT NULL,
|
|
27
|
+
route_version INTEGER NOT NULL,
|
|
28
|
+
provider TEXT NOT NULL,
|
|
29
|
+
model TEXT NOT NULL,
|
|
30
|
+
requested_tier TEXT NOT NULL,
|
|
31
|
+
served_tier TEXT NOT NULL,
|
|
32
|
+
tokens_in INTEGER NOT NULL,
|
|
33
|
+
tokens_out INTEGER NOT NULL,
|
|
34
|
+
tokens_cached INTEGER NOT NULL,
|
|
35
|
+
cost_estimate_usd REAL NOT NULL,
|
|
36
|
+
latency_ms INTEGER NOT NULL,
|
|
37
|
+
ttfb_ms INTEGER,
|
|
38
|
+
failure_class TEXT,
|
|
39
|
+
attempts_json TEXT NOT NULL,
|
|
40
|
+
tags_json TEXT NOT NULL,
|
|
41
|
+
fingerprint_cell TEXT,
|
|
42
|
+
served_variant TEXT,
|
|
43
|
+
repaired_by TEXT,
|
|
44
|
+
pricing_missing INTEGER NOT NULL DEFAULT 0,
|
|
45
|
+
-- v10 (WS-A cache accounting): cache-write buckets + cache-key/prefix
|
|
46
|
+
-- substrate. Fresh here; v9-and-earlier gain them via the ALTER ladder below.
|
|
47
|
+
tokens_cache_write INTEGER NOT NULL DEFAULT 0,
|
|
48
|
+
tokens_cache_write_1h INTEGER NOT NULL DEFAULT 0,
|
|
49
|
+
cache_key TEXT,
|
|
50
|
+
prefix_fingerprint TEXT
|
|
51
|
+
);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_inferences_route_ts ON inferences (route, ts);
|
|
53
|
+
-- v8 (G-4 observed-health): per-endpoint windowed aggregation filters by
|
|
54
|
+
-- (provider, model, ts). Index-only; no data change.
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_inferences_provider_model_ts ON inferences (provider, model, ts);
|
|
56
|
+
|
|
57
|
+
CREATE TABLE IF NOT EXISTS captures (
|
|
58
|
+
inference_id TEXT PRIMARY KEY,
|
|
59
|
+
ts TEXT NOT NULL,
|
|
60
|
+
route TEXT NOT NULL,
|
|
61
|
+
route_version INTEGER NOT NULL,
|
|
62
|
+
variables_json TEXT NOT NULL,
|
|
63
|
+
output_text TEXT NOT NULL
|
|
64
|
+
);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_captures_route_ts ON captures (route, ts);
|
|
66
|
+
|
|
67
|
+
CREATE TABLE IF NOT EXISTS envelopes (
|
|
68
|
+
envelope_key TEXT PRIMARY KEY,
|
|
69
|
+
budget_usd REAL NOT NULL,
|
|
70
|
+
spent_usd REAL NOT NULL DEFAULT 0,
|
|
71
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'exhausted'))
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
CREATE TABLE IF NOT EXISTS export_state (
|
|
75
|
+
source_id TEXT PRIMARY KEY,
|
|
76
|
+
last_rowid INTEGER NOT NULL DEFAULT 0
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
CREATE TABLE IF NOT EXISTS feedback (
|
|
80
|
+
id TEXT PRIMARY KEY,
|
|
81
|
+
ts TEXT NOT NULL,
|
|
82
|
+
inference_id TEXT,
|
|
83
|
+
episode_key TEXT,
|
|
84
|
+
verdict TEXT NOT NULL CHECK (verdict IN ('up', 'down')),
|
|
85
|
+
score REAL,
|
|
86
|
+
note TEXT,
|
|
87
|
+
source TEXT NOT NULL,
|
|
88
|
+
-- v7 (Phase 6 WS2): the verdict's own tenant and author. NULL org_id means
|
|
89
|
+
-- "whatever org this exporter is", which is the right answer for every
|
|
90
|
+
-- self-hosted rig; a non-null one is a verdict recorded THROUGH a server on
|
|
91
|
+
-- behalf of another org, and the exporter must not overwrite it (QA-P6-010).
|
|
92
|
+
org_id TEXT,
|
|
93
|
+
created_by TEXT
|
|
94
|
+
);
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_feedback_inference ON feedback (inference_id);
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_feedback_episode ON feedback (episode_key);
|
|
97
|
+
|
|
98
|
+
-- v9 (Expansion E2 chunk A): the execution graph's local buffer.
|
|
99
|
+
--
|
|
100
|
+
-- runs is a PROJECTION (PK on id): run.start inserts a running row and run.end
|
|
101
|
+
-- UPDATEs it to a terminal status in place -- a run is genuinely mutable
|
|
102
|
+
-- (start -> end). A rowid watermark cannot re-export an updated row (UPDATE does
|
|
103
|
+
-- not move rowid), so the exporter waters off export_seq, a monotonic counter
|
|
104
|
+
-- bumped on EVERY write (insert or update). run.end bumps it, so the terminal
|
|
105
|
+
-- state re-exports; and because there is one row per id, a batch never carries
|
|
106
|
+
-- the same (org_id,id) twice -- which a merge=true upsert (DO UPDATE) would
|
|
107
|
+
-- reject with "cannot affect row a second time". The server merge collapses
|
|
108
|
+
-- the two exports into the one mutable row.
|
|
109
|
+
CREATE TABLE IF NOT EXISTS runs (
|
|
110
|
+
id TEXT PRIMARY KEY,
|
|
111
|
+
pipeline TEXT NOT NULL,
|
|
112
|
+
pipeline_version TEXT,
|
|
113
|
+
environment TEXT,
|
|
114
|
+
episode_key TEXT,
|
|
115
|
+
started_at TEXT NOT NULL,
|
|
116
|
+
ended_at TEXT,
|
|
117
|
+
status TEXT NOT NULL CHECK (status IN ('running','succeeded','failed','abandoned')),
|
|
118
|
+
export_seq INTEGER NOT NULL
|
|
119
|
+
);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_runs_export_seq ON runs (export_seq);
|
|
121
|
+
|
|
122
|
+
-- steps are FACTS -- one row per attempt. The composite PK makes a re-emit a
|
|
123
|
+
-- harmless INSERT-OR-IGNORE (server is merge=false too). rowid still exists (not
|
|
124
|
+
-- WITHOUT ROWID), so the watermark read works identically to the other streams.
|
|
125
|
+
CREATE TABLE IF NOT EXISTS steps (
|
|
126
|
+
run_id TEXT NOT NULL,
|
|
127
|
+
step_key TEXT NOT NULL,
|
|
128
|
+
attempt_no INTEGER NOT NULL,
|
|
129
|
+
task TEXT,
|
|
130
|
+
provenance TEXT NOT NULL CHECK (provenance IN ('ground-truth','attested')),
|
|
131
|
+
inference_id TEXT,
|
|
132
|
+
span_trace_id TEXT,
|
|
133
|
+
span_id TEXT,
|
|
134
|
+
started_at TEXT NOT NULL,
|
|
135
|
+
ended_at TEXT,
|
|
136
|
+
failure_class TEXT,
|
|
137
|
+
PRIMARY KEY (run_id, step_key, attempt_no)
|
|
138
|
+
);
|
|
139
|
+
CREATE INDEX IF NOT EXISTS idx_steps_run ON steps (run_id);
|
|
140
|
+
`;
|
|
141
|
+
function toRunRow(r) {
|
|
142
|
+
return {
|
|
143
|
+
id: r.id,
|
|
144
|
+
pipeline: r.pipeline,
|
|
145
|
+
pipelineVersion: r.pipeline_version,
|
|
146
|
+
environment: r.environment,
|
|
147
|
+
episodeKey: r.episode_key,
|
|
148
|
+
startedAt: r.started_at,
|
|
149
|
+
endedAt: r.ended_at,
|
|
150
|
+
status: r.status,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function toStepRow(r) {
|
|
154
|
+
return {
|
|
155
|
+
runId: r.run_id,
|
|
156
|
+
stepKey: r.step_key,
|
|
157
|
+
attemptNo: r.attempt_no,
|
|
158
|
+
task: r.task,
|
|
159
|
+
provenance: r.provenance,
|
|
160
|
+
inferenceId: r.inference_id,
|
|
161
|
+
spanTraceId: r.span_trace_id,
|
|
162
|
+
spanId: r.span_id,
|
|
163
|
+
startedAt: r.started_at,
|
|
164
|
+
endedAt: r.ended_at,
|
|
165
|
+
failureClass: r.failure_class,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function toFeedbackRow(r) {
|
|
169
|
+
return {
|
|
170
|
+
id: r.id,
|
|
171
|
+
ts: r.ts,
|
|
172
|
+
inferenceId: r.inference_id,
|
|
173
|
+
episodeKey: r.episode_key,
|
|
174
|
+
verdict: r.verdict,
|
|
175
|
+
score: r.score,
|
|
176
|
+
note: r.note,
|
|
177
|
+
source: r.source,
|
|
178
|
+
// `?? null` rather than a bare read: a v6 database returns `undefined`
|
|
179
|
+
// for a column that did not exist when its rows were written, and
|
|
180
|
+
// `undefined` would serialize to a MISSING key on the wire rather than an
|
|
181
|
+
// explicit null — which reads to the server as "no opinion" instead of
|
|
182
|
+
// "no org", a distinction that matters exactly once and expensively.
|
|
183
|
+
orgId: r.org_id ?? null,
|
|
184
|
+
createdBy: r.created_by ?? null,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function toTelemetryRow(r) {
|
|
188
|
+
return {
|
|
189
|
+
id: r.id,
|
|
190
|
+
ts: r.ts,
|
|
191
|
+
route: r.route,
|
|
192
|
+
routeVersion: r.route_version,
|
|
193
|
+
provider: r.provider,
|
|
194
|
+
model: r.model,
|
|
195
|
+
requestedTier: r.requested_tier,
|
|
196
|
+
servedTier: r.served_tier,
|
|
197
|
+
tokensIn: r.tokens_in,
|
|
198
|
+
tokensOut: r.tokens_out,
|
|
199
|
+
tokensCached: r.tokens_cached,
|
|
200
|
+
costEstimateUsd: r.cost_estimate_usd,
|
|
201
|
+
latencyMs: r.latency_ms,
|
|
202
|
+
ttfbMs: r.ttfb_ms,
|
|
203
|
+
failureClass: r.failure_class,
|
|
204
|
+
attemptsJson: r.attempts_json,
|
|
205
|
+
tagsJson: r.tags_json,
|
|
206
|
+
fingerprintCell: r.fingerprint_cell,
|
|
207
|
+
servedVariant: r.served_variant,
|
|
208
|
+
repairedBy: r.repaired_by,
|
|
209
|
+
pricingMissing: r.pricing_missing !== 0,
|
|
210
|
+
// `?? 0` / `?? null`: a v9-or-earlier database returns undefined for a v10
|
|
211
|
+
// ALTER column, and those rows genuinely predate cache accounting (WS-A).
|
|
212
|
+
tokensCacheWrite: r.tokens_cache_write ?? 0,
|
|
213
|
+
tokensCacheWrite1h: r.tokens_cache_write_1h ?? 0,
|
|
214
|
+
cacheKey: r.cache_key ?? null,
|
|
215
|
+
prefixFingerprint: r.prefix_fingerprint ?? null,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function toEnvelopeRow(r) {
|
|
219
|
+
return {
|
|
220
|
+
envelopeKey: r.envelope_key,
|
|
221
|
+
budgetUsd: r.budget_usd,
|
|
222
|
+
spentUsd: r.spent_usd,
|
|
223
|
+
status: r.status,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function openTelemetryStore(dbPath) {
|
|
227
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(dbPath), { recursive: true });
|
|
228
|
+
const db = new better_sqlite3_1.default(dbPath);
|
|
229
|
+
db.pragma("journal_mode = WAL");
|
|
230
|
+
db.exec(SCHEMA_SQL);
|
|
231
|
+
// Migrations, idempotent on every open. Fresh databases get the full v2
|
|
232
|
+
// schema from SCHEMA_SQL above; v1 databases (tables pre-existing, so the
|
|
233
|
+
// CREATEs were no-ops) gain the fingerprint_cell column additively —
|
|
234
|
+
// existing rows are untouched and read back with fingerprint_cell = NULL.
|
|
235
|
+
if (db.pragma("user_version", { simple: true }) < 2) {
|
|
236
|
+
const columns = db.prepare("PRAGMA table_info(inferences)").all();
|
|
237
|
+
if (!columns.some((c) => c.name === "fingerprint_cell")) {
|
|
238
|
+
db.exec("ALTER TABLE inferences ADD COLUMN fingerprint_cell TEXT");
|
|
239
|
+
}
|
|
240
|
+
db.pragma("user_version = 2");
|
|
241
|
+
}
|
|
242
|
+
// v3 (Phase 3): captures table (from SCHEMA_SQL above — a no-op CREATE on
|
|
243
|
+
// fresh databases) + the variant/repair columns, additive and nullable.
|
|
244
|
+
if (db.pragma("user_version", { simple: true }) < 3) {
|
|
245
|
+
const columns = db.prepare("PRAGMA table_info(inferences)").all();
|
|
246
|
+
if (!columns.some((c) => c.name === "served_variant")) {
|
|
247
|
+
db.exec("ALTER TABLE inferences ADD COLUMN served_variant TEXT");
|
|
248
|
+
}
|
|
249
|
+
if (!columns.some((c) => c.name === "repaired_by")) {
|
|
250
|
+
db.exec("ALTER TABLE inferences ADD COLUMN repaired_by TEXT");
|
|
251
|
+
}
|
|
252
|
+
db.pragma("user_version = 3");
|
|
253
|
+
}
|
|
254
|
+
// v4 (addendum A1): pricing_missing flag — additive; old rows read false.
|
|
255
|
+
if (db.pragma("user_version", { simple: true }) < 4) {
|
|
256
|
+
const columns = db.prepare("PRAGMA table_info(inferences)").all();
|
|
257
|
+
if (!columns.some((c) => c.name === "pricing_missing")) {
|
|
258
|
+
db.exec("ALTER TABLE inferences ADD COLUMN pricing_missing INTEGER NOT NULL DEFAULT 0");
|
|
259
|
+
}
|
|
260
|
+
db.pragma("user_version = 4");
|
|
261
|
+
}
|
|
262
|
+
// v5 (Phase 4 WS2): feedback table — purely additive; SCHEMA_SQL's
|
|
263
|
+
// CREATE IF NOT EXISTS handles fresh AND migrating databases identically,
|
|
264
|
+
// so the bump only stamps the version.
|
|
265
|
+
if (db.pragma("user_version", { simple: true }) < 5) {
|
|
266
|
+
db.pragma("user_version = 5");
|
|
267
|
+
}
|
|
268
|
+
// v6 (Phase 4 WS3): ttfb_ms — additive, nullable; old rows read null.
|
|
269
|
+
if (db.pragma("user_version", { simple: true }) < 6) {
|
|
270
|
+
const columns = db.prepare("PRAGMA table_info(inferences)").all();
|
|
271
|
+
if (!columns.some((c) => c.name === "ttfb_ms")) {
|
|
272
|
+
db.exec("ALTER TABLE inferences ADD COLUMN ttfb_ms INTEGER");
|
|
273
|
+
}
|
|
274
|
+
db.pragma("user_version = 6");
|
|
275
|
+
}
|
|
276
|
+
// v7 (Phase 6 WS2): feedback.org_id + feedback.created_by — additive,
|
|
277
|
+
// nullable. Old verdicts read null on both, which is TRUE of them: they were
|
|
278
|
+
// recorded before either concept existed, and backfilling a guess into an
|
|
279
|
+
// unrecomputable record is exactly what 00017 refused to do.
|
|
280
|
+
if (db.pragma("user_version", { simple: true }) < 7) {
|
|
281
|
+
const columns = db.prepare("PRAGMA table_info(feedback)").all();
|
|
282
|
+
if (!columns.some((c) => c.name === "org_id")) {
|
|
283
|
+
db.exec("ALTER TABLE feedback ADD COLUMN org_id TEXT");
|
|
284
|
+
}
|
|
285
|
+
if (!columns.some((c) => c.name === "created_by")) {
|
|
286
|
+
db.exec("ALTER TABLE feedback ADD COLUMN created_by TEXT");
|
|
287
|
+
}
|
|
288
|
+
db.pragma("user_version = 7");
|
|
289
|
+
}
|
|
290
|
+
// v8 (G-4 observed-health): idx_inferences_provider_model_ts — index-only, no
|
|
291
|
+
// data change. SCHEMA_SQL's CREATE INDEX IF NOT EXISTS handles fresh AND
|
|
292
|
+
// migrating databases identically (it ran above), so the bump only stamps the
|
|
293
|
+
// version. Kept explicit rather than folded into v5's bare-stamp branch so the
|
|
294
|
+
// migration ladder reads one rung per schema epoch.
|
|
295
|
+
if (db.pragma("user_version", { simple: true }) < 8) {
|
|
296
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_inferences_provider_model_ts ON inferences (provider, model, ts)");
|
|
297
|
+
db.pragma("user_version = 8");
|
|
298
|
+
}
|
|
299
|
+
// v9 (Expansion E2 chunk A): runs + steps local outbox. Purely additive —
|
|
300
|
+
// SCHEMA_SQL's CREATE TABLE IF NOT EXISTS handles fresh AND migrating
|
|
301
|
+
// databases identically (it ran above), so the bump only stamps the version.
|
|
302
|
+
// A rig that never enables the artifact namespace simply never writes to them.
|
|
303
|
+
if (db.pragma("user_version", { simple: true }) < 9) {
|
|
304
|
+
db.pragma("user_version = 9");
|
|
305
|
+
}
|
|
306
|
+
// v10 (WS-A cache accounting): cache-write buckets + cache-key/prefix
|
|
307
|
+
// substrate. Additive; old rows read 0 / null (true of them — recorded before
|
|
308
|
+
// caching was accounted). Same ALTER pattern as v2–v6, folded over a list.
|
|
309
|
+
if (db.pragma("user_version", { simple: true }) < 10) {
|
|
310
|
+
const cols = db.prepare("PRAGMA table_info(inferences)").all();
|
|
311
|
+
const add = (name, ddl) => {
|
|
312
|
+
if (!cols.some((c) => c.name === name))
|
|
313
|
+
db.exec(`ALTER TABLE inferences ADD COLUMN ${ddl}`);
|
|
314
|
+
};
|
|
315
|
+
add("tokens_cache_write", "tokens_cache_write INTEGER NOT NULL DEFAULT 0");
|
|
316
|
+
add("tokens_cache_write_1h", "tokens_cache_write_1h INTEGER NOT NULL DEFAULT 0");
|
|
317
|
+
add("cache_key", "cache_key TEXT");
|
|
318
|
+
add("prefix_fingerprint", "prefix_fingerprint TEXT");
|
|
319
|
+
db.pragma("user_version = 10");
|
|
320
|
+
}
|
|
321
|
+
const insertInference = db.prepare(`
|
|
322
|
+
INSERT INTO inferences (
|
|
323
|
+
id, ts, route, route_version, provider, model, requested_tier, served_tier,
|
|
324
|
+
tokens_in, tokens_out, tokens_cached, cost_estimate_usd, latency_ms, ttfb_ms,
|
|
325
|
+
failure_class, attempts_json, tags_json, fingerprint_cell, served_variant, repaired_by, pricing_missing,
|
|
326
|
+
tokens_cache_write, tokens_cache_write_1h, cache_key, prefix_fingerprint
|
|
327
|
+
) VALUES (
|
|
328
|
+
@id, @ts, @route, @route_version, @provider, @model, @requested_tier, @served_tier,
|
|
329
|
+
@tokens_in, @tokens_out, @tokens_cached, @cost_estimate_usd, @latency_ms, @ttfb_ms,
|
|
330
|
+
@failure_class, @attempts_json, @tags_json, @fingerprint_cell, @served_variant, @repaired_by, @pricing_missing,
|
|
331
|
+
@tokens_cache_write, @tokens_cache_write_1h, @cache_key, @prefix_fingerprint
|
|
332
|
+
)
|
|
333
|
+
`);
|
|
334
|
+
const selectByTag = db.prepare(`
|
|
335
|
+
SELECT * FROM inferences
|
|
336
|
+
WHERE json_extract(tags_json, '$.' || ?) = ?
|
|
337
|
+
ORDER BY ts, rowid
|
|
338
|
+
`);
|
|
339
|
+
const selectEnvelope = db.prepare("SELECT * FROM envelopes WHERE envelope_key = ?");
|
|
340
|
+
const insertEnvelope = db.prepare(`
|
|
341
|
+
INSERT INTO envelopes (envelope_key, budget_usd, spent_usd, status)
|
|
342
|
+
VALUES (?, ?, 0, 'open')
|
|
343
|
+
ON CONFLICT (envelope_key) DO NOTHING
|
|
344
|
+
`);
|
|
345
|
+
const insertFeedback = db.prepare(`
|
|
346
|
+
INSERT INTO feedback (
|
|
347
|
+
id, ts, inference_id, episode_key, verdict, score, note, source, org_id, created_by
|
|
348
|
+
)
|
|
349
|
+
VALUES (
|
|
350
|
+
@id, @ts, @inference_id, @episode_key, @verdict, @score, @note, @source, @org_id, @created_by
|
|
351
|
+
)
|
|
352
|
+
`);
|
|
353
|
+
const accrueEnvelope = db.prepare(`
|
|
354
|
+
UPDATE envelopes
|
|
355
|
+
SET spent_usd = spent_usd + ?,
|
|
356
|
+
status = CASE WHEN spent_usd + ? >= budget_usd THEN 'exhausted' ELSE status END
|
|
357
|
+
WHERE envelope_key = ?
|
|
358
|
+
`);
|
|
359
|
+
// Upsert the run projection and bump export_seq on every write, so run.end's
|
|
360
|
+
// terminal state re-exports past the `:runs` watermark. better-sqlite3 is
|
|
361
|
+
// synchronous, so the MAX(export_seq)+1 read is race-free.
|
|
362
|
+
const nextRunSeq = db.prepare("SELECT COALESCE(MAX(export_seq), 0) + 1 AS n FROM runs");
|
|
363
|
+
const upsertRun = db.prepare(`
|
|
364
|
+
INSERT INTO runs (id, pipeline, pipeline_version, environment, episode_key, started_at, ended_at, status, export_seq)
|
|
365
|
+
VALUES (@id, @pipeline, @pipeline_version, @environment, @episode_key, @started_at, @ended_at, @status, @export_seq)
|
|
366
|
+
ON CONFLICT (id) DO UPDATE SET
|
|
367
|
+
pipeline = excluded.pipeline,
|
|
368
|
+
pipeline_version = excluded.pipeline_version,
|
|
369
|
+
environment = excluded.environment,
|
|
370
|
+
episode_key = excluded.episode_key,
|
|
371
|
+
started_at = excluded.started_at,
|
|
372
|
+
ended_at = excluded.ended_at,
|
|
373
|
+
status = excluded.status,
|
|
374
|
+
export_seq = excluded.export_seq
|
|
375
|
+
`);
|
|
376
|
+
const insertStep = db.prepare(`
|
|
377
|
+
INSERT OR IGNORE INTO steps (
|
|
378
|
+
run_id, step_key, attempt_no, task, provenance, inference_id, span_trace_id, span_id,
|
|
379
|
+
started_at, ended_at, failure_class
|
|
380
|
+
) VALUES (
|
|
381
|
+
@run_id, @step_key, @attempt_no, @task, @provenance, @inference_id, @span_trace_id, @span_id,
|
|
382
|
+
@started_at, @ended_at, @failure_class
|
|
383
|
+
)
|
|
384
|
+
`);
|
|
385
|
+
return {
|
|
386
|
+
record(row) {
|
|
387
|
+
insertInference.run({
|
|
388
|
+
id: row.id,
|
|
389
|
+
ts: row.ts,
|
|
390
|
+
route: row.route,
|
|
391
|
+
route_version: row.routeVersion,
|
|
392
|
+
provider: row.provider,
|
|
393
|
+
model: row.model,
|
|
394
|
+
requested_tier: row.requestedTier,
|
|
395
|
+
served_tier: row.servedTier,
|
|
396
|
+
tokens_in: row.tokensIn,
|
|
397
|
+
tokens_out: row.tokensOut,
|
|
398
|
+
tokens_cached: row.tokensCached,
|
|
399
|
+
cost_estimate_usd: row.costEstimateUsd,
|
|
400
|
+
latency_ms: row.latencyMs,
|
|
401
|
+
ttfb_ms: row.ttfbMs,
|
|
402
|
+
failure_class: row.failureClass,
|
|
403
|
+
attempts_json: row.attemptsJson,
|
|
404
|
+
tags_json: row.tagsJson,
|
|
405
|
+
fingerprint_cell: row.fingerprintCell,
|
|
406
|
+
served_variant: row.servedVariant,
|
|
407
|
+
repaired_by: row.repairedBy,
|
|
408
|
+
pricing_missing: row.pricingMissing ? 1 : 0,
|
|
409
|
+
// `?? 0` / `?? null`: the fields are optional on TelemetryRow, and
|
|
410
|
+
// better-sqlite3 rejects an `undefined` bound param — a row that omits
|
|
411
|
+
// them is a zero-write / no-key row (fail-closed default).
|
|
412
|
+
tokens_cache_write: row.tokensCacheWrite ?? 0,
|
|
413
|
+
tokens_cache_write_1h: row.tokensCacheWrite1h ?? 0,
|
|
414
|
+
cache_key: row.cacheKey ?? null,
|
|
415
|
+
prefix_fingerprint: row.prefixFingerprint ?? null,
|
|
416
|
+
});
|
|
417
|
+
},
|
|
418
|
+
recordFeedback(row) {
|
|
419
|
+
insertFeedback.run({
|
|
420
|
+
id: row.id,
|
|
421
|
+
ts: row.ts,
|
|
422
|
+
inference_id: row.inferenceId,
|
|
423
|
+
episode_key: row.episodeKey,
|
|
424
|
+
verdict: row.verdict,
|
|
425
|
+
score: row.score,
|
|
426
|
+
note: row.note,
|
|
427
|
+
source: row.source,
|
|
428
|
+
org_id: row.orgId,
|
|
429
|
+
created_by: row.createdBy,
|
|
430
|
+
});
|
|
431
|
+
},
|
|
432
|
+
readFeedbackAfter(afterRowid, limit) {
|
|
433
|
+
const rows = db
|
|
434
|
+
.prepare("SELECT rowid AS __rowid, * FROM feedback WHERE rowid > ? ORDER BY rowid LIMIT ?")
|
|
435
|
+
.all(afterRowid, limit);
|
|
436
|
+
return rows.map((r) => ({ rowid: r.__rowid, row: toFeedbackRow(r) }));
|
|
437
|
+
},
|
|
438
|
+
recordRun(row) {
|
|
439
|
+
const seq = nextRunSeq.get().n;
|
|
440
|
+
upsertRun.run({
|
|
441
|
+
id: row.id,
|
|
442
|
+
pipeline: row.pipeline,
|
|
443
|
+
pipeline_version: row.pipelineVersion,
|
|
444
|
+
environment: row.environment,
|
|
445
|
+
episode_key: row.episodeKey,
|
|
446
|
+
started_at: row.startedAt,
|
|
447
|
+
ended_at: row.endedAt,
|
|
448
|
+
status: row.status,
|
|
449
|
+
export_seq: seq,
|
|
450
|
+
});
|
|
451
|
+
},
|
|
452
|
+
recordStep(row) {
|
|
453
|
+
insertStep.run({
|
|
454
|
+
run_id: row.runId,
|
|
455
|
+
step_key: row.stepKey,
|
|
456
|
+
attempt_no: row.attemptNo,
|
|
457
|
+
task: row.task,
|
|
458
|
+
provenance: row.provenance,
|
|
459
|
+
inference_id: row.inferenceId,
|
|
460
|
+
span_trace_id: row.spanTraceId,
|
|
461
|
+
span_id: row.spanId,
|
|
462
|
+
started_at: row.startedAt,
|
|
463
|
+
ended_at: row.endedAt,
|
|
464
|
+
failure_class: row.failureClass,
|
|
465
|
+
});
|
|
466
|
+
},
|
|
467
|
+
readRunsAfter(afterSeq, limit) {
|
|
468
|
+
// Watermark is export_seq (bumped on every write), NOT rowid — a run.end
|
|
469
|
+
// UPDATE keeps the rowid but advances export_seq, so its terminal state
|
|
470
|
+
// re-exports. The exporter treats the returned handle opaquely.
|
|
471
|
+
const rows = db
|
|
472
|
+
.prepare("SELECT export_seq AS __seq, * FROM runs WHERE export_seq > ? ORDER BY export_seq LIMIT ?")
|
|
473
|
+
.all(afterSeq, limit);
|
|
474
|
+
return rows.map((r) => ({ rowid: r.__seq, row: toRunRow(r) }));
|
|
475
|
+
},
|
|
476
|
+
readStepsAfter(afterRowid, limit) {
|
|
477
|
+
const rows = db
|
|
478
|
+
.prepare("SELECT rowid AS __rowid, * FROM steps WHERE rowid > ? ORDER BY rowid LIMIT ?")
|
|
479
|
+
.all(afterRowid, limit);
|
|
480
|
+
return rows.map((r) => ({ rowid: r.__rowid, row: toStepRow(r) }));
|
|
481
|
+
},
|
|
482
|
+
getStepInferenceId(runId, stepKey) {
|
|
483
|
+
const r = db
|
|
484
|
+
.prepare("SELECT inference_id FROM steps WHERE run_id = ? AND step_key = ? AND inference_id IS NOT NULL " +
|
|
485
|
+
"ORDER BY attempt_no DESC LIMIT 1")
|
|
486
|
+
.get(runId, stepKey);
|
|
487
|
+
return r === undefined ? null : r.inference_id;
|
|
488
|
+
},
|
|
489
|
+
listFeedback(limit) {
|
|
490
|
+
const rows = db
|
|
491
|
+
.prepare("SELECT * FROM feedback ORDER BY ts DESC, rowid DESC LIMIT ?")
|
|
492
|
+
.all(limit);
|
|
493
|
+
return rows.map(toFeedbackRow);
|
|
494
|
+
},
|
|
495
|
+
queryByTag(tag, value) {
|
|
496
|
+
return selectByTag.all(tag, value).map(toTelemetryRow);
|
|
497
|
+
},
|
|
498
|
+
getEnvelope(key) {
|
|
499
|
+
const row = selectEnvelope.get(key);
|
|
500
|
+
return row ? toEnvelopeRow(row) : null;
|
|
501
|
+
},
|
|
502
|
+
openEnvelope(key, budgetUsd) {
|
|
503
|
+
insertEnvelope.run(key, budgetUsd);
|
|
504
|
+
return toEnvelopeRow(selectEnvelope.get(key));
|
|
505
|
+
},
|
|
506
|
+
accrue(key, usd) {
|
|
507
|
+
const result = accrueEnvelope.run(usd, usd, key);
|
|
508
|
+
if (result.changes === 0) {
|
|
509
|
+
throw new Error(`accrue on unopened envelope "${key}" — call openEnvelope first`);
|
|
510
|
+
}
|
|
511
|
+
return toEnvelopeRow(selectEnvelope.get(key));
|
|
512
|
+
},
|
|
513
|
+
readInferencesAfter(afterRowid, limit) {
|
|
514
|
+
const rows = db
|
|
515
|
+
.prepare("SELECT rowid AS __rowid, * FROM inferences WHERE rowid > ? ORDER BY rowid LIMIT ?")
|
|
516
|
+
.all(afterRowid, limit);
|
|
517
|
+
return rows.map((r) => ({ rowid: r.__rowid, row: toTelemetryRow(r) }));
|
|
518
|
+
},
|
|
519
|
+
listEnvelopes() {
|
|
520
|
+
const rows = db.prepare("SELECT * FROM envelopes ORDER BY envelope_key").all();
|
|
521
|
+
return rows.map(toEnvelopeRow);
|
|
522
|
+
},
|
|
523
|
+
getExportWatermark(sourceId) {
|
|
524
|
+
const row = db.prepare("SELECT last_rowid FROM export_state WHERE source_id = ?").get(sourceId);
|
|
525
|
+
return row?.last_rowid ?? 0;
|
|
526
|
+
},
|
|
527
|
+
setExportWatermark(sourceId, lastRowid) {
|
|
528
|
+
db.prepare(`INSERT INTO export_state (source_id, last_rowid) VALUES (?, ?)
|
|
529
|
+
ON CONFLICT (source_id) DO UPDATE SET last_rowid = excluded.last_rowid`).run(sourceId, lastRowid);
|
|
530
|
+
},
|
|
531
|
+
readEndpointHealth(windowMinutes, minN) {
|
|
532
|
+
// Capture `now` once so the SQL prefilter and the in-memory window agree.
|
|
533
|
+
// ts is ISO-8601 UTC (…Z), so lexical >= is chronological >= — the prefilter
|
|
534
|
+
// is exact, and aggregateEndpointHealth re-checks the window defensively.
|
|
535
|
+
const now = Date.now();
|
|
536
|
+
const windowStartIso = new Date(now - windowMinutes * 60000).toISOString();
|
|
537
|
+
const rows = db
|
|
538
|
+
.prepare(`SELECT provider, model, ts, latency_ms, ttfb_ms, failure_class
|
|
539
|
+
FROM inferences WHERE ts >= ?`)
|
|
540
|
+
.all(windowStartIso);
|
|
541
|
+
return (0, health_1.aggregateEndpointHealth)(rows, { windowMinutes, minN, now });
|
|
542
|
+
},
|
|
543
|
+
close() {
|
|
544
|
+
db.close();
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `rig_sk_` key FORMAT — Phase 6 WS2.
|
|
3
|
+
*
|
|
4
|
+
* Shared knowledge, deliberately: the SDK builds the header that presents a
|
|
5
|
+
* key, modelrig-server resolves one, and the oracle decides whether the value
|
|
6
|
+
* it was handed is a key at all. Three packages agreeing on a prefix by
|
|
7
|
+
* copying a string literal is how N1's "one name per concept" fails in
|
|
8
|
+
* practice, so the string lives here and they all import it.
|
|
9
|
+
*
|
|
10
|
+
* What is NOT here is MINTING. Generating a secret and writing its hash is the
|
|
11
|
+
* control plane's job; an SDK that could do it would imply a client could
|
|
12
|
+
* issue itself a credential, which is the shape of the thing this scheme
|
|
13
|
+
* exists to prevent. `mintApiKey` lives in modelrig-server.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The one place this prefix is spelled. Grep-visible on purpose: the
|
|
17
|
+
* guardrails C2 rule keys off it, and so does the exporter's sink selection.
|
|
18
|
+
*/
|
|
19
|
+
export declare const API_KEY_PREFIX = "rig_sk_";
|
|
20
|
+
/** 32 bytes = 256 bits, as base64url. The minting side uses this to generate;
|
|
21
|
+
* this side uses its ENCODED length to recognise. See 00020's header for why
|
|
22
|
+
* that number carries the argument that a plain sha-256 at rest is sound. */
|
|
23
|
+
export declare const API_KEY_SECRET_BYTES = 32;
|
|
24
|
+
/** base64url length of API_KEY_SECRET_BYTES — the minimum a real key's body has. */
|
|
25
|
+
export declare const API_KEY_BODY_MIN_LENGTH = 43;
|
|
26
|
+
/**
|
|
27
|
+
* The granted authorities. Mirrors migration 00020's CHECK constraint (widened
|
|
28
|
+
* by 00033 for content custody) — a test pins that the two agree, because a
|
|
29
|
+
* scope that exists here and not there is a key that cannot be written, and one
|
|
30
|
+
* that exists there and not here is an authority nothing enforces.
|
|
31
|
+
*
|
|
32
|
+
* `artifact-write`/`artifact-read` (E2-C, 00033): request a content upload grant
|
|
33
|
+
* / mint a content download URL. Both are ordinary (non-elevated) machine
|
|
34
|
+
* grants — they move an org's own artifact bytes, they do not spend money or
|
|
35
|
+
* approve swaps (contrast decision/oracle-act, gated to admin/owner minters).
|
|
36
|
+
*
|
|
37
|
+
* `task-settings` (settings-plane, 00043): PATCH a task's governance settings
|
|
38
|
+
* (capture / artifacts / content / scrub). Held by a coding agent flipping
|
|
39
|
+
* settings for the user. READING settings needs no scope — any org-scoped key
|
|
40
|
+
* may read, since settings ride the already-readable task row.
|
|
41
|
+
*/
|
|
42
|
+
export declare const API_KEY_SCOPES: readonly ["ingest", "query", "feedback", "decision", "oracle-act", "artifact-write", "artifact-read", "task-settings"];
|
|
43
|
+
export type ApiKeyScope = (typeof API_KEY_SCOPES)[number];
|
|
44
|
+
/** sha256 of the WHOLE presented string, prefix included — so a caller cannot
|
|
45
|
+
* strip the prefix and land on a different row. */
|
|
46
|
+
export declare function hashApiKeySecret(secret: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Cheap shape check, used to decide which credential branch a bearer token
|
|
49
|
+
* takes before any I/O happens.
|
|
50
|
+
*
|
|
51
|
+
* The minimum body length matters: without it the bare string `rig_sk_` would
|
|
52
|
+
* take the api-key branch and cost a database round trip per garbage request,
|
|
53
|
+
* which is a free amplification primitive on an unauthenticated surface.
|
|
54
|
+
*/
|
|
55
|
+
export declare function looksLikeApiKey(presented: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* What a key may be called in a log line, an error, or a boot banner.
|
|
58
|
+
*
|
|
59
|
+
* Returns the placeholder form for a non-key so that a caller who reaches for
|
|
60
|
+
* this with the wrong variable prints nothing useful rather than printing the
|
|
61
|
+
* whole thing. C2's leak-gate is the belt; this is the braces.
|
|
62
|
+
*/
|
|
63
|
+
export declare function redactApiKey(presented: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Narrow an untrusted scope list to the known set (T7: a jsonb/array column
|
|
66
|
+
* is not proof of shape — narrow at the boundary).
|
|
67
|
+
*
|
|
68
|
+
* Unknown entries are DROPPED, not rejected: a row written by a future
|
|
69
|
+
* migration with a scope this build predates should still authorize the
|
|
70
|
+
* scopes this build understands, rather than failing closed on everything.
|
|
71
|
+
* Returns declaration order so two equal grant sets compare equal.
|
|
72
|
+
*/
|
|
73
|
+
export declare function parseScopes(raw: unknown): ApiKeyScope[];
|
|
74
|
+
/** An empty grant set authorizes nothing — stated as code so it cannot be
|
|
75
|
+
* accidentally re-derived as "no scopes means unrestricted". */
|
|
76
|
+
export declare function hasScope(granted: readonly ApiKeyScope[], required: ApiKeyScope): boolean;
|
|
77
|
+
//# sourceMappingURL=api-key-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-format.d.ts","sourceRoot":"","sources":["../../src/tenancy/api-key-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;GAGG;AACH,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC;;6EAE6E;AAC7E,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,wHASjB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D;mDACmD;AACnD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI1D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,EAAE,CAIvD;AAED;gEACgE;AAChE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAExF"}
|