@apifuse/provider-sdk 2.2.0-beta.47 → 2.2.0-beta.49
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 +91 -36
- package/CHANGELOG.md +8 -0
- package/README.md +11 -9
- package/SUBMISSION.md +1 -1
- package/bin/apifuse-dev.ts +24 -13
- package/bin/apifuse-migrate-operation-declaration.ts +55 -0
- package/bin/apifuse-pack-smoke.ts +1 -1
- package/bin/apifuse-pack-types.ts +2 -1
- package/bin/apifuse-record.ts +30 -16
- package/bin/apifuse-submit-check.ts +20 -35
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +11 -0
- package/dist/cli/migrate-operation-declaration.d.ts +59 -0
- package/dist/cli/migrate-operation-declaration.js +1178 -0
- package/dist/cli/templates/provider/README.md.tpl +3 -3
- package/dist/cli/templates/provider/operations/ping.ts.tpl +2 -0
- package/dist/config/loader.d.ts +2 -0
- package/dist/config/loader.js +18 -7
- package/dist/contract-types.d.ts +11 -5
- package/dist/contract.js +21 -10
- package/dist/define.d.ts +25 -22
- package/dist/define.js +49 -75
- package/dist/dev.d.ts +3 -0
- package/dist/dev.js +1 -1
- package/dist/engine.d.ts +78 -0
- package/dist/engine.js +133 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/lint.d.ts +7 -15
- package/dist/lint.js +45 -70
- package/dist/provider.d.ts +3 -1
- package/dist/provider.js +1 -0
- package/dist/runtime/chrome149-header-order.d.ts +58 -0
- package/dist/runtime/chrome149-header-order.js +289 -0
- package/dist/runtime/env.js +12 -0
- package/dist/runtime/executor.d.ts +2 -1
- package/dist/runtime/executor.js +3 -36
- package/dist/runtime/insights.js +2 -2
- package/dist/runtime/otlp.d.ts +71 -2
- package/dist/runtime/otlp.js +397 -16
- package/dist/runtime/resolver-public.d.ts +1 -1
- package/dist/runtime/resolver-public.js +1 -1
- package/dist/runtime/resolver-vendors/capsolver.js +9 -3
- package/dist/runtime/resolver-vendors/twocaptcha.js +1 -0
- package/dist/runtime/resolver.d.ts +12 -0
- package/dist/runtime/resolver.js +45 -11
- package/dist/runtime/stealth.d.ts +13 -4
- package/dist/runtime/stealth.js +362 -85
- package/dist/runtime/trace-config.js +2 -1
- package/dist/runtime/trace.d.ts +5 -0
- package/dist/runtime/trace.js +43 -10
- package/dist/server/self-test.d.ts +1 -3
- package/dist/server/self-test.js +2 -12
- package/dist/server/serve-implementation.d.ts +6 -1
- package/dist/server/serve-implementation.js +55 -40
- package/dist/server/trace-output.d.ts +3 -1
- package/dist/server/trace-output.js +61 -2
- package/dist/stealth/profiles.d.ts +9 -8
- package/dist/stealth/profiles.js +123 -286
- package/dist/types.d.ts +116 -108
- package/package.json +2 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +3 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +10 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +8 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +5 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +16 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +3 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +31 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +21 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +11 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +14 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +6 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +7 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +15 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +4 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +12 -0
- package/src/cli/commands.ts +13 -0
- package/src/cli/migrate-operation-declaration.ts +1654 -0
- package/src/cli/templates/provider/README.md.tpl +3 -3
- package/src/cli/templates/provider/operations/ping.ts.tpl +2 -0
- package/src/config/loader.ts +31 -6
- package/src/contract-types.ts +11 -5
- package/src/contract.ts +21 -10
- package/src/define.ts +107 -119
- package/src/dev.ts +4 -1
- package/src/engine.ts +279 -0
- package/src/index.ts +13 -5
- package/src/lint.ts +58 -92
- package/src/provider.ts +25 -3
- package/src/runtime/chrome149-header-order.ts +330 -0
- package/src/runtime/env.ts +13 -0
- package/src/runtime/executor.ts +7 -40
- package/src/runtime/insights.ts +2 -2
- package/src/runtime/otlp.ts +467 -21
- package/src/runtime/resolver-public.ts +3 -0
- package/src/runtime/resolver-vendors/capsolver.ts +12 -4
- package/src/runtime/resolver-vendors/twocaptcha.ts +1 -0
- package/src/runtime/resolver.ts +68 -19
- package/src/runtime/stealth.ts +435 -103
- package/src/runtime/trace-config.ts +3 -2
- package/src/runtime/trace.ts +57 -17
- package/src/server/self-test.ts +2 -9
- package/src/server/serve-implementation.ts +89 -72
- package/src/server/trace-output.ts +99 -2
- package/src/stealth/profiles.ts +169 -327
- package/src/types.ts +114 -137
|
@@ -113,9 +113,9 @@ Structured errors return an `error` object with `code`, `message`,
|
|
|
113
113
|
`connection.secrets`, and read them with `ctx.credential`.
|
|
114
114
|
- Auth flow: call `/auth/start`, then `/auth/continue` with the same `flowId`;
|
|
115
115
|
carry returned `contextPatch` values into the next request's `context`.
|
|
116
|
-
- Stealth/browser runtime: keep access-sensitive operations on `ctx.stealth.fetch()` with
|
|
117
|
-
SDK stealth `
|
|
118
|
-
and supports Chrome, Firefox, and Safari
|
|
116
|
+
- Stealth/browser runtime: keep access-sensitive operations on `ctx.stealth.fetch()` with
|
|
117
|
+
structured SDK `stealth: { browser, os }` selection; the TypeScript stealth runtime uses
|
|
118
|
+
`wreq-js` internally and supports Chrome, Firefox, and Safari. Use `ctx.browser` only when
|
|
119
119
|
the provider needs browser execution; TypeScript browser Providers use
|
|
120
120
|
`browser.engine: "playwright-stealth"` (`nodriver` is Python-runtime only). Install local Chromium with
|
|
121
121
|
`bunx playwright install chromium` or set `APIFUSE__CDP_POOL__URL`.
|
|
@@ -4,6 +4,8 @@ import type { ProviderContext } from "../index";
|
|
|
4
4
|
import { pingInputSchema, pingOutputSchema } from "../schemas/ping";
|
|
5
5
|
|
|
6
6
|
export const pingOperation = defineOperation<ProviderContext>()({
|
|
7
|
+
connectionMode: "none",
|
|
8
|
+
riskClass: "read",
|
|
7
9
|
descriptionKey: "operations.ping.description",
|
|
8
10
|
input: pingInputSchema,
|
|
9
11
|
output: pingOutputSchema,
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -58,6 +58,8 @@ export type ProxyResolutionOptions = {
|
|
|
58
58
|
*/
|
|
59
59
|
proxyRefreshEpoch?: number;
|
|
60
60
|
telemetry?: ProxyTelemetrySink;
|
|
61
|
+
/** Engine-owned credential snapshot. Provider code must never populate this field. */
|
|
62
|
+
engineCredentials?: Readonly<Record<string, string>>;
|
|
61
63
|
};
|
|
62
64
|
export type ProxyCacheStatus = "memory_hit" | "redis_hit" | "allocator" | "soft_stale_refresh" | "lock_wait" | "redis_error" | "redis_corrupt" | "disabled";
|
|
63
65
|
export type SmartproxyAllocatorBodyClass = "network_error" | "http_error" | "empty" | "json_without_proxies" | "text_without_proxies" | "usable_proxy_endpoints";
|
package/dist/config/loader.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { NODEMAVEN_DEFAULT_PROTOCOL, NODEMAVEN_FILTER_ENV, NODEMAVEN_MAX_POOL_SIZE, NODEMAVEN_PASSWORD_ENV, NODEMAVEN_USERNAME_ENV,
|
|
5
|
+
import { NODEMAVEN_DEFAULT_PROTOCOL, NODEMAVEN_FILTER_ENV, NODEMAVEN_MAX_POOL_SIZE, NODEMAVEN_PASSWORD_ENV, NODEMAVEN_USERNAME_ENV, 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
|
|
@@ -287,7 +287,7 @@ export async function resolveProxyConfigAsync(options = {}) {
|
|
|
287
287
|
const nextVendor = chain[vendorIndex + 1];
|
|
288
288
|
const poolIndex = vendorIndex === startVendorIndex ? startPoolIndex : 0;
|
|
289
289
|
const protocol = options.protocol ?? VENDOR_DEFAULT_PROTOCOL[vendor];
|
|
290
|
-
if (!vendorHasCredentials(vendor)) {
|
|
290
|
+
if (!vendorHasCredentials(vendor, options.engineCredentials)) {
|
|
291
291
|
options.telemetry?.recordProxyVendorFailover?.({
|
|
292
292
|
vendor,
|
|
293
293
|
nextVendor,
|
|
@@ -313,6 +313,7 @@ export async function resolveProxyConfigAsync(options = {}) {
|
|
|
313
313
|
protocol,
|
|
314
314
|
poolIndex,
|
|
315
315
|
refreshEpoch,
|
|
316
|
+
credentials: options.engineCredentials,
|
|
316
317
|
});
|
|
317
318
|
}
|
|
318
319
|
catch (error) {
|
|
@@ -497,10 +498,18 @@ function envDefaultProvider() {
|
|
|
497
498
|
const raw = process.env[DEFAULT_PROXY_PROVIDER_ENV]?.trim().toLowerCase();
|
|
498
499
|
return raw ?? undefined;
|
|
499
500
|
}
|
|
500
|
-
function vendorHasCredentials(vendor) {
|
|
501
|
-
if (vendor === "nodemaven")
|
|
502
|
-
return
|
|
503
|
-
|
|
501
|
+
function vendorHasCredentials(vendor, credentials) {
|
|
502
|
+
if (vendor === "nodemaven") {
|
|
503
|
+
return Boolean((credentials === undefined
|
|
504
|
+
? process.env[NODEMAVEN_USERNAME_ENV]
|
|
505
|
+
: credentials[NODEMAVEN_USERNAME_ENV])?.trim() &&
|
|
506
|
+
(credentials === undefined
|
|
507
|
+
? process.env[NODEMAVEN_PASSWORD_ENV]
|
|
508
|
+
: credentials[NODEMAVEN_PASSWORD_ENV])?.trim());
|
|
509
|
+
}
|
|
510
|
+
return Boolean((credentials === undefined
|
|
511
|
+
? process.env[SMARTPROXY_APP_KEY_ENV]
|
|
512
|
+
: credentials[SMARTPROXY_APP_KEY_ENV])?.trim());
|
|
504
513
|
}
|
|
505
514
|
function missingCredentialEnv(vendor) {
|
|
506
515
|
return vendor === "nodemaven" ? "APIFUSE__PROXY__NODEMAVEN_USERNAME" : SMARTPROXY_APP_KEY_ENV;
|
|
@@ -1149,7 +1158,9 @@ function markSmartproxyCacheInvalidated(options = {}) {
|
|
|
1149
1158
|
return undefined;
|
|
1150
1159
|
}
|
|
1151
1160
|
const lifetimeMinutes = resolveSmartproxyLifetime(policy);
|
|
1152
|
-
const appKey =
|
|
1161
|
+
const appKey = (options.engineCredentials === undefined
|
|
1162
|
+
? process.env[SMARTPROXY_APP_KEY_ENV]
|
|
1163
|
+
: options.engineCredentials[SMARTPROXY_APP_KEY_ENV])?.trim();
|
|
1153
1164
|
if (!appKey)
|
|
1154
1165
|
return undefined;
|
|
1155
1166
|
const cacheKey = buildSmartproxyCacheKey(policy, appKey, options.affinityKey, lifetimeMinutes, options.protocol ?? VENDOR_DEFAULT_PROTOCOL.smartproxy);
|
package/dist/contract-types.d.ts
CHANGED
|
@@ -27,17 +27,23 @@ export interface ProviderContractSnapshot {
|
|
|
27
27
|
}
|
|
28
28
|
export interface ProviderContractOperation {
|
|
29
29
|
readonly id: string;
|
|
30
|
+
readonly connectionMode?: JsonValue;
|
|
31
|
+
readonly connectionExternalRefParam?: JsonValue;
|
|
32
|
+
readonly riskClass: JsonValue;
|
|
33
|
+
readonly approval?: JsonValue;
|
|
34
|
+
readonly timeoutMs?: JsonValue;
|
|
35
|
+
readonly titleKey?: JsonValue;
|
|
30
36
|
readonly descriptionKey?: JsonValue;
|
|
31
|
-
readonly
|
|
37
|
+
readonly summaryKey?: JsonValue;
|
|
38
|
+
readonly markdownKey?: JsonValue;
|
|
32
39
|
readonly whenToUseKeys?: JsonValue;
|
|
33
40
|
readonly whenNotToUseKeys?: JsonValue;
|
|
34
|
-
readonly
|
|
35
|
-
readonly
|
|
36
|
-
readonly
|
|
41
|
+
readonly normalizationNotesKeys?: JsonValue;
|
|
42
|
+
readonly errorCodes?: JsonValue;
|
|
43
|
+
readonly examples?: JsonValue;
|
|
37
44
|
readonly contract?: JsonValue;
|
|
38
45
|
readonly tags?: JsonValue;
|
|
39
46
|
readonly relatedOperations?: JsonValue;
|
|
40
|
-
readonly toolRouter?: JsonValue;
|
|
41
47
|
readonly observability?: JsonValue;
|
|
42
48
|
readonly transport?: JsonValue;
|
|
43
49
|
readonly inputSchema: JsonValue;
|
package/dist/contract.js
CHANGED
|
@@ -48,17 +48,22 @@ export function digestProviderContract(snapshot) {
|
|
|
48
48
|
return createHash("sha256").update(canonicalJson(snapshot)).digest("hex");
|
|
49
49
|
}
|
|
50
50
|
function extractOperation(operationId, operation) {
|
|
51
|
+
const connectionMode = toJsonValue(operation.connectionMode);
|
|
52
|
+
const connectionExternalRefParam = toJsonValue(operation.connectionExternalRefParam);
|
|
53
|
+
const approval = toJsonValue(operation.approval);
|
|
54
|
+
const timeoutMs = toJsonValue(operation.timeoutMs);
|
|
55
|
+
const titleKey = toJsonValue(operation.titleKey);
|
|
51
56
|
const descriptionKey = toJsonValue(operation.descriptionKey);
|
|
52
|
-
const
|
|
57
|
+
const summaryKey = toJsonValue(operation.summaryKey);
|
|
58
|
+
const markdownKey = toJsonValue(operation.markdownKey);
|
|
53
59
|
const whenToUseKeys = toJsonValue(operation.whenToUseKeys);
|
|
54
60
|
const whenNotToUseKeys = toJsonValue(operation.whenNotToUseKeys);
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
61
|
+
const normalizationNotesKeys = toJsonValue(operation.normalizationNotesKeys);
|
|
62
|
+
const errorCodes = toJsonValue(operation.errorCodes);
|
|
63
|
+
const examples = toJsonValue(operation.examples);
|
|
58
64
|
const contract = toJsonValue(operation.contract);
|
|
59
65
|
const tags = toJsonValue(operation.tags);
|
|
60
66
|
const relatedOperations = toJsonValue(operation.relatedOperations);
|
|
61
|
-
const toolRouter = toJsonValue(operation.toolRouter);
|
|
62
67
|
const observability = toJsonValue(operation.observability);
|
|
63
68
|
const transport = extractTransport(operation.transport);
|
|
64
69
|
const fixtures = toJsonValue(operation.fixtures);
|
|
@@ -70,17 +75,23 @@ function extractOperation(operationId, operation) {
|
|
|
70
75
|
id: operationId,
|
|
71
76
|
inputSchema: describeSchema(operation.input),
|
|
72
77
|
outputSchema: describeSchema(operation.output),
|
|
78
|
+
...(connectionMode === undefined ? {} : { connectionMode }),
|
|
79
|
+
...(connectionExternalRefParam === undefined ? {} : { connectionExternalRefParam }),
|
|
80
|
+
riskClass: operation.riskClass,
|
|
81
|
+
...(approval === undefined ? {} : { approval }),
|
|
82
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
83
|
+
...(titleKey === undefined ? {} : { titleKey }),
|
|
73
84
|
...(descriptionKey === undefined ? {} : { descriptionKey }),
|
|
74
|
-
...(
|
|
85
|
+
...(summaryKey === undefined ? {} : { summaryKey }),
|
|
86
|
+
...(markdownKey === undefined ? {} : { markdownKey }),
|
|
75
87
|
...(whenToUseKeys === undefined ? {} : { whenToUseKeys }),
|
|
76
88
|
...(whenNotToUseKeys === undefined ? {} : { whenNotToUseKeys }),
|
|
77
|
-
...(
|
|
78
|
-
...(
|
|
79
|
-
...(
|
|
89
|
+
...(normalizationNotesKeys === undefined ? {} : { normalizationNotesKeys }),
|
|
90
|
+
...(errorCodes === undefined ? {} : { errorCodes }),
|
|
91
|
+
...(examples === undefined ? {} : { examples }),
|
|
80
92
|
...(contract === undefined ? {} : { contract }),
|
|
81
93
|
...(tags === undefined ? {} : { tags }),
|
|
82
94
|
...(relatedOperations === undefined ? {} : { relatedOperations }),
|
|
83
|
-
...(toolRouter === undefined ? {} : { toolRouter }),
|
|
84
95
|
...(observability === undefined ? {} : { observability }),
|
|
85
96
|
...(transport === undefined ? {} : { transport }),
|
|
86
97
|
...(fixtures === undefined ? {} : { fixtures }),
|
package/dist/define.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthConfig, BrowserEngine, ContextDeclaration, CredentialDeclaration, HealthJourneyDefinition, HealthJourneySchedule, HealthScheduleRandomization, InferSchemaOutput, NativeProviderConfig, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, ProviderAccessConfig, ProviderContext,
|
|
1
|
+
import type { AuthConfig, BrowserEngine, ContextDeclaration, CredentialDeclaration, HealthJourneyDefinition, HealthJourneySchedule, HealthScheduleRandomization, InferSchemaOutput, NativeProviderConfig, OperationDefinition, OperationHandlerResult, OperationHttpStreamTransport, OperationSseTransport, OperationWebSocketTransport, ProviderAccessConfig, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderHealthMonitorConfig, ProviderOcrConfig, ProviderProxyConfig, ProviderPublicProfile, ProviderResolverConfig, ProviderReviewed, ProviderRuntimeTarget, ProviderSecretDeclaration, ProviderStreamEvent, ProviderSttConfig, SchemaLike, SmsOtpMatcherDefinition, StealthProfileSelection } 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 {
|
|
@@ -46,6 +46,8 @@ export interface ProviderDeclaration {
|
|
|
46
46
|
id: string;
|
|
47
47
|
version: string;
|
|
48
48
|
runtime: "standard" | "shared" | "browser";
|
|
49
|
+
/** Provider business-logic target. Omit only while migrating a legacy provider. */
|
|
50
|
+
runtimeTarget?: ProviderRuntimeTarget;
|
|
49
51
|
/**
|
|
50
52
|
* Optional deployment overrides, passed through verbatim onto the returned
|
|
51
53
|
* provider definition. The SDK types this field but does not deep-validate
|
|
@@ -53,14 +55,13 @@ export interface ProviderDeclaration {
|
|
|
53
55
|
* resolves omitted fields against the runtime deployment profiles.
|
|
54
56
|
*/
|
|
55
57
|
deployment?: ProviderDeploymentOverrides;
|
|
56
|
-
/** Declares
|
|
57
|
-
http?: true;
|
|
58
|
+
/** Declares the HTTP capability binding. A bare object states use without configuration. */
|
|
59
|
+
http?: Record<string, never> | true;
|
|
60
|
+
/** Declares upstream host policy; this does not add a `ctx.allowedHosts` member. */
|
|
58
61
|
allowedHosts?: string[];
|
|
59
62
|
native?: NativeProviderConfig;
|
|
60
|
-
stealth?:
|
|
61
|
-
|
|
62
|
-
platform: StealthPlatform;
|
|
63
|
-
};
|
|
63
|
+
stealth?: StealthProfileSelection;
|
|
64
|
+
/** Declares proxy policy; this is provider intent and does not add a `ctx.proxy` member. */
|
|
64
65
|
proxy?: ProviderProxyConfig;
|
|
65
66
|
ocr?: ProviderOcrConfig;
|
|
66
67
|
stt?: ProviderSttConfig;
|
|
@@ -69,21 +70,23 @@ export interface ProviderDeclaration {
|
|
|
69
70
|
engine: BrowserEngine;
|
|
70
71
|
};
|
|
71
72
|
auth?: AuthConfig;
|
|
72
|
-
/** Declares
|
|
73
|
-
choice?: true;
|
|
73
|
+
/** Declares the choice capability binding. A bare object states use without configuration. */
|
|
74
|
+
choice?: Record<string, never> | true;
|
|
74
75
|
reviewed?: ProviderReviewed;
|
|
75
76
|
access?: ProviderAccessConfig;
|
|
77
|
+
/** Declares secret requirements; this does not add a `ctx.secrets` member. */
|
|
76
78
|
secrets?: ProviderSecretDeclaration[];
|
|
77
|
-
/** Declares
|
|
78
|
-
env?: true;
|
|
79
|
+
/** Declares the environment capability binding. A bare object states use without configuration. */
|
|
80
|
+
env?: Record<string, never> | true;
|
|
79
81
|
credential?: CredentialDeclaration;
|
|
82
|
+
/** Declares provider context metadata; this does not add a `ctx.context` member. */
|
|
80
83
|
context?: ContextDeclaration;
|
|
81
|
-
/** Declares
|
|
82
|
-
state?: true;
|
|
83
|
-
/** Declares
|
|
84
|
-
cache?: true;
|
|
85
|
-
/** Declares
|
|
86
|
-
files?: true;
|
|
84
|
+
/** Declares the state capability binding. A bare object states use without configuration. */
|
|
85
|
+
state?: Record<string, never> | true;
|
|
86
|
+
/** Declares the cache capability binding. A bare object states use without configuration. */
|
|
87
|
+
cache?: Record<string, never> | true;
|
|
88
|
+
/** Declares the files capability binding. A bare object states use without configuration. */
|
|
89
|
+
files?: Record<string, never> | true;
|
|
87
90
|
meta: {
|
|
88
91
|
displayName: string;
|
|
89
92
|
displayNameKey?: string;
|
|
@@ -127,17 +130,17 @@ export declare function delayed(maxDelay: string): HealthScheduleRandomization;
|
|
|
127
130
|
export declare function defineSmsOtpMatcher(config: Omit<SmsOtpMatcherDefinition, "extractOtp">): SmsOtpMatcherDefinition;
|
|
128
131
|
export declare function defineHealthJourney(config: HealthJourneyDefinition): HealthJourneyDefinition;
|
|
129
132
|
/** The second authoring phase for a declaration established by defineProvider. */
|
|
130
|
-
export type ProviderBuilder<
|
|
131
|
-
operations: OperationMapConfig<TOperations,
|
|
133
|
+
export type ProviderBuilder<TConfig extends ProviderDeclaration> = <TOperations extends Record<string, ProviderOperation>>(implementation: {
|
|
134
|
+
operations: OperationMapConfig<TOperations, ProviderContext<TConfig>>;
|
|
132
135
|
}) => Omit<ProviderDefinition, "operations"> & {
|
|
133
|
-
operations: OperationMapConfig<TOperations,
|
|
136
|
+
operations: OperationMapConfig<TOperations, ProviderContext<TConfig>>;
|
|
134
137
|
};
|
|
135
138
|
/** Extract the declaration-derived operation context from a provider builder. */
|
|
136
|
-
export type ProviderContextOf<TBuilder> = TBuilder extends ProviderBuilder<infer
|
|
139
|
+
export type ProviderContextOf<TBuilder> = TBuilder extends ProviderBuilder<infer TConfig> ? ProviderContext<TConfig> : never;
|
|
137
140
|
/** Annotate an operation while preserving the declaration-derived context. */
|
|
138
141
|
export type OperationDefinitionFor<TBuilder, TInput extends SchemaLike = SchemaLike, TOutput extends SchemaLike = SchemaLike> = OperationDefinition<TInput, TOutput, ProviderContextOf<TBuilder>>;
|
|
139
142
|
/** Annotate a built provider while preserving the declaration-derived context. */
|
|
140
143
|
export type ProviderDefinitionFor<TBuilder> = ProviderDefinition<ProviderContextOf<TBuilder>>;
|
|
141
144
|
/** Establish a provider declaration before its operations are contextually typed. */
|
|
142
|
-
export declare function defineProvider<const
|
|
145
|
+
export declare function defineProvider<const TConfig extends ProviderDeclaration>(declaration: TConfig & Record<Exclude<keyof TConfig, keyof ProviderDeclaration>, never> & AuthStartNoInputGuard<TConfig>): ProviderBuilder<TConfig>;
|
|
143
146
|
export {};
|
package/dist/define.js
CHANGED
|
@@ -2,6 +2,7 @@ import ms from "ms";
|
|
|
2
2
|
import { validateFailClosedOperationDeclaration, validateFailClosedProviderDeclaration, } from "./declaration-validation.js";
|
|
3
3
|
import { SDK_RUNTIME_OWNED_ERROR_CODES } from "./error-resolution.js";
|
|
4
4
|
import { ProviderError, ValidationError } from "./errors.js";
|
|
5
|
+
import { isEngineOwnedProxyCredentialName, isEngineOwnedTelemetryEnvName } from "./engine.js";
|
|
5
6
|
import { HealthScenarioSchema } from "./health-scenario.js";
|
|
6
7
|
import { NativeEgressPolicyValidationError, validateNativeProviderConfig, } from "./native-egress-policy.js";
|
|
7
8
|
import { safeParseSchemaSync } from "./schema.js";
|
|
@@ -10,6 +11,7 @@ import { HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX, HEALTH_CHECK_DEGRADED_THRESHOLD
|
|
|
10
11
|
const CONNECTOR_ID_REGEX = /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)*$/;
|
|
11
12
|
const OPERATION_ID_REGEX = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/;
|
|
12
13
|
const VALID_RUNTIMES = ["standard", "shared", "browser"];
|
|
14
|
+
const VALID_RUNTIME_TARGETS = ["vanilla", "engine"];
|
|
13
15
|
const VALID_AUTH_MODES = [
|
|
14
16
|
"none",
|
|
15
17
|
"platform-managed",
|
|
@@ -71,24 +73,10 @@ export const VALID_PROVIDER_CHALLENGE_KINDS = exhaustiveLiteralArray()([
|
|
|
71
73
|
"akamai_sec_cpt",
|
|
72
74
|
"akamai_sensor",
|
|
73
75
|
]);
|
|
74
|
-
const SMARTPROXY_APP_KEY_SECRET = "APIFUSE__PROXY__SMARTPROXY_APP_KEY";
|
|
75
|
-
const NODEMAVEN_USERNAME_SECRET = "APIFUSE__PROXY__NODEMAVEN_USERNAME";
|
|
76
|
-
const NODEMAVEN_PASSWORD_SECRET = "APIFUSE__PROXY__NODEMAVEN_PASSWORD";
|
|
77
|
-
// Per-vendor provider-declared credential secrets. A required-mode chain must
|
|
78
|
-
// declare every secret of every credentialed vendor it names, so a missing
|
|
79
|
-
// credential fails at build/validation time rather than during a live outage: a
|
|
80
|
-
// declared-but-uncredentialed fallback leg is a silently dead SPOF, which is
|
|
81
|
-
// exactly the failure class the multi-vendor chain exists to remove. Vendors
|
|
82
|
-
// absent from this map (the deprecated `custom`/`decodo` values have no managed
|
|
83
|
-
// adapter) impose no declaration requirement.
|
|
84
|
-
const VENDOR_REQUIRED_SECRETS = {
|
|
85
|
-
smartproxy: [SMARTPROXY_APP_KEY_SECRET],
|
|
86
|
-
nodemaven: [NODEMAVEN_USERNAME_SECRET, NODEMAVEN_PASSWORD_SECRET],
|
|
87
|
-
};
|
|
88
76
|
const RESERVED_OPERATION_IDS = new Set(["auth", "health"]);
|
|
89
|
-
const MCP_TOOL_NAME_REGEX = /^[A-Za-z][A-Za-z0-9_]{0,127}$/;
|
|
90
77
|
const VALID_OPERATION_RISK_CLASSES = ["read", "write", "destructive", "external-send"];
|
|
91
78
|
const VALID_OPERATION_APPROVAL_POLICIES = ["never", "risk-based", "always"];
|
|
79
|
+
const VALID_OPERATION_CONNECTION_MODES = ["none", "optional", "required"];
|
|
92
80
|
const VALID_OPERATION_TRANSPORT_KINDS = ["json", "sse", "http-stream", "websocket"];
|
|
93
81
|
const SSE_EVENT_NAME_REGEX = /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/;
|
|
94
82
|
const WEBSOCKET_SUBPROTOCOL_REGEX = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
@@ -562,11 +550,21 @@ function validateProviderDeclarationShape(config) {
|
|
|
562
550
|
assertRequiredField(config, "meta", String(config.id));
|
|
563
551
|
if (typeof config.runtime === "string")
|
|
564
552
|
assertLiteralField(config.runtime, "runtime", VALID_RUNTIMES, String(config.id));
|
|
553
|
+
if (config.runtimeTarget !== undefined && typeof config.runtimeTarget !== "string") {
|
|
554
|
+
throw new ValidationError(`Provider "${String(config.id)}" has invalid runtimeTarget: expected "vanilla" or "engine"`);
|
|
555
|
+
}
|
|
556
|
+
if (typeof config.runtimeTarget === "string")
|
|
557
|
+
assertLiteralField(config.runtimeTarget, "runtimeTarget", VALID_RUNTIME_TARGETS, String(config.id));
|
|
565
558
|
if (config.native !== undefined && config.runtime === "browser") {
|
|
566
559
|
throw new ValidationError(`Provider "${String(config.id)}" cannot declare capability "native" with runtime "browser"`, {
|
|
567
560
|
fix: 'Use runtime: "standard" or runtime: "shared", or remove the native declaration.',
|
|
568
561
|
});
|
|
569
562
|
}
|
|
563
|
+
if (config.native !== undefined && config.runtimeTarget === "vanilla") {
|
|
564
|
+
throw new ValidationError(`Provider "${String(config.id)}" cannot declare capability "native" with runtime target "vanilla"; native requires an engine-resident runtime`, {
|
|
565
|
+
fix: 'Set runtimeTarget: "engine", or remove the native declaration.',
|
|
566
|
+
});
|
|
567
|
+
}
|
|
570
568
|
const auth = config.auth;
|
|
571
569
|
if (auth && typeof auth === "object" && "mode" in auth && typeof auth.mode === "string")
|
|
572
570
|
assertLiteralField(auth.mode, "auth.mode", VALID_AUTH_MODES, String(config.id));
|
|
@@ -634,6 +632,18 @@ function validateProviderImplementationShape(config) {
|
|
|
634
632
|
assertRequiredField(configRecord, "operations", String(config.id));
|
|
635
633
|
}
|
|
636
634
|
function validateProviderProxy(config) {
|
|
635
|
+
for (const secret of config.secrets ?? []) {
|
|
636
|
+
if (isEngineOwnedTelemetryEnvName(secret.name)) {
|
|
637
|
+
throw new ValidationError(`Provider "${config.id}" cannot declare engine-owned telemetry variable "${secret.name}"`, {
|
|
638
|
+
fix: `Remove "${secret.name}" from provider secrets; trace export is configured only on the provider engine.`,
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
if (!isEngineOwnedProxyCredentialName(secret.name))
|
|
642
|
+
continue;
|
|
643
|
+
throw new ValidationError(`Provider "${config.id}" cannot declare engine-owned proxy credential "${secret.name}"`, {
|
|
644
|
+
fix: `Remove "${secret.name}" from provider secrets; configure it only on the provider engine.`,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
637
647
|
const proxy = config.proxy;
|
|
638
648
|
if (proxy === undefined || typeof proxy === "boolean") {
|
|
639
649
|
return;
|
|
@@ -712,39 +722,11 @@ function validateProviderProxy(config) {
|
|
|
712
722
|
});
|
|
713
723
|
}
|
|
714
724
|
}
|
|
715
|
-
// Every credentialed vendor in a required-mode chain must declare its
|
|
716
|
-
// provider secret(s) so a missing credential fails at build/validation time,
|
|
717
|
-
// not during a live outage. This covers the fallback legs too (not just the
|
|
718
|
-
// first vendor): a declared-but-uncredentialed nodemaven fallback would leave
|
|
719
|
-
// the chain silently down to a single vendor, reintroducing the SPOF the chain
|
|
720
|
-
// removes.
|
|
721
725
|
const vendorChain = proxy.providers && proxy.providers.length > 0
|
|
722
726
|
? proxy.providers
|
|
723
727
|
: proxy.provider
|
|
724
728
|
? [proxy.provider]
|
|
725
729
|
: [];
|
|
726
|
-
if (proxy.mode === "required") {
|
|
727
|
-
for (const vendor of vendorChain) {
|
|
728
|
-
const requiredSecrets = VENDOR_REQUIRED_SECRETS[vendor];
|
|
729
|
-
if (!requiredSecrets)
|
|
730
|
-
continue;
|
|
731
|
-
for (const secretName of requiredSecrets) {
|
|
732
|
-
// Match the canonical runtime gate (assertRequiredSecretsPresent /
|
|
733
|
-
// listMissingRequiredSecrets), which enforces only `required === true`
|
|
734
|
-
// declarations. A declaration that omits `required` (defaulting to
|
|
735
|
-
// optional) is skipped at runtime, so accepting it here would pass
|
|
736
|
-
// validation while leaving the credential unenforced until proxy
|
|
737
|
-
// resolution during a live request — the fail-open gap this check exists
|
|
738
|
-
// to close.
|
|
739
|
-
const declared = config.secrets?.some((secret) => secret.name === secretName && secret.required === true);
|
|
740
|
-
if (!declared) {
|
|
741
|
-
throw new ValidationError(`Provider "${config.id}" requires ${vendor} egress but does not declare ${secretName}.`, {
|
|
742
|
-
fix: `Add secrets: [{ name: "${secretName}", required: true }] to the provider (every vendor in a required proxy chain must declare its credential secrets).`,
|
|
743
|
-
});
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
730
|
// `decodo`/`custom` are deprecated vendor values (string-union members, so the
|
|
749
731
|
// @deprecated symbol gate can't catch them — warn at validation time instead).
|
|
750
732
|
const deprecatedVendors = vendorChain.filter((vendor) => vendor === "decodo" || vendor === "custom");
|
|
@@ -839,31 +821,19 @@ function assertNonEmptyString(value, field, providerId, operationName) {
|
|
|
839
821
|
throw new ValidationError(`Provider "${providerId}" operation "${operationName}" has invalid ${field}: must be a non-empty string.`, { fix: `Set ${field} to a non-empty customer-facing value.` });
|
|
840
822
|
}
|
|
841
823
|
}
|
|
842
|
-
function
|
|
824
|
+
function validateOperationMetadata(providerId, operations) {
|
|
843
825
|
for (const [operationName, operation] of Object.entries(operations)) {
|
|
844
|
-
|
|
845
|
-
if (
|
|
846
|
-
|
|
847
|
-
if (!toolRouter || typeof toolRouter !== "object") {
|
|
848
|
-
throw new ValidationError(`Provider "${providerId}" operation "${operationName}" has invalid operations.${operationName}.toolRouter: must be an object.`, {
|
|
849
|
-
fix: `Remove operations.${operationName}.toolRouter or provide MCP-safe metadata.`,
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
if (toolRouter.name !== undefined && !MCP_TOOL_NAME_REGEX.test(toolRouter.name)) {
|
|
853
|
-
throw new ValidationError(`Provider "${providerId}" operation "${operationName}" has invalid operations.${operationName}.toolRouter.name: expected an MCP-safe name.`, {
|
|
854
|
-
fix: `Use letters, numbers, and underscores only, starting with a letter, for example "${providerId.replace(/[^A-Za-z0-9]+/g, "_")}__${operationName.replace(/[^A-Za-z0-9]+/g, "_")}".`,
|
|
855
|
-
});
|
|
826
|
+
assertLiteralField(operation.riskClass, `operations.${operationName}.riskClass`, VALID_OPERATION_RISK_CLASSES, providerId);
|
|
827
|
+
if (operation.approval !== undefined) {
|
|
828
|
+
assertLiteralField(operation.approval, `operations.${operationName}.approval`, VALID_OPERATION_APPROVAL_POLICIES, providerId);
|
|
856
829
|
}
|
|
857
|
-
if (
|
|
858
|
-
assertLiteralField(
|
|
830
|
+
if (operation.connectionMode !== undefined) {
|
|
831
|
+
assertLiteralField(operation.connectionMode, `operations.${operationName}.connectionMode`, VALID_OPERATION_CONNECTION_MODES, providerId);
|
|
859
832
|
}
|
|
860
|
-
if (
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
(typeof toolRouter.connectionExternalRefParam !== "string" ||
|
|
865
|
-
toolRouter.connectionExternalRefParam.trim().length === 0)) {
|
|
866
|
-
throw new ValidationError(`Provider "${providerId}" operation "${operationName}" has invalid operations.${operationName}.toolRouter.connectionExternalRefParam: must be a non-empty string.`, {
|
|
833
|
+
if (operation.connectionExternalRefParam !== undefined &&
|
|
834
|
+
(typeof operation.connectionExternalRefParam !== "string" ||
|
|
835
|
+
operation.connectionExternalRefParam.trim().length === 0)) {
|
|
836
|
+
throw new ValidationError(`Provider "${providerId}" operation "${operationName}" has invalid operations.${operationName}.connectionExternalRefParam: must be a non-empty string.`, {
|
|
867
837
|
fix: `Use "externalRef" unless the operation has a documented public alias.`,
|
|
868
838
|
});
|
|
869
839
|
}
|
|
@@ -899,15 +869,12 @@ function validateOperationContracts(providerId, operations) {
|
|
|
899
869
|
}
|
|
900
870
|
}
|
|
901
871
|
}
|
|
902
|
-
function
|
|
872
|
+
function validateOperationTimeouts(providerId, operations) {
|
|
903
873
|
for (const [operationName, operation] of Object.entries(operations)) {
|
|
904
|
-
const
|
|
905
|
-
if (!annotations)
|
|
906
|
-
continue;
|
|
907
|
-
const timeoutMs = annotations.timeoutMs;
|
|
874
|
+
const timeoutMs = operation.timeoutMs;
|
|
908
875
|
if (timeoutMs === undefined)
|
|
909
876
|
continue;
|
|
910
|
-
const field = `operations.${operationName}.
|
|
877
|
+
const field = `operations.${operationName}.timeoutMs`;
|
|
911
878
|
if (typeof timeoutMs !== "number" || !Number.isInteger(timeoutMs))
|
|
912
879
|
throw new ValidationError(`Provider "${providerId}" has invalid ${field}: must be an integer number of milliseconds.`, {
|
|
913
880
|
fix: `Set ${field} to an integer in [${OPERATION_TIMEOUT_MS_MIN}, ${OPERATION_TIMEOUT_MS_MAX}] (milliseconds).`,
|
|
@@ -957,10 +924,10 @@ function validateOperationObservability(providerId, operations) {
|
|
|
957
924
|
}
|
|
958
925
|
function validateOperationErrorCodes(providerId, operations) {
|
|
959
926
|
for (const [operationName, operation] of Object.entries(operations)) {
|
|
960
|
-
for (const [index, errorCode] of (operation.
|
|
927
|
+
for (const [index, errorCode] of (operation.errorCodes ?? []).entries()) {
|
|
961
928
|
if (errorCode.status !== undefined &&
|
|
962
929
|
!VALID_OPERATION_ERROR_STATUSES.some((status) => status === errorCode.status)) {
|
|
963
|
-
const field = `operations.${operationName}.
|
|
930
|
+
const field = `operations.${operationName}.errorCodes[${index}].status`;
|
|
964
931
|
throw new ValidationError(`Provider "${providerId}" has invalid ${field}: ${String(errorCode.status)} is not an emittable provider error status.`, {
|
|
965
932
|
fix: `Set ${field} to one of ${VALID_OPERATION_ERROR_STATUSES.join(", ")}, or omit it.`,
|
|
966
933
|
});
|
|
@@ -2022,12 +1989,12 @@ function finalizeProvider(config) {
|
|
|
2022
1989
|
fix: "Add at least one operation to the operations object",
|
|
2023
1990
|
});
|
|
2024
1991
|
validateOperationIds(config.id, config.operations);
|
|
2025
|
-
|
|
1992
|
+
validateOperationTimeouts(config.id, config.operations);
|
|
2026
1993
|
validateOperationObservability(config.id, config.operations);
|
|
2027
1994
|
validateOperationErrorCodes(config.id, config.operations);
|
|
2028
1995
|
validateOperationTransports(config.id, config.operations);
|
|
2029
1996
|
validateOperationContracts(config.id, config.operations);
|
|
2030
|
-
|
|
1997
|
+
validateOperationMetadata(config.id, config.operations);
|
|
2031
1998
|
const journeyCoveredOperations = validateHealthJourneys(config.id, config.operations, config.healthJourneys);
|
|
2032
1999
|
validateOperationHealthChecks(config.id, config.operations, journeyCoveredOperations);
|
|
2033
2000
|
validateOperationFixtures(config.id, operations);
|
|
@@ -2035,9 +2002,11 @@ function finalizeProvider(config) {
|
|
|
2035
2002
|
id: config.id,
|
|
2036
2003
|
version: config.version,
|
|
2037
2004
|
runtime: config.runtime,
|
|
2005
|
+
runtimeTarget: config.runtimeTarget,
|
|
2038
2006
|
// Verbatim passthrough: deployment validation and profile resolution
|
|
2039
2007
|
// are owned by the APIFuse registry builder, not the SDK.
|
|
2040
2008
|
deployment: config.deployment,
|
|
2009
|
+
http: config.http,
|
|
2041
2010
|
allowedHosts: config.allowedHosts,
|
|
2042
2011
|
native: config.native,
|
|
2043
2012
|
stealth: config.stealth,
|
|
@@ -2047,11 +2016,16 @@ function finalizeProvider(config) {
|
|
|
2047
2016
|
resolver: config.resolver,
|
|
2048
2017
|
browser: config.browser,
|
|
2049
2018
|
auth: config.auth,
|
|
2019
|
+
choice: config.choice,
|
|
2050
2020
|
reviewed: config.reviewed,
|
|
2051
2021
|
access: config.access,
|
|
2052
2022
|
secrets: config.secrets,
|
|
2023
|
+
env: config.env,
|
|
2053
2024
|
credential: config.credential,
|
|
2054
2025
|
context: config.context,
|
|
2026
|
+
state: config.state,
|
|
2027
|
+
cache: config.cache,
|
|
2028
|
+
files: config.files,
|
|
2055
2029
|
meta: config.meta,
|
|
2056
2030
|
operations,
|
|
2057
2031
|
// Transitional healthMonitor → healthProbe alias: mirror whichever field
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import type { ProviderEngine } from "./engine.js";
|
|
1
2
|
import type { ProviderDefinition } from "./types.js";
|
|
2
3
|
export interface DevServerOptions {
|
|
3
4
|
port?: number;
|
|
4
5
|
sessionDbPath?: string;
|
|
6
|
+
/** Override the default in-process engine attachment. */
|
|
7
|
+
engine?: ProviderEngine;
|
|
5
8
|
}
|
|
6
9
|
export declare function createDevServer(provider: ProviderDefinition, options?: DevServerOptions): {
|
|
7
10
|
start: () => void;
|
package/dist/dev.js
CHANGED
|
@@ -3,7 +3,7 @@ export function createDevServer(provider, options) {
|
|
|
3
3
|
const port = options?.port ?? 3900;
|
|
4
4
|
return {
|
|
5
5
|
start: () => {
|
|
6
|
-
void serve(provider, { port });
|
|
6
|
+
void serve(provider, { port, engine: options?.engine });
|
|
7
7
|
console.log(`[apifuse dev] ${provider.id}@${provider.version} running at http://localhost:${port}`);
|
|
8
8
|
console.log(`[apifuse dev] Operations: ${Object.keys(provider.operations).join(", ")}`);
|
|
9
9
|
console.log(`[apifuse dev] Health: http://localhost:${port}/health`);
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { AuthContext, BrowserClient, CredentialContext, EnvContext, HttpClient, NativeContext, OcrContext, ProviderCache, ProviderChoiceContext, ProviderContext, ProviderDefinition, ProviderFilesContext, ProviderRequestContext, ProviderRuntimeState, ResolverContext, StealthClient, SttContext, TraceContext } from "./types.js";
|
|
2
|
+
/** Versioned envelope protocol used by out-of-process engine transports. */
|
|
3
|
+
export declare const PROVIDER_ENGINE_PROTOCOL_VERSION: "provider-engine.v1";
|
|
4
|
+
/** Credential names owned by the engine and forbidden in provider declarations. */
|
|
5
|
+
export declare const ENGINE_OWNED_PROXY_CREDENTIAL_ENV_NAMES: readonly ["APIFUSE__PROXY__SMARTPROXY_APP_KEY", "APIFUSE__PROXY__NODEMAVEN_USERNAME", "APIFUSE__PROXY__NODEMAVEN_PASSWORD"];
|
|
6
|
+
export declare function isEngineOwnedProxyCredentialName(name: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Trace-export configuration owned by the engine and forbidden in provider
|
|
9
|
+
* declarations. The header variables carry collector credentials; the rest are
|
|
10
|
+
* engine deployment settings a provider has no reason to read.
|
|
11
|
+
*/
|
|
12
|
+
export declare const ENGINE_OWNED_TELEMETRY_ENV_NAMES: readonly ["OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "OTEL_EXPORTER_OTLP_ENDPOINT", "OTEL_EXPORTER_OTLP_TRACES_HEADERS", "OTEL_EXPORTER_OTLP_HEADERS", "OTEL_SERVICE_NAME", "OTEL_RESOURCE_ATTRIBUTES"];
|
|
13
|
+
export declare function isEngineOwnedTelemetryEnvName(name: string): boolean;
|
|
14
|
+
/** Every environment name the engine owns: rejected in declarations and filtered from provider projections. */
|
|
15
|
+
export declare function isEngineOwnedEnvName(name: string): boolean;
|
|
16
|
+
/** Capture credentials in the engine host before constructing provider bindings. */
|
|
17
|
+
export declare function readEngineProxyCredentials(environment?: Readonly<Record<string, string | undefined>>): Readonly<Record<string, string>>;
|
|
18
|
+
/** Build the exact environment projection permitted to enter a provider runtime. */
|
|
19
|
+
export declare function createProviderEnvironment(environment: Readonly<Record<string, string | undefined>>, declaredNames: readonly string[]): Readonly<Record<string, string>>;
|
|
20
|
+
/**
|
|
21
|
+
* Request/response is the first remote transport lane. Stream and session
|
|
22
|
+
* handles are separate lanes so lifecycle-bearing capabilities are never
|
|
23
|
+
* disguised as ordinary JSON calls.
|
|
24
|
+
*/
|
|
25
|
+
export interface ProviderEngineTransport {
|
|
26
|
+
request<TResponse = unknown>(request: ProviderEngineRequest): Promise<TResponse>;
|
|
27
|
+
openStream?(request: ProviderEngineRequest): Promise<ReadableStream<Uint8Array>>;
|
|
28
|
+
openSession?(request: ProviderEngineRequest): Promise<ProviderEngineSession>;
|
|
29
|
+
}
|
|
30
|
+
export interface ProviderEngineRequest {
|
|
31
|
+
readonly version: typeof PROVIDER_ENGINE_PROTOCOL_VERSION;
|
|
32
|
+
readonly providerId: string;
|
|
33
|
+
readonly requestId: string;
|
|
34
|
+
readonly capability: ProviderCapabilityKey;
|
|
35
|
+
readonly method: string;
|
|
36
|
+
readonly payload: unknown;
|
|
37
|
+
}
|
|
38
|
+
export interface ProviderEngineSession {
|
|
39
|
+
request<TResponse = unknown>(method: string, payload: unknown): Promise<TResponse>;
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/** Capability implementations owned by the engine rather than provider code. */
|
|
43
|
+
export interface ProviderEngineCapabilitySurface {
|
|
44
|
+
readonly http: HttpClient;
|
|
45
|
+
readonly browser: BrowserClient;
|
|
46
|
+
readonly stealth: StealthClient;
|
|
47
|
+
readonly stt: SttContext;
|
|
48
|
+
readonly ocr: OcrContext;
|
|
49
|
+
readonly resolver: ResolverContext;
|
|
50
|
+
readonly cache: ProviderCache;
|
|
51
|
+
readonly state: ProviderRuntimeState;
|
|
52
|
+
}
|
|
53
|
+
/** Engine-resident-only capabilities, kept separate from the portable surface. */
|
|
54
|
+
export interface ProviderEngineResidentSurface {
|
|
55
|
+
readonly native: NativeContext;
|
|
56
|
+
}
|
|
57
|
+
export declare const PROVIDER_CAPABILITY_KEYS: readonly ["env", "credential", "http", "files", "native", "cache", "state", "stealth", "browser", "auth", "ocr", "stt", "resolver", "choice"];
|
|
58
|
+
export type ProviderCapabilityKey = (typeof PROVIDER_CAPABILITY_KEYS)[number];
|
|
59
|
+
export type ProviderEngineBindingCandidates = Partial<ProviderEngineCapabilitySurface & ProviderEngineResidentSurface & {
|
|
60
|
+
readonly env: EnvContext;
|
|
61
|
+
readonly credential: CredentialContext;
|
|
62
|
+
readonly files: ProviderFilesContext;
|
|
63
|
+
readonly auth: AuthContext;
|
|
64
|
+
readonly choice: ProviderChoiceContext;
|
|
65
|
+
}> & {
|
|
66
|
+
readonly request?: ProviderRequestContext;
|
|
67
|
+
readonly trace: TraceContext;
|
|
68
|
+
};
|
|
69
|
+
export interface ProviderEngineAttachmentInput {
|
|
70
|
+
readonly provider: ProviderDefinition;
|
|
71
|
+
readonly bindings: ProviderEngineBindingCandidates;
|
|
72
|
+
}
|
|
73
|
+
/** Attachment boundary shared by in-process development and remote RPC bridges. */
|
|
74
|
+
export interface ProviderEngine {
|
|
75
|
+
attach<TDeclaration extends object = Record<string, unknown>>(input: ProviderEngineAttachmentInput): ProviderContext<TDeclaration>;
|
|
76
|
+
}
|
|
77
|
+
/** Local engine attachment; deployed bridges implement the same interface with RPC clients. */
|
|
78
|
+
export declare function createInProcessProviderEngine(): ProviderEngine;
|