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.
- package/CHANGELOG.md +140 -0
- package/README.md +66 -14
- package/dist/adapters/deepseek.d.ts.map +1 -1
- package/dist/adapters/deepseek.js +8 -1
- package/dist/adapters/gemini.d.ts +6 -0
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +14 -4
- package/dist/adapters/grok.d.ts +7 -0
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +23 -1
- package/dist/adapters/openai-compat.d.ts +7 -0
- package/dist/adapters/openai-compat.d.ts.map +1 -1
- package/dist/adapters/openai-compat.js +24 -1
- package/dist/adapters/openai.d.ts +7 -0
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +23 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -4
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -25
- package/dist/init/init-cli.d.ts.map +1 -1
- package/dist/init/init-cli.js +2 -1
- package/dist/init/observe-cli.d.ts.map +1 -1
- package/dist/init/observe-cli.js +2 -1
- package/dist/routes/sampling-config.d.ts.map +1 -1
- package/dist/routes/sampling-config.js +11 -0
- package/dist/run/dispatch.d.ts +14 -2
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +31 -2
- package/dist/run/ladder-key.d.ts +40 -0
- package/dist/run/ladder-key.d.ts.map +1 -0
- package/dist/run/ladder-key.js +39 -0
- package/dist/run/raw-support.d.ts +123 -0
- package/dist/run/raw-support.d.ts.map +1 -0
- package/dist/run/raw-support.js +150 -0
- package/dist/run/raw.d.ts +41 -11
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +67 -23
- package/dist/run/rawonly.d.ts +60 -0
- package/dist/run/rawonly.d.ts.map +1 -0
- package/dist/run/rawonly.js +120 -0
- package/dist/run/record-attempt.d.ts +14 -1
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +43 -2
- package/dist/run/resolve.d.ts +4 -0
- package/dist/run/resolve.d.ts.map +1 -1
- package/dist/run/resolve.js +9 -2
- package/dist/run/routing-docs.d.ts +73 -0
- package/dist/run/routing-docs.d.ts.map +1 -0
- package/dist/run/routing-docs.js +222 -0
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +24 -22
- package/dist/telemetry/exporter.d.ts.map +1 -1
- package/dist/telemetry/exporter.js +6 -0
- package/dist/telemetry/ingest-protocol.d.ts +7 -0
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/load-error-report.d.ts.map +1 -1
- package/dist/telemetry/load-error-report.js +4 -1
- package/dist/telemetry/otel-map.d.ts.map +1 -1
- package/dist/telemetry/otel-map.js +8 -0
- package/dist/telemetry/store-migrations.d.ts +15 -0
- package/dist/telemetry/store-migrations.d.ts.map +1 -0
- package/dist/telemetry/store-migrations.js +119 -0
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/store.js +26 -93
- package/dist/types/failures-teaching.js +1 -1
- package/dist/types/provider.d.ts +13 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/route.d.ts +6 -1
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +31 -0
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/validate-cli.d.ts.map +1 -1
- package/dist/validate-cli.js +17 -4
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CE-9 (spec R5) — the raw-lane provider × knob support matrix, the SINGLE
|
|
3
|
+
* source of truth for which knobs each provider honors on `rig.runRaw`.
|
|
4
|
+
*
|
|
5
|
+
* BOTH the runtime guard (`assertRawKnobsSupported`, run/raw.ts) and the docs
|
|
6
|
+
* generator (scripts/build-docs-site.ts) import `RAW_KNOB_SUPPORT` — so the
|
|
7
|
+
* fail-closed behavior a customer hits at runtime and the published matrix they
|
|
8
|
+
* read beforehand can never disagree. The guard's provider sets are no longer
|
|
9
|
+
* inline literals; adding a provider (or widening a knob) is one edit here.
|
|
10
|
+
*
|
|
11
|
+
* The knob discipline this table encodes (spec R1/R2/R4):
|
|
12
|
+
* - grounding: gemini honors native web grounding (grok's Live Search was retired by
|
|
13
|
+
* xAI — 410 on the CE-9 live gate — so grok is fail-closed until CE-9b lands the
|
|
14
|
+
* Responses-API web_search path); every other provider
|
|
15
|
+
* FAILS CLOSED pre-dispatch (guarded).
|
|
16
|
+
* - reasoning: NO per-model allowlist outside gemini (the drift cost the
|
|
17
|
+
* customer flagged). openai/deepinfra/fireworks forward `level` verbatim as
|
|
18
|
+
* `reasoning_effort` and let the provider enforce (a rejection is classified
|
|
19
|
+
* teachably in each adapter); grok forwards a DISCLOSED coarsening
|
|
20
|
+
* (`coarsenGrokReasoningEffort`); gemini stays model-gated (the adapter
|
|
21
|
+
* rejects a non-thinking model); deepseek + anthropic FAIL CLOSED at the
|
|
22
|
+
* guard with a provider-specific fixHint.
|
|
23
|
+
* - responseFormat ("json_object"): the OpenAI-dialect providers + gemini
|
|
24
|
+
* (mime-shaping only) honor it; anthropic FAILS CLOSED (guarded). This is
|
|
25
|
+
* mime-shaping, NOT schema enforcement — F4 stands (no validation/repair,
|
|
26
|
+
* `meta.validated` stays false).
|
|
27
|
+
* - cache + serviceTier are INFORMATIONAL here (never a hard fail): the cache
|
|
28
|
+
* directive is provider-neutral (a resource HANDLE on gemini, a routing HINT
|
|
29
|
+
* on the prompt_cache_key providers) and serviceTier forwards everywhere.
|
|
30
|
+
*/
|
|
31
|
+
import type { ProviderId, ReasoningLevel } from "../types/provider";
|
|
32
|
+
/** How a provider treats a declared `reasoning.level` on the raw lane (R1). */
|
|
33
|
+
export type ReasoningSupportKind =
|
|
34
|
+
/** openai / deepinfra / fireworks — `level` → `reasoning_effort` 1:1,
|
|
35
|
+
* forwarded verbatim; an "unsupported parameter" rejection is classified
|
|
36
|
+
* teachably by the adapter (no per-model allowlist). */
|
|
37
|
+
"forward"
|
|
38
|
+
/** grok — `level` coarsened to xAI's `low|high` via
|
|
39
|
+
* `coarsenGrokReasoningEffort` (a DISCLOSED lossy mapping, never silent). */
|
|
40
|
+
| "coarsen"
|
|
41
|
+
/** gemini — honored only on a thinking-capable model; the adapter rejects a
|
|
42
|
+
* non-thinking model classified (`geminiReasoningUnsupported`). */
|
|
43
|
+
| "model-gated"
|
|
44
|
+
/** deepseek / anthropic — no effort control exists; rejected pre-dispatch by
|
|
45
|
+
* the guard with a provider-specific fixHint. */
|
|
46
|
+
| "fail-closed";
|
|
47
|
+
/** Cache-directive semantics per provider (R3) — documentation only; the raw
|
|
48
|
+
* lane never fails a call over the cache directive. */
|
|
49
|
+
export type CacheSemantics =
|
|
50
|
+
/** gemini — `cache.key` is a `cachedContent` resource HANDLE (customer-owned;
|
|
51
|
+
* ModelRig never creates/refreshes/deletes it). */
|
|
52
|
+
"handle"
|
|
53
|
+
/** openai / grok / deepinfra / fireworks — `cache.key` → `prompt_cache_key`, a
|
|
54
|
+
* routing HINT (openai also maps `ttlSeconds ≥ 86400` → 24h retention). */
|
|
55
|
+
| "hint"
|
|
56
|
+
/** deepseek — automatic prefix cache; the key is not used. */
|
|
57
|
+
| "implicit"
|
|
58
|
+
/** anthropic — prefix caching via `cache_control` markers; the key is not
|
|
59
|
+
* used (out of scope for the raw lane). */
|
|
60
|
+
| "marker";
|
|
61
|
+
/** A guarded knob (grounding / responseFormat): boolean support + the matrix
|
|
62
|
+
* cell text. The guard computes its thrown fixHint from the matrix (the list of
|
|
63
|
+
* supported providers), so widening the matrix updates the error too. */
|
|
64
|
+
export interface KnobFact {
|
|
65
|
+
readonly supported: boolean;
|
|
66
|
+
/** Human teaching string rendered in the docs matrix cell. */
|
|
67
|
+
readonly note: string;
|
|
68
|
+
}
|
|
69
|
+
/** Reasoning support per provider (R1) — `kind` drives the guard (only
|
|
70
|
+
* `fail-closed` throws) and the docs. */
|
|
71
|
+
export interface ReasoningFact {
|
|
72
|
+
readonly kind: ReasoningSupportKind;
|
|
73
|
+
readonly note: string;
|
|
74
|
+
/** Rendered by the guard's thrown error when `kind === "fail-closed"`. */
|
|
75
|
+
readonly fixHint?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface CacheFact {
|
|
78
|
+
readonly semantics: CacheSemantics;
|
|
79
|
+
readonly note: string;
|
|
80
|
+
}
|
|
81
|
+
export interface RawKnobSupport {
|
|
82
|
+
/** GUARDED — a declared `grounding` on an unsupported provider throws. */
|
|
83
|
+
readonly grounding: KnobFact;
|
|
84
|
+
/** GUARDED only when `kind === "fail-closed"` (deepseek/anthropic). */
|
|
85
|
+
readonly reasoning: ReasoningFact;
|
|
86
|
+
/** GUARDED — a declared `responseFormat` on an unsupported provider throws. */
|
|
87
|
+
readonly responseFormat: KnobFact;
|
|
88
|
+
/** INFORMATIONAL — the cache directive never hard-fails on the raw lane. */
|
|
89
|
+
readonly cache: CacheFact;
|
|
90
|
+
/** INFORMATIONAL — serviceTier forwards to every adapter; the served tier
|
|
91
|
+
* reports the truth. */
|
|
92
|
+
readonly serviceTier: KnobFact;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The grok reasoning coarsening (R1): xAI's `reasoning_effort` accepts only
|
|
96
|
+
* `"low" | "high"`, so the four-level neutral vocabulary is coarsened —
|
|
97
|
+
* `minimal, low → "low"`; `medium, high → "high"`. This is a DISCLOSED, lossy
|
|
98
|
+
* mapping (it appears in the matrix note, the grok field's doc comment, and the
|
|
99
|
+
* `grok.test.ts` test), never a silent semantic drop. Kept here — beside the
|
|
100
|
+
* matrix that documents it — as the ONE place the algorithm lives (grok.ts
|
|
101
|
+
* imports it).
|
|
102
|
+
*/
|
|
103
|
+
export declare function coarsenGrokReasoningEffort(level: ReasoningLevel): "low" | "high";
|
|
104
|
+
/** The matrix. Exhaustive over ProviderId — a new provider forces a compile
|
|
105
|
+
* error here (Record<ProviderId, …>), so it can never be silently unlisted. */
|
|
106
|
+
export declare const RAW_KNOB_SUPPORT: Record<ProviderId, RawKnobSupport>;
|
|
107
|
+
/** Pure lookup into the matrix (spec R6, exported from the package root). A
|
|
108
|
+
* customer's multi-provider dispatcher ASKS this instead of duplicating the
|
|
109
|
+
* provider lists. */
|
|
110
|
+
export declare function rawKnobSupport(provider: ProviderId): RawKnobSupport;
|
|
111
|
+
/** Providers that honor a knob, in PROVIDER_IDS order — used by the guard to
|
|
112
|
+
* build a "supported on X, Y only" fixHint from the matrix (so the error text
|
|
113
|
+
* can never drift from the table). */
|
|
114
|
+
export declare function groundingSupportedProviders(): readonly ProviderId[];
|
|
115
|
+
export declare function responseFormatSupportedProviders(): readonly ProviderId[];
|
|
116
|
+
/** Matrix-level notes rendered below the table (spec §3.2 restated in docs). */
|
|
117
|
+
export declare const RAW_KNOB_MATRIX_NOTES: readonly string[];
|
|
118
|
+
/** Render the provider × knob matrix as a Markdown table + notes, FROM the
|
|
119
|
+
* matrix (never a hand-written table — R5). Consumed by the docs generator
|
|
120
|
+
* (scripts/build-docs-site.ts) so the published matrix and the runtime guard
|
|
121
|
+
* derive from the same source. */
|
|
122
|
+
export declare function renderRawKnobMatrix(): string;
|
|
123
|
+
//# sourceMappingURL=raw-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-support.d.ts","sourceRoot":"","sources":["../../src/run/raw-support.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB;AAC9B;;wDAEwD;AACtD,SAAS;AACX;6EAC6E;GAC3E,SAAS;AACX;mEACmE;GACjE,aAAa;AACf;iDACiD;GAC/C,aAAa,CAAC;AAElB;uDACuD;AACvD,MAAM,MAAM,cAAc;AACxB;mDACmD;AACjD,QAAQ;AACV;2EAC2E;GACzE,MAAM;AACR,8DAA8D;GAC5D,UAAU;AACZ;2CAC2C;GACzC,QAAQ,CAAC;AAEb;;yEAEyE;AACzE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;yCACyC;AACzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B;4BACwB;IACxB,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,GAAG,MAAM,CAEhF;AAED;+EAC+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,EAAE,cAAc,CA+D/D,CAAC;AAEF;;qBAEqB;AACrB,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,cAAc,CAEnE;AAED;;sCAEsC;AACtC,wBAAgB,2BAA2B,IAAI,SAAS,UAAU,EAAE,CAEnE;AAED,wBAAgB,gCAAgC,IAAI,SAAS,UAAU,EAAE,CAExE;AAED,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAKlD,CAAC;AAEF;;;kCAGkC;AAClC,wBAAgB,mBAAmB,IAAI,MAAM,CAQ5C"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CE-9 (spec R5) — the raw-lane provider × knob support matrix, the SINGLE
|
|
4
|
+
* source of truth for which knobs each provider honors on `rig.runRaw`.
|
|
5
|
+
*
|
|
6
|
+
* BOTH the runtime guard (`assertRawKnobsSupported`, run/raw.ts) and the docs
|
|
7
|
+
* generator (scripts/build-docs-site.ts) import `RAW_KNOB_SUPPORT` — so the
|
|
8
|
+
* fail-closed behavior a customer hits at runtime and the published matrix they
|
|
9
|
+
* read beforehand can never disagree. The guard's provider sets are no longer
|
|
10
|
+
* inline literals; adding a provider (or widening a knob) is one edit here.
|
|
11
|
+
*
|
|
12
|
+
* The knob discipline this table encodes (spec R1/R2/R4):
|
|
13
|
+
* - grounding: gemini honors native web grounding (grok's Live Search was retired by
|
|
14
|
+
* xAI — 410 on the CE-9 live gate — so grok is fail-closed until CE-9b lands the
|
|
15
|
+
* Responses-API web_search path); every other provider
|
|
16
|
+
* FAILS CLOSED pre-dispatch (guarded).
|
|
17
|
+
* - reasoning: NO per-model allowlist outside gemini (the drift cost the
|
|
18
|
+
* customer flagged). openai/deepinfra/fireworks forward `level` verbatim as
|
|
19
|
+
* `reasoning_effort` and let the provider enforce (a rejection is classified
|
|
20
|
+
* teachably in each adapter); grok forwards a DISCLOSED coarsening
|
|
21
|
+
* (`coarsenGrokReasoningEffort`); gemini stays model-gated (the adapter
|
|
22
|
+
* rejects a non-thinking model); deepseek + anthropic FAIL CLOSED at the
|
|
23
|
+
* guard with a provider-specific fixHint.
|
|
24
|
+
* - responseFormat ("json_object"): the OpenAI-dialect providers + gemini
|
|
25
|
+
* (mime-shaping only) honor it; anthropic FAILS CLOSED (guarded). This is
|
|
26
|
+
* mime-shaping, NOT schema enforcement — F4 stands (no validation/repair,
|
|
27
|
+
* `meta.validated` stays false).
|
|
28
|
+
* - cache + serviceTier are INFORMATIONAL here (never a hard fail): the cache
|
|
29
|
+
* directive is provider-neutral (a resource HANDLE on gemini, a routing HINT
|
|
30
|
+
* on the prompt_cache_key providers) and serviceTier forwards everywhere.
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.RAW_KNOB_MATRIX_NOTES = exports.RAW_KNOB_SUPPORT = void 0;
|
|
34
|
+
exports.coarsenGrokReasoningEffort = coarsenGrokReasoningEffort;
|
|
35
|
+
exports.rawKnobSupport = rawKnobSupport;
|
|
36
|
+
exports.groundingSupportedProviders = groundingSupportedProviders;
|
|
37
|
+
exports.responseFormatSupportedProviders = responseFormatSupportedProviders;
|
|
38
|
+
exports.renderRawKnobMatrix = renderRawKnobMatrix;
|
|
39
|
+
const provider_1 = require("../types/provider");
|
|
40
|
+
/**
|
|
41
|
+
* The grok reasoning coarsening (R1): xAI's `reasoning_effort` accepts only
|
|
42
|
+
* `"low" | "high"`, so the four-level neutral vocabulary is coarsened —
|
|
43
|
+
* `minimal, low → "low"`; `medium, high → "high"`. This is a DISCLOSED, lossy
|
|
44
|
+
* mapping (it appears in the matrix note, the grok field's doc comment, and the
|
|
45
|
+
* `grok.test.ts` test), never a silent semantic drop. Kept here — beside the
|
|
46
|
+
* matrix that documents it — as the ONE place the algorithm lives (grok.ts
|
|
47
|
+
* imports it).
|
|
48
|
+
*/
|
|
49
|
+
function coarsenGrokReasoningEffort(level) {
|
|
50
|
+
return level === "minimal" || level === "low" ? "low" : "high";
|
|
51
|
+
}
|
|
52
|
+
/** The matrix. Exhaustive over ProviderId — a new provider forces a compile
|
|
53
|
+
* error here (Record<ProviderId, …>), so it can never be silently unlisted. */
|
|
54
|
+
exports.RAW_KNOB_SUPPORT = {
|
|
55
|
+
gemini: {
|
|
56
|
+
grounding: { supported: true, note: "native — Google Search (`googleSearch` tool)" },
|
|
57
|
+
reasoning: { kind: "model-gated", note: "`level` → `thinkingConfig.thinkingLevel`, thinking-capable models only (see `GEMINI_THINKING_CAPABLE_MODELS`)" },
|
|
58
|
+
responseFormat: { supported: true, note: "`responseMimeType: application/json` (mime-shaping only — no schema, `validated` stays false)" },
|
|
59
|
+
cache: { semantics: "handle", note: "`cache.key` = a `cachedContent` resource handle (customer-owned lifecycle)" },
|
|
60
|
+
serviceTier: { supported: true, note: "`flex` / `standard` / `priority` honored" },
|
|
61
|
+
},
|
|
62
|
+
openai: {
|
|
63
|
+
grounding: { supported: false, note: "fail-closed" },
|
|
64
|
+
reasoning: { kind: "forward", note: "`level` → `reasoning_effort` (1:1); a non-reasoning model's rejection is classified teachably" },
|
|
65
|
+
responseFormat: { supported: true, note: "`response_format: { type: json_object }`" },
|
|
66
|
+
cache: { semantics: "hint", note: "`cache.key` → `prompt_cache_key`; `ttlSeconds ≥ 86400` → `prompt_cache_retention: 24h`" },
|
|
67
|
+
serviceTier: { supported: true, note: "`flex` (allowlist) / `priority`; flex→standard is a customer-side degrade (§3.2)" },
|
|
68
|
+
},
|
|
69
|
+
grok: {
|
|
70
|
+
grounding: { supported: false, note: "fail-closed — xAI retired Live Search (HTTP 410, 2026-08-21); native `web_search` needs the Responses API, tracked as CE-9b" },
|
|
71
|
+
reasoning: { kind: "coarsen", note: 'coarsened (disclosed): `minimal,low → "low"`; `medium,high → "high"` → `reasoning_effort`' },
|
|
72
|
+
responseFormat: { supported: true, note: "`response_format: { type: json_object }`" },
|
|
73
|
+
cache: { semantics: "hint", note: "`cache.key` → `prompt_cache_key` (routing hint)" },
|
|
74
|
+
serviceTier: { supported: false, note: "no tiers — always `standard`" },
|
|
75
|
+
},
|
|
76
|
+
deepseek: {
|
|
77
|
+
grounding: { supported: false, note: "fail-closed" },
|
|
78
|
+
reasoning: {
|
|
79
|
+
kind: "fail-closed",
|
|
80
|
+
note: "no effort control — reasoning is model selection (`deepseek-reasoner`)",
|
|
81
|
+
fixHint: "DeepSeek has no reasoning-effort control — select the deepseek-reasoner model instead and remove reasoning",
|
|
82
|
+
},
|
|
83
|
+
responseFormat: { supported: true, note: "`response_format: { type: json_object }` — the prompt must contain the word \"JSON\" (caller's responsibility on the raw lane)" },
|
|
84
|
+
cache: { semantics: "implicit", note: "automatic prefix cache — the key is not used" },
|
|
85
|
+
serviceTier: { supported: false, note: "no tiers — always `standard`" },
|
|
86
|
+
},
|
|
87
|
+
anthropic: {
|
|
88
|
+
grounding: { supported: false, note: "fail-closed" },
|
|
89
|
+
reasoning: {
|
|
90
|
+
kind: "fail-closed",
|
|
91
|
+
note: "extended thinking is not wired on the raw lane (future work)",
|
|
92
|
+
fixHint: "Anthropic extended thinking is not wired on the raw lane in v1 — remove reasoning",
|
|
93
|
+
},
|
|
94
|
+
responseFormat: {
|
|
95
|
+
supported: false,
|
|
96
|
+
note: "fail-closed — no json_object equivalent (structured output is a forced tool call)",
|
|
97
|
+
},
|
|
98
|
+
cache: { semantics: "marker", note: "prefix caching via `cache_control` markers — the key is not used" },
|
|
99
|
+
serviceTier: { supported: false, note: "no tiers — always `standard`" },
|
|
100
|
+
},
|
|
101
|
+
deepinfra: {
|
|
102
|
+
grounding: { supported: false, note: "fail-closed" },
|
|
103
|
+
reasoning: { kind: "forward", note: "`level` → `reasoning_effort` (1:1); a non-reasoning model's rejection is classified teachably" },
|
|
104
|
+
responseFormat: { supported: true, note: "`response_format: { type: json_object }`" },
|
|
105
|
+
cache: { semantics: "hint", note: "`cache.key` → `prompt_cache_key` (routing hint)" },
|
|
106
|
+
serviceTier: { supported: false, note: "no tiers — always `standard`" },
|
|
107
|
+
},
|
|
108
|
+
fireworks: {
|
|
109
|
+
grounding: { supported: false, note: "fail-closed" },
|
|
110
|
+
reasoning: { kind: "forward", note: "`level` → `reasoning_effort` (1:1); a non-reasoning model's rejection is classified teachably" },
|
|
111
|
+
responseFormat: { supported: true, note: "`response_format: { type: json_object }`" },
|
|
112
|
+
cache: { semantics: "hint", note: "`cache.key` → `prompt_cache_key` (routing hint; caching is automatic host-side)" },
|
|
113
|
+
serviceTier: { supported: false, note: "no tiers — always `standard`" },
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
/** Pure lookup into the matrix (spec R6, exported from the package root). A
|
|
117
|
+
* customer's multi-provider dispatcher ASKS this instead of duplicating the
|
|
118
|
+
* provider lists. */
|
|
119
|
+
function rawKnobSupport(provider) {
|
|
120
|
+
return exports.RAW_KNOB_SUPPORT[provider];
|
|
121
|
+
}
|
|
122
|
+
/** Providers that honor a knob, in PROVIDER_IDS order — used by the guard to
|
|
123
|
+
* build a "supported on X, Y only" fixHint from the matrix (so the error text
|
|
124
|
+
* can never drift from the table). */
|
|
125
|
+
function groundingSupportedProviders() {
|
|
126
|
+
return provider_1.PROVIDER_IDS.filter((p) => exports.RAW_KNOB_SUPPORT[p].grounding.supported);
|
|
127
|
+
}
|
|
128
|
+
function responseFormatSupportedProviders() {
|
|
129
|
+
return provider_1.PROVIDER_IDS.filter((p) => exports.RAW_KNOB_SUPPORT[p].responseFormat.supported);
|
|
130
|
+
}
|
|
131
|
+
/** Matrix-level notes rendered below the table (spec §3.2 restated in docs). */
|
|
132
|
+
exports.RAW_KNOB_MATRIX_NOTES = [
|
|
133
|
+
"**Fail-closed is discoverable, not a surprise.** A knob a provider cannot honor throws `RigFailureError` `invariant_violation` PRE-DISPATCH (no meter, no provider call, no telemetry row) — read this table before you call, not after.",
|
|
134
|
+
"**reasoning has NO per-model allowlist outside gemini.** openai/deepinfra/fireworks forward `level` verbatim and let the provider enforce; a rejection surfaces as a classified failure that names the fix. grok coarsens (disclosed above). deepseek reasoning is model selection (`deepseek-reasoner`); anthropic extended thinking is unwired.",
|
|
135
|
+
"**responseFormat is mime-shaping, not schema enforcement.** `json_object` forces syntactic JSON only — the raw lane still never validates or repairs, and `meta.validated` stays `false` (F4).",
|
|
136
|
+
"**§3.2 flex degrade is customer-side.** ModelRig does not replicate the gemini direct-path infra-retry wrapper on the raw lane; under `flex` a capacity rejection surfaces classified (`capacity_shed`) for your own `→ standard` retry ladder — a NAMED difference for your migration record, not a silent one.",
|
|
137
|
+
];
|
|
138
|
+
/** Render the provider × knob matrix as a Markdown table + notes, FROM the
|
|
139
|
+
* matrix (never a hand-written table — R5). Consumed by the docs generator
|
|
140
|
+
* (scripts/build-docs-site.ts) so the published matrix and the runtime guard
|
|
141
|
+
* derive from the same source. */
|
|
142
|
+
function renderRawKnobMatrix() {
|
|
143
|
+
const header = "| Provider | grounding | reasoning | responseFormat | cache | serviceTier |";
|
|
144
|
+
const sep = "|---|---|---|---|---|---|";
|
|
145
|
+
const rows = provider_1.PROVIDER_IDS.map((p) => {
|
|
146
|
+
const s = exports.RAW_KNOB_SUPPORT[p];
|
|
147
|
+
return `| \`${p}\` | ${s.grounding.note} | ${s.reasoning.note} | ${s.responseFormat.note} | ${s.cache.note} | ${s.serviceTier.note} |`;
|
|
148
|
+
});
|
|
149
|
+
return [header, sep, ...rows, "", ...exports.RAW_KNOB_MATRIX_NOTES].join("\n");
|
|
150
|
+
}
|
package/dist/run/raw.d.ts
CHANGED
|
@@ -28,10 +28,18 @@
|
|
|
28
28
|
* Each is ADDITIVE: absent ⇒ byte-identical dispatch. A DECLARED directive is
|
|
29
29
|
* never silently dropped — `grounding`/`reasoning` on a provider that cannot
|
|
30
30
|
* honor it are rejected fail-closed PRE-DISPATCH (`assertRawKnobsSupported`),
|
|
31
|
-
* with no meter, no provider call, and no telemetry row.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* with no meter, no provider call, and no telemetry row. `serviceTier`
|
|
32
|
+
* forwards to every adapter's tier path and `meta.requestedTier` now reports
|
|
33
|
+
* the DECLARED tier (an honesty fix — it previously hardcoded `"standard"`).
|
|
34
|
+
* - CE-9: multi-provider parity. `grounding` now also serves grok (xAI Live
|
|
35
|
+
* Search); `reasoning` generalizes beyond gemini WITHOUT a per-model
|
|
36
|
+
* allowlist — openai/deepinfra/fireworks forward `level` → `reasoning_effort`
|
|
37
|
+
* verbatim (provider enforces, rejection classified teachably), grok coarsens
|
|
38
|
+
* (disclosed), gemini stays model-gated, deepseek/anthropic fail closed; a
|
|
39
|
+
* new `responseFormat: "json_object"` knob mime-shapes on the OpenAI-dialect
|
|
40
|
+
* providers + gemini (anthropic fails closed). The provider×knob support set
|
|
41
|
+
* is ONE table (`run/raw-support.ts`) the guard AND the published docs matrix
|
|
42
|
+
* both read — they can never disagree (R5).
|
|
35
43
|
*/
|
|
36
44
|
import type { AdapterRequest, CandidateRef, ProviderId, ReasoningParams, ServiceTier, ToolChoice, ToolDefinition } from "../types/provider";
|
|
37
45
|
import type { RunResult, RunTags } from "../types/route";
|
|
@@ -95,6 +103,16 @@ export interface RawRunInput {
|
|
|
95
103
|
* pre-dispatch (`assertRawKnobsSupported`); declared on a non-thinking gemini
|
|
96
104
|
* model is rejected classified by the adapter (`geminiReasoningUnsupported`). */
|
|
97
105
|
readonly reasoning?: ReasoningParams;
|
|
106
|
+
/** CE-9 R4 — syntactic-JSON response shaping on the raw lane. `"json_object"`
|
|
107
|
+
* maps to each provider's json_object / json-mime directive (OpenAI-dialect
|
|
108
|
+
* providers + gemini); ABSENT ⇒ byte-identical (no key added). This is
|
|
109
|
+
* MIME-SHAPING, NOT schema enforcement — F4 stands: no validation, no repair,
|
|
110
|
+
* `meta.validated` stays false. GUARDED: anthropic has no equivalent and is
|
|
111
|
+
* rejected fail-closed pre-dispatch (`assertRawKnobsSupported`). DeepSeek's
|
|
112
|
+
* documented wrinkle — its json_object mode 400s when the literal word "JSON"
|
|
113
|
+
* appears nowhere in the prompt — is the CALLER's prompt responsibility on the
|
|
114
|
+
* raw lane (documented in the R5 matrix, never injected here). */
|
|
115
|
+
readonly responseFormat?: "json_object";
|
|
98
116
|
}
|
|
99
117
|
export interface RawRunDeps {
|
|
100
118
|
readonly telemetry: TelemetryStore;
|
|
@@ -104,13 +122,25 @@ export interface RawRunDeps {
|
|
|
104
122
|
readonly unpricedRateUsdPerMTok?: number;
|
|
105
123
|
}
|
|
106
124
|
/**
|
|
107
|
-
* CE-2 fail-closed guard (spec §3 F1/F3). A DECLARED
|
|
108
|
-
* dropped: `grounding`/`
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* is
|
|
125
|
+
* CE-2/CE-9 fail-closed guard (spec §3 F1/F3, CE-9 R1/R2/R4). A DECLARED
|
|
126
|
+
* directive is NEVER silently dropped: a `grounding`/`responseFormat` on a
|
|
127
|
+
* provider that cannot honor it, a `reasoning` on a provider with NO effort
|
|
128
|
+
* control (deepseek/anthropic), or a `grounding.mode` other than the
|
|
129
|
+
* v1-supported `"native"` throws `RigFailureError` `invariant_violation` (the
|
|
130
|
+
* existing TERMINAL class; no new FailureClass member) BEFORE any adapter is
|
|
131
|
+
* built, any provider call is made, or any telemetry row is written.
|
|
132
|
+
*
|
|
133
|
+
* The support facts come from `RAW_KNOB_SUPPORT` (run/raw-support.ts) — the ONE
|
|
134
|
+
* table the published docs matrix also reads, so the guard and the docs can
|
|
135
|
+
* never disagree (R5). What the guard does NOT reject (and why):
|
|
136
|
+
* - reasoning on openai/deepinfra/fireworks is FORWARDED verbatim
|
|
137
|
+
* (`kind: "forward"`) and the provider enforces — a rejection is classified
|
|
138
|
+
* teachably by the adapter (no per-model allowlist, R1).
|
|
139
|
+
* - reasoning on grok is a DISCLOSED coarsening (`kind: "coarsen"`).
|
|
140
|
+
* - reasoning on gemini is model-gated (`kind: "model-gated"`) — the adapter
|
|
141
|
+
* rejects a non-thinking model (`geminiReasoningUnsupported`).
|
|
142
|
+
* Exported so the guard is unit-testable without a network. Idempotent and
|
|
143
|
+
* side-effect-free.
|
|
114
144
|
*/
|
|
115
145
|
export declare function assertRawKnobsSupported(input: RawRunInput): void;
|
|
116
146
|
/** Pure raw-lane request shaping — exported for unit tests (no network). */
|
package/dist/run/raw.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/run/raw.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/run/raw.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAiBH,OAAO,KAAK,EACV,cAAc,EAGd,YAAY,EAGZ,UAAU,EACV,eAAe,EACf,WAAW,EACX,UAAU,EACV,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAW,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,KAAK,EAA+B,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEtF;;;sCAGsC;AACtC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;iFAC6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;6EAGyE;IACzE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC;;;;;;;0BAOsB;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE;;;;;;;iDAO6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IACjD;;;;mFAI+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;qFAIiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC;;;;;;;;sEAQkE;IAClE,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;CACzC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC;;+EAE2E;IAC3E,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AA0CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAiDhE;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,cAAc,CAqC3F;AAsKD;wDACwD;AACxD,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CASrF;AAcD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,eAAe,CA6ClF"}
|
package/dist/run/raw.js
CHANGED
|
@@ -29,10 +29,18 @@
|
|
|
29
29
|
* Each is ADDITIVE: absent ⇒ byte-identical dispatch. A DECLARED directive is
|
|
30
30
|
* never silently dropped — `grounding`/`reasoning` on a provider that cannot
|
|
31
31
|
* honor it are rejected fail-closed PRE-DISPATCH (`assertRawKnobsSupported`),
|
|
32
|
-
* with no meter, no provider call, and no telemetry row.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
* with no meter, no provider call, and no telemetry row. `serviceTier`
|
|
33
|
+
* forwards to every adapter's tier path and `meta.requestedTier` now reports
|
|
34
|
+
* the DECLARED tier (an honesty fix — it previously hardcoded `"standard"`).
|
|
35
|
+
* - CE-9: multi-provider parity. `grounding` now also serves grok (xAI Live
|
|
36
|
+
* Search); `reasoning` generalizes beyond gemini WITHOUT a per-model
|
|
37
|
+
* allowlist — openai/deepinfra/fireworks forward `level` → `reasoning_effort`
|
|
38
|
+
* verbatim (provider enforces, rejection classified teachably), grok coarsens
|
|
39
|
+
* (disclosed), gemini stays model-gated, deepseek/anthropic fail closed; a
|
|
40
|
+
* new `responseFormat: "json_object"` knob mime-shapes on the OpenAI-dialect
|
|
41
|
+
* providers + gemini (anthropic fails closed). The provider×knob support set
|
|
42
|
+
* is ONE table (`run/raw-support.ts`) the guard AND the published docs matrix
|
|
43
|
+
* both read — they can never disagree (R5).
|
|
36
44
|
*/
|
|
37
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
46
|
exports.assertRawKnobsSupported = assertRawKnobsSupported;
|
|
@@ -48,6 +56,7 @@ const openai_1 = require("../adapters/openai");
|
|
|
48
56
|
const openai_compat_1 = require("../adapters/openai-compat");
|
|
49
57
|
const cost_1 = require("./cost");
|
|
50
58
|
const resolve_1 = require("./resolve");
|
|
59
|
+
const raw_support_1 = require("./raw-support");
|
|
51
60
|
const failures_1 = require("../types/failures");
|
|
52
61
|
/** Absent a route timeout, the raw lane uses a generous default — a passthrough
|
|
53
62
|
* should not be shorter-fused than the underlying provider SDK. */
|
|
@@ -86,23 +95,29 @@ function buildRawAdapter(provider, apiKey) {
|
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
}
|
|
89
|
-
/** Providers that can honor a DECLARED raw-lane directive in v1 (spec §3
|
|
90
|
-
* fail-closed matrix). Native grounding and reasoning are both gemini-only
|
|
91
|
-
* today; the other adapters would silently ignore the field — exactly the bug
|
|
92
|
-
* class CE-2 makes impossible. A new-provider entry here is a deliberate,
|
|
93
|
-
* spec-gated widening, never an accident. */
|
|
94
|
-
const NATIVE_GROUNDING_PROVIDERS = new Set(["gemini"]);
|
|
95
|
-
const REASONING_PROVIDERS = new Set(["gemini"]);
|
|
96
98
|
/**
|
|
97
|
-
* CE-2 fail-closed guard (spec §3 F1/F3). A DECLARED
|
|
98
|
-
* dropped: `grounding`/`
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* is
|
|
99
|
+
* CE-2/CE-9 fail-closed guard (spec §3 F1/F3, CE-9 R1/R2/R4). A DECLARED
|
|
100
|
+
* directive is NEVER silently dropped: a `grounding`/`responseFormat` on a
|
|
101
|
+
* provider that cannot honor it, a `reasoning` on a provider with NO effort
|
|
102
|
+
* control (deepseek/anthropic), or a `grounding.mode` other than the
|
|
103
|
+
* v1-supported `"native"` throws `RigFailureError` `invariant_violation` (the
|
|
104
|
+
* existing TERMINAL class; no new FailureClass member) BEFORE any adapter is
|
|
105
|
+
* built, any provider call is made, or any telemetry row is written.
|
|
106
|
+
*
|
|
107
|
+
* The support facts come from `RAW_KNOB_SUPPORT` (run/raw-support.ts) — the ONE
|
|
108
|
+
* table the published docs matrix also reads, so the guard and the docs can
|
|
109
|
+
* never disagree (R5). What the guard does NOT reject (and why):
|
|
110
|
+
* - reasoning on openai/deepinfra/fireworks is FORWARDED verbatim
|
|
111
|
+
* (`kind: "forward"`) and the provider enforces — a rejection is classified
|
|
112
|
+
* teachably by the adapter (no per-model allowlist, R1).
|
|
113
|
+
* - reasoning on grok is a DISCLOSED coarsening (`kind: "coarsen"`).
|
|
114
|
+
* - reasoning on gemini is model-gated (`kind: "model-gated"`) — the adapter
|
|
115
|
+
* rejects a non-thinking model (`geminiReasoningUnsupported`).
|
|
116
|
+
* Exported so the guard is unit-testable without a network. Idempotent and
|
|
117
|
+
* side-effect-free.
|
|
104
118
|
*/
|
|
105
119
|
function assertRawKnobsSupported(input) {
|
|
120
|
+
const support = raw_support_1.RAW_KNOB_SUPPORT[input.provider];
|
|
106
121
|
const groundingMode = input.grounding?.mode;
|
|
107
122
|
if (groundingMode !== undefined) {
|
|
108
123
|
if (groundingMode !== "native") {
|
|
@@ -114,23 +129,35 @@ function assertRawKnobsSupported(input) {
|
|
|
114
129
|
fixHint: 'only { mode: "native" } grounding is supported on the raw lane in v1',
|
|
115
130
|
});
|
|
116
131
|
}
|
|
117
|
-
if (!
|
|
132
|
+
if (!support.grounding.supported) {
|
|
118
133
|
throw new failures_1.RigFailureError({
|
|
119
134
|
class: "invariant_violation",
|
|
120
135
|
message: `native grounding on the raw lane is not supported for provider "${input.provider}"`,
|
|
121
136
|
provider: input.provider,
|
|
122
137
|
model: input.model,
|
|
123
|
-
fixHint:
|
|
138
|
+
fixHint: `native grounding on the raw lane is supported on ${(0, raw_support_1.groundingSupportedProviders)().join(", ")} only; remove grounding or switch provider`,
|
|
124
139
|
});
|
|
125
140
|
}
|
|
126
141
|
}
|
|
127
|
-
if (input.reasoning !== undefined &&
|
|
142
|
+
if (input.reasoning !== undefined && support.reasoning.kind === "fail-closed") {
|
|
128
143
|
throw new failures_1.RigFailureError({
|
|
129
144
|
class: "invariant_violation",
|
|
130
145
|
message: `reasoning control on the raw lane is not supported for provider "${input.provider}"`,
|
|
131
146
|
provider: input.provider,
|
|
132
147
|
model: input.model,
|
|
133
|
-
|
|
148
|
+
// Provider-specific teaching straight from the matrix (deepseek →
|
|
149
|
+
// deepseek-reasoner; anthropic → extended thinking unwired).
|
|
150
|
+
fixHint: support.reasoning.fixHint ??
|
|
151
|
+
"reasoning control is not available for this provider on the raw lane; remove reasoning",
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (input.responseFormat !== undefined && !support.responseFormat.supported) {
|
|
155
|
+
throw new failures_1.RigFailureError({
|
|
156
|
+
class: "invariant_violation",
|
|
157
|
+
message: `responseFormat on the raw lane is not supported for provider "${input.provider}"`,
|
|
158
|
+
provider: input.provider,
|
|
159
|
+
model: input.model,
|
|
160
|
+
fixHint: `responseFormat: "json_object" on the raw lane is supported on ${(0, raw_support_1.responseFormatSupportedProviders)().join(", ")} only; remove responseFormat or switch provider`,
|
|
134
161
|
});
|
|
135
162
|
}
|
|
136
163
|
}
|
|
@@ -163,6 +190,10 @@ function buildRawRequest(candidate, input) {
|
|
|
163
190
|
...(input.grounding?.mode === "native" ? { grounding: true } : {}),
|
|
164
191
|
// CE-2 F3: forward reasoning verbatim; absent ⇒ no key added (byte-identical).
|
|
165
192
|
...(input.reasoning !== undefined ? { reasoning: input.reasoning } : {}),
|
|
193
|
+
// CE-9 R4: forward the json_object directive verbatim; absent ⇒ no key added
|
|
194
|
+
// (byte-identical). An unsupported provider (anthropic) never reaches here —
|
|
195
|
+
// the guard (assertRawKnobsSupported) rejects it pre-dispatch.
|
|
196
|
+
...(input.responseFormat !== undefined ? { responseFormat: input.responseFormat } : {}),
|
|
166
197
|
...(input.tools !== undefined ? { tools: input.tools } : {}),
|
|
167
198
|
...(input.toolChoice !== undefined ? { toolChoice: input.toolChoice } : {}),
|
|
168
199
|
...(input.cache !== undefined ? { cache: input.cache } : {}),
|
|
@@ -193,7 +224,10 @@ function recordRawRow(telemetry, p) {
|
|
|
193
224
|
ttfbMs: p.usage?.ttfbMs ?? null,
|
|
194
225
|
failureClass: p.failureClass,
|
|
195
226
|
attemptsJson: "{}",
|
|
196
|
-
|
|
227
|
+
// Rung tag (R1 review, F1): the raw lane is a single primary dispatch. Raw
|
|
228
|
+
// rows carry `lane: "raw"` and are excluded from route rollups, but every row
|
|
229
|
+
// gets a rung for a uniform contract.
|
|
230
|
+
tagsJson: JSON.stringify({ ...p.tags, rung: "primary" }),
|
|
197
231
|
fingerprintCell: null,
|
|
198
232
|
servedVariant: null,
|
|
199
233
|
repairedBy: null,
|
|
@@ -203,6 +237,10 @@ function recordRawRow(telemetry, p) {
|
|
|
203
237
|
// provenance rule reads any non-null key here as `customer`.
|
|
204
238
|
cacheKey: p.cacheKey ?? null,
|
|
205
239
|
prefixFingerprint: null,
|
|
240
|
+
// Ladder key (spec §2.1 R0): raw lane = one row per call, seq 1, index 0.
|
|
241
|
+
callId: p.callId,
|
|
242
|
+
attemptSeq: 1,
|
|
243
|
+
candidateIndex: 0,
|
|
206
244
|
};
|
|
207
245
|
telemetry.record(row);
|
|
208
246
|
}
|
|
@@ -215,6 +253,9 @@ function recordRawRow(telemetry, p) {
|
|
|
215
253
|
function finalizeRaw(deps, input, result, latencyMs) {
|
|
216
254
|
const unpricedRatePerTok = (deps.unpricedRateUsdPerMTok ?? cost_1.DEFAULT_UNPRICED_RATE_USD_PER_MTOK) / 1000000;
|
|
217
255
|
const rawModelId = `${input.provider}/${input.model}`;
|
|
256
|
+
// One call_id for this raw invocation — shared by the (single) recorded row and
|
|
257
|
+
// the returned meta (spec §2.1 R0).
|
|
258
|
+
const callId = (0, node_crypto_1.randomUUID)();
|
|
218
259
|
// CE-2 F2: the declared tier is reported truthfully on the row AND the meta.
|
|
219
260
|
const requestedTier = input.serviceTier ?? "standard";
|
|
220
261
|
// lane is SDK-owned and cannot be overridden by a caller-supplied tag.
|
|
@@ -239,6 +280,7 @@ function finalizeRaw(deps, input, result, latencyMs) {
|
|
|
239
280
|
failureClass: result.failure.class,
|
|
240
281
|
tags,
|
|
241
282
|
pricingMissing,
|
|
283
|
+
callId,
|
|
242
284
|
...(input.cache !== undefined ? { cacheKey: input.cache.key } : {}),
|
|
243
285
|
});
|
|
244
286
|
throw new failures_1.RigFailureError(result.failure);
|
|
@@ -257,6 +299,7 @@ function finalizeRaw(deps, input, result, latencyMs) {
|
|
|
257
299
|
failureClass: null,
|
|
258
300
|
tags,
|
|
259
301
|
pricingMissing,
|
|
302
|
+
callId,
|
|
260
303
|
...(input.cache !== undefined ? { cacheKey: input.cache.key } : {}),
|
|
261
304
|
});
|
|
262
305
|
const toolCalls = result.toolCalls;
|
|
@@ -278,6 +321,7 @@ function finalizeRaw(deps, input, result, latencyMs) {
|
|
|
278
321
|
attemptsByClass: {},
|
|
279
322
|
servedVariant: null,
|
|
280
323
|
repairedBy: null,
|
|
324
|
+
callId,
|
|
281
325
|
...(isToolTurn ? { toolCalls } : {}),
|
|
282
326
|
};
|
|
283
327
|
return { output: isToolTurn ? null : result.text, meta };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runRaw-only construction — CE-8 (ruling R1,
|
|
3
|
+
* `docs/ModelRig/customer-efficiency/ce8-runraw-only-rig-spec-plan.md`).
|
|
4
|
+
*
|
|
5
|
+
* A Lane-B customer who only calls `rig.runRaw`/`rig.runRawStream` has no routes.
|
|
6
|
+
* With `routesDir: null`, `createRig` SKIPS route loading, the `rig.yaml`
|
|
7
|
+
* manifest, and the serveable-candidate gate — so a stray route file (or a route
|
|
8
|
+
* whose provider key is absent in this deployment) can no longer down a rig that
|
|
9
|
+
* never serves it. The raw lane is unchanged; every route-dependent surface
|
|
10
|
+
* (`run`/`runStream`/`runBundle`/`replay`/`bakeoff`/`verifySwap`) fails with a
|
|
11
|
+
* TERMINAL `invariant_violation` that teaches the fix — Promise surfaces reject,
|
|
12
|
+
* the two streaming surfaces hand back a handle whose `result`/`events` fail
|
|
13
|
+
* (never a synchronous throw, matching the real `runStream` contract).
|
|
14
|
+
*
|
|
15
|
+
* This module holds the small pieces of that opt-out (the empty store, the
|
|
16
|
+
* teaching failure, the throwing route methods) so `index.ts` stays under the
|
|
17
|
+
* 700-LOC cap — `createRig` remains the ONE construction path (a separate
|
|
18
|
+
* `createRawRig()` factory was considered and REJECTED, spec §2 R1).
|
|
19
|
+
*/
|
|
20
|
+
import type { RigConfig } from "../config";
|
|
21
|
+
import { type LoadedRoutes } from "../routes/loader";
|
|
22
|
+
import { RigFailureError } from "../types/failures";
|
|
23
|
+
import type { Rig } from "../index";
|
|
24
|
+
/** The teaching remediation for a route-lane call on a runRaw-only rig (spec §2
|
|
25
|
+
* R1). One constant so the failure and the docs stay in lock-step. */
|
|
26
|
+
export declare const RAW_ONLY_FIX_HINT = "this rig was constructed runRaw-only (routesDir: null); give createRig a routesDir to serve routes";
|
|
27
|
+
/** Build the TERMINAL failure a route-dependent surface throws when the rig was
|
|
28
|
+
* constructed runRaw-only. Reuses `invariant_violation` (already TERMINAL + in
|
|
29
|
+
* the teaching table) — no new FailureClass (spec §3 rationale). */
|
|
30
|
+
export declare function rawOnlyRouteFailure(surface: string): RigFailureError;
|
|
31
|
+
/** Narrow a config's `routesDir` to a string for a route-REQUIRED context (the
|
|
32
|
+
* route-oriented CLI subcommands: bakeoff/watch/swap/init/observe/validate),
|
|
33
|
+
* throwing the teaching failure if the rig was built runRaw-only.
|
|
34
|
+
* `loadConfigFromEnv` always yields a string (R2), so this is unreachable for
|
|
35
|
+
* env-built configs — it guards a hand-built `routesDir: null` reaching a
|
|
36
|
+
* route-only command, and satisfies the `string | null` type at those seams. */
|
|
37
|
+
export declare function requireRoutesDir(config: RigConfig, surface: string): string;
|
|
38
|
+
/** The empty route store for a runRaw-only rig: `list()` is `[]` (so
|
|
39
|
+
* serveability, capture-detection, and the exported route mirror are all no-ops)
|
|
40
|
+
* and `get()` teaches, though no public surface reaches it — every route method
|
|
41
|
+
* is overridden by {@link rawOnlyRouteMethods}. */
|
|
42
|
+
export declare function emptyRouteStore(): LoadedRoutes;
|
|
43
|
+
/** Load routes from a real (string) `routesDir`, mirroring a malformed-bundle
|
|
44
|
+
* diagnosis to the console before re-throwing — the byte-for-byte behaviour the
|
|
45
|
+
* string path had inline in `createRig` before CE-8 extracted it here. */
|
|
46
|
+
export declare function loadRoutesOrReport(config: RigConfig, routesDir: string): LoadedRoutes;
|
|
47
|
+
/** The route-dependent slice of the {@link Rig} surface, replaced wholesale when
|
|
48
|
+
* `routesDir === null` so every one of them throws the teaching failure rather
|
|
49
|
+
* than dereferencing an empty store. Spread LAST over the real methods in
|
|
50
|
+
* `createRig`, so later keys win. */
|
|
51
|
+
type RouteMethods = Pick<Rig, "run" | "runStream" | "runBundle" | "runBundleStream" | "replay" | "bakeoff" | "bakeoffFromEvalCases" | "verifySwap">;
|
|
52
|
+
/** The throwing overrides for a runRaw-only rig (spec §2 R1). Each names the
|
|
53
|
+
* surface + the route/task the caller asked for, so the terminal error points at
|
|
54
|
+
* exactly the call that needs a `routesDir`. Promise-returning surfaces REJECT
|
|
55
|
+
* (matching the routed lane, where errors surface as rejections); the two
|
|
56
|
+
* streaming surfaces return a handle synchronously, so they throw synchronously
|
|
57
|
+
* — the caller never reaches an event to await. */
|
|
58
|
+
export declare function rawOnlyRouteMethods(): RouteMethods;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=rawonly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawonly.d.ts","sourceRoot":"","sources":["../../src/run/rawonly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC;sEACsE;AACtE,eAAO,MAAM,iBAAiB,uGACwE,CAAC;AAEvG;;oEAEoE;AACpE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAMpE;AAsBD;;;;;gFAKgF;AAChF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3E;AAED;;;mDAGmD;AACnD,wBAAgB,eAAe,IAAI,YAAY,CAS9C;AAED;;0EAE0E;AAC1E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CASrF;AAED;;;qCAGqC;AACrC,KAAK,YAAY,GAAG,IAAI,CACtB,GAAG,EACD,KAAK,GACL,WAAW,GACX,WAAW,GACX,iBAAiB,GACjB,QAAQ,GACR,SAAS,GACT,sBAAsB,GACtB,YAAY,CACf,CAAC;AAEF;;;;;mDAKmD;AACnD,wBAAgB,mBAAmB,IAAI,YAAY,CAYlD"}
|