modelrig 0.4.0 → 0.6.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 +238 -0
- package/README.md +65 -3
- package/dist/adapters/anthropic.d.ts.map +1 -1
- package/dist/adapters/anthropic.js +36 -7
- package/dist/adapters/attempt-meta-map.d.ts +63 -0
- package/dist/adapters/attempt-meta-map.d.ts.map +1 -0
- package/dist/adapters/attempt-meta-map.js +154 -0
- package/dist/adapters/deepseek.d.ts.map +1 -1
- package/dist/adapters/deepseek.js +25 -2
- package/dist/adapters/gemini.d.ts +39 -0
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +82 -4
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +25 -2
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +25 -2
- package/dist/adapters/openai-stream.d.ts +2 -0
- package/dist/adapters/openai-stream.d.ts.map +1 -1
- package/dist/adapters/openai-stream.js +23 -3
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +36 -6
- package/dist/artifacts/artifact.d.ts +3 -2
- package/dist/artifacts/artifact.d.ts.map +1 -1
- package/dist/artifacts/artifact.js +35 -9
- package/dist/artifacts/classification.d.ts +27 -0
- package/dist/artifacts/classification.d.ts.map +1 -0
- package/dist/artifacts/classification.js +38 -0
- package/dist/artifacts/index.d.ts +3 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +10 -1
- package/dist/artifacts/run-context.d.ts +33 -2
- package/dist/artifacts/run-context.d.ts.map +1 -1
- package/dist/artifacts/run-context.js +95 -1
- package/dist/artifacts/scrub.d.ts +26 -0
- package/dist/artifacts/scrub.d.ts.map +1 -1
- package/dist/artifacts/scrub.js +53 -0
- package/dist/artifacts/step.d.ts +9 -0
- package/dist/artifacts/step.d.ts.map +1 -1
- package/dist/artifacts/step.js +9 -0
- package/dist/bakeoff/engine.d.ts +46 -4
- package/dist/bakeoff/engine.d.ts.map +1 -1
- package/dist/bakeoff/engine.js +269 -19
- package/dist/bakeoff/eval-cases.d.ts +5 -0
- package/dist/bakeoff/eval-cases.d.ts.map +1 -1
- package/dist/bakeoff/eval-cases.js +3 -0
- package/dist/bakeoff/judge.d.ts +39 -0
- package/dist/bakeoff/judge.d.ts.map +1 -0
- package/dist/bakeoff/judge.js +102 -0
- package/dist/bakeoff/quality.d.ts +44 -0
- package/dist/bakeoff/quality.d.ts.map +1 -0
- package/dist/bakeoff/quality.js +126 -0
- package/dist/bakeoff/reference.d.ts +34 -0
- package/dist/bakeoff/reference.d.ts.map +1 -0
- package/dist/bakeoff/reference.js +68 -0
- package/dist/bakeoff/replay.d.ts +25 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +65 -2
- package/dist/bakeoff/report.d.ts +8 -1
- package/dist/bakeoff/report.d.ts.map +1 -1
- package/dist/bakeoff/report.js +83 -12
- package/dist/bakeoff/samples.d.ts +35 -2
- package/dist/bakeoff/samples.d.ts.map +1 -1
- package/dist/bakeoff/samples.js +67 -6
- package/dist/bakeoff/stats.d.ts +17 -1
- package/dist/bakeoff/stats.d.ts.map +1 -1
- package/dist/bakeoff/stats.js +67 -0
- package/dist/bakeoff/types.d.ts +76 -5
- package/dist/bakeoff/types.d.ts.map +1 -1
- package/dist/bakeoff/types.js +4 -3
- package/dist/cli-query.d.ts +14 -0
- package/dist/cli-query.d.ts.map +1 -0
- package/dist/cli-query.js +59 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +47 -24
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -0
- package/dist/detect/detector.d.ts +82 -0
- package/dist/detect/detector.d.ts.map +1 -0
- package/dist/detect/detector.js +23 -0
- package/dist/index.d.ts +34 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -12
- package/dist/query/analytics.d.ts +84 -0
- package/dist/query/analytics.d.ts.map +1 -0
- package/dist/query/analytics.js +280 -0
- package/dist/query/columns.d.ts +59 -0
- package/dist/query/columns.d.ts.map +1 -0
- package/dist/query/columns.js +89 -0
- package/dist/query/grammar.d.ts +74 -7
- package/dist/query/grammar.d.ts.map +1 -1
- package/dist/query/grammar.js +179 -71
- package/dist/query/saved.d.ts +26 -0
- package/dist/query/saved.d.ts.map +1 -0
- package/dist/query/saved.js +51 -0
- package/dist/registry/select.d.ts +59 -0
- package/dist/registry/select.d.ts.map +1 -1
- package/dist/registry/select.js +66 -0
- package/dist/routes/loader-warnings.d.ts +28 -0
- package/dist/routes/loader-warnings.d.ts.map +1 -0
- package/dist/routes/loader-warnings.js +56 -0
- package/dist/routes/loader.d.ts +1 -11
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +54 -31
- package/dist/routes/objective-loader.d.ts +35 -0
- package/dist/routes/objective-loader.d.ts.map +1 -0
- package/dist/routes/objective-loader.js +286 -0
- package/dist/run/accept.d.ts +43 -0
- package/dist/run/accept.d.ts.map +1 -0
- package/dist/run/accept.js +65 -0
- package/dist/run/cost.d.ts +13 -0
- package/dist/run/cost.d.ts.map +1 -1
- package/dist/run/cost.js +27 -0
- package/dist/run/dispatch.d.ts +24 -1
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +19 -0
- package/dist/run/ladder-key.d.ts +4 -0
- package/dist/run/ladder-key.d.ts.map +1 -1
- package/dist/run/ladder-key.js +3 -0
- package/dist/run/quality-gate.d.ts +39 -0
- package/dist/run/quality-gate.d.ts.map +1 -0
- package/dist/run/quality-gate.js +70 -0
- package/dist/run/raw-defaults.d.ts +52 -0
- package/dist/run/raw-defaults.d.ts.map +1 -0
- package/dist/run/raw-defaults.js +123 -0
- package/dist/run/raw.d.ts +12 -0
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +107 -8
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +22 -1
- package/dist/run/resolve.d.ts +17 -1
- package/dist/run/resolve.d.ts.map +1 -1
- package/dist/run/resolve.js +20 -4
- package/dist/run/routing-docs.d.ts.map +1 -1
- package/dist/run/routing-docs.js +12 -5
- package/dist/run/run.d.ts +7 -1
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +54 -69
- package/dist/run/variant.d.ts +43 -0
- package/dist/run/variant.d.ts.map +1 -0
- package/dist/run/variant.js +86 -0
- package/dist/savings/emit.d.ts +33 -0
- package/dist/savings/emit.d.ts.map +1 -1
- package/dist/savings/emit.js +75 -3
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +2 -1
- package/dist/settings/task-settings.d.ts +10 -0
- package/dist/settings/task-settings.d.ts.map +1 -1
- package/dist/settings/task-settings.js +17 -0
- package/dist/telemetry/attempt-meta.d.ts +178 -0
- package/dist/telemetry/attempt-meta.d.ts.map +1 -0
- package/dist/telemetry/attempt-meta.js +319 -0
- package/dist/telemetry/exporter.d.ts.map +1 -1
- package/dist/telemetry/exporter.js +6 -0
- package/dist/telemetry/ingest-protocol.d.ts +11 -0
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/ingest-protocol.js +3 -0
- package/dist/telemetry/otel-map.d.ts +10 -0
- package/dist/telemetry/otel-map.d.ts.map +1 -1
- package/dist/telemetry/otel-map.js +64 -0
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +15 -0
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/store.js +25 -7
- package/dist/types/failures-teaching.d.ts.map +1 -1
- package/dist/types/failures-teaching.js +20 -0
- package/dist/types/failures.d.ts +1 -1
- package/dist/types/failures.d.ts.map +1 -1
- package/dist/types/failures.js +1 -0
- package/dist/types/provider.d.ts +9 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/quality.d.ts +41 -0
- package/dist/types/quality.d.ts.map +1 -0
- package/dist/types/quality.js +12 -0
- package/dist/types/route.d.ts +120 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +13 -0
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/validate-cli.d.ts.map +1 -1
- package/dist/validate-cli.js +10 -0
- package/dist/watch/evaluate.d.ts +27 -1
- package/dist/watch/evaluate.d.ts.map +1 -1
- package/dist/watch/evaluate.js +13 -0
- package/dist/watch/proposals.d.ts +28 -0
- package/dist/watch/proposals.d.ts.map +1 -1
- package/dist/watch/proposals.js +51 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,244 @@ published package diverge.
|
|
|
10
10
|
This project adheres to [Semantic Versioning](https://semver.org/). Dates are
|
|
11
11
|
UTC.
|
|
12
12
|
|
|
13
|
+
## [0.6.0] — 2026-08-23
|
|
14
|
+
|
|
15
|
+
Released with the docs/registry mirror in one R-A ceremony. Headline for router
|
|
16
|
+
codebases: the candidate ladder can now fall through on **quality** (`qualityGate`
|
|
17
|
+
→ `quality_rejected`), bake-offs measure **regret against a reference arm** under a
|
|
18
|
+
declared objective (legacy routes stay cost-first, byte-identical), the console
|
|
19
|
+
gains the **project tree** (`/projects`) and the **analytics API**
|
|
20
|
+
(`/v1/analytics/meta` + `/query`, metadata only — never content), and the
|
|
21
|
+
OpenAI-compatible proxy accepts the `developer` role. ZERO DDL across the line.
|
|
22
|
+
|
|
23
|
+
Regret-bounded bake-offs (RB-1, near-optimal) — the bake-off objective flips from
|
|
24
|
+
"cheapest that passes" to **near-optimal at a reasonable price**. New additive
|
|
25
|
+
route YAML: `objective` (`mode: quality-first | balanced | cost-first`,
|
|
26
|
+
`max_regret`, `price_ceiling`, `lambda`), `bakeoff` (`reference: auto | provider/model`,
|
|
27
|
+
`reference_envelope_usd`, `judge: { model, max_samples }`), and `value_checks`
|
|
28
|
+
(JSON-pointer assertions). Every bake-off can run a **reference (ceiling) arm**
|
|
29
|
+
and report each arm's **regret vs the reference with a seeded-bootstrap CI and n**.
|
|
30
|
+
Quality per sample resolves eval-case golden → `value_checks` → an opt-in capped,
|
|
31
|
+
metered judge (judge model ∈ declared candidates) → 1/0 conformance; it composes
|
|
32
|
+
with Q1's `qualityGate` (deterministic checks first, then the gate/judge). The
|
|
33
|
+
proposal gate is objective-aware: `cost-first` keeps Q1's gate byte-identical
|
|
34
|
+
(golden); a declared `quality-first`/`balanced` objective with no bound reports
|
|
35
|
+
regret but proposes nothing (no silent actuation). `modelrig bakeoff --objective
|
|
36
|
+
<mode>` overrides per run. The report/PR body state regret, cost and the ceiling
|
|
37
|
+
on one line. ZERO DDL. See `docs/bakeoffs.md` §5.
|
|
38
|
+
|
|
39
|
+
Analytics surface (WI-1b) — the read side of the attempt envelope. `GET
|
|
40
|
+
/v1/analytics/meta` describes every dimension and metric with its classification
|
|
41
|
+
and `since` version; `POST /v1/analytics/query` runs the SELECT-only grammar over
|
|
42
|
+
an org's inferences (metadata only — enums, numbers, hashes, identifiers; never
|
|
43
|
+
content; bake-off replay rows excluded). `modelrig query "<grammar>"` /
|
|
44
|
+
`--saved <id>` run the same grammar locally. Console: saved questions on
|
|
45
|
+
`/costs`, `/coverage`, `/routes/[route]`. OTLP-out gains `modelrig.meta.*` span
|
|
46
|
+
attributes for the metadata-safe envelope fields. Behaviour change: a free-text
|
|
47
|
+
`actor` is dropped with one warning (metadata-safe rule). New root exports:
|
|
48
|
+
`parseQuery`, `compileQuery`, `evaluateAnalyticsQuery`, `describeAnalyticsSchema`,
|
|
49
|
+
`planAnalyticsRead`, `runTelemetryQuery`, `SAVED_QUERIES`, `savedQueryById`, the
|
|
50
|
+
column registries and their types.
|
|
51
|
+
ZERO DDL.
|
|
52
|
+
|
|
53
|
+
Quality gate (#223, Q1) — the candidate ladder can now fall through on *quality*,
|
|
54
|
+
not just shape. Pass `rig.run(route, { qualityGate })` and a schema-valid output
|
|
55
|
+
your predicate rejects is recorded as a new `quality_rejected` failure (its own
|
|
56
|
+
retry budget, never the repair rung) and the ladder advances. The same predicate
|
|
57
|
+
scores bake-offs (`rig.bakeoff({ qualityGate })`) — a quality pass rate and an
|
|
58
|
+
`effectiveUsdPer1kPassing` metric beside the conformant one. SDK lane only: a
|
|
59
|
+
function cannot cross the hosted boundary; the route-declared hosted judge is Q2.
|
|
60
|
+
|
|
61
|
+
### Added — quality gate (#223, Q1)
|
|
62
|
+
|
|
63
|
+
- **`RunOptions.qualityGate?`** — a builder predicate
|
|
64
|
+
`(output, meta) => { ok, score?, reason? }` (sync or async) evaluated on a
|
|
65
|
+
schema-VALID output before it is accepted. `ok:false` records a
|
|
66
|
+
`quality_rejected` attempt (message carries the reason + score), captures the
|
|
67
|
+
rejected text for replay, and falls the ladder through on the class's OWN retry
|
|
68
|
+
budget (`policy.retries.quality_rejected`, default 0) — the repair rung is NEVER
|
|
69
|
+
entered from this path. A throwing predicate rejects fail-closed (`reason:
|
|
70
|
+
"qualityGate threw: …"`, one warning per process). Tool-call turns and
|
|
71
|
+
`schema: null` routes are handled per spec §4.1. `runStream` inherits it.
|
|
72
|
+
- **`FailureClass "quality_rejected"`** — retryable (own non-fungible budget),
|
|
73
|
+
never terminal, with an errors-that-teach entry (`docsUrl`
|
|
74
|
+
→ routing-reliability.html#quality_rejected) and a suggested `policy.retries`
|
|
75
|
+
edit. `policy.retries.quality_rejected` is accepted by the loader.
|
|
76
|
+
- **`RunMeta.quality?`** `{ score, verdict, judgedBy }` — present when a gate ran
|
|
77
|
+
(`verdict: "pass"` on a returned run; `judgedBy: null` for an SDK predicate).
|
|
78
|
+
SDK-owned `tags.quality` / `tags.quality_score` are stamped on the attempt row.
|
|
79
|
+
- **`rig.bakeoff` / `rig.bakeoffFromEvalCases` gain `qualityGate?`** — scored on
|
|
80
|
+
each replayed sample into `ReplaySampleResult.valueAccuracy` + `qualityPassed`;
|
|
81
|
+
`VariantMetrics` gains `qualityPassCi95` and `effectiveUsdPer1kPassing` (beside,
|
|
82
|
+
never redefining, `effectiveUsdPer1kConformant`), and `computeProposal` gains a
|
|
83
|
+
third clause (challenger quality-pass CI-lower ≥ incumbent's). The `modelrig
|
|
84
|
+
bakeoff` CLI cannot carry a function — use programmatic `rig.bakeoff` until Q2.
|
|
85
|
+
- **Exports:** `QualityGate`, `QualityVerdict`, `QualityGateMeta` from the root.
|
|
86
|
+
- **Boundary B1 rewritten** to "Route-declared judge (hosted lane)" (`not_built`,
|
|
87
|
+
tripwire `/\bjudge\??\s*:/`) now the SDK predicate ships; the routing-reliability
|
|
88
|
+
page, llms.txt (C11), README, `/definitions`, and the v4 setup prompt are swept
|
|
89
|
+
to match.
|
|
90
|
+
|
|
91
|
+
Project tree (G2b) — the console gains `/projects` (picker) and `/projects/[value]`
|
|
92
|
+
(project → run → step → call → attempts, cost + quality + lane on every node) over
|
|
93
|
+
one new read, `GET /v1/console/tree`. Server + console only; the SDK change below
|
|
94
|
+
is documentation. ZERO DDL.
|
|
95
|
+
|
|
96
|
+
- **`@step` / `step()` sets the ambient step key.** Documented in `step.ts` that
|
|
97
|
+
entering a step scope mints `label#n` and makes it the run context's ambient
|
|
98
|
+
step: an `artifact.save` with no explicit `stepKey` attaches to it — for saves
|
|
99
|
+
inside the scope AND for saves after it, until the next step mints a new key
|
|
100
|
+
(the ambient key is a running "most recent step", not a lexical bracket).
|
|
101
|
+
`run-context.ts` clarifies that within one run's parallel step waves only an
|
|
102
|
+
explicit `stepKey` prevents cross-attribution (`run.scope()` separates distinct
|
|
103
|
+
runs, not overlapping steps in one run).
|
|
104
|
+
|
|
105
|
+
Screening (B0 + B1) — two bug-class fixes and a shared detector contract.
|
|
106
|
+
- **Bake-off review samples are scrubbed before they persist.** A `--keep-outputs`
|
|
107
|
+
bake-off now runs each sample's input and output through the rig's content-custody
|
|
108
|
+
scrub mode (`detect` counts onto `arm_meta.scrub`, `redact` masks, `block` keeps a
|
|
109
|
+
metadata-only sample). Default `off` ⇒ rows byte-identical to before.
|
|
110
|
+
- **Proxy role enum.** `messages[].role` must be `system|developer|user|assistant|tool`
|
|
111
|
+
(`developer` normalises to the system slot); anything else is rejected with a
|
|
112
|
+
teaching message before dispatch (HTTP 422). Previously an arbitrary role was cast
|
|
113
|
+
through.
|
|
114
|
+
- **Raw-lane multi-turn encoding (behaviour change).** A genuine multi-turn transcript
|
|
115
|
+
is now flattened into the adapter's user prompt as one JSON object per line instead
|
|
116
|
+
of `role: content` text, so a crafted turn can never read as a synthetic system
|
|
117
|
+
line. Single-user-turn (and system + single user) requests are byte-identical.
|
|
118
|
+
- **Shared `Detector` interface.** `Detector`, `DetectionSpan`, `detectSpans`, and
|
|
119
|
+
`scrubDetectors` are exported from the package root; `scrubContent` is unchanged.
|
|
120
|
+
`buildBakeoffSamples` gains a scrub-resolver argument.
|
|
121
|
+
|
|
122
|
+
## [0.5.0] — 2026-08-22
|
|
123
|
+
|
|
124
|
+
Released with the docs/registry mirror in one R-A ceremony. Headline for router
|
|
125
|
+
codebases: `rig.runRaw` inside a run context now records a step (the `/runs`
|
|
126
|
+
tree fills in), raw-lane timeouts are tier-aware and teach, the `trial:`
|
|
127
|
+
candidate flag + console picker ship (deploy the server before any YAML uses
|
|
128
|
+
`trial:`), and the console rollups show cost and quality together by route or
|
|
129
|
+
tag. `modelrig-oracle` 0.2.0 ships alongside (`propose_candidates`).
|
|
130
|
+
|
|
131
|
+
Raw-lane defaults (#245) — the raw lane teaches its own timeouts. The `timeoutMs`
|
|
132
|
+
default becomes tier-aware, a `timeout` failure carries a teaching `fixHint`, an
|
|
133
|
+
empty no-tools gemini response carries a hint naming grounding, and the raw-lane
|
|
134
|
+
defaults are published as a generated table that cannot drift from the runtime.
|
|
135
|
+
|
|
136
|
+
Declare-first experiment ergonomics (routing-console R3, #239) — a `trial:`
|
|
137
|
+
candidate you declare but never serve live, a console challenger picker, and a
|
|
138
|
+
one-command bake-off that measures it on real captured traffic before you
|
|
139
|
+
promote it.
|
|
140
|
+
|
|
141
|
+
### Changed
|
|
142
|
+
|
|
143
|
+
- **Raw-lane `timeoutMs` default is now tier-aware** (was a flat 120 s):
|
|
144
|
+
`standard`/`priority` default to 300 s and `flex` to 900 s (the 15-minute budget
|
|
145
|
+
ModelRig advertises) — a passthrough should not be shorter-fused than the tier it
|
|
146
|
+
advertises, and grounded/large prompts routinely exceed 120 s even at standard.
|
|
147
|
+
An explicit `timeoutMs` **always wins** (no pre-dispatch rejection — a short
|
|
148
|
+
deadline is a choice), and a `timeout` failure on the raw lane now carries a
|
|
149
|
+
`fixHint` naming the elapsed time, the tier, that tier's budget, and the two
|
|
150
|
+
fixes (raise `timeoutMs`, or drop to `serviceTier: "standard"`). The routed
|
|
151
|
+
lane's required `policy.timeout_ms` is unchanged. Callers who relied on a fast
|
|
152
|
+
120 s failure should set `timeoutMs` explicitly.
|
|
153
|
+
|
|
154
|
+
### Added — declare-first experiment (routing-console R3)
|
|
155
|
+
|
|
156
|
+
- **`candidates[].trial: true`** (route bundle) — a DECLARED candidate that is
|
|
157
|
+
NEVER served live. The loader parses and validates it, marks an all-trial
|
|
158
|
+
variant `trialOnly`, and warns on a trial candidate no variant references;
|
|
159
|
+
`resolveCandidates` drops trial candidates on every live path (`rig.run`,
|
|
160
|
+
`runStream`, `runBundle`, the hosted gateway slug lane) and keeps them only in
|
|
161
|
+
bake-off replay. Selecting a trial variant on a live call is a
|
|
162
|
+
`RouteConfigError` that names the bake-off. This lets a customer measure a new
|
|
163
|
+
model on real captured traffic before promoting it. Additive: a route with no
|
|
164
|
+
trial candidate is byte-identical to before.
|
|
165
|
+
- CAVEAT — **deploy the server before any customer YAML carries `trial:`.** An
|
|
166
|
+
SDK/server older than 0.5.0 IGNORES `trial:` (the loader has always been
|
|
167
|
+
tolerant of unknown candidate keys) and its resolver has no trial-mode filter,
|
|
168
|
+
so it would serve the candidate LIVE — including an older hosted-gateway build
|
|
169
|
+
reading the flag through the mirror. Roll the server first, then let routes
|
|
170
|
+
start declaring `trial:`. The console's declare-YAML says so inline.
|
|
171
|
+
- **`requirementPredicates(route)` / `evaluateChallengerEligibility(...)`** (new
|
|
172
|
+
exports) — decompose a route's `require` + json rung into capability-flag
|
|
173
|
+
requirements and answer "can this model be a trial challenger?", pinned in
|
|
174
|
+
agreement with the live resolver's `satisfiesRequirements`.
|
|
175
|
+
- **`buildDeclareTrialChange(bundle, challenger)` / `trialVariantName(...)`** and
|
|
176
|
+
a trial-winner branch of **`buildSwapChange`** (new exports) — the paste-ready
|
|
177
|
+
declare-YAML (challenger appended `trial: true`, a `trial-<provider>-<model>`
|
|
178
|
+
variant, `version: n+1`) and the promote-YAML that drops the winner's trial
|
|
179
|
+
flag, moves it to position 0, and removes the trial variant. No filesystem, no
|
|
180
|
+
git — the human applies the PR (F6).
|
|
181
|
+
- **`ManualChallengerTrigger` + `manualChallengerTriggerHash`**, and
|
|
182
|
+
**`proposalsClient.createManualChallenger`** — a console/oracle-initiated
|
|
183
|
+
declare-first proposal (`kind:"bakeoff"`, idempotent per `(route, challenger)`).
|
|
184
|
+
- **`RunMeta`/`Rig` additions:** `rig.capabilities` and `rig.searchAvailable` are
|
|
185
|
+
exposed so the challenger picker answers eligibility with the exact live flags;
|
|
186
|
+
`modelrig bakeoff --from-proposal <id>` reads the trial variant from a
|
|
187
|
+
manual_challenger proposal (default vs that one variant).
|
|
188
|
+
- **`resolveRouteBundle` / `hashResolvedBundle`** (new exports) — the canonical
|
|
189
|
+
`bundle_sha` helpers, used by the hosted-lane bake-off to prove the caller org's
|
|
190
|
+
mirrored bundle is the SAME bundle the deployment holds locally (a route-name
|
|
191
|
+
collision on a multi-tenant mirror otherwise baked off a foreign org's route).
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- **A grounding-naming `fixHint` on an empty no-tools gemini response.** When a
|
|
196
|
+
call that declared no tools comes back with no text parts (a grounding turn
|
|
197
|
+
that produced only `functionCall` parts, for example), the `content_invalid`
|
|
198
|
+
"empty response" failure now names grounding as the likely cause. Note: the
|
|
199
|
+
text extraction itself is unchanged in effect — the SDK already concatenated
|
|
200
|
+
mixed `functionCall` + text parts — so the customer-zero empty-response report
|
|
201
|
+
(#245 secondary) remains an OPEN investigation pending a captured response.
|
|
202
|
+
|
|
203
|
+
### Docs
|
|
204
|
+
|
|
205
|
+
- **Raw-lane defaults table** — a generated table (`RAW_DEFAULTS`, rendered at the
|
|
206
|
+
`<!-- RAW_DEFAULTS -->` marker in `route-bundles.md` and in `llms.txt`) lists
|
|
207
|
+
every raw-lane knob and its default, with the tier-aware `timeoutMs` read from
|
|
208
|
+
the same constant the runtime resolves from — so the published defaults cannot
|
|
209
|
+
drift from what `rig.runRaw` sends. README / quickstart / migration-playbook
|
|
210
|
+
gain the "flex ⇒ set `timeoutMs` in minutes" one-liner.
|
|
211
|
+
|
|
212
|
+
Raw-lane artifact graph + tags parity (G1). A `rig.runRaw` / `rig.runRawStream`
|
|
213
|
+
call inside a `rig.artifacts.run.start` context now records a ground-truth step,
|
|
214
|
+
so a router or report pipeline that wraps raw (BYOK) calls in a run context gets
|
|
215
|
+
a real per-run tree at `/runs/[id]` instead of an empty one. ZERO DDL.
|
|
216
|
+
|
|
217
|
+
### Added — raw-lane graph
|
|
218
|
+
|
|
219
|
+
- **Raw calls record a ground-truth step.** Inside a run context,
|
|
220
|
+
`runRaw`/`runRawStream` emit a step (on success AND failure, buffered AND
|
|
221
|
+
streaming) whose `inference_id` joins the metered `lane=raw` row — parity with
|
|
222
|
+
the routed lane's auto-step. Fail-open: a buffer error there never affects the
|
|
223
|
+
returned result. Outside a run context the dispatch is byte-identical to 0.4.0
|
|
224
|
+
(no step row). Raw steps are **metadata only** — no artifact content is written
|
|
225
|
+
on the raw lane.
|
|
226
|
+
- **`stepKey` on BOTH lanes.** `RunOptions.stepKey` (routed) and
|
|
227
|
+
`RawRunInput.stepKey` (raw) name the step. Resolution is `stepKey ?? tags.step
|
|
228
|
+
?? auto` (`route#n` / `provider/model#n`), validated `[A-Za-z0-9_.:#-]{1,128}`;
|
|
229
|
+
an invalid value is warned once and dropped to the auto key (never thrown). A
|
|
230
|
+
raw row's step **task** is `tags.step ?? provider/model`.
|
|
231
|
+
- **Ambient artifact step.** `artifact.save` without a `stepKey` now attaches to
|
|
232
|
+
the ambient step (the most recent step in the run context), so the two grouping
|
|
233
|
+
mechanisms compose — a raw/routed call and the artifacts saved around it land in
|
|
234
|
+
one group.
|
|
235
|
+
- **Required-dimension hygiene on the raw lane.** `runRaw`/`runRawStream` run the
|
|
236
|
+
same once-per-process "required dimension missing from tags" warning the routed
|
|
237
|
+
lane does.
|
|
238
|
+
|
|
239
|
+
### Added — docs
|
|
240
|
+
|
|
241
|
+
- **instrumentation.md** gains "Tags, dimensions, and the graph": tags = flat
|
|
242
|
+
filter/rollup (`/costs`), the graph = the per-run tree (`/runs/[id]`), how
|
|
243
|
+
`stepKey` + ambient artifacts compose, and the raw-lane behavior.
|
|
244
|
+
- **The per-service key rule** is now stated in the quickstart, the migration
|
|
245
|
+
playbook (F-6), and llms.txt: `MODELRIG_API_KEY` gates the exporter *per
|
|
246
|
+
process* — set it on EVERY service, worker, and cron, or a keyless process
|
|
247
|
+
buffers to its own local SQLite and ships nothing.
|
|
248
|
+
- **route-bundles.md** points at where `rig.yaml` `dimensions` are declared; the
|
|
249
|
+
**README** documents `stepKey` on the raw lane.
|
|
250
|
+
|
|
13
251
|
## [0.4.0] — 2026-08-22
|
|
14
252
|
|
|
15
253
|
Released with the docs/registry mirror in one R-A ceremony. NOT in this tag:
|
package/README.md
CHANGED
|
@@ -144,6 +144,19 @@ never stores it. It records one metered `lane=raw` telemetry row at the
|
|
|
144
144
|
provider's list price (zero ModelRig margin) and throws a typed `RigFailureError`
|
|
145
145
|
on failure, exactly like `rig.run`.
|
|
146
146
|
|
|
147
|
+
Called inside a `rig.artifacts.run.start` context, `runRaw`/`runRawStream` also
|
|
148
|
+
records a ground-truth **step** in the run's graph (`/runs/[id]`) — since
|
|
149
|
+
modelrig 0.5.0, on success and on failure. Name it with `stepKey` (the same field
|
|
150
|
+
`RunOptions` exposes on the routed lane; precedence `stepKey` > `tags.step` > an
|
|
151
|
+
auto `provider/model#n` key), so a raw call and the artifacts you `save` around it
|
|
152
|
+
group under one step.
|
|
153
|
+
|
|
154
|
+
The raw-lane `timeoutMs` default is **tier-aware** since 0.5.0 — `standard`/
|
|
155
|
+
`priority` 300 s, `flex` 900 s; an explicit `timeoutMs` always wins, and a
|
|
156
|
+
`timeout` failure teaches the tier + budget in its `fixHint`. **flex ⇒ set
|
|
157
|
+
`timeoutMs` in minutes** (default 900 s since 0.5.0). See the generated
|
|
158
|
+
[raw-lane defaults table](https://modelrig.dev/route-bundles.html#raw-lane-defaults-rigrunraw).
|
|
159
|
+
|
|
147
160
|
**runRaw-only construction (`routesDir: null`) — 0.4.0+.** A
|
|
148
161
|
Lane-B deployment that ONLY calls `runRaw`/`runRawStream` has no routes. Build it
|
|
149
162
|
with `routesDir: null` and `createRig` skips route loading, the `rig.yaml`
|
|
@@ -166,9 +179,55 @@ Every attempt is recorded in a local SQLite file (`.modelrig/telemetry.db`)
|
|
|
166
179
|
tagged with your `tags`. Failures are typed —
|
|
167
180
|
`RigFailureError.failure.class` is one of `content_invalid`, `capacity_shed`,
|
|
168
181
|
`network`, `refusal`, `cache_invalid`, `timeout`, `config_auth`, `budget_exhausted`,
|
|
169
|
-
`invariant_violation` — with a separate retry budget per class, so a flaky
|
|
182
|
+
`invariant_violation`, `quality_rejected` — with a separate retry budget per class, so a flaky
|
|
170
183
|
network never spends your content-validation retries. What each class means, whether it retries, and how it backs off is on [Routing & reliability](https://modelrig.dev/routing-reliability.html#5-failure-classes).
|
|
171
184
|
|
|
185
|
+
## Metadata capture ("capture now, analyze later")
|
|
186
|
+
|
|
187
|
+
Every inference records a versioned, **metadata-safe** attempt envelope
|
|
188
|
+
(`AttemptMeta@v1`) on `inferences.meta` — in both the routed and the raw lane,
|
|
189
|
+
from the same producer. It is the metadata the adapters already see and used to
|
|
190
|
+
discard: finish reason, refusal, reasoning tokens, the provider-reported model
|
|
191
|
+
snapshot and request id, coarse HTTP status / error code, sampling echo, tool
|
|
192
|
+
names (declared kept, undeclared hashed) with counts, per-component cost, request
|
|
193
|
+
and output **hashes** (never the content), request/response byte sizes, response
|
|
194
|
+
char count, and a coarse context bucket.
|
|
195
|
+
|
|
196
|
+
**It never contains free text.** Every field is an enum, a number, a boolean, a
|
|
197
|
+
hash, or an identifier. The producer drops any string that is over 128 chars or
|
|
198
|
+
contains whitespace, and the hosted ingest endpoint re-applies the same rule as a
|
|
199
|
+
backstop — so analysis later is possible without prompts or outputs ever being
|
|
200
|
+
stored here. Building the envelope never blocks or changes a run: on any failure
|
|
201
|
+
it is simply absent (`meta` is null).
|
|
202
|
+
|
|
203
|
+
Runs carry a companion `RunMeta@v1` on `runs.meta`, set at `run.start`:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
const h = rig.run.start({
|
|
207
|
+
pipeline: "nightly-report",
|
|
208
|
+
meta: { v: 1, trigger: "cron", actor: "scheduler", config_hash: "…" },
|
|
209
|
+
// pipeline_sha auto-fills from git when you don't set it (never fails the run)
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Reserved dimensions
|
|
214
|
+
|
|
215
|
+
Business dimensions live in `tags`. Five keys are **well-known** and become
|
|
216
|
+
first-class group-bys in cost and coverage views — use them verbatim so your data
|
|
217
|
+
lines up with the console's built-ins:
|
|
218
|
+
|
|
219
|
+
| key | meaning |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `subject` | the customer/tenant the work is for — an **opaque** id, hashed if it looks like PII |
|
|
222
|
+
| `feature` | the product feature the call serves |
|
|
223
|
+
| `user` | the end user (an opaque id) |
|
|
224
|
+
| `session` | the conversation/session the call belongs to |
|
|
225
|
+
| `cost_center` | the team/budget to attribute spend to |
|
|
226
|
+
|
|
227
|
+
`modelrig validate` warns on near-misses — a declared `rig.yaml` dimension named
|
|
228
|
+
`customer`, `tenant`, `user_id`, `team`, … is nudged toward the reserved key it
|
|
229
|
+
resembles. They stay ordinary tags; nothing is required.
|
|
230
|
+
|
|
172
231
|
## CLI
|
|
173
232
|
|
|
174
233
|
The package ships a `modelrig` binary:
|
|
@@ -204,8 +263,11 @@ on the quickstart:
|
|
|
204
263
|
- **`modelrig serve` needs the `modelrig-server` package** — it is not bundled
|
|
205
264
|
here.
|
|
206
265
|
- **What the ladder does and does not do.** Fall-through is structural and
|
|
207
|
-
infrastructural,
|
|
208
|
-
|
|
266
|
+
infrastructural, plus an OPTIONAL SDK-lane `qualityGate` predicate you supply
|
|
267
|
+
(a schema-valid output it rejects becomes
|
|
268
|
+
`quality_rejected`); the route-declared
|
|
269
|
+
hosted judge is not built yet, and the full boundary (raw-lane structure, latency
|
|
270
|
+
ordering…) is generated and tripwire-tested on
|
|
209
271
|
[Routing & reliability](https://modelrig.dev/routing-reliability.html#10-not-yet-implemented-the-boundary).
|
|
210
272
|
|
|
211
273
|
## License
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEhE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,6 +22,7 @@ exports.normalizeAnthropicInputUsage = normalizeAnthropicInputUsage;
|
|
|
22
22
|
exports.createAnthropicAdapter = createAnthropicAdapter;
|
|
23
23
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
24
24
|
const tool_mapping_1 = require("./tool-mapping");
|
|
25
|
+
const attempt_meta_map_1 = require("./attempt-meta-map");
|
|
25
26
|
const sampling_1 = require("./sampling");
|
|
26
27
|
const DEFAULT_MAX_TOKENS = 32000;
|
|
27
28
|
const OUTPUT_TOOL_NAME = "route_output";
|
|
@@ -159,6 +160,8 @@ function createAnthropicAdapter(config) {
|
|
|
159
160
|
supportsTools: () => true,
|
|
160
161
|
async call(req) {
|
|
161
162
|
const model = req.candidate.model;
|
|
163
|
+
// WI-1: native attempt envelope for this call (see openai.ts for the pattern).
|
|
164
|
+
let attemptMeta;
|
|
162
165
|
// F1: post-stream failures still billed tokens — attach usage.
|
|
163
166
|
const fail = (cls, message, fixHint, usage) => ({
|
|
164
167
|
ok: false,
|
|
@@ -170,6 +173,7 @@ function createAnthropicAdapter(config) {
|
|
|
170
173
|
...(fixHint !== undefined ? { fixHint } : {}),
|
|
171
174
|
},
|
|
172
175
|
...(usage !== undefined ? { usage } : {}),
|
|
176
|
+
...(attemptMeta !== undefined ? { meta: attemptMeta } : {}),
|
|
173
177
|
});
|
|
174
178
|
const wantJson = req.outputSchema !== null;
|
|
175
179
|
try {
|
|
@@ -210,9 +214,20 @@ function createAnthropicAdapter(config) {
|
|
|
210
214
|
};
|
|
211
215
|
let completionTokens = 0;
|
|
212
216
|
let stopReason = null;
|
|
217
|
+
// WI-1 native fields: message.id + message.model arrive at message_start.
|
|
218
|
+
let responseModel = "";
|
|
219
|
+
let responseId = "";
|
|
213
220
|
for await (const event of events) {
|
|
214
|
-
if (event.type === "message_start"
|
|
215
|
-
|
|
221
|
+
if (event.type === "message_start") {
|
|
222
|
+
if (event.message?.usage !== undefined) {
|
|
223
|
+
inputUsage = normalizeAnthropicInputUsage(event.message.usage);
|
|
224
|
+
}
|
|
225
|
+
if (responseModel === "" && typeof event.message?.model === "string") {
|
|
226
|
+
responseModel = event.message.model;
|
|
227
|
+
}
|
|
228
|
+
if (responseId === "" && typeof event.message?.id === "string") {
|
|
229
|
+
responseId = event.message.id;
|
|
230
|
+
}
|
|
216
231
|
}
|
|
217
232
|
else if (event.type === "content_block_start" &&
|
|
218
233
|
wantTools &&
|
|
@@ -257,13 +272,25 @@ function createAnthropicAdapter(config) {
|
|
|
257
272
|
};
|
|
258
273
|
// Tool-call turn (spec §4.4): `arguments` is the raw JSON string the
|
|
259
274
|
// model streamed (OpenAI parity) — text may be empty, skip the guards.
|
|
260
|
-
|
|
261
|
-
|
|
275
|
+
const toolCalls = wantTools && toolBlocks.size > 0
|
|
276
|
+
? [...toolBlocks.values()].map((b, i) => ({
|
|
262
277
|
id: b.id !== "" ? b.id : `call_${i}`,
|
|
263
278
|
type: "function",
|
|
264
279
|
function: { name: b.name, arguments: b.json === "" ? "{}" : b.json },
|
|
265
|
-
}))
|
|
266
|
-
|
|
280
|
+
}))
|
|
281
|
+
: undefined;
|
|
282
|
+
// WI-1: native attempt envelope. refusal derives from stop_reason=refusal.
|
|
283
|
+
attemptMeta = (0, attempt_meta_map_1.buildAdapterMeta)("anthropic", {
|
|
284
|
+
req,
|
|
285
|
+
finishReasonRaw: stopReason,
|
|
286
|
+
refusal: stopReason === "refusal",
|
|
287
|
+
modelSnapshot: responseModel,
|
|
288
|
+
providerRequestId: responseId,
|
|
289
|
+
toolCalls,
|
|
290
|
+
streaming: false,
|
|
291
|
+
});
|
|
292
|
+
if (toolCalls !== undefined) {
|
|
293
|
+
return { ok: true, text, usage, toolCalls, meta: attemptMeta };
|
|
267
294
|
}
|
|
268
295
|
if (stopReason === "refusal") {
|
|
269
296
|
return fail("refusal", "Anthropic refused this request (stop_reason=refusal)", undefined, usage);
|
|
@@ -274,11 +301,12 @@ function createAnthropicAdapter(config) {
|
|
|
274
301
|
if (stopReason === "max_tokens" && wantJson) {
|
|
275
302
|
return fail("content_invalid", "Anthropic structured output truncated (stop_reason=max_tokens)", "raise maxOutputTokens for this route", usage);
|
|
276
303
|
}
|
|
277
|
-
return { ok: true, text, usage };
|
|
304
|
+
return { ok: true, text, usage, meta: attemptMeta };
|
|
278
305
|
}
|
|
279
306
|
catch (error) {
|
|
280
307
|
const message = error instanceof Error ? error.message : String(error);
|
|
281
308
|
const { cls, fixHint } = classifyAnthropicFailure(message);
|
|
309
|
+
attemptMeta = (0, attempt_meta_map_1.transportErrorMeta)(error);
|
|
282
310
|
return {
|
|
283
311
|
ok: false,
|
|
284
312
|
failure: {
|
|
@@ -289,6 +317,7 @@ function createAnthropicAdapter(config) {
|
|
|
289
317
|
cause: error,
|
|
290
318
|
...(fixHint !== undefined ? { fixHint } : {}),
|
|
291
319
|
},
|
|
320
|
+
meta: attemptMeta,
|
|
292
321
|
};
|
|
293
322
|
}
|
|
294
323
|
},
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-adapter NATIVE metadata mapping (WI-1, spec §2). ONE place that turns a
|
|
3
|
+
* provider's native finish/refusal/usage/id signals into the additive
|
|
4
|
+
* `AdapterResult.meta` (`Partial<AttemptMetaV1>`). Adapters map ONLY what the
|
|
5
|
+
* provider reports; the producer (`telemetry/attempt-meta.ts`) adds
|
|
6
|
+
* hashes/sizes/cost and enforces the classification rule. Absent = unknown;
|
|
7
|
+
* nothing here is inferred.
|
|
8
|
+
*
|
|
9
|
+
* `refusal` derivation, per adapter:
|
|
10
|
+
* - openai / grok / deepseek / deepinfra / fireworks (OpenAI dialect): the
|
|
11
|
+
* stream carried a non-empty `choices[].delta.refusal` string, OR
|
|
12
|
+
* `finish_reason === "content_filter"`.
|
|
13
|
+
* - anthropic: `stop_reason === "refusal"`.
|
|
14
|
+
* - gemini: `finishReason` is `SAFETY` / `PROHIBITED_CONTENT` / `RECITATION`.
|
|
15
|
+
* The refusal TEXT itself is never carried (content) — only the boolean.
|
|
16
|
+
*/
|
|
17
|
+
import type { AttemptMetaV1, FinishReason } from "../telemetry/attempt-meta";
|
|
18
|
+
import type { AdapterRequest, ProviderId, ToolCall } from "../types/provider";
|
|
19
|
+
/** Map a provider's native finish/stop reason to the `FinishReason` enum
|
|
20
|
+
* (spec §2). Unknown/absent ⇒ undefined (never inferred); an unrecognised
|
|
21
|
+
* non-empty value ⇒ `"other"`. */
|
|
22
|
+
export declare function mapFinishReason(provider: ProviderId, raw: string | null | undefined): FinishReason | undefined;
|
|
23
|
+
/** The declared sampling echo (spec §2 `sampling`) — the values ModelRig sent,
|
|
24
|
+
* read back from the request. topP → top_p, maxOutputTokens → max_output_tokens
|
|
25
|
+
* (the raw lane's top-level or the routed lane's `sampling` block). Numbers
|
|
26
|
+
* only; undefined when the caller declared none. */
|
|
27
|
+
export declare function samplingEcho(req: AdapterRequest): {
|
|
28
|
+
temperature?: number;
|
|
29
|
+
top_p?: number;
|
|
30
|
+
max_output_tokens?: number;
|
|
31
|
+
} | undefined;
|
|
32
|
+
/** Aggregate normalized tool calls into `{ name, count }` (RAW names — the
|
|
33
|
+
* producer hashes undeclared ones). Undefined when the turn made none. */
|
|
34
|
+
export declare function aggregateToolCalls(toolCalls: readonly ToolCall[] | undefined): {
|
|
35
|
+
name: string;
|
|
36
|
+
count: number;
|
|
37
|
+
}[] | undefined;
|
|
38
|
+
/** The signals an adapter collects on ONE completed call. All optional. */
|
|
39
|
+
export interface AdapterMetaSignals {
|
|
40
|
+
readonly req: AdapterRequest;
|
|
41
|
+
readonly finishReasonRaw?: string | null;
|
|
42
|
+
readonly refusal?: boolean;
|
|
43
|
+
readonly reasoningTokens?: number;
|
|
44
|
+
readonly modelSnapshot?: string;
|
|
45
|
+
readonly providerRequestId?: string;
|
|
46
|
+
readonly region?: string;
|
|
47
|
+
readonly toolCalls?: readonly ToolCall[];
|
|
48
|
+
readonly grounding?: {
|
|
49
|
+
citations?: number;
|
|
50
|
+
searchProvider?: string;
|
|
51
|
+
};
|
|
52
|
+
/** true = the run loop streamed deltas (stream()); false/absent = buffered. */
|
|
53
|
+
readonly streaming?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** Build one adapter's NATIVE `meta` (spec §2). Only defined signals appear —
|
|
56
|
+
* everything else is unknown and omitted. The producer takes it from here. */
|
|
57
|
+
export declare function buildAdapterMeta(provider: ProviderId, s: AdapterMetaSignals): Partial<AttemptMetaV1>;
|
|
58
|
+
/** A transport/SDK error's coarse envelope (spec §2 `http_status`/`error_code`).
|
|
59
|
+
* Reads `error.status` (number) and a short `error.code` / `error.error.code`
|
|
60
|
+
* slug — NEVER the message (that is free text). The producer's classification
|
|
61
|
+
* rule drops a code that turns out to be free text. */
|
|
62
|
+
export declare function transportErrorMeta(error: unknown): Partial<AttemptMetaV1>;
|
|
63
|
+
//# sourceMappingURL=attempt-meta-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attempt-meta-map.d.ts","sourceRoot":"","sources":["../../src/adapters/attempt-meta-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE9E;;kCAEkC;AAClC,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,UAAU,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7B,YAAY,GAAG,SAAS,CA6C1B;AAED;;;oDAGoD;AACpD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,GAClB;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAOlF;AAED;0EAC0E;AAC1E,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,GACzC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAS,CAQ/C;AAED,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EACpB,CAAC,EAAE,kBAAkB,GACpB,OAAO,CAAC,aAAa,CAAC,CAyBxB;AAED;;;uDAGuD;AACvD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CASzE"}
|