@apifuse/provider-sdk 2.2.0-beta.22 → 2.2.0-beta.24

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 (64) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/bin/apifuse-dev.ts +4 -0
  3. package/bin/apifuse-pack-types.ts +234 -38
  4. package/bin/apifuse-perf.ts +15 -12
  5. package/bin/apifuse-record.ts +4 -0
  6. package/dist/config/loader.d.ts +8 -19
  7. package/dist/config/loader.js +28 -86
  8. package/dist/contract-types.d.ts +1 -0
  9. package/dist/contract.js +2 -0
  10. package/dist/define.d.ts +5 -1
  11. package/dist/define.js +79 -6
  12. package/dist/error-resolution.js +5 -0
  13. package/dist/index.d.ts +4 -2
  14. package/dist/index.js +2 -0
  15. package/dist/provider.d.ts +1 -1
  16. package/dist/runtime/auth-flow.d.ts +2 -1
  17. package/dist/runtime/auth-flow.js +4 -0
  18. package/dist/runtime/browser.js +78 -9
  19. package/dist/runtime/http.js +0 -1
  20. package/dist/runtime/instrumentation.js +26 -1
  21. package/dist/runtime/ocr.d.ts +29 -0
  22. package/dist/runtime/ocr.js +440 -0
  23. package/dist/runtime/resolver-vendors/bindings.d.ts +8 -0
  24. package/dist/runtime/resolver-vendors/bindings.js +15 -0
  25. package/dist/runtime/resolver-vendors/browser.d.ts +24 -0
  26. package/dist/runtime/resolver-vendors/browser.js +287 -0
  27. package/dist/runtime/resolver-vendors/types.d.ts +42 -0
  28. package/dist/runtime/resolver-vendors/types.js +57 -0
  29. package/dist/runtime/resolver.d.ts +39 -0
  30. package/dist/runtime/resolver.js +414 -0
  31. package/dist/runtime/state.d.ts +3 -0
  32. package/dist/runtime/state.js +245 -141
  33. package/dist/runtime/stealth.js +3 -6
  34. package/dist/runtime/stt.js +1 -12
  35. package/dist/runtime/timeout.d.ts +5 -0
  36. package/dist/runtime/timeout.js +12 -0
  37. package/dist/server/serve.d.ts +6 -1
  38. package/dist/server/serve.js +39 -8
  39. package/dist/testing/run.js +10 -0
  40. package/dist/types.d.ts +163 -4
  41. package/package.json +1 -1
  42. package/src/config/loader.ts +35 -111
  43. package/src/contract-types.ts +1 -0
  44. package/src/contract.ts +2 -0
  45. package/src/define.ts +121 -7
  46. package/src/error-resolution.ts +5 -0
  47. package/src/index.ts +45 -1
  48. package/src/provider.ts +1 -0
  49. package/src/runtime/auth-flow.ts +6 -0
  50. package/src/runtime/browser.ts +139 -19
  51. package/src/runtime/http.ts +0 -1
  52. package/src/runtime/instrumentation.ts +36 -2
  53. package/src/runtime/ocr.ts +523 -0
  54. package/src/runtime/resolver-vendors/bindings.ts +31 -0
  55. package/src/runtime/resolver-vendors/browser.ts +420 -0
  56. package/src/runtime/resolver-vendors/types.ts +113 -0
  57. package/src/runtime/resolver.ts +668 -0
  58. package/src/runtime/state.ts +323 -166
  59. package/src/runtime/stealth.ts +3 -6
  60. package/src/runtime/stt.ts +1 -19
  61. package/src/runtime/timeout.ts +18 -0
  62. package/src/server/serve.ts +80 -5
  63. package/src/testing/run.ts +15 -0
  64. package/src/types.ts +188 -4
@@ -221,64 +221,7 @@ function serializeSmartproxyPool(pool) {
221
221
  }
