@apifuse/provider-sdk 2.2.0-beta.21 → 2.2.0-beta.23
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/CHANGELOG.md +12 -0
- package/bin/apifuse-dev.ts +2 -0
- package/bin/apifuse-record.ts +2 -0
- package/dist/contract-types.d.ts +1 -0
- package/dist/contract.js +2 -0
- package/dist/define.d.ts +2 -1
- package/dist/define.js +15 -0
- package/dist/error-resolution.d.ts +2 -0
- package/dist/error-resolution.js +32 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/lint.d.ts +5 -0
- package/dist/lint.js +277 -0
- package/dist/runtime/auth-flow.d.ts +2 -1
- package/dist/runtime/auth-flow.js +2 -0
- package/dist/runtime/browser.js +28 -9
- package/dist/runtime/ocr.d.ts +29 -0
- package/dist/runtime/ocr.js +440 -0
- package/dist/runtime/stt.js +1 -12
- package/dist/runtime/timeout.d.ts +5 -0
- package/dist/runtime/timeout.js +12 -0
- package/dist/server/serve.d.ts +3 -1
- package/dist/server/serve.js +12 -29
- package/dist/testing/run.js +3 -0
- package/dist/types.d.ts +51 -0
- package/package.json +1 -1
- package/src/contract-types.ts +1 -0
- package/src/contract.ts +2 -0
- package/src/define.ts +17 -0
- package/src/error-resolution.ts +36 -0
- package/src/index.ts +25 -0
- package/src/lint.ts +303 -0
- package/src/runtime/auth-flow.ts +4 -0
- package/src/runtime/browser.ts +70 -19
- package/src/runtime/ocr.ts +523 -0
- package/src/runtime/stt.ts +1 -19
- package/src/runtime/timeout.ts +18 -0
- package/src/server/serve.ts +15 -28
- package/src/testing/run.ts +7 -0
- package/src/types.ts +58 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @apifuse/provider-sdk Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.0-beta.23
|
|
4
|
+
|
|
5
|
+
- Release candidate for main commit 36b3bedc9c14913c4152c4631cc87de71062f21f.
|
|
6
|
+
|
|
7
|
+
## 2.2.0-beta.22
|
|
8
|
+
|
|
9
|
+
- Release candidate for main commit b8bf920b5ca053d1bf43018167fd4eedff01700d.
|
|
10
|
+
|
|
11
|
+
## Unreleased
|
|
12
|
+
|
|
13
|
+
- Added the `thrown-error-code-undeclared` authoring lint (warning level): `apifuse check` now statically flags literal `ProviderError`/`ValidationError` codes that are neither SDK-registered nor declared in any operation's `docs.errorCodes`, surfacing the runtime `unregistered_provider_error_code` signal at check time. The canonical SDK code→status mapping moved to `SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES` in `error-resolution.ts`, shared by the runtime status resolver and the lint.
|
|
14
|
+
|
|
3
15
|
## 2.2.0-beta.21
|
|
4
16
|
|
|
5
17
|
- Release candidate for main commit 00f61024fb18db39711dc5076c4621508baa49f5.
|
package/bin/apifuse-dev.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
createCredentialContext,
|
|
9
9
|
createEnvContext,
|
|
10
10
|
createHttpClient,
|
|
11
|
+
createOcrClientFromEnv,
|
|
11
12
|
createProviderCache,
|
|
12
13
|
createProviderChoiceContext,
|
|
13
14
|
createStealthClient,
|
|
@@ -96,6 +97,7 @@ export function createProviderContext(provider: ProviderDefinition): {
|
|
|
96
97
|
state,
|
|
97
98
|
trace: createTraceContext(),
|
|
98
99
|
stealth: createStealthClient("http://localhost"),
|
|
100
|
+
ocr: createOcrClientFromEnv(provider.ocr),
|
|
99
101
|
stt: createSttClientFromEnv(provider.stt),
|
|
100
102
|
choice: createProviderChoiceContext({
|
|
101
103
|
providerId: provider.id,
|
package/bin/apifuse-record.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { pathToFileURL } from "node:url";
|
|
|
8
8
|
import {
|
|
9
9
|
createBypassProviderCache,
|
|
10
10
|
createHttpClient,
|
|
11
|
+
createOcrClientFromEnv,
|
|
11
12
|
createProviderChoiceContext,
|
|
12
13
|
createStealthClient,
|
|
13
14
|
createSttClientFromEnv,
|
|
@@ -536,6 +537,7 @@ function createCaptureContext(provider: ProviderRuntime, baseUrl: string, saniti
|
|
|
536
537
|
throw new Error("Auth prompts are not available in apifuse record.");
|
|
537
538
|
},
|
|
538
539
|
},
|
|
540
|
+
ocr: createOcrClientFromEnv(provider.ocr),
|
|
539
541
|
stt: createSttClientFromEnv(provider.stt),
|
|
540
542
|
choice: createProviderChoiceContext({
|
|
541
543
|
providerId: provider.id,
|
package/dist/contract-types.d.ts
CHANGED
|
@@ -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, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, NativeProviderConfig, ProviderOcrConfig, ProviderAccessConfig, ProviderDefinition, ProviderDeploymentOverrides, ProviderHealthMonitorConfig, ProviderProxyConfig, ProviderPublicProfile, 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 {
|
|
@@ -55,6 +55,7 @@ export interface ProviderConfig<TOperations extends Record<string, ProviderOpera
|
|
|
55
55
|
platform: StealthPlatform;
|
|
56
56
|
};
|
|
57
57
|
proxy?: ProviderProxyConfig;
|
|
58
|
+
ocr?: ProviderOcrConfig;
|
|
58
59
|
stt?: ProviderSttConfig;
|
|
59
60
|
browser?: {
|
|
60
61
|
engine: BrowserEngine;
|
package/dist/define.js
CHANGED
|
@@ -47,6 +47,7 @@ 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"];
|
|
51
52
|
const SMARTPROXY_APP_KEY_SECRET = "APIFUSE__PROXY__SMARTPROXY_APP_KEY";
|
|
52
53
|
const NODEMAVEN_USERNAME_SECRET = "APIFUSE__PROXY__NODEMAVEN_USERNAME";
|
|
@@ -377,6 +378,18 @@ function validateProviderStt(config) {
|
|
|
377
378
|
rejectUnknownFields(stt, new Set(["mode"]), "stt");
|
|
378
379
|
assertLiteralField(stt.mode, "stt.mode", VALID_PROVIDER_STT_MODES, config.id);
|
|
379
380
|
}
|
|
381
|
+
function validateProviderOcr(config) {
|
|
382
|
+
const ocr = config.ocr;
|
|
383
|
+
if (ocr === undefined)
|
|
384
|
+
return;
|
|
385
|
+
if (!ocr || typeof ocr !== "object" || Array.isArray(ocr)) {
|
|
386
|
+
throw new ValidationError(`Provider "${config.id}" has invalid ocr: must be an object.`, {
|
|
387
|
+
fix: `Use ocr: { mode: "required" } or ocr: { mode: "optional" }.`,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
rejectUnknownFields(ocr, new Set(["mode"]), "ocr");
|
|
391
|
+
assertLiteralField(ocr.mode, "ocr.mode", VALID_PROVIDER_OCR_MODES, config.id);
|
|
392
|
+
}
|
|
380
393
|
function validateOperationIds(providerId, operations) {
|
|
381
394
|
for (const operationName of Object.keys(operations)) {
|
|
382
395
|
if (!OPERATION_ID_REGEX.test(operationName))
|
|
@@ -1538,6 +1551,7 @@ export function defineProvider(config) {
|
|
|
1538
1551
|
throw error;
|
|
1539
1552
|
}
|
|
1540
1553
|
validateProviderProxy(config);
|
|
1554
|
+
validateProviderOcr(config);
|
|
1541
1555
|
validateProviderStt(config);
|
|
1542
1556
|
if (config.runtime === "browser" && !config.browser)
|
|
1543
1557
|
throw new ProviderError(`Provider "${config.id}" must define browser.engine when runtime is "browser"`, {
|
|
@@ -1556,6 +1570,7 @@ export function defineProvider(config) {
|
|
|
1556
1570
|
native: config.native,
|
|
1557
1571
|
stealth: config.stealth,
|
|
1558
1572
|
proxy: config.proxy,
|
|
1573
|
+
ocr: config.ocr,
|
|
1559
1574
|
stt: config.stt,
|
|
1560
1575
|
browser: config.browser,
|
|
1561
1576
|
auth: config.auth,
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
import type { ProviderErrorStatus } from "./types.js";
|
|
1
2
|
export declare const SDK_OWNED_PROVIDER_ERROR_CODES: Set<string>;
|
|
2
3
|
export declare const SDK_RUNTIME_OWNED_ERROR_CODES: Set<string>;
|
|
4
|
+
export declare const SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES: ReadonlyMap<string, ProviderErrorStatus>;
|
package/dist/error-resolution.js
CHANGED
|
@@ -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,9 +83,40 @@ 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",
|
|
88
91
|
"NOT_FOUND",
|
|
89
92
|
"not_found",
|
|
90
93
|
]);
|
|
94
|
+
// Canonical SDK status mapping for recognized provider-thrown error codes.
|
|
95
|
+
// serve.ts toStatusCode consults this map (after operation-declared overrides
|
|
96
|
+
// for non-SDK-owned codes), and the authoring lint treats these codes as
|
|
97
|
+
// SDK-registered. Add new codes here instead of duplicating literals in
|
|
98
|
+
// either consumer.
|
|
99
|
+
export const SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES = new Map([
|
|
100
|
+
["AUTH_REQUIRED", 401],
|
|
101
|
+
["reauth_required", 401],
|
|
102
|
+
// Unprovisioned declared secret: a deployment/config defect, never an
|
|
103
|
+
// upstream failure — explicit 400.
|
|
104
|
+
["MISSING_SECRET", 400],
|
|
105
|
+
["NOT_FOUND", 404],
|
|
106
|
+
["not_found", 404],
|
|
107
|
+
["NO_DATA", 404],
|
|
108
|
+
["RATE_LIMITED", 429],
|
|
109
|
+
["UPSTREAM_RATE_LIMIT", 429],
|
|
110
|
+
["LIMITED_NUMBER_OF_SERVICE_REQUESTS_EXCEEDS_ERROR", 429],
|
|
111
|
+
// Deterministic upstream business refusal (honest-provider-error-
|
|
112
|
+
// contract): the upstream evaluated the request and said no under its
|
|
113
|
+
// own rules — a conflict with upstream state, never a 5xx.
|
|
114
|
+
["UPSTREAM_REJECTED", 409],
|
|
115
|
+
["UPSTREAM_ERROR", 502],
|
|
116
|
+
["BLOCKED", 502],
|
|
117
|
+
["OCR_UNAVAILABLE", 503],
|
|
118
|
+
["UNSUPPORTED_OCR_BACKEND", 503],
|
|
119
|
+
["STT_UNAVAILABLE", 503],
|
|
120
|
+
["UNSUPPORTED_STT_BACKEND", 503],
|
|
121
|
+
["STATEFUL_FORWARDING_REPLAY_CACHE_FULL", 503],
|
|
122
|
+
]);
|
package/dist/index.d.ts
CHANGED
|
@@ -32,13 +32,14 @@ export { getProviderBaseUrl } from "./runtime/provider.js";
|
|
|
32
32
|
export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
|
|
33
33
|
export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
|
|
34
34
|
export { createStealthClient } from "./runtime/stealth.js";
|
|
35
|
+
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
36
|
export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
|
|
36
37
|
export { type CreateTraceContextOptions, createTraceContext, type Span, type TraceContext, } from "./runtime/trace.js";
|
|
37
38
|
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
39
|
export { createServerApp, ERROR_OBSERVABILITY_HEADER, type ServeOptions, serve, } from "./server/index.js";
|
|
39
40
|
export { getStealthProfile, listStealthProfiles } from "./stealth/profiles.js";
|
|
40
41
|
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";
|
|
42
|
+
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, 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, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderOcrConfig, 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";
|
|
42
43
|
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
44
|
export * from "./utils/date.js";
|
|
44
45
|
export * from "./utils/parse.js";
|
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export { getProviderBaseUrl } from "./runtime/provider.js";
|
|
|
29
29
|
export { assertRequiredSecretsPresent, listMissingRequiredSecrets, MISSING_SECRET_CODE, } from "./runtime/secrets.js";
|
|
30
30
|
export { createUnsupportedProviderRuntimeState, UnsupportedProviderStateError, } from "./runtime/state.js";
|
|
31
31
|
export { createStealthClient } from "./runtime/stealth.js";
|
|
32
|
+
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
33
|
export { APIFUSE__STT__BACKEND_ENV, APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV, APIFUSE__STT__MODEL_ENV, createSttClientFromEnv, createUnsupportedSttClient, extractVerificationCode, resolveSttPrompt, } from "./runtime/stt.js";
|
|
33
34
|
export { createTraceContext, } from "./runtime/trace.js";
|
|
34
35
|
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";
|
package/dist/lint.d.ts
CHANGED
|
@@ -65,6 +65,11 @@ export declare function lintProvider(provider: {
|
|
|
65
65
|
derivations?: Record<string, string>;
|
|
66
66
|
handler?: unknown;
|
|
67
67
|
source?: string;
|
|
68
|
+
docs?: {
|
|
69
|
+
errorCodes?: ReadonlyArray<{
|
|
70
|
+
code: string;
|
|
71
|
+
}>;
|
|
72
|
+
};
|
|
68
73
|
}>;
|
|
69
74
|
meta?: {
|
|
70
75
|
contract?: ProviderContractMetaLike;
|
package/dist/lint.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SDK_RUNTIME_OWNED_ERROR_CODES, SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES, } from "./error-resolution.js";
|
|
1
2
|
import { lintPublicSchemaFieldNames } from "./public-schema-field-lint.js";
|
|
2
3
|
import { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_SENSITIVE_META_KEY } from "./schema.js";
|
|
3
4
|
const AUTH_OPERATION_ID_PATTERN = /^(?:auth[-_])?(?:login|exchange|continue|refresh|callback)(?:[-_]|$)/i;
|
|
@@ -587,6 +588,281 @@ function lintSelfHostedBrowserPatterns(provider, options) {
|
|
|
587
588
|
}
|
|
588
589
|
return diagnostics;
|
|
589
590
|
}
|
|
591
|
+
const THROWN_ERROR_CONSTRUCTION_PATTERN = /new\s+(?:ProviderError|ValidationError)\s*\(/g;
|
|
592
|
+
const TEST_SOURCE_FILE_PATTERN = /(?:^|\/)(?:__tests__|__mocks__)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/;
|
|
593
|
+
/**
|
|
594
|
+
* Skips a string literal starting at `startIndex` (which must point at the
|
|
595
|
+
* opening quote). Returns the index of the closing quote, or -1 when the
|
|
596
|
+
* literal is unterminated. Template literals handle nested `${...}`
|
|
597
|
+
* expressions, including strings inside them.
|
|
598
|
+
*/
|
|
599
|
+
function skipStringLiteral(source, startIndex) {
|
|
600
|
+
const quote = source[startIndex];
|
|
601
|
+
for (let index = startIndex + 1; index < source.length; index++) {
|
|
602
|
+
const char = source[index];
|
|
603
|
+
if (char === "\\") {
|
|
604
|
+
index++;
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
if (quote === "`" && char === "$" && source[index + 1] === "{") {
|
|
608
|
+
index = skipTemplateExpression(source, index + 2);
|
|
609
|
+
if (index < 0) {
|
|
610
|
+
return -1;
|
|
611
|
+
}
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
if (char === quote) {
|
|
615
|
+
return index;
|
|
616
|
+
}
|
|
617
|
+
if (quote !== "`" && char === "\n") {
|
|
618
|
+
return -1;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return -1;
|
|
622
|
+
}
|
|
623
|
+
function skipTemplateExpression(source, startIndex) {
|
|
624
|
+
let depth = 1;
|
|
625
|
+
for (let index = startIndex; index < source.length; index++) {
|
|
626
|
+
const char = source[index];
|
|
627
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
628
|
+
index = skipStringLiteral(source, index);
|
|
629
|
+
if (index < 0) {
|
|
630
|
+
return -1;
|
|
631
|
+
}
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (char === "{") {
|
|
635
|
+
depth++;
|
|
636
|
+
}
|
|
637
|
+
else if (char === "}") {
|
|
638
|
+
depth--;
|
|
639
|
+
if (depth === 0) {
|
|
640
|
+
return index;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return -1;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Extracts the argument text of a call whose opening paren has already been
|
|
648
|
+
* consumed (`startIndex` points just past it). Returns undefined when the
|
|
649
|
+
* call never closes in this source, which the caller treats as "skip
|
|
650
|
+
* silently" — this scanner is conservative by design.
|
|
651
|
+
*/
|
|
652
|
+
function extractBalancedCallArguments(source, startIndex) {
|
|
653
|
+
let depth = 1;
|
|
654
|
+
for (let index = startIndex; index < source.length; index++) {
|
|
655
|
+
const char = source[index];
|
|
656
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
657
|
+
index = skipStringLiteral(source, index);
|
|
658
|
+
if (index < 0) {
|
|
659
|
+
return undefined;
|
|
660
|
+
}
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
if (char === "/" && source[index + 1] === "/") {
|
|
664
|
+
const newline = source.indexOf("\n", index);
|
|
665
|
+
if (newline === -1) {
|
|
666
|
+
return undefined;
|
|
667
|
+
}
|
|
668
|
+
index = newline;
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
if (char === "/" && source[index + 1] === "*") {
|
|
672
|
+
const end = source.indexOf("*/", index + 2);
|
|
673
|
+
if (end === -1) {
|
|
674
|
+
return undefined;
|
|
675
|
+
}
|
|
676
|
+
index = end + 1;
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
if (char === "(") {
|
|
680
|
+
depth++;
|
|
681
|
+
}
|
|
682
|
+
else if (char === ")") {
|
|
683
|
+
depth--;
|
|
684
|
+
if (depth === 0) {
|
|
685
|
+
return source.slice(startIndex, index);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return undefined;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Collects literal string values of top-level `code:` properties inside a
|
|
693
|
+
* ProviderError/ValidationError options object. Only plain `"..."` / `'...'`
|
|
694
|
+
* literals at options-object depth count; computed codes (identifiers,
|
|
695
|
+
* ternaries, template substitutions, concatenations, escapes) are skipped
|
|
696
|
+
* silently so the rule never guesses.
|
|
697
|
+
*/
|
|
698
|
+
function collectLiteralErrorCodeValues(args) {
|
|
699
|
+
const codes = [];
|
|
700
|
+
let braceDepth = 0;
|
|
701
|
+
let parenDepth = 0;
|
|
702
|
+
let bracketDepth = 0;
|
|
703
|
+
let previousSignificantChar = "";
|
|
704
|
+
for (let index = 0; index < args.length; index++) {
|
|
705
|
+
const char = args[index] ?? "";
|
|
706
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
707
|
+
const end = skipStringLiteral(args, index);
|
|
708
|
+
if (end < 0) {
|
|
709
|
+
return codes;
|
|
710
|
+
}
|
|
711
|
+
index = end;
|
|
712
|
+
previousSignificantChar = char;
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
if (char === "/" && args[index + 1] === "/") {
|
|
716
|
+
const newline = args.indexOf("\n", index);
|
|
717
|
+
if (newline === -1) {
|
|
718
|
+
return codes;
|
|
719
|
+
}
|
|
720
|
+
index = newline;
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
if (char === "/" && args[index + 1] === "*") {
|
|
724
|
+
const end = args.indexOf("*/", index + 2);
|
|
725
|
+
if (end === -1) {
|
|
726
|
+
return codes;
|
|
727
|
+
}
|
|
728
|
+
index = end + 1;
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
if (/\s/.test(char)) {
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (char === "{") {
|
|
735
|
+
braceDepth++;
|
|
736
|
+
}
|
|
737
|
+
else if (char === "}") {
|
|
738
|
+
braceDepth--;
|
|
739
|
+
}
|
|
740
|
+
else if (char === "(") {
|
|
741
|
+
parenDepth++;
|
|
742
|
+
}
|
|
743
|
+
else if (char === ")") {
|
|
744
|
+
parenDepth--;
|
|
745
|
+
}
|
|
746
|
+
else if (char === "[") {
|
|
747
|
+
bracketDepth++;
|
|
748
|
+
}
|
|
749
|
+
else if (char === "]") {
|
|
750
|
+
bracketDepth--;
|
|
751
|
+
}
|
|
752
|
+
else if (braceDepth === 1 &&
|
|
753
|
+
parenDepth === 0 &&
|
|
754
|
+
bracketDepth === 0 &&
|
|
755
|
+
(previousSignificantChar === "{" || previousSignificantChar === ",") &&
|
|
756
|
+
args.startsWith("code", index)) {
|
|
757
|
+
let cursor = index + "code".length;
|
|
758
|
+
while (cursor < args.length && /\s/.test(args[cursor] ?? "")) {
|
|
759
|
+
cursor++;
|
|
760
|
+
}
|
|
761
|
+
if (args[cursor] === ":") {
|
|
762
|
+
cursor++;
|
|
763
|
+
while (cursor < args.length && /\s/.test(args[cursor] ?? "")) {
|
|
764
|
+
cursor++;
|
|
765
|
+
}
|
|
766
|
+
const quote = args[cursor];
|
|
767
|
+
if (quote === '"' || quote === "'") {
|
|
768
|
+
const end = skipStringLiteral(args, cursor);
|
|
769
|
+
if (end > cursor) {
|
|
770
|
+
const value = args.slice(cursor + 1, end);
|
|
771
|
+
let after = end + 1;
|
|
772
|
+
while (after < args.length && /\s/.test(args[after] ?? "")) {
|
|
773
|
+
after++;
|
|
774
|
+
}
|
|
775
|
+
const nextChar = after < args.length ? (args[after] ?? "") : "";
|
|
776
|
+
if (!value.includes("\\") && (nextChar === "," || nextChar === "}" || nextChar === "")) {
|
|
777
|
+
codes.push(value);
|
|
778
|
+
}
|
|
779
|
+
index = end;
|
|
780
|
+
previousSignificantChar = quote;
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
return codes;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
previousSignificantChar = char;
|
|
788
|
+
}
|
|
789
|
+
return codes;
|
|
790
|
+
}
|
|
791
|
+
function collectLiteralThrownErrorCodes(source) {
|
|
792
|
+
const codes = [];
|
|
793
|
+
THROWN_ERROR_CONSTRUCTION_PATTERN.lastIndex = 0;
|
|
794
|
+
for (let match = THROWN_ERROR_CONSTRUCTION_PATTERN.exec(source); match; match = THROWN_ERROR_CONSTRUCTION_PATTERN.exec(source)) {
|
|
795
|
+
const argsStart = match.index + match[0].length;
|
|
796
|
+
const args = extractBalancedCallArguments(source, argsStart);
|
|
797
|
+
if (args !== undefined) {
|
|
798
|
+
codes.push(...collectLiteralErrorCodeValues(args));
|
|
799
|
+
}
|
|
800
|
+
THROWN_ERROR_CONSTRUCTION_PATTERN.lastIndex = argsStart;
|
|
801
|
+
}
|
|
802
|
+
return codes;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Static counterpart of the runtime `unregistered_provider_error_code`
|
|
806
|
+
* signal (honest-provider-error-contract Phase 3.5.5): flags
|
|
807
|
+
* `new ProviderError(...)` / `new ValidationError(...)` constructions whose
|
|
808
|
+
* literal `code` is neither SDK-registered (SDK_RUNTIME_OWNED_ERROR_CODES
|
|
809
|
+
* plus the canonical status-mapped codes shared with serve.ts toStatusCode)
|
|
810
|
+
* nor declared in any operation's docs.errorCodes. At runtime such a code
|
|
811
|
+
* serves HTTP 500 and emits the signal; this rule surfaces it at check time.
|
|
812
|
+
*
|
|
813
|
+
* A throw site cannot be attributed to a specific operation statically —
|
|
814
|
+
* providers routinely throw from helpers shared across operations — so this
|
|
815
|
+
* rule matches against the provider-level union of declared codes. That is
|
|
816
|
+
* the honest scope: it will not catch a code declared only on the "wrong"
|
|
817
|
+
* operation, and it never claims per-operation attribution it cannot prove.
|
|
818
|
+
* Only literal string codes are checked; computed/dynamic codes and test
|
|
819
|
+
* sources are skipped silently. Warning level: the long tail of existing
|
|
820
|
+
* providers converges gradually, so this must not fail `apifuse check`.
|
|
821
|
+
*/
|
|
822
|
+
function lintUndeclaredThrownErrorCodes(provider) {
|
|
823
|
+
const knownCodes = new Set([
|
|
824
|
+
...SDK_RUNTIME_OWNED_ERROR_CODES,
|
|
825
|
+
...SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES.keys(),
|
|
826
|
+
]);
|
|
827
|
+
for (const operation of Object.values(provider.operations ?? {})) {
|
|
828
|
+
for (const entry of operation.docs?.errorCodes ?? []) {
|
|
829
|
+
if (typeof entry?.code === "string") {
|
|
830
|
+
knownCodes.add(entry.code);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
const sources = [];
|
|
835
|
+
const sourceFiles = Object.entries(provider.providerSourceFiles ?? {}).filter(([filePath]) => !TEST_SOURCE_FILE_PATTERN.test(filePath));
|
|
836
|
+
if (sourceFiles.length > 0) {
|
|
837
|
+
for (const [filePath, source] of sourceFiles) {
|
|
838
|
+
sources.push({ field: `sourceFiles.${filePath}`, source });
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
if (provider.authFlowSource) {
|
|
843
|
+
sources.push({ field: "auth.flow", source: provider.authFlowSource });
|
|
844
|
+
}
|
|
845
|
+
for (const [operationKey, operation] of Object.entries(provider.operations ?? {})) {
|
|
846
|
+
const source = getOperationSource(operation);
|
|
847
|
+
if (source) {
|
|
848
|
+
sources.push({ field: `operations.${operationKey}.handler`, source });
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
const diagnostics = [];
|
|
853
|
+
for (const { field, source } of sources) {
|
|
854
|
+
const undeclaredCodes = new Set(collectLiteralThrownErrorCodes(source).filter((code) => !knownCodes.has(code)));
|
|
855
|
+
for (const code of undeclaredCodes) {
|
|
856
|
+
diagnostics.push({
|
|
857
|
+
rule: "thrown-error-code-undeclared",
|
|
858
|
+
level: "warn",
|
|
859
|
+
field,
|
|
860
|
+
message: `Thrown error code "${code}" (${field}) is neither SDK-registered nor declared in any operation's docs.errorCodes; at runtime it serves HTTP 500 and emits the unregistered_provider_error_code signal. Declare it in the owning operation's docs.errorCodes with status and retryable.`,
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
return diagnostics;
|
|
865
|
+
}
|
|
590
866
|
export function lintOperation(op) {
|
|
591
867
|
const diagnostics = [];
|
|
592
868
|
const description = op.description ?? "";
|
|
@@ -677,6 +953,7 @@ export function lintProvider(provider, options = {}) {
|
|
|
677
953
|
...lintCredentialWriteUsage(provider),
|
|
678
954
|
...lintPlaywrightDirectImports(provider),
|
|
679
955
|
...lintSelfHostedBrowserPatterns(provider, options),
|
|
956
|
+
...lintUndeclaredThrownErrorCodes(provider),
|
|
680
957
|
];
|
|
681
958
|
if (provider.operations) {
|
|
682
959
|
const authMode = provider.auth?.mode;
|
|
@@ -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,6 @@
|
|
|
1
1
|
import { ContextAccessError } from "../errors.js";
|
|
2
2
|
import { createAuthFlowHelpers } from "../auth.js";
|
|
3
|
+
import { createUnsupportedOcrClient } from "./ocr.js";
|
|
3
4
|
import { createUnsupportedSttClient } from "./stt.js";
|
|
4
5
|
function normalizeAllowedKeys(allowedKeys) {
|
|
5
6
|
return new Set(allowedKeys.filter((key) => key.trim().length > 0));
|
|
@@ -41,6 +42,7 @@ export function createFlowContext(options) {
|
|
|
41
42
|
stealth: options.stealth,
|
|
42
43
|
env: options.env,
|
|
43
44
|
context: createScratchpad(options.allowedKeys, options.initialContext),
|
|
45
|
+
ocr: options.ocr ?? createUnsupportedOcrClient(),
|
|
44
46
|
stt: options.stt ?? createUnsupportedSttClient(),
|
|
45
47
|
auth: createAuthFlowHelpers(),
|
|
46
48
|
};
|
package/dist/runtime/browser.js
CHANGED
|
@@ -457,7 +457,7 @@ function normalizeWebSocketEndpoint(endpoint) {
|
|
|
457
457
|
}
|
|
458
458
|
throw new Error(`Unsupported WebSocket endpoint protocol: ${url.protocol}`);
|
|
459
459
|
}
|
|
460
|
-
class
|
|
460
|
+
class WebSocketCommandClient {
|
|
461
461
|
nextId = 1;
|
|
462
462
|
endpoint;
|
|
463
463
|
listeners = new Map();
|
|
@@ -483,12 +483,7 @@ class JsonRpcWebSocketClient {
|
|
|
483
483
|
const id = this.nextId++;
|
|
484
484
|
return await new Promise((resolve, reject) => {
|
|
485
485
|
this.pending.set(id, { resolve, reject });
|
|
486
|
-
socket.send(JSON.stringify(
|
|
487
|
-
id,
|
|
488
|
-
jsonrpc: "2.0",
|
|
489
|
-
method,
|
|
490
|
-
params,
|
|
491
|
-
}));
|
|
486
|
+
socket.send(JSON.stringify(this.createCommandFrame(id, method, params)));
|
|
492
487
|
});
|
|
493
488
|
}
|
|
494
489
|
async close() {
|
|
@@ -526,7 +521,11 @@ class JsonRpcWebSocketClient {
|
|
|
526
521
|
}
|
|
527
522
|
this.pending.delete(payload.id);
|
|
528
523
|
if (payload.error) {
|
|
529
|
-
|
|
524
|
+
const error = new Error(payload.error.message ?? "JSON-RPC command failed");
|
|
525
|
+
if (typeof payload.error.code === "number") {
|
|
526
|
+
Object.assign(error, { code: payload.error.code });
|
|
527
|
+
}
|
|
528
|
+
pending.reject(error);
|
|
530
529
|
return;
|
|
531
530
|
}
|
|
532
531
|
pending.resolve(payload.result ?? {});
|
|
@@ -554,6 +553,26 @@ class JsonRpcWebSocketClient {
|
|
|
554
553
|
return this.socketPromise;
|
|
555
554
|
}
|
|
556
555
|
}
|
|
556
|
+
class CdpWebSocketClient extends WebSocketCommandClient {
|
|
557
|
+
sessionId;
|
|
558
|
+
constructor(endpoint, sessionId) {
|
|
559
|
+
super(endpoint);
|
|
560
|
+
this.sessionId = sessionId;
|
|
561
|
+
}
|
|
562
|
+
createCommandFrame(id, method, params) {
|
|
563
|
+
return {
|
|
564
|
+
id,
|
|
565
|
+
method,
|
|
566
|
+
params,
|
|
567
|
+
...(this.sessionId === undefined ? {} : { sessionId: this.sessionId }),
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
class JsonRpcWebSocketClient extends WebSocketCommandClient {
|
|
572
|
+
createCommandFrame(id, method, params) {
|
|
573
|
+
return { id, jsonrpc: "2.0", method, params };
|
|
574
|
+
}
|
|
575
|
+
}
|
|
557
576
|
function flattenCdpFrameTree(node, out = []) {
|
|
558
577
|
if (!node) {
|
|
559
578
|
return out;
|
|
@@ -996,7 +1015,7 @@ class CdpPoolBrowserClient {
|
|
|
996
1015
|
...(this.allowedHosts.length > 0 ? { allowedHosts: this.allowedHosts } : {}),
|
|
997
1016
|
...(options?.isolatedContext ? { isolationMode: "browserContext" } : {}),
|
|
998
1017
|
}));
|
|
999
|
-
const pageClient = new
|
|
1018
|
+
const pageClient = new CdpWebSocketClient(acquireResult.wsEndpoint);
|
|
1000
1019
|
const page = new CdpPoolBrowserPage(acquireResult.pageId, acquireResult.browserContextId, pageClient, async (request) => {
|
|
1001
1020
|
await this.poolClient.send("release", request);
|
|
1002
1021
|
});
|