@yanlinglabs/winter-provider-conformance 0.0.2
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 +41 -0
- package/README.md +51 -0
- package/dist/corpus/azure.d.ts +7 -0
- package/dist/corpus/classifier-safety.d.ts +146 -0
- package/dist/corpus/continuity.d.ts +52 -0
- package/dist/corpus/cross-vendor-headers.d.ts +38 -0
- package/dist/corpus/harness.d.ts +57 -0
- package/dist/corpus/runner.d.ts +69 -0
- package/dist/fakes/anthropic-console-oauth.d.ts +36 -0
- package/dist/fakes/anthropic-messages.d.ts +115 -0
- package/dist/fakes/azure-openai.d.ts +18 -0
- package/dist/fakes/bedrock.d.ts +90 -0
- package/dist/fakes/codex-oauth.d.ts +46 -0
- package/dist/fakes/gemini.d.ts +121 -0
- package/dist/fakes/index.d.ts +15 -0
- package/dist/fakes/index.js +56 -0
- package/dist/fakes/jwt-verify.d.ts +13 -0
- package/dist/fakes/openai-chat.d.ts +61 -0
- package/dist/fakes/openai-models.d.ts +49 -0
- package/dist/fakes/openai-responses.d.ts +86 -0
- package/dist/fakes/redact-opaque.d.ts +4 -0
- package/dist/fakes/server.d.ts +143 -0
- package/dist/fakes/vertex.d.ts +60 -0
- package/dist/fakes/xai-oauth.d.ts +2 -0
- package/dist/index-k4mhh1q5.js +4377 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1671 -0
- package/dist/live/cases.d.ts +87 -0
- package/dist/live/index.d.ts +101 -0
- package/package.json +50 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ProviderAdapter, ProviderContext } from "@yanlinglabs/winter-provider-runtime";
|
|
2
|
+
import type { WinterModelDescriptor } from "@yanlinglabs/winter-provider-catalog";
|
|
3
|
+
/**
|
|
4
|
+
* A case's OWN assertion failure — the one error whose `.message` the runner prints (review round 1,
|
|
5
|
+
* I1).
|
|
6
|
+
*
|
|
7
|
+
* The distinction is not stylistic. Every message constructed with this class is Winter-authored
|
|
8
|
+
* text in this file, built from measurements: a stop reason, a byte count, a normalized error code.
|
|
9
|
+
* Every OTHER error reaching the runner came from an adapter, and an adapter failure is a
|
|
10
|
+
* `ProviderRequestError` whose message embeds a 200-character snippet of the provider's response
|
|
11
|
+
* body (`provider-runtime/src/errors.ts`). That snippet is scrubbed of credential-shaped strings, but
|
|
12
|
+
* it is still response CONTENT, and the constraint on this gate's output is verbatim: identifiers and
|
|
13
|
+
* byte counts only.
|
|
14
|
+
*
|
|
15
|
+
* So the type IS the permission to print. A message that is safe to render is one this file wrote.
|
|
16
|
+
*/
|
|
17
|
+
export declare class LiveCaseAssertionError extends Error {
|
|
18
|
+
constructor(message: string);
|
|
19
|
+
}
|
|
20
|
+
export type LiveCaseId = "discovery" | "text-turn" | "tool-round" | "thinking-summary" | "count-tokens" | "honest-identity-inference";
|
|
21
|
+
export interface LiveCaseSpec {
|
|
22
|
+
id: LiveCaseId;
|
|
23
|
+
question: string;
|
|
24
|
+
}
|
|
25
|
+
/** The legs the gate runs, in order: cheapest and least stateful first. */
|
|
26
|
+
export declare const LIVE_CASES: readonly LiveCaseSpec[];
|
|
27
|
+
/**
|
|
28
|
+
* The auth-shaped keys a refused inference request's body may be reported by NAME (WS-13b §4).
|
|
29
|
+
*
|
|
30
|
+
* AN ALLOWLIST, and it is the whole safety argument for reporting anything at all. A provider's error
|
|
31
|
+
* body is content and this gate never prints it (`live/index.ts`'s rendering rule) — but when a
|
|
32
|
+
* subscription bearer is refused, the ONE thing an operator needs is which auth dimension the vendor
|
|
33
|
+
* says was missing, and that is a handful of named scalar fields. Anything not named here, including
|
|
34
|
+
* every human-readable message, is dropped.
|
|
35
|
+
*
|
|
36
|
+
* `x_xai_token_auth` and `auth_kind` are the two xAI's own proxy reports (Lane O's capture); `scope`
|
|
37
|
+
* and `token_auth` are the neighbouring spellings the same family uses.
|
|
38
|
+
*/
|
|
39
|
+
export declare const AUTH_DIMENSION_FIELDS: readonly string[];
|
|
40
|
+
/**
|
|
41
|
+
* Pulls ONLY the allowlisted auth dimensions out of an error message, as `field=value`.
|
|
42
|
+
*
|
|
43
|
+
* Exported for its own unit test, because "a marker elsewhere in the same body never survives" is the
|
|
44
|
+
* property that makes this safe and it must be falsifiable without a vendor. Values are bounded to a
|
|
45
|
+
* scalar shape (`[\w.:/-]+` — the `/` admits a scoped value like `grok-cli:access` written as a path
|
|
46
|
+
* and a bare URL host), so a field whose value is a sentence contributes only its first token.
|
|
47
|
+
*/
|
|
48
|
+
export declare function authDimensionsOf(message: string): string[];
|
|
49
|
+
export interface LiveCaseContext {
|
|
50
|
+
/** The catalog PROVIDER id. Named in a report's remediation, so it is threaded rather than assumed. */
|
|
51
|
+
providerId: string;
|
|
52
|
+
adapter: ProviderAdapter;
|
|
53
|
+
ctx: ProviderContext;
|
|
54
|
+
/** The provider-local id that goes on the wire (never the catalog key). */
|
|
55
|
+
model: string;
|
|
56
|
+
/** Absent only for an `allowUnlisted` pass-through, in which case every capability-gated case skips. */
|
|
57
|
+
descriptor?: WinterModelDescriptor;
|
|
58
|
+
/**
|
|
59
|
+
* The PROVIDER row's pricing basis (WS-13b §1) — a provider fact, which is why it does not come off
|
|
60
|
+
* the model descriptor. The inference-path reversion case is about an entitlement, and
|
|
61
|
+
* `subscription` is what "an entitlement rather than a key" means in catalog terms.
|
|
62
|
+
*/
|
|
63
|
+
pricingBasis?: "token" | "subscription" | "free";
|
|
64
|
+
/**
|
|
65
|
+
* WHICH DOCUMENTED THIRD-PARTY PATH this run's credential came down (WS-13b §1), supplied by the
|
|
66
|
+
* gate that planned the target.
|
|
67
|
+
*
|
|
68
|
+
* It is the discriminator the reversion case needs and the one `pricingBasis` cannot be:
|
|
69
|
+
* `subscription` catches four rows and two of them (`clinepass`, `kimi-coding`) are ordinary
|
|
70
|
+
* API-KEY products with a seat price. Reporting a bad key on one of those as "the vendor rejected
|
|
71
|
+
* Winter's identity" would be a false alarm about the one thing this phase is careful about.
|
|
72
|
+
*
|
|
73
|
+
* `ProviderContext.authRef` cannot answer it: its `kind` is a LOCATOR (`keychain`/`env`/…), never
|
|
74
|
+
* the material's — a host may legitimately keep an api key in the Keychain. Absent, the case
|
|
75
|
+
* declines rather than guessing.
|
|
76
|
+
*/
|
|
77
|
+
targetKind?: "api-key" | "oauth" | "keyless";
|
|
78
|
+
signal?: AbortSignal;
|
|
79
|
+
}
|
|
80
|
+
export type LiveCaseResult = {
|
|
81
|
+
status: "ok";
|
|
82
|
+
detail: string;
|
|
83
|
+
} | {
|
|
84
|
+
status: "skipped";
|
|
85
|
+
detail: string;
|
|
86
|
+
};
|
|
87
|
+
export declare const LIVE_CASE_IMPLS: Record<LiveCaseId, (ctx: LiveCaseContext) => Promise<LiveCaseResult>>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { ProviderAdapter, ProviderContext } from "@yanlinglabs/winter-provider-runtime";
|
|
2
|
+
import type { WinterModelDescriptor } from "@yanlinglabs/winter-provider-catalog";
|
|
3
|
+
import { LIVE_CASES, LiveCaseAssertionError, type LiveCaseContext, type LiveCaseId, type LiveCaseSpec } from "./cases.js";
|
|
4
|
+
export { LIVE_CASES, LiveCaseAssertionError };
|
|
5
|
+
export type { LiveCaseContext, LiveCaseId, LiveCaseSpec };
|
|
6
|
+
export interface LiveCaseOutcome {
|
|
7
|
+
id: LiveCaseId;
|
|
8
|
+
status: "ok" | "skipped" | "failed";
|
|
9
|
+
detail: string;
|
|
10
|
+
/** Wall-clock, because a live gate's most common real failure is "it answered, eventually". */
|
|
11
|
+
ms: number;
|
|
12
|
+
}
|
|
13
|
+
export interface LiveReport {
|
|
14
|
+
providerId: string;
|
|
15
|
+
adapterId: string;
|
|
16
|
+
adapterVersion: string;
|
|
17
|
+
/** The catalog key, so a reader can tell which row this run is evidence for. */
|
|
18
|
+
modelKey: string;
|
|
19
|
+
outcomes: LiveCaseOutcome[];
|
|
20
|
+
/** True when nothing FAILED. A skip is a recorded capability fact, not a failure. */
|
|
21
|
+
ok: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface RunLiveCasesOptions {
|
|
24
|
+
providerId: string;
|
|
25
|
+
modelKey: string;
|
|
26
|
+
adapter: ProviderAdapter;
|
|
27
|
+
ctx: ProviderContext;
|
|
28
|
+
/** The provider-local id that goes on the wire. */
|
|
29
|
+
model: string;
|
|
30
|
+
descriptor?: WinterModelDescriptor;
|
|
31
|
+
/** The PROVIDER row's pricing basis (WS-13b §1). Gates the inference-path reversion case. */
|
|
32
|
+
pricingBasis?: "token" | "subscription" | "free";
|
|
33
|
+
/** Which documented third-party path this run's credential came down. `runLiveTarget` supplies it from the gate's own plan. */
|
|
34
|
+
targetKind?: LiveTargetKindLabel;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
/** Progress, one line per case as it finishes. Identifiers and counts only — the case details already obey that rule. */
|
|
37
|
+
onProgress?: (outcome: LiveCaseOutcome) => void;
|
|
38
|
+
}
|
|
39
|
+
export declare function runLiveCases(opts: RunLiveCasesOptions): Promise<LiveReport>;
|
|
40
|
+
/** How the target's credential was named — WS-13b §1's three documented third-party paths. Mirrors the gate's `LiveTargetKind`. */
|
|
41
|
+
export type LiveTargetKindLabel = "api-key" | "oauth" | "keyless";
|
|
42
|
+
export interface LiveRowSummary {
|
|
43
|
+
providerId: string;
|
|
44
|
+
/** The CATALOG KEY (`<providerId>/<model>`), never the provider-local id and never a display name. */
|
|
45
|
+
model: string;
|
|
46
|
+
kind: LiveTargetKindLabel;
|
|
47
|
+
/** True when no case FAILED. A skipped case is a recorded capability fact, not a failure. */
|
|
48
|
+
ok: boolean;
|
|
49
|
+
/** The summed wall-clock of every case. A live gate's most common real failure is "it answered, eventually". */
|
|
50
|
+
latencyMs: number;
|
|
51
|
+
/**
|
|
52
|
+
* True only when the tool round ran and PASSED.
|
|
53
|
+
*
|
|
54
|
+
* A skip therefore reads `false` — deliberately, because the question this column answers is "can
|
|
55
|
+
* this row be driven agentically?", and "the descriptor says it cannot" is a no. The per-case line
|
|
56
|
+
* above always says WHICH of the two it was, so the row is a summary and never the whole story.
|
|
57
|
+
*/
|
|
58
|
+
toolCallOk: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* The identity string THIS BUILD sends (`winterUserAgent()`), recorded beside the result so a live
|
|
61
|
+
* run's output carries the identity claim WS-13b §1 makes.
|
|
62
|
+
*
|
|
63
|
+
* It is not a wire observation — this runner never sees an outgoing header. That Winter's own
|
|
64
|
+
* user-agent is genuinely on every family's requests is pinned by the corpus (`corpus/*.test.ts`,
|
|
65
|
+
* "every request carries Winter's OWN user-agent"), against the live request a fake received.
|
|
66
|
+
*/
|
|
67
|
+
identityHeader: string;
|
|
68
|
+
/**
|
|
69
|
+
* The row's ADMISSION EVIDENCE TIER (fix-wave R-FW-3, condition (b)).
|
|
70
|
+
*
|
|
71
|
+
* Printed because promotion is TWO-KEY: a live pass alone does not promote a row — it takes a live
|
|
72
|
+
* pass AND a fetched vendor document, with the citation upgraded in the same reviewed commit. A
|
|
73
|
+
* green row from a `pinned-upstream` provider says "the path works", not "the evidence is
|
|
74
|
+
* complete", and an operator reading a pasted row is exactly who would otherwise promote it by
|
|
75
|
+
* habit.
|
|
76
|
+
*
|
|
77
|
+
* A catalog fact, read off the resolved provider row — never re-derived here.
|
|
78
|
+
*/
|
|
79
|
+
admissionTier: string;
|
|
80
|
+
}
|
|
81
|
+
export interface LiveRowSummaryOptions {
|
|
82
|
+
kind: LiveTargetKindLabel;
|
|
83
|
+
identityHeader: string;
|
|
84
|
+
admissionTier: string;
|
|
85
|
+
}
|
|
86
|
+
/** Folds a finished `LiveReport` into its one-line row. Pure: no adapter, no endpoint, no clock. */
|
|
87
|
+
export declare function liveRowSummary(report: LiveReport, opts: LiveRowSummaryOptions): LiveRowSummary;
|
|
88
|
+
/** `key=value` pairs, in a fixed order, so a run's rows grep and diff. */
|
|
89
|
+
export declare function formatLiveRow(row: LiveRowSummary): string;
|
|
90
|
+
/**
|
|
91
|
+
* The per-target case: run every live leg against one target, and fold the result into its row.
|
|
92
|
+
*
|
|
93
|
+
* One call so the gate cannot run the cases and then forget the row, or report a row built from
|
|
94
|
+
* something other than the run it names.
|
|
95
|
+
*/
|
|
96
|
+
export declare function runLiveTarget(opts: RunLiveCasesOptions & LiveRowSummaryOptions): Promise<{
|
|
97
|
+
report: LiveReport;
|
|
98
|
+
row: LiveRowSummary;
|
|
99
|
+
}>;
|
|
100
|
+
/** One line per case. Identifiers, counts and durations only — never a byte of what a provider returned. */
|
|
101
|
+
export declare function formatLiveReport(report: LiveReport): string;
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yanlinglabs/winter-provider-conformance",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"bun": ">=1.2"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/yanlingLabs/winter-agent-sdk.git",
|
|
12
|
+
"directory": "packages/provider-conformance"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/yanlingLabs/winter-agent-sdk",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/yanlingLabs/winter-agent-sdk/issues"
|
|
17
|
+
},
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./fakes": {
|
|
26
|
+
"types": "./dist/fakes/index.d.ts",
|
|
27
|
+
"default": "./dist/fakes/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"NOTICE",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "restricted"
|
|
38
|
+
},
|
|
39
|
+
"winter": {
|
|
40
|
+
"publish": {
|
|
41
|
+
"npm": true,
|
|
42
|
+
"harness": true
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@yanlinglabs/winter-provider-catalog": "0.0.2",
|
|
47
|
+
"@yanlinglabs/winter-provider-runtime": "0.0.2"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {}
|
|
50
|
+
}
|