222
222
  function normalizeProxyUrl(url) {
223
223
  const normalized = url?.trim();
224
- return normalized ? applyStickyProxySession(normalized) : undefined;
225
- }
226
- function readPositiveIntegerEnv(name) {
227
- const raw = process.env[name]?.trim();
228
- if (!raw)
229
- return undefined;
230
- if (!/^[1-9]\d*$/.test(raw)) {
231
- throw new Error(`${name} must be a positive integer`);
232
- }
233
- return raw;
234
- }
235
- function applyStickyProxySession(proxyUrl) {
236
- let parsed;
237
- try {
238
- parsed = new URL(proxyUrl);
239
- }
240
- catch {
241
- return proxyUrl;
242
- }
243
- if (!parsed.hostname || !parsed.username || !parsed.password) {
244
- return proxyUrl;
245
- }
246
- // This rewrites sticky-session usernames for a bring-your-own *gateway* URL
247
- // (APIFUSE__PROXY__URL). The `smartproxy` host here means a smartproxy.com /
248
- // Decodo-family gateway that authenticates by username — NOT the
249
- // api.smartproxy.org allocation vendor, whose endpoints are raw ip:port with
250
- // no credentials and therefore return early above.
251
- const host = parsed.hostname.toLowerCase();
252
- if (!host.includes("smartproxy") && !host.includes("decodo")) {
253
- return proxyUrl;
254
- }
255
- const username = decodeURIComponent(parsed.username);
256
- const sessionId = process.env.APIFUSE__PROXY__SESSION_ID?.trim() || "apifuse-shared";
257
- const sessionDuration = readPositiveIntegerEnv("APIFUSE__PROXY__SESSION_DURATION");
258
- const stickyUsername = host.includes("smartproxy")
259
- ? buildSmartproxyUsername(username, sessionId, sessionDuration)
260
- : buildDecodoUsername(username, sessionId, sessionDuration ?? "60");
261
- parsed.username = stickyUsername;
262
- return parsed.toString();
263
- }
264
- function buildSmartproxyUsername(username, sessionId, sessionDuration) {
265
- const parts = username.split("_");
266
- const configuredLife = parts.find((part) => part.startsWith("life-"))?.slice("life-".length);
267
- const baseUsername = parts
268
- .filter((part) => !part.startsWith("session-") && !part.startsWith("life-"))
269
- .join("_");
270
- return `${baseUsername}_session-${sessionId}_life-${sessionDuration ?? configuredLife ?? "60"}`;
271
- }
272
- function buildDecodoUsername(username, sessionId, sessionDuration) {
273
- const withoutSticky = username.replace(/-session-.+-sessionduration-\d+$/, "");
274
- const baseUsername = withoutSticky.startsWith("user-") ? withoutSticky : `user-${withoutSticky}`;
275
- return `${baseUsername}-session-${sessionId}-sessionduration-${sessionDuration}`;
276
- }
277
- function syncProxyEnv(config) {
278
- const configProxyUrl = normalizeProxyUrl(config.proxy?.url);
279
- if (!process.env.APIFUSE__PROXY__URL && configProxyUrl) {
280
- process.env.APIFUSE__PROXY__URL = configProxyUrl;
281
- }
224
+ return normalized || undefined;
282
225
  }
