@apifuse/provider-sdk 2.1.0-beta.6 → 2.1.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/bin/apifuse-perf.ts +18 -9
  3. package/dist/ceremonies/index.d.ts +41 -0
  4. package/dist/ceremonies/index.js +490 -0
  5. package/dist/choice-token.d.ts +24 -0
  6. package/dist/choice-token.js +74 -0
  7. package/dist/cli/commands.d.ts +10 -0
  8. package/dist/cli/commands.js +80 -0
  9. package/dist/cli/create.d.ts +47 -0
  10. package/dist/cli/create.js +762 -0
  11. package/dist/config/loader.d.ts +107 -0
  12. package/dist/config/loader.js +935 -0
  13. package/dist/contract-json.d.ts +9 -0
  14. package/dist/contract-json.js +51 -0
  15. package/dist/contract-serialization.d.ts +4 -0
  16. package/dist/contract-serialization.js +78 -0
  17. package/dist/contract-types.d.ts +49 -0
  18. package/dist/contract-types.js +1 -0
  19. package/dist/contract.d.ts +6 -0
  20. package/dist/contract.js +155 -0
  21. package/dist/define.d.ts +97 -0
  22. package/dist/define.js +1320 -0
  23. package/dist/dev.d.ts +9 -0
  24. package/dist/dev.js +15 -0
  25. package/dist/errors.d.ts +59 -0
  26. package/dist/errors.js +97 -0
  27. package/dist/i18n/catalog.d.ts +29 -0
  28. package/dist/i18n/catalog.js +159 -0
  29. package/dist/i18n/index.d.ts +2 -0
  30. package/dist/i18n/index.js +2 -0
  31. package/dist/i18n/keys.d.ts +10 -0
  32. package/dist/i18n/keys.js +34 -0
  33. package/dist/index.d.ts +41 -0
  34. package/dist/index.js +37 -0
  35. package/dist/lint.d.ts +73 -0
  36. package/dist/lint.js +702 -0
  37. package/dist/observability.d.ts +5 -0
  38. package/dist/observability.js +39 -0
  39. package/dist/provider.d.ts +9 -0
  40. package/dist/provider.js +8 -0
  41. package/dist/public-schema-field-lint.d.ts +2 -0
  42. package/dist/public-schema-field-lint.js +158 -0
  43. package/dist/recipes/gov-api.d.ts +19 -0
  44. package/dist/recipes/gov-api.js +72 -0
  45. package/dist/recipes/rest-api.d.ts +21 -0
  46. package/dist/recipes/rest-api.js +115 -0
  47. package/dist/runtime/auth-flow.d.ts +14 -0
  48. package/dist/runtime/auth-flow.js +44 -0
  49. package/dist/runtime/browser.d.ts +25 -0
  50. package/dist/runtime/browser.js +1034 -0
  51. package/dist/runtime/cache.d.ts +10 -0
  52. package/dist/runtime/cache.js +372 -0
  53. package/dist/runtime/choice.d.ts +15 -0
  54. package/dist/runtime/choice.js +435 -0
  55. package/dist/runtime/credential.d.ts +8 -0
  56. package/dist/runtime/credential.js +61 -0
  57. package/dist/runtime/env.d.ts +2 -0
  58. package/dist/runtime/env.js +10 -0
  59. package/dist/runtime/executor.d.ts +16 -0
  60. package/dist/runtime/executor.js +51 -0
  61. package/dist/runtime/http.d.ts +8 -0
  62. package/dist/runtime/http.js +706 -0
  63. package/dist/runtime/insights.d.ts +9 -0
  64. package/dist/runtime/insights.js +324 -0
  65. package/dist/runtime/instrumentation.d.ts +8 -0
  66. package/dist/runtime/instrumentation.js +269 -0
  67. package/dist/runtime/key-derivation.d.ts +24 -0
  68. package/dist/runtime/key-derivation.js +73 -0
  69. package/dist/runtime/keyring.d.ts +25 -0
  70. package/dist/runtime/keyring.js +93 -0
  71. package/dist/runtime/namespace.d.ts +9 -0
  72. package/dist/runtime/namespace.js +19 -0
  73. package/dist/runtime/otlp.d.ts +39 -0
  74. package/dist/runtime/otlp.js +103 -0
  75. package/dist/runtime/perf.d.ts +12 -0
  76. package/dist/runtime/perf.js +52 -0
  77. package/dist/runtime/prevalidate.d.ts +12 -0
  78. package/dist/runtime/prevalidate.js +173 -0
  79. package/dist/runtime/provider.d.ts +2 -0
  80. package/dist/runtime/provider.js +11 -0
  81. package/dist/runtime/proxy-errors.d.ts +21 -0
  82. package/dist/runtime/proxy-errors.js +83 -0
  83. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  84. package/dist/runtime/proxy-telemetry.js +174 -0
  85. package/dist/runtime/redis.d.ts +17 -0
  86. package/dist/runtime/redis.js +82 -0
  87. package/dist/runtime/request-options.d.ts +3 -0
  88. package/dist/runtime/request-options.js +42 -0
  89. package/dist/runtime/state.d.ts +17 -0
  90. package/dist/runtime/state.js +344 -0
  91. package/dist/runtime/stealth.d.ts +18 -0
  92. package/dist/runtime/stealth.js +834 -0
  93. package/dist/runtime/stt.d.ts +22 -0
  94. package/dist/runtime/stt.js +480 -0
  95. package/dist/runtime/trace.d.ts +26 -0
  96. package/dist/runtime/trace.js +142 -0
  97. package/dist/runtime/waterfall.d.ts +12 -0
  98. package/dist/runtime/waterfall.js +147 -0
  99. package/dist/schema.d.ts +74 -0
  100. package/dist/schema.js +243 -0
  101. package/dist/serve.d.ts +1 -0
  102. package/dist/serve.js +1 -0
  103. package/dist/server/index.d.ts +3 -0
  104. package/dist/server/index.js +2 -0
  105. package/dist/server/serve.d.ts +64 -0
  106. package/dist/server/serve.js +1110 -0
  107. package/dist/server/types.d.ts +136 -0
  108. package/dist/server/types.js +86 -0
  109. package/dist/stealth/profiles.d.ts +4 -0
  110. package/dist/stealth/profiles.js +259 -0
  111. package/dist/stream.d.ts +44 -0
  112. package/dist/stream.js +151 -0
  113. package/dist/testing/helpers.d.ts +23 -0
  114. package/dist/testing/helpers.js +95 -0
  115. package/dist/testing/index.d.ts +2 -0
  116. package/dist/testing/index.js +2 -0
  117. package/dist/testing/run.d.ts +34 -0
  118. package/dist/testing/run.js +303 -0
  119. package/dist/types.d.ts +1326 -0
  120. package/dist/types.js +61 -0
  121. package/dist/utils/date.d.ts +6 -0
  122. package/dist/utils/date.js +101 -0
  123. package/dist/utils/parse.d.ts +16 -0
  124. package/dist/utils/parse.js +51 -0
  125. package/dist/utils/text.d.ts +4 -0
  126. package/dist/utils/text.js +14 -0
  127. package/dist/utils/transform.d.ts +8 -0
  128. package/dist/utils/transform.js +48 -0
  129. package/package.json +109 -107
  130. package/src/runtime/stealth.ts +8 -1
  131. package/src/types.ts +2 -0
