modelrig 0.3.0 → 0.4.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +140 -0
  2. package/README.md +66 -14
  3. package/dist/adapters/deepseek.d.ts.map +1 -1
  4. package/dist/adapters/deepseek.js +8 -1
  5. package/dist/adapters/gemini.d.ts +6 -0
  6. package/dist/adapters/gemini.d.ts.map +1 -1
  7. package/dist/adapters/gemini.js +14 -4
  8. package/dist/adapters/grok.d.ts +7 -0
  9. package/dist/adapters/grok.d.ts.map +1 -1
  10. package/dist/adapters/grok.js +23 -1
  11. package/dist/adapters/openai-compat.d.ts +7 -0
  12. package/dist/adapters/openai-compat.d.ts.map +1 -1
  13. package/dist/adapters/openai-compat.js +24 -1
  14. package/dist/adapters/openai.d.ts +7 -0
  15. package/dist/adapters/openai.d.ts.map +1 -1
  16. package/dist/adapters/openai.js +23 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +5 -4
  19. package/dist/config.d.ts +7 -1
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/index.d.ts +6 -6
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +28 -25
  24. package/dist/init/init-cli.d.ts.map +1 -1
  25. package/dist/init/init-cli.js +2 -1
  26. package/dist/init/observe-cli.d.ts.map +1 -1
  27. package/dist/init/observe-cli.js +2 -1
  28. package/dist/routes/sampling-config.d.ts.map +1 -1
  29. package/dist/routes/sampling-config.js +11 -0
  30. package/dist/run/dispatch.d.ts +14 -2
  31. package/dist/run/dispatch.d.ts.map +1 -1
  32. package/dist/run/dispatch.js +31 -2
  33. package/dist/run/ladder-key.d.ts +40 -0
  34. package/dist/run/ladder-key.d.ts.map +1 -0
  35. package/dist/run/ladder-key.js +39 -0
  36. package/dist/run/raw-support.d.ts +123 -0
  37. package/dist/run/raw-support.d.ts.map +1 -0
  38. package/dist/run/raw-support.js +150 -0
  39. package/dist/run/raw.d.ts +41 -11
  40. package/dist/run/raw.d.ts.map +1 -1
  41. package/dist/run/raw.js +67 -23
  42. package/dist/run/rawonly.d.ts +60 -0
  43. package/dist/run/rawonly.d.ts.map +1 -0
  44. package/dist/run/rawonly.js +120 -0
  45. package/dist/run/record-attempt.d.ts +14 -1
  46. package/dist/run/record-attempt.d.ts.map +1 -1
  47. package/dist/run/record-attempt.js +43 -2
  48. package/dist/run/resolve.d.ts +4 -0
  49. package/dist/run/resolve.d.ts.map +1 -1
  50. package/dist/run/resolve.js +9 -2
  51. package/dist/run/routing-docs.d.ts +73 -0
  52. package/dist/run/routing-docs.d.ts.map +1 -0
  53. package/dist/run/routing-docs.js +222 -0
  54. package/dist/run/run.d.ts.map +1 -1
  55. package/dist/run/run.js +24 -22
  56. package/dist/telemetry/exporter.d.ts.map +1 -1
  57. package/dist/telemetry/exporter.js +6 -0
  58. package/dist/telemetry/ingest-protocol.d.ts +7 -0
  59. package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
  60. package/dist/telemetry/load-error-report.d.ts.map +1 -1
  61. package/dist/telemetry/load-error-report.js +4 -1
  62. package/dist/telemetry/otel-map.d.ts.map +1 -1
  63. package/dist/telemetry/otel-map.js +8 -0
  64. package/dist/telemetry/store-migrations.d.ts +15 -0
  65. package/dist/telemetry/store-migrations.d.ts.map +1 -0
  66. package/dist/telemetry/store-migrations.js +119 -0
  67. package/dist/telemetry/store.d.ts.map +1 -1
  68. package/dist/telemetry/store.js +26 -93
  69. package/dist/types/failures-teaching.js +1 -1
  70. package/dist/types/provider.d.ts +13 -0
  71. package/dist/types/provider.d.ts.map +1 -1
  72. package/dist/types/route.d.ts +6 -1
  73. package/dist/types/route.d.ts.map +1 -1
  74. package/dist/types/telemetry.d.ts +31 -0
  75. package/dist/types/telemetry.d.ts.map +1 -1
  76. package/dist/validate-cli.d.ts.map +1 -1
  77. package/dist/validate-cli.js +17 -4
  78. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,146 @@ published package diverge.
