@yanlinglabs/winter-provider-runtime 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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +109 -0
  4. package/dist/adapters/anthropic/console-oauth.d.ts +101 -0
  5. package/dist/adapters/anthropic/index.d.ts +4 -0
  6. package/dist/adapters/anthropic/messages.d.ts +76 -0
  7. package/dist/adapters/bedrock/converse.d.ts +143 -0
  8. package/dist/adapters/bedrock/crc32.d.ts +9 -0
  9. package/dist/adapters/bedrock/credentials.d.ts +32 -0
  10. package/dist/adapters/bedrock/eventstream.d.ts +65 -0
  11. package/dist/adapters/bedrock/index.d.ts +8 -0
  12. package/dist/adapters/bedrock/sigv4.d.ts +119 -0
  13. package/dist/adapters/bedrock/testing.d.ts +46 -0
  14. package/dist/adapters/content-blocks.d.ts +7 -0
  15. package/dist/adapters/google/adc.d.ts +35 -0
  16. package/dist/adapters/google/generate-content.d.ts +136 -0
  17. package/dist/adapters/google/index.d.ts +8 -0
  18. package/dist/adapters/google/jwt-rs256.d.ts +36 -0
  19. package/dist/adapters/google/vertex.d.ts +15 -0
  20. package/dist/adapters/index.d.ts +34 -0
  21. package/dist/adapters/oauth/device-code.d.ts +32 -0
  22. package/dist/adapters/oauth/refresh.d.ts +40 -0
  23. package/dist/adapters/openai/azure.d.ts +38 -0
  24. package/dist/adapters/openai/chat-completions.d.ts +86 -0
  25. package/dist/adapters/openai/codex-config.d.ts +42 -0
  26. package/dist/adapters/openai/codex-oauth.d.ts +47 -0
  27. package/dist/adapters/openai/index.d.ts +20 -0
  28. package/dist/adapters/openai/local.d.ts +16 -0
  29. package/dist/adapters/openai/pkce.d.ts +111 -0
  30. package/dist/adapters/openai/quota.d.ts +99 -0
  31. package/dist/adapters/openai/responses.d.ts +142 -0
  32. package/dist/adapters/openai/shared.d.ts +359 -0
  33. package/dist/adapters/openai/testing.d.ts +59 -0
  34. package/dist/adapters/openai/xai-derived-shapes.d.ts +67 -0
  35. package/dist/adapters/openai/xai-oauth.d.ts +102 -0
  36. package/dist/adapters/openai/xai-oauth.testing.d.ts +62 -0
  37. package/dist/adapters/privileged-headers.d.ts +51 -0
  38. package/dist/adapters/refusals.d.ts +10 -0
  39. package/dist/address-classifier.d.ts +17 -0
  40. package/dist/bun-required.d.ts +54 -0
  41. package/dist/continuity/decoration.d.ts +89 -0
  42. package/dist/continuity/domains.d.ts +92 -0
  43. package/dist/continuity/fixtures.d.ts +44 -0
  44. package/dist/continuity/handoff.d.ts +94 -0
  45. package/dist/continuity/index.d.ts +10 -0
  46. package/dist/continuity/renderer.d.ts +111 -0
  47. package/dist/continuity/warnings.d.ts +46 -0
  48. package/dist/credentials/env.d.ts +6 -0
  49. package/dist/credentials/file.d.ts +21 -0
  50. package/dist/credentials/memory.d.ts +8 -0
  51. package/dist/credentials/types.d.ts +38 -0
  52. package/dist/discovery.d.ts +15 -0
  53. package/dist/endpoint-policy.d.ts +127 -0
  54. package/dist/errors.d.ts +68 -0
  55. package/dist/http.d.ts +29 -0
  56. package/dist/identity.d.ts +62 -0
  57. package/dist/index-5z94gxhk.js +43790 -0
  58. package/dist/index.d.ts +39 -0
  59. package/dist/index.js +3194 -0
  60. package/dist/registry.d.ts +136 -0
  61. package/dist/retry.d.ts +38 -0
  62. package/dist/sse.d.ts +12 -0
  63. package/dist/testing.d.ts +19 -0
  64. package/dist/testing.js +432 -0
  65. package/dist/types.d.ts +376 -0
  66. package/package.json +49 -0
