@yanlinglabs/winter-provider-catalog 0.0.1
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/LICENSE +21 -0
- package/NOTICE +59 -0
- package/PROVENANCE.md +598 -0
- package/README.md +46 -0
- package/UPSTREAM.json +10 -0
- package/dist/extract/fetch.d.ts +62 -0
- package/dist/extract/ledgers.d.ts +113 -0
- package/dist/extract/literal-extractor.d.ts +94 -0
- package/dist/extract/merge.d.ts +213 -0
- package/dist/families.d.ts +55 -0
- package/dist/families.js +30 -0
- package/dist/index-t40pzh81.js +94 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +40027 -0
- package/dist/types.d.ts +385 -0
- package/dist/validate.d.ts +98 -0
- package/generated/catalog.json +39282 -0
- package/generated/denominator.json +65 -0
- package/generated/rejections.json +5780 -0
- package/generated/upstream-layer.json +37125 -0
- package/overlay/families.json +600 -0
- package/overlay/models.json +4691 -0
- package/overlay/providers.json +2383 -0
- package/package.json +50 -0
- package/schema/catalog.schema.json +238 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/** The wire dialect an adapter speaks. One adapter family per protocol (WS-13 §5) — never one ported executor per upstream row. */
|
|
2
|
+
export type ProviderProtocol = "openai-responses" | "openai-chat-completions" | "anthropic-messages" | "google-generate-content" | "bedrock-converse" | "azure-openai" | "custom";
|
|
3
|
+
/** How a provider is authenticated. `local-none` is a real, first-class kind — a local endpoint with no key is not a degenerate api-key case (WS-13 §6). */
|
|
4
|
+
export type ProviderAuthKind = "api-key" | "oauth-approved" | "cloud-credential-chain" | "local-none" | "custom";
|
|
5
|
+
/**
|
|
6
|
+
* Where a capability claim came from. Ordered loosely from most to least durable.
|
|
7
|
+
*
|
|
8
|
+
* The last two are WINTER'S OWN, and they exist because the alternative was a false label. The
|
|
9
|
+
* upstream mapper has to stamp `outputModalities` on every row, upstream's `RegistryModel` declares
|
|
10
|
+
* no output modality for ANY model, and the only members available were provider-shaped -- so
|
|
11
|
+
* `["text"]`, which is Winter's inference for a chat registry, shipped as `source: "upstream-static"`
|
|
12
|
+
* with the caveat pushed into a `sourceRef` sentence nothing reads programmatically. A reader
|
|
13
|
+
* filtering for "what upstream said" got a Winter guess (whole-branch review, Lane X r1 carry).
|
|
14
|
+
*
|
|
15
|
+
* `winter-default` — a value WINTER chose in the absence of any upstream or vendor statement. Not
|
|
16
|
+
* a normalization of anything: the field is required and something has to be in it.
|
|
17
|
+
* `local-override` — a value from a LOCAL, non-vendor declaration: an operator's own configuration
|
|
18
|
+
* for a local endpoint, which is neither a vendor document nor a probe of one.
|
|
19
|
+
*
|
|
20
|
+
* Both are strictly less durable than `user-override` (a deliberate human statement about a specific
|
|
21
|
+
* row), so they sort last. Neither may ever carry `confidence: "verified"`; the validator enforces it.
|
|
22
|
+
*/
|
|
23
|
+
export type EvidenceSource = "official-doc" | "live-discovery" | "live-probe" | "upstream-static" | "user-override" | "local-override" | "winter-default";
|
|
24
|
+
/** How much the reader should trust the claim. `unknown` is a legitimate, recordable state — never a reason to omit the evidence wrapper and assert a bare value. */
|
|
25
|
+
export type EvidenceConfidence = "verified" | "declared" | "inferred" | "unknown";
|
|
26
|
+
/** A capability claim with its provenance. `observedAt` is an ISO-8601 instant when present. */
|
|
27
|
+
export interface CapabilityEvidence<T> {
|
|
28
|
+
value: T;
|
|
29
|
+
source: EvidenceSource;
|
|
30
|
+
sourceRef?: string;
|
|
31
|
+
observedAt?: string;
|
|
32
|
+
confidence: EvidenceConfidence;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* WS-13 §8.1's three-state tool capability. `native` becomes agent-eligible only after schema/
|
|
36
|
+
* streaming proof; `emulated` is DISABLED BY DEFAULT for agent modes; `none` fails capability
|
|
37
|
+
* negotiation when the mode requires tools. Silently dropping tools and continuing as plain chat is
|
|
38
|
+
* prohibited — which is why this is three states and not a boolean.
|
|
39
|
+
*
|
|
40
|
+
* Disclosed divergence (derived-shapes-p6.md item (d), OQ-P6-3): the pinned `ModelInfo` has NO
|
|
41
|
+
* tool-capability field at all, so this three-state model is a Winter extension with no pinned
|
|
42
|
+
* counterpart, not a mirror of one.
|
|
43
|
+
*/
|
|
44
|
+
export type ToolCalling = "native" | "emulated" | "none";
|
|
45
|
+
/**
|
|
46
|
+
* A row's promotion state. Every row a lane adds starts `candidate`; promotion to `supported`
|
|
47
|
+
* requires the behavioural corpus (WS-13 §13). `blocked` is the only value the registry refuses to
|
|
48
|
+
* resolve — a `candidate` row is resolvable (that is what makes a lane's own fixtures runnable).
|
|
49
|
+
*/
|
|
50
|
+
export type ModelStatus = "candidate" | "experimental" | "supported" | "deprecated" | "blocked";
|
|
51
|
+
/**
|
|
52
|
+
* WS-13 §8.2, amended 2026-09-02 from the reasoning-continuity report. "Provider" is NOT the
|
|
53
|
+
* capability unit here — the exact endpoint+model is: same-provider does not imply same
|
|
54
|
+
* continuation domain (Anthropic strips thinking across Claude models), so `continuationDomain`
|
|
55
|
+
* lists the models PROVEN to accept this endpoint's native continuation object.
|
|
56
|
+
*/
|
|
57
|
+
export interface ReasoningCapabilities {
|
|
58
|
+
supported: CapabilityEvidence<boolean>;
|
|
59
|
+
/** The model's own effort vocabulary, verbatim. Vocabularies are NOT interchangeable across providers (WS-13 §8.2). */
|
|
60
|
+
efforts: string[];
|
|
61
|
+
defaultEffort?: string;
|
|
62
|
+
continuation: "none" | "plaintext" | "opaque-provider-state" | "server-response-handle";
|
|
63
|
+
readableState?: CapabilityEvidence<"none" | "summary" | "full-exposed">;
|
|
64
|
+
/** e.g. Anthropic `display: "summarized"`, OpenAI `reasoning.summary`, Gemini `includeThoughts`. */
|
|
65
|
+
summaryRequest?: CapabilityEvidence<{
|
|
66
|
+
field: string;
|
|
67
|
+
values: string[];
|
|
68
|
+
}>;
|
|
69
|
+
replayScope?: CapabilityEvidence<"current-tool-loop" | "current-turn" | "selected-turns" | "all-turns">;
|
|
70
|
+
continuationDomain?: CapabilityEvidence<string[]>;
|
|
71
|
+
/** The stream/final event from which the COMPLETE replay object must be captured — never an earlier partial copy. */
|
|
72
|
+
completionEvent?: CapabilityEvidence<string>;
|
|
73
|
+
/** What missing reasoning state costs mid-tool-loop (DeepSeek with tools: a 400). */
|
|
74
|
+
toolLoopRequirement?: CapabilityEvidence<"hard-error" | "silent-degradation" | "not-required">;
|
|
75
|
+
}
|
|
76
|
+
/** List prices, USD per million tokens. R6-H: the ONLY price source Winter has — an unpriced model reports `0` / `costBasis: "unknown"`, never an invented number. */
|
|
77
|
+
export interface ModelPricing {
|
|
78
|
+
inputPerMTokUsd: number;
|
|
79
|
+
outputPerMTokUsd: number;
|
|
80
|
+
cacheReadPerMTokUsd?: number;
|
|
81
|
+
cacheWritePerMTokUsd?: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* WS-13c §2: where a slot's ranking and its description came from.
|
|
85
|
+
*
|
|
86
|
+
* `user-ruling` carries the user's own framing verbatim (or a faithful one-sentence condensation
|
|
87
|
+
* that keeps the user's key phrase); `vendor-doc` cites the vendor's model page; `winter-curated` is
|
|
88
|
+
* Winter's own editorial judgement and enters `candidate` until the user reviews it (§9).
|
|
89
|
+
*/
|
|
90
|
+
export type SlotBasis = "user-ruling" | "vendor-doc" | "winter-curated";
|
|
91
|
+
/** A slot's promotion state, mirroring `ModelStatus`'s two reviewed values (WS-13c §2/§9). */
|
|
92
|
+
export type SlotStatus = "candidate" | "supported";
|
|
93
|
+
/**
|
|
94
|
+
* One ranked option in a family's lineup (WS-13c §2).
|
|
95
|
+
*
|
|
96
|
+
* POSITION IN THE ARRAY IS THE OPTION ORDER, NOT A STRENGTH CLAIM (D26): the Gemini case is the
|
|
97
|
+
* whole reason the two text fields are required and separate — 3.8 Flash is documented as the
|
|
98
|
+
* strongest while 3.1 Pro still leads the list on breadth. `description` says what it is good for
|
|
99
|
+
* and `reason` says why it holds this position; neither may carry a currency amount, because pricing
|
|
100
|
+
* lives on model rows with its own evidence wrapper and a price copied into prose is a price nobody
|
|
101
|
+
* can audit or update.
|
|
102
|
+
*/
|
|
103
|
+
export interface FamilySlot {
|
|
104
|
+
/** The facing enum token people know (`astra`, `flash`, `grok-4.6`). Matches `^[a-z0-9][a-z0-9.-]{0,31}$`; never a version number alone. */
|
|
105
|
+
name: string;
|
|
106
|
+
/** Resolves to at least one model row's `canonicalModelId` — the integrity suite refuses a slot on a missing row, so no id is invented into `generated/`. */
|
|
107
|
+
canonicalModelId: string;
|
|
108
|
+
/** Pins a serving provider id (WS-13c §4 step 4). Optional; it must survive the credential/enablement filter or the slot is unservable. */
|
|
109
|
+
provider?: string;
|
|
110
|
+
/** What this option is for. No currency amounts. */
|
|
111
|
+
description: string;
|
|
112
|
+
/** Why it holds this position in the lineup. */
|
|
113
|
+
reason: string;
|
|
114
|
+
basis: SlotBasis;
|
|
115
|
+
citation: string;
|
|
116
|
+
status: SlotStatus;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A vendor lineup, independent of the provider that serves it (WS-13c §1).
|
|
120
|
+
*
|
|
121
|
+
* `matchers` are anchored RegExp SOURCES evaluated over `canonicalModelId`, first match wins. They
|
|
122
|
+
* are authored DISJOINT (`^gpt-(?!oss)` beside `^gpt-oss-`) so the pipeline's sort-by-id can never
|
|
123
|
+
* change a row's stamp; `catalog-integrity.test.ts` asserts that order independence over the real
|
|
124
|
+
* catalog rather than trusting the authoring.
|
|
125
|
+
*
|
|
126
|
+
* `vendorProviders` is ORDERED and is step 3-i of slot resolution: the vendor's own rows first, a
|
|
127
|
+
* configured SUBSCRIPTION row before a token row of the same vendor.
|
|
128
|
+
*/
|
|
129
|
+
export interface ModelFamilyDescriptor {
|
|
130
|
+
/** `^[a-z0-9][a-z0-9-]{0,31}$`. `other` is the reserved id for a row no matcher claims. */
|
|
131
|
+
id: string;
|
|
132
|
+
displayName: string;
|
|
133
|
+
vendor: string;
|
|
134
|
+
/** Ordered provider ids, subscription row before token row of the same vendor (WS-13c §4 step 3-i). */
|
|
135
|
+
vendorProviders: string[];
|
|
136
|
+
/** Anchored RegExp sources over `canonicalModelId`; first match wins. Authored disjoint. */
|
|
137
|
+
matchers: Array<{
|
|
138
|
+
pattern: string;
|
|
139
|
+
note: string;
|
|
140
|
+
}>;
|
|
141
|
+
/** 0..4, unique names. A family with zero slots is legal — it is listed under "more options" only. */
|
|
142
|
+
slots: FamilySlot[];
|
|
143
|
+
status: "candidate" | "supported";
|
|
144
|
+
citation: string;
|
|
145
|
+
}
|
|
146
|
+
export interface WinterModelDescriptor {
|
|
147
|
+
/** The stable Winter key, `<providerId>/<model>` (WS-13 §8.3). Globally unique across the catalog. */
|
|
148
|
+
key: string;
|
|
149
|
+
providerId: string;
|
|
150
|
+
/** The provider-local id sent on the wire. Unique within a provider, and never assumed unique across providers. */
|
|
151
|
+
upstreamId: string;
|
|
152
|
+
/**
|
|
153
|
+
* WS-13c §1: the family id this row's model belongs to, or `"other"` when no matcher claims it.
|
|
154
|
+
*
|
|
155
|
+
* DERIVED AT BUILD by `stampFamilyFields`; an overlay row MAY set it as an override, and the
|
|
156
|
+
* stamper never overwrites a value that is already there. Never `WinterProviderDescriptor.family`,
|
|
157
|
+
* which is the ADAPTER family and keeps its own meaning (R13c-1).
|
|
158
|
+
*/
|
|
159
|
+
modelFamily: string;
|
|
160
|
+
/**
|
|
161
|
+
* WS-13c §1: the vendor's model identity with the provider's spelling removed, so
|
|
162
|
+
* `deepseek/deepseek-v4-pro`, `vertex/DeepSeek-V4-Pro` and `qwen-cloud/deepseek-v4-pro` are ONE
|
|
163
|
+
* canonical model.
|
|
164
|
+
*
|
|
165
|
+
* DERIVED AT BUILD by `stampFamilyFields` (via `canonicalModelIdOf`); an overlay row MAY set it as
|
|
166
|
+
* an override, which is how `kimi-coding/k3` — whose coding-plan id is just `k3` — reaches the
|
|
167
|
+
* same canonical model as `moonshot/kimi-k3`.
|
|
168
|
+
*/
|
|
169
|
+
canonicalModelId: string;
|
|
170
|
+
displayName: string;
|
|
171
|
+
aliases: string[];
|
|
172
|
+
endpoints: Array<"chat" | "responses" | "embeddings" | "image" | "audio" | "video">;
|
|
173
|
+
contextWindow?: CapabilityEvidence<number>;
|
|
174
|
+
maxInputTokens?: CapabilityEvidence<number>;
|
|
175
|
+
maxOutputTokens?: CapabilityEvidence<number>;
|
|
176
|
+
inputModalities: CapabilityEvidence<string[]>;
|
|
177
|
+
outputModalities: CapabilityEvidence<string[]>;
|
|
178
|
+
toolCalling: CapabilityEvidence<ToolCalling>;
|
|
179
|
+
nativeTools: CapabilityEvidence<boolean>;
|
|
180
|
+
parallelTools?: CapabilityEvidence<boolean>;
|
|
181
|
+
structuredOutput?: CapabilityEvidence<boolean>;
|
|
182
|
+
promptCaching?: CapabilityEvidence<boolean>;
|
|
183
|
+
reasoning?: ReasoningCapabilities;
|
|
184
|
+
pricing?: CapabilityEvidence<ModelPricing>;
|
|
185
|
+
/** R6-14: set only after the safety corpus passes live. A worker with no configured classifier route serves only when this is true AND `structuredOutput.confidence === "verified"`. */
|
|
186
|
+
classifierEligible?: CapabilityEvidence<boolean>;
|
|
187
|
+
/** Request parameters this model rejects. Adapters must not send them (WS-13 §8.2: reject the selection BEFORE sending). */
|
|
188
|
+
unsupportedParameters: string[];
|
|
189
|
+
status: ModelStatus;
|
|
190
|
+
}
|
|
191
|
+
export interface WinterProviderDescriptor {
|
|
192
|
+
id: string;
|
|
193
|
+
displayName: string;
|
|
194
|
+
protocols: ProviderProtocol[];
|
|
195
|
+
authKinds: ProviderAuthKind[];
|
|
196
|
+
/** Generated endpoints are IMMUTABLE (R6-11): a user override rides `ConnectionProfile.baseUrl` and goes through the endpoint policy instead. */
|
|
197
|
+
defaultEndpoints: Record<string, string>;
|
|
198
|
+
modelDiscovery: "none" | "openai-models" | "provider-native" | "local";
|
|
199
|
+
/**
|
|
200
|
+
* Whether the live catalog is the last word on which models exist. `authoritative` means an id
|
|
201
|
+
* absent from live discovery does not exist; anything else means the compiled seed may still be
|
|
202
|
+
* right — and, per R6-F, is the precondition for an `allowUnlisted` connection passing an
|
|
203
|
+
* unlisted id straight through.
|
|
204
|
+
*/
|
|
205
|
+
liveCatalogAuthority: "authoritative" | "partial" | "unknown";
|
|
206
|
+
adapterId: string;
|
|
207
|
+
/** The adapter FAMILY this provider's wire mapping belongs to; mirrors `ProviderFamily` in provider-runtime (kept a bare string here so the data package stays free of the runtime's unions). */
|
|
208
|
+
family: string;
|
|
209
|
+
/** `project: "winter"` marks a Winter-owned provider (codex-oauth per D11, and every local id) that no upstream extraction produced. */
|
|
210
|
+
upstream: {
|
|
211
|
+
project: "OmniRoute" | "winter";
|
|
212
|
+
commit: string;
|
|
213
|
+
sourcePaths: string[];
|
|
214
|
+
};
|
|
215
|
+
risk: {
|
|
216
|
+
class: "approved" | "review-required" | "blocked";
|
|
217
|
+
reasons: string[];
|
|
218
|
+
};
|
|
219
|
+
/** WS-13 §4: only `llm` rows feed the Agent SDK's model selection; the other scopes feed separate subsystems and must never reach the worker-model picker. */
|
|
220
|
+
scope: "llm" | "stt" | "tts" | "embedding" | "image" | "video" | "search";
|
|
221
|
+
/**
|
|
222
|
+
* WS-13b §1: how the vendor charges for the credential Winter actually uses.
|
|
223
|
+
*
|
|
224
|
+
* DATA, not a derived guess, and it is the whole reason the field exists: R6-H prices a turn from
|
|
225
|
+
* the model row's `pricing` evidence, and a subscription-priced backend (the ChatGPT Codex
|
|
226
|
+
* entitlement, a "coding plan") has list prices published for its API twin that do NOT describe
|
|
227
|
+
* what this credential is billed. `subscription`/`free` rows never feed `total_cost_usd`/
|
|
228
|
+
* `modelUsage` — a per-token number for a seat is not a smaller error than no number, it is a
|
|
229
|
+
* wrong one that reads as authoritative.
|
|
230
|
+
*/
|
|
231
|
+
pricingBasis: "token" | "subscription" | "free";
|
|
232
|
+
/**
|
|
233
|
+
* WS-13b §1 (D21): the documented third-party path this row ships through, and the citation that
|
|
234
|
+
* admits it.
|
|
235
|
+
*
|
|
236
|
+
* R6b-3 makes the citation load-bearing rather than decorative: `validateCatalog` refuses a row
|
|
237
|
+
* whose `citation` is absent or empty (`admission-missing`), and refuses one that cites the
|
|
238
|
+
* audit's own `unknown` evidence class (`admission-unknown`) — "the decisive document was not
|
|
239
|
+
* found" is a disposition to EXCLUDE, so a row may not ship carrying it.
|
|
240
|
+
*
|
|
241
|
+
* `citation` forms, in order of strength: a URL to the vendor document; `audit:<section>` for the
|
|
242
|
+
* third-party-access audit's evidence table; `spec:<section>` for a Winter spec ruling that admits
|
|
243
|
+
* a class of rows (WS-13 §1's disposition table admits the reviewed api-key/cloud allowlist rows);
|
|
244
|
+
* `local` for a `local-none` row, whose "vendor" is the operator's own machine.
|
|
245
|
+
*/
|
|
246
|
+
admission: {
|
|
247
|
+
basis: "api-key" | "oauth-documented" | "keyless-documented" | "local" | "cloud-credential";
|
|
248
|
+
citation: string;
|
|
249
|
+
tier: AdmissionTier;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* WS-13b §2/§7/§8.4 (fix-wave ruling R-FW-2): the SECOND identity field this vendor names, if it
|
|
253
|
+
* names one.
|
|
254
|
+
*
|
|
255
|
+
* Winter's `User-Agent` is unconditional and lives in code (`identity.ts`). This is the per-row
|
|
256
|
+
* half: AI Horde documents a `Client-Agent: <name>:<version>:<contact>` field, and the spec's own
|
|
257
|
+
* words are "a truthful `Client-Agent`" — an obligation that fell between the row author (who
|
|
258
|
+
* cited the header) and the adapter owner (whose lane was the live gate), and shipped as prose on
|
|
259
|
+
* neither side. Making it DATA on the row is what stops that: the row that documents the header is
|
|
260
|
+
* the row that carries it, and one seam applies every row's.
|
|
261
|
+
*
|
|
262
|
+
* WHAT MAY BE HERE, enforced by `validateCatalog` rather than by review:
|
|
263
|
+
* - the NAME must be one of a Winter-authored allowlist (`Client-Agent` today). A row may not
|
|
264
|
+
* invent a header name, and it may certainly not name a vendor's product-identity field —
|
|
265
|
+
* that is the exact thing WS-13 §5 and D21 forbid, and a free-text name field would be a hole
|
|
266
|
+
* straight through both.
|
|
267
|
+
* - the VALUE must begin with the `<product>` PLACEHOLDER. The running product names ITSELF in
|
|
268
|
+
* every identity field; a value naming an editor, a CLI or a first-party product is not a
|
|
269
|
+
* configuration mistake to fix later, it is impersonation. The literal Winter package name was
|
|
270
|
+
* accepted here until the P7a fix wave, for "rows written before the profile existed" — no row
|
|
271
|
+
* was ever written that way, and a hard-coded product token is precisely what this rule calls
|
|
272
|
+
* impersonation when somebody else does it.
|
|
273
|
+
* - THREE PLACEHOLDERS are substituted by the adapter at request time (provider-runtime's
|
|
274
|
+
* `renderIdentityHeaders`): `<version>` with this build's own version, so a release cannot
|
|
275
|
+
* leave a stale number on the wire; `<product>` (P7a, D19) with the running brand's
|
|
276
|
+
* `packageName`, so a REUSER's identity header names the reuser rather than Winter; and
|
|
277
|
+
* `<contact>` (P7a fix wave) with `brand.contactUrl`. The contact is the half of the
|
|
278
|
+
* `<name>:<version>:<contact>` triple a vendor actually acts on, so a row hard-coding a
|
|
279
|
+
* repository URL sends every reuser's traffic to whoever owns that repository — the same
|
|
280
|
+
* untruth as the product token, and less visible, because the row still LOOKS rebranded.
|
|
281
|
+
*
|
|
282
|
+
* NOT routed through `applyPrivilegedHeaders`. This is Winter's own identity, the same class as
|
|
283
|
+
* the `User-Agent` beside it — it discloses nothing about the operator, and gating it on a
|
|
284
|
+
* generated endpoint would silently drop it for every multi-provider row, whose reviewed endpoint
|
|
285
|
+
* is COPIED into the connection profile and therefore evaluated as a user endpoint (seam 1c).
|
|
286
|
+
* `aihorde` is exactly such a row, so a privileged reading would have delivered the header in a
|
|
287
|
+
* fixture and never in production.
|
|
288
|
+
*/
|
|
289
|
+
identityHeaders?: Record<string, string>;
|
|
290
|
+
/**
|
|
291
|
+
* P7a carry (Lane D): a PER-TENANT provider whose API endpoint is the customer's own resource, so
|
|
292
|
+
* the row ships with NO usable `defaultEndpoints.api` at all (`azure-ai`, `oci`).
|
|
293
|
+
*
|
|
294
|
+
* `true` is the only value: absence means "the row's endpoint is usable as shipped", and a `false`
|
|
295
|
+
* would be a claim no row needs to make. A session selecting such a row without supplying an
|
|
296
|
+
* endpoint is a typed `endpoint-required` refusal — never a request sent to a placeholder host.
|
|
297
|
+
*
|
|
298
|
+
* DECLARED AT P7a'S SPINE, RULED ON BY LANE D: the validator ACCEPTS this field (shape only) so
|
|
299
|
+
* both halves can land independently; the rules that bind it to `defaultEndpoints`, and the rows
|
|
300
|
+
* that set it, are Lane D's.
|
|
301
|
+
*/
|
|
302
|
+
requiresUserEndpoint?: true;
|
|
303
|
+
/**
|
|
304
|
+
* DOCUMENTATION ONLY, never sent: the shape a user's own endpoint takes for a
|
|
305
|
+
* `requiresUserEndpoint` row, e.g. `"https://<resource>.services.ai.azure.com/models"`.
|
|
306
|
+
*
|
|
307
|
+
* It exists so a host can TELL the user what to paste. Nothing resolves it, nothing substitutes
|
|
308
|
+
* into it, and no request is ever built from it — a template that reached the wire would be a
|
|
309
|
+
* request to a literal `<resource>` host.
|
|
310
|
+
*/
|
|
311
|
+
endpointTemplate?: string;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* WS-13b §1 (fix-wave ruling R-FW-3): HOW GOOD the evidence behind `admission.citation` is, as DATA.
|
|
315
|
+
*
|
|
316
|
+
* The tiers were prose before this — a marker inside the citation STRING, explained in PROVENANCE.md
|
|
317
|
+
* — and the one test that claimed to keep the fifteen reviewed rows out of the weakest tier could
|
|
318
|
+
* not: it matched `^https?:\/\/`, which a pinned-upstream citation also satisfies. Nothing in the
|
|
319
|
+
* validator, the live gate or the promotion path could key on a substring, so the label drifted from
|
|
320
|
+
* the rows it described (`minimax` sat in the weak tier while its own sibling cited a fetched
|
|
321
|
+
* MiniMax document naming the same base URL).
|
|
322
|
+
*
|
|
323
|
+
* `fetched-document` a page this repository's lane FETCHED and READ, quoted in the citation with
|
|
324
|
+
* the date it was retrieved. The strongest tier and the only one a `supported`
|
|
325
|
+
* model may sit on.
|
|
326
|
+
* `pinned-upstream` the vendor's own site as OmniRoute's product catalog records it at the pin,
|
|
327
|
+
* plus the pinned `RegistryEntry` (auth type, dialect, base URL). An admission
|
|
328
|
+
* of the PATH and a placeholder for the DOCUMENT: honest, consequential
|
|
329
|
+
* (`review-required`, models `candidate`), and never a claimed review that did
|
|
330
|
+
* not happen.
|
|
331
|
+
* `spec-ruling` a Winter spec ruling admits the row as a class (WS-13b §0 D20).
|
|
332
|
+
* `audit` the third-party-access audit's own evidence table.
|
|
333
|
+
* `local` the "vendor" is the operator's own machine.
|
|
334
|
+
*
|
|
335
|
+
* PROMOTION IS TWO-KEY (ruling (b)): a live-gate pass AND a fetched vendor document, with the
|
|
336
|
+
* citation upgraded in the same reviewed commit. `catalog-integrity.test.ts` asserts the half a test
|
|
337
|
+
* can hold — no `approved` row and no `supported` model on `pinned-upstream` — and the live gate's
|
|
338
|
+
* report row prints the tier so a promotion cannot be made from a pinned row by habit.
|
|
339
|
+
*/
|
|
340
|
+
export type AdmissionTier = "fetched-document" | "pinned-upstream" | "spec-ruling" | "local" | "audit";
|
|
341
|
+
export interface WinterCatalog {
|
|
342
|
+
/** 2 since WS-13c: every model row carries `modelFamily`/`canonicalModelId` and the document carries `families`. */
|
|
343
|
+
schemaVersion: 2;
|
|
344
|
+
catalogVersion: string;
|
|
345
|
+
/** The upstream pin the generated layer came from. All-empty on the hand-authored SEED (`catalogVersion: "0.0.0-seed"`) — that emptiness is what says "not extracted". */
|
|
346
|
+
upstream: {
|
|
347
|
+
tag: string;
|
|
348
|
+
tagObject: string;
|
|
349
|
+
commit: string;
|
|
350
|
+
extractorVersion: string;
|
|
351
|
+
overlayVersion: string;
|
|
352
|
+
};
|
|
353
|
+
providers: WinterProviderDescriptor[];
|
|
354
|
+
models: WinterModelDescriptor[];
|
|
355
|
+
/** WS-13c §1: the vendor lineups, generated from `overlay/families.json` and sorted by `id`. May be empty (a layer validated standalone has no families). */
|
|
356
|
+
families: ModelFamilyDescriptor[];
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* One validation failure.
|
|
360
|
+
*
|
|
361
|
+
* `message` is the whole human sentence, `path`-prefixed — byte-identical to the strings this
|
|
362
|
+
* result used to be an array of, so every existing consumer (`loadCatalog`'s throw, the two
|
|
363
|
+
* scripts' stderr, the tests' `includes` helper) reads the same text it always did.
|
|
364
|
+
*
|
|
365
|
+
* `code` is P6.5's addition and the reason the shape changed at all: R6b-3 is a rule a GATE has to
|
|
366
|
+
* key on ("a row without an admission citation fails validation"), and keying a gate on prose is
|
|
367
|
+
* how a reworded message silently disarms it. Codes are opt-in — every pre-existing check reports
|
|
368
|
+
* the generic `invalid`, and only the rules something else keys on carry a specific one. Widening
|
|
369
|
+
* that is a later, deliberate edit, not a prerequisite for this one.
|
|
370
|
+
*/
|
|
371
|
+
export interface CatalogValidationError {
|
|
372
|
+
code: string;
|
|
373
|
+
/** JSON-pointer-ish location of the offending value, e.g. `providers[3].admission.citation`. */
|
|
374
|
+
path: string;
|
|
375
|
+
/** `${path}: ${reason}` — the complete sentence. */
|
|
376
|
+
message: string;
|
|
377
|
+
}
|
|
378
|
+
/** The result of `validateCatalog`. A failure carries EVERY error found, not just the first — a generator run wants the whole list. */
|
|
379
|
+
export type CatalogValidationResult = {
|
|
380
|
+
ok: true;
|
|
381
|
+
catalog: WinterCatalog;
|
|
382
|
+
} | {
|
|
383
|
+
ok: false;
|
|
384
|
+
errors: CatalogValidationError[];
|
|
385
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { CatalogValidationResult, EvidenceConfidence, EvidenceSource, ModelStatus, ProviderAuthKind, ProviderProtocol, SlotBasis, SlotStatus, ToolCalling, WinterCatalog, WinterModelDescriptor, WinterProviderDescriptor } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The header NAMES a reviewed row may put in `identityHeaders` (fix-wave R-FW-2).
|
|
4
|
+
*
|
|
5
|
+
* ONE ENTRY, and widening it is a deliberate edit with a vendor document behind it. `Client-Agent`
|
|
6
|
+
* is AI Horde's documented `<name>:<version>:<contact>` client-identity field. A row that needs a
|
|
7
|
+
* different second identity field adds its name here, in review, beside the document that names it —
|
|
8
|
+
* which is the whole difference between a Winter-authored identity and an imported one.
|
|
9
|
+
*/
|
|
10
|
+
export declare const WINTER_IDENTITY_HEADER_NAMES: readonly string[];
|
|
11
|
+
/**
|
|
12
|
+
* The THREE tokens an `identityHeaders` VALUE may carry, substituted by the adapter at request time
|
|
13
|
+
* (provider-runtime's `renderIdentityHeaders`).
|
|
14
|
+
*
|
|
15
|
+
* `<version>` predates P7a. `<product>` is D19's: the product token is `brand.packageName`, so a row
|
|
16
|
+
* that hard-codes Winter's own name is honest for Winter and a LIE for a reuser — it would put
|
|
17
|
+
* Winter's identity on a request the reuser's product made. `<contact>` is the P7a fix wave's (item
|
|
18
|
+
* 7, Lane A review M-4): a vendor identity field is a `<name>:<version>:<contact>` triple and the
|
|
19
|
+
* contact is the half a vendor ACTS on, so a row hard-coding Winter's repository URL points every
|
|
20
|
+
* reuser's traffic at Winter's issue tracker — the same untruth as the product token, and less
|
|
21
|
+
* visible, because the row still LOOKS rebranded once `<product>` has moved.
|
|
22
|
+
*
|
|
23
|
+
* A ROW MUST NOW START WITH `<product>`; the literal Winter package name is no longer accepted (P7a
|
|
24
|
+
* fix wave, item 8's enabler). It was a back-compat spelling for "rows written before the profile
|
|
25
|
+
* existed", and there are none — the one shipped row uses the placeholder. Keeping it would mean
|
|
26
|
+
* a validator that calls a hard-coded product token impersonation in its own error message while
|
|
27
|
+
* accepting exactly that, and it was the last raw brand literal in the four source trees.
|
|
28
|
+
*/
|
|
29
|
+
export declare const IDENTITY_PRODUCT_PLACEHOLDER = "<product>";
|
|
30
|
+
export declare const IDENTITY_VERSION_PLACEHOLDER = "<version>";
|
|
31
|
+
export declare const IDENTITY_CONTACT_PLACEHOLDER = "<contact>";
|
|
32
|
+
/**
|
|
33
|
+
* The closed vocabularies, exported as ONE object so the JSON Schema can be checked against the
|
|
34
|
+
* validator rather than the two drifting apart in silence.
|
|
35
|
+
*
|
|
36
|
+
* The schema is the cross-language contract (Lane X's generator, the Swift decoder) and nothing in
|
|
37
|
+
* this repo executes it — no ajv in the fence — so without a parity test its `enum` arrays are
|
|
38
|
+
* prose. A validator that rejects a value the schema permits (or the reverse) is a row that passes
|
|
39
|
+
* one gate and fails the other, discovered by whoever is furthest from the change.
|
|
40
|
+
*/
|
|
41
|
+
export declare const CATALOG_VOCABULARIES: {
|
|
42
|
+
readonly protocols: readonly ProviderProtocol[];
|
|
43
|
+
readonly authKinds: readonly ProviderAuthKind[];
|
|
44
|
+
readonly evidenceSources: readonly EvidenceSource[];
|
|
45
|
+
readonly evidenceConfidences: readonly EvidenceConfidence[];
|
|
46
|
+
readonly toolCalling: readonly ToolCalling[];
|
|
47
|
+
readonly modelStatuses: readonly ModelStatus[];
|
|
48
|
+
readonly modelEndpoints: readonly ["chat", "responses", "embeddings", "image", "audio", "video"];
|
|
49
|
+
readonly modelDiscovery: readonly ["none", "openai-models", "provider-native", "local"];
|
|
50
|
+
readonly catalogAuthority: readonly ["authoritative", "partial", "unknown"];
|
|
51
|
+
readonly riskClasses: readonly ["approved", "review-required", "blocked"];
|
|
52
|
+
readonly providerScopes: readonly ["llm", "stt", "tts", "embedding", "image", "video", "search"];
|
|
53
|
+
readonly upstreamProjects: readonly ["OmniRoute", "winter"];
|
|
54
|
+
readonly pricingBases: readonly ["token", "subscription", "free"];
|
|
55
|
+
readonly admissionBases: readonly ["api-key", "oauth-documented", "keyless-documented", "local", "cloud-credential"];
|
|
56
|
+
readonly admissionTiers: readonly ["fetched-document", "pinned-upstream", "spec-ruling", "local", "audit"];
|
|
57
|
+
readonly slotBases: readonly SlotBasis[];
|
|
58
|
+
readonly slotStatuses: readonly SlotStatus[];
|
|
59
|
+
readonly familyStatuses: readonly ("candidate" | "supported")[];
|
|
60
|
+
readonly identityHeaderNames: readonly string[];
|
|
61
|
+
readonly continuations: readonly ["none", "plaintext", "opaque-provider-state", "server-response-handle"];
|
|
62
|
+
readonly readableStates: readonly ["none", "summary", "full-exposed"];
|
|
63
|
+
readonly replayScopes: readonly ["current-tool-loop", "current-turn", "selected-turns", "all-turns"];
|
|
64
|
+
readonly toolLoopRequirements: readonly ["hard-error", "silent-degradation", "not-required"];
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Recursively scans any JSON value for credential material. Exported because Lane X's generator
|
|
68
|
+
* runs it over the RAW extraction before a row ever reaches a descriptor, and the catalog's own
|
|
69
|
+
* test runs it over the committed file — one implementation, two call sites, no drift.
|
|
70
|
+
*
|
|
71
|
+
* Depth- and breadth-bounded and cycle-safe: a hostile or malformed input can make it return
|
|
72
|
+
* findings, never hang or overflow the stack.
|
|
73
|
+
*/
|
|
74
|
+
export declare function scanForSecrets(value: unknown, path?: string, seen?: Set<object>, depth?: number): string[];
|
|
75
|
+
/**
|
|
76
|
+
* A citation that names the audit's `unknown` evidence class rather than a document.
|
|
77
|
+
*
|
|
78
|
+
* Anchored, and case-insensitive on the class name only: `audit:unknown`, `audit:unknown-pending`,
|
|
79
|
+
* or the bare word. It deliberately does NOT match a URL that merely contains "unknown" somewhere in
|
|
80
|
+
* its path — the rule is about a row that admits it has no decisive document, not about spelling.
|
|
81
|
+
*/
|
|
82
|
+
export declare const UNKNOWN_CITATION_RE: RegExp;
|
|
83
|
+
/**
|
|
84
|
+
* Validates any JSON value as a `WinterCatalog`. Never throws.
|
|
85
|
+
*
|
|
86
|
+
* Beyond per-field shape and closed-vocabulary checks it enforces the four structural invariants
|
|
87
|
+
* WS-13 §13's acceptance list names, plus the secrets floor:
|
|
88
|
+
*
|
|
89
|
+
* - provider `id` unique across the catalog;
|
|
90
|
+
* - model `key` unique across the catalog (this is the registry's primary index);
|
|
91
|
+
* - within ONE provider, `upstreamId ∪ aliases` is collision-free — alias scope is per-provider by
|
|
92
|
+
* design (two providers may both serve a model called `sonnet`), and an alias colliding with a
|
|
93
|
+
* sibling's real id would make resolution order load-bearing;
|
|
94
|
+
* - every model's `providerId` names a provider that exists (an orphan row is unresolvable);
|
|
95
|
+
* - no credential-shaped field or value anywhere in the document.
|
|
96
|
+
*/
|
|
97
|
+
export declare function validateCatalog(json: unknown): CatalogValidationResult;
|
|
98
|
+
export type { WinterCatalog, WinterModelDescriptor, WinterProviderDescriptor };
|