@apifuse/provider-sdk 2.2.0-beta.15 → 2.2.0-beta.17

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 CHANGED
@@ -411,12 +411,14 @@ Provider-server failures use a stable public envelope:
411
411
 
412
412
  `retryable` is always present on responses emitted by the current SDK. Set
413
413
  `retryable` in the `ProviderError` options when the provider knows the answer;
414
- an explicit `true` or `false` wins over SDK derivation. When it is omitted, the
415
- SDK derives the value for its known error classes and otherwise defaults to
416
- `false`. During stateful rolling upgrades, the forwarding client also accepts
417
- an older owner response that omits `retryable` and treats it as `false` without
418
- loosening the emitted response contract. Existing optional `fix` guidance is
419
- also preserved when a `ProviderError` supplies it.
414
+ an explicit `true` or `false` wins over the matching operation declaration and
415
+ SDK derivation. When it is omitted, `operations.<id>.docs.errorCodes[].retryable`
416
+ is used for a matching provider-owned code, followed by SDK derivation (which
417
+ defaults ordinary `ProviderError` values to `false`). During stateful rolling
418
+ upgrades, the forwarding client also accepts an older owner response that omits
419
+ `retryable` and treats it as `false` without loosening the emitted response
420
+ contract. Existing optional `fix` guidance is also preserved when a
421
+ `ProviderError` supplies it.
420
422
 
421
423
  `details` belongs exclusively to the provider. The server passes
422
424
  `ProviderError.options.details` through verbatim, including strings and arrays,
@@ -435,8 +437,41 @@ Treat this header as telemetry, not as provider-controlled public error detail.
435
437
  Its category, taxonomy version, retryability, and optional upstream status match
436
438
  the structured `provider_request_failed` log event.
437
439
 
438
- Registered error-code mappings take precedence for every `ProviderError`,
439
- including `ValidationError`:
440
+ Declare provider-owned operation failures next to their documentation. The
441
+ server builds a lookup once at startup and applies it to failures from that
442
+ operation:
443
+
444
+ ```ts
445
+ docs: {
446
+ errorCodes: [{
447
+ code: "UPSTREAM_SCHEMA_ERROR",
448
+ status: 502,
449
+ retryable: true,
450
+ description: "The upstream response no longer matches its schema.",
451
+ }],
452
+ },
453
+ handler: async () => {
454
+ throw new ProviderError("Upstream schema changed", {
455
+ code: "UPSTREAM_SCHEMA_ERROR",
456
+ });
457
+ },
458
+ ```
459
+
460
+ `defineProvider` accepts only statuses the server can emit: 400, 401, 404, 429,
461
+ 500, 502, 503, and 504. Invalid declared statuses fail provider definition,
462
+ not a live request. Status selection uses this order:
463
+
464
+ 1. SDK-owned errors retain SDK status semantics. Operation declarations cannot
465
+ override SDK-owned codes, stateful-forwarding failures, Zod/deadline errors,
466
+ or `TransportError` values.
467
+ 2. A matching operation `errorCodes` entry with `status` supplies the status.
468
+ This slot applies to `ValidationError` as well as ordinary `ProviderError`.
469
+ 3. The registered mappings below apply.
470
+ 4. Existing fallbacks apply: `TransportError` 502/504, unregistered input
471
+ `ValidationError` 400 (output validation 500), and other unregistered
472
+ `ProviderError` values 500.
473
+
474
+ The registered mappings are:
440
475
 
441
476
  | Error code or fallback | HTTP status |
442
477
  | --- | ---: |
@@ -451,11 +486,15 @@ including `ValidationError`:
451
486
 
452
487
  An unregistered non-validation `ProviderError` code returns HTTP 500 and emits
453
488
  the greppable `unregistered_provider_error_code` signal with the code in the
454
- structured failure log. Before publishing a new code, register its status in
455
- the SDK mapping and add it to the mapping tests; declaring it only in operation
456
- documentation does not change runtime status selection. The HTTP 400
457
- `ValidationError` behavior is only the fallback for unregistered input
458
- validation codes; a registered code such as `NOT_FOUND` retains its mapped 404.
489
+ structured failure log. A matching operation declaration, including one that
490
+ omits `status`, makes the code registered for this signal and may independently
491
+ supply `retryable`. The HTTP 400 `ValidationError` behavior is only the fallback
492
+ when neither an operation status nor a registered mapping applies.
493
+
494
+ Throw the domain `ProviderError` directly. Subclassing or wrapping it as a
495
+ `TransportError` solely to preserve a 5xx response is obsolete; declare the
496
+ domain code's `status` instead. Genuine `TransportError` values remain
497
+ SDK-owned and keep their 502/504 mapping.
459
498
 
460
499
  ### Declared secrets are SDK-enforced
461
500
 
@@ -703,6 +742,46 @@ const credentialsAuth = defineCredentialsAuth({
703
742
  `bunx playwright install chromium`, or set
704
743
  `APIFUSE__CDP_POOL__URL` for remote browser debugging.
705
744
 
745
+ ### Native gateway adapter migration
746
+
747
+ Native proxy resolution supports both HTTP CONNECT and SOCKS5 without
748
+ terminating origin TLS. The built-in vendor order follows `proxy.providers`
749
+ exactly: `smartproxy` means the `api.smartproxy.org` allocation vendor (raw
750
+ `ip:port` endpoints), while `nodemaven` is the credentialed gateway. It is not
751
+ the company formerly called Smartproxy; that separate company is represented
752
+ by the deprecated `decodo` name.
753
+
754
+ Custom `gatewaySynthesizers` must now accept the selected `protocol` and the
755
+ injected `credentials` resolver on `NativeGatewayProxySynthesisInput`.
756
+ Synthesizers may be async because allocation vendors perform network I/O. They
757
+ may return a proxy, `undefined` when they do not implement the offered vendor,
758
+ or `{ kind: "skipped", reason }` so an exhausted required chain can explain an
759
+ absent credential, unsupported protocol, or allocation failure. Accordingly,
760
+ `resolveNativeGatewayProxy(...)` must now be awaited.
761
+
762
+ Callers that do not supply custom synthesizers or credentials keep env-backed
763
+ behavior. Hosts that already have an allowlisted `EnvContext` can inject it
764
+ explicitly, and vault-backed or per-tenant hosts can supply their own resolver:
765
+
766
+ ```ts
767
+ import {
768
+ createEnvVendorCredentialResolver,
769
+ createNativeNetworkClient,
770
+ } from "@apifuse/provider-sdk";
771
+
772
+ const network = createNativeNetworkClient({
773
+ proxyPolicy: { mode: "required", providers: ["smartproxy", "nodemaven"] },
774
+ credentials: createEnvVendorCredentialResolver(ctx.env),
775
+ // Optional advanced override; omit for each vendor's default.
776
+ proxyProtocol: "socks5",
777
+ });
778
+ ```
779
+
780
+ Never include credential values in adapter skip messages or thrown errors. The
781
+ SDK redacts built-in proxy URL userinfo, CONNECT authentication, and allocator
782
+ causes, but a custom adapter remains responsible for not publishing secrets in
783
+ its own diagnostics.
784
+
706
785
  ### Limiting stealth response bodies
707
786
 
708
787
  Set `maxBodyBytes` on `ctx.stealth.fetch()` or `session.redirects.run()` when an
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.17
4
+
5
+ - Release candidate for main commit 5a0f9127a5861992d5c144b07ad379a085756544.
6
+
7
+ ## 2.2.0-beta.16
8
+
9
+ - Release candidate for main commit c5deb2bc31a4a4a236d27a2ce3d214b533ed358f.
10
+
3
11
  ## 2.2.0-beta.15
4
12
 
5
13
  - Release candidate for main commit b5ebd25e48f6502e4ddb775d4e0a25f5c8276712.
@@ -90,6 +98,8 @@
90
98
 
91
99
  ## Unreleased
92
100
 
101
+ - **Breaking for custom native gateway adapters:** `NativeGatewayProxySynthesisInput` now includes an injected `credentials` resolver and selected `protocol`; synthesizers may return promises and structured skip reasons, and `resolveNativeGatewayProxy` is async. Default callers retain env-backed behavior. Native transport now supports both HTTP CONNECT and SOCKS5, defaults per vendor with an explicit runtime override, registers smartproxy allocation ahead of nodemaven when declared in that order, and reports every exhausted vendor reason without exposing proxy credentials.
102
+ - Honor operation `docs.errorCodes` at runtime: declared provider-owned statuses and retryability now drive the HTTP envelope, observability header, and structured log; invalid statuses fail `defineProvider`, declared codes no longer emit the unregistered-code signal, and `TransportError` status-preservation workarounds are obsolete.
93
103
  - Add an opt-in same-origin redirect hop policy to `ctx.http`, with bounded manual following and typed failures before a refused target is requested.
94
104
  - Enforce provider-declared native TCP/TLS egress before proxy or socket setup, with revocable and expiring dynamic grants plus typed authorization failures; providers without a native egress declaration retain legacy behavior.
95
105
  - **Breaking:** Provider error `details` is now passed through verbatim; SDK observability fields (`category`, `taxonomyVersion`, `upstreamStatus`, and derived `retryable`) are no longer merged into the public body. Emitted error envelopes now require top-level `retryable`, while inbound stateful forwarding tolerates an older owner response that omits it and defaults it to `false`. The removed observability metadata is available in the new `X-ApiFuse-Error-Observability` response header.
@@ -150,12 +150,31 @@ export declare function resolveProxyConfigAsync(options?: ProxyResolutionOptions
150
150
  * Vendor allocation and failover remain owned by the SDK.
151
151
  */
152
152
  export declare function resolveProxy(options?: ProxyResolutionOptions): Promise<ResolvedProxyConfig>;
153
+ /**
154
+ * Each vendor's default egress protocol, chosen from live KR benchmarks. HTTP
155
+ * CONNECT wins for nodemaven (socks5 adds ~500ms through the gateway) and ties
156
+ * for smartproxy, and is the only protocol ctx.http (Bun native fetch) supports.
157
+ * Override per call via ProxyResolutionOptions.protocol (harness/tests).
158
+ */
159
+ export declare const VENDOR_DEFAULT_PROTOCOL: Readonly<Record<ProxyVendorName, ProxyProtocol>>;
153
160
  /**
154
161
  * Guard the No-MITM invariant: a resolved proxy URL must use a tunnelling scheme
155
162
  * (http CONNECT or socks5) so the client TLS handshake reaches the origin
156
163
  * end-to-end. Anything else would intercept TLS and break fingerprinting.
157
164
  */
158
165
  export declare function assertTunnelingScheme(url: string): void;
166
+ export type ProxyVendorResolutionContext = {
167
+ readonly protocol: ProxyProtocol;
168
+ readonly poolIndex: number;
169
+ readonly refreshEpoch: number;
170
+ /** Explicit vendor credentials. Omit only on the legacy ambient-env path. */
171
+ readonly credentials?: Readonly<Record<string, string>>;
172
+ /** Disable non-policy env defaults for deterministic injected adapters. */
173
+ readonly ambientDefaults?: boolean;
174
+ /** Disable env-discovered Redis sharing for deterministic injected adapters. */
175
+ readonly sharedCache?: boolean;
176
+ };
177
+ export declare function resolveWithVendor(vendor: ProxyVendorName, policy: ProviderProxyPolicy, options: ProxyResolutionOptions, context: ProxyVendorResolutionContext): Promise<ResolvedProxyConfig>;
159
178
  /**
160
179
  * Ordered list of SDK-native proxy vendors declared by the policy. `providers`
161
180
  * takes precedence over the legacy singular `provider`; the platform default
@@ -2,7 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
2
2
  import { existsSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { Redis } from "ioredis";
5
- import { NODEMAVEN_DEFAULT_PROTOCOL, NODEMAVEN_MAX_POOL_SIZE, hasNodemavenCredentials, nodemavenPoolSize, synthesizeNodemavenProxy, } from "../runtime/proxy-nodemaven.js";
5
+ import { NODEMAVEN_DEFAULT_PROTOCOL, NODEMAVEN_FILTER_ENV, NODEMAVEN_MAX_POOL_SIZE, NODEMAVEN_PASSWORD_ENV, NODEMAVEN_USERNAME_ENV, hasNodemavenCredentials, nodemavenPoolSize, synthesizeNodemavenProxy, } from "../runtime/proxy-nodemaven.js";
6
6
  // "smartproxy" here is api.smartproxy.org — a residential proxy with an IP
7
7
  // extraction API (app_key → raw ip:port pool). It is NOT the company formerly
8
8
  // named Smartproxy (smartproxy.com), which rebranded to Decodo in 2025 and is
@@ -415,7 +415,7 @@ export async function resolveProxy(options = {}) {
415
415
  * for smartproxy, and is the only protocol ctx.http (Bun native fetch) supports.
416
416
  * Override per call via ProxyResolutionOptions.protocol (harness/tests).
417
417
  */
418
- const VENDOR_DEFAULT_PROTOCOL = {
418
+ export const VENDOR_DEFAULT_PROTOCOL = {
419
419
  smartproxy: "http",
420
420
  nodemaven: NODEMAVEN_DEFAULT_PROTOCOL,
421
421
  };
@@ -436,16 +436,33 @@ export function assertTunnelingScheme(url) {
436
436
  throw new ProxyResolutionError("PROXY_ALLOCATION_FAILED", `Resolved proxy scheme "${scheme}" is not a tunnelling scheme (expected http or socks5). Refusing to route TLS through a non-tunnelling proxy.`);
437
437
  }
438
438
  }
439
- async function resolveWithVendor(vendor, policy, options, context) {
439
+ export async function resolveWithVendor(vendor, policy, options, context) {
440
440
  if (vendor === "nodemaven") {
441
441
  const startedAt = Date.now();
442
+ const username = (context.credentials === undefined
443
+ ? process.env[NODEMAVEN_USERNAME_ENV]
444
+ : context.credentials[NODEMAVEN_USERNAME_ENV])?.trim();
445
+ const password = (context.credentials === undefined
446
+ ? process.env[NODEMAVEN_PASSWORD_ENV]
447
+ : context.credentials[NODEMAVEN_PASSWORD_ENV])?.trim();
448
+ const filter = context.credentials === undefined
449
+ ? process.env[NODEMAVEN_FILTER_ENV]
450
+ : context.credentials[NODEMAVEN_FILTER_ENV];
451
+ if (!username || !password) {
452
+ throw new ProxyResolutionError("PROXY_ALLOCATION_FAILED", `NodeMaven credentials missing: set ${NODEMAVEN_USERNAME_ENV} and ${NODEMAVEN_PASSWORD_ENV}.`, { vendor: "nodemaven" });
453
+ }
442
454
  const synthesized = synthesizeNodemavenProxy({
443
455
  policy,
456
+ credentials: {
457
+ username,
458
+ password,
459
+ ...(filter ? { filter } : {}),
460
+ },
444
461
  affinityKey: options.affinityKey,
445
462
  protocol: context.protocol,
446
463
  poolIndex: context.poolIndex,
447
464
  refreshEpoch: context.refreshEpoch,
448
- country: resolveSmartproxyCountry(policy),
465
+ country: resolveSmartproxyCountry(policy, context.ambientDefaults !== false),
449
466
  });
450
467
  options.telemetry?.recordProxyResolution({
451
468
  provider: "nodemaven",
@@ -468,13 +485,15 @@ async function resolveWithVendor(vendor, policy, options, context) {
468
485
  };
469
486
  }
470
487
  // smartproxy allocation-style vendor.
471
- const appKey = process.env[SMARTPROXY_APP_KEY_ENV]?.trim();
488
+ const appKey = (context.credentials === undefined
489
+ ? process.env[SMARTPROXY_APP_KEY_ENV]
490
+ : context.credentials[SMARTPROXY_APP_KEY_ENV])?.trim();
472
491
  if (!appKey) {
473
492
  // Guarded by vendorHasCredentials; treated as a vendor-internal failure.
474
493
  throw new ProxyResolutionError("PROXY_ALLOCATION_FAILED", `${SMARTPROXY_APP_KEY_ENV} is not configured.`, { vendor: "smartproxy" });
475
494
  }
476
- const lifetimeMinutes = resolveSmartproxyLifetime(policy);
477
- const allocated = await allocateSmartproxy(policy, appKey, lifetimeMinutes, options.affinityKey, context.protocol);
495
+ const lifetimeMinutes = resolveSmartproxyLifetime(policy, context.ambientDefaults !== false);
496
+ const allocated = await allocateSmartproxy(policy, appKey, lifetimeMinutes, options.affinityKey, context.protocol, context.ambientDefaults !== false, context.sharedCache !== false);
478
497
  options.telemetry?.recordProxyResolution({ ...allocated.telemetry, protocol: context.protocol });
479
498
  const poolIndex = selectProxyPoolIndex(allocated.pool.urls.length, context.poolIndex);
480
499
  const url = allocated.pool.urls[poolIndex];
@@ -665,11 +684,15 @@ export function mapFlatAttempt(flat, sizes) {
665
684
  }
666
685
  return { vendorIndex: 0, poolIndex: 0 };
667
686
  }
668
- function resolveSmartproxyCountry(policy) {
669
- return (policy.geo?.country ?? process.env[DEFAULT_PROXY_COUNTRY_ENV]?.trim().toUpperCase() ?? undefined);
687
+ function resolveSmartproxyCountry(policy, ambientDefaults = true) {
688
+ return (policy.geo?.country ??
689
+ (ambientDefaults
690
+ ? process.env[DEFAULT_PROXY_COUNTRY_ENV]?.trim().toUpperCase() || undefined
691
+ : undefined));
670
692
  }
671
- function resolveSmartproxyLifetime(policy) {
672
- const configuredLifetime = policy.session?.lifetimeMinutes ?? readPositiveNumberEnv(DEFAULT_PROXY_LIFETIME_ENV, 30);
693
+ function resolveSmartproxyLifetime(policy, ambientDefaults = true) {
694
+ const configuredLifetime = policy.session?.lifetimeMinutes ??
695
+ (ambientDefaults ? readPositiveNumberEnv(DEFAULT_PROXY_LIFETIME_ENV, 30) : 30);
673
696
  return Math.min(SMARTPROXY_MAX_LIFETIME_MINUTES, Math.max(1, Math.floor(configuredLifetime)));
674
697
  }
675
698
  function readPositiveNumberEnv(name, fallback) {
@@ -692,20 +715,24 @@ function selectProxyPoolIndex(poolSize, attempt = 0) {
692
715
  const normalizedAttempt = Number.isFinite(attempt) ? Math.max(0, Math.floor(attempt)) : 0;
693
716
  return normalizedAttempt % poolSize;
694
717
  }
695
- function buildSmartproxyCacheKey(policy, affinityKey, lifetimeMinutes, protocol) {
718
+ function buildSmartproxyCacheKey(policy, appKey, affinityKey, lifetimeMinutes, protocol, ambientDefaults = true) {
696
719
  const poolSize = resolveSmartproxyPoolSize(policy);
697
720
  return JSON.stringify({
698
721
  provider: "smartproxy",
722
+ credentialHash: createHash("sha256")
723
+ .update("apifuse-smartproxy-credential:v1\0")
724
+ .update(appKey)
725
+ .digest("hex"),
699
726
  protocol,
700
- country: resolveSmartproxyCountry(policy),
727
+ country: resolveSmartproxyCountry(policy, ambientDefaults),
701
728
  affinity: policy.session?.affinity ?? "request",
702
729
  affinityKey: (policy.session?.affinity ?? "request") === "request" ? undefined : affinityKey,
703
730
  lifetimeMinutes,
704
731
  poolSize,
705
732
  });
706
733
  }
707
- async function allocateSmartproxy(policy, appKey, lifetimeMinutes, affinityKey, protocol) {
708
- const cacheKey = buildSmartproxyCacheKey(policy, affinityKey, lifetimeMinutes, protocol);
734
+ async function allocateSmartproxy(policy, appKey, lifetimeMinutes, affinityKey, protocol, ambientDefaults = true, sharedCache = true) {
735
+ const cacheKey = buildSmartproxyCacheKey(policy, appKey, affinityKey, lifetimeMinutes, protocol, ambientDefaults);
709
736
  const startedAt = Date.now();
710
737
  const now = startedAt;
711
738
  const invalidatedUntil = invalidatedProxyKeys.get(cacheKey) ?? 0;
@@ -713,7 +740,7 @@ async function allocateSmartproxy(policy, appKey, lifetimeMinutes, affinityKey,
713
740
  const cached = proxyCache.get(cacheKey);
714
741
  if (!skipCached && cached && isFresh(cached, now)) {
715
742
  if (shouldSoftRefresh(cached, now)) {
716
- void refreshSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, protocol);
743
+ void refreshSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, protocol, ambientDefaults, sharedCache);
717
744
  return {
718
745
  pool: cached,
719
746
  telemetry: telemetryForPool(cached, "soft_stale_refresh", startedAt, {
@@ -726,7 +753,7 @@ async function allocateSmartproxy(policy, appKey, lifetimeMinutes, affinityKey,
726
753
  telemetry: telemetryForPool(cached, "memory_hit", startedAt),
727
754
  };
728
755
  }
729
- if (!skipCached) {
756
+ if (!skipCached && sharedCache) {
730
757
  const redisResult = await readSmartproxyRedisPool(cacheKey, startedAt);
731
758
  if (redisResult)
732
759
  return redisResult;
@@ -741,7 +768,7 @@ async function allocateSmartproxy(policy, appKey, lifetimeMinutes, affinityKey,
741
768
  }),
742
769
  };
743
770
  }
744
- const promise = allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, startedAt, protocol).finally(() => {
771
+ const promise = allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, startedAt, protocol, ambientDefaults, sharedCache).finally(() => {
745
772
  proxyInflight.delete(cacheKey);
746
773
  });
747
774
  proxyInflight.set(cacheKey, promise);
@@ -772,9 +799,9 @@ async function readSmartproxyRedisPool(cacheKey, startedAt) {
772
799
  telemetry: telemetryForPool(pool, "redis_hit", startedAt, { redisReadMs }),
773
800
  };
774
801
  }
775
- async function refreshSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, protocol) {
802
+ async function refreshSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, protocol, ambientDefaults, sharedCache) {
776
803
  try {
777
- await allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, Date.now(), protocol, {
804
+ await allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, Date.now(), protocol, ambientDefaults, sharedCache, {
778
805
  background: true,
779
806
  });
780
807
  }
@@ -782,10 +809,10 @@ async function refreshSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes,
782
809
  // Soft refresh is opportunistic; current fresh pool remains usable.
783
810
  }
784
811
  }
785
- async function allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, startedAt, protocol, options = {}) {
786
- const redis = getProxyRedis();
812
+ async function allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinutes, startedAt, protocol, ambientDefaults, sharedCache, options = {}) {
813
+ const redis = sharedCache ? getProxyRedis() : undefined;
787
814
  if (!redis || !(await ensureRedisReady(redis))) {
788
- return await allocateAndStoreSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, startedAt, { cacheStatus: "allocator", protocol });
815
+ return await allocateAndStoreSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, startedAt, { cacheStatus: "allocator", protocol, ambientDefaults });
789
816
  }
790
817
  const poolKey = smartproxyRedisPoolKey(cacheKey);
791
818
  const lockKey = smartproxyRedisLockKey(cacheKey);
@@ -800,6 +827,7 @@ async function allocateSmartproxyShared(cacheKey, policy, appKey, lifetimeMinute
800
827
  redis,
801
828
  poolKey,
802
829
  protocol,
830
+ ambientDefaults,
803
831
  });
804
832
  }
805
833
  finally {
@@ -912,7 +940,7 @@ async function readSmartproxyAllocatorBodyWithDeadline(response, signal) {
912
940
  }
913
941
  async function allocateAndStoreSmartproxyPool(cacheKey, policy, appKey, lifetimeMinutes, startedAt, options) {
914
942
  const poolSize = resolveSmartproxyPoolSize(policy);
915
- const allocatorUrl = buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize, options.protocol);
943
+ const allocatorUrl = buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize, options.protocol, options.ambientDefaults);
916
944
  const allocatorStartedAt = Date.now();
917
945
  const allocatorDeadlineAt = allocatorStartedAt + smartproxyAllocatorDeadlineMs();
918
946
  let allocation;
@@ -970,7 +998,7 @@ async function allocateAndStoreSmartproxyPool(cacheKey, policy, appKey, lifetime
970
998
  expiresAt: allocatedAt + ttlMs,
971
999
  diagnostics: {
972
1000
  provider: "smartproxy",
973
- country: resolveSmartproxyCountry(policy) ?? "default",
1001
+ country: resolveSmartproxyCountry(policy, options.ambientDefaults) ?? "default",
974
1002
  lifetimeMinutes,
975
1003
  affinity: policy.session?.affinity ?? "request",
976
1004
  rawConnect: true,
@@ -1090,7 +1118,7 @@ const SMARTPROXY_PROTOCOL_PARAM = {
1090
1118
  http: "1",
1091
1119
  socks5: "2",
1092
1120
  };
1093
- function buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize, protocol) {
1121
+ function buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize, protocol, ambientDefaults = true) {
1094
1122
  const params = new URLSearchParams({
1095
1123
  app_key: appKey,
1096
1124
  pt: "9",
@@ -1100,7 +1128,7 @@ function buildSmartproxyAllocatorUrl(policy, appKey, lifetimeMinutes, poolSize,
1100
1128
  format: "txt",
1101
1129
  lb: "\\n",
1102
1130
  });
1103
- const country = resolveSmartproxyCountry(policy);
1131
+ const country = resolveSmartproxyCountry(policy, ambientDefaults);
1104
1132
  if (country) {
1105
1133
  params.set("cc", country);
1106
1134
  }
@@ -1172,7 +1200,10 @@ function markSmartproxyCacheInvalidated(options = {}) {
1172
1200
  return undefined;
1173
1201
  }
1174
1202
  const lifetimeMinutes = resolveSmartproxyLifetime(policy);
1175
- const cacheKey = buildSmartproxyCacheKey(policy, options.affinityKey, lifetimeMinutes, options.protocol ?? VENDOR_DEFAULT_PROTOCOL.smartproxy);
1203
+ const appKey = process.env[SMARTPROXY_APP_KEY_ENV]?.trim();
1204
+ if (!appKey)
1205
+ return undefined;
1206
+ const cacheKey = buildSmartproxyCacheKey(policy, appKey, options.affinityKey, lifetimeMinutes, options.protocol ?? VENDOR_DEFAULT_PROTOCOL.smartproxy);
1176
1207
  invalidatedProxyKeys.set(cacheKey, Date.now() + SMARTPROXY_INVALIDATION_SKIP_REDIS_MS);
1177
1208
  proxyCache.delete(cacheKey);
1178
1209
  proxyInflight.delete(cacheKey);
package/dist/define.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import ms from "ms";
2
+ import { SDK_RUNTIME_OWNED_ERROR_CODES } from "./error-resolution.js";
2
3
  import { ProviderError, ValidationError } from "./errors.js";
3
4
  import { NativeEgressPolicyValidationError, validateNativeProviderConfig, } from "./native-egress-policy.js";
4
5
  import { safeParseSchemaSync } from "./schema.js";
5
6
  import { resolveHealthCheckInputDateTokens } from "./server/self-test-input-tokens.js";
6
- import { HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX, HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN, HEALTH_CHECK_TIMEOUT_MS_MAX, HEALTH_CHECK_TIMEOUT_MS_MIN, OPERATION_TIMEOUT_MS_MAX, OPERATION_TIMEOUT_MS_MIN, 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";
7
+ import { HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX, HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN, HEALTH_CHECK_TIMEOUT_MS_MAX, HEALTH_CHECK_TIMEOUT_MS_MIN, OPERATION_TIMEOUT_MS_MAX, OPERATION_TIMEOUT_MS_MIN, 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, VALID_OPERATION_ERROR_STATUSES, } from "./types.js";
7
8
  const CONNECTOR_ID_REGEX = /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)*$/;
8
9
  const OPERATION_ID_REGEX = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/;
9
10
  const VALID_RUNTIMES = ["standard", "shared", "browser"];
@@ -410,6 +411,23 @@ function validateOperationObservability(providerId, operations) {
410
411
  }
411
412
  }
412
413
  }
414
+ function validateOperationErrorCodes(providerId, operations) {
415
+ for (const [operationName, operation] of Object.entries(operations)) {
416
+ for (const [index, errorCode] of (operation.docs?.errorCodes ?? []).entries()) {
417
+ if (errorCode.status !== undefined &&
418
+ !VALID_OPERATION_ERROR_STATUSES.some((status) => status === errorCode.status)) {
419
+ const field = `operations.${operationName}.docs.errorCodes[${index}].status`;
420
+ throw new ValidationError(`Provider "${providerId}" has invalid ${field}: ${String(errorCode.status)} is not an emittable provider error status.`, {
421
+ fix: `Set ${field} to one of ${VALID_OPERATION_ERROR_STATUSES.join(", ")}, or omit it.`,
422
+ });
423
+ }
424
+ if (errorCode.status !== undefined &&
425
+ SDK_RUNTIME_OWNED_ERROR_CODES.has(errorCode.code)) {
426
+ console.warn(`[provider-sdk] Provider "${providerId}" operation "${operationName}" declares status ${errorCode.status} for SDK-owned error code "${errorCode.code}"; the declared status is documentation-only and will be ignored at runtime.`);
427
+ }
428
+ }
429
+ }
430
+ }
413
431
  const JSON_TRANSPORT_FIELDS = new Set(["kind"]);
414
432
  const SSE_TRANSPORT_FIELDS = new Set([
415
433
  "kind",
@@ -1396,6 +1414,7 @@ export function defineProvider(config) {
1396
1414
  validateOperationIds(config.id, config.operations);
1397
1415
  validateOperationAnnotations(config.id, config.operations);
1398
1416
  validateOperationObservability(config.id, config.operations);
1417
+ validateOperationErrorCodes(config.id, config.operations);
1399
1418
  validateOperationTransports(config.id, config.operations);
1400
1419
  validateOperationContracts(config.id, config.operations);
1401
1420
  validateToolRouterMetadata(config.id, config.operations);
@@ -0,0 +1,2 @@
1
+ export declare const SDK_OWNED_PROVIDER_ERROR_CODES: Set<string>;
2
+ export declare const SDK_RUNTIME_OWNED_ERROR_CODES: Set<string>;
@@ -0,0 +1,90 @@
1
+ // This set suppresses the unregistered-provider-error-code signal for codes
2
+ // intentionally emitted by SDK paths. It is not the complete authority for
3
+ // runtime error resolution: branded errors and additional canonical SDK codes
4
+ // must also remain immune to provider-declared status/retryability overrides.
5
+ export const SDK_OWNED_PROVIDER_ERROR_CODES = new Set([
6
+ "MISSING_SECRET",
7
+ "AUTH_PROMPT_UNAVAILABLE",
8
+ "BROWSER_CDP_POOL_REQUIRED",
9
+ "BROWSER_RUNTIME_UNSUPPORTED",
10
+ "STEALTH_RUNTIME_UNSUPPORTED",
11
+ "SSE_EVENT_UNDECLARED",
12
+ "STREAM_EVENT_TOO_LARGE",
13
+ "STREAM_CHUNK_TOO_LARGE",
14
+ "SSE_RESULT_UNSUPPORTED",
15
+ "STREAM_RESULT_UNSUPPORTED",
16
+ "AUTH_FLOW_NOT_CONFIGURED",
17
+ "refresh_not_supported",
18
+ "RUNTIME_UNSUPPORTED",
19
+ "PROVIDER_STATE_UNSUPPORTED",
20
+ "CHOICE_TOKEN_MASTER_SECRET_NOT_CONFIGURED",
21
+ "CHOICE_STATE_PAYLOAD_TOO_LARGE",
22
+ "CHOICE_STATE_UNAVAILABLE",
23
+ "CHOICE_CONTEXT_REQUIRED",
24
+ "unsupported_stealth_cookie_store_version",
25
+ "provider_secret_error",
26
+ "credential_key_error",
27
+ "credential_mode_error",
28
+ "flow_expired",
29
+ "turn_validation_error",
30
+ "context_access_error",
31
+ "UNSUPPORTED_STT_OPTION",
32
+ "INVALID_STT_AUDIO",
33
+ "STT_AUDIO_TOO_LARGE",
34
+ "STT_UPSTREAM_FAILED",
35
+ "INVALID_STT_VERIFICATION_CODE_OPTIONS",
36
+ "NO_CODE_FOUND",
37
+ "AMBIGUOUS_CODE",
38
+ "retry_invalid_policy",
39
+ "retry_unsafe_method",
40
+ "stealth_cookie_store_serialize_failed",
41
+ "response_too_large",
42
+ "transport_stream_unavailable",
43
+ "transport_invalid_method",
44
+ "http_transport_override_unsupported",
45
+ "http_redirect_policy_invalid",
46
+ "http_redirect_stopped",
47
+ "http_redirect_max_hops",
48
+ "http_redirect_missing_location",
49
+ "http_redirect_loop",
50
+ "transport_invalid_url",
51
+ "retry_exhausted",
52
+ "auth_abort_unsafe_data",
53
+ "credentials_auth_missing_credential_keys",
54
+ "credentials_auth_missing_credential",
55
+ "credentials_auth_invalid_login_result",
56
+ "credentials_auth_unknown_challenge",
57
+ "credentials_auth_unknown_pending_challenge",
58
+ "STATEFUL_FORWARDING_NOT_CONFIGURED",
59
+ "STATEFUL_FORWARDING_SIGNATURE_MISSING",
60
+ "STATEFUL_FORWARDING_NONCE_INVALID",
61
+ "STATEFUL_FORWARDING_TIMESTAMP_INVALID",
62
+ "STATEFUL_FORWARDING_SIGNATURE_INVALID",
63
+ "STATEFUL_FORWARDING_REPLAY_DETECTED",
64
+ "STATEFUL_FORWARDING_REPLAY_CACHE_FULL",
65
+ "STATEFUL_FORWARDING_ENVELOPE_INVALID",
66
+ "STATEFUL_FORWARDING_PROVIDER_MISMATCH",
67
+ "STATEFUL_FORWARDING_SOURCE_POD_MISMATCH",
68
+ "STATEFUL_FORWARDING_OWNER_FENCE_INVALID",
69
+ "STATEFUL_FORWARDING_REQUEST_FAILED",
70
+ "STATEFUL_FORWARDING_CONTEXT_MISSING",
71
+ "STATEFUL_FORWARDING_BAD_RESPONSE",
72
+ "STATEFUL_INTERNAL_EXECUTOR_NOT_CONFIGURED",
73
+ "STATEFUL_FILE_FORWARDING_UNSUPPORTED",
74
+ "STATEFUL_CONTROL_PLANE_OPERATION_AMBIGUOUS",
75
+ "STATEFUL_CONTROL_PLANE_REQUEST_FAILED",
76
+ "STATEFUL_CONTROL_PLANE_HTTP_ERROR",
77
+ "STATEFUL_CONTROL_PLANE_INVALID_RESPONSE",
78
+ ]);
79
+ // Complete code authority for provider-declared runtime resolution. Keep this
80
+ // separate from signal suppression: declarations may document these codes, but
81
+ // their status and retryability can never override the SDK's canonical result.
82
+ export const SDK_RUNTIME_OWNED_ERROR_CODES = new Set([
83
+ ...SDK_OWNED_PROVIDER_ERROR_CODES,
84
+ "reauth_required",
85
+ "STT_UNAVAILABLE",
86
+ "UNSUPPORTED_STT_BACKEND",
87
+ "OUTPUT_VALIDATION_FAILED",
88
+ "NOT_FOUND",
89
+ "not_found",
90
+ ]);
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export { type CreateCredentialContextOptions, createCredentialContext, } from ".
22
22
  export { createEnvContext } from "./runtime/env.js";
23
23
  export { executeOperation } from "./runtime/executor.js";
24
24
  export { createHttpClient } from "./runtime/http.js";
25
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, type NativeGatewayProxy, type NativeGatewayProxyResolutionInput, type NativeGatewayProxySynthesizer, type NativeGatewayProxySynthesisInput, type NativeNetworkClientOptions, type NativeNetworkErrorCode, } from "./runtime/native-network.js";
25
+ 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";
26
26
  export type { Insight, InsightSeverity } from "./runtime/insights.js";
27
27
  export { generateInsights } from "./runtime/insights.js";
28
28
  export { type InstrumentationOptions, type InstrumentedProviderContext, wrapWithInstrumentation, } from "./runtime/instrumentation.js";
@@ -37,7 +37,7 @@ export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SEN
37
37
  export { createServerApp, ERROR_OBSERVABILITY_HEADER, type ServeOptions, serve, } from "./server/index.js";
38
38
  export { getStealthProfile, listStealthProfiles } from "./stealth/profiles.js";
39
39
  export * from "./stream.js";
40
- 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, 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, 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";
40
+ 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, 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";
41
41
  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";
42
42
  export * from "./utils/date.js";
43
43
  export * from "./utils/parse.js";
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ export { createCredentialContext, } from "./runtime/credential.js";
20
20
  export { createEnvContext } from "./runtime/env.js";
21
21
  export { executeOperation } from "./runtime/executor.js";
22
22
  export { createHttpClient } from "./runtime/http.js";
23
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
23
+ export { createNativeNetworkClient, createEnvVendorCredentialResolver, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
24
24
  export { generateInsights } from "./runtime/insights.js";
25
25
  export { wrapWithInstrumentation, } from "./runtime/instrumentation.js";
26
26
  export { prevalidate } from "./runtime/prevalidate.js";
@@ -10,6 +10,7 @@ export type DynamicEgressRuleSnapshot = {
10
10
  readonly sourcePorts: readonly number[];
11
11
  readonly sourcePortRanges: readonly NativeTcpPortRange[];
12
12
  readonly targetHostSuffixes: readonly string[];
13
+ readonly targetIpv4Cidrs: readonly string[];
13
14
  readonly targetPorts: readonly number[];
14
15
  readonly targetPortRanges: readonly NativeTcpPortRange[];
15
16
  readonly tls: NativeTcpTlsMode;