@apifuse/provider-sdk 2.2.0-beta.59 → 2.2.0-beta.61
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/AUTHORING.md +33 -16
- package/CHANGELOG.md +8 -0
- package/bin/apifuse-dev.ts +7 -8
- package/bin/apifuse-pack-types.ts +22 -0
- package/bin/apifuse-perf.ts +45 -10
- package/bin/apifuse-record.ts +6 -8
- package/bin/apifuse-submit-check.ts +2 -2
- package/dist/config/loader.js +13 -12
- package/dist/define.d.ts +3 -2
- package/dist/define.js +1 -1
- package/dist/dev.js +3 -1
- package/dist/engine.d.ts +7 -6
- package/dist/engine.js +6 -6
- package/dist/error-resolution.js +21 -4
- package/dist/errors.d.ts +3 -0
- package/dist/errors.js +9 -0
- package/dist/handle-meta.d.ts +39 -0
- package/dist/handle-meta.js +29 -0
- package/dist/handle.d.ts +187 -0
- package/dist/handle.js +254 -0
- package/dist/i18n/catalog.js +21 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -3
- package/dist/lint.d.ts +3 -0
- package/dist/lint.js +388 -62
- package/dist/provider.d.ts +4 -4
- package/dist/provider.js +3 -3
- package/dist/runtime/browser.js +2 -1
- package/dist/runtime/cache.js +3 -2
- package/dist/runtime/diagnostic-env-values.d.ts +5 -0
- package/dist/runtime/diagnostic-env-values.js +57 -0
- package/dist/runtime/diagnostic-env.d.ts +11 -0
- package/dist/runtime/diagnostic-env.js +35 -0
- package/dist/runtime/diagnostic-redactor.d.ts +49 -0
- package/dist/runtime/diagnostic-redactor.js +569 -0
- package/dist/runtime/egress-lease.d.ts +2 -0
- package/dist/runtime/egress-lease.js +4 -1
- package/dist/runtime/env.js +2 -1
- package/dist/runtime/handle-wordlist.d.ts +43 -0
- package/dist/runtime/{choice-wordlist.js → handle-wordlist.js} +127 -9
- package/dist/runtime/handle.d.ts +71 -0
- package/dist/runtime/handle.js +895 -0
- package/dist/runtime/instrumentation.js +3 -0
- package/dist/runtime/native-network.d.ts +10 -1
- package/dist/runtime/native-network.js +230 -29
- package/dist/runtime/native-telemetry.d.ts +142 -0
- package/dist/runtime/native-telemetry.js +231 -0
- package/dist/runtime/ocr.js +2 -1
- package/dist/runtime/otlp.js +5 -4
- package/dist/runtime/proxy-nodemaven.js +3 -2
- package/dist/runtime/request-options.d.ts +7 -0
- package/dist/runtime/request-options.js +62 -22
- package/dist/runtime/resolver-vendors/browser.js +0 -1
- package/dist/runtime/resolver.js +3 -2
- package/dist/runtime/state.d.ts +4 -1
- package/dist/runtime/state.js +32 -17
- package/dist/runtime/stt.js +3 -2
- package/dist/runtime/trace.d.ts +5 -0
- package/dist/runtime/trace.js +115 -20
- package/dist/schema.d.ts +11 -0
- package/dist/schema.js +56 -2
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/self-test-redaction.js +8 -33
- package/dist/server/sensitive-values.d.ts +26 -0
- package/dist/server/sensitive-values.js +128 -0
- package/dist/server/serve-implementation.d.ts +4 -11
- package/dist/server/serve-implementation.js +305 -96
- package/dist/server/trace-output.d.ts +2 -1
- package/dist/server/trace-output.js +46 -14
- package/dist/testing/run.js +10 -7
- package/dist/trace-sanitization.d.ts +4 -3
- package/dist/trace-sanitization.js +45 -22
- package/dist/types.d.ts +4 -107
- package/package.json +2 -1
- package/src/config/loader.ts +13 -12
- package/src/define.ts +4 -3
- package/src/dev.ts +3 -1
- package/src/engine.ts +8 -8
- package/src/error-resolution.ts +21 -4
- package/src/errors.ts +13 -0
- package/src/handle-meta.ts +58 -0
- package/src/handle.ts +529 -0
- package/src/i18n/catalog.ts +23 -1
- package/src/index.ts +28 -13
- package/src/lint.ts +456 -71
- package/src/provider.ts +10 -20
- package/src/runtime/browser.ts +2 -1
- package/src/runtime/cache.ts +3 -2
- package/src/runtime/diagnostic-env-values.ts +56 -0
- package/src/runtime/diagnostic-env.ts +55 -0
- package/src/runtime/diagnostic-redactor.ts +662 -0
- package/src/runtime/egress-lease.ts +6 -1
- package/src/runtime/env.ts +2 -1
- package/src/runtime/{choice-wordlist.ts → handle-wordlist.ts} +130 -9
- package/src/runtime/handle.ts +1162 -0
- package/src/runtime/instrumentation.ts +3 -0
- package/src/runtime/native-network.ts +281 -33
- package/src/runtime/native-telemetry.ts +366 -0
- package/src/runtime/ocr.ts +2 -1
- package/src/runtime/otlp.ts +5 -4
- package/src/runtime/proxy-nodemaven.ts +3 -2
- package/src/runtime/request-options.ts +76 -28
- package/src/runtime/resolver-vendors/browser.ts +0 -1
- package/src/runtime/resolver.ts +3 -2
- package/src/runtime/state.ts +44 -16
- package/src/runtime/stt.ts +3 -2
- package/src/runtime/trace.ts +168 -26
- package/src/schema.ts +63 -2
- package/src/server/index.ts +17 -0
- package/src/server/self-test-redaction.ts +10 -40
- package/src/server/sensitive-values.ts +197 -0
- package/src/server/serve-implementation.ts +388 -128
- package/src/server/trace-output.ts +77 -17
- package/src/testing/run.ts +11 -7
- package/src/trace-sanitization.ts +70 -23
- package/src/types.ts +4 -137
- package/dist/choice-token.d.ts +0 -24
- package/dist/choice-token.js +0 -74
- package/dist/runtime/choice-wordlist.d.ts +0 -9
- package/dist/runtime/choice.d.ts +0 -27
- package/dist/runtime/choice.js +0 -801
- package/src/choice-token.ts +0 -165
- package/src/runtime/choice.ts +0 -1197
package/AUTHORING.md
CHANGED
|
@@ -41,9 +41,10 @@ rounds — weak models drop or corrupt it. Split the operation into a
|
|
|
41
41
|
|
|
42
42
|
- The prepare operation is non-destructive. A start call takes only the
|
|
43
43
|
scalar intent fields; every response returns a fresh `attempt_token`
|
|
44
|
-
referencing a server-side record (`ctx.
|
|
45
|
-
`
|
|
46
|
-
calls take `attempt_token` plus only the
|
|
44
|
+
referencing a server-side record (a `ctx.handle` draft kind from
|
|
45
|
+
`defineDraft`, declared on the schema with `kind.field()`) that stores
|
|
46
|
+
every settled decision. Continue calls take `attempt_token` plus only the
|
|
47
|
+
NEW answers.
|
|
47
48
|
- `needs_input` rounds list only the still-pending selections; settled
|
|
48
49
|
decisions may ride along in a display-only field but are never re-sent.
|
|
49
50
|
- When nothing is pending, the prepare operation returns `status: "ready"`
|
|
@@ -55,15 +56,14 @@ rounds — weak models drop or corrupt it. Split the operation into a
|
|
|
55
56
|
for what the user picked.
|
|
56
57
|
- Expired or foreign tokens fail factually (nothing happened; start a new
|
|
57
58
|
attempt with the scalar fields) — no answer salvage from a dead token.
|
|
58
|
-
- **
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
interrupted confirm stays retryable.
|
|
59
|
+
- **Commit is one-shot with replay; providers no longer hand-roll dedup.**
|
|
60
|
+
`ctx.handle.read` and `ctx.handle.update` never consume a draft, so a
|
|
61
|
+
confirm handler must execute upstream work through `ctx.handle.commit`. It
|
|
62
|
+
runs the work once, stores the result under the handle, and a repeated
|
|
63
|
+
confirm returns `{ status: "replayed", result }` without touching upstream.
|
|
64
|
+
A failing upstream call restores the draft to `active`, so an interrupted
|
|
65
|
+
confirm stays retryable; later prepare rounds on a committed draft fail
|
|
66
|
+
factually with `HANDLE_COMMITTED`.
|
|
67
67
|
|
|
68
68
|
The invariant behind all of it: complex flow state is the system's job, not
|
|
69
69
|
the model's. The model carries exactly one opaque key between calls.
|
|
@@ -114,8 +114,10 @@ descriptionKey: "operations.realtimeWeather.description",
|
|
|
114
114
|
### Capability declarations
|
|
115
115
|
|
|
116
116
|
Declare each capability used by provider operations. Capabilities without
|
|
117
|
-
configuration use a bare object, for example `http: {}`, `
|
|
118
|
-
`cache: {}`. `
|
|
117
|
+
configuration use a bare object, for example `http: {}`, `state: {}`, or
|
|
118
|
+
`cache: {}`. `handle` is the exception: it takes an array of kinds
|
|
119
|
+
(`handle: [WaitingDraft]`) and requires `state: {}` alongside it. `trace` is
|
|
120
|
+
ambient and must not be declared: every operation
|
|
119
121
|
context receives it. `allowedHosts`, `proxy`, `secrets`, and `context` declare
|
|
120
122
|
policy or metadata only; they do not create context members and are not
|
|
121
123
|
capability bindings.
|
|
@@ -132,8 +134,7 @@ policy intent only.
|
|
|
132
134
|
|
|
133
135
|
Hosted runtime settings are engine-owned as well: every `APIFUSE__CDP_POOL__*`
|
|
134
136
|
variable, the Cloudflare OCR/STT tokens and account identifier,
|
|
135
|
-
`APIFUSE__OCR__API_KEY`, `APIFUSE__CACHE__KEY_PEPPER
|
|
136
|
-
`APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET`. `defineProvider`
|
|
137
|
+
`APIFUSE__OCR__API_KEY`, and `APIFUSE__CACHE__KEY_PEPPER`. `defineProvider`
|
|
137
138
|
rejects them in `secrets`; the engine reads them from its own environment.
|
|
138
139
|
|
|
139
140
|
### Factored operations
|
|
@@ -226,6 +227,22 @@ const utcInput = resolveHealthCheckInputDateTokens({ date: "+45d" }, new Date(),
|
|
|
226
227
|
Do not re-resolve a health assertion's dates in UTC when its case input used the
|
|
227
228
|
default KST calendar.
|
|
228
229
|
|
|
230
|
+
### Sensitive vs public fields
|
|
231
|
+
|
|
232
|
+
The platform fixture-privacy ratchet flags name-, phone-, and address-shaped keys
|
|
233
|
+
unless the schema at that path declares them one way or the other. Declare every hit:
|
|
234
|
+
|
|
235
|
+
- `sensitive(schema, kind)` / `fields.*()` — anything about a person: user, profile,
|
|
236
|
+
passenger, driver, or member names, emails, member ids, personal phone numbers.
|
|
237
|
+
Emits `x-apifuse-sensitive: true`; the value is redacted in published artifacts.
|
|
238
|
+
- `publicField(schema)` — reviewed public data: business, shop, product, artist, or
|
|
239
|
+
facility names, hospital/hotel/station phones, timezone names. Emits
|
|
240
|
+
`x-apifuse-sensitive: false`; nothing is redacted. It is a review verdict, not a mute.
|
|
241
|
+
Credential-shaped keys (token, password, apiKey, …) cannot be declared public.
|
|
242
|
+
|
|
243
|
+
Apply either helper to the leaf, before `.optional()`/`.nullable()`/`.default()`;
|
|
244
|
+
`publicField()` over a wrapper that hides a `sensitive()` leaf throws at definition time.
|
|
245
|
+
|
|
229
246
|
### Real-handler E2E in standard tests
|
|
230
247
|
|
|
231
248
|
`runStandardTests(provider)` validates declarations and fixtures but reports a
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @apifuse/provider-sdk Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.0-beta.61
|
|
4
|
+
|
|
5
|
+
- Release candidate for main commit 8ba435285f6f448bb1b8d01b1d65d2e1a4b42aaa.
|
|
6
|
+
|
|
7
|
+
## 2.2.0-beta.60
|
|
8
|
+
|
|
9
|
+
- Release candidate for main commit 5f417c6282b3a4d92bf31c8258ba913b5e53dc8b.
|
|
10
|
+
|
|
3
11
|
## 2.2.0-beta.59
|
|
4
12
|
|
|
5
13
|
- Release candidate for main commit 55ae556fcf33e28a228c2d54ce76e7afa41e5dc7.
|
package/bin/apifuse-dev.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
import { readDiagnosticEnv } from "../src/runtime/diagnostic-env.js";
|
|
2
3
|
|
|
3
4
|
import { existsSync } from "node:fs";
|
|
4
5
|
import { dirname, relative, resolve } from "node:path";
|
|
5
6
|
import {
|
|
6
7
|
createCredentialContext,
|
|
7
|
-
createEnvContext,
|
|
8
8
|
createHttpClient,
|
|
9
9
|
createInProcessProviderEngine,
|
|
10
10
|
createOcrClientFromEnv,
|
|
11
11
|
createProviderCache,
|
|
12
|
-
|
|
12
|
+
createHandleContext,
|
|
13
13
|
createProviderEnvironment,
|
|
14
14
|
createUnsupportedResolverClient,
|
|
15
15
|
createSttClientFromEnv,
|
|
16
|
-
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
17
16
|
readEngineProxyCredentials,
|
|
18
17
|
type ProviderDefinition,
|
|
19
18
|
type ProviderEngineBindingCandidates,
|
|
@@ -87,8 +86,7 @@ export function createProviderContext(provider: ProviderDefinition): {
|
|
|
87
86
|
process.env,
|
|
88
87
|
provider.secrets?.map((secret) => secret.name) ?? [],
|
|
89
88
|
);
|
|
90
|
-
const providerEnv = { get: (key: string) =>
|
|
91
|
-
const engineEnv = createEnvContext([PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV]);
|
|
89
|
+
const providerEnv = { get: (key: string) => readDiagnosticEnv(key, providerEnvironment) };
|
|
92
90
|
const engineCredentials = readEngineProxyCredentials();
|
|
93
91
|
const credential = createCredentialContext();
|
|
94
92
|
const state = createMemoryProviderRuntimeState();
|
|
@@ -130,10 +128,11 @@ export function createProviderContext(provider: ProviderDefinition): {
|
|
|
130
128
|
: {}),
|
|
131
129
|
})
|
|
132
130
|
: createUnsupportedResolverClient("Provider does not declare resolver capability"),
|
|
133
|
-
|
|
131
|
+
handle: createHandleContext({
|
|
134
132
|
providerId: provider.id,
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
// Local dev is a single-user session: one stable connection scope so
|
|
134
|
+
// bound handles (drafts, default cursors) work exactly as in production.
|
|
135
|
+
request: { headers: {}, connectionId: "local-dev" },
|
|
137
136
|
state,
|
|
138
137
|
}),
|
|
139
138
|
};
|
|
@@ -450,6 +450,28 @@ const NEGATIVE_CONTROLS = [
|
|
|
450
450
|
"",
|
|
451
451
|
].join("\n"),
|
|
452
452
|
},
|
|
453
|
+
{
|
|
454
|
+
filename: "negative-control-native-telemetry-description.ts",
|
|
455
|
+
expectedCode: "TS2322",
|
|
456
|
+
description: "native gateway telemetry rejects free-string diagnostic fields",
|
|
457
|
+
source: [
|
|
458
|
+
'import type { GatewayIngestible, NativeTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
|
|
459
|
+
"type UnsafeHeader = NativeTelemetryHeaderPayload & { vendorErrorMessage: string };",
|
|
460
|
+
"declare const header: NativeTelemetryHeaderPayload;",
|
|
461
|
+
'export const mustNotCompile: GatewayIngestible<UnsafeHeader> = { ...header, vendorErrorMessage: "free text stays log-only" };',
|
|
462
|
+
].join("\n"),
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
filename: "positive-control-native-telemetry-contributor.ts",
|
|
466
|
+
expectedCode: "",
|
|
467
|
+
description: "native telemetry contributor satisfies the gateway-ingestible contract",
|
|
468
|
+
source: [
|
|
469
|
+
'import { NativeTelemetryCollector, type GatewayIngestible, type NativeTelemetryHeaderPayload, type NativeTelemetryLogPayload, type TelemetryContributor } from "@apifuse/provider-sdk";',
|
|
470
|
+
"export const native: TelemetryContributor<NativeTelemetryLogPayload, NativeTelemetryHeaderPayload> = new NativeTelemetryCollector();",
|
|
471
|
+
"declare const header: NativeTelemetryHeaderPayload;",
|
|
472
|
+
"export const ingestible: GatewayIngestible<NativeTelemetryHeaderPayload> = header;",
|
|
473
|
+
].join("\n"),
|
|
474
|
+
},
|
|
453
475
|
] as const;
|
|
454
476
|
|
|
455
477
|
const tempRoot = mkdtempSync(join(tmpdir(), "apifuse-provider-sdk-pack-types-"));
|
package/bin/apifuse-perf.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @ts-nocheck
|
|
3
|
+
import { readDiagnosticEnv } from "../src/runtime/diagnostic-env.js";
|
|
3
4
|
|
|
4
5
|
import { existsSync } from "node:fs";
|
|
5
6
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
type ApiFuseConfig,
|
|
11
12
|
createBypassProviderCache,
|
|
12
13
|
createHttpClient,
|
|
13
|
-
|
|
14
|
+
createHandleContext,
|
|
14
15
|
createSttClientFromEnv,
|
|
15
16
|
executeOperation,
|
|
16
17
|
getProviderBaseUrl,
|
|
@@ -25,11 +26,20 @@ import {
|
|
|
25
26
|
type StealthResponse,
|
|
26
27
|
wrapWithInstrumentation,
|
|
27
28
|
} from "../src/index.js";
|
|
29
|
+
import {
|
|
30
|
+
bindDiagnosticSensitiveRegistry,
|
|
31
|
+
type CompiledDiagnosticSensitiveValues,
|
|
32
|
+
compileProcessDiagnosticSensitiveValues,
|
|
33
|
+
createDiagnosticRedactor,
|
|
34
|
+
redactDiagnosticText,
|
|
35
|
+
} from "../src/runtime/diagnostic-redactor.js";
|
|
28
36
|
import { computeStats, groupSpansByName, type PerfStats } from "../src/runtime/perf.js";
|
|
29
37
|
import { createMemoryProviderRuntimeState } from "../src/runtime/state.js";
|
|
30
38
|
import { createStealthClient } from "../src/runtime/stealth.js";
|
|
31
39
|
import { createTraceContext, resolveTraceContextOptions } from "../src/runtime/trace.js";
|
|
32
40
|
import { renderWaterfall } from "../src/runtime/waterfall.js";
|
|
41
|
+
import { collectStaticDiagnosticSensitiveValues } from "../src/server/sensitive-values.js";
|
|
42
|
+
import { sanitizeSpanForOutput } from "../src/trace-sanitization.js";
|
|
33
43
|
import type { BrowserClient } from "../src/types.js";
|
|
34
44
|
|
|
35
45
|
type CliArgs = {
|
|
@@ -100,6 +110,9 @@ export async function main() {
|
|
|
100
110
|
const providerDirectory = resolve(process.cwd(), args.providerPath);
|
|
101
111
|
const providerEntry = resolveProviderEntry(providerDirectory);
|
|
102
112
|
const provider = await loadProvider(providerEntry);
|
|
113
|
+
const staticSensitiveValues = compileProcessDiagnosticSensitiveValues(
|
|
114
|
+
collectStaticDiagnosticSensitiveValues(provider),
|
|
115
|
+
);
|
|
103
116
|
const providerId = basename(providerDirectory);
|
|
104
117
|
const config = await loadApiFuseConfig(process.cwd());
|
|
105
118
|
const operation = getOperation(provider, args.operation);
|
|
@@ -119,6 +132,7 @@ export async function main() {
|
|
|
119
132
|
operationName: args.operation,
|
|
120
133
|
outputSchema,
|
|
121
134
|
proxyEnabled: false,
|
|
135
|
+
staticSensitiveValues,
|
|
122
136
|
});
|
|
123
137
|
|
|
124
138
|
let proxySuite: ProfileSuite | undefined;
|
|
@@ -135,6 +149,7 @@ export async function main() {
|
|
|
135
149
|
operationName: args.operation,
|
|
136
150
|
outputSchema,
|
|
137
151
|
proxyEnabled: true,
|
|
152
|
+
staticSensitiveValues,
|
|
138
153
|
});
|
|
139
154
|
}
|
|
140
155
|
|
|
@@ -170,8 +185,8 @@ export async function main() {
|
|
|
170
185
|
runs: args.runs,
|
|
171
186
|
warmup: args.warmup,
|
|
172
187
|
concurrency: args.concurrency,
|
|
173
|
-
direct: directSuite,
|
|
174
|
-
proxy: proxySuite,
|
|
188
|
+
direct: sanitizeProfileSuiteForExport(directSuite),
|
|
189
|
+
proxy: proxySuite ? sanitizeProfileSuiteForExport(proxySuite) : undefined,
|
|
175
190
|
flamePath,
|
|
176
191
|
});
|
|
177
192
|
console.log(`Exported JSON: ${resolve(process.cwd(), args.exportPath)}`);
|
|
@@ -480,6 +495,7 @@ async function runProfileSuite(options: {
|
|
|
480
495
|
operationName: string;
|
|
481
496
|
outputSchema: { parse(input: unknown): unknown };
|
|
482
497
|
proxyEnabled: boolean;
|
|
498
|
+
staticSensitiveValues: CompiledDiagnosticSensitiveValues;
|
|
483
499
|
}): Promise<ProfileSuite> {
|
|
484
500
|
for (let index = 0; index < options.args.warmup; index += 1) {
|
|
485
501
|
await profileRun({
|
|
@@ -492,6 +508,7 @@ async function runProfileSuite(options: {
|
|
|
492
508
|
operationName: options.operationName,
|
|
493
509
|
outputSchema: options.outputSchema,
|
|
494
510
|
proxyEnabled: options.proxyEnabled,
|
|
511
|
+
staticSensitiveValues: options.staticSensitiveValues,
|
|
495
512
|
});
|
|
496
513
|
}
|
|
497
514
|
|
|
@@ -509,6 +526,7 @@ async function runProfileSuite(options: {
|
|
|
509
526
|
operationName: options.operationName,
|
|
510
527
|
outputSchema: options.outputSchema,
|
|
511
528
|
proxyEnabled: options.proxyEnabled,
|
|
529
|
+
staticSensitiveValues: options.staticSensitiveValues,
|
|
512
530
|
}),
|
|
513
531
|
);
|
|
514
532
|
runs.push(...(await Promise.all(batch)));
|
|
@@ -545,6 +563,7 @@ async function profileRun(options: {
|
|
|
545
563
|
operationName: string;
|
|
546
564
|
outputSchema: { parse(input: unknown): unknown };
|
|
547
565
|
proxyEnabled: boolean;
|
|
566
|
+
staticSensitiveValues: CompiledDiagnosticSensitiveValues;
|
|
548
567
|
}): Promise<RunResult> {
|
|
549
568
|
try {
|
|
550
569
|
return await executeProfileRun({ ...options, forceFixtureReplay: false });
|
|
@@ -576,9 +595,16 @@ async function executeProfileRun(options: {
|
|
|
576
595
|
operationName: string;
|
|
577
596
|
outputSchema: { parse(input: unknown): unknown };
|
|
578
597
|
proxyEnabled: boolean;
|
|
598
|
+
staticSensitiveValues: CompiledDiagnosticSensitiveValues;
|
|
579
599
|
}): Promise<RunResult> {
|
|
580
600
|
const _operation = getOperation(options.provider, options.operationName);
|
|
581
|
-
const
|
|
601
|
+
const sensitiveRegistry = createDiagnosticRedactor([], options.staticSensitiveValues);
|
|
602
|
+
const redact = (text: string) => redactDiagnosticText(text, sensitiveRegistry.redact);
|
|
603
|
+
const traceContext = createTraceContext({
|
|
604
|
+
...resolveTraceContextOptions(options.config.trace),
|
|
605
|
+
redact,
|
|
606
|
+
});
|
|
607
|
+
bindDiagnosticSensitiveRegistry(traceContext, sensitiveRegistry);
|
|
582
608
|
const baseContext = createBaseContext({
|
|
583
609
|
config: options.config,
|
|
584
610
|
provider: options.provider,
|
|
@@ -650,7 +676,7 @@ function createBaseContext(options: {
|
|
|
650
676
|
});
|
|
651
677
|
|
|
652
678
|
const env = {
|
|
653
|
-
get: (key: string) =>
|
|
679
|
+
get: (key: string) => readDiagnosticEnv(key),
|
|
654
680
|
};
|
|
655
681
|
const credential = {
|
|
656
682
|
mode: "none" as const,
|
|
@@ -663,7 +689,7 @@ function createBaseContext(options: {
|
|
|
663
689
|
return {
|
|
664
690
|
env,
|
|
665
691
|
credential,
|
|
666
|
-
request: { headers: {} },
|
|
692
|
+
request: { headers: {}, connectionId: "local-perf" },
|
|
667
693
|
http,
|
|
668
694
|
cache: createBypassProviderCache({ providerId: options.provider.id }),
|
|
669
695
|
state,
|
|
@@ -672,11 +698,9 @@ function createBaseContext(options: {
|
|
|
672
698
|
trace: options.traceContext,
|
|
673
699
|
auth: createAuthStub(),
|
|
674
700
|
stt: createSttClientFromEnv(options.provider.stt),
|
|
675
|
-
|
|
701
|
+
handle: createHandleContext({
|
|
676
702
|
providerId: options.provider.id,
|
|
677
|
-
|
|
678
|
-
request: { headers: {} },
|
|
679
|
-
credential,
|
|
703
|
+
request: { headers: {}, connectionId: "local-perf" },
|
|
680
704
|
state,
|
|
681
705
|
}),
|
|
682
706
|
};
|
|
@@ -925,6 +949,17 @@ function selectRepresentativeRun(runs: RunResult[]): RunResult {
|
|
|
925
949
|
return first;
|
|
926
950
|
}
|
|
927
951
|
|
|
952
|
+
function sanitizeProfileSuiteForExport(suite: ProfileSuite): ProfileSuite {
|
|
953
|
+
// The perf CLI has no server request scope; retain the shared output policy on disk.
|
|
954
|
+
return {
|
|
955
|
+
...suite,
|
|
956
|
+
runs: suite.runs.map((run) => ({
|
|
957
|
+
...run,
|
|
958
|
+
spans: run.spans.map((span) => sanitizeSpanForOutput(span)),
|
|
959
|
+
})),
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
928
963
|
async function writeExport(filePath: string, payload: unknown): Promise<void> {
|
|
929
964
|
const absolutePath = resolve(process.cwd(), filePath);
|
|
930
965
|
await mkdir(dirname(absolutePath), { recursive: true });
|
package/bin/apifuse-record.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
import { readDiagnosticEnv } from "../src/runtime/diagnostic-env.js";
|
|
2
3
|
|
|
3
4
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
4
5
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
createHttpClient,
|
|
11
12
|
createInProcessProviderEngine,
|
|
12
13
|
createOcrClientFromEnv,
|
|
13
|
-
|
|
14
|
+
createHandleContext,
|
|
14
15
|
createProviderEnvironment,
|
|
15
16
|
createSttClientFromEnv,
|
|
16
17
|
createUnsupportedResolverClient,
|
|
@@ -519,8 +520,7 @@ export function createCaptureContext(
|
|
|
519
520
|
process.env,
|
|
520
521
|
provider.secrets?.map((secret) => secret.name) ?? [],
|
|
521
522
|
);
|
|
522
|
-
const env = { get: (key: string) =>
|
|
523
|
-
const engineEnv = { get: (key: string) => process.env[key] };
|
|
523
|
+
const env = { get: (key: string) => readDiagnosticEnv(key, providerEnvironment) };
|
|
524
524
|
const engineCredentials = readEngineProxyCredentials();
|
|
525
525
|
const credential = {
|
|
526
526
|
mode: "none" as const,
|
|
@@ -536,7 +536,7 @@ export function createCaptureContext(
|
|
|
536
536
|
const candidates: ProviderEngineBindingCandidates = {
|
|
537
537
|
env,
|
|
538
538
|
credential,
|
|
539
|
-
request: { headers: {} },
|
|
539
|
+
request: { headers: {}, connectionId: "local-record" },
|
|
540
540
|
http,
|
|
541
541
|
cache,
|
|
542
542
|
state,
|
|
@@ -582,11 +582,9 @@ export function createCaptureContext(
|
|
|
582
582
|
: {}),
|
|
583
583
|
})
|
|
584
584
|
: createUnsupportedResolverClient("Provider does not declare resolver capability"),
|
|
585
|
-
|
|
585
|
+
handle: createHandleContext({
|
|
586
586
|
providerId: provider.id,
|
|
587
|
-
|
|
588
|
-
request: { headers: {} },
|
|
589
|
-
credential,
|
|
587
|
+
request: { headers: {}, connectionId: "local-record" },
|
|
590
588
|
state,
|
|
591
589
|
}),
|
|
592
590
|
};
|
|
@@ -949,11 +949,11 @@ function scoreNoDynamicCode(providerRoot: string): SubmitCheck {
|
|
|
949
949
|
}
|
|
950
950
|
|
|
951
951
|
const REDUNDANT_RUNTIME_GUARD_PATTERNS: readonly RegExp[] = [
|
|
952
|
-
/\bctx\.(?:stealth|http|cache|state|browser|trace|auth|stt|
|
|
952
|
+
/\bctx\.(?:stealth|http|cache|state|browser|trace|auth|stt|handle)\?\./,
|
|
953
953
|
];
|
|
954
954
|
|
|
955
955
|
const SDK_CONTEXT_METHOD_ALIAS_PATTERN =
|
|
956
|
-
/\bconst\s+(\w+)\s*=\s*ctx\.(?:stealth|http|cache|state|browser|trace|auth|stt|
|
|
956
|
+
/\bconst\s+(\w+)\s*=\s*ctx\.(?:stealth|http|cache|state|browser|trace|auth|stt|handle)\.(?:\w+)/;
|
|
957
957
|
|
|
958
958
|
function hasRedundantRuntimeGuard(line: string, remainingLines: readonly string[]): boolean {
|
|
959
959
|
if (REDUNDANT_RUNTIME_GUARD_PATTERNS.some((pattern) => pattern.test(line))) {
|
package/dist/config/loader.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readDiagnosticEnv } from "../runtime/diagnostic-env.js";
|
|
1
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
@@ -63,17 +64,17 @@ const SMARTPROXY_ALLOCATOR_RETRY_BASE_MS = 25;
|
|
|
63
64
|
const SMARTPROXY_EXTRACTION_CACHE_TTL_MS = 15_000;
|
|
64
65
|
const SMARTPROXY_EXTRACTION_SOFT_REFRESH_MS = 10_000;
|
|
65
66
|
function redisUrlFromEnv() {
|
|
66
|
-
return (
|
|
67
|
-
|
|
67
|
+
return (readDiagnosticEnv(PROVIDER_CACHE_REDIS_URL_ENV)?.trim() ||
|
|
68
|
+
readDiagnosticEnv(REDIS_URL_ENV)?.trim() ||
|
|
68
69
|
undefined);
|
|
69
70
|
}
|
|
70
71
|
export function providerCacheRedisUrlFromEnv() {
|
|
71
72
|
return redisUrlFromEnv();
|
|
72
73
|
}
|
|
73
74
|
export function providerStateRedisUrlFromEnv() {
|
|
74
|
-
return (
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
return (readDiagnosticEnv(PROVIDER_STATE_REDIS_URL_ENV)?.trim() ||
|
|
76
|
+
readDiagnosticEnv(PROVIDER_CACHE_REDIS_URL_ENV)?.trim() ||
|
|
77
|
+
readDiagnosticEnv(REDIS_URL_ENV)?.trim() ||
|
|
77
78
|
undefined);
|
|
78
79
|
}
|
|
79
80
|
/** @internal Test-only hook for exercising shared proxy-cache behavior. */
|
|
@@ -407,10 +408,10 @@ export async function resolveWithVendor(vendor, policy, options, context) {
|
|
|
407
408
|
if (vendor === "nodemaven") {
|
|
408
409
|
const startedAt = Date.now();
|
|
409
410
|
const username = (context.credentials === undefined
|
|
410
|
-
?
|
|
411
|
+
? readDiagnosticEnv(NODEMAVEN_USERNAME_ENV)
|
|
411
412
|
: context.credentials[NODEMAVEN_USERNAME_ENV])?.trim();
|
|
412
413
|
const password = (context.credentials === undefined
|
|
413
|
-
?
|
|
414
|
+
? readDiagnosticEnv(NODEMAVEN_PASSWORD_ENV)
|
|
414
415
|
: context.credentials[NODEMAVEN_PASSWORD_ENV])?.trim();
|
|
415
416
|
const filter = context.credentials === undefined
|
|
416
417
|
? process.env[NODEMAVEN_FILTER_ENV]
|
|
@@ -453,7 +454,7 @@ export async function resolveWithVendor(vendor, policy, options, context) {
|
|
|
453
454
|
}
|
|
454
455
|
// smartproxy allocation-style vendor.
|
|
455
456
|
const appKey = (context.credentials === undefined
|
|
456
|
-
?
|
|
457
|
+
? readDiagnosticEnv(SMARTPROXY_APP_KEY_ENV)
|
|
457
458
|
: context.credentials[SMARTPROXY_APP_KEY_ENV])?.trim();
|
|
458
459
|
if (!appKey) {
|
|
459
460
|
// Guarded by vendorHasCredentials; treated as a vendor-internal failure.
|
|
@@ -520,14 +521,14 @@ function envDefaultProvider() {
|
|
|
520
521
|
function vendorHasCredentials(vendor, credentials) {
|
|
521
522
|
if (vendor === "nodemaven") {
|
|
522
523
|
return Boolean((credentials === undefined
|
|
523
|
-
?
|
|
524
|
+
? readDiagnosticEnv(NODEMAVEN_USERNAME_ENV)
|
|
524
525
|
: credentials[NODEMAVEN_USERNAME_ENV])?.trim() &&
|
|
525
526
|
(credentials === undefined
|
|
526
|
-
?
|
|
527
|
+
? readDiagnosticEnv(NODEMAVEN_PASSWORD_ENV)
|
|
527
528
|
: credentials[NODEMAVEN_PASSWORD_ENV])?.trim());
|
|
528
529
|
}
|
|
529
530
|
return Boolean((credentials === undefined
|
|
530
|
-
?
|
|
531
|
+
? readDiagnosticEnv(SMARTPROXY_APP_KEY_ENV)
|
|
531
532
|
: credentials[SMARTPROXY_APP_KEY_ENV])?.trim());
|
|
532
533
|
}
|
|
533
534
|
function missingCredentialEnv(vendor) {
|
|
@@ -1178,7 +1179,7 @@ function markSmartproxyCacheInvalidated(options = {}) {
|
|
|
1178
1179
|
}
|
|
1179
1180
|
const lifetimeMinutes = resolveSmartproxyLifetime(policy);
|
|
1180
1181
|
const appKey = (options.engineCredentials === undefined
|
|
1181
|
-
?
|
|
1182
|
+
? readDiagnosticEnv(SMARTPROXY_APP_KEY_ENV)
|
|
1182
1183
|
: options.engineCredentials[SMARTPROXY_APP_KEY_ENV])?.trim();
|
|
1183
1184
|
if (!appKey)
|
|
1184
1185
|
return undefined;
|
package/dist/define.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { HandleKind } from "./handle.js";
|
|
1
2
|
import type { AuthConfig, BrowserEngine, ContextDeclaration, CredentialDeclaration, HealthJourneyDefinition, HealthJourneySchedule, HealthScheduleRandomization, InferSchemaOutput, NativeProviderConfig, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, ProviderAccessConfig, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderHealthMonitorConfig, ProviderOcrConfig, ProviderProxyConfig, ProviderPublicProfile, ProviderResolverConfig, ProviderReviewed, ProviderRuntimeTarget, ProviderSecretDeclaration, ProviderStreamEvent, ProviderSttConfig, ProviderStealthConfig, SchemaLike, SmsOtpMatcherDefinition } from "./types.js";
|
|
2
3
|
type ProviderImplementationSourceAccess = "official_api" | "private_api" | "browser_flow" | "hybrid";
|
|
3
4
|
type ProviderImplementationCredentialStrategy = "apifuse_managed" | "workspace_secret" | "user_oauth" | "user_session" | "none";
|
|
@@ -70,8 +71,8 @@ export interface ProviderDeclaration {
|
|
|
70
71
|
engine: BrowserEngine;
|
|
71
72
|
};
|
|
72
73
|
auth?: AuthConfig;
|
|
73
|
-
/** Declares the
|
|
74
|
-
|
|
74
|
+
/** Declares the handle kinds this provider issues and accepts (ADR-0012). */
|
|
75
|
+
handle?: readonly HandleKind[];
|
|
75
76
|
reviewed?: ProviderReviewed;
|
|
76
77
|
access?: ProviderAccessConfig;
|
|
77
78
|
/** Declares secret requirements; this does not add a `ctx.secrets` member. */
|
package/dist/define.js
CHANGED
|
@@ -2040,7 +2040,7 @@ function finalizeProvider(config) {
|
|
|
2040
2040
|
resolver: config.resolver,
|
|
2041
2041
|
browser: config.browser,
|
|
2042
2042
|
auth: config.auth,
|
|
2043
|
-
|
|
2043
|
+
handle: config.handle,
|
|
2044
2044
|
reviewed: config.reviewed,
|
|
2045
2045
|
access: config.access,
|
|
2046
2046
|
secrets: config.secrets,
|
package/dist/dev.js
CHANGED
|
@@ -3,7 +3,9 @@ export function createDevServer(provider, options) {
|
|
|
3
3
|
const port = options?.port ?? 3900;
|
|
4
4
|
return {
|
|
5
5
|
start: () => {
|
|
6
|
-
|
|
6
|
+
// Local development has no Redis by default; handles (ADR-0012) need a
|
|
7
|
+
// state backend, so fall back to memory state when none is configured.
|
|
8
|
+
void serve(provider, { port, engine: options?.engine, allowMemoryStateFallback: true });
|
|
7
9
|
console.log(`[apifuse dev] ${provider.id}@${provider.version} running at http://localhost:${port}`);
|
|
8
10
|
console.log(`[apifuse dev] Operations: ${Object.keys(provider.operations).join(", ")}`);
|
|
9
11
|
console.log(`[apifuse dev] Health: http://localhost:${port}/health`);
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HandleContext } from "./handle.js";
|
|
2
|
+
import type { AuthContext, BrowserClient, CredentialContext, EnvContext, HttpClient, NativeContext, OcrContext, ProviderCache, ProviderContext, ProviderDefinition, ProviderFilesContext, ProviderRequestContext, ProviderRuntimeState, ResolverContext, StealthClient, SttContext, TraceContext } from "./types.js";
|
|
2
3
|
/** Versioned envelope protocol used by out-of-process engine transports. */
|
|
3
4
|
export declare const PROVIDER_ENGINE_PROTOCOL_VERSION: "provider-engine.v1";
|
|
4
5
|
/** Credential names owned by the engine and forbidden in provider declarations. */
|
|
@@ -21,11 +22,11 @@ export declare function isEngineOwnedResolverCredentialName(name: string): boole
|
|
|
21
22
|
export declare const ENGINE_OWNED_TELEMETRY_ENV_NAMES: readonly ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "OTEL_EXPORTER_OTLP_ENDPOINT", "OTEL_EXPORTER_OTLP_TRACES_HEADERS", "OTEL_EXPORTER_OTLP_HEADERS", "OTEL_SERVICE_NAME", "OTEL_RESOURCE_ATTRIBUTES"];
|
|
22
23
|
export declare function isEngineOwnedTelemetryEnvName(name: string): boolean;
|
|
23
24
|
/**
|
|
24
|
-
* Hosted runtime settings the engine reads for OCR, STT, cache keying,
|
|
25
|
-
*
|
|
25
|
+
* Hosted runtime settings the engine reads for OCR, STT, cache keying, and
|
|
26
|
+
* the CDP pool. Providers never own them: declarations are rejected
|
|
26
27
|
* and projections drop them, like the vendor credentials above.
|
|
27
28
|
*/
|
|
28
|
-
export declare const ENGINE_OWNED_RUNTIME_ENV_NAMES: readonly ["APIFUSE__STT__CLOUDFLARE_API_TOKEN", "APIFUSE__OCR__CLOUDFLARE_API_TOKEN", "APIFUSE__OCR__API_KEY", "APIFUSE__CLOUDFLARE__ACCOUNT_ID", "APIFUSE__CACHE__KEY_PEPPER"
|
|
29
|
+
export declare const ENGINE_OWNED_RUNTIME_ENV_NAMES: readonly ["APIFUSE__STT__CLOUDFLARE_API_TOKEN", "APIFUSE__OCR__CLOUDFLARE_API_TOKEN", "APIFUSE__OCR__API_KEY", "APIFUSE__CLOUDFLARE__ACCOUNT_ID", "APIFUSE__CACHE__KEY_PEPPER"];
|
|
29
30
|
export declare function isEngineOwnedRuntimeEnvName(name: string): boolean;
|
|
30
31
|
/** Every environment name the engine owns: rejected in declarations and filtered from provider projections. */
|
|
31
32
|
export declare function isEngineOwnedEnvName(name: string): boolean;
|
|
@@ -70,14 +71,14 @@ export interface ProviderEngineCapabilitySurface {
|
|
|
70
71
|
export interface ProviderEngineResidentSurface {
|
|
71
72
|
readonly native: NativeContext;
|
|
72
73
|
}
|
|
73
|
-
export declare const PROVIDER_CAPABILITY_KEYS: readonly ["env", "credential", "http", "files", "native", "cache", "state", "stealth", "browser", "auth", "ocr", "stt", "resolver", "
|
|
74
|
+
export declare const PROVIDER_CAPABILITY_KEYS: readonly ["env", "credential", "http", "files", "native", "cache", "state", "stealth", "browser", "auth", "ocr", "stt", "resolver", "handle"];
|
|
74
75
|
export type ProviderCapabilityKey = (typeof PROVIDER_CAPABILITY_KEYS)[number];
|
|
75
76
|
export type ProviderEngineBindingCandidates = Partial<ProviderEngineCapabilitySurface & ProviderEngineResidentSurface & {
|
|
76
77
|
readonly env: EnvContext;
|
|
77
78
|
readonly credential: CredentialContext;
|
|
78
79
|
readonly files: ProviderFilesContext;
|
|
79
80
|
readonly auth: AuthContext;
|
|
80
|
-
readonly
|
|
81
|
+
readonly handle: HandleContext;
|
|
81
82
|
}> & {
|
|
82
83
|
readonly request?: ProviderRequestContext;
|
|
83
84
|
readonly trace: TraceContext;
|
package/dist/engine.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readDiagnosticEnv } from "./runtime/diagnostic-env.js";
|
|
1
2
|
import { ProviderError } from "./errors.js";
|
|
2
3
|
import { APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__HYPERSOLUTIONS__API_KEY, } from "./runtime/resolver-config.js";
|
|
3
4
|
import { OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS, OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME, } from "./runtime/otlp.js";
|
|
@@ -68,8 +69,8 @@ function isEngineOwnedEngineEnvName(name) {
|
|
|
68
69
|
return canonicalEnvName(name).startsWith("APIFUSE__ENGINE__");
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
|
-
* Hosted runtime settings the engine reads for OCR, STT, cache keying,
|
|
72
|
-
*
|
|
72
|
+
* Hosted runtime settings the engine reads for OCR, STT, cache keying, and
|
|
73
|
+
* the CDP pool. Providers never own them: declarations are rejected
|
|
73
74
|
* and projections drop them, like the vendor credentials above.
|
|
74
75
|
*/
|
|
75
76
|
export const ENGINE_OWNED_RUNTIME_ENV_NAMES = [
|
|
@@ -78,7 +79,6 @@ export const ENGINE_OWNED_RUNTIME_ENV_NAMES = [
|
|
|
78
79
|
"APIFUSE__OCR__API_KEY",
|
|
79
80
|
"APIFUSE__CLOUDFLARE__ACCOUNT_ID",
|
|
80
81
|
"APIFUSE__CACHE__KEY_PEPPER",
|
|
81
|
-
"APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET",
|
|
82
82
|
];
|
|
83
83
|
const ENGINE_OWNED_RUNTIME_ENV_NAME_SET = new Set(ENGINE_OWNED_RUNTIME_ENV_NAMES);
|
|
84
84
|
/** CDP pool settings form a prefix family (`APIFUSE__CDP_POOL__URL` today); the whole prefix is engine-owned. */
|
|
@@ -99,7 +99,7 @@ export function isEngineOwnedEnvName(name) {
|
|
|
99
99
|
/** Capture credentials in the engine host before constructing provider bindings. */
|
|
100
100
|
export function readEngineProxyCredentials(environment = process.env) {
|
|
101
101
|
return Object.fromEntries(ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES.flatMap((name) => {
|
|
102
|
-
const value = environment
|
|
102
|
+
const value = readDiagnosticEnv(name, environment)?.trim();
|
|
103
103
|
return value ? [[name, value]] : [];
|
|
104
104
|
}));
|
|
105
105
|
}
|
|
@@ -108,7 +108,7 @@ export function createProviderEnvironment(environment, declaredNames) {
|
|
|
108
108
|
return Object.fromEntries(declaredNames.flatMap((name) => {
|
|
109
109
|
if (isEngineOwnedEnvName(name))
|
|
110
110
|
return [];
|
|
111
|
-
const value = environment
|
|
111
|
+
const value = readDiagnosticEnv(name, environment);
|
|
112
112
|
return value === undefined ? [] : [[name, value]];
|
|
113
113
|
}));
|
|
114
114
|
}
|
|
@@ -126,7 +126,7 @@ export const PROVIDER_CAPABILITY_KEYS = [
|
|
|
126
126
|
"ocr",
|
|
127
127
|
"stt",
|
|
128
128
|
"resolver",
|
|
129
|
-
"
|
|
129
|
+
"handle",
|
|
130
130
|
];
|
|
131
131
|
const CAPABILITY_KEY_SET = new Set(PROVIDER_CAPABILITY_KEYS);
|
|
132
132
|
function declaresCapability(provider, capability) {
|
package/dist/error-resolution.js
CHANGED
|
@@ -18,10 +18,17 @@ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
|
|
|
18
18
|
"refresh_not_supported",
|
|
19
19
|
"RUNTIME_UNSUPPORTED",
|
|
20
20
|
"PROVIDER_STATE_UNSUPPORTED",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
21
|
+
"HANDLE_INVALID",
|
|
22
|
+
"HANDLE_NOT_FOUND",
|
|
23
|
+
"HANDLE_EXPIRED",
|
|
24
|
+
"HANDLE_KIND_MISMATCH",
|
|
25
|
+
"HANDLE_BUSY",
|
|
26
|
+
"HANDLE_COMMITTED",
|
|
27
|
+
"HANDLE_CONNECTION_REQUIRED",
|
|
28
|
+
"HANDLE_STORAGE_UNAVAILABLE",
|
|
29
|
+
"HANDLE_TOO_LARGE",
|
|
30
|
+
"HANDLE_INVALID_DATA",
|
|
31
|
+
"PICK_NOT_OFFERED",
|
|
25
32
|
"unsupported_stealth_cookie_store_version",
|
|
26
33
|
"provider_secret_error",
|
|
27
34
|
"credential_key_error",
|
|
@@ -125,6 +132,16 @@ export const SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES = new Map([
|
|
|
125
132
|
["EGRESS_LEASE_INVALID", 409],
|
|
126
133
|
["REPLAY_SESSION_MISMATCH", 409],
|
|
127
134
|
["REPLAY_ALREADY_ATTEMPTED", 409],
|
|
135
|
+
// Handles (ADR-0012): only caller-side faults are mapped. Storage,
|
|
136
|
+
// connection-scope, size, and schema faults stay 500 because the provider
|
|
137
|
+
// or host owns them.
|
|
138
|
+
["HANDLE_INVALID", 400],
|
|
139
|
+
["HANDLE_KIND_MISMATCH", 400],
|
|
140
|
+
["PICK_NOT_OFFERED", 400],
|
|
141
|
+
["HANDLE_NOT_FOUND", 404],
|
|
142
|
+
["HANDLE_EXPIRED", 410],
|
|
143
|
+
["HANDLE_COMMITTED", 409],
|
|
144
|
+
["HANDLE_BUSY", 409],
|
|
128
145
|
["UPSTREAM_ERROR", 502],
|
|
129
146
|
["BLOCKED", 502],
|
|
130
147
|
["OCR_UNAVAILABLE", 503],
|