10
10
  This project adheres to [Semantic Versioning](https://semver.org/). Dates are
11
11
  UTC.
12
12
 
13
+ ## [0.4.0] — 2026-08-22
14
+
15
+ Released with the docs/registry mirror in one R-A ceremony. NOT in this tag:
16
+ the R3 declare-first `trial:` candidate flag (#239) and raw-lane artifact
17
+ steps (G1) — both land in 0.5.0.
18
+
19
+ CE-9 raw-lane multi-provider parity — the `reasoning` and native-grounding knobs
20
+ generalize beyond gemini, a `responseFormat` knob joins the raw lane, and the
21
+ provider×knob support set becomes ONE table (`RAW_KNOB_SUPPORT`) that the runtime
22
+ guard AND the published docs matrix both read, so they can never disagree. Every
23
+ knob stays ADDITIVE: absent ⇒ byte-identical to the 0.3.0 request shape.
24
+
25
+ ### Added — docs
26
+
27
+ - **Routing & reliability page** (`https://modelrig.dev/routing-reliability.html`) —
28
+ the runtime model in one concept page: resolve -> candidate ladder -> validate ->
29
+ repair -> fall-through -> exhaust, what is stored per attempt, and a **code-anchored
30
+ boundary** (`ROUTING_BOUNDARY`, one tripwire test per entry) that lists what does not
31
+ trigger fall-through and what is not built — the build fails if a listed feature ships
32
+ without the entry being updated.
33
+
34
+ ### Fixed
35
+
36
+ - **Failure-teaching links resolve.** `RigFailureError.docsUrl` (and the CLI/console
37
+ error render) now point at `routing-reliability.html#<class>` — one stable heading per
38
+ failure class — instead of the never-built `/docs/failures` path, which 404'd on
39
+ every typed failure.
40
+
41
+ ### Added — `rig.runRaw` / `rig.runRawStream`
42
+
43
+ - **`reasoning` generalizes beyond gemini WITHOUT a per-model allowlist (R1).**
44
+ openai / deepinfra / fireworks forward `level` → `reasoning_effort` verbatim
45
+ and let the provider enforce — a model that does not accept it surfaces a
46
+ CLASSIFIED, teaching failure ("this model does not accept reasoning_effort —
47
+ remove reasoning or pick a reasoning model"), never a cryptic 400 or a silent
48
+ drop. grok forwards a DISCLOSED coarsening (`minimal,low → "low"`;
49
+ `medium,high → "high"`; xAI accepts `low|high` only). gemini stays
50
+ model-gated (thinking-capable models only). deepseek + anthropic FAIL CLOSED
51
+ pre-dispatch with a provider-specific fixHint (deepseek → select the
52
+ `deepseek-reasoner` model; anthropic → extended thinking unwired).
53
+ - **Grok native grounding (R2) — WITHDRAWN before release.** The CE-9 live gate hit xAI's `410 Live search is deprecated`; the replacement `web_search` tool is Responses-API-only, which the grok adapter does not speak yet. grok grounding FAILS CLOSED (matrix `supported: false`, teaching note) until CE-9b lands that path. Original entry, kept for the record: `grounding: { mode: "native" }` on grok →
54
+ xAI Live Search (`search_parameters: { mode: "on" }`). Citations are not
55
+ surfaced on `meta` in v1 (same documented limitation as gemini).
56
+ - **`responseFormat?: "json_object"` (R4).** MIME-shaping on the OpenAI-dialect
57
+ providers (openai/deepseek/grok/deepinfra/fireworks → `response_format: { type:
58
+ "json_object" }`) and gemini (`responseMimeType: "application/json"`, no
59
+ schema). This is syntactic-JSON forcing, NOT schema enforcement — F4 stands:
60
+ no validation, no repair, `meta.validated` stays false. anthropic has no
61
+ equivalent and FAILS CLOSED. DeepSeek's word-"JSON" prompt wrinkle is the
62
+ caller's responsibility on the raw lane (documented, never injected).
63
+ - **DeepInfra/Fireworks prompt-cache hint (R3).** `cache.key` now maps to
64
+ `prompt_cache_key` on the openai-compatible adapter, closing the DeepInfra cost
65
+ gap. (openai and grok already mapped `cache.key → prompt_cache_key` on 0.3.0 —
66
+ that was a docs gap, not a code gap; it is now documented as plain fact.)
67
+
68
+ ### Added — exports (R5/R6)
69
+
70
+ - **`RAW_KNOB_SUPPORT`** (the provider×knob matrix) + **`rawKnobSupport(provider)`**
71
+ (a pure lookup) — a multi-provider dispatcher ASKS which knobs a provider
72
+ honors instead of duplicating our lists. The guard (`assertRawKnobsSupported`)
73
+ and the docs generator both import this table.
74
+ - **`GEMINI_THINKING_CAPABLE_MODELS`** — the thinking-capable set (previously
75
+ un-exported), so customers stop duplicating it (the §3.1 drift complaint).
76
+ - **`coarsenGrokReasoningEffort`** + **`renderRawKnobMatrix`** — the disclosed
77
+ grok coarsening and the docs matrix renderer.
78
+
79
+ ### Docs
80
+
81
+ - A generated provider×knob matrix on the modelrig.dev route-bundles page and in
82
+ `llms.txt`, rendered FROM `RAW_KNOB_SUPPORT` (never a hand-written twin).
83
+ - `caching-lifecycle.md`: the cache directive is provider-neutral — a resource
84
+ HANDLE on gemini, a routing HINT (`prompt_cache_key`, retention on openai) on
85
+ the OpenAI-dialect providers.
86
+
87
+ CE-8 — first-class **runRaw-only construction**. A Lane-B customer who only calls
88
+ `rig.runRaw`/`runRawStream` can now build a rig with no routes at all, so a stray
89
+ route file it never serves cannot down construction — retiring the empty-temp-dir
90
+ workaround.
91
+
92
+ ### Added
93
+
94
+ - **`RigConfig.routesDir` now accepts `null`** (was `string`). With `null`,
95
+ `createRig` SKIPS route loading, the `rig.yaml` manifest, and the
96
+ serveable-candidate gate; `runRaw`/`runRawStream` work exactly as before. The
97
+ `string` path is byte-identical to 0.3.0 (the existing serveability hard-error
98
+ on a zero-serveable route is unchanged and regression-pinned).
99
+ - **`requireRoutesDir(config, surface)`** exported — narrows `routesDir` to a
100
+ string for route-required contexts, throwing the teaching failure on `null`.
101
+ Used by `modelrig-server` and `modelrig-oracle` (both always serve routes).
102
+
103
+ ### Behaviour
104
+
105
+ - On a `routesDir: null` rig, `run`/`runStream`/`runBundle`/`runBundleStream`/
106
+ `replay`/`bakeoff`/`bakeoffFromEvalCases`/`verifySwap` throw `RigFailureError`
107
+ class `invariant_violation` (no new failure class) with the fixHint
108
+ *"this rig was constructed runRaw-only (routesDir: null); give createRig a
109
+ routesDir to serve routes"*. `rig.serveability` is `[]`.
110
+ - `loadConfigFromEnv` stays string-only (no env var disables routes, by design);
111
+ opt out in code: `createRig({ ...loadConfigFromEnv(), routesDir: null })`.
112
+
113
+ ### Docs
114
+
115
+ - README, `docs/migration-playbook.md` (Lane-B seam + C4 checkpoint), and the
116
+ generated `llms.txt` gain the runRaw-only construction snippet, the `apiKey`
117
+ BYOK line on every `runRaw` example, the combined-prompt → `userPrompt` note,
118
+ and the note that the cache-ratio-vs-baseline metric is a REAL-run measurement
119
+ (deferred-to-first-run at the checkpoint), not a probe.
120
+
121
+ R0 — the **per-call telemetry ladder key** (routing-console spec §2.1). Every
122
+ inference row now records which call it belongs to and its position in the
123
+ routing ladder, so a dashboard can reconstruct the exact sequence one `rig.run`
124
+ walked and compute fallback / repair rates.
125
+
126
+ ### Added — telemetry ladder key
127
+
128
+ - **`RunMeta.callId`** — the `call_id` shared by every telemetry row a single
129
+ `run` / `runStream` / `runBundle` / `runRaw` invocation writes (primary, retry,
130
+ repair, grounding-search, tool-call), so a caller can correlate a `RunResult`
131
+ with its ladder in the console. Additive & OPTIONAL — a pre-0.4.0 caller's meta
132
+ omits it.
133
+ - Telemetry rows gain **`call_id`**, **`attempt_seq`** (1-based, monotonic across
134
+ every row of the call), and **`candidate_index`** (position of the dispatched
135
+ candidate in the call's EFFECTIVE declared list — after variant narrowing and
136
+ per-run filters; a repair row carries the repaired candidate's index; the raw
137
+ lane is seq 1 / index 0). All three are OPTIONAL on the wire and nullable in
138
+ storage: an older SDK OMITS them and the payload is byte-identical to before
139
+ R0; a reader treats null as *"recorded by an SDK older than 0.4.0."*
140
+ - OTLP spans gain `modelrig.call_id` / `modelrig.attempt_seq` /
141
+ `modelrig.candidate_index`, emitted only when present.
142
+ - **`CandidateIterator.index`** (read-only getter, public type) — the index of the
143
+ candidate the last `next()` returned (−1 before the first call). Additive for
144
+ callers; an external IMPLEMENTER of the interface must add the member.
145
+ - **`tags.rung`** on every telemetry row (R1 review, F1) — one of `primary` |
146
+ `retry` | `repair` | `search` | `tool_call` | `predispatch_fail`, so the routing
147
+ dashboard and ladder view can tell a real candidate dispatch from a tool-call
148
+ turn or a pre-dispatch failure without column heuristics. Additive (rides
149
+ `tags_json`, no schema change); a pre-0.4.0 row omits it and the rollup falls
150
+ back to `repaired_by` / `provider = "search"`. Public type `TelemetryRung` is
151
+ exported.
152
+
13
153
  ## [0.3.0] — 2026-08-21
14
154
 
15
155
  The `modelrig-oracle` MCP server ships to npm alongside this release (its own
package/README.md CHANGED
@@ -99,27 +99,75 @@ over the route's `cache: auto` stamp, and a non-matching fallback dispatches
99
99
  without it. ModelRig carries the handle and prices the hits — it never creates,
100
100
  refreshes, or deletes the resource, so a long job needs your own TTL heartbeat
101
101
  (see the [caching lifecycle](https://modelrig.dev/caching-lifecycle.html) doc).
102
- The Lane-B `rig.runRaw({ provider, model, …, cache: { key } })` seam takes the
103
- same field.
102
+ The Lane-B `rig.runRaw({ provider, model, apiKey, …, cache: { key } })` seam takes
103
+ the same field.
104
104
 
105
105
  `rig.runRaw` also accepts
106
- three provider knobs, each additive — absent ⇒ byte-identical dispatch:
107
- `grounding: { mode: "native" }` (native provider web grounding, gemini-only in
108
- v1), `serviceTier: "standard" | "flex" | "priority"`, and
109
- `reasoning: { level: "minimal" | "low" | "medium" | "high" }` (gemini-only in
110
- v1, mapped to the thinking level). A declared directive a provider cannot honor
111
- FAILS CLOSED — a thrown `RigFailureError` with class `invariant_violation`,
112
- pre-dispatch (no meter, no provider call) — never a silent drop. A grounded step
113
- that also passes a `cache.key` keeps its cached-token ratio: bake the
114
- `googleSearch` tool into the cache resource at creation (ModelRig sends
115
- `cachedContent` without tools, which the provider requires).
106
+ provider knobs, each additive — absent ⇒ byte-identical dispatch:
107
+ `grounding: { mode: "native" }` (native provider web grounding —
108
+ gemini; grok fail-closed until CE-9b), `serviceTier: "standard" | "flex" | "priority"`,
109
+ `reasoning: { level: "minimal" | "low" | "medium" | "high" }` (reasoning effort¹),
110
+ and `responseFormat: "json_object"` (syntactic-JSON forcing¹ — MIME-shaping, NOT
111
+ schema enforcement, so `meta.validated` stays `false`). A declared directive a
112
+ provider cannot honor FAILS CLOSED — a thrown `RigFailureError` with class
113
+ `invariant_violation`, pre-dispatch (no meter, no provider call) — never a silent
114
+ drop. **Which provider honors which knob is one table** — the runtime guard and
115
+ the published
116
+ [provider × knob matrix](https://modelrig.dev/route-bundles.html#raw-lane-provider-knob-support-rigrunraw)
117
+ are generated from the same `RAW_KNOB_SUPPORT`; ask it in code with
118
+ `rawKnobSupport(provider)` (and `GEMINI_THINKING_CAPABLE_MODELS` is exported so
119
+ you don't duplicate the thinking-model set). A grounded step that also passes a
120
+ `cache.key` keeps its cached-token ratio: bake the `googleSearch` tool into the
121
+ cache resource at creation (ModelRig sends `cachedContent` without tools, which
122
+ the provider requires).
123
+
124
+ _¹ Multi-provider `reasoning` and `responseFormat` ship in
125
+ 0.4.0; on the published package `reasoning`/`grounding` are gemini-only._
126
+
127
+ **runRaw — a BYOK passthrough (Lane B).** When you don't need a route — no
128
+ schema, no validation, no retries — call a `provider/model` directly with your
129
+ own provider key:
130
+
131
+ ```ts
132
+ const rig = createRig(loadConfigFromEnv());
133
+ const result = await rig.runRaw({
134
+ provider: "gemini",
135
+ model: "gemini-3.1-pro",
136
+ apiKey: process.env.GEMINI_API_KEY!, // runRaw is BYOK — pass your provider key
137
+ systemPrompt: "", // one combined prompt? put it ALL in userPrompt, leave systemPrompt empty
138
+ userPrompt: buildPrompt(input),
139
+ });
140
+ ```
141
+
142
+ `runRaw` is BYOK — pass your provider key; ModelRig holds it for the one call and
143
+ never stores it. It records one metered `lane=raw` telemetry row at the
144
+ provider's list price (zero ModelRig margin) and throws a typed `RigFailureError`
145
+ on failure, exactly like `rig.run`.
146
+
147
+ **runRaw-only construction (`routesDir: null`) — 0.4.0+.** A
148
+ Lane-B deployment that ONLY calls `runRaw`/`runRawStream` has no routes. Build it
149
+ with `routesDir: null` and `createRig` skips route loading, the `rig.yaml`
150
+ manifest, and the serveability gate entirely — so a stray route file it never
151
+ calls (or a route whose provider key is absent in this deployment) can no longer
152
+ down construction:
153
+
154
+ ```ts
155
+ const rig = createRig({ ...loadConfigFromEnv(), routesDir: null });
156
+ await rig.runRaw({ provider, model, apiKey, systemPrompt, userPrompt });
157
+ ```
158
+
159
+ `loadConfigFromEnv()` always yields a string `routesDir`, so the opt-out is a
160
+ deliberate code-level choice — override it as above; there is no env var that
161
+ disables routes, by design. On such a rig, `rig.run` and every other
162
+ route-dependent surface (`runStream`, `runBundle`, bake-offs, watch, replay,
163
+ `verifySwap`) throws a terminal `invariant_violation` naming the fix.
116
164
 
117
165
  Every attempt is recorded in a local SQLite file (`.modelrig/telemetry.db`)
118
166
  tagged with your `tags`. Failures are typed —
119
167
  `RigFailureError.failure.class` is one of `content_invalid`, `capacity_shed`,
120
- `network`, `refusal`, `cache_invalid`, `timeout`, `budget_exhausted`,
168
+ `network`, `refusal`, `cache_invalid`, `timeout`, `config_auth`, `budget_exhausted`,
121
169
  `invariant_violation` — with a separate retry budget per class, so a flaky
122
- network never spends your content-validation retries.
170
+ 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).
123
171
 
124
172
  ## CLI
125
173
 
@@ -155,6 +203,10 @@ on the quickstart:
155
203
  stable enough to build on, not frozen.
156
204
  - **`modelrig serve` needs the `modelrig-server` package** — it is not bundled
157
205
  here.
206
+ - **What the ladder does and does not do.** Fall-through is structural and
207
+ infrastructural, never a quality judgment; the full boundary (quality gate,
208
+ raw-lane structure, latency ordering…) is generated and tripwire-tested on
209
+ [Routing & reliability](https://modelrig.dev/routing-reliability.html#10-not-yet-implemented-the-boundary).
158
210
 
159
211
  ## License
160
212
 
@@ -1 +1 @@
1
- {"version":3,"file":"deepseek.d.ts","sourceRoot":"","sources":["../../src/adapters/deepseek.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMhG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAMhF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAiB1E;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAOD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,oBAAoB,CA2B1F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CA8JpF"}
1
+ {"version":3,"file":"deepseek.d.ts","sourceRoot":"","sources":["../../src/adapters/deepseek.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMhG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAKD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAMhF;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAiB1E;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAOD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,oBAAoB,CAkC1F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CA8JpF"}
@@ -62,6 +62,13 @@ function classifyDeepSeekFailure(message) {
62
62
  const JSON_GUARD = "Respond with a single valid JSON object.";
63
63
  function buildDeepSeekParams(model, req) {
64
64
  const wantJson = req.outputSchema !== null;
65
+ // CE-9 R4: the raw lane's `responseFormat: "json_object"` also drives DeepSeek's
66
+ // json_object mode (the flag previously fired ONLY on the routed outputSchema
67
+ // path, which is always null on the raw lane). Absent both ⇒ no key
68
+ // (byte-identical). The JSON_GUARD below stays keyed on the ROUTED path only:
69
+ // on the raw lane the word-"JSON" wrinkle is the caller's prompt responsibility
70
+ // (spec R4), not silently intercepted here.
71
+ const jsonObject = wantJson || req.responseFormat === "json_object";
65
72
  let systemPrompt = req.systemPrompt;
66
73
  if (wantJson && !req.systemPrompt.includes("JSON") && !req.userPrompt.includes("JSON")) {
67
74
  systemPrompt = systemPrompt === "" ? JSON_GUARD : `${systemPrompt}\n\n${JSON_GUARD}`;
@@ -77,7 +84,7 @@ function buildDeepSeekParams(model, req) {
77
84
  stream: true,
78
85
  stream_options: { include_usage: true },
79
86
  ...(0, sampling_1.openAISamplingFields)(req),
80
- ...(wantJson ? { response_format: { type: "json_object" } } : {}),
87
+ ...(jsonObject ? { response_format: { type: "json_object" } } : {}),
81
88
  ...(req.tools !== undefined && req.tools.length > 0
82
89
  ? {
83
90
  tools: (0, tool_mapping_1.toOpenAITools)(req.tools),
@@ -18,6 +18,12 @@ import type { FailureClass } from "../types/failures";
18
18
  export interface GeminiAdapterConfig {
19
19
  readonly apiKey: string;
20
20
  }
21
+ /** Models that accept thinkingConfig — passing it to 2.x models 400s.
22
+ * Ported from the production THINKING_CAPABLE_MODELS set. EXPORTED (CE-9 R6) so
23
+ * a multi-provider customer's dispatcher reads THIS set instead of duplicating
24
+ * it (the §3.1 drift complaint) — the same fact the raw-lane guard uses to keep
25
+ * gemini reasoning model-gated. */
26
+ export declare const GEMINI_THINKING_CAPABLE_MODELS: ReadonlySet<string>;
21
27
  export declare function geminiSupports(feature: CapabilityFlag, model: string): boolean;
22
28
  export interface ClassifiedFailure {
23
29
  readonly cls: FailureClass;
@@ -1 +1 @@
1
- {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EACV,cAAc,EAGd,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AAKlE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAkCD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG9E;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAyCxE;AAED;6EAC6E;AAC7E,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,iBAAiB,GAAG,IAAI,CAQrG;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,mBAAmB,CAgDxF;AA0BD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,eAAe,CA+JhF"}
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EACV,cAAc,EAGd,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AAKlE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;mCAImC;AACnC,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAI7D,CAAC;AA0BH,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG9E;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAyCxE;AAED;6EAC6E;AAC7E,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,iBAAiB,GAAG,IAAI,CAQrG;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,mBAAmB,CAqDxF;AA0BD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,eAAe,CA+JhF"}
@@ -15,6 +15,7 @@
15
15
  * gemini transformation logic is consulted during the port.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.GEMINI_THINKING_CAPABLE_MODELS = void 0;
18
19
  exports.geminiSupports = geminiSupports;
19
20
  exports.classifyGeminiFailure = classifyGeminiFailure;
20
21
  exports.geminiReasoningUnsupported = geminiReasoningUnsupported;
@@ -24,8 +25,11 @@ const genai_1 = require("@google/genai");
24
25
  const tool_mapping_1 = require("./tool-mapping");
25
26
  const sampling_1 = require("./sampling");
26
27
  /** Models that accept thinkingConfig — passing it to 2.x models 400s.
27
- * Ported from the production THINKING_CAPABLE_MODELS set. */
28
- const THINKING_CAPABLE_MODELS = new Set([
28
+ * Ported from the production THINKING_CAPABLE_MODELS set. EXPORTED (CE-9 R6) so
29
+ * a multi-provider customer's dispatcher reads THIS set instead of duplicating
30
+ * it (the §3.1 drift complaint) — the same fact the raw-lane guard uses to keep
31
+ * gemini reasoning model-gated. */
32
+ exports.GEMINI_THINKING_CAPABLE_MODELS = new Set([
29
33
  "gemini-3.1-pro-preview",
30
34
  "gemini-3.0-pro-preview",
31
35
  "gemini-3.1-flash-preview",
@@ -110,7 +114,7 @@ function classifyGeminiFailure(message) {
110
114
  * reasoning declared, or a thinking-capable model). Pure — unit-tested directly.
111
115
  */
112
116
  function geminiReasoningUnsupported(model, req) {
113
- if (req.reasoning !== undefined && !THINKING_CAPABLE_MODELS.has(model)) {
117
+ if (req.reasoning !== undefined && !exports.GEMINI_THINKING_CAPABLE_MODELS.has(model)) {
114
118
  return {
115
119
  cls: "invariant_violation",
116
120
  fixHint: `reasoning control requires a thinking-capable Gemini model; "${model}" is not one — remove reasoning or choose a thinking-capable model`,
@@ -134,12 +138,18 @@ function buildGeminiRequest(model, req) {
134
138
  maxOutputTokens: (0, sampling_1.effectiveMaxOutputTokens)(req, DEFAULT_MAX_OUTPUT_TOKENS),
135
139
  topP: req.sampling?.topP ?? TOP_P,
136
140
  topK: TOP_K,
137
- ...(THINKING_CAPABLE_MODELS.has(model) ? { thinkingConfig: { thinkingLevel } } : {}),
141
+ ...(exports.GEMINI_THINKING_CAPABLE_MODELS.has(model) ? { thinkingConfig: { thinkingLevel } } : {}),
138
142
  };
139
143
  if (req.outputSchema !== null) {
140
144
  config.responseMimeType = "application/json";
141
145
  config.responseJsonSchema = req.outputSchema;
142
146
  }
147
+ else if (req.responseFormat === "json_object") {
148
+ // CE-9 R4: mime-shaping ONLY — force a JSON mime type WITHOUT a schema. This
149
+ // is the raw lane, so F4 stands: no responseJsonSchema, no validation, no
150
+ // repair, `validated` stays false. Absent ⇒ no key (byte-identical).
151
+ config.responseMimeType = "application/json";
152
+ }
143
153
  // cachedContent excludes systemInstruction and tools — the API rejects
144
154
  // requests setting both (they are baked into the cache at creation time,
145
155
  // including the googleSearch tool for cached grounded steps).
@@ -36,7 +36,14 @@ export interface GrokShapedParams {
36
36
  /** Prompt-cache routing hint (WS-C) — the stable-prefix fingerprint the run
37
37
  * loop stamps; xAI keeps a warm cache keyed to it (writes free today). */
38
38
  readonly prompt_cache_key?: string;
39
+ /** CE-9 R1 — xAI accepts `reasoning_effort: "low" | "high"` ONLY, so the
40
+ * neutral four-level `level` is coarsened by `coarsenGrokReasoningEffort`
41
+ * (a DISCLOSED, lossy mapping: `minimal,low → "low"`; `medium,high → "high"`).
42
+ * Present only when the caller declared `reasoning`. */
43
+ readonly reasoning_effort?: "low" | "high";
39
44
  readonly response_format?: {
45
+ readonly type: "json_object";
46
+ } | {
40
47
  readonly type: "json_schema";
41
48
  readonly json_schema: {
42
49
  readonly name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"grok.d.ts","sourceRoot":"","sources":["../../src/adapters/grok.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMhG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAKD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAc7E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAsBtE;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;8EAC0E;IAC1E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,eAAe,CAAC,EAAE;QACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAC;KACjG,CAAC;IACF,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,gBAAgB,CAsClF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAgK5E"}
1
+ {"version":3,"file":"grok.d.ts","sourceRoot":"","sources":["../../src/adapters/grok.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAOhG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAKD,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAc7E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CA+BtE;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;8EAC0E;IAC1E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;4DAGwD;IACxD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC3C,QAAQ,CAAC,eAAe,CAAC,EACrB;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,GAChC;QACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAC;KACjG,CAAC;IACN,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,gBAAgB,CAmDlF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAgK5E"}
@@ -23,6 +23,7 @@ const openai_1 = __importDefault(require("openai"));
23
23
  const tool_mapping_1 = require("./tool-mapping");
24
24
  const openai_stream_1 = require("./openai-stream");
25
25
  const sampling_1 = require("./sampling");
26
+ const raw_support_1 = require("../run/raw-support");
26
27
  const GROK_BASE_URL = "https://api.x.ai/v1";
27
28
  const DEFAULT_MAX_TOKENS = 32000;
28
29
  function grokSupports(feature, _model) {
@@ -65,6 +66,14 @@ function classifyGrokFailure(message) {
65
66
  fixHint: "the candidate model was not found — fix the model id in the route's candidate list",
66
67
  };
67
68
  }
69
+ // CE-9 R1: a non-reasoning grok variant rejects `reasoning_effort` — teach the
70
+ // fix (pick a reasoning variant) rather than surface a cryptic 400.
71
+ if (/reasoning_effort/.test(msg)) {
72
+ return {
73
+ cls: "network",
74
+ fixHint: "this Grok model does not accept reasoning_effort — remove reasoning or pick a Grok reasoning variant",
75
+ };
76
+ }
68
77
  return { cls: "network" };
69
78
  }
70
79
  function buildGrokParams(model, req) {
@@ -84,6 +93,17 @@ function buildGrokParams(model, req) {
84
93
  ...(req.cache?.key !== undefined && req.cache.key !== ""
85
94
  ? { prompt_cache_key: req.cache.key }
86
95
  : {}),
96
+ // CE-9 R1: coarsen the neutral level to xAI's low|high (disclosed mapping).
97
+ // Absent ⇒ no key. A non-reasoning grok model's rejection is taught below.
98
+ ...(req.reasoning !== undefined
99
+ ? { reasoning_effort: (0, raw_support_1.coarsenGrokReasoningEffort)(req.reasoning.level) }
100
+ : {}),
101
+ // CE-9b: grounding is NOT mapped here. xAI retired Live Search
102
+ // (`search_parameters` → HTTP 410 on the CE-9 live gate); the replacement
103
+ // `web_search` tool is Responses-API-only. The raw-lane guard fails grok
104
+ // grounding closed (matrix: supported=false) until CE-9b adds that path.
105
+ // response_format: a native strict json_schema (routed lane) wins; else the
106
+ // RAW lane's mime-shaping json_object (CE-9 R4). Absent both ⇒ no key.
87
107
  ...(req.outputSchema !== null
88
108
  ? {
89
109
  response_format: {
@@ -95,7 +115,9 @@ function buildGrokParams(model, req) {
95
115
  },
96
116
  },
97
117
  }
98
- : {}),
118
+ : req.responseFormat === "json_object"
119
+ ? { response_format: { type: "json_object" } }
120
+ : {}),
99
121
  ...(req.tools !== undefined && req.tools.length > 0
100
122
  ? {
101
123
  tools: (0, tool_mapping_1.toOpenAITools)(req.tools),
@@ -49,6 +49,13 @@ export interface OpenAICompatShapedParams {
49
49
  /** CE-6 declared sampling — present only when the route/raw asks for them. */
50
50
  readonly temperature?: number;
51
51
  readonly top_p?: number;
52
+ /** CE-9 R1 — reasoning effort forwarded verbatim (1:1). Present only when the
53
+ * caller declared `reasoning`; a host/model that does not accept it rejects at
54
+ * the provider and `classifyCompatFailure` teaches (no per-model allowlist). */
55
+ readonly reasoning_effort?: "minimal" | "low" | "medium" | "high";
56
+ /** CE-9 R3 — the DeepInfra prompt_cache_key gap: `cache.key` → the routing
57
+ * hint. Present only when the caller supplies `cache.key`. */
58
+ readonly prompt_cache_key?: string;
52
59
  readonly response_format?: {
53
60
  readonly type: "json_object";
54
61
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAQhG;;8CAE8C;AAC9C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AAED;;;0EAG0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,GAAG,WAAW,EAAE,gBAAgB,CAAC,CAG7F,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAiBtF;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EACrB;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,GAChC;QACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACjG,CAAC;IACN,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAOD;;2DAE2D;AAC3D,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,YAAY,EACjB,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,GACxC,wBAAwB,CAqC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD;+DAC2D;IAC3D,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC,cAAc,CAAC,CAAC;CAC5E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,GAAG,eAAe,CAwK5F"}
1
+ {"version":3,"file":"openai-compat.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EACf,UAAU,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAQhG;;8CAE8C;AAC9C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AAED;;;0EAG0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,GAAG,WAAW,EAAE,gBAAgB,CAAC,CAG7F,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA2BtF;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;oFAEgF;IAChF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClE;kEAC8D;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,eAAe,CAAC,EACrB;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,GAChC;QACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACjG,CAAC;IACN,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAOD;;2DAE2D;AAC3D,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,YAAY,EACjB,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,GACxC,wBAAwB,CAmD1B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD;+DAC2D;IAC3D,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC,cAAc,CAAC,CAAC;CAC5E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB,GAAG,eAAe,CAwK5F"}
@@ -66,6 +66,15 @@ function classifyCompatFailure(message, host) {
66
66
  fixHint: "the candidate model was not found — fix the model id in the route's candidate list",
67
67
  };
68
68
  }
69
+ // CE-9 R1: a model that does not accept `reasoning_effort` rejects the request
70
+ // — teach it rather than surfacing a cryptic generic 400 (the reason we forward
71
+ // verbatim instead of keeping a per-model allowlist).
72
+ if (/reasoning_effort/.test(msg)) {
73
+ return {
74
+ cls: "network",
75
+ fixHint: `this ${host} model does not accept reasoning_effort — remove reasoning or pick a reasoning model`,
76
+ };
77
+ }
69
78
  return { cls: "network" };
70
79
  }
71
80
  /** json_object mode 400s on several compat backends when the literal word
@@ -93,6 +102,18 @@ function buildOpenAICompatParams(model, req, profileFlags) {
93
102
  stream: true,
94
103
  stream_options: { include_usage: true },
95
104
  ...(0, sampling_1.openAISamplingFields)(req),
105
+ // CE-9 R1: forward reasoning effort verbatim (1:1). Absent ⇒ no key.
106
+ ...(req.reasoning !== undefined ? { reasoning_effort: req.reasoning.level } : {}),
107
+ // CE-9 R3: the DeepInfra prompt_cache_key gap — map cache.key → the routing
108
+ // hint (absent ⇒ no key, byte-identical). Additive; unrecognized on a host
109
+ // that doesn't cache, the hint is simply ignored.
110
+ ...(req.cache?.key !== undefined && req.cache.key !== ""
111
+ ? { prompt_cache_key: req.cache.key }
112
+ : {}),
113
+ // response_format: a routed strict json_schema (structured_native profile)
114
+ // wins; else routed json_object; else the RAW lane's mime-shaping json_object
115
+ // (CE-9 R4). The raw path carries NO JSON_GUARD injection — the word-"JSON"
116
+ // wrinkle is the caller's prompt responsibility on the raw lane.
96
117
  ...(wantJson
97
118
  ? strict
98
119
  ? {
@@ -102,7 +123,9 @@ function buildOpenAICompatParams(model, req, profileFlags) {
102
123
  },
103
124
  }
104
125
  : { response_format: { type: "json_object" } }
105
- : {}),
126
+ : req.responseFormat === "json_object"
127
+ ? { response_format: { type: "json_object" } }
128
+ : {}),
106
129
  ...(req.tools !== undefined && req.tools.length > 0
107
130
  ? {
108
131
  tools: (0, tool_mapping_1.toOpenAITools)(req.tools),
@@ -38,7 +38,14 @@ export interface OpenAIShapedParams {
38
38
  readonly service_tier?: "flex" | "priority";
39
39
  readonly prompt_cache_key?: string;
40
40
  readonly prompt_cache_retention?: "24h";
41
+ /** CE-9 R1 — reasoning effort forwarded verbatim (1:1 from the neutral
42
+ * `level`). Present only when the caller declared `reasoning`. A model that
43
+ * does not accept it rejects at the provider; `classifyOpenAIFailure` turns
44
+ * that 400 into a teaching failure (no per-model allowlist). */
45
+ readonly reasoning_effort?: "minimal" | "low" | "medium" | "high";
41
46
  readonly response_format?: {
47
+ readonly type: "json_object";
48
+ } | {
42
49
  readonly type: "json_schema";
43
50
  readonly json_schema: {
44
51
  readonly name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMhG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAMD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAe9E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAiBxE;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,KAAK,CAAC;IACxC,QAAQ,CAAC,eAAe,CAAC,EAAE;QACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAC;KACjG,CAAC;IACF,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,kBAAkB,CA6CtF;AAcD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,eAAe,CAwMhF"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAIV,cAAc,EACd,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMhE,OAAO,KAAK,EAAuB,cAAc,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAMhG,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAMD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAe9E;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CA8BxE;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,KAAK,CAAC;IACxC;;;oEAGgE;IAChE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClE,QAAQ,CAAC,eAAe,CAAC,EACrB;QAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;KAAE,GAChC;QACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,WAAW,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAC;KACjG,CAAC;IACN,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,GAAG,kBAAkB,CAuDtF;AAcD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,eAAe,CAwMhF"}
@@ -71,6 +71,18 @@ function classifyOpenAIFailure(message) {
71
71
  fixHint: "the candidate model was not found — fix the model id in the route's candidate list",
72
72
  };
73
73
  }
74
+ // CE-9 R1: a model that does not accept `reasoning_effort` rejects the request
75
+ // (400 "unsupported/unknown parameter reasoning_effort"). Teach it instead of
76
+ // surfacing a cryptic generic 400 — the whole point of forwarding verbatim
77
+ // rather than keeping a per-model allowlist. Mirrors gemini's invalid_argument
78
+ // → network + fixHint (a request-shape rejection, retryable to the next
79
+ // candidate, never terminal).
80
+ if (/reasoning_effort/.test(msg)) {
81
+ return {
82
+ cls: "network",
83
+ fixHint: "this model does not accept reasoning_effort — remove reasoning or pick a reasoning model (e.g. an o-series / gpt-5 reasoning model)",
84
+ };
85
+ }
74
86
  return { cls: "network" };
75
87
  }
76
88
  const DEFAULT_MAX_COMPLETION_TOKENS = 32000;
@@ -98,6 +110,14 @@ function buildOpenAIParams(model, req) {
98
110
  ...((req.cache.ttlSeconds ?? 0) >= 86400 ? { prompt_cache_retention: "24h" } : {}),
99
111
  }
100
112
  : {}),
113
+ // CE-9 R1: forward reasoning effort verbatim (1:1). Absent ⇒ no key
114
+ // (byte-identical). The provider — not an allowlist here — decides whether
115
+ // the model accepts it; a rejection is classified teachably below.
116
+ ...(req.reasoning !== undefined ? { reasoning_effort: req.reasoning.level } : {}),
117
+ // response_format precedence: a native/strict json_schema (routed lane,
118
+ // outputSchema set) WINS; else the raw lane's mime-shaping json_object
119
+ // (CE-9 R4). The two never co-occur — the routed lane sets outputSchema, the
120
+ // raw lane responseFormat — but the precedence keeps resolution deterministic.
101
121
  ...(req.outputSchema !== null
102
122
  ? {
103
123
  response_format: {
@@ -109,7 +129,9 @@ function buildOpenAIParams(model, req) {
109
129
  },
110
130
  },
111
131
  }
112
- : {}),
132
+ : req.responseFormat === "json_object"
133
+ ? { response_format: { type: "json_object" } }
134
+ : {}),
113
135
  ...(req.tools !== undefined && req.tools.length > 0
114
136
  ? {
115
137
  tools: (0, tool_mapping_1.toOpenAITools)(req.tools),
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAiCH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAeD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAuBxD;AA0gBD,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqCnE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAkCH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAeD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAuBxD;AA0gBD,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqCnE"}
package/dist/cli.js CHANGED
@@ -35,6 +35,7 @@ const samples_1 = require("./bakeoff/samples");
35
35
  const report_1 = require("./bakeoff/report");
36
36
  const cli_run_1 = require("./verify/cli-run");
37
37
  const loader_1 = require("./routes/loader");
38
+ const rawonly_1 = require("./run/rawonly");
38
39
  const validate_cli_1 = require("./validate-cli");
39
40
  const store_1 = require("./telemetry/store");
40
41
  const budget_1 = require("./watch/budget");
@@ -156,7 +157,7 @@ async function cmdBakeoff(flags) {
156
157
  throw new Error(`proposal ${proposalId} is ${proposal.status} — evidence runs apply to ` +
157
158
  "suggested/evidenced proposals only");
158
159
  }
159
- const routes = (0, loader_1.loadRoutes)(config.routesDir);
160
+ const routes = (0, loader_1.loadRoutes)((0, rawonly_1.requireRoutesDir)(config, "modelrig bakeoff"));
160
161
  const bundle = routes.get(proposal.route);
161
162
  const variants = ["default", ...bundle.variants.map((v) => v.name)];
162
163
  const lastRaw = flags.named.get("replay-last");
@@ -243,7 +244,7 @@ async function cmdWatch(flags) {
243
244
  }
244
245
  const config = (0, config_1.loadConfigFromEnv)();
245
246
  const client = proposalsClientFrom(config);
246
- const routes = (0, loader_1.loadRoutes)(config.routesDir);
247
+ const routes = (0, loader_1.loadRoutes)((0, rawonly_1.requireRoutesDir)(config, "modelrig watch"));
247
248
  const routeEconomics = routes.list().map((b) => ({
248
249
  route: b.route,
249
250
  candidates: b.candidates.map((c) => ({ provider: c.provider, model: c.model })),
@@ -318,7 +319,7 @@ async function cmdSwapExecute(flags) {
318
319
  const config = (0, config_1.loadConfigFromEnv)();
319
320
  const proposals = proposalsClientFrom(config);
320
321
  const swaps = swapsClientFrom(config);
321
- const routes = (0, loader_1.loadRoutes)(config.routesDir);
322
+ const routes = (0, loader_1.loadRoutes)((0, rawonly_1.requireRoutesDir)(config, "modelrig swap execute"));
322
323
  // The orchestration (guards, ordering, baseline snapshot) lives in the
323
324
  // hermetically-tested executeSwap; the CLI only injects the real config
324
325
  // deps and prints. The --approve gate is enforced here (fast-fail before
@@ -359,7 +360,7 @@ async function cmdSwapRevert(flags) {
359
360
  const incumbents = swap.baseline.incumbent_candidates ?? [];
360
361
  console.log(`swap ${swapId} marked reverted — the odometer stops accruing it at ${revertedAt}\n`);
361
362
  console.log("APPLY THIS CHANGE (git is the actuator, as always):\n");
362
- const routes = (0, loader_1.loadRoutes)(config.routesDir);
363
+ const routes = (0, loader_1.loadRoutes)((0, rawonly_1.requireRoutesDir)(config, "modelrig swap revert"));
363
364
  let version = null;
364
365
  try {
365
366
  version = routes.get(swap.route).version + 1;