283
226
  export function resolveProxyConfig(options = {}) {
284
227
  const explicitProxyUrl = normalizeProxyUrl(options.proxy);
@@ -293,14 +236,6 @@ export function resolveProxyConfig(options = {}) {
293
236
  if (!legacyProxyRequested) {
294
237
  return { shouldWarn: false };
295
238
  }
296
- const envProxyUrl = normalizeProxyUrl(process.env.APIFUSE__PROXY__URL);
297
- if (envProxyUrl) {
298
- return { shouldWarn: false, url: envProxyUrl };
299
- }
300
- const configuredProxyUrl = normalizeProxyUrl(options.apifuseConfig?.proxy?.url);
301
- if (configuredProxyUrl) {
302
- return { shouldWarn: false, url: configuredProxyUrl };
303
- }
304
239
  return { shouldWarn: true };
305
240
  }
306
241
  export async function resolveProxyConfigAsync(options = {}) {
@@ -317,7 +252,17 @@ export async function resolveProxyConfigAsync(options = {}) {
317
252
  }
318
253
  const chain = resolveVendorChain(policy);
319
254
  if (chain.length === 0) {
320
- // decodo/custom/env-static providers keep the legacy static-URL path.
255
+ const declared = declaredVendorChain(policy);
256
+ const deprecated = declared.filter((vendor) => vendor === "decodo" || vendor === "custom");
257
+ if (policy.mode === "required") {
258
+ const providerIds = declared.length > 0 ? declared.map((vendor) => `"${vendor}"`).join(", ") : "none";
259
+ const deprecatedDetail = deprecated.length > 0
260
+ ? ` Deprecated vendor(s): ${deprecated.map((vendor) => `"${vendor}"`).join(", ")}.`
261
+ : "";
262
+ throw new ProxyResolutionError("PROXY_REQUIRED", `Required proxy policy has no SDK-managed adapter for provider id(s): ${providerIds}.${deprecatedDetail} Use "smartproxy" or "nodemaven".`);
263
+ }
264
+ // Deprecated decodo/custom providers have no SDK-managed adapter. Optional
265
+ // policies preserve the warning-only behavior and may continue directly.
321
266
  return resolveProxyConfig({
322
267
  ...options,
323
268
  upstream: { proxy: true },
@@ -524,18 +469,21 @@ function resolvePolicy(options) {
524
469
  function isRegistryVendor(name) {
525
470
  return name === "smartproxy" || name === "nodemaven";
526
471
  }
472
+ function declaredVendorChain(policy) {
473
+ const declared = policy.providers?.length
474
+ ? policy.providers
475
+ : [policy.provider ?? envDefaultProvider()];
476
+ return declared.filter((vendor) => vendor !== undefined);
477
+ }
527
478
  /**
528
479
  * Ordered list of SDK-native proxy vendors declared by the policy. `providers`
529
480
  * takes precedence over the legacy singular `provider`; the platform default
530
481
  * env is the final fallback. Non-registry names (decodo/custom) are dropped so
531
- * an all-static chain falls through to the legacy env-URL path unchanged.
482
+ * an all-deprecated chain has no managed adapter.
532
483
  */
533
484
  export function resolveVendorChain(policy) {
534
- const declared = policy.providers?.length
535
- ? policy.providers
536
- : [policy.provider ?? envDefaultProvider()];
537
485
  const chain = [];
538
- for (const name of declared) {
486
+ for (const name of declaredVendorChain(policy)) {
539
487
  if (isRegistryVendor(name) && !chain.includes(name)) {
540
488
  chain.push(name);
541
489
  }
@@ -600,9 +548,8 @@ const UNSAFE_TRANSPORT_RETRY_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"
600
548
  * - the method is safe/idempotent — an unsafe request must never be duplicated
601
549
  * across the pool even if some framework default would allow it;
602
550
  * - the policy resolves a non-empty *registry* vendor chain (smartproxy /
603
- * nodemaven). Static vendors (custom / decodo) and credential-less policies
604
- * resolve no allocator pool, so every attempt would hit the same endpoint
605
- * with no possible crossover — they keep the retry budget.
551
+ * nodemaven). Deprecated vendors (custom / decodo) resolve no managed pool,
552
+ * so there is no possible endpoint crossover they keep the retry budget.
606
553
  *
607
554
  * The widened cap is bounded by the chain's true maximum span (sum of each
608
555
  * vendor's max pool size), so a large NodeMaven pool (≤50) stays reachable and
@@ -621,8 +568,8 @@ const UNSAFE_TRANSPORT_RETRY_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"
621
568
  * endpoint each attempt resolves (even a repeated one), so no de-duplication;
622
569
  * - the method is safe/idempotent — an unsafe request is never duplicated;
623
570
  * - the policy resolves a non-empty registry vendor chain (smartproxy /
624
- * nodemaven). Static vendors (custom / decodo) resolve the same URL every
625
- * attempt, so there is nothing to rotate or de-duplicate.
571
+ * nodemaven). Deprecated vendors (custom / decodo) resolve no managed
572
+ * endpoint, so there is nothing to rotate or de-duplicate.
626
573
  */
627
574
  export function policyRotatesTransportVendorChain(input) {
628
575
  if (!input.usesPolicyAllocator || !input.policy || input.explicitRetry) {
@@ -650,9 +597,8 @@ export function resolvePolicyTransportAttemptCap(input) {
650
597
  * A registry vendor chain (smartproxy/nodemaven) resolves a potentially
651
598
  * *different* endpoint per flat attempt index, so a transport retry should
652
599
  * advance across endpoints and de-duplicate once the chain stops yielding new
653
- * ones. Static/custom/decodo policies (empty registry chain) resolve the *same*
654
- * URL every attempt by design retrying that same endpoint is intended, so the
655
- * transport loop must not de-duplicate them.
600
+ * ones. Deprecated custom/decodo policies have an empty registry chain and no
601
+ * managed endpoint, so the transport loop has nothing to rotate or de-duplicate.
656
602
  */
657
603
  export function policyResolvesRegistryVendorChain(policy) {
658
604
  return Boolean(policy) && resolveVendorChain(policy).length > 0;
@@ -1249,16 +1195,12 @@ export async function loadApiFuseConfig(dir = process.cwd()) {
1249
1195
  const tsPath = path.resolve(dir, "apifuse.config.ts");
1250
1196
  if (existsSync(tsPath)) {
1251
1197
  const config = await importConfig(tsPath);
1252
- const resolvedConfig = config ?? {};
1253
- syncProxyEnv(resolvedConfig);
1254
- return resolvedConfig;
1198
+ return config ?? {};
1255
1199
  }
1256
1200
  const jsPath = path.resolve(dir, "apifuse.config.js");
1257
1201
  if (existsSync(jsPath)) {
1258
1202
  const config = await importConfig(jsPath);
1259
- const resolvedConfig = config ?? {};
1260
- syncProxyEnv(resolvedConfig);
1261
- return resolvedConfig;
1203
+ return config ?? {};
1262
1204
  }
1263
1205
  return {};
1264
1206
  }
@@ -11,6 +11,7 @@ export interface ProviderContractSnapshot {
11
11
  readonly allowedHosts?: readonly string[];
12
12
  readonly stealth?: JsonValue;
13
13
  readonly proxy?: JsonValue;
14
+ readonly ocr?: JsonValue;
14
15
  readonly stt?: JsonValue;
15
16
  readonly browser?: JsonValue;
16
17
  readonly auth?: JsonValue;
package/dist/contract.js CHANGED
@@ -7,6 +7,7 @@ export function extractProviderContract(provider) {
7
7
  const auth = extractAuth(provider.auth);
8
8
  const stealth = toJsonValue(provider.stealth);
9
9
  const proxy = toJsonValue(provider.proxy);
10
+ const ocr = toJsonValue(provider.ocr);
10
11
  const stt = toJsonValue(provider.stt);
11
12
  const browser = toJsonValue(provider.browser);
12
13
  const reviewed = toJsonValue(provider.reviewed);
@@ -30,6 +31,7 @@ export function extractProviderContract(provider) {
30
31
  ...(provider.allowedHosts ? { allowedHosts: [...provider.allowedHosts].sort() } : {}),
31
32
  ...(stealth === undefined ? {} : { stealth }),
32
33
  ...(proxy === undefined ? {} : { proxy }),
34
+ ...(ocr === undefined ? {} : { ocr }),
33
35
  ...(stt === undefined ? {} : { stt }),
34
36
  ...(browser === undefined ? {} : { browser }),
35
37
  ...(auth === undefined ? {} : { auth }),
package/dist/define.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AuthConfig, BrowserEngine, ContextDeclaration, CredentialDeclaration, HealthJourneyDefinition, HealthJourneySchedule, HealthScheduleRandomization, InferSchemaOutput, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, NativeProviderConfig, ProviderAccessConfig, ProviderDefinition, ProviderDeploymentOverrides, ProviderHealthMonitorConfig, ProviderProxyConfig, ProviderPublicProfile, ProviderReviewed, ProviderSecretDeclaration, ProviderStreamEvent, ProviderSttConfig, SchemaLike, SmsOtpMatcherDefinition, StealthPlatform } from "./types.js";
1
+ import type { AuthConfig, BrowserEngine, ContextDeclaration, CredentialDeclaration, HealthJourneyDefinition, HealthJourneySchedule, HealthScheduleRandomization, InferSchemaOutput, NativeProviderConfig, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, ProviderAccessConfig, ProviderDefinition, ProviderOcrConfig, ProviderDeploymentOverrides, ProviderHealthMonitorConfig, ProviderProxyConfig, ProviderPublicProfile, ProviderResolverConfig, ProviderReviewed, ProviderSecretDeclaration, ProviderStreamEvent, ProviderSttConfig, SchemaLike, SmsOtpMatcherDefinition, StealthPlatform } from "./types.js";
2
2
  type ProviderImplementationSourceAccess = "official_api" | "private_api" | "browser_flow" | "hybrid";
3
3
  type ProviderImplementationCredentialStrategy = "apifuse_managed" | "workspace_secret" | "user_oauth" | "user_session" | "none";
4
4
  interface ProviderImplementationProfile {
@@ -8,6 +8,8 @@ interface ProviderImplementationProfile {
8
8
  operatorNotes?: string;
9
9
  visibility: "internal" | "operator";
10
10
  }
11
+ export declare const VALID_PROVIDER_RESOLVER_VENDORS: readonly ["browser", "capsolver", "capmonster", "2captcha", "custom"];
12
+ export declare const VALID_PROVIDER_CHALLENGE_KINDS: readonly ["turnstile", "recaptcha_v2", "recaptcha_v3", "hcaptcha", "cloudflare_interstitial", "aws_waf"];
11
13
  type ProviderOperation = OperationDefinition<SchemaLike, SchemaLike>;
12
14
  type OperationConfig<TInput extends SchemaLike, TOutput extends SchemaLike> = Omit<OperationDefinition<TInput, TOutput>, "handler"> & {
13
15
  handler(ctx: Parameters<OperationDefinition<TInput, TOutput>["handler"]>[0], input: InferSchemaOutput<TInput>): OperationHandlerResult<InferSchemaOutput<TOutput>> | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
@@ -55,7 +57,9 @@ export interface ProviderConfig<TOperations extends Record<string, ProviderOpera
55
57
  platform: StealthPlatform;
56
58
  };
57
59
  proxy?: ProviderProxyConfig;
60
+ ocr?: ProviderOcrConfig;
58
61
  stt?: ProviderSttConfig;
62
+ resolver?: ProviderResolverConfig;
59
63
  browser?: {
60
64
  engine: BrowserEngine;
61
65
  };
package/dist/define.js CHANGED
@@ -47,7 +47,26 @@ const VALID_PROVIDER_PROXY_AFFINITIES = [
47
47
  "auth-flow",
48
48
  "connection",
49
49
  ];
50
+ const VALID_PROVIDER_OCR_MODES = ["optional", "required"];
50
51
  const VALID_PROVIDER_STT_MODES = ["optional", "required"];
52
+ function exhaustiveLiteralArray() {
53
+ return (values, ..._missing) => values;
54
+ }
55
+ export const VALID_PROVIDER_RESOLVER_VENDORS = exhaustiveLiteralArray()([
56
+ "browser",
57
+ "capsolver",
58
+ "capmonster",
59
+ "2captcha",
60
+ "custom",
61
+ ]);
62
+ export const VALID_PROVIDER_CHALLENGE_KINDS = exhaustiveLiteralArray()([
63
+ "turnstile",
64
+ "recaptcha_v2",
65
+ "recaptcha_v3",
66
+ "hcaptcha",
67
+ "cloudflare_interstitial",
68
+ "aws_waf",
69
+ ]);
51
70
  const SMARTPROXY_APP_KEY_SECRET = "APIFUSE__PROXY__SMARTPROXY_APP_KEY";
52
71
  const NODEMAVEN_USERNAME_SECRET = "APIFUSE__PROXY__NODEMAVEN_USERNAME";
53
72
  const NODEMAVEN_PASSWORD_SECRET = "APIFUSE__PROXY__NODEMAVEN_PASSWORD";
@@ -56,9 +75,8 @@ const NODEMAVEN_PASSWORD_SECRET = "APIFUSE__PROXY__NODEMAVEN_PASSWORD";
56
75
  // credential fails at build/validation time rather than during a live outage: a
57
76
  // declared-but-uncredentialed fallback leg is a silently dead SPOF, which is
58
77
  // exactly the failure class the multi-vendor chain exists to remove. Vendors
59
- // absent from this map (e.g. `custom`/`decodo`, whose credentials come from the
60
- // `APIFUSE__PROXY__URL` bring-your-own escape hatch, not provider secrets) impose
61
- // no declaration requirement.
78
+ // absent from this map (the deprecated `custom`/`decodo` values have no managed
79
+ // adapter) impose no declaration requirement.
62
80
  const VENDOR_REQUIRED_SECRETS = {
63
81
  smartproxy: [SMARTPROXY_APP_KEY_SECRET],
64
82
  nodemaven: [NODEMAVEN_USERNAME_SECRET, NODEMAVEN_PASSWORD_SECRET],
@@ -361,8 +379,15 @@ function validateProviderProxy(config) {
361
379
  // `decodo`/`custom` are deprecated vendor values (string-union members, so the
362
380
  // @deprecated symbol gate can't catch them — warn at validation time instead).
363
381
  const deprecatedVendors = vendorChain.filter((vendor) => vendor === "decodo" || vendor === "custom");
382
+ if (proxy.mode === "required" &&
383
+ vendorChain.length > 0 &&
384
+ deprecatedVendors.length === vendorChain.length) {
385
+ throw new ValidationError(`Provider "${config.id}" requires proxy egress but declares only deprecated proxy vendor(s): ${deprecatedVendors.join(", ")}.`, {
386
+ fix: `Use proxy.provider or proxy.providers with "smartproxy" and/or "nodemaven".`,
387
+ });
388
+ }
364
389
  if (deprecatedVendors.length > 0) {
365
- console.warn(`[provider-sdk] Provider "${config.id}" uses deprecated proxy vendor(s): ${deprecatedVendors.join(", ")}. Use "smartproxy"/"nodemaven", or the APIFUSE__PROXY__URL bring-your-own escape hatch.`);
390
+ console.warn(`[provider-sdk] Provider "${config.id}" uses deprecated proxy vendor(s): ${deprecatedVendors.join(", ")}. Use "smartproxy"/"nodemaven".`);
366
391
  }
367
392
  }
368
393
  function validateProviderStt(config) {
@@ -377,6 +402,46 @@ function validateProviderStt(config) {
377
402
  rejectUnknownFields(stt, new Set(["mode"]), "stt");
378
403
  assertLiteralField(stt.mode, "stt.mode", VALID_PROVIDER_STT_MODES, config.id);
379
404
  }
405
+ function validateProviderOcr(config) {
406
+ const ocr = config.ocr;
407
+ if (ocr === undefined)
408
+ return;
409
+ if (!ocr || typeof ocr !== "object" || Array.isArray(ocr)) {
410
+ throw new ValidationError(`Provider "${config.id}" has invalid ocr: must be an object.`, {
411
+ fix: `Use ocr: { mode: "required" } or ocr: { mode: "optional" }.`,
412
+ });
413
+ }
414
+ rejectUnknownFields(ocr, new Set(["mode"]), "ocr");
415
+ assertLiteralField(ocr.mode, "ocr.mode", VALID_PROVIDER_OCR_MODES, config.id);
416
+ }
417
+ function validateProviderResolver(config) {
418
+ const resolver = config.resolver;
419
+ if (resolver === undefined)
420
+ return;
421
+ if (!resolver || typeof resolver !== "object" || Array.isArray(resolver)) {
422
+ throw new ValidationError(`Provider "${config.id}" has invalid resolver: must be an object.`, {
423
+ fix: `Set resolver for provider "${config.id}" to { vendors: ["2captcha"], kinds: ["turnstile"] }.`,
424
+ });
425
+ }
426
+ rejectUnknownFields(resolver, new Set(["vendors", "kinds"]), "resolver", config.id);
427
+ validateResolverLiteralArray(resolver.vendors, "resolver.vendors", VALID_PROVIDER_RESOLVER_VENDORS, config.id);
428
+ validateResolverLiteralArray(resolver.kinds, "resolver.kinds", VALID_PROVIDER_CHALLENGE_KINDS, config.id);
429
+ }
430
+ function validateResolverLiteralArray(value, field, validValues, providerId) {
431
+ if (!Array.isArray(value)) {
432
+ throw new ValidationError(`Provider "${providerId}" has invalid ${field}: must be an array.`, {
433
+ fix: `Set ${field} for provider "${providerId}" to an array containing only: ${validValues.join(", ")}.`,
434
+ });
435
+ }
436
+ for (const [index, item] of value.entries()) {
437
+ if (typeof item === "string" && validValues.some((validValue) => validValue === item)) {
438
+ continue;
439
+ }
440
+ throw new ValidationError(`Provider "${providerId}" has invalid ${field}[${index}]: ${JSON.stringify(item)}. Expected one of: ${validValues.join(", ")}`, {
441
+ fix: `Set ${field}[${index}] for provider "${providerId}" to one of ${validValues.map((validValue) => `"${validValue}"`).join(", ")}.`,
442
+ });
443
+ }
444
+ }
380
445
  function validateOperationIds(providerId, operations) {
381
446
  for (const operationName of Object.keys(operations)) {
382
447
  if (!OPERATION_ID_REGEX.test(operationName))
@@ -751,14 +816,18 @@ function suggestField(unknown, candidates) {
751
816
  }
752
817
  return best;
753
818
  }
754
- function rejectUnknownFields(value, allowed, fieldPath) {
819
+ function rejectUnknownFields(value, allowed, fieldPath, providerId) {
755
820
  for (const key of Object.keys(value)) {
756
821
  if (allowed.has(key))
757
822
  continue;
758
823
  const hint = suggestField(key, allowed);
759
824
  throw new ValidationError(hint
760
825
  ? `Unknown field "${key}" on ${fieldPath}. Did you mean "${hint}"?`
761
- : `Unknown field "${key}" on ${fieldPath}.`, { fix: `Remove ${fieldPath}.${key} or rename it.` });
826
+ : `Unknown field "${key}" on ${fieldPath}.`, {
827
+ fix: providerId
828
+ ? `Remove ${fieldPath}.${key} from provider "${providerId}" or rename it.`
829
+ : `Remove ${fieldPath}.${key} or rename it.`,
830
+ });
762
831
  }
763
832
  }
764
833
  function assertBoundedIntegerMs(value, fieldPath, options) {
@@ -1538,7 +1607,9 @@ export function defineProvider(config) {
1538
1607
  throw error;
1539
1608
  }
1540
1609
  validateProviderProxy(config);
1610
+ validateProviderOcr(config);
1541
1611
  validateProviderStt(config);
1612
+ validateProviderResolver(config);
1542
1613
  if (config.runtime === "browser" && !config.browser)
1543
1614
  throw new ProviderError(`Provider "${config.id}" must define browser.engine when runtime is "browser"`, {
1544
1615
  fix: 'Add browser: { engine: "playwright-stealth" } for TypeScript providers, or another supported engine for your runtime',
@@ -1556,7 +1627,9 @@ export function defineProvider(config) {
1556
1627
  native: config.native,
1557
1628
  stealth: config.stealth,
1558
1629
  proxy: config.proxy,
1630
+ ocr: config.ocr,
1559
1631
  stt: config.stt,
1632
+ resolver: config.resolver,
1560
1633
  browser: config.browser,
1561
1634
  auth: config.auth,
1562
1635
  reviewed: config.reviewed,
@@ -28,6 +28,7 @@ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
28
28
  "flow_expired",
29
29
  "turn_validation_error",
30
30
  "context_access_error",
31
+ "OCR_UPSTREAM_FAILED",
31
32
  "UNSUPPORTED_STT_OPTION",
32
33
  "INVALID_STT_AUDIO",
33
34
  "STT_AUDIO_TOO_LARGE",
@@ -82,6 +83,8 @@ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
82
83
  export const SDK_RUNTIME_OWNED_ERROR_CODES = new Set([
83
84
  ...SDK_OWNED_PROVIDER_ERROR_CODES,
84
85
  "reauth_required",
86
+ "OCR_UNAVAILABLE",
87
+ "UNSUPPORTED_OCR_BACKEND",
85
88
  "STT_UNAVAILABLE",
86
89
  "UNSUPPORTED_STT_BACKEND",
87
90
  "OUTPUT_VALIDATION_FAILED",
@@ -111,6 +114,8 @@ export const SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES = new Map([
111
114
  ["UPSTREAM_REJECTED", 409],
112
115
  ["UPSTREAM_ERROR", 502],
113
116
  ["BLOCKED", 502],
117
+ ["OCR_UNAVAILABLE", 503],
118
+ ["UNSUPPORTED_OCR_BACKEND", 503],
114
119
  ["STT_UNAVAILABLE", 503],
115
120
  ["UNSUPPORTED_STT_BACKEND", 503],
116
121
  ["STATEFUL_FORWARDING_REPLAY_CACHE_FULL", 503],
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from "./auth.js";
2
2
  export * from "./ceremonies/index.js";
3
3
  export * from "./choice-token.js";
4
- export type { ApiFuseConfig, BrowserConfig, ProxyConfig, ProxyProtocol, ProxyResolutionOptions, ProxyResolutionSource, ProxyVendorName, ResolvedProxyConfig, SessionConfig, } from "./config/loader.js";
4
+ export type { ApiFuseConfig, BrowserConfig, ProxyProtocol, ProxyResolutionOptions, ProxyResolutionSource, ProxyVendorName, ResolvedProxyConfig, SessionConfig, } from "./config/loader.js";
5
5
  export { defineConfig, loadApiFuseConfig, resolveProxy } from "./config/loader.js";
6
6
  export { canonicalJson, digestProviderContract, extractProviderContract, type JsonPrimitive, type JsonValue, PROVIDER_CONTRACT_SCHEMA_VERSION, type ProviderContractOperation, type ProviderContractSnapshot, } from "./contract.js";
7
7
  export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, defineStreamOperation, every, type ProviderConfig, } from "./define.js";
@@ -29,16 +29,18 @@ export { generateInsights } from "./runtime/insights.js";
29
29
  export { type InstrumentationOptions, type InstrumentedProviderContext, wrapWithInstrumentation, } from "./runtime/instrumentation.js";
30
30
  export { type PrevalidateResult, prevalidate } from "./runtime/prevalidate.js";
31
31
  export { getProviderBaseUrl } from "./runtime/provider.js";
32
+ export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, type ResolverRuntimeOptions, } from "./runtime/resolver.js";
32
33
  export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
33
34
  export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
34
35
  export { createStealthClient } from "./runtime/stealth.js";
36
+ export { APIFUSE__OCR__API_KEY_ENV, APIFUSE__OCR__BACKEND_ENV, APIFUSE__OCR__BASE_URL_ENV, APIFUSE__OCR__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__OCR__MODEL_ENV, CLOUDFLARE_ACCOUNT_ID_ENV, CLOUDFLARE_WORKERS_AI_OCR_BACKEND, createCloudflareWorkersAiOcrClient, createOcrClientFromEnv, createOpenAiCompatibleOcrClient, createUnsupportedOcrClient, DEFAULT_CLOUDFLARE_WORKERS_AI_OCR_MODEL, extractCaptchaCandidates, OPENAI_COMPATIBLE_OCR_BACKEND, } from "./runtime/ocr.js";
35
37
  export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
36
38
  export { type CreateTraceContextOptions, createTraceContext, type Span, type TraceContext, } from "./runtime/trace.js";
37
39
  export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
38
40
  export { createServerApp, ERROR_OBSERVABILITY_HEADER, type ServeOptions, serve, } from "./server/index.js";
39
41
  export { getStealthProfile, listStealthProfiles } from "./stealth/profiles.js";
40
42
  export * from "./stream.js";
41
- export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationAnnotations, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationHandlerResult, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, RedirectRunReason, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, StealthClient, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
43
+ export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserCookie, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ChallengeSolution, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OcrCaptchaCandidate, OcrCaptchaOptions, OcrCaptchaResult, OcrContext, OcrImageInput, OcrRecognizeRequest, OcrResult, OcrWarning, OperationAnnotations, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationHandlerResult, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderChallenge, ProviderChallengeKind, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderOcrConfig, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderResolverConfig, ProviderResolverVendor, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, RedirectRunReason, ResolverContext, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, StealthClient, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
42
44
  export { DEFAULT_OPERATION_TRANSPORT, HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, PROBE_INTERVALS, STREAM_CHUNK_BYTES_MAX, STREAM_CHUNK_BYTES_MIN, STREAM_HEARTBEAT_MS_MAX, STREAM_HEARTBEAT_MS_MIN, STREAM_IDLE_TIMEOUT_MS_MAX, STREAM_IDLE_TIMEOUT_MS_MIN, STREAM_MAX_DURATION_MS_MAX, STREAM_MAX_DURATION_MS_MIN, } from "./types.js";
43
45
  export * from "./utils/date.js";
44
46
  export * from "./utils/parse.js";
package/dist/index.js CHANGED
@@ -26,9 +26,11 @@ export { generateInsights } from "./runtime/insights.js";
26
26
  export { wrapWithInstrumentation, } from "./runtime/instrumentation.js";
27
27
  export { prevalidate } from "./runtime/prevalidate.js";
28
28
  export { getProviderBaseUrl } from "./runtime/provider.js";
29
+ export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, } from "./runtime/resolver.js";
29
30
  export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
30
31
  export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
31
32
  export { createStealthClient } from "./runtime/stealth.js";
33
+ export { APIFUSE__OCR__API_KEY_ENV, APIFUSE__OCR__BACKEND_ENV, APIFUSE__OCR__BASE_URL_ENV, APIFUSE__OCR__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__OCR__MODEL_ENV, CLOUDFLARE_ACCOUNT_ID_ENV, CLOUDFLARE_WORKERS_AI_OCR_BACKEND, createCloudflareWorkersAiOcrClient, createOcrClientFromEnv, createOpenAiCompatibleOcrClient, createUnsupportedOcrClient, DEFAULT_CLOUDFLARE_WORKERS_AI_OCR_MODEL, extractCaptchaCandidates, OPENAI_COMPATIBLE_OCR_BACKEND, } from "./runtime/ocr.js";
32
34
  export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
33
35
  export { createTraceContext, } from "./runtime/trace.js";
34
36
  export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, z, } from "./schema.js";
@@ -7,6 +7,6 @@ export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, i
7
7
  export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
8
8
  export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
9
9
  export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
10
- export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, } from "./types.js";
10
+ export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, } from "./types.js";
11
11
  export { createNativeNetworkClient, createEnvVendorCredentialResolver, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, type NativeGatewayProxy, type NativeGatewayProxyResolutionInput, type NativeGatewayProxySkipReason, type NativeGatewayProxySynthesizer, type NativeGatewayProxySynthesisResult, type NativeGatewayProxySynthesisInput, type NativeNetworkClientOptions, type NativeNetworkErrorCode, type VendorCredentialLookup, type VendorCredentialResolver, } from "./runtime/native-network.js";
12
12
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
@@ -1,4 +1,4 @@
1
- import type { ContextScratchpad, EnvContext, FlowContext, HttpClient, StealthClient, SttContext } from "../types.js";
1
+ import type { ContextScratchpad, EnvContext, FlowContext, HttpClient, OcrContext, StealthClient, SttContext } from "../types.js";
2
2
  export declare function createScratchpad(allowedKeys: string[], initial?: Record<string, unknown>): ContextScratchpad;
3
3
  export declare function createFlowContext(options: {
4
4
  flowId?: string;
@@ -11,5 +11,6 @@ export declare function createFlowContext(options: {
11
11
  externalRef?: string;
12
12
  allowedKeys: string[];
13
13
  initialContext?: Record<string, unknown>;
14
+ ocr?: OcrContext;
14
15
  stt?: SttContext;
15
16
  }): FlowContext;
@@ -1,5 +1,7 @@
1
1
  import { ContextAccessError } from "../errors.js";
2
2
  import { createAuthFlowHelpers } from "../auth.js";
3
+ import { createUnsupportedOcrClient } from "./ocr.js";
4
+ import { createUnsupportedResolverClient } from "./resolver.js";
3
5
  import { createUnsupportedSttClient } from "./stt.js";
4
6
  function normalizeAllowedKeys(allowedKeys) {
5
7
  return new Set(allowedKeys.filter((key) => key.trim().length > 0));
@@ -41,7 +43,9 @@ export function createFlowContext(options) {
41
43
  stealth: options.stealth,
42
44
  env: options.env,
43
45
  context: createScratchpad(options.allowedKeys, options.initialContext),
46
+ ocr: options.ocr ?? createUnsupportedOcrClient(),
44
47
  stt: options.stt ?? createUnsupportedSttClient(),
48
+ resolver: createUnsupportedResolverClient("Resolver is not available in auth flow context"),
45
49
  auth: createAuthFlowHelpers(),
46
50
  };
47
51
  }