@@ -0,0 +1,1326 @@
1
+ import type ms from "ms";
2
+ import type { infer as ZodInfer, ZodType } from "zod";
3
+ /** Minimal Standard Schema v1 shape accepted by provider operations. */
4
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
5
+ readonly "~standard": {
6
+ readonly version: 1;
7
+ readonly vendor: string;
8
+ readonly validate: (value: unknown) => StandardSchemaV1.Result<Output> | Promise<StandardSchemaV1.Result<Output>>;
9
+ readonly types?: {
10
+ readonly input: Input;
11
+ readonly output: Output;
12
+ };
13
+ };
14
+ }
15
+ export declare namespace StandardSchemaV1 {
16
+ interface Issue {
17
+ readonly message: string;
18
+ readonly path?: readonly (PropertyKey | PathSegment)[];
19
+ }
20
+ interface PathSegment {
21
+ readonly key: PropertyKey;
22
+ }
23
+ interface SuccessResult<Output> {
24
+ readonly value: Output;
25
+ }
26
+ interface FailureResult {
27
+ readonly issues: readonly Issue[];
28
+ }
29
+ type Result<Output> = SuccessResult<Output> | FailureResult;
30
+ }
31
+ /** Schema formats supported by provider operations. */
32
+ export type SchemaLike = ZodType | StandardSchemaV1;
33
+ /** Infer the validated output type produced by a Zod or Standard Schema. */
34
+ export type InferSchemaOutput<TSchema extends SchemaLike> = TSchema extends ZodType ? ZodInfer<TSchema> : TSchema extends StandardSchemaV1<unknown, infer Output> ? Output : unknown;
35
+ export interface OperationInputExample {
36
+ scenario: string;
37
+ input: unknown;
38
+ rationale?: string;
39
+ }
40
+ export type OperationRiskClass = "read" | "write" | "destructive" | "external-send";
41
+ export type OperationApprovalPolicy = "never" | "risk-based" | "always";
42
+ export interface OperationToolRouterMetadata {
43
+ /** Optional MCP-safe override. Defaults to providerId__operationId. */
44
+ name?: string;
45
+ /** Safety class exposed to Tool Router clients and approval policy. */
46
+ riskClass?: OperationRiskClass;
47
+ /** OpenAI remote-MCP approval hint. Defaults from riskClass. */
48
+ approval?: OperationApprovalPolicy;
49
+ /** Override connection requirement when provider auth + openWorld inference is insufficient. */
50
+ requiresConnection?: boolean;
51
+ /** Public argument used to resolve the tenant-owned connection. Defaults to externalRef. */
52
+ connectionExternalRefParam?: string;
53
+ }
54
+ export type OperationSensitivePath = string;
55
+ export interface OperationObservabilitySensitiveConfig {
56
+ /**
57
+ * Additional dot paths to redact from captured invocation inputs. Use `*`
58
+ * for array elements, for example `items.*.phone`.
59
+ */
60
+ input?: readonly OperationSensitivePath[];
61
+ /**
62
+ * Additional dot paths to redact from captured invocation outputs. Use `*`
63
+ * for array elements, for example `items.*.paymentUrl`.
64
+ */
65
+ output?: readonly OperationSensitivePath[];
66
+ }
67
+ export interface OperationObservabilityConfig {
68
+ /**
69
+ * Complements schema-level `fields.*()` / `sensitive()` metadata for values
70
+ * that are shape-dependent, provider-normalized, or otherwise easier to
71
+ * express as stable public paths.
72
+ */
73
+ sensitive?: OperationObservabilitySensitiveConfig;
74
+ }
75
+ export interface OperationAnnotations {
76
+ readOnly?: boolean;
77
+ destructive?: boolean;
78
+ idempotent?: boolean;
79
+ /**
80
+ * Marks the operation as callable without provider-level authentication.
81
+ *
82
+ * Provider-level `auth.mode` describes the **majority** auth model of a
83
+ * provider; individual operations can still opt out via `openWorld: true`
84
+ * when their handler does not consume `ctx.credential`. This is the
85
+ * canonical way to declare "this operation is public, even though the
86
+ * provider is `credentials`-mode" without splitting the provider into two.
87
+ *
88
+ * Health-check projections treat `openWorld: true` operations as
89
+ * connection-free probes (no `requiresConnection` required, no SA token
90
+ * lookup). Future gateway work MAY extend this annotation to bypass
91
+ * `X-ApiFuse-Connection-Id` enforcement at proxy time.
92
+ *
93
+ * Example: Naver Map's `search`, `geocode`, and directions operations
94
+ * call public Naver endpoints with no cookies, while `collections` and
95
+ * `export` consume the user's session cookie — the provider declares
96
+ * `auth.mode: "credentials"` (for the latter) and the former mark
97
+ * `openWorld: true`.
98
+ */
99
+ openWorld?: boolean;
100
+ rateLimit?: {
101
+ calls: number;
102
+ window: "minute" | "hour" | "day";
103
+ };
104
+ timeoutMs?: number;
105
+ }
106
+ export declare const OPERATION_TIMEOUT_MS_MIN = 1;
107
+ export declare const OPERATION_TIMEOUT_MS_MAX = 60000;
108
+ export declare const STREAM_HEARTBEAT_MS_MIN = 1000;
109
+ export declare const STREAM_HEARTBEAT_MS_MAX = 60000;
110
+ export declare const STREAM_IDLE_TIMEOUT_MS_MIN = 1000;
111
+ export declare const STREAM_IDLE_TIMEOUT_MS_MAX = 300000;
112
+ export declare const STREAM_MAX_DURATION_MS_MIN = 1000;
113
+ export declare const STREAM_MAX_DURATION_MS_MAX = 1800000;
114
+ export declare const STREAM_CHUNK_BYTES_MIN = 1;
115
+ export declare const STREAM_CHUNK_BYTES_MAX = 1048576;
116
+ export type OperationTransportKind = "json" | "sse" | "http-stream" | "websocket";
117
+ export interface OperationJsonTransport {
118
+ kind: "json";
119
+ }
120
+ export interface OperationSseTransport {
121
+ kind: "sse";
122
+ heartbeatMs?: number;
123
+ idleTimeoutMs?: number;
124
+ maxDurationMs?: number;
125
+ maxEventBytes?: number;
126
+ resumable?: false | "last-event-id";
127
+ events: Record<string, SchemaLike>;
128
+ }
129
+ export interface OperationHttpStreamTransport {
130
+ kind: "http-stream";
131
+ contentType?: string;
132
+ idleTimeoutMs?: number;
133
+ maxDurationMs?: number;
134
+ maxChunkBytes?: number;
135
+ }
136
+ export interface OperationWebSocketTransport {
137
+ kind: "websocket";
138
+ subprotocols?: readonly string[];
139
+ idleTimeoutMs?: number;
140
+ maxDurationMs?: number;
141
+ maxFrameBytes?: number;
142
+ /**
143
+ * WebSocket Operation metadata is future-ready. Gateway dispatch remains
144
+ * disabled until a gateway-managed session implementation is present.
145
+ */
146
+ dispatch: "unsupported";
147
+ }
148
+ export type OperationTransport = OperationJsonTransport | OperationSseTransport | OperationHttpStreamTransport | OperationWebSocketTransport;
149
+ export declare const DEFAULT_OPERATION_TRANSPORT: OperationJsonTransport;
150
+ export interface OperationRelationships {
151
+ alternatives?: string[];
152
+ }
153
+ export type Iso3166Alpha2CountryCode = Uppercase<string>;
154
+ export type Bcp47Locale = string;
155
+ export type ProviderLocale = Bcp47Locale;
156
+ export type ProviderLocaleKey = string & {
157
+ readonly __brand: "ProviderLocaleKey";
158
+ };
159
+ export type ProviderLocaleKeyInput = ProviderLocaleKey | string;
160
+ export type Iso8601Duration = string;
161
+ export type Rfc3339Instant = string;
162
+ export type IanaTimeZone = string;
163
+ export type Iso4217CurrencyCode = Uppercase<string>;
164
+ export type E164PhoneNumber = `+${string}`;
165
+ export type SmsOrigin = {
166
+ /** Sender represented as an ITU-T E.164 phone number. */
167
+ kind: "e164";
168
+ value: E164PhoneNumber;
169
+ display?: string;
170
+ } | {
171
+ /** Country-local service sender, for example KR 1661-5270. */
172
+ kind: "nationalServiceCode";
173
+ country: Iso3166Alpha2CountryCode;
174
+ value: string;
175
+ display?: string;
176
+ };
177
+ export interface SmsOtpExtractionPattern {
178
+ /** RegExp or source string containing exactly one usable OTP capture. */
179
+ pattern: RegExp | string;
180
+ /** Named capture key or one-based numeric capture index. Defaults to first capture. */
181
+ capture?: string | number;
182
+ }
183
+ export interface SmsOtpMatcherDefinition {
184
+ id: string;
185
+ country: Iso3166Alpha2CountryCode;
186
+ locale?: Bcp47Locale;
187
+ phoneNumber?: E164PhoneNumber;
188
+ origins: readonly [SmsOrigin, ...SmsOrigin[]];
189
+ code: SmsOtpExtractionPattern;
190
+ maxAge: Iso8601Duration;
191
+ waitTimeout: Iso8601Duration;
192
+ clockSkew?: Iso8601Duration;
193
+ /** Runtime/fixture helper. Not serialized into generated registry artifacts. */
194
+ extractOtp(body: string): string | null;
195
+ }
196
+ export type SttTranscribeMode = "general" | "otp";
197
+ export type SttPromptPolicy = "none" | "default-hint" | "custom-hint";
198
+ export type SttUnsupportedOptionPolicy = "warn" | "error";
199
+ export type ProviderSttMode = "optional" | "required";
200
+ export interface ProviderSttConfig {
201
+ mode: ProviderSttMode;
202
+ }
203
+ export type SttAudioInput = {
204
+ kind: "base64";
205
+ data: string;
206
+ mediaType?: string;
207
+ durationMs?: number;
208
+ };
209
+ export interface SttVerificationCodeOptions {
210
+ locale?: Bcp47Locale;
211
+ codeLengths?: number | readonly number[] | {
212
+ min: number;
213
+ max: number;
214
+ };
215
+ }
216
+ export interface SttTranscribeRequest {
217
+ audio: SttAudioInput;
218
+ language?: Bcp47Locale;
219
+ mode?: SttTranscribeMode;
220
+ promptPolicy?: SttPromptPolicy;
221
+ initialPrompt?: string;
222
+ unsupportedOptionPolicy?: SttUnsupportedOptionPolicy;
223
+ verificationCode?: SttVerificationCodeOptions;
224
+ timeoutMs?: number;
225
+ maxAudioBytes?: number;
226
+ }
227
+ export interface SttSegment {
228
+ text: string;
229
+ startMs?: number;
230
+ endMs?: number;
231
+ confidence?: number;
232
+ }
233
+ export interface SttUsage {
234
+ audioDurationMs?: number;
235
+ audioBytes?: number;
236
+ billableUnits?: number;
237
+ }
238
+ export interface SttWarning {
239
+ code: "UNSUPPORTED_STT_OPTION" | "PROMPT_IGNORED" | "LOCALE_PARTIAL";
240
+ message: string;
241
+ }
242
+ export interface SttTranscript {
243
+ text: string;
244
+ language?: Bcp47Locale;
245
+ durationMs?: number;
246
+ segments?: readonly SttSegment[];
247
+ usage?: SttUsage;
248
+ warnings?: readonly SttWarning[];
249
+ verificationCode?: VerificationCodeExtractionResult;
250
+ }
251
+ export type VerificationCodeCandidateSource = "digits" | "spoken_words" | "mixed";
252
+ export interface VerificationCodeCandidate {
253
+ code: string;
254
+ source: VerificationCodeCandidateSource;
255
+ startIndex?: number;
256
+ endIndex?: number;
257
+ }
258
+ export interface VerificationCodeExtractionResult {
259
+ code: string;
260
+ candidates: readonly VerificationCodeCandidate[];
261
+ normalizedText: string;
262
+ }
263
+ export interface SttContext {
264
+ transcribe(request: SttTranscribeRequest): Promise<SttTranscript>;
265
+ extractVerificationCode(text: string, options?: SttVerificationCodeOptions): VerificationCodeExtractionResult;
266
+ }
267
+ export interface HealthJourneySchedule {
268
+ kind: "interval";
269
+ /** ISO 8601 duration, for example PT8H. */
270
+ interval: Iso8601Duration;
271
+ jitter?: Iso8601Duration;
272
+ }
273
+ export interface HealthJourneyStep {
274
+ id: string;
275
+ description?: string;
276
+ operationId?: string;
277
+ usesSmsMatcher?: string;
278
+ coversOperations?: readonly string[];
279
+ safeBoundary?: "paymentWebviewUrl" | "paymentUrl" | "none";
280
+ kind?: "operation" | "smsOtp" | "assertion" | "journal";
281
+ }
282
+ export interface HealthJourneyGatewayContext {
283
+ connect?(options?: {
284
+ providerId?: string;
285
+ externalRef?: string;
286
+ authMode?: "credentials" | "oauth2";
287
+ input?: Record<string, unknown>;
288
+ metadata?: Record<string, unknown>;
289
+ }): Promise<{
290
+ connectionId: string;
291
+ rowVersion: number;
292
+ }>;
293
+ disconnect?(connection: {
294
+ connectionId: string;
295
+ rowVersion: number;
296
+ }): Promise<void>;
297
+ execute(providerId: string, operationId: string, input: unknown, options?: {
298
+ connectionId?: string;
299
+ requestId?: string;
300
+ /**
301
+ * Set false when the journey will record the semantic operation
302
+ * outcome itself through `ctx.event.operation()`. Transport success
303
+ * must not become a competing public health sample in that case.
304
+ */
305
+ recordOperationEvent?: boolean;
306
+ }): Promise<{
307
+ data: unknown;
308
+ status: number;
309
+ duration: number;
310
+ meta?: Record<string, unknown>;
311
+ }>;
312
+ }
313
+ export interface SmsPhoneIdentity {
314
+ id: string;
315
+ country: Iso3166Alpha2CountryCode | string;
316
+ e164: E164PhoneNumber | string;
317
+ nationalNumber: string;
318
+ displayName?: string;
319
+ }
320
+ export interface HealthJourneySmsContext {
321
+ resolvePhone(params?: {
322
+ matcherId?: string;
323
+ }): Promise<SmsPhoneIdentity>;
324
+ waitForOtp(params: {
325
+ matcherId: string;
326
+ attemptId: string;
327
+ phoneId?: string;
328
+ phoneNumber?: string;
329
+ signal?: AbortSignal;
330
+ }): Promise<{
331
+ code: string;
332
+ messageId: string;
333
+ receivedAt: string;
334
+ }>;
335
+ }
336
+ export interface HealthJourneyJournalContext {
337
+ sideEffect<T>(params: {
338
+ stepId: string;
339
+ kind: string;
340
+ idempotencyKey: string;
341
+ run: () => Promise<T>;
342
+ }): Promise<T>;
343
+ }
344
+ export interface HealthJourneyEventContext {
345
+ /**
346
+ * Record an operation-level health outcome that was proven by the journey but
347
+ * not emitted by a direct `ctx.gateway.execute()` call, such as a recovery or
348
+ * manual-review assertion. This is intentionally narrow; it is not a generic
349
+ * event bus.
350
+ */
351
+ operation(params: {
352
+ operationId: string;
353
+ status: "ok" | "degraded" | "down" | "unknown" | "not_reached";
354
+ stepId?: string;
355
+ label?: string;
356
+ error?: string;
357
+ latencyMs?: number;
358
+ statusCode?: number;
359
+ metadata?: Record<string, unknown>;
360
+ }): Promise<void>;
361
+ }
362
+ export interface HealthJourneyRunContext {
363
+ attemptId: string;
364
+ providerId: string;
365
+ journeyId: string;
366
+ gateway: HealthJourneyGatewayContext;
367
+ sms: HealthJourneySmsContext;
368
+ journal: HealthJourneyJournalContext;
369
+ state: ProviderRuntimeState;
370
+ event: HealthJourneyEventContext;
371
+ signal: AbortSignal;
372
+ secrets: Record<string, string | undefined>;
373
+ }
374
+ export type HealthJourneyManualTriggerPolicy = {
375
+ enabled: false;
376
+ reason?: string;
377
+ } | {
378
+ enabled: true;
379
+ requiresAcknowledgement: boolean;
380
+ risk: "read_only" | "writes_external_state" | "sms_or_payment";
381
+ /** ISO 8601 duration. Minimum time between manual executions. */
382
+ minManualInterval: Iso8601Duration;
383
+ publicRationale: string;
384
+ };
385
+ export interface HealthJourneyRunResult {
386
+ status?: "ok" | "degraded" | "down" | "unknown";
387
+ label?: string;
388
+ metadata?: Record<string, unknown>;
389
+ }
390
+ export interface HealthJourneyDefinition {
391
+ id: string;
392
+ title?: string;
393
+ description?: string;
394
+ schedule: HealthJourneySchedule;
395
+ coversOperations: readonly [string, ...string[]];
396
+ timeout?: Iso8601Duration;
397
+ cooldown?: Iso8601Duration;
398
+ smsMatchers?: readonly SmsOtpMatcherDefinition[];
399
+ requiredSecrets?: readonly string[];
400
+ manualTrigger?: HealthJourneyManualTriggerPolicy;
401
+ steps: readonly [HealthJourneyStep, ...HealthJourneyStep[]];
402
+ run?: (ctx: HealthJourneyRunContext) => Promise<HealthJourneyRunResult | undefined>;
403
+ }
404
+ /**
405
+ * Health-check authoring surface owned by `@apifuse/provider-sdk`.
406
+ *
407
+ * IMPORTANT (architectural invariant): These types are PURE DATA + assertion
408
+ * lambdas. They MUST NOT import or reference any health-monitor runtime
409
+ * surface (scheduler, recorder, gateway client, registry projection types).
410
+ * Provider declarations remain runtime-agnostic at build time.
411
+ *
412
+ * See `openspec/changes/enforce-sdk-operation-health-suite/design.md` §D1.
413
+ */
414
+ /** Polling interval duration accepted by the health-monitor runtime. */
415
+ export type ProbeInterval = ms.StringValue;
416
+ /**
417
+ * Common probe interval examples retained for discoverability/backwards
418
+ * compatibility. This list is not exhaustive; any positive `ms`-style duration
419
+ * string accepted by `@types/ms` (for example `2m`, `8h`, or `1 day`) is valid.
420
+ */
421
+ export declare const PROBE_INTERVALS: readonly ProbeInterval[];
422
+ export declare const HEALTH_CHECK_TIMEOUT_MS_MIN = 1;
423
+ export declare const HEALTH_CHECK_TIMEOUT_MS_MAX = 60000;
424
+ export declare const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN = 1;
425
+ export declare const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX = 60000;
426
+ /**
427
+ * Context passed to a `HealthCheckCase.assertions` lambda.
428
+ * `data` is typed against the operation's declared output schema (TOutput).
429
+ */
430
+ export interface HealthCheckAssertionContext<TOutput = unknown> {
431
+ /** Parsed response body (already validated against operation.output). */
432
+ readonly data: TOutput;
433
+ /** HTTP status code returned by the gateway. */
434
+ readonly status: number;
435
+ /** Wall-clock duration of the operation invocation, in milliseconds. */
436
+ readonly durationMs: number;
437
+ /** Optional provider response metadata such as cache hit/stale flags. */
438
+ readonly meta?: Record<string, unknown>;
439
+ }
440
+ export interface HealthCheckInputPreparationContext<TInput = unknown> {
441
+ readonly providerId: string;
442
+ readonly operationId: string;
443
+ readonly input: TInput;
444
+ readonly connectionId?: string;
445
+ readonly gateway: {
446
+ execute: (providerId: string, operationId: string, input: unknown, options?: {
447
+ connectionId?: string;
448
+ }) => Promise<{
449
+ status: number;
450
+ duration: number;
451
+ data: unknown;
452
+ meta?: Record<string, unknown>;
453
+ }>;
454
+ };
455
+ }
456
+ /**
457
+ * Optional return value from an assertions lambda. Allows the case to
458
+ * downgrade to "degraded" without throwing, and to attach a human-friendly
459
+ * label that surfaces on the status page (e.g., "BTC 95,000,000원").
460
+ */
461
+ export interface HealthCheckCaseResult {
462
+ /** Override final status; if omitted, "ok" unless assertion threw. */
463
+ status?: "ok" | "degraded";
464
+ /** Optional human-readable label surfaced on the status page. */
465
+ label?: string;
466
+ }
467
+ /**
468
+ * A single test-case-style verification scenario for an operation.
469
+ *
470
+ * Type parameters flow from the OperationDefinition's input/output schemas
471
+ * so authors get IntelliSense and compile-time errors when accessing fields
472
+ * that do not exist on the operation's declared output schema.
473
+ */
474
+ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
475
+ /** Human-readable case name; unique within the suite. */
476
+ name: string;
477
+ /** Optional longer description shown on ops dashboards. */
478
+ description?: string;
479
+ /** Input passed to the operation handler for this case. */
480
+ input: TInput;
481
+ /**
482
+ * Optional runtime input preparation hook for volatile probes. Use this when
483
+ * the durable probe input must be derived from a live read-only operation
484
+ * immediately before the checked operation executes.
485
+ */
486
+ prepareInput?: (ctx: HealthCheckInputPreparationContext<TInput>) => TInput | Promise<TInput>;
487
+ /**
488
+ * Assertion executed against the operation's response and timing.
489
+ *
490
+ * - Throw to fail the case (recorded as `down`).
491
+ * - Return `{ status: "degraded", label }` to flag without failing.
492
+ * - Return `void` (implicit) for `ok`.
493
+ *
494
+ * MUST NOT access scheduler, recorder, or any runtime type — pure data
495
+ * + lambda only.
496
+ */
497
+ assertions: (ctx: HealthCheckAssertionContext<TOutput>) => void | Promise<void> | HealthCheckCaseResult | Promise<HealthCheckCaseResult>;
498
+ /** Override per-case degradation threshold (ms); falls back to the suite default. */
499
+ degradedThresholdMs?: number;
500
+ /** Override per-case timeout in milliseconds; falls back to the suite/provider/runtime default. */
501
+ timeoutMs?: number;
502
+ /** Expected outcome for "negative" cases (e.g., expecting a degraded baseline). Default: `"ok"`. */
503
+ expectedStatus?: "ok" | "degraded";
504
+ /** Runtime gate (env-driven); if returns false the case is skipped & logged. */
505
+ enabled?: () => boolean;
506
+ }
507
+ /**
508
+ * Operation-level health-check suite. At least one case is required when
509
+ * present. All cases share the suite's interval and default timeout.
510
+ */
511
+ export interface HealthCheckSuite<TInput = unknown, TOutput = unknown> {
512
+ /** Polling interval for the suite. All cases share this cadence. */
513
+ interval: ProbeInterval;
514
+ /** Per-case timeout in milliseconds. Default: 30000. */
515
+ timeoutMs?: number;
516
+ /** Default degradation threshold for cases in this suite. Default: runtime threshold. */
517
+ degradedThresholdMs?: number;
518
+ /** Non-empty list of cases. Empty arrays are rejected at definition time. */
519
+ cases: [
520
+ HealthCheckCase<TInput, TOutput>,
521
+ ...HealthCheckCase<TInput, TOutput>[]
522
+ ];
523
+ /**
524
+ * If true, the runtime SHALL invoke `connect()` before `execute()` and
525
+ * `disconnect()` after, using the service-account token. The provider
526
+ * MUST also declare `healthMonitor.requiredSecrets` for the env values
527
+ * the connect ceremony will consume.
528
+ */
529
+ requiresConnection?: boolean;
530
+ }
531
+ /**
532
+ * Explicit, audited opt-out for operations that genuinely cannot be probed
533
+ * (e.g., destructive mutations, paid-per-call flows). Either `healthCheck`
534
+ * or `healthCheckUnsupported` SHALL be present on every operation; missing
535
+ * both is a registry-build error.
536
+ */
537
+ export interface HealthCheckUnsupported {
538
+ /** Human-readable explanation. Required, non-empty. */
539
+ reason: string;
540
+ /** Optional issue/PR url that revisits the decision. */
541
+ trackedIn?: string;
542
+ }
543
+ /**
544
+ * Provider-level monitoring metadata for credential-bearing health checks.
545
+ * Describes ONLY env-secret keys the runtime needs and the service account
546
+ * to use; SHALL NOT carry probe schedules, sample inputs, or assertion
547
+ * logic (those remain on `OperationDefinition.healthCheck`).
548
+ */
549
+ export interface ProviderHealthMonitorConfig {
550
+ /**
551
+ * Provider-wide default probe timeout in milliseconds. Individual
552
+ * `healthCheck.timeoutMs` and `healthCheck.cases[].timeoutMs` values take
553
+ * precedence. Defaults to the monitor runtime default.
554
+ */
555
+ defaultProbeTimeoutMs?: number;
556
+ /**
557
+ * Provider-wide default latency threshold in milliseconds before an
558
+ * otherwise successful probe is marked degraded. Suite/case thresholds take
559
+ * precedence. Defaults to the monitor runtime default.
560
+ */
561
+ defaultDegradedThresholdMs?: number;
562
+ /**
563
+ * Env-secret key names (e.g., "APIFUSE__HEALTH_MONITOR__CATCHTABLE_PHONE") the
564
+ * synthetic-monitor runtime needs to execute probes that declare
565
+ * `requiresConnection: true`.
566
+ */
567
+ requiredSecrets?: string[];
568
+ /**
569
+ * Mapping from provider auth ceremony input fields to runtime env-secret
570
+ * names. The health-monitor uses this to create a fresh connection for
571
+ * `requiresConnection: true` probes, then disconnects after execution.
572
+ */
573
+ credentialInputs?: Record<string, string>;
574
+ /**
575
+ * Runtime probe overrides keyed by generated registry probe id. Use this for
576
+ * operation health checks that need a runtime-specific interval or threshold
577
+ * without changing the provider-authored default suite.
578
+ */
579
+ probeOverrides?: Record<string, HealthMonitorProbeOverride>;
580
+ /**
581
+ * Override the default service account ID for this provider's probes.
582
+ * Defaults to the runtime's `APIFUSE__HEALTH_MONITOR__SERVICE_ACCOUNT_ID` env var.
583
+ */
584
+ serviceAccount?: string;
585
+ }
586
+ export interface HealthMonitorProbeOverride {
587
+ /** Optional runtime interval override as a positive `ms`-style duration string. */
588
+ interval?: ProbeInterval;
589
+ /** Optional timeout override for generated registry probes. */
590
+ timeoutMs?: number;
591
+ /** Optional degraded threshold override for generated registry probes. */
592
+ degradedThresholdMs?: number;
593
+ }
594
+ export interface OperationErrorCode {
595
+ code: string;
596
+ status?: number;
597
+ description: string;
598
+ retryable?: boolean;
599
+ }
600
+ export interface OperationDocMeta {
601
+ titleKey?: ProviderLocaleKeyInput;
602
+ descriptionKey?: ProviderLocaleKeyInput;
603
+ summaryKey?: ProviderLocaleKeyInput;
604
+ markdownKey?: ProviderLocaleKeyInput;
605
+ normalizationNotesKeys?: ProviderLocaleKeyInput[];
606
+ requestExample?: Record<string, unknown>;
607
+ responseExample?: unknown;
608
+ errorCodes?: OperationErrorCode[];
609
+ }
610
+ export type StealthPlatform = "macos" | "windows" | "linux" | "android" | "ios";
611
+ export type BrowserEngine = "playwright-stealth" | "nodriver" | "selenium-uc";
612
+ export interface BrowserOptions {
613
+ headless?: boolean;
614
+ stealth?: boolean;
615
+ proxy?: string;
616
+ engine?: BrowserEngine;
617
+ requireCdpPool?: boolean;
618
+ }
619
+ export interface StealthProfile {
620
+ name: string;
621
+ platform: StealthPlatform;
622
+ version: string;
623
+ userAgent: string;
624
+ tlsClientIdentifier?: string;
625
+ ja3?: string;
626
+ ja4?: string;
627
+ h2Settings?: Record<string, unknown>;
628
+ headerOrder?: string[];
629
+ }
630
+ export type AuthMode = "none" | "platform-managed" | "credentials" | "oauth2";
631
+ export type ConnectionMode = AuthMode;
632
+ export type ProviderReviewed = "first-party" | "community" | "staging";
633
+ export type ProviderAccessVisibility = "public" | "early_access";
634
+ export type ProviderProxyMode = "disabled" | "optional" | "required";
635
+ export type ProviderProxyProvider = "smartproxy" | "decodo" | "custom";
636
+ export type ProviderProxySessionAffinity = "request" | "operation" | "auth-flow" | "connection";
637
+ export interface ProviderProxyPolicy {
638
+ /**
639
+ * Provider intent only. Transport details such as raw CONNECT, origin
640
+ * certificate verification, and vendor allocator endpoints are SDK-owned.
641
+ */
642
+ mode: ProviderProxyMode;
643
+ provider?: ProviderProxyProvider;
644
+ geo?: {
645
+ /** ISO 3166-1 alpha-2 country code, for example KR or US. */
646
+ country?: Iso3166Alpha2CountryCode;
647
+ subdivision?: string;
648
+ city?: string;
649
+ };
650
+ session?: {
651
+ affinity?: ProviderProxySessionAffinity;
652
+ lifetimeMinutes?: number;
653
+ poolSize?: number;
654
+ };
655
+ }
656
+ export type ProviderProxyConfig = boolean | ProviderProxyPolicy;
657
+ export interface ProviderAccessConfig {
658
+ /**
659
+ * Provider-level rollout visibility.
660
+ *
661
+ * - `public`: visible in public docs/catalog/OpenAPI and callable through
662
+ * the existing provider policy stack.
663
+ * - `early_access`: hidden from public discovery and callable only when the
664
+ * active customer organization has a provider-level access grant.
665
+ *
666
+ * This is intentionally provider-level only. It does not alter auth mode,
667
+ * operation schemas, health-check authoring, `openWorld`, or Connection
668
+ * requirements.
669
+ */
670
+ visibility?: ProviderAccessVisibility;
671
+ }
672
+ export type ProviderLogoSource = "asset" | "monogram" | "none";
673
+ export type ProviderLogoProfile = {
674
+ source: "asset";
675
+ path: string;
676
+ /**
677
+ * Absolute, customer-renderable URL emitted by discovery projections.
678
+ * Provider source definitions may omit this and let the registry projection
679
+ * derive it from the committed public asset path.
680
+ */
681
+ url?: string;
682
+ background?: string;
683
+ } | {
684
+ source: "monogram" | "none";
685
+ background?: string;
686
+ fallbackReason: string;
687
+ };
688
+ export type ProviderPublicConnectionMode = "apifuse_managed" | "workspace_enabled" | "user_connected" | "no_connection_required";
689
+ export type ProviderSupportLevel = "stable" | "beta" | "experimental";
690
+ export interface ProviderPublicProfile {
691
+ displayNameKey?: ProviderLocaleKeyInput;
692
+ shortDescriptionKey?: ProviderLocaleKeyInput;
693
+ longDescriptionKey?: ProviderLocaleKeyInput;
694
+ logo?: ProviderLogoProfile;
695
+ category?: string;
696
+ tags?: readonly string[];
697
+ capabilityKeys?: readonly ProviderLocaleKeyInput[];
698
+ examplePromptKeys?: readonly ProviderLocaleKeyInput[];
699
+ setupSummaryKey?: ProviderLocaleKeyInput;
700
+ connectionMode?: ProviderPublicConnectionMode;
701
+ requirementKeys?: readonly ProviderLocaleKeyInput[];
702
+ limitationKeys?: readonly ProviderLocaleKeyInput[];
703
+ availability?: {
704
+ regions?: readonly string[];
705
+ supportLevel?: ProviderSupportLevel;
706
+ };
707
+ /**
708
+ * Brand primary color as a 6-digit hex string (e.g. "#1a73e8").
709
+ * Single source of truth for all provider-specific color expressions
710
+ * (mood wash, monogram fallback, icon tint). The UI derives subtle washes
711
+ * via color-mix; provider definitions do not control mood percentages.
712
+ */
713
+ primaryColor?: string;
714
+ }
715
+ export interface ProviderMeta {
716
+ displayName: string;
717
+ displayNameKey?: ProviderLocaleKeyInput;
718
+ descriptionKey: ProviderLocaleKeyInput;
719
+ category: string;
720
+ tags?: readonly string[];
721
+ icon?: string;
722
+ docTitleKey?: ProviderLocaleKeyInput;
723
+ docDescriptionKey?: ProviderLocaleKeyInput;
724
+ docSummaryKey?: ProviderLocaleKeyInput;
725
+ docMarkdownKey?: ProviderLocaleKeyInput;
726
+ normalizationNotesKeys?: readonly ProviderLocaleKeyInput[];
727
+ environment?: "staging";
728
+ purpose?: string;
729
+ purposeKey?: ProviderLocaleKeyInput;
730
+ publicProfile?: ProviderPublicProfile;
731
+ contract?: {
732
+ publicSchemaFieldNames?: "normalized";
733
+ };
734
+ }
735
+ export type RequestParamPrimitive = string | number | boolean | null | undefined;
736
+ export type RequestParamValue = RequestParamPrimitive | readonly RequestParamPrimitive[];
737
+ export type RequestParams = Record<string, RequestParamValue>;
738
+ export declare const HttpRetryPreset: {
739
+ readonly Off: "off";
740
+ readonly TransportTransient: "transport_transient";
741
+ readonly SafeRead: "safe_read";
742
+ readonly AggressiveRead: "aggressive_read";
743
+ readonly RateLimitAware: "rate_limit_aware";
744
+ };
745
+ export type HttpRetryPreset = (typeof HttpRetryPreset)[keyof typeof HttpRetryPreset];
746
+ export declare const HttpRetryJitter: {
747
+ readonly None: "none";
748
+ readonly Full: "full";
749
+ readonly Equal: "equal";
750
+ };
751
+ export type HttpRetryJitter = (typeof HttpRetryJitter)[keyof typeof HttpRetryJitter];
752
+ export declare const HttpRetryDelayStrategy: {
753
+ readonly Fixed: "fixed";
754
+ readonly Exponential: "exponential";
755
+ };
756
+ export type HttpRetryDelayStrategy = (typeof HttpRetryDelayStrategy)[keyof typeof HttpRetryDelayStrategy];
757
+ export declare const HttpRetryAfterPolicy: {
758
+ readonly Ignore: "ignore";
759
+ /** Honor Retry-After up to maxDelayMs. */
760
+ readonly Respect: "respect";
761
+ /** Honor Retry-After but also cap it to the SDK-computed backoff delay. */
762
+ readonly Cap: "cap";
763
+ };
764
+ export type HttpRetryAfterPolicy = (typeof HttpRetryAfterPolicy)[keyof typeof HttpRetryAfterPolicy];
765
+ export declare const HttpRetryUnsafeMethodPolicy: {
766
+ readonly Reject: "reject";
767
+ readonly AllowExplicitUnsafe: "allow_explicit_unsafe";
768
+ };
769
+ export type HttpRetryUnsafeMethodPolicy = (typeof HttpRetryUnsafeMethodPolicy)[keyof typeof HttpRetryUnsafeMethodPolicy];
770
+ export interface HttpRetryOptions {
771
+ preset?: HttpRetryPreset;
772
+ /** Total logical ctx.http attempts, including the first attempt. */
773
+ attempts?: number;
774
+ methods?: readonly HttpMethod[];
775
+ statusCodes?: readonly number[];
776
+ errorCodes?: readonly string[];
777
+ delayStrategy?: HttpRetryDelayStrategy;
778
+ baseDelayMs?: number;
779
+ maxDelayMs?: number;
780
+ jitter?: HttpRetryJitter;
781
+ retryAfter?: HttpRetryAfterPolicy;
782
+ unsafeMethodPolicy?: HttpRetryUnsafeMethodPolicy;
783
+ }
784
+ export interface HttpRetrySummary {
785
+ attempts: number;
786
+ retries: number;
787
+ preset?: HttpRetryPreset;
788
+ transport: "native";
789
+ lastErrorCode?: string;
790
+ lastStatus?: number;
791
+ }
792
+ export interface RequestOptions {
793
+ headers?: Record<string, string>;
794
+ params?: RequestParams;
795
+ proxy?: string;
796
+ timeout?: number;
797
+ /**
798
+ * Defaults to true. Set to false when callers need to inspect upstream
799
+ * non-2xx bodies themselves instead of converting them to TransportError.
800
+ */
801
+ throwOnHttpError?: boolean;
802
+ retry?: boolean | HttpRetryPreset | HttpRetryOptions;
803
+ }
804
+ export type HttpMethod = "HEAD" | "head" | "GET" | "get" | "POST" | "post" | "PUT" | "put" | "DELETE" | "delete" | "OPTIONS" | "options" | "TRACE" | "trace" | "PATCH" | "patch";
805
+ export interface StealthFetchOptions extends RequestOptions {
806
+ method?: HttpMethod;
807
+ body?: string | Buffer;
808
+ /**
809
+ * Offsets policy-managed proxy pool selection for caller-managed retries.
810
+ * Use when a request receives an upstream challenge page rather than a
811
+ * transport error, so the next logical retry does not restart at the same
812
+ * operation-affinity proxy.
813
+ */
814
+ proxyAttemptOffset?: number;
815
+ /** Override the configured browser-like stealth profile for this request. */
816
+ profile?: string;
817
+ /**
818
+ * Stealth transport certificate controls. Use only for proxy products that
819
+ * terminate CONNECT with a private CA instead of tunneling the origin
820
+ * certificate chain.
821
+ */
822
+ stealth?: {
823
+ insecureSkipVerify?: boolean;
824
+ };
825
+ }
826
+ export interface CookieJar {
827
+ get(name: string): string | undefined;
828
+ getAll(): Record<string, string>;
829
+ toString(): string;
830
+ find?(predicate: (cookie: string) => boolean): string | undefined;
831
+ }
832
+ export interface DeclarativeStealthResponse {
833
+ status: number;
834
+ ok: boolean;
835
+ headers: Record<string, string>;
836
+ rawHeaders: [string, string][];
837
+ body: string;
838
+ httpVersion?: string;
839
+ tlsInfo?: {
840
+ protocol?: string;
841
+ cipher?: string;
842
+ [key: string]: unknown;
843
+ };
844
+ cookies: CookieJar;
845
+ json<T>(): Promise<T>;
846
+ arrayBuffer(): Promise<ArrayBuffer>;
847
+ bytes(): Promise<Uint8Array>;
848
+ }
849
+ export type StealthResponse = DeclarativeStealthResponse;
850
+ export type RequestWithMethodOptions = RequestOptions & {
851
+ method?: string;
852
+ body?: unknown;
853
+ };
854
+ export interface StealthSession {
855
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
856
+ close(): void;
857
+ }
858
+ export interface ApiFuseResponse<T> {
859
+ data: T;
860
+ meta: {
861
+ requestId: string;
862
+ duration: number;
863
+ cached?: boolean;
864
+ stale?: boolean;
865
+ cache?: ProviderCacheResponseMeta;
866
+ retry?: HttpRetrySummary;
867
+ };
868
+ }
869
+ export interface HttpResponse<T = unknown> {
870
+ status: number;
871
+ ok: boolean;
872
+ headers: Record<string, string>;
873
+ data: T;
874
+ json<U = T>(): Promise<U>;
875
+ text(): Promise<string>;
876
+ }
877
+ export interface HttpStreamResponse {
878
+ status: number;
879
+ ok: boolean;
880
+ headers: Record<string, string>;
881
+ body: ReadableStream<Uint8Array>;
882
+ bytes(): AsyncIterable<Uint8Array>;
883
+ textChunks(): AsyncIterable<string>;
884
+ lines(): AsyncIterable<string>;
885
+ }
886
+ export interface SseMessage {
887
+ event: string;
888
+ data: string;
889
+ id?: string;
890
+ retry?: number;
891
+ json<T = unknown>(): T;
892
+ }
893
+ export interface ProviderStreamEvent<TData = unknown> {
894
+ event: string;
895
+ data: TData;
896
+ id?: string;
897
+ retry?: number;
898
+ }
899
+ export type OperationHandlerResult<TOutput> = TOutput | Response | ReadableStream<Uint8Array> | AsyncIterable<ProviderStreamEvent>;
900
+ export interface HttpClient {
901
+ request(url: string, opts?: RequestWithMethodOptions): Promise<HttpResponse>;
902
+ get(url: string, options?: RequestOptions): Promise<HttpResponse>;
903
+ post(url: string, body: unknown, options?: RequestOptions): Promise<HttpResponse>;
904
+ put(url: string, body: unknown, options?: RequestOptions): Promise<HttpResponse>;
905
+ delete(url: string, options?: RequestOptions): Promise<HttpResponse>;
906
+ stream(url: string, options?: RequestWithMethodOptions): Promise<HttpStreamResponse>;
907
+ sse(url: string, options?: RequestWithMethodOptions): Promise<AsyncIterable<SseMessage>>;
908
+ }
909
+ export interface ProviderCacheKeyOptions {
910
+ /**
911
+ * Additional field names to omit from stable key material. The SDK always
912
+ * omits known secret-bearing names such as serviceKey, authorization,
913
+ * cookie, token, password, and secret.
914
+ */
915
+ redactFields?: string[];
916
+ }
917
+ export interface ProviderCacheGetOrSetOptions {
918
+ /** Freshness TTL. A fresh hit returns without calling the loader. */
919
+ ttlMs: number;
920
+ /**
921
+ * Optional stale window after ttlMs. If the loader fails while the entry is
922
+ * still inside this window, stale data is returned and marked stale.
923
+ */
924
+ staleIfErrorMs?: number;
925
+ /** Optional jitter applied to writes to avoid synchronized expiry. */
926
+ jitterPct?: number;
927
+ }
928
+ export interface ProviderCacheLookupMeta {
929
+ key: string;
930
+ hit: boolean;
931
+ stale: boolean;
932
+ ageMs?: number;
933
+ source: "redis" | "memory" | "loader";
934
+ }
935
+ export interface ProviderCacheResult<T> {
936
+ value: T;
937
+ meta: ProviderCacheLookupMeta;
938
+ }
939
+ export interface ProviderCacheResponseMeta {
940
+ hit: boolean;
941
+ stale: boolean;
942
+ keys: string[];
943
+ source?: "redis" | "memory" | "loader" | "mixed";
944
+ }
945
+ export interface ProviderCache {
946
+ key(namespace: string, parts: unknown, options?: ProviderCacheKeyOptions): string;
947
+ get<T = unknown>(key: string): Promise<ProviderCacheResult<T> | null>;
948
+ set<T = unknown>(key: string, value: T, options: ProviderCacheGetOrSetOptions): Promise<void>;
949
+ delete(key: string): Promise<void>;
950
+ getOrSet<T = unknown>(key: string, loader: () => Promise<T>, options: ProviderCacheGetOrSetOptions): Promise<ProviderCacheResult<T>>;
951
+ responseMeta(): ProviderCacheResponseMeta | undefined;
952
+ }
953
+ export interface StealthClient {
954
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
955
+ createSession(opts?: {
956
+ profile?: string;
957
+ }): StealthSession;
958
+ close?(): void;
959
+ }
960
+ export interface BrowserClient {
961
+ readonly engine: BrowserEngine;
962
+ close?(): Promise<void>;
963
+ newPage(): Promise<BrowserPage>;
964
+ rawPage(): Promise<BrowserPage>;
965
+ withIsolatedContext<T>(handler: (page: BrowserPage) => Promise<T>): Promise<T>;
966
+ solveChallenge(request: BrowserChallengeRequest): Promise<BrowserChallengeResult>;
967
+ }
968
+ export interface BrowserLocator {
969
+ click(): Promise<void>;
970
+ fill(text: string): Promise<void>;
971
+ textContent(): Promise<string | null>;
972
+ waitFor(options?: {
973
+ timeout?: number;
974
+ }): Promise<void>;
975
+ }
976
+ export interface BrowserFrame {
977
+ id: string;
978
+ name?: string;
979
+ parentId?: string;
980
+ url(): Promise<string>;
981
+ title(): Promise<string>;
982
+ content(): Promise<string>;
983
+ evaluate<T>(fn: string | (() => T)): Promise<T>;
984
+ locator(selector: string): BrowserLocator;
985
+ }
986
+ export interface BrowserPage extends BrowserFrame {
987
+ close(): Promise<void>;
988
+ fill(selector: string, text: string): Promise<void>;
989
+ goto(url: string): Promise<void>;
990
+ pageId?: string;
991
+ screenshot(options?: {
992
+ fullPage?: boolean;
993
+ }): Promise<Buffer>;
994
+ click(selector: string): Promise<void>;
995
+ type(selector: string, text: string): Promise<void>;
996
+ waitForSelector(selector: string, options?: {
997
+ timeout?: number;
998
+ }): Promise<void>;
999
+ frames(): Promise<BrowserFrame[]>;
1000
+ }
1001
+ export type BrowserChallengeRequest = {
1002
+ type: "recaptcha";
1003
+ siteKey?: string;
1004
+ timeout?: number;
1005
+ };
1006
+ export type BrowserChallengeResult = {
1007
+ type: BrowserChallengeRequest["type"];
1008
+ solved: boolean;
1009
+ frameUrl?: string;
1010
+ };
1011
+ export type TraceAttributeValue = string | number | boolean;
1012
+ export interface TraceSpan {
1013
+ id: string;
1014
+ name: string;
1015
+ startedAt: number;
1016
+ endedAt: number;
1017
+ duration_ms: number;
1018
+ status: "ok" | "error";
1019
+ error?: string;
1020
+ attributes: Record<string, TraceAttributeValue>;
1021
+ parentId?: string;
1022
+ }
1023
+ export interface TraceConfig {
1024
+ enabled?: boolean;
1025
+ maxSpans?: number;
1026
+ onSpan?: (span: TraceSpan) => void;
1027
+ exporter?: "console" | "json" | "otlp" | "none";
1028
+ endpoint?: string;
1029
+ otlp?: {
1030
+ endpoint: string;
1031
+ headers?: Record<string, string>;
1032
+ timeout?: number;
1033
+ };
1034
+ }
1035
+ export interface TraceContext {
1036
+ span<T>(name: string, fn: () => Promise<T>): Promise<T>;
1037
+ }
1038
+ export interface AuthContext {
1039
+ requestField(name: string, options?: {
1040
+ type?: "otp" | "text";
1041
+ }): Promise<string>;
1042
+ }
1043
+ export interface EnvContext {
1044
+ get(key: string): string | undefined;
1045
+ }
1046
+ export interface CredentialContext {
1047
+ mode: AuthMode;
1048
+ get(key: string): string | undefined;
1049
+ getAll(): Record<string, string>;
1050
+ getAccessToken(): string | undefined;
1051
+ getScopes(): string[];
1052
+ }
1053
+ export interface ProviderRequestContext {
1054
+ connectionId?: string;
1055
+ headers: Record<string, string>;
1056
+ }
1057
+ export interface ProviderChoiceBindingOptions {
1058
+ connection?: boolean;
1059
+ credentialKeys?: readonly string[];
1060
+ }
1061
+ export type ProviderChoiceStorageOptions = {
1062
+ readonly mode: "inline";
1063
+ } | {
1064
+ readonly mode: "server";
1065
+ readonly namespace: string;
1066
+ readonly state?: ProviderRuntimeState;
1067
+ readonly ttl?: ProviderStateDurationString;
1068
+ readonly maxEntries: number;
1069
+ readonly maxValueBytes: number;
1070
+ readonly unavailable?: "reject";
1071
+ } | {
1072
+ readonly mode: "auto";
1073
+ readonly namespace: string;
1074
+ readonly state?: ProviderRuntimeState;
1075
+ readonly ttl?: ProviderStateDurationString;
1076
+ readonly maxInlineBytes: number;
1077
+ readonly maxEntries: number;
1078
+ readonly maxValueBytes: number;
1079
+ readonly unavailable?: "reject";
1080
+ };
1081
+ export interface ProviderChoiceIssueOptions<TPayload extends Record<string, unknown>> {
1082
+ prefix: string;
1083
+ purpose: string;
1084
+ payload: TPayload;
1085
+ ttlMs: number;
1086
+ nowMs?: number;
1087
+ bind?: ProviderChoiceBindingOptions;
1088
+ storage?: ProviderChoiceStorageOptions;
1089
+ }
1090
+ export interface ProviderChoiceParseOptions {
1091
+ token: string;
1092
+ prefix: string;
1093
+ purpose: string;
1094
+ ttlMs?: number;
1095
+ nowMs?: number;
1096
+ futureToleranceMs?: number;
1097
+ bind?: ProviderChoiceBindingOptions;
1098
+ storage?: ProviderChoiceStorageOptions;
1099
+ }
1100
+ export interface ProviderChoiceContext {
1101
+ issue<TPayload extends Record<string, unknown>>(options: ProviderChoiceIssueOptions<TPayload> & {
1102
+ readonly storage?: {
1103
+ readonly mode: "inline";
1104
+ };
1105
+ }): string;
1106
+ issue<TPayload extends Record<string, unknown>>(options: ProviderChoiceIssueOptions<TPayload> & {
1107
+ readonly storage: Extract<ProviderChoiceStorageOptions, {
1108
+ readonly mode: "server";
1109
+ }>;
1110
+ }): Promise<string>;
1111
+ issue<TPayload extends Record<string, unknown>>(options: ProviderChoiceIssueOptions<TPayload> & {
1112
+ readonly storage: Extract<ProviderChoiceStorageOptions, {
1113
+ readonly mode: "auto";
1114
+ }>;
1115
+ }): string | Promise<string>;
1116
+ issue<TPayload extends Record<string, unknown>>(options: ProviderChoiceIssueOptions<TPayload>): string | Promise<string>;
1117
+ parse(options: ProviderChoiceParseOptions & {
1118
+ readonly storage?: {
1119
+ readonly mode: "inline";
1120
+ };
1121
+ }): Record<string, unknown>;
1122
+ parse(options: ProviderChoiceParseOptions & {
1123
+ readonly storage: Extract<ProviderChoiceStorageOptions, {
1124
+ readonly mode: "server";
1125
+ }>;
1126
+ }): Promise<Record<string, unknown>>;
1127
+ parse(options: ProviderChoiceParseOptions & {
1128
+ readonly storage: Extract<ProviderChoiceStorageOptions, {
1129
+ readonly mode: "auto";
1130
+ }>;
1131
+ }): Record<string, unknown> | Promise<Record<string, unknown>>;
1132
+ parse(options: ProviderChoiceParseOptions): Record<string, unknown>;
1133
+ }
1134
+ export interface ContextScratchpad {
1135
+ get(key: string): unknown;
1136
+ set(key: string, value: unknown): void;
1137
+ toJSON(): Record<string, unknown>;
1138
+ }
1139
+ export type FlowContextStore = ContextScratchpad;
1140
+ export interface FlowContext {
1141
+ connectionId?: string;
1142
+ externalRef?: string;
1143
+ tenantId: string;
1144
+ providerId: string;
1145
+ http: HttpClient;
1146
+ stealth: StealthClient;
1147
+ env: EnvContext;
1148
+ credential?: CredentialContext;
1149
+ context: ContextScratchpad;
1150
+ stt: SttContext;
1151
+ }
1152
+ export interface AuthTurn {
1153
+ kind: string;
1154
+ turnId: string;
1155
+ expiresAt?: string;
1156
+ data?: Record<string, unknown>;
1157
+ expectedInput?: Record<string, unknown>;
1158
+ /**
1159
+ * @deprecated Compatibility-only materialized provider auth hint.
1160
+ * Provider source must emit hintKey; SDK/server boundaries may materialize
1161
+ * this field from provider locale catalogs for legacy clients.
1162
+ */
1163
+ hint?: string;
1164
+ /** Provider locale catalog key for the auth turn hint. */
1165
+ hintKey?: ProviderLocaleKeyInput;
1166
+ timing?: {
1167
+ suggestedPollIntervalMs?: number;
1168
+ maxWaitMs?: number;
1169
+ };
1170
+ }
1171
+ export type AuthFlowStartHandler = (ctx: FlowContext) => Promise<AuthTurn>;
1172
+ export type AuthFlowInputHandler = (ctx: FlowContext, input?: Record<string, unknown>) => Promise<AuthTurn>;
1173
+ export interface AuthFlowDefinition {
1174
+ start: AuthFlowStartHandler;
1175
+ continue: AuthFlowInputHandler;
1176
+ poll?: AuthFlowStartHandler;
1177
+ abort?: AuthFlowStartHandler;
1178
+ refresh?: AuthFlowInputHandler;
1179
+ }
1180
+ export type ProviderStateDurationString = `${number}${"ms" | "s" | "m" | "h" | "d"}` | `PT${string}`;
1181
+ export interface StateNamespaceOptions {
1182
+ /** Default TTL used when a write omits ttl. Required to avoid unbounded state. */
1183
+ defaultTtl: ProviderStateDurationString;
1184
+ /** Maximum allowed TTL; writes are rejected when they exceed this policy. */
1185
+ maxTtl: ProviderStateDurationString;
1186
+ /** Maximum number of live entries in this namespace scope. */
1187
+ maxEntries: number;
1188
+ /** Maximum JSON-encoded value size in bytes. */
1189
+ maxValueBytes: number;
1190
+ }
1191
+ export interface StateWriteOptions {
1192
+ ttl?: ProviderStateDurationString;
1193
+ }
1194
+ export interface StateValue<T = unknown> {
1195
+ key: string;
1196
+ value: T;
1197
+ version: number;
1198
+ expiresAt: string;
1199
+ createdAt: string;
1200
+ updatedAt: string;
1201
+ }
1202
+ export type StateCasResult<T = unknown> = {
1203
+ ok: true;
1204
+ value: StateValue<T>;
1205
+ } | {
1206
+ ok: false;
1207
+ current: StateValue<T> | null;
1208
+ };
1209
+ export interface ProviderStateNamespace {
1210
+ list<T = unknown>(options?: {
1211
+ limit?: number;
1212
+ /** Optional literal key prefix used for scoped recovery scans. */
1213
+ prefix?: string;
1214
+ }): Promise<StateValue<T>[]>;
1215
+ get<T = unknown>(key: string): Promise<StateValue<T> | null>;
1216
+ set<T = unknown>(key: string, value: T, options?: StateWriteOptions): Promise<StateValue<T>>;
1217
+ patch<T extends Record<string, unknown>>(key: string, partial: Partial<T>, options?: StateWriteOptions): Promise<StateValue<T>>;
1218
+ compareAndSet<T = unknown>(key: string, expectedVersion: number, value: T, options?: StateWriteOptions): Promise<StateCasResult<T>>;
1219
+ delete(key: string): Promise<void>;
1220
+ increment(key: string, field: string, delta?: number, options?: StateWriteOptions): Promise<StateValue<Record<string, unknown>>>;
1221
+ }
1222
+ export interface ProviderRuntimeState {
1223
+ namespace(name: string, options: StateNamespaceOptions): ProviderStateNamespace;
1224
+ }
1225
+ export interface ProviderContext {
1226
+ env: EnvContext;
1227
+ credential: CredentialContext;
1228
+ request?: ProviderRequestContext;
1229
+ http: HttpClient;
1230
+ cache: ProviderCache;
1231
+ state: ProviderRuntimeState;
1232
+ stealth: StealthClient;
1233
+ browser: BrowserClient;
1234
+ trace: TraceContext;
1235
+ auth: AuthContext;
1236
+ stt: SttContext;
1237
+ choice: ProviderChoiceContext;
1238
+ }
1239
+ export interface AuthConfig {
1240
+ mode: AuthMode;
1241
+ flow?: AuthFlowDefinition;
1242
+ }
1243
+ export interface ProviderSecretDeclaration {
1244
+ name: string;
1245
+ description?: string;
1246
+ required?: boolean;
1247
+ }
1248
+ export interface CredentialDeclaration {
1249
+ keys: string[];
1250
+ storesReusableSecret?: boolean;
1251
+ justification?: string;
1252
+ }
1253
+ export interface ContextDeclaration {
1254
+ keys: string[];
1255
+ }
1256
+ export type OperationLifecycle = "stable" | "beta" | "deprecated" | "removed";
1257
+ export interface OperationDeprecationMetadata {
1258
+ announcedAt: string;
1259
+ removalAfter: string;
1260
+ replacement?: string;
1261
+ migrationGuide: string;
1262
+ }
1263
+ export interface OperationContractMetadata {
1264
+ /**
1265
+ * Callable operation contract version. Defaults to 1.0.0 for the clean
1266
+ * pre-GA baseline; it intentionally does not fall back to provider.version.
1267
+ */
1268
+ version?: string;
1269
+ lifecycle?: OperationLifecycle;
1270
+ deprecation?: OperationDeprecationMetadata;
1271
+ }
1272
+ export interface OperationDefinition<TInput extends SchemaLike = SchemaLike, TOutput extends SchemaLike = SchemaLike> {
1273
+ descriptionKey?: ProviderLocaleKeyInput;
1274
+ docs?: OperationDocMeta;
1275
+ whenToUseKeys?: readonly ProviderLocaleKeyInput[];
1276
+ whenNotToUseKeys?: readonly ProviderLocaleKeyInput[];
1277
+ derivations?: Record<string, string>;
1278
+ inputExamples?: readonly OperationInputExample[];
1279
+ annotations?: OperationAnnotations;
1280
+ contract?: OperationContractMetadata;
1281
+ tags?: readonly string[];
1282
+ relatedOperations?: OperationRelationships;
1283
+ toolRouter?: OperationToolRouterMetadata;
1284
+ observability?: OperationObservabilityConfig;
1285
+ transport?: OperationTransport;
1286
+ retryOnAuthRefresh?: boolean;
1287
+ input: TInput;
1288
+ output: TOutput;
1289
+ handler(ctx: ProviderContext, input: InferSchemaOutput<TInput>): OperationHandlerResult<InferSchemaOutput<TOutput>> | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
1290
+ fixtures?: {
1291
+ request: InferSchemaOutput<TInput>;
1292
+ response: InferSchemaOutput<TOutput>;
1293
+ };
1294
+ upstream?: {
1295
+ baseUrl?: string;
1296
+ proxy?: boolean | ProviderProxyPolicy;
1297
+ };
1298
+ hints?: Record<string, string>;
1299
+ healthCheck?: HealthCheckSuite<InferSchemaOutput<TInput>, InferSchemaOutput<TOutput>>;
1300
+ healthCheckUnsupported?: HealthCheckUnsupported;
1301
+ }
1302
+ export interface ProviderDefinition {
1303
+ id: string;
1304
+ version: string;
1305
+ runtime: "standard" | "shared" | "browser";
1306
+ allowedHosts?: string[];
1307
+ stealth?: {
1308
+ profile: string;
1309
+ platform: StealthPlatform;
1310
+ };
1311
+ proxy?: ProviderProxyConfig;
1312
+ stt?: ProviderSttConfig;
1313
+ browser?: {
1314
+ engine: BrowserEngine;
1315
+ };
1316
+ auth?: AuthConfig;
1317
+ reviewed?: ProviderReviewed;
1318
+ access?: ProviderAccessConfig;
1319
+ secrets?: ProviderSecretDeclaration[];
1320
+ credential?: CredentialDeclaration;
1321
+ context?: ContextDeclaration;
1322
+ meta: ProviderMeta;
1323
+ operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
1324
+ healthMonitor?: ProviderHealthMonitorConfig;
1325
+ healthJourneys?: readonly HealthJourneyDefinition[];
1326
+ }