@@ -0,0 +1,136 @@
1
+ import type { WinterCatalog, WinterModelDescriptor, WinterProviderDescriptor } from "@yanlinglabs/winter-provider-catalog";
2
+ import type { ProviderAdapter } from "./types.js";
3
+ export interface ResolvedModel {
4
+ providerId: string;
5
+ /** The catalog key, or `<providerId>/<id>` for an allowUnlisted passthrough. */
6
+ modelKey: string;
7
+ /** What actually goes on the wire. */
8
+ providerModelId: string;
9
+ adapterId: string;
10
+ adapter: ProviderAdapter;
11
+ /** `undefined` ONLY for an allowUnlisted passthrough on a non-authoritative provider. Absence is the honest signal that nothing is known — never read capabilities off it. */
12
+ descriptor: WinterModelDescriptor | undefined;
13
+ provider: WinterProviderDescriptor;
14
+ continuationDomain?: string;
15
+ catalogVersion: string;
16
+ }
17
+ export type ResolutionErrorCode = "unknown-provider" | "unknown-model" | "no-adapter" | "blocked" | "no-provider-for-bare-model"
18
+ /** RULING R6-K: the model id is qualified for one provider while the session is configured for another. Never resolved either way — see `resolve`'s own header. */
19
+ | "provider-mismatch"
20
+ /**
21
+ * WS-13b R6b-7: the row resolved, but the user has turned this provider OFF
22
+ * (`settings.providers.<id>.enabled === false`). A REFUSAL rather than a skip, on purpose: a skip
23
+ * is a substitution by another name, and WS-13 §9 forbids a session quietly running on something
24
+ * other than what it was asked for. Produced by the runtime's `selection.ts`, which is where the
25
+ * settings cascade is visible -- the registry itself has no settings and never will.
26
+ */
27
+ | "provider-disabled" | "capability"
28
+ /**
29
+ * P6 fix wave, Ruling E-1: a provider built for a target on ANOTHER provider than the session's has
30
+ * no credential of its own -- no explicit `authRef` on the target's route and no keychain record for
31
+ * the target provider. The session's credential is NEVER substituted (`session-provider.ts`
32
+ * `describeTargetMaterial`); this code is what the deferred refusal carries instead.
33
+ */
34
+ | "no-credential-for-provider"
35
+ /**
36
+ * WS-13c §4 step 5: a slot name resolved to a canonical model, and NOTHING can serve it — every
37
+ * candidate row is blocked/deprecated, its provider has no credential, its provider is disabled,
38
+ * or the slot's pinned provider is absent.
39
+ *
40
+ * A REFUSAL that names what would have served it, never a substitution and never another family
41
+ * (WS-13 §9). The Agent tool's `model` enum advertises a lineup, not an entitlement: a session may
42
+ * legitimately be offered `astra` and hold no OpenAI credential, and answering that by quietly
43
+ * running `sonnet` is the exact "false information" D25 forbids.
44
+ */
45
+ | "slot-unservable"
46
+ /**
47
+ * WS-13c §3 acceptance (c): a slot name that is NOT in the session's active set and exists in two
48
+ * or more families — `pro` and `flash` live in `gemini`, `deepseek` and `glm`.
49
+ *
50
+ * Typed rather than resolved by a tie-break, because either choice would be a guess about which
51
+ * vendor the model meant, and a model copying a name it saw in older context is exactly the case
52
+ * acceptance (b) makes work when the name IS unique.
53
+ */
54
+ | "ambiguous-slot-name"
55
+ /**
56
+ * P7a carry (Lane D): the row is a PER-TENANT provider (`requiresUserEndpoint`) and this session
57
+ * supplied no endpoint of its own, so there is nothing to send the request to.
58
+ *
59
+ * A REFUSAL, and it has to be one: such a row ships with no usable `defaultEndpoints.api` at all,
60
+ * so the alternatives are a request to a literal `<resource>` placeholder host (a confusing DNS
61
+ * failure) or a silent fall back to some other provider, which WS-13 §9 forbids. The message
62
+ * carries the row's `endpointTemplate` so the host can tell the user exactly what to paste.
63
+ *
64
+ * DECLARED AT P7a'S SPINE so producer and consumer can land in either order; nothing raises it
65
+ * until Lane D's `connectionForProvider` does.
66
+ */
67
+ | "endpoint-required";
68
+ export declare class WinterProviderResolutionError extends Error {
69
+ readonly code: ResolutionErrorCode;
70
+ constructor(code: ResolutionErrorCode, message: string);
71
+ }
72
+ /** What `resolve` is asked. `provider` carries the session's selection; `allowUnlisted` is a selection-policy bit, deliberately NOT part of `ConnectionProfile`. */
73
+ export interface ResolveRequest {
74
+ model: string;
75
+ provider?: {
76
+ providerId?: string;
77
+ allowUnlisted?: boolean;
78
+ };
79
+ }
80
+ /**
81
+ * The pinned `ModelInfo` shape (`sdk.d.ts:1261-1300`): three required fields, six optional.
82
+ *
83
+ * RE-EXPORTED from the sdk rather than declared here (T10), the same way `CredentialRef` already is:
84
+ * `Query.supportedModels()` puts this shape on the sdk's public surface, and two independent copies
85
+ * of a pinned wire type are how the producer and the consumer of one round trip start disagreeing
86
+ * about an optional field. One declaration; either import path gets it.
87
+ */
88
+ import type { ModelInfo } from "@yanlinglabs/winter-agent-sdk";
89
+ export type { ModelInfo };
90
+ export interface RegistryListing {
91
+ catalogVersion: string;
92
+ adapters: Array<{
93
+ id: string;
94
+ version: string;
95
+ family: string;
96
+ protocol: string;
97
+ }>;
98
+ providers: Array<{
99
+ id: string;
100
+ displayName: string;
101
+ adapterId: string;
102
+ adapterRegistered: boolean;
103
+ modelCount: number;
104
+ riskClass: string;
105
+ }>;
106
+ }
107
+ export interface ProviderRegistry {
108
+ register(adapter: ProviderAdapter): void;
109
+ resolve(request: ResolveRequest): ResolvedModel | WinterProviderResolutionError;
110
+ list(): RegistryListing;
111
+ /** R6-I: pinned-shaped rows for one provider's models. Optional capability booleans are OMITTED when unknown, never `false`. */
112
+ listModelInfo(sessionProviderId: string): ModelInfo[];
113
+ }
114
+ export interface UsageForCost {
115
+ inputTokens: number;
116
+ outputTokens: number;
117
+ cacheReadTokens?: number;
118
+ cacheWriteTokens?: number;
119
+ }
120
+ /**
121
+ * R6-H: the descriptor's `pricing` evidence is the ONLY price source.
122
+ *
123
+ * An unpriced model — or one resolved with no descriptor at all — reports `0` with
124
+ * `costBasis: "unknown"`. That is a DELIBERATE, DISCLOSED DIVERGENCE from the pin: capture (K) shows
125
+ * the pinned runtime reporting a non-zero cost for a model no price table contains, guessing at the
126
+ * default model's rate. A number nobody can justify is worse than an honest zero next to a marker
127
+ * that says the basis is unknown, and `maxBudgetUsd` is correspondingly inert for such a model.
128
+ *
129
+ * Cache tokens with no cache rate are priced at the INPUT rate rather than free: pricing them at
130
+ * zero would silently under-report, and the basis stays `"list"` because a real list price was used.
131
+ */
132
+ export declare function estimateCostUsd(usage: UsageForCost, descriptor: WinterModelDescriptor | undefined): {
133
+ costUsd: number;
134
+ costBasis: "list" | "unknown";
135
+ };
136
+ export declare function createRegistry(catalog: WinterCatalog): ProviderRegistry;
@@ -0,0 +1,38 @@
1
+ import type { ProviderEvent } from "./types.js";
2
+ export declare const DEFAULT_MAX_RETRIES = 10;
3
+ export declare const RETRY_BACKOFF_BASE_MS = 1000;
4
+ export declare const RETRY_BACKOFF_CAP_MS = 30000;
5
+ export declare const RETRY_AFTER_HONOUR_CEILING_MS = 60000;
6
+ export interface RetryPolicyOptions {
7
+ maxRetries?: number;
8
+ /** Injected for deterministic tests. Full jitter multiplies the whole interval by this in [0, 1). */
9
+ random?: () => number;
10
+ /** Injected for deterministic tests — a real `withRetry` never sleeps in a unit test. */
11
+ sleep?: (ms: number) => Promise<void>;
12
+ }
13
+ export interface RetryPolicy {
14
+ readonly maxRetries: number;
15
+ /** True once `commit()` has been called: the stream has begun and no further retry is safe. */
16
+ readonly committed: boolean;
17
+ /** Called by the caller the moment the first response byte is consumed. Idempotent, one-way. */
18
+ commit(): void;
19
+ /** The delay before retry number `attempt` (1-based). `retryAfterMs`, when within the ceiling, replaces the schedule entirely. */
20
+ delayMs(attempt: number, retryAfterMs?: number): number;
21
+ /** Waits, ABORTABLY. A backoff can be 30 s (or a clamped 60 s of Retry-After), and an interrupt must not have to outlast it. */
22
+ sleep(ms: number, signal?: AbortSignal): Promise<void>;
23
+ }
24
+ export declare function createRetryPolicy(opts?: RetryPolicyOptions): RetryPolicy;
25
+ /**
26
+ * Runs `attempt` under the policy, emitting one `retry` event per retry — announced BEFORE the delay
27
+ * is taken, which is the pinned ordering (capture (G): the frame's `retry_delay_ms` of 577 preceded
28
+ * a measured 586ms gap).
29
+ *
30
+ * `attempt` is the RETRY ORDINAL starting at 1, matching the pin: a single failure then success
31
+ * produced exactly one frame with `attempt: 1`. So the total number of invocations is
32
+ * `maxRetries + 1`.
33
+ */
34
+ export declare function withRetry<T>(attempt: (n: number) => Promise<T>, policy: RetryPolicy, onRetry: (event: Extract<ProviderEvent, {
35
+ type: "retry";
36
+ }>) => void,
37
+ /** Cancels the BACKOFF as well as the attempt. Optional so every existing call site is unchanged. */
38
+ signal?: AbortSignal): Promise<T>;
package/dist/sse.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface SseOptions {
2
+ /** Milliseconds of TOTAL SILENCE (no bytes at all) after which the stream is abandoned as stalled. */
3
+ stallTimeoutMs: number;
4
+ signal?: AbortSignal;
5
+ /** Called with every chunk's byte count — telemetry counts bytes, never content (Global Constraints). */
6
+ onBytes?: (n: number) => void;
7
+ }
8
+ export interface SseEvent {
9
+ event?: string;
10
+ data: string;
11
+ }
12
+ export declare function parseSse(body: ReadableStream<Uint8Array>, opts: SseOptions): AsyncGenerator<SseEvent>;
@@ -0,0 +1,19 @@
1
+ export { concatFrames, converseStreamEvent, converseStreamException, verifySigV4, encodeEventStreamMessage } from "./adapters/bedrock/testing.js";
2
+ export type { EventStreamHeaderInput, SigV4Verdict, VerifySigV4Input } from "./adapters/bedrock/testing.js";
3
+ export { parseAuthorization } from "./adapters/bedrock/sigv4.js";
4
+ export { FAST_RETRY, descriptor, testContext, testDiscoveryContext } from "./adapters/openai/testing.js";
5
+ export type { DescriptorOverrides, TestContextOptions } from "./adapters/openai/testing.js";
6
+ export { BunRequiredError } from "./bun-required.js";
7
+ export { startXaiChatFake, startXaiOauthFake } from "./adapters/openai/xai-oauth.testing.js";
8
+ export type { XaiOauthFake, XaiOauthFakeOptions, XaiRecordedRequest } from "./adapters/openai/xai-oauth.testing.js";
9
+ export { CODEX } from "./adapters/openai/codex-config.js";
10
+ export { QuotaManager } from "./adapters/openai/quota.js";
11
+ export { base64Url } from "./adapters/openai/pkce.js";
12
+ export { AZURE_PREVIEW_API_VERSION } from "./adapters/openai/azure.js";
13
+ export { hostHeaders } from "./adapters/privileged-headers.js";
14
+ export { RS256, base64UrlEncode, importRs256PrivateKey, pkcs8DerFromPem, signRs256Jwt } from "./adapters/google/jwt-rs256.js";
15
+ export { vertexModelPath } from "./adapters/google/index.js";
16
+ export { GCP_CLOUD_PLATFORM_SCOPE, createServiceAccountTokenSource } from "./adapters/google/adc.js";
17
+ export { googleCompletionMarker } from "./adapters/google/generate-content.js";
18
+ export { THINKING_ENABLED_NEEDS_BUDGET } from "./adapters/refusals.js";
19
+ export { fixtureCatalog, fixtureModel, fixtureProvider, fixtureReasoning, scriptedAdapter } from "./continuity/fixtures.js";
@@ -0,0 +1,432 @@
1
+ import {
2
+ createMemoryCredentialStore2,
3
+ stampFamilyFields,
4
+ BunRequiredError2,
5
+ requireBunRuntime2,
6
+ hostHeaders2,
7
+ THINKING_ENABLED_NEEDS_BUDGET2,
8
+ base64Url2,
9
+ googleCompletionMarker2,
10
+ RS2562,
11
+ base64UrlEncode2,
12
+ pkcs8DerFromPem2,
13
+ importRs256PrivateKey2,
14
+ signRs256Jwt2,
15
+ GCP_CLOUD_PLATFORM_SCOPE2,
16
+ createServiceAccountTokenSource2,
17
+ vertexModelPath2,
18
+ crc32,
19
+ sha256Hex,
20
+ buildCanonicalRequest,
21
+ buildStringToSign,
22
+ computeSignature,
23
+ parseAuthorization2,
24
+ CODEX2,
25
+ QuotaManager2,
26
+ AZURE_PREVIEW_API_VERSION2,
27
+ readableStateOf2
28
+ } from "./index-5z94gxhk.js";
29
+
30
+ // src/adapters/bedrock/testing.ts
31
+ function encodeHeader(header) {
32
+ const encoder = new TextEncoder;
33
+ const name = encoder.encode(header.name);
34
+ const value = encoder.encode(header.value);
35
+ const out = new Uint8Array(1 + name.length + 1 + 2 + value.length);
36
+ const view = new DataView(out.buffer);
37
+ let offset = 0;
38
+ view.setUint8(offset, name.length);
39
+ offset += 1;
40
+ out.set(name, offset);
41
+ offset += name.length;
42
+ view.setUint8(offset, 7);
43
+ offset += 1;
44
+ view.setUint16(offset, value.length);
45
+ offset += 2;
46
+ out.set(value, offset);
47
+ return out;
48
+ }
49
+ function encodeEventStreamMessage(headers, payload) {
50
+ const encodedHeaders = headers.map(encodeHeader);
51
+ const headersLength = encodedHeaders.reduce((sum, h) => sum + h.length, 0);
52
+ const totalLength = 16 + headersLength + payload.length;
53
+ const out = new Uint8Array(totalLength);
54
+ const view = new DataView(out.buffer);
55
+ view.setUint32(0, totalLength);
56
+ view.setUint32(4, headersLength);
57
+ view.setUint32(8, crc32(out.subarray(0, 8)));
58
+ let offset = 16 - 4;
59
+ for (const header of encodedHeaders) {
60
+ out.set(header, offset);
61
+ offset += header.length;
62
+ }
63
+ out.set(payload, offset);
64
+ view.setUint32(totalLength - 4, crc32(out.subarray(0, totalLength - 4)));
65
+ return out;
66
+ }
67
+ function converseStreamEvent(eventType, payload) {
68
+ return encodeEventStreamMessage([
69
+ { name: ":message-type", value: "event" },
70
+ { name: ":event-type", value: eventType },
71
+ { name: ":content-type", value: "application/json" }
72
+ ], new TextEncoder().encode(JSON.stringify(payload)));
73
+ }
74
+ function converseStreamException(exceptionType, payload = {}) {
75
+ return encodeEventStreamMessage([
76
+ { name: ":message-type", value: "exception" },
77
+ { name: ":exception-type", value: exceptionType },
78
+ { name: ":content-type", value: "application/json" }
79
+ ], new TextEncoder().encode(JSON.stringify(payload)));
80
+ }
81
+ function concatFrames(frames) {
82
+ const total = frames.reduce((sum, f) => sum + f.length, 0);
83
+ const out = new Uint8Array(total);
84
+ let offset = 0;
85
+ for (const frame of frames) {
86
+ out.set(frame, offset);
87
+ offset += frame.length;
88
+ }
89
+ return out;
90
+ }
91
+ async function verifySigV4(input) {
92
+ const parsed = parseAuthorization2(input.headers.get("authorization"));
93
+ if (parsed === undefined)
94
+ return { ok: false, reason: "the request carried no parseable AWS4-HMAC-SHA256 Authorization header" };
95
+ if (input.expectedAccessKeyId !== undefined && parsed.accessKeyId !== input.expectedAccessKeyId) {
96
+ return { ok: false, reason: `the credential names access key "${parsed.accessKeyId}", which this fake does not know` };
97
+ }
98
+ const url = new URL(input.url);
99
+ const headers = {};
100
+ for (const name of parsed.signedHeaders) {
101
+ const value = name === "host" ? url.host : input.headers.get(name);
102
+ if (value === null || value === undefined)
103
+ return { ok: false, reason: `the signature covers header "${name}", which the request does not carry` };
104
+ headers[name] = value;
105
+ }
106
+ const payloadHash = await sha256Hex(input.body);
107
+ const declaredHash = input.headers.get("x-amz-content-sha256");
108
+ if (declaredHash !== null && declaredHash !== payloadHash) {
109
+ return { ok: false, reason: "x-amz-content-sha256 does not match the body the server received" };
110
+ }
111
+ const stamp = input.headers.get("x-amz-date");
112
+ if (stamp === null)
113
+ return { ok: false, reason: "the request carried no x-amz-date" };
114
+ const { canonicalRequest } = buildCanonicalRequest({ method: input.method, pathname: url.pathname, search: url.search, headers, payloadHash });
115
+ const scope = `${parsed.datestamp}/${parsed.region}/${parsed.service}/aws4_request`;
116
+ const stringToSign = await buildStringToSign(canonicalRequest, stamp, scope);
117
+ const expected = await computeSignature(input.secretAccessKey, parsed.datestamp, parsed.region, parsed.service, stringToSign);
118
+ if (expected !== parsed.signature)
119
+ return { ok: false, reason: "the request signature does not match the one this fake computes for it" };
120
+ return { ok: true, accessKeyId: parsed.accessKeyId };
121
+ }
122
+ // src/adapters/openai/testing.ts
123
+ var TEST_API_KEY = "test-key-openai-0000";
124
+ function evidence(value, confidence = "verified") {
125
+ return { value, source: "official-doc", confidence, observedAt: "2026-09-05T00:00:00Z" };
126
+ }
127
+ var stampRow = (row) => stampFamilyFields([row], [])[0];
128
+ function descriptor(overrides = {}) {
129
+ const key = overrides.key ?? "openai/o4-mini";
130
+ return stampRow({
131
+ key,
132
+ providerId: overrides.providerId ?? key.split("/")[0],
133
+ upstreamId: overrides.upstreamId ?? key.slice(key.indexOf("/") + 1),
134
+ displayName: key,
135
+ aliases: [],
136
+ endpoints: ["responses"],
137
+ inputModalities: evidence(overrides.inputModalities ?? ["text", "image"]),
138
+ outputModalities: evidence(["text"]),
139
+ toolCalling: evidence(overrides.toolCalling ?? "native"),
140
+ nativeTools: evidence(true),
141
+ ...overrides.parallelTools !== undefined ? { parallelTools: evidence(overrides.parallelTools) } : {},
142
+ ...overrides.maxOutputTokens !== undefined ? { maxOutputTokens: evidence(overrides.maxOutputTokens) } : {},
143
+ ...overrides.noReasoning === true ? {} : {
144
+ reasoning: {
145
+ supported: evidence(true),
146
+ efforts: overrides.efforts ?? ["low", "medium", "high"],
147
+ ...overrides.defaultEffort !== undefined ? { defaultEffort: overrides.defaultEffort } : {},
148
+ continuation: overrides.continuation ?? "opaque-provider-state",
149
+ readableState: evidence(overrides.readableState ?? "summary"),
150
+ ...overrides.summaryValues !== undefined ? { summaryRequest: evidence({ field: "reasoning.summary", values: overrides.summaryValues }) } : {},
151
+ ...overrides.continuationDomain !== undefined ? { continuationDomain: evidence(overrides.continuationDomain) } : {}
152
+ }
153
+ },
154
+ unsupportedParameters: overrides.unsupportedParameters ?? [],
155
+ status: "candidate"
156
+ });
157
+ }
158
+ var KEYCHAIN_REF = { kind: "keychain", account: "openai:test" };
159
+ function testContext(opts = {}) {
160
+ const key = opts.apiKey === undefined ? TEST_API_KEY : opts.apiKey;
161
+ const credentials = createMemoryCredentialStore2(key === null ? [] : [[KEYCHAIN_REF, { kind: "api-key", key }]]);
162
+ const connection = {
163
+ providerId: opts.providerId ?? "openai",
164
+ ...opts.baseUrl !== undefined ? { baseUrl: opts.baseUrl } : {},
165
+ ...opts.local !== undefined ? { local: opts.local } : {},
166
+ ...opts.headers !== undefined ? { headers: opts.headers } : {},
167
+ ...opts.deployment !== undefined ? { deployment: opts.deployment } : {},
168
+ ...opts.apiVersion !== undefined ? { apiVersion: opts.apiVersion } : {}
169
+ };
170
+ return {
171
+ connection,
172
+ credentials,
173
+ authRef: opts.authRef ?? (key === null ? { kind: "none" } : KEYCHAIN_REF),
174
+ stallTimeoutMs: opts.stallTimeoutMs ?? 2000,
175
+ log: (event) => opts.logs?.push(event)
176
+ };
177
+ }
178
+ function testDiscoveryContext(opts = {}) {
179
+ return {
180
+ ...testContext(opts),
181
+ ...opts.signal !== undefined ? { signal: opts.signal } : {},
182
+ limits: { maxBytes: opts.maxBytes ?? 1024 * 1024, maxItems: opts.maxItems ?? 100, timeoutMs: opts.timeoutMs ?? 5000 }
183
+ };
184
+ }
185
+ var FAST_RETRY = { maxRetries: 3, random: () => 0.5, sleep: (_ms) => new Promise((r) => setTimeout(r, 1)) };
186
+ // src/adapters/openai/xai-oauth.testing.ts
187
+ var ACCOUNT_ID = "acct-x";
188
+ var REFRESHED_ACCESS_TOKEN = "test-token-xai-access-refreshed";
189
+ function fakeIdToken(sub = ACCOUNT_ID) {
190
+ const b64 = (value) => btoa(JSON.stringify(value)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
191
+ return `${b64({ alg: "ES256", typ: "JWT" })}.${b64({ sub, email: "someone@example.invalid" })}.c2ln`;
192
+ }
193
+ async function startXaiChatFake(opts = {}) {
194
+ requireBunRuntime2("startXaiChatFake", "Bun.serve", "It binds a loopback HTTP server on 127.0.0.1:0 to stand in for the vendor. Drive it from a Bun test process; a Node consumer has no fake to start.");
195
+ const requests = [];
196
+ const fresh = opts.freshBearer ?? REFRESHED_ACCESS_TOKEN;
197
+ let sawFreshBearer = false;
198
+ const server = Bun.serve({
199
+ hostname: "127.0.0.1",
200
+ port: 0,
201
+ fetch: async (req) => {
202
+ const url = new URL(req.url);
203
+ const body = await req.text();
204
+ const headers = {};
205
+ for (const [name, value] of req.headers) {
206
+ headers[name.toLowerCase()] = /^(authorization|x-api-key|api-key)$/i.test(name) ? `${value.split(" ")[0] ?? ""} ***`.trim() : value;
207
+ }
208
+ if (req.headers.get("authorization") === `Bearer ${fresh}`)
209
+ sawFreshBearer = true;
210
+ requests.push({ method: req.method, path: url.pathname, headers, body });
211
+ const frames = [
212
+ `data: ${JSON.stringify({ id: "cmpl-1", choices: [{ index: 0, delta: { content: "ok" } }] })}
213
+
214
+ `,
215
+ `data: ${JSON.stringify({ id: "cmpl-1", choices: [{ index: 0, delta: {}, finish_reason: "stop" }] })}
216
+
217
+ `,
218
+ `data: [DONE]
219
+
220
+ `
221
+ ].join("");
222
+ return new Response(frames, { headers: { "content-type": "text/event-stream" } });
223
+ }
224
+ });
225
+ return {
226
+ url: `http://127.0.0.1:${server.port}`,
227
+ requests,
228
+ get sawFreshBearer() {
229
+ return sawFreshBearer;
230
+ },
231
+ close: async () => {
232
+ await server.stop(true);
233
+ }
234
+ };
235
+ }
236
+ async function startXaiOauthFake(opts = {}) {
237
+ requireBunRuntime2("startXaiOauthFake", "Bun.serve", "It binds a loopback HTTP server on 127.0.0.1:0 to stand in for the vendor. Drive it from a Bun test process; a Node consumer has no fake to start.");
238
+ const requests = [];
239
+ let polls = 0;
240
+ const server = Bun.serve({
241
+ hostname: "127.0.0.1",
242
+ port: 0,
243
+ fetch: async (req) => {
244
+ const url = new URL(req.url);
245
+ const body = await req.text();
246
+ const headers = {};
247
+ for (const [name, value] of req.headers) {
248
+ headers[name.toLowerCase()] = /^(authorization|x-api-key|api-key)$/i.test(name) ? `${value.split(" ")[0] ?? ""} ***`.trim() : value;
249
+ }
250
+ requests.push({ method: req.method, path: url.pathname, headers, body });
251
+ const form = new URLSearchParams(body);
252
+ const identity = form.get("referrer");
253
+ if (identity === null || identity.length === 0) {
254
+ return Response.json({ error: "invalid_request", error_description: "the client did not identify itself" }, { status: 400 });
255
+ }
256
+ if (url.pathname === "/oauth2/device/code") {
257
+ return Response.json({
258
+ device_code: "test-device-code-xai",
259
+ user_code: "WXYZ-1234",
260
+ verification_uri: "https://example.invalid/activate",
261
+ verification_uri_complete: "https://example.invalid/activate?user_code=WXYZ-1234",
262
+ interval: 0,
263
+ expires_in: 900
264
+ });
265
+ }
266
+ if (url.pathname === "/oauth2/token") {
267
+ if (form.get("grant_type") === "refresh_token") {
268
+ return Response.json({ access_token: REFRESHED_ACCESS_TOKEN, expires_in: 3600, token_type: "Bearer" });
269
+ }
270
+ if (opts.rejectIdentity !== undefined && identity === opts.rejectIdentity) {
271
+ return Response.json({ error: "access_denied", error_description: "client not allowed" }, { status: 400 });
272
+ }
273
+ if (opts.tokenError !== undefined) {
274
+ return Response.json({ error: opts.tokenError, error_description: "the fixture's ordinary failure" }, { status: 400 });
275
+ }
276
+ polls += 1;
277
+ if (polls <= (opts.pendingPolls ?? 0))
278
+ return Response.json({ error: "authorization_pending" }, { status: 400 });
279
+ return Response.json({
280
+ access_token: "test-token-xai-access",
281
+ refresh_token: "test-token-xai-refresh",
282
+ ...opts.omitIdToken === true ? {} : { id_token: fakeIdToken() },
283
+ expires_in: 3600,
284
+ token_type: "Bearer"
285
+ });
286
+ }
287
+ return Response.json({ error: "not_found" }, { status: 404 });
288
+ }
289
+ });
290
+ return {
291
+ deviceCodeUrl: `http://127.0.0.1:${server.port}/oauth2/device/code`,
292
+ tokenUrl: `http://127.0.0.1:${server.port}/oauth2/token`,
293
+ requests,
294
+ close: async () => {
295
+ await server.stop(true);
296
+ }
297
+ };
298
+ }
299
+ // src/continuity/fixtures.ts
300
+ var evidence2 = (value, confidence = "verified") => ({
301
+ value,
302
+ source: "official-doc",
303
+ observedAt: "2026-09-05",
304
+ confidence
305
+ });
306
+ var stampRow2 = (row) => stampFamilyFields([row], [])[0];
307
+ function fixtureModel(init) {
308
+ return stampRow2({
309
+ key: init.key,
310
+ providerId: init.providerId,
311
+ upstreamId: init.upstreamId ?? init.key.slice(init.key.indexOf("/") + 1),
312
+ displayName: init.key,
313
+ aliases: init.aliases ?? [],
314
+ endpoints: ["responses"],
315
+ ...init.contextWindow !== undefined ? { contextWindow: evidence2(init.contextWindow) } : {},
316
+ inputModalities: evidence2(["text"]),
317
+ outputModalities: evidence2(["text"]),
318
+ toolCalling: evidence2(init.toolCalling ?? "native"),
319
+ nativeTools: evidence2(true),
320
+ ...init.reasoning !== undefined ? { reasoning: init.reasoning } : {},
321
+ unsupportedParameters: [],
322
+ status: "supported"
323
+ });
324
+ }
325
+ function fixtureReasoning(init) {
326
+ return {
327
+ supported: evidence2(true),
328
+ efforts: init.efforts ?? [],
329
+ continuation: init.continuation ?? "opaque-provider-state",
330
+ readableState: evidence2(init.readableState, init.confidence),
331
+ ...init.summaryRequest !== undefined ? { summaryRequest: evidence2(init.summaryRequest, init.confidence) } : {},
332
+ ...init.domain !== undefined ? { continuationDomain: evidence2(init.domain, init.confidence) } : {}
333
+ };
334
+ }
335
+ function fixtureProvider(init) {
336
+ return {
337
+ id: init.id,
338
+ displayName: init.id,
339
+ protocols: ["openai-responses"],
340
+ authKinds: ["api-key"],
341
+ defaultEndpoints: { base: init.baseUrl ?? "https://example.invalid/v1/responses" },
342
+ modelDiscovery: "none",
343
+ liveCatalogAuthority: "partial",
344
+ adapterId: init.adapterId ?? `${init.id}-adapter`,
345
+ family: init.family ?? "openai",
346
+ upstream: { project: "winter", commit: "", sourcePaths: [] },
347
+ risk: { class: "approved", reasons: [] },
348
+ scope: "llm",
349
+ pricingBasis: "token",
350
+ admission: { basis: "api-key", citation: "fixture:continuity", tier: "local" }
351
+ };
352
+ }
353
+ function fixtureCatalog(providers, models) {
354
+ return {
355
+ schemaVersion: 2,
356
+ families: [],
357
+ catalogVersion: "0.0.0-continuity-fixture",
358
+ upstream: { tag: "", tagObject: "", commit: "", extractorVersion: "", overlayVersion: "" },
359
+ providers,
360
+ models
361
+ };
362
+ }
363
+ function scriptedAdapter(init) {
364
+ const requests = [];
365
+ return {
366
+ id: init.id,
367
+ version: "0.0.0-fixture",
368
+ family: init.family ?? "openai",
369
+ protocol: "openai-responses",
370
+ requests,
371
+ async validateCredential() {
372
+ return { ok: true };
373
+ },
374
+ async listModels() {
375
+ return { models: [], partial: false, cached: false, warnings: [] };
376
+ },
377
+ streamTurn(req) {
378
+ requests.push(req);
379
+ const events = init.events ?? [{ type: "done", stopReason: "end_turn" }];
380
+ return async function* () {
381
+ for (const event of events)
382
+ yield event;
383
+ }();
384
+ },
385
+ mapEffort() {
386
+ return { ok: true, value: undefined };
387
+ },
388
+ capabilities(model) {
389
+ const domain = model.reasoning?.continuationDomain?.value;
390
+ return {
391
+ toolCalling: model.toolCalling.value,
392
+ ...domain !== undefined && domain.length > 0 ? { continuationDomain: [...domain].sort()[0] } : {},
393
+ readableState: readableStateOf2(model)
394
+ };
395
+ }
396
+ };
397
+ }
398
+ export {
399
+ AZURE_PREVIEW_API_VERSION2 as AZURE_PREVIEW_API_VERSION,
400
+ BunRequiredError2 as BunRequiredError,
401
+ CODEX2 as CODEX,
402
+ FAST_RETRY,
403
+ GCP_CLOUD_PLATFORM_SCOPE2 as GCP_CLOUD_PLATFORM_SCOPE,
404
+ QuotaManager2 as QuotaManager,
405
+ RS2562 as RS256,
406
+ THINKING_ENABLED_NEEDS_BUDGET2 as THINKING_ENABLED_NEEDS_BUDGET,
407
+ base64Url2 as base64Url,
408
+ base64UrlEncode2 as base64UrlEncode,
409
+ concatFrames,
410
+ converseStreamEvent,
411
+ converseStreamException,
412
+ createServiceAccountTokenSource2 as createServiceAccountTokenSource,
413
+ descriptor,
414
+ encodeEventStreamMessage,
415
+ fixtureCatalog,
416
+ fixtureModel,
417
+ fixtureProvider,
418
+ fixtureReasoning,
419
+ googleCompletionMarker2 as googleCompletionMarker,
420
+ hostHeaders2 as hostHeaders,
421
+ importRs256PrivateKey2 as importRs256PrivateKey,
422
+ parseAuthorization2 as parseAuthorization,
423
+ pkcs8DerFromPem2 as pkcs8DerFromPem,
424
+ scriptedAdapter,
425
+ signRs256Jwt2 as signRs256Jwt,
426
+ startXaiChatFake,
427
+ startXaiOauthFake,
428
+ testContext,
429
+ testDiscoveryContext,
430
+ verifySigV4,
431
+ vertexModelPath2 as vertexModelPath
432
+ };