@apifuse/provider-sdk 2.1.0-beta.9 → 2.2.0-beta.10
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 +240 -0
- package/CHANGELOG.md +93 -0
- package/README.md +26 -10
- package/SUBMISSION.md +11 -12
- package/bin/apifuse-check.ts +44 -59
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-check.ts +36 -0
- package/bin/apifuse-pack-smoke.ts +22 -81
- package/bin/apifuse-pack-types.ts +266 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +53 -70
- package/bin/apifuse-submit-check.ts +2177 -353
- package/bin/apifuse-sync-assets.ts +117 -0
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-delimited-text.ts +50 -0
- package/bin/submit-check-xml-semantics.ts +204 -0
- package/bin/submit-check-xml.ts +134 -0
- package/dist/auth-turn/auth-turn.v1.schema.json +89 -0
- package/dist/auth-turn/fixtures/invalid/empty-kind.json +4 -0
- package/dist/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
- package/dist/auth-turn/fixtures/invalid/missing-kind.json +3 -0
- package/dist/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
- package/dist/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
- package/dist/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
- package/dist/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
- package/dist/auth-turn/fixtures/valid/abort.json +8 -0
- package/dist/auth-turn/fixtures/valid/challenge.json +17 -0
- package/dist/auth-turn/fixtures/valid/complete.json +13 -0
- package/dist/auth-turn/fixtures/valid/form.json +14 -0
- package/dist/auth-turn/fixtures/valid/message.json +13 -0
- package/dist/auth-turn/fixtures/valid/multi_choice.json +15 -0
- package/dist/auth-turn/fixtures/valid/pending.json +5 -0
- package/dist/auth-turn/fixtures/valid/poll.json +9 -0
- package/dist/auth-turn/fixtures/valid/redirect.json +16 -0
- package/dist/auth-turn/fixtures/valid/retry.json +8 -0
- package/dist/auth-turn/fixtures/valid/unknown-kind.json +7 -0
- package/dist/auth-turn/index.d.ts +195 -0
- package/dist/auth-turn/index.js +133 -0
- package/dist/auth.d.ts +76 -0
- package/dist/auth.js +427 -0
- package/dist/ceremonies/index.d.ts +1 -1
- package/dist/ceremonies/index.js +14 -48
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +8 -0
- package/dist/cli/create.d.ts +3 -0
- package/dist/cli/create.js +47 -33
- package/dist/cli/prompt-assets.d.ts +80 -0
- package/dist/cli/prompt-assets.js +743 -0
- package/dist/cli/templates/provider/.agents/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
- package/dist/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
- package/dist/cli/templates/provider/.agents/skills/normalization-standards/SKILL.md.tpl +57 -0
- package/dist/cli/templates/provider/.agents/skills/pagination-and-counts/SKILL.md.tpl +52 -0
- package/dist/cli/templates/provider/.agents/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
- package/dist/cli/templates/provider/.agents/skills/upstream-notes/README.md.tpl +13 -0
- package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
- package/dist/cli/templates/provider/.gitignore.tpl +22 -0
- package/dist/cli/templates/provider/AGENTS.md.tpl +96 -0
- package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
- package/dist/cli/templates/provider/README.md.tpl +163 -0
- package/dist/cli/templates/provider/dev.ts.tpl +5 -0
- package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
- package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
- package/dist/cli/templates/provider/index.ts.tpl +15 -0
- package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
- package/dist/cli/templates/provider/meta.ts.tpl +7 -0
- package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
- package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
- package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
- package/dist/cli/templates/provider/start.ts.tpl +5 -0
- package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
- package/dist/config/loader.d.ts +149 -8
- package/dist/config/loader.js +378 -89
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +5 -6
- package/dist/define.d.ts +13 -1
- package/dist/define.js +245 -178
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/errors.d.ts +4 -1
- package/dist/errors.js +48 -0
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +44 -41
- package/dist/index.js +39 -36
- package/dist/lint.d.ts +1 -0
- package/dist/lint.js +35 -15
- package/dist/provider.d.ts +11 -9
- package/dist/provider.js +9 -8
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +1 -1
- package/dist/runtime/auth-flow.js +4 -2
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +214 -25
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +31 -35
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +15 -3
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +160 -344
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +56 -19
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +9 -7
- package/dist/runtime/proxy-nodemaven.d.ts +35 -0
- package/dist/runtime/proxy-nodemaven.js +128 -0
- package/dist/runtime/proxy-retry-policy.d.ts +40 -0
- package/dist/runtime/proxy-retry-policy.js +326 -0
- package/dist/runtime/proxy-telemetry.d.ts +2 -1
- package/dist/runtime/proxy-telemetry.js +55 -52
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +2 -4
- package/dist/runtime/request-options.d.ts +1 -1
- package/dist/runtime/secrets.d.ts +27 -0
- package/dist/runtime/secrets.js +51 -0
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +15 -4
- package/dist/runtime/stealth.d.ts +7 -4
- package/dist/runtime/stealth.js +257 -215
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -3
- package/dist/server/index.js +6 -2
- package/dist/server/self-test-input-tokens.d.ts +1 -0
- package/dist/server/self-test-input-tokens.js +37 -0
- package/dist/server/self-test-redaction.d.ts +20 -0
- package/dist/server/self-test-redaction.js +70 -0
- package/dist/server/self-test-token.d.ts +30 -0
- package/dist/server/self-test-token.js +50 -0
- package/dist/server/self-test.d.ts +199 -0
- package/dist/server/self-test.js +1113 -0
- package/dist/server/serve.d.ts +14 -3
- package/dist/server/serve.js +135 -64
- package/dist/server/types.d.ts +10 -9
- package/dist/server/types.js +3 -7
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +1 -1
- package/dist/testing/run.js +12 -15
- package/dist/types.d.ts +237 -1
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +16 -5
- package/src/auth-turn/auth-turn.v1.schema.json +89 -0
- package/src/auth-turn/fixtures/invalid/empty-kind.json +4 -0
- package/src/auth-turn/fixtures/invalid/expires-at-not-string.json +5 -0
- package/src/auth-turn/fixtures/invalid/missing-kind.json +3 -0
- package/src/auth-turn/fixtures/invalid/missing-turn-id.json +3 -0
- package/src/auth-turn/fixtures/invalid/timing-unknown-field.json +7 -0
- package/src/auth-turn/fixtures/invalid/turn-id-snake-case.json +4 -0
- package/src/auth-turn/fixtures/invalid/unknown-top-level-field.json +5 -0
- package/src/auth-turn/fixtures/valid/abort.json +8 -0
- package/src/auth-turn/fixtures/valid/challenge.json +17 -0
- package/src/auth-turn/fixtures/valid/complete.json +13 -0
- package/src/auth-turn/fixtures/valid/form.json +14 -0
- package/src/auth-turn/fixtures/valid/message.json +13 -0
- package/src/auth-turn/fixtures/valid/multi_choice.json +15 -0
- package/src/auth-turn/fixtures/valid/pending.json +5 -0
- package/src/auth-turn/fixtures/valid/poll.json +9 -0
- package/src/auth-turn/fixtures/valid/redirect.json +16 -0
- package/src/auth-turn/fixtures/valid/retry.json +8 -0
- package/src/auth-turn/fixtures/valid/unknown-kind.json +7 -0
- package/src/auth-turn/index.ts +177 -0
- package/src/auth.ts +728 -0
- package/src/ceremonies/index.ts +33 -121
- package/src/cli/commands.ts +10 -0
- package/src/cli/create.ts +69 -99
- package/src/cli/prompt-assets.ts +865 -0
- package/src/cli/templates/provider/.agents/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
- package/src/cli/templates/provider/.agents/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
- package/src/cli/templates/provider/.agents/skills/normalization-standards/SKILL.md.tpl +57 -0
- package/src/cli/templates/provider/.agents/skills/pagination-and-counts/SKILL.md.tpl +52 -0
- package/src/cli/templates/provider/.agents/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
- package/src/cli/templates/provider/.agents/skills/upstream-notes/README.md.tpl +13 -0
- package/src/cli/templates/provider/AGENTS.md.tpl +96 -0
- package/src/cli/templates/provider/README.md.tpl +7 -4
- package/src/config/loader.ts +543 -208
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +13 -28
- package/src/define.ts +397 -528
- package/src/dev.ts +4 -9
- package/src/errors.ts +58 -5
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +64 -41
- package/src/lint.ts +122 -159
- package/src/provider.ts +40 -9
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +6 -6
- package/src/runtime/browser.ts +320 -151
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +79 -132
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +23 -20
- package/src/runtime/http.ts +216 -539
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +78 -65
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +29 -42
- package/src/runtime/proxy-nodemaven.ts +178 -0
- package/src/runtime/proxy-retry-policy.ts +469 -0
- package/src/runtime/proxy-telemetry.ts +79 -77
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +4 -13
- package/src/runtime/secrets.ts +64 -0
- package/src/runtime/state.ts +41 -110
- package/src/runtime/stealth.ts +331 -369
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +44 -3
- package/src/server/self-test-input-tokens.ts +46 -0
- package/src/server/self-test-redaction.ts +97 -0
- package/src/server/self-test-token.ts +70 -0
- package/src/server/self-test.ts +1450 -0
- package/src/server/serve.ts +206 -216
- package/src/server/types.ts +7 -19
- package/src/stealth/profiles.ts +10 -26
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +2 -2
- package/src/testing/run.ts +24 -64
- package/src/types.ts +274 -1
- package/src/user-input.ts +118 -0
package/src/types.ts
CHANGED
|
@@ -331,9 +331,20 @@ export interface HealthJourneySchedule {
|
|
|
331
331
|
kind: "interval";
|
|
332
332
|
/** ISO 8601 duration, for example PT8H. */
|
|
333
333
|
interval: Iso8601Duration;
|
|
334
|
+
randomize?: HealthScheduleRandomization;
|
|
334
335
|
jitter?: Iso8601Duration;
|
|
335
336
|
}
|
|
336
337
|
|
|
338
|
+
export type HealthScheduleRandomization =
|
|
339
|
+
| {
|
|
340
|
+
mode: "centered";
|
|
341
|
+
maxOffset: Iso8601Duration;
|
|
342
|
+
}
|
|
343
|
+
| {
|
|
344
|
+
mode: "delayed";
|
|
345
|
+
maxDelay: Iso8601Duration;
|
|
346
|
+
};
|
|
347
|
+
|
|
337
348
|
export interface HealthJourneyStep {
|
|
338
349
|
id: string;
|
|
339
350
|
description?: string;
|
|
@@ -612,6 +623,9 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
|
|
|
612
623
|
export interface HealthCheckSuite<TInput = unknown, TOutput = unknown> {
|
|
613
624
|
/** Polling interval for the suite. All cases share this cadence. */
|
|
614
625
|
interval: ProbeInterval;
|
|
626
|
+
schedule?: {
|
|
627
|
+
randomize?: HealthScheduleRandomization;
|
|
628
|
+
};
|
|
615
629
|
/** Per-case timeout in milliseconds. Default: 30000. */
|
|
616
630
|
timeoutMs?: number;
|
|
617
631
|
/** Default degradation threshold for cases in this suite. Default: runtime threshold. */
|
|
@@ -687,6 +701,14 @@ export interface ProviderHealthMonitorConfig {
|
|
|
687
701
|
serviceAccount?: string;
|
|
688
702
|
}
|
|
689
703
|
|
|
704
|
+
/**
|
|
705
|
+
* New name for `ProviderHealthMonitorConfig` as part of the health dependency
|
|
706
|
+
* inversion (`healthMonitor` → `healthProbe`). Both provider-level fields are
|
|
707
|
+
* accepted transitionally with identical validation; declaring both is a
|
|
708
|
+
* `ValidationError`.
|
|
709
|
+
*/
|
|
710
|
+
export type ProviderHealthProbeConfig = ProviderHealthMonitorConfig;
|
|
711
|
+
|
|
690
712
|
export interface HealthMonitorProbeOverride {
|
|
691
713
|
/** Optional runtime interval override as a positive `ms`-style duration string. */
|
|
692
714
|
interval?: ProbeInterval;
|
|
@@ -747,7 +769,25 @@ export type ProviderAccessVisibility = "public" | "early_access";
|
|
|
747
769
|
|
|
748
770
|
export type ProviderProxyMode = "disabled" | "optional" | "required";
|
|
749
771
|
|
|
750
|
-
|
|
772
|
+
/**
|
|
773
|
+
* Proxy egress vendors. These are FOUR DISTINCT services — do not conflate them
|
|
774
|
+
* (a common mistake because the names collide with a well-known rebrand):
|
|
775
|
+
*
|
|
776
|
+
* - `smartproxy` — **api.smartproxy.org**, a residential proxy with an IP
|
|
777
|
+
* *extraction/allocation* API (app_key → a pool of raw `ip:port` CONNECT
|
|
778
|
+
* endpoints). This is our own vendor. It is NOT the company formerly named
|
|
779
|
+
* "Smartproxy". Credentials: `APIFUSE__PROXY__SMARTPROXY_APP_KEY`.
|
|
780
|
+
* - `nodemaven` — **gate.nodemaven.com**, a *gateway* proxy with static
|
|
781
|
+
* credentials; geo/session encoded in the username, no allocation API.
|
|
782
|
+
* - `decodo` — **decodo.com**, the *gateway* proxy that was named "Smartproxy"
|
|
783
|
+
* (smartproxy.com) before its 2025 rebrand to Decodo. Sticky sessions via
|
|
784
|
+
* username params. A different company from `smartproxy` above.
|
|
785
|
+
* **@deprecated** — unused; no managed adapter. Use `smartproxy`/`nodemaven`,
|
|
786
|
+
* or the `APIFUSE__PROXY__URL` bring-your-own escape hatch.
|
|
787
|
+
* - `custom` — **@deprecated** bring-your-own static proxy URL marker. The
|
|
788
|
+
* `APIFUSE__PROXY__URL` env still works without declaring this value.
|
|
789
|
+
*/
|
|
790
|
+
export type ProviderProxyProvider = "smartproxy" | "nodemaven" | "decodo" | "custom";
|
|
751
791
|
|
|
752
792
|
export type ProviderProxySessionAffinity =
|
|
753
793
|
| "request"
|
|
@@ -761,7 +801,18 @@ export interface ProviderProxyPolicy {
|
|
|
761
801
|
* certificate verification, and vendor allocator endpoints are SDK-owned.
|
|
762
802
|
*/
|
|
763
803
|
mode: ProviderProxyMode;
|
|
804
|
+
/**
|
|
805
|
+
* @deprecated Use `providers: [...]` to declare an ordered vendor fallback
|
|
806
|
+
* chain. A single-element `providers` list is equivalent to this field.
|
|
807
|
+
*/
|
|
764
808
|
provider?: ProviderProxyProvider;
|
|
809
|
+
/**
|
|
810
|
+
* Ordered proxy-vendor fallback chain. The SDK tries each vendor in order and
|
|
811
|
+
* fails over to the next when a vendor lacks credentials or its allocation /
|
|
812
|
+
* transport is exhausted. When omitted, `provider` (or the platform default)
|
|
813
|
+
* is used as a single-vendor chain.
|
|
814
|
+
*/
|
|
815
|
+
providers?: ProviderProxyProvider[];
|
|
765
816
|
geo?: {
|
|
766
817
|
/** ISO 3166-1 alpha-2 country code, for example KR or US. */
|
|
767
818
|
country?: Iso3166Alpha2CountryCode;
|
|
@@ -979,6 +1030,7 @@ export type HttpMethod =
|
|
|
979
1030
|
export interface StealthFetchOptions extends RequestOptions {
|
|
980
1031
|
method?: HttpMethod;
|
|
981
1032
|
body?: string | Buffer;
|
|
1033
|
+
redirect?: "follow" | "manual" | "error";
|
|
982
1034
|
/**
|
|
983
1035
|
* Offsets policy-managed proxy pool selection for caller-managed retries.
|
|
984
1036
|
* Use when a request receives an upstream challenge page rather than a
|
|
@@ -1005,9 +1057,20 @@ export interface CookieJar {
|
|
|
1005
1057
|
find?(predicate: (cookie: string) => boolean): string | undefined;
|
|
1006
1058
|
}
|
|
1007
1059
|
|
|
1060
|
+
export interface StealthSessionCookies extends CookieJar {
|
|
1061
|
+
has(name: string): boolean;
|
|
1062
|
+
setFromCookieStrings(cookieStrings: readonly string[]): void;
|
|
1063
|
+
toHeader(): string;
|
|
1064
|
+
snapshot(): Record<string, string>;
|
|
1065
|
+
restore(cookies: Record<string, string>): void;
|
|
1066
|
+
clear(): void;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1008
1069
|
export interface DeclarativeStealthResponse {
|
|
1009
1070
|
status: number;
|
|
1010
1071
|
ok: boolean;
|
|
1072
|
+
url?: string;
|
|
1073
|
+
redirected?: boolean;
|
|
1011
1074
|
headers: Record<string, string>;
|
|
1012
1075
|
rawHeaders: [string, string][];
|
|
1013
1076
|
body: string;
|
|
@@ -1026,8 +1089,34 @@ export type RequestWithMethodOptions = RequestOptions & {
|
|
|
1026
1089
|
body?: unknown;
|
|
1027
1090
|
};
|
|
1028
1091
|
|
|
1092
|
+
export interface StealthRedirectHop {
|
|
1093
|
+
url: string;
|
|
1094
|
+
status: number;
|
|
1095
|
+
method: string;
|
|
1096
|
+
location?: string;
|
|
1097
|
+
nextUrl?: string;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
export interface StealthRedirectRunOptions
|
|
1101
|
+
extends Omit<StealthFetchOptions, "redirect"> {
|
|
1102
|
+
url: string;
|
|
1103
|
+
maxHops?: number;
|
|
1104
|
+
stopWhen?: (hop: StealthRedirectHop) => boolean | Promise<boolean>;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
export interface StealthRedirectRunResult {
|
|
1108
|
+
final: StealthResponse;
|
|
1109
|
+
hops: StealthRedirectHop[];
|
|
1110
|
+
reason: "completed" | "stopped" | "max_hops" | "missing_location" | "loop";
|
|
1111
|
+
cookies: Record<string, string>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1029
1114
|
export interface StealthSession {
|
|
1030
1115
|
fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
|
|
1116
|
+
cookies: StealthSessionCookies;
|
|
1117
|
+
redirects: {
|
|
1118
|
+
run(options: StealthRedirectRunOptions): Promise<StealthRedirectRunResult>;
|
|
1119
|
+
};
|
|
1031
1120
|
close(): void;
|
|
1032
1121
|
}
|
|
1033
1122
|
|
|
@@ -1050,6 +1139,8 @@ export interface HttpResponse<T = unknown> {
|
|
|
1050
1139
|
data: T;
|
|
1051
1140
|
json<U = T>(): Promise<U>;
|
|
1052
1141
|
text(): Promise<string>;
|
|
1142
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
1143
|
+
bytes(): Promise<Uint8Array>;
|
|
1053
1144
|
}
|
|
1054
1145
|
|
|
1055
1146
|
export interface HttpStreamResponse {
|
|
@@ -1206,6 +1297,45 @@ export interface BrowserFrame {
|
|
|
1206
1297
|
locator(selector: string): BrowserLocator;
|
|
1207
1298
|
}
|
|
1208
1299
|
|
|
1300
|
+
export type BrowserResourceMethod = "GET" | "HEAD";
|
|
1301
|
+
|
|
1302
|
+
export type BrowserResourceRequest = {
|
|
1303
|
+
readonly url: string;
|
|
1304
|
+
readonly method: BrowserResourceMethod;
|
|
1305
|
+
readonly resourceType?: string;
|
|
1306
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
1307
|
+
};
|
|
1308
|
+
|
|
1309
|
+
export type BrowserResourceBody = Buffer | Uint8Array | ArrayBuffer | string;
|
|
1310
|
+
|
|
1311
|
+
export type BrowserResourceDecision =
|
|
1312
|
+
| {
|
|
1313
|
+
readonly action: "fulfill";
|
|
1314
|
+
readonly status?: number;
|
|
1315
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
1316
|
+
readonly body?: BrowserResourceBody;
|
|
1317
|
+
}
|
|
1318
|
+
| {
|
|
1319
|
+
readonly action: "block";
|
|
1320
|
+
readonly reason?: string;
|
|
1321
|
+
};
|
|
1322
|
+
|
|
1323
|
+
export type BrowserResourceRoute = {
|
|
1324
|
+
readonly match:
|
|
1325
|
+
| string
|
|
1326
|
+
| RegExp
|
|
1327
|
+
| ((request: BrowserResourceRequest) => boolean);
|
|
1328
|
+
readonly handle: (
|
|
1329
|
+
request: BrowserResourceRequest,
|
|
1330
|
+
) => Promise<BrowserResourceDecision> | BrowserResourceDecision;
|
|
1331
|
+
};
|
|
1332
|
+
|
|
1333
|
+
export type BrowserResourcePolicy = {
|
|
1334
|
+
readonly defaultAction?: "block";
|
|
1335
|
+
readonly allowedMethods?: readonly BrowserResourceMethod[];
|
|
1336
|
+
readonly routes: readonly BrowserResourceRoute[];
|
|
1337
|
+
};
|
|
1338
|
+
|
|
1209
1339
|
export interface BrowserPage extends BrowserFrame {
|
|
1210
1340
|
close(): Promise<void>;
|
|
1211
1341
|
fill(selector: string, text: string): Promise<void>;
|
|
@@ -1219,6 +1349,10 @@ export interface BrowserPage extends BrowserFrame {
|
|
|
1219
1349
|
options?: { timeout?: number },
|
|
1220
1350
|
): Promise<void>;
|
|
1221
1351
|
frames(): Promise<BrowserFrame[]>;
|
|
1352
|
+
withResourcePolicy<T>(
|
|
1353
|
+
policy: BrowserResourcePolicy,
|
|
1354
|
+
run: () => Promise<T>,
|
|
1355
|
+
): Promise<T>;
|
|
1222
1356
|
}
|
|
1223
1357
|
|
|
1224
1358
|
export type BrowserChallengeRequest = {
|
|
@@ -1397,6 +1531,84 @@ export interface ContextScratchpad {
|
|
|
1397
1531
|
|
|
1398
1532
|
export type FlowContextStore = ContextScratchpad;
|
|
1399
1533
|
|
|
1534
|
+
export type AuthSafeJson =
|
|
1535
|
+
| string
|
|
1536
|
+
| number
|
|
1537
|
+
| boolean
|
|
1538
|
+
| null
|
|
1539
|
+
| readonly AuthSafeJson[]
|
|
1540
|
+
| { readonly [key: string]: AuthSafeJson };
|
|
1541
|
+
|
|
1542
|
+
export type AuthSafeData = { readonly [key: string]: AuthSafeJson };
|
|
1543
|
+
|
|
1544
|
+
export type AuthAbortRetry = "never" | "retry" | "after_user_action";
|
|
1545
|
+
|
|
1546
|
+
export type AuthAbortData = Record<string, unknown> & {
|
|
1547
|
+
readonly code: string;
|
|
1548
|
+
readonly message?: string;
|
|
1549
|
+
readonly retry?: AuthAbortRetry;
|
|
1550
|
+
readonly actionHint?: AuthSafeJson;
|
|
1551
|
+
readonly fieldErrors?: { readonly [field: string]: string };
|
|
1552
|
+
readonly details?: AuthSafeData;
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
export interface AuthFlowTerminalContext {
|
|
1556
|
+
readonly signal?: AbortSignal;
|
|
1557
|
+
readonly deadline?: string;
|
|
1558
|
+
complete<TCredential extends Record<string, string>>(options: {
|
|
1559
|
+
readonly credential: TCredential;
|
|
1560
|
+
readonly metadata?: AuthSafeData;
|
|
1561
|
+
readonly data?: AuthSafeData;
|
|
1562
|
+
readonly turnId?: string;
|
|
1563
|
+
readonly expiresAt?: string;
|
|
1564
|
+
}): AuthTurn;
|
|
1565
|
+
abort(options: {
|
|
1566
|
+
readonly code: string;
|
|
1567
|
+
readonly message?: string;
|
|
1568
|
+
readonly retry?: AuthAbortRetry;
|
|
1569
|
+
readonly actionHint?: AuthSafeJson;
|
|
1570
|
+
readonly fieldErrors?: { readonly [field: string]: string };
|
|
1571
|
+
readonly data?: AuthSafeData;
|
|
1572
|
+
readonly turnId?: string;
|
|
1573
|
+
readonly expiresAt?: string;
|
|
1574
|
+
}): AuthTurn;
|
|
1575
|
+
nextForm(
|
|
1576
|
+
options: {
|
|
1577
|
+
readonly hintKey?: ProviderLocaleKeyInput;
|
|
1578
|
+
readonly data?: AuthSafeData;
|
|
1579
|
+
readonly turnId?: string;
|
|
1580
|
+
readonly expiresAt?: string;
|
|
1581
|
+
readonly timing?: AuthTurn["timing"];
|
|
1582
|
+
} & (
|
|
1583
|
+
| {
|
|
1584
|
+
readonly fields: Record<
|
|
1585
|
+
string,
|
|
1586
|
+
{
|
|
1587
|
+
readonly type?: "string" | "email" | "password" | "otp";
|
|
1588
|
+
readonly labelKey?: ProviderLocaleKeyInput;
|
|
1589
|
+
readonly descriptionKey?: ProviderLocaleKeyInput;
|
|
1590
|
+
readonly placeholderKey?: ProviderLocaleKeyInput;
|
|
1591
|
+
readonly required?: boolean;
|
|
1592
|
+
readonly sensitive?: boolean;
|
|
1593
|
+
}
|
|
1594
|
+
>;
|
|
1595
|
+
readonly expectedInput?: never;
|
|
1596
|
+
}
|
|
1597
|
+
| {
|
|
1598
|
+
readonly expectedInput: Record<string, unknown>;
|
|
1599
|
+
readonly fields?: never;
|
|
1600
|
+
}
|
|
1601
|
+
),
|
|
1602
|
+
): AuthTurn;
|
|
1603
|
+
nextPoll(options?: {
|
|
1604
|
+
readonly hintKey?: ProviderLocaleKeyInput;
|
|
1605
|
+
readonly data?: AuthSafeData;
|
|
1606
|
+
readonly turnId?: string;
|
|
1607
|
+
readonly expiresAt?: string;
|
|
1608
|
+
readonly timing?: AuthTurn["timing"];
|
|
1609
|
+
}): AuthTurn;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1400
1612
|
export interface FlowContext {
|
|
1401
1613
|
connectionId?: string;
|
|
1402
1614
|
externalRef?: string;
|
|
@@ -1408,6 +1620,7 @@ export interface FlowContext {
|
|
|
1408
1620
|
credential?: CredentialContext;
|
|
1409
1621
|
context: ContextScratchpad;
|
|
1410
1622
|
stt: SttContext;
|
|
1623
|
+
auth: AuthFlowTerminalContext;
|
|
1411
1624
|
}
|
|
1412
1625
|
|
|
1413
1626
|
export interface AuthTurn {
|
|
@@ -1575,6 +1788,19 @@ export interface OperationDefinition<
|
|
|
1575
1788
|
TInput extends SchemaLike = SchemaLike,
|
|
1576
1789
|
TOutput extends SchemaLike = SchemaLike,
|
|
1577
1790
|
> {
|
|
1791
|
+
/**
|
|
1792
|
+
* Short English display title for the operation. The SDK passes it through
|
|
1793
|
+
* verbatim; the APIFuse registry derives the operation's en locale title
|
|
1794
|
+
* baseline from it (`docs.titleKey` remains available as an explicit key
|
|
1795
|
+
* override).
|
|
1796
|
+
*/
|
|
1797
|
+
title?: string;
|
|
1798
|
+
/**
|
|
1799
|
+
* Raw English operation description. The SDK passes it through verbatim;
|
|
1800
|
+
* keyed descriptions via `descriptionKey` remain the primary flow, and
|
|
1801
|
+
* provider lint rules for raw prose descriptions still apply.
|
|
1802
|
+
*/
|
|
1803
|
+
description?: string;
|
|
1578
1804
|
descriptionKey?: ProviderLocaleKeyInput;
|
|
1579
1805
|
docs?: OperationDocMeta;
|
|
1580
1806
|
whenToUseKeys?: readonly ProviderLocaleKeyInput[];
|
|
@@ -1613,10 +1839,55 @@ export interface OperationDefinition<
|
|
|
1613
1839
|
healthCheckUnsupported?: HealthCheckUnsupported;
|
|
1614
1840
|
}
|
|
1615
1841
|
|
|
1842
|
+
/**
|
|
1843
|
+
* Author-declared deployment overrides accepted as the optional top-level
|
|
1844
|
+
* `deployment` key on `defineProvider()`.
|
|
1845
|
+
*
|
|
1846
|
+
* The SDK passes this object through VERBATIM onto the returned provider
|
|
1847
|
+
* definition — it is typed here but deliberately not deep-validated: the
|
|
1848
|
+
* APIFuse registry builder owns deployment validation and resolves omitted
|
|
1849
|
+
* fields against the runtime deployment profiles. The shape mirrors the
|
|
1850
|
+
* registry's `ProviderDeploymentOverrides` contract; every field is
|
|
1851
|
+
* optional. Note that the deployment `runtime` axis
|
|
1852
|
+
* (`shared`/`dedicated`/`browser`) is distinct from the provider execution
|
|
1853
|
+
* `runtime` (`standard`/`shared`/`browser`).
|
|
1854
|
+
*/
|
|
1855
|
+
export interface ProviderDeploymentOverrides {
|
|
1856
|
+
runtime?: "shared" | "dedicated" | "browser";
|
|
1857
|
+
language?: "typescript" | "python";
|
|
1858
|
+
replicas?: number;
|
|
1859
|
+
hpa?: {
|
|
1860
|
+
enabled: boolean;
|
|
1861
|
+
minReplicas?: number;
|
|
1862
|
+
maxReplicas?: number;
|
|
1863
|
+
targetCPUUtilizationPercentage?: number;
|
|
1864
|
+
};
|
|
1865
|
+
resources?: {
|
|
1866
|
+
cpu: string;
|
|
1867
|
+
memory: string;
|
|
1868
|
+
};
|
|
1869
|
+
cache?: {
|
|
1870
|
+
redis?: {
|
|
1871
|
+
enabled: boolean;
|
|
1872
|
+
url?: string;
|
|
1873
|
+
};
|
|
1874
|
+
};
|
|
1875
|
+
network?: {
|
|
1876
|
+
additionalTcpPorts?: number[];
|
|
1877
|
+
};
|
|
1878
|
+
buildContext?: string;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1616
1881
|
export interface ProviderDefinition {
|
|
1617
1882
|
id: string;
|
|
1618
1883
|
version: string;
|
|
1619
1884
|
runtime: "standard" | "shared" | "browser";
|
|
1885
|
+
/**
|
|
1886
|
+
* Optional deployment overrides, passed through verbatim from
|
|
1887
|
+
* `defineProvider({ deployment })`. Validation and profile resolution are
|
|
1888
|
+
* owned by the APIFuse registry builder, not the SDK.
|
|
1889
|
+
*/
|
|
1890
|
+
deployment?: ProviderDeploymentOverrides;
|
|
1620
1891
|
allowedHosts?: string[];
|
|
1621
1892
|
stealth?: {
|
|
1622
1893
|
profile: string;
|
|
@@ -1636,5 +1907,7 @@ export interface ProviderDefinition {
|
|
|
1636
1907
|
meta: ProviderMeta;
|
|
1637
1908
|
operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
|
|
1638
1909
|
healthMonitor?: ProviderHealthMonitorConfig;
|
|
1910
|
+
/** Transitional alias for `healthMonitor`; `defineProvider` mirrors both. */
|
|
1911
|
+
healthProbe?: ProviderHealthProbeConfig;
|
|
1639
1912
|
healthJourneys?: readonly HealthJourneyDefinition[];
|
|
1640
1913
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Official cross-provider contract for user-input round-trips.
|
|
2
|
+
//
|
|
3
|
+
// Doctrine (born from the 2026-07-20 CatchTable reserve incident): an
|
|
4
|
+
// operation MUST NOT dead-end on a problem the end user can resolve by
|
|
5
|
+
// choosing among live options. Instead of throwing, the provider returns a
|
|
6
|
+
// SUCCESSFUL payload with `status: "needs_input"` that carries everything a
|
|
7
|
+
// consumer-side agent needs to relay the choice verbatim and retry:
|
|
8
|
+
//
|
|
9
|
+
// - `required_selections`: only the still-pending questions, each with
|
|
10
|
+
// human-readable `label`s and `valid_options` the agent shows the user
|
|
11
|
+
// as-is. The agent never chooses on the user's behalf.
|
|
12
|
+
// - `selected_options`: selections already settled, echoed so the follow-up
|
|
13
|
+
// call keeps them without the agent reconstructing anything.
|
|
14
|
+
// - a fresh provider-specific state token (e.g. `reservation_state`) minted
|
|
15
|
+
// at response time, so the retry never races an expired token.
|
|
16
|
+
//
|
|
17
|
+
// Keeping this success-shaped (instead of error `details`) is deliberate:
|
|
18
|
+
// consumer error-shaping layers routinely strip error metadata, and a model
|
|
19
|
+
// that only sees "error" narrates failure to the user. Complex recovery
|
|
20
|
+
// logic belongs to the system, not the model.
|
|
21
|
+
//
|
|
22
|
+
// Deliberately ABSENT: retry templates, next-action routing, or any other
|
|
23
|
+
// agent choreography. Provider payloads carry upstream-backed data only; how
|
|
24
|
+
// to phrase the ask and shape the retry call is the consumer's contract
|
|
25
|
+
// (apifuse#1030). The retry is fully determined by data: copy the echoed
|
|
26
|
+
// selected_options, add the user's new answers, resend with the fresh state.
|
|
27
|
+
|
|
28
|
+
export const NEEDS_INPUT_STATUS = "needs_input" as const;
|
|
29
|
+
|
|
30
|
+
export interface ProviderSelectionOption {
|
|
31
|
+
readonly selection_value: string;
|
|
32
|
+
readonly label: string;
|
|
33
|
+
readonly [extra: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ProviderRequiredSelection {
|
|
37
|
+
readonly selection_key: string;
|
|
38
|
+
readonly label: string;
|
|
39
|
+
readonly required: boolean;
|
|
40
|
+
readonly selection_type?: string;
|
|
41
|
+
readonly valid_options: readonly ProviderSelectionOption[];
|
|
42
|
+
readonly [extra: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ProviderSelectedOption {
|
|
46
|
+
readonly selection_key: string;
|
|
47
|
+
readonly selection_value: string;
|
|
48
|
+
/** Free-text answer for text-kind selections. */
|
|
49
|
+
readonly text?: string;
|
|
50
|
+
/** Quantity for quantity-kind selections. */
|
|
51
|
+
readonly quantity?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ProviderNeedsInputPayload {
|
|
55
|
+
readonly status: typeof NEEDS_INPUT_STATUS;
|
|
56
|
+
readonly required_selections: readonly ProviderRequiredSelection[];
|
|
57
|
+
readonly selected_options?: readonly ProviderSelectedOption[];
|
|
58
|
+
/** Provider-specific fresh state token(s), e.g. `reservation_state`. */
|
|
59
|
+
readonly [extra: string]: unknown;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
63
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isSelectionOption(value: unknown): value is ProviderSelectionOption {
|
|
67
|
+
return (
|
|
68
|
+
isRecord(value) &&
|
|
69
|
+
typeof value.selection_value === "string" &&
|
|
70
|
+
typeof value.label === "string"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isRequiredSelection(
|
|
75
|
+
value: unknown,
|
|
76
|
+
): value is ProviderRequiredSelection {
|
|
77
|
+
return (
|
|
78
|
+
isRecord(value) &&
|
|
79
|
+
typeof value.selection_key === "string" &&
|
|
80
|
+
typeof value.label === "string" &&
|
|
81
|
+
typeof value.required === "boolean" &&
|
|
82
|
+
Array.isArray(value.valid_options) &&
|
|
83
|
+
value.valid_options.every(isSelectionOption)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isSelectedOption(value: unknown): value is ProviderSelectedOption {
|
|
88
|
+
return (
|
|
89
|
+
isRecord(value) &&
|
|
90
|
+
typeof value.selection_key === "string" &&
|
|
91
|
+
typeof value.selection_value === "string"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function isProviderNeedsInputPayload(
|
|
96
|
+
value: unknown,
|
|
97
|
+
): value is ProviderNeedsInputPayload {
|
|
98
|
+
if (!isRecord(value)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (
|
|
102
|
+
value.status !== NEEDS_INPUT_STATUS ||
|
|
103
|
+
!Array.isArray(value.required_selections) ||
|
|
104
|
+
!value.required_selections.every(isRequiredSelection)
|
|
105
|
+
) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
// A needs_input with nothing to ask AND nothing settled to echo is a
|
|
109
|
+
// no-op dead end — reject it so providers cannot ship it accidentally.
|
|
110
|
+
if (value.required_selections.length > 0) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return (
|
|
114
|
+
Array.isArray(value.selected_options) &&
|
|
115
|
+
value.selected_options.length > 0 &&
|
|
116
|
+
value.selected_options.every(isSelectedOption)
|
|
117
|
+
);
|
|
118
|
